[
  {
    "path": ".babelrc",
    "content": "{\n  \"presets\": [\"es2015\", \"flow-vue\"],\n  \"plugins\": [\"transform-vue-jsx\", \"syntax-dynamic-import\"],\n  \"ignore\": [\n    \"dist/*.js\",\n    \"packages/**/*.js\"\n  ]\n}\n"
  },
  {
    "path": ".editorconfig",
    "content": "# http://editorconfig.org\n\nroot = true\n\n[*]\ncharset = utf-8\nindent_style = space\nindent_size = 2\nend_of_line = lf\ninsert_final_newline = true\ntrim_trailing_whitespace = true\n\n[*.md]\ninsert_final_newline = false\ntrim_trailing_whitespace = false\n"
  },
  {
    "path": ".eslintignore",
    "content": "flow\ndist\npackages\n"
  },
  {
    "path": ".eslintrc",
    "content": "{\n  \"root\": true,\n  \"plugins\": [\n    \"flowtype\"\n  ],\n  \"extends\": [\n    \"plugin:vue-libs/recommended\",\n    \"plugin:flowtype/recommended\"\n  ],\n  \"globals\": {\n    \"__WEEX__\": true\n  }\n}\n"
  },
  {
    "path": ".flowconfig",
    "content": "[ignore]\n.*/node_modules/.*\n.*/test/.*\n.*/build/.*\n.*/examples/.*\n.*/benchmarks/.*\n\n[include]\n\n[libs]\nflow\n\n[options]\nunsafe.enable_getters_and_setters=true\nmodule.name_mapper='^compiler/\\(.*\\)$' -> '<PROJECT_ROOT>/src/compiler/\\1'\nmodule.name_mapper='^core/\\(.*\\)$' -> '<PROJECT_ROOT>/src/core/\\1'\nmodule.name_mapper='^shared/\\(.*\\)$' -> '<PROJECT_ROOT>/src/shared/\\1'\nmodule.name_mapper='^web/\\(.*\\)$' -> '<PROJECT_ROOT>/src/platforms/web/\\1'\nmodule.name_mapper='^weex/\\(.*\\)$' -> '<PROJECT_ROOT>/src/platforms/weex/\\1'\nmodule.name_mapper='^server/\\(.*\\)$' -> '<PROJECT_ROOT>/src/server/\\1'\nmodule.name_mapper='^entries/\\(.*\\)$' -> '<PROJECT_ROOT>/src/entries/\\1'\nmodule.name_mapper='^sfc/\\(.*\\)$' -> '<PROJECT_ROOT>/src/sfc/\\1'\nsuppress_comment= \\\\(.\\\\|\\n\\\\)*\\\\$flow-disable-line\n"
  },
  {
    "path": ".github/CODE_OF_CONDUCT.md",
    "content": "# Contributor Code of Conduct\n\nAs contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.\n\nWe are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, age, or religion.\n\nExamples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.\n\nProject maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.\n\nThis Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)\n"
  },
  {
    "path": ".github/COMMIT_CONVENTION.md",
    "content": "## Git Commit Message Convention\n\n> This is adapted from [Angular's commit convention](https://github.com/conventional-changelog/conventional-changelog/blob/master/packages/conventional-changelog-angular/convention.md).\n\n#### Examples\n\nAppears under \"Features\" header, `compiler` subheader:\n\n```\nfeat(compiler): add 'comments' option\n```\n\nAppears under \"Bug Fixes\" header, `v-model` subheader, with a link to issue #28:\n\n```\nfix(v-model): handle events on blur\n\nclose #28\n```\n\nAppears under \"Performance Improvements\" header, and under \"Breaking Changes\" with the breaking change explanation:\n\n```\nperf(core): improve vdom diffing by removing 'foo' option\n\nBREAKING CHANGE: The 'foo' option has been removed.\n```\n\nThe following commit and commit `667ecc1` do not appear in the changelog if they are under the same release. If not, the revert commit appears under the \"Reverts\" header.\n\n```\nrevert: feat(compiler): add 'comments' option\n\nThis reverts commit 667ecc1654a317a13331b17617d973392f415f02.\n```\n\n### Full Message Format\n\nA commit message consists of a **header**, **body** and **footer**.  The header has a **type**, **scope** and **subject**:\n\n```\n<type>(<scope>): <subject>\n<BLANK LINE>\n<body>\n<BLANK LINE>\n<footer>\n```\n\nThe **header** is mandatory and the **scope** of the header is optional.\n\n### Revert\n\nIf the commit reverts a previous commit, it should begin with `revert: `, followed by the header of the reverted commit. In the body it should say: `This reverts commit <hash>.`, where the hash is the SHA of the commit being reverted.\n\n### Type\n\nIf the prefix is `feat`, `fix` or `perf`, it will appear in the changelog. However if there is any [BREAKING CHANGE](#footer), the commit will always appear in the changelog.\n\nOther prefixes are up to your discretion. Suggested prefixes are `docs`, `chore`, `style`, `refactor`, and `test` for non-changelog related tasks.\n\n### Scope\n\nThe scope could be anything specifying place of the commit change. For example `core`, `compiler`, `ssr`, `v-model`, `transition` etc...\n\n### Subject\n\nThe subject contains succinct description of the change:\n\n* use the imperative, present tense: \"change\" not \"changed\" nor \"changes\"\n* don't capitalize first letter\n* no dot (.) at the end\n\n### Body\n\nJust as in the **subject**, use the imperative, present tense: \"change\" not \"changed\" nor \"changes\".\nThe body should include the motivation for the change and contrast this with previous behavior.\n\n### Footer\n\nThe footer should contain any information about **Breaking Changes** and is also the place to\nreference GitHub issues that this commit **Closes**.\n\n**Breaking Changes** should start with the word `BREAKING CHANGE:` with a space or two newlines. The rest of the commit message is then used for this.\n"
  },
  {
    "path": ".github/CONTRIBUTING.md",
    "content": "# 贡献\n\n> 欢迎任何形式的贡献，我们的开发计划见 [mpvue 开发计划](https://trello.com/b/ZBP1leCF/mpvue)\n\n## Issues\n\n### 提交 issues\n\n- 确定在最新版本中该 bug 存在。我们将不会持续维护所有的发布版本，所有的修改仅根据当前版本。\n- 确认该 bug 是可以复现的，请尽量提供完整的重现步骤。\n- 确定这是不是一个 bug，请仔细阅读文档。\n- 确定这不是一个重复的 bug。 查看 [Issue Page](https://github.com/Meituan-Dianping/mpvue/issues) 列表，搜索您要提交的 bug 是否已经被报告过。\n\n### 如何提交一个有质量的 bug\n\n请在 [Issue Page](https://github.com/Meituan-Dianping/mpvue/issues) 页面中提交 bug。\n\n- 使用一个清晰并有描述性的标题来定义bug。\n- 详细的描述复现bug的步骤。包括您使用的 mpvue、mpvue-loader、mpvue-template-compiler 版本，配置情况，预计产生的结果，实际产生的结果。\n- 如果程序抛出异常，请附加完整的堆栈日志。\n- 如有可能，请附上屏幕截图或动态的 GIF 图，这些图片能帮助演示整个问题的产生过程。\n\n### 提交功能增强建议\n\n请在 [Issue Page](https://github.com/Meituan-Dianping/mpvue/issues) 页面中提交增强建议。\n\n- 请确定这不是一个重复的功能增强建议。 查看 [Issue Page](https://github.com/Meituan-Dianping/mpvue/issues) 列表，搜索您要提交的功能增强建议是否已经被提交过。\n- 使用一个清晰并有描述性的标题来定义增强建议。\n- 详细描述增强功能的行为模式。\n- 解释说明为什么该功能是对大多数用户是有用的。新功能应该具有广泛的适用性。\n- 如有可能，可以列出其他数据库中间已经具备的类似功能。商用与开源软件均可。\n- 使用 enhancement 标签(Label)来标记这个 issue。\n\n### 贡献补丁\n\n- fork 本仓库到自己账户。\n- 您应该新建一个分支来开始您的工作，分支的名字为功能名称/issueId。\n- 完成功能后请添加完整测试。\n- 完成后，发送一个 pull request 到 Meituan-Dianping/mpvue。\n- 等待核心开发者做 CodeReview。\n- 最后，恭喜您已经成为了 mpvue 的官方贡献者！\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/Bug_report.md",
    "content": "---\nname: 报告问题（Bug report）\nabout: 描述你遇到的问题并寻求社区帮助\n---\n<!--\n    注意：为更好的解决你的问题，请参考模板提供完整信息，准确描述问题，信息不全的 issue 将被关闭。\n-->\n## [扼要问题描述]\n\n**mpvue 版本号：**\n\n[mpvue@x.x.x]\n\n**最小化复现代码：**\n\n[建议提供最小化可运行的代码：附件或文本代码]\n\n```\n// 示例代码：\n```\n\n**问题复现步骤：**\n\n1. [第一步]\n2. [第二步]\n3. [其它...]\n\n**观察到的表现：**\n\n[在这里描述观察到的表现]\n\n**截图或动态图：**\n\n![复现步骤截图或gif图片](图片的 url)\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/Feature_request.md",
    "content": "---\nname: 建议新功能（Feature Request）\nabout: 展示已经实现的新功能，或者对项目提出新的需求和建议\n---\n\n## [在此简单描述您的建议]\n\n**新功能相关的问题issue或讨论：**\n\n[在这里引用新功能相关的讨论]\n\n**新功能的实现：**\n\n[在这里填写或简单描述功能的实现方式或需求的解决方式]\n\n**相关项目或文档：**\n\n[在这里引用相关项目或文档地址]\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "<!-- PULL REQUEST TEMPLATE -->\n<!-- (Update \"[ ]\" to \"[x]\" to check a box) -->\n\n**What kind of change does this PR introduce?** (check at least one)\n\n- [ ] Bugfix\n- [ ] Feature\n- [ ] Code style update\n- [ ] Refactor\n- [ ] Build-related changes\n- [ ] Other, please describe:\n\n**Does this PR introduce a breaking change?** (check one)\n\n- [ ] Yes\n- [ ] No\n\nIf yes, please describe the impact and migration path for existing applications:\n\n**The PR fulfills these requirements:**\n\n- [ ] It's submitted to the `dev` branch for v2.x (or to a previous version branch), _not_ the `master` branch\n- [ ] When resolving a specific issue, it's referenced in the PR's title (e.g. `fix #xxx[,#xxx]`, where \"xxx\" is the issue number)\n- [ ] All tests are passing\n- [ ] New/updated tests are included\n\nIf adding a **new feature**, the PR's description includes:\n- [ ] A convincing reason for adding this feature (to avoid wasting your time, it's best to open a suggestion issue first and wait for approval before working on it)\n\n**Other information:**\n"
  },
  {
    "path": ".github/issue_template.yml",
    "content": "issueConfigs:\n  -\n    bannedTitle: \"问题简单描述\"\n    subtitles:\n      - \"问题复现步骤：\"\n      - \"期望的表现：\"\n      - \"观察到的表现：\"\n      - \"屏幕截图或动态图：\"\n    bannedContents:\n      - \"第一步\"\n      - \"第二步\"\n      - \"其他步骤...\"\n      - \"在这里描述期望的表现\"\n      - \"在这里描述观察到的表现\"\n      - \"复现步骤的屏幕截图和动态 GIF 图\"\n      - \"图片的 url\",\n      - \"建议提供可运行的demo\"\n  -\n    bannedTitle: \"在此简单描述您的建议\"\n    subtitles:\n      - \"新功能相关的问题issue或讨论：\"\n      - \"新功能的实现：\"\n      - \"相关项目或文档：\"\n    bannedContents:\n      - \"在这里引用新功能相关的讨论\"\n      - \"在这里填写或简单描述功能的实现方式或需求的解决方式\"\n      - \"在这里引用相关项目或文档地址\"\n\ncomments:\n  closeIssue: \"issue不符合格式要求，请确保格式正确且填写所有有效信息。\\n请保留issue模板中的各级小标题（如“期望的表现：”），并使用有效信息替换模板默认内容（如“[在这里描述期望的表现]”）\"\n"
  },
  {
    "path": ".github/stale.yml",
    "content": "daysUntilStale: 30\n\nmarkComment: \"issue超过30天无更新或响应，7天后将自动关闭，如果问题状态有更新请及时更新issue\"\n\nlimitPerRun: 24\n\nonly: issues"
  },
  {
    "path": ".gitignore",
    "content": ".DS_Store\nnode_modules\n*.log\npackage-lock.json\nexplorations\nTODOs.md\ndist/*.gz\ndist/*.map\ndist/vue.common.min.js\ntest/e2e/reports\ntest/e2e/screenshots\ncoverage\nRELEASE_NOTE*.md\ndist/*.js\npackages/vue-server-renderer/basic.js\npackages/vue-server-renderer/build.js\npackages/vue-server-renderer/server-plugin.js\npackages/vue-server-renderer/client-plugin.js\npackages/vue-template-compiler/build.js\n.vscode/\n"
  },
  {
    "path": "BACKERS.md",
    "content": "# Backers\n\nYou can join them in supporting  Vue.js development by [pledging on Patreon](https://www.patreon.com/evanyou)! Backers in the same pledge level appear in the order of pledge date.\n\n### $2000\n\n<a href=\"https://stdlib.com/\">\n  <img width=\"600px\" src=\"https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/stdlib.png\">\n</a>\n\n---\n\n### $1000\n\n<a href=\"https://www.upyun.com/?utm_source=vue&utm_medium=ad&utm_content=github\">\n  <img width=\"400px\" src=\"https://raw.githubusercontent.com/vuejs/cn.vuejs.org/master/themes/vue/source/images/upyun-large.png\">\n</a>\n\n---\n\n### $500\n\n<a href=\"https://deepstreamhub.com\">\n  <img width=\"260px\" src=\"https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/deepstream.png\">\n</a>\n<br><br>\n<a href=\"https://jsfiddle.net/\">\n  <img width=\"240px\" src=\"https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/jsfiddle.png\">\n</a>\n<br><br>\n<a href=\"https://laravel.com\">\n  <img width=\"240px\" src=\"https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/laravel.png\">\n</a>\n<br><br>\n<a href=\"https://chaitin.cn\">\n  <img width=\"240px\" src=\"https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/chaitin.png\">\n</a>\n<br><br>\n<a href=\"https://htmlburger.com/\">\n  <img width=\"240px\" src=\"https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/htmlburger.png\">\n</a>\n<br><br>\n<a href=\"https://starter.someline.com/\">\n  <img width=\"240px\" src=\"https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/someline.png\">\n</a>\n<br><br>\n<a href=\"http://monterail.com/\" target=\"_blank\">\n  <img width=\"240px\" src=\"https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/monterail.png\">\n</a>\n<br><br>\n<a href=\"https://www.trisoft.ro/\" target=\"_blank\">\n  <img width=\"240px\" src=\"https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/trisoft.png\">\n</a>\n<br><br>\n<a href=\"https://www.2mhost.com/\" target=\"_blank\">\n  <img width=\"240px\" src=\"https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/2mhost.png\">\n</a>\n<br><br>\n<a href=\"https://vuejsjob.com/?ref=vuejs\" target=\"_blank\">\n  <img width=\"240px\" src=\"https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/vuejobs.png\">\n</a>\n<br><br>\n<a href=\"https://leanpub.com/vuejs2\" target=\"_blank\">\n  <img width=\"240px\" src=\"https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/tmvuejs2.png\">\n</a>\n<br><br>\n<a href=\"https://famebroker.com\" target=\"_blank\">\n  <img width=\"260px\" src=\"https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/famebroker.png\">\n</a>\n<br><br>\n<a href=\"https://component.io/\" target=\"_blank\">\n  <img width=\"260px\" src=\"https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/component_io.png\">\n</a>\n\n---\n\n### $100\n\n<a href=\"http://tighten.co/\">\n  <img width=\"240px\" src=\"http://i.imgur.com/T7fQYLT.png\">\n</a>\n<br><br>\n<a href=\"http://invoicemachine.com/\">\n  <img width=\"220px\" src=\"http://assets.invoicemachine.com/images/flat_logo.png\">\n</a>\n<br><br>\n<a href=\"https://alligator.io\">\n  <img width=\"240px\" src=\"https://alligator.io/images/alligator-logo.svg\">\n</a>\n<br><br>\n<a href=\"https://monei.net/\">\n  <img width=\"200px\" src=\"http://i.imgur.com/JUSjHAi.png\">\n</a>\n<br><br>\n<a href=\"https://www.accelebrate.com/\">\n  <img width=\"220px\" src=\"https://www.accelebrate.com/assets/images/accelebrate_logo@2x.png\">\n</a>\n<br><br>\n<a href=\"https://www.waterfall.com\">\n  <img width=\"200px\" src=\"https://waterfall.com/waterfall_logo_large.png\">\n</a>\n\n---\n\n### $50+\n\n- No Divide Studio\n- James Kyle\n- Blake Newman\n- Lee Smith\n- Adam Dorsey\n- Greg McCarvell\n- Yoshiya Hinosawa\n- Wasim Khamlichi\n- errorrik\n- Alex Balashov\n\n---\n\n### $10+\n\n- Sylvain Pollet-Villard\n- Luca Borghini\n- Kazuya Kawaguchi\n- Keisuke Kita\n- Anirudh Sanjeev\n- Guido Bertolino\n- Fábio Vedovelli\n- Jack Barham\n- Stephane Demoote\n- Paul R. Dillinger\n- Sean Washington\n- Alun Davey\n- Eduardo Kyvenko\n- Thijs de Maa\n- Joris Noordermeer\n- Niklas Lifors\n- An Phan\n- Richard Wyke\n- Roman Kuba\n- Tom Conlon\n- Matt Pickle\n- Simon East\n- Bill Columbia\n- Hayden Bickerton\n- Henry Zhu\n- John Smith\n- Benjamin Listwon\n- Rainer Morgan\n- Brian Jorden\n- Christopher Dosin\n- Lars Andreas Ness\n- Drew Lustro\n- Victor Tolbert\n- Jon Pokrzyk\n- Frank Dungan III\n- Lanes.io\n- Anders\n- Dexter Miguel\n- Stephen Michael Hartley\n- Wen-Tien Chang\n- Ole Støvern\n- Valerian Cure\n- Dani Ilops\n- louisbl\n- Yegor Sytnyk\n- Guido H.\n- Joan Cejudo\n- Ian Walter\n- Nikola Trifunovic\n- Nicolas Mutis Mesa\n- Fahed Toumi\n- James Brooks\n- Kirk Lewis\n- Spenser\n- Takuya Nishio\n- Daniel Diekmeier\n- Peter Thaleikis\n- Karol Fabjanczuk\n- Eduardo\n- Lê Chương\n- Webber Wang\n- Daniel Schmitz\n- Bruce Li\n- Mohammed\n- Sam Wainwright\n- TJ Hillard\n- Kyle Arrington\n- Jason Land\n- Miljan Aleksic\n- James Ye\n- Laurids Duellmann\n- Christo Crampton\n- Adon Metcalfe\n- Paul Straw\n- Jake Ingman\n- Eduardo Camillo\n- Barbara Liau\n- Jens Lind\n- Yegor Sytnyk\n- Benson Wong\n- Anthony Tsui\n- Karol Fabjanczuk\n- Isaac Sant\n- Milos Stojanovic\n- Matsumoto Takamasa\n- Douglas Lowder\n- Bess Brooks\n- Christian Griffith\n- Matt Rockwell\n- Jarek Tkaczyk\n- Michael Laccetti\n- Jonothan Allen\n- Andrew Davis\n- Jason Rys\n- Sean\n- Xiaojie Li\n- Joakim Bugge\n- Lacey Pevey\n- David Hess\n- Niannian Modisette\n- Kim Cuartero\n- Luke Sampson\n- Dariusz Jastrzębski\n- Ivan Sieder\n- Jivan Roquet\n- Shane\n- Stew Heckenberg\n- Matt Jones\n- Dave Chenell\n- Frank Baele\n- Jack McDade\n- Patrick O'Dacre\n- Wietse Wind\n- Donny Donny\n- Duncan Kenzie\n- Mike Margerum\n- Michael Richards\n- Eduardo Reveles\n- Jan Kremlacek\n- Guy Gavergun\n- Keith Bailey\n- Joel Birch\n- Bernhard E. Reiter\n- Radu Cretu\n- Luiz Tanure\n- Poamrong Rith\n- Chengzhi Yin\n- Dan Barrett\n- Zoran Knezevic\n- Charles Beaumont\n- Jonathan Kent\n- James Simpson\n- Pascal Germain\n- Pierre Vanhulst\n- Vincent Gabriel\n- Kyovo Digaw\n- devneko\n- Cheng-Wei Chien\n- Michael Mazurczak\n- Daniel\n- Chris Anderson\n- Jon Hobbs-Smith\n- Chez Tschetter\n- Akiho Nagao\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2018-present, 美团点评\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE."
  },
  {
    "path": "README.md",
    "content": "<p align=\"center\"><a href=\"http://mpvue.com\" target=\"_blank\" rel=\"noopener noreferrer\"><img width=\"100\" src=\"http://mpvue.com/assets/logo.png\" alt=\"mpvue logo\"></a></p>\n<p align=\"center\">\n   <a href=\"https://www.npmjs.com/package/mpvue\"><img src=\"https://img.shields.io/npm/v/mpvue.svg?style=flat\" alt=\"npm\"></a>\n   <a href=\"https://www.npmjs.com/package/mpvue\"><img src=\"https://img.shields.io/npm/dm/mpvue.svg?style=flat\" alt=\"npm\"></a>\n </p>\n\n# mpvue\n> Vue.js 小程序版, fork 自 [vuejs/vue@2.4.1](https://github.com/vuejs/vue)，保留了 vue runtime 能力，添加了小程序平台的支持。\n\n\n`mpvue` 是一个使用 [Vue.js](https://vuejs.org) 开发小程序的前端框架，目前支持 `微信小程序`、`百度智能小程序`，`头条小程序` 和 `支付宝小程序`。 框架基于 `Vue.js`，修改了的运行时框架 runtime 和代码编译器 compiler 实现，使其可运行在小程序环境中，从而为小程序开发引入了 `Vue.js` 开发体验。\n\n## mpvue 2.0\n\nmpvue 2.0 开始正式支持 **百度智能小程序**、**头条小程序** 和 **支付宝小程序**，使用 `mpvue-quickstart` 项目模板新创建的项目，将默认升级到 2.0。老项目可继续使用原有版本。详情请参见 [**mpvue 2.0 升级指南**](https://github.com/Meituan-Dianping/mpvue/releases/tag/2.0.0)\n\n**新版本的问题或建议，有请各位关注者及时反馈，mpvue 2.0 祝大家节日快乐~** -2019.02.14\n\n### mpvue 1.x 稳定版本\n**对于不升级 2.0 的项目，可以继续使用1.x 的大版本，目前1.x 会持续在 1.4.x 上继续维护** 升级方式参见：[1.x 稳定版说明](https://github.com/Meituan-Dianping/mpvue/releases/tag/2.0.0)\n\n[mpvue 文档](http://mpvue.com)\n\n## 快速开始\n\n我们精心准备了一个简单的 [五分钟上手教程](http://mpvue.com/mpvue/quickstart) 方便你快速体验到 `mpvue` 带来的开发乐趣。\n\n## 名称由来\n- `mp`：mini program 的缩写\n- `mpvue`：Vue.js in mini program\n\n## 主要特性\n使用 `mpvue` 开发小程序，你将在小程序技术体系的基础上获取到这样一些能力：\n\n- 彻底的组件化开发能力：提高代码复用性\n- 完整的 `Vue.js` 开发体验\n- 方便的 `Vuex` 数据管理方案：方便构建复杂应用\n- 快捷的 `webpack` 构建机制：自定义构建策略、开发阶段 hotReload\n- 支持使用 npm 外部依赖\n- 使用 `Vue.js` 命令行工具 vue-cli 快速初始化项目\n- H5 代码转换编译成小程序目标代码的能力\n\n其它特性正在等着你去探索。\n\n\n## 配套设施\n`mpvue` 作为小程序版本的 `Vue.js`，在框架 SDK 之外，完整的技术体系还包括如下设施。\n\n- [mpvue-loader](http://mpvue.com/build/mpvue-loader) 提供 webpack 版本的加载器\n- [mpvue-webpack-target](http://mpvue.com/build/mpvue-webpack-target) webpack 构建目标\n- [postcss-mpvue-wxss](http://mpvue.com/build/postcss-mpvue-wxss) 样式代码转换预处理工具\n- [px2rpx-loader](http://mpvue.com/build/px2rpx-loader) 样式转化插件\n- [mpvue-quickstart](http://mpvue.com/mpvue/quickstart) mpvue-quickstart\n- [mpvue-simple](http://mpvue.com/mpvue/simple) 辅助 mpvue 快速开发 Page / Component 级小程序页面的工具\n- 其它\n\n## 使用 mpvue 的项目\n\n<div>\n    <img src=\"https://user-images.githubusercontent.com/1715463/42300198-c79e41ac-8041-11e8-9bf4-569901bc8c5d.jpeg\" width=\"100\" title=\"享物说\"/>\n    <img src=\"https://user-images.githubusercontent.com/13334618/38455900-d608df44-3ab0-11e8-94db-a5b7ac782612.jpg\" width=\"100\" />\n    <img src=\"https://camo.githubusercontent.com/d0fe641cc98e6dcdff3b3e28f3f46ed47a3b5777/68747470733a2f2f7773312e73696e61696d672e636e2f6c617267652f36313134353733386c7931667139723334316a33356a323037363037363735392e6a7067\" width=\"100\" />\n    <img src=\"https://user-images.githubusercontent.com/26051070/39106618-75ed54b4-46ef-11e8-834d-faf2629c218b.jpg\" width=\"100\" />\n    <img src=\"https://user-images.githubusercontent.com/12172868/39176660-e973d0de-47df-11e8-88c2-fbd36b14caed.jpg\" width=\"100\" />\n    <img src=\"https://user-images.githubusercontent.com/8087694/39505682-93727596-4e06-11e8-8978-6075d6b03742.jpg\" width=\"100\" />\n    <img src=\"https://user-images.githubusercontent.com/16408246/40176958-ac78023a-5a0f-11e8-85bf-0ff56426f202.jpg\" width=\"100\" />\n    <img src=\"https://user-images.githubusercontent.com/7871813/39956784-b3b978c0-5619-11e8-9bc4-658c8f2907e6.png\" width=\"100\" />\n    <img src=\"https://user-images.githubusercontent.com/8219610/40181466-b8e1f204-5a1b-11e8-9c39-545226b354b6.jpg\" width=\"100\" />\n    <img src=\"https://user-images.githubusercontent.com/8426097/40212791-72744312-5a84-11e8-819d-654057def4a2.jpg\" width=\"100\" />\n    <img src=\"https://user-images.githubusercontent.com/22385741/40222981-fd28501e-5ab3-11e8-8558-79447270e118.png\" width=\"100\" />\n    <img src=\"https://user-images.githubusercontent.com/28003460/40229157-017bcc24-5ac6-11e8-921a-f424a70724dd.jpg\" width=\"100\" />\n    <img src=\"https://user-images.githubusercontent.com/20151096/40263981-a4072682-5b4d-11e8-95aa-292da6ee9228.png\" width=\"100\" />\n    <img src=\"https://user-images.githubusercontent.com/652171/40602836-a064ab44-628c-11e8-962c-c5c75455c1c8.jpg\" width=\"100\" />\n    <img src=\"https://camo.githubusercontent.com/735d3be145d2632dd010b5fe6e047bc1f5d1b56d/68747470733a2f2f692e6c6f6c692e6e65742f323031382f30362f30342f356231346536616634633537322e6a7067\" width=\"100\" />\n    <img src=\"https://user-images.githubusercontent.com/5120505/41412484-ba85a04e-7012-11e8-9833-3ed4762073ea.png\" width=\"100\" />\n    <img src=\"https://user-images.githubusercontent.com/2733269/41572435-5a1700d6-73aa-11e8-84fa-6ab95f8276fa.jpg\" width=\"100\" title=\"大智慧行情\"/>\n    <img src=\"https://user-images.githubusercontent.com/16707486/41587965-0b984daa-73e3-11e8-8fee-c3a516733262.jpg\" width=\"100\" title=\"小亿买房\"/>\n    <img src=\"https://github.com/Hzy0913/hanlibrary/raw/master/xcx.jpg\" width=\"100\" title=\"小程序日历组件\"/>\n    <img src=\"https://user-images.githubusercontent.com/18204304/41755130-3edd141c-7608-11e8-9e20-596fd0c30262.jpg\" width=\"100\" title=\"速算练习小程序\"/>\n    <img src=\"https://user-images.githubusercontent.com/26002161/41972348-3798cbca-7a44-11e8-82ec-0dfd1c16c946.jpg\" width=\"100\" title=\"逗图Lite （表情包小程序）\"/>\n    <img src=\"https://user-images.githubusercontent.com/14872348/42489167-29c4cae2-843c-11e8-8b28-b704907497a3.jpg\" width=\"100\" title=\"童学云校微海报\"/>\n    <img src=\"https://user-images.githubusercontent.com/1220971/42721673-3bbd3080-8771-11e8-91dd-73622d9115cd.jpg\" width=\"100\" title=\"内涵段子Lite\"/>\n    <img src=\"https://user-images.githubusercontent.com/2350193/42740747-00714598-88de-11e8-817d-3b91ca33003c.jpg\" width=\"100\" title=\"SINA诊股\"/>\n    <img src=\"https://user-images.githubusercontent.com/2350193/42740748-00a6e2fc-88de-11e8-8642-2d73709fdb26.jpg\" width=\"100\" title=\"SINA资讯\"/>\n    <img src=\"https://user-images.githubusercontent.com/2350193/42740749-00e0808e-88de-11e8-90a0-09f412f54e86.jpg\" width=\"100\" title=\"SINA行情\"/>\n    <img src=\"https://user-images.githubusercontent.com/2350193/42801721-1fb5cabe-89d3-11e8-986b-a7e2a8b6f330.jpg\" width=\"100\" title=\"SINA课堂\"/>\n    <img src=\"https://user-images.githubusercontent.com/2350193/42871520-21c125e4-8aad-11e8-8b8c-5ff98698069f.jpg\" width=\"100\" title=\"SINA视觉\"/>\n    <img src=\"https://user-images.githubusercontent.com/2350193/42740746-00379c4e-88de-11e8-8958-c4c75d90ac36.jpg\" width=\"100\" title=\"我看涨\"/>\n    <img src=\"https://user-images.githubusercontent.com/6629280/42795085-e5fae9f8-89b4-11e8-9514-7764428be788.jpg\" width=\"100\" title=\"义乌购优选\"/>\n    <img src=\"https://camo.githubusercontent.com/9103a160806c94ed0e5787ee3b197159b3ba9f80/687474703a2f2f792e70686f746f2e71712e636f6d2f696d673f733d6a4456653262784862266c3d792e6a7067\" width=\"100\" title=\"熊猫斗图助手\"/>\n    <img src=\"https://user-images.githubusercontent.com/5915245/42990083-437e3072-8c34-11e8-8f6a-69ea58522be8.jpg\" width=\"100\" title=\"SPC运动宝\"/>\n    <img src=\"https://user-images.githubusercontent.com/5443058/42999490-9022a4dc-8c50-11e8-9e90-96bbc1bbbc8e.jpg\" width=\"100\" title=\"牛津阅读树点读版\"/>\n    <img src=\"https://camo.githubusercontent.com/c47426c0e0ad542f6399de4129682fed1f2b475c/68747470733a2f2f73312e617831782e636f6d2f323031382f30372f32312f50386f7368442e6a7067\" width=\"100\" title=\"花笙美妆\"/>\n    <img src=\"https://camo.githubusercontent.com/64ce4dd31ab2edc9f3a2f6f7dc943bd1dfaefa21/687474703a2f2f7063397034717362322e626b742e636c6f7564646e2e636f6d2f77782d6769746875622e6a7067\" width=\"100\" title=\"gitHub01\"/>\n    <img src=\"https://user-images.githubusercontent.com/15187909/43053228-29e08738-8e5e-11e8-8f91-377a28dcf771.jpg\" width=\"100\" title=\"极客教程\"/>\n    <img src=\"https://user-images.githubusercontent.com/7599915/43298816-425635f4-918a-11e8-9f0f-380dca9401dd.jpg\" width=\"100\" title=\"gitee工具\"/>\n    <img src=\"https://camo.githubusercontent.com/25a919d9549feb0b713ad86472c09e9c3f46aa83/687474703a2f2f696d616765732e70616e64616f6d656e672e636f6d2f32346665333339666662333936636662656238633136306435336261313539342e6a7067\" width=\"100\" title=\"销售神器\"/>\n    <img src=\"https://user-images.githubusercontent.com/17445000/43376242-3715ce48-93ec-11e8-90be-a59fe9788a98.jpg\" width=\"100\" title=\"360旗下-南瓜屋\"/>\n    <img src=\"https://user-images.githubusercontent.com/25244009/43445236-76c224be-94d8-11e8-9901-1ff399db7b70.jpg\" width=\"100\" title=\"地图小程序\"/>\n    <img src=\"https://user-images.githubusercontent.com/1448308/43559485-cbd41390-9640-11e8-848e-69b662be8da7.jpg\" width=\"100\" title=\"微工具书\"/>\n    <img src=\"https://user-images.githubusercontent.com/19870533/43562575-eed086f8-964f-11e8-8c39-20e604fd84fa.jpg\" width=\"100\" title=\"选课精灵\"/>\n    <img src=\"https://user-images.githubusercontent.com/13146991/43621850-f1df6730-970b-11e8-9d07-4db4f2c4c52f.png\" width=\"100\" title=\"京东云技术新知\"/>\n    <img src=\"https://user-images.githubusercontent.com/1627874/43621865-0df3a314-970c-11e8-8f1b-30cfdf6a9a47.jpg\" width=\"100\" title=\"运个货-互联网内贸集装箱海运物流平台\"/>\n    <img src=\"https://user-images.githubusercontent.com/4090027/44255554-0e352680-a239-11e8-96fe-8316a1fb22f8.jpg\" width=\"100\" title=\"小桔有车违章查询\"/>\n    <img src=\"https://user-images.githubusercontent.com/26808622/44326326-e1c61800-a48d-11e8-958f-d50ef7f45d62.png\" width=\"100\" title=\"餐饮，商超小程序\"/>\n    <img src=\"https://camo.githubusercontent.com/6f1b397785cd88ec260509e2768f10604b5711b9/687474703a2f2f7777772e77636c696d622e736974652f63646e2f7863782e6a7065673f763d31\" width=\"100\" title=\"妹子趣图\"/>\n    <img src=\"https://user-images.githubusercontent.com/12904977/44563258-02dd8000-a790-11e8-961d-fb50c4f27ba1.png\" width=\"100\" title=\"记工无忧\"/>\n    <img src=\"https://user-images.githubusercontent.com/22048131/44619692-5994a800-a8bd-11e8-98f0-b2337ef49b35.png\" width=\"100\" title=\"北美省钱快报App\"/>\n    <img src=\"https://user-images.githubusercontent.com/3882370/45558053-8bbc7880-b871-11e8-9b03-901f27f4e7d3.png\" width=\"100\" title=\"抽奖工具\" />\n    <img src=\"https://user-images.githubusercontent.com/16730031/45584645-e99c9f00-b909-11e8-853b-1f19b9cd76fd.jpg\" width=\"100\" title=\"盯事清单\" />\n    <img src=\"https://user-images.githubusercontent.com/18476675/45791542-adc45980-bcbc-11e8-803f-9c45c55c784b.png\" width=\"100\" title=\"微目标小程序\" />\n    <img src=\"https://user-images.githubusercontent.com/23513387/46054832-93d2bd00-c17b-11e8-9197-d5aa0c764ddb.jpg\" width=\"100\" title=\"微厅小程序\" />\n    <img src=\"https://i.loli.net/2018/10/11/5bbef01a68773.jpg\" width=\"100\" title=\"逗猫神器\" />\n    <img src=\"https://user-images.githubusercontent.com/16631463/46907861-eb2ea680-cf4b-11e8-92a2-0a8917417325.jpg\" width=\"100\" title=\"前端最火框架排行榜\" />\n    <img src=\"https://user-images.githubusercontent.com/16631463/46907868-187b5480-cf4c-11e8-8302-dcc722430b6d.jpg\" width=\"100\" title=\"猜谜语\" />\n    <img src=\"https://user-images.githubusercontent.com/38179236/47001679-9ebab500-d15d-11e8-99df-27b61e53c652.jpg\" width=\"100\" title=\"旅游大巴\" />\n    <img src=\"https://user-images.githubusercontent.com/20639676/47198055-a9af5880-d39c-11e8-8b1c-fcd4ba0ea57b.png\" width=\"100\" title=\"云鲜社区生鲜购\" />\n    <img src=\"https://user-images.githubusercontent.com/8544120/47279097-4114e580-d601-11e8-8a95-2d7dcc165d6b.jpg\" width=\"100\" title=\"闲停扯乎\" />\n    <img src=\"https://user-images.githubusercontent.com/22420/47401062-5bba9c00-d772-11e8-9717-d7c468d9b939.jpg\" width=\"100\" title=\"狗脸识别\" />\n    <img src=\"https://user-images.githubusercontent.com/31442077/47412617-c97cbd00-d79e-11e8-9002-7a0614d6ad1b.jpg\" width=\"100\" title=\"思政云\" />\n    <img src=\"https://user-images.githubusercontent.com/17083284/47612128-0b23a580-dac8-11e8-9582-70db2889e698.jpg\" width=\"100\" title=\"澳洲U站\" />\n    <img src=\"https://user-images.githubusercontent.com/16513510/47947846-8faa7400-df5f-11e8-8ee8-63c1a9fb6eac.jpg\" width=\"100\" title=\"莴聚\" />\n    <img src=\"https://user-images.githubusercontent.com/22372095/48299143-b6d6e780-e503-11e8-963a-4789e54f57d7.jpg\" width=\"100\" title=\"百世集团供应链TNET\" />\n    <img src=\"https://user-images.githubusercontent.com/15187909/48299710-c5290180-e50b-11e8-8cb5-339be1531608.jpg\" width=\"100\" />\n    <img src=\"https://user-images.githubusercontent.com/1715463/49988179-d0f76000-ffb0-11e8-8a69-cd57d6e54890.jpeg\" width=\"100\" title=\"漂流小情书\"/>\n    <img src=\"https://user-images.githubusercontent.com/1715568/48662132-6b4eab80-eab8-11e8-95de-c1e21786b2d9.jpg\" width=\"100\" title=\"绿芽找房\"/>\n    <img src=\"http://jiankang.juwu168.com/blog/wp-content/uploads/2018/10/gh_36a0a852bf6f_258-1.jpg\" width=\"100\" title=\"慕课网\" />\n    <img src=\"https://user-images.githubusercontent.com/14272879/49424002-38085e00-f7d4-11e8-8242-13ddda18cec3.jpg\" width=\"100\" title=\"一人宴\" />\n    <img src=\"https://upload-images.jianshu.io/upload_images/3356839-59bfd93deb76afca.jpg\" width=\"100\" title=\"惠动平台\">\n    <!-- 非标准小程序码 -->\n    <img src=\"https://user-images.githubusercontent.com/1176855/41755510-62b9fc90-760a-11e8-89be-b6ddbee08e63.jpg\" width=\"100\" title=\"暖茶阿妈的占卜小屋\"/>\n    <img src=\"https://user-images.githubusercontent.com/22720942/40184432-da33291c-5a22-11e8-966c-c836d1dc8078.png\" width=\"100\" />\n    <img src=\"https://camo.githubusercontent.com/25b2636179cd939461975ada9f996c77d15c4d2a/68747470733a2f2f7778342e73696e61696d672e636e2f6d773639302f373032643563616167793166746e323975797a38666a323037363038367439612e6a7067\" width=\"100\" title=\"扫域名的小程序，米农帮\"/>\n</div>\n\n[贡献方法](./.github/CONTRIBUTING.md)\n\n[更多项目征集](https://github.com/Meituan-Dianping/mpvue/issues/21)\n\n[分享交流群](https://github.com/Meituan-Dianping/mpvue/issues/14)\n"
  },
  {
    "path": "benchmarks/big-table/demo.css",
    "content": "form {\n  margin-bottom: 15px;\n}\n\ntd.hidden {\n  color: #ccc;\n}\n\ntable.filtered td.item {\n  background-color: #FFFFBF;\n}\n\ntable.filtered td.item.hidden {\n  background-color: transparent;\n}\n"
  },
  {
    "path": "benchmarks/big-table/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <title></title>\n    <script src=\"../../dist/vue.min.js\"></script>\n    <link rel=\"stylesheet\" href=\"style.css\">\n    <link rel=\"stylesheet\" href=\"demo.css\">\n  </head>\n  <body>\n    <div id=\"el\">\n      <h1>Rendering Dynamic Big Table</h1>\n      <p>Reference: <a href=\"http://insin.github.io/ui-lib-samples/large-datasets/index.html\">insin/ui-lib-samples/large-datasets</a></p>\n\n      <p>\n        <span>{{ rows }} x {{ cols }}, {{ optimized ? 'with' : 'without' }} optimization. {{ msg }}</span>\n      </p>\n\n      <p>\n        <button v-if=\"optimized\" @click=\"loadBase\">Disable optimization</button>\n        <button v-else @click=\"loadOptimized\">Enable optimization (Object.freeze)</button>\n        <button @click=\"unmount\">Unmount</button>\n        <button @click=\"rerender\">Rerender with fresh data</button>\n      </p>\n\n      <form>\n        <strong>Filter Data</strong>:\n        <input type=\"text\" v-model=\"filter\">\n\n        <!--\n          If the user is filtering the data, we want to offer some insight into\n          the breadth of the filtering.\n        -->\n        <span v-if=\"filter\">\n          &mdash;\n          Filtering <strong>{{ filter }}</strong>\n          over {{ dataPoints }} data points,\n          {{ visibleCount() }} found.\n        </span>\n\n      </form>\n\n      <table width=\"100%\" cellspacing=\"2\" :class=\"{ filtered: filter }\">\n        <tr v-for=\"row in grid\">\n          <th>{{ row.id }}</th>\n          <td v-for=\"item in row.items\"\n            class=\"item\"\n            :class=\"{ hidden: !matches(item) }\">\n            {{ item.value }}\n          </td>\n        </tr>\n      </table>\n    </div>\n\n    <script>\n    var ROWS = 1000\n    var COLS = 10\n    var OPTIMIZED = window.location.hash === '#optimized'\n\n    window.onhashchange = function () {\n      window.location.reload()\n    }\n\n    function generateGrid( rowCount, columnCount ) {\n      var valuePoints = [\n        \"Daenerys\", \"Jon\", \"Sansa\", \"Arya\", \"Stannis\", \"Gregor\", \"Tyrion\",\n        \"Theon\", \"Joffrey\", \"Ramsay\", \"Cersei\", \"Bran\", \"Margaery\",\n        \"Melisandre\", \"Daario\", \"Jamie\", \"Eddard\", \"Myrcella\", \"Robb\",\n        \"Jorah\", \"Petyr\", \"Tommen\", \"Sandor\", \"Oberyn\", \"Drogo\", \"Ygritte\"\n      ]\n      var valueIndex = 0\n      var grid = []\n\n      for ( var r = 0; r < rowCount; r++ ) {\n        var row = {\n          id: r,\n          items: []\n        }\n        for ( var c = 0; c < columnCount; c++ ) {\n          row.items.push({\n            id: ( r + \"-\" + c ),\n            value: valuePoints[ valueIndex ]\n          })\n          if ( ++valueIndex >= valuePoints.length ) {\n            valueIndex = 0\n          }\n        }\n        grid.push(row)\n      }\n\n      return OPTIMIZED ? Object.freeze(grid) : grid\n    }\n\n    var grid = generateGrid(ROWS, COLS)\n    var s = window.performance.now()\n    console.profile('a')\n    var vm = new Vue({\n\n      el: '#el',\n\n      data: {\n        cols: COLS,\n        rows: ROWS,\n        optimized: OPTIMIZED,\n        msg: 'loading...',\n        grid: grid,\n        dataPoints: grid.length * grid[0].items.length,\n        filter: ''\n      },\n\n      methods: {\n        matches: function (item) {\n          return item.value.toLowerCase().indexOf(this.filter.toLowerCase()) > -1\n        },\n        visibleCount: function () {\n          var count = 0\n          var grid = this.grid\n          for (var i = 0, l = grid.length; i < l; i++) {\n            var row = grid[i].items\n            for (var j = 0, k = row.length; j < k; j++) {\n              var item = row[j]\n              var matched = !this.filter || this.matches(item)\n              if (matched) {\n                count++\n              }\n            }\n          }\n          return count\n        },\n        loadBase: function () {\n          window.location.hash = ''\n        },\n        loadOptimized: function () {\n          window.location.hash = '#optimized'\n        },\n        unmount: function () {\n          console.profile('unmount')\n          var s = window.performance.now()\n          this.grid = []\n          setTimeout(function () {\n            vm.msg = 'umount took: ' + (window.performance.now() - s).toFixed(2) + 'ms'\n            console.profileEnd('unmount')\n          }, 0)\n        },\n        rerender: function () {\n          var grid = generateGrid(1000, 10)\n          var s = window.performance.now()\n          console.profile('rerender')\n          this.grid = grid\n          setTimeout(function () {\n            vm.msg = 'rerender took: ' + (window.performance.now() - s).toFixed(2) + 'ms'\n            console.profileEnd('rerender')\n          }, 0)\n        }\n      }\n    })\n    console.profileEnd('a')\n    setTimeout(function () {\n      vm.msg = 'initial render took: ' + (window.performance.now() - s).toFixed(2) + 'ms'\n    }, 0)\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "benchmarks/big-table/style.css",
    "content": "@font-face {\n  font-family: octicons-anchor;\n  src: url(data:font/woff;charset=utf-8;base64,d09GRgABAAAAAAYcAA0AAAAACjQAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABGRlRNAAABMAAAABwAAAAca8vGTk9TLzIAAAFMAAAARAAAAFZG1VHVY21hcAAAAZAAAAA+AAABQgAP9AdjdnQgAAAB0AAAAAQAAAAEACICiGdhc3AAAAHUAAAACAAAAAj//wADZ2x5ZgAAAdwAAADRAAABEKyikaNoZWFkAAACsAAAAC0AAAA2AtXoA2hoZWEAAALgAAAAHAAAACQHngNFaG10eAAAAvwAAAAQAAAAEAwAACJsb2NhAAADDAAAAAoAAAAKALIAVG1heHAAAAMYAAAAHwAAACABEAB2bmFtZQAAAzgAAALBAAAFu3I9x/Nwb3N0AAAF/AAAAB0AAAAvaoFvbwAAAAEAAAAAzBdyYwAAAADP2IQvAAAAAM/bz7t4nGNgZGFgnMDAysDB1Ml0hoGBoR9CM75mMGLkYGBgYmBlZsAKAtJcUxgcPsR8iGF2+O/AEMPsznAYKMwIkgMA5REMOXicY2BgYGaAYBkGRgYQsAHyGMF8FgYFIM0ChED+h5j//yEk/3KoSgZGNgYYk4GRCUgwMaACRoZhDwCs7QgGAAAAIgKIAAAAAf//AAJ4nHWMMQrCQBBF/0zWrCCIKUQsTDCL2EXMohYGSSmorScInsRGL2DOYJe0Ntp7BK+gJ1BxF1stZvjz/v8DRghQzEc4kIgKwiAppcA9LtzKLSkdNhKFY3HF4lK69ExKslx7Xa+vPRVS43G98vG1DnkDMIBUgFN0MDXflU8tbaZOUkXUH0+U27RoRpOIyCKjbMCVejwypzJJG4jIwb43rfl6wbwanocrJm9XFYfskuVC5K/TPyczNU7b84CXcbxks1Un6H6tLH9vf2LRnn8Ax7A5WQAAAHicY2BkYGAA4teL1+yI57f5ysDNwgAC529f0kOmWRiYVgEpDgYmEA8AUzEKsQAAAHicY2BkYGB2+O/AEMPCAAJAkpEBFbAAADgKAe0EAAAiAAAAAAQAAAAEAAAAAAAAKgAqACoAiAAAeJxjYGRgYGBhsGFgYgABEMkFhAwM/xn0QAIAD6YBhwB4nI1Ty07cMBS9QwKlQapQW3VXySvEqDCZGbGaHULiIQ1FKgjWMxknMfLEke2A+IJu+wntrt/QbVf9gG75jK577Lg8K1qQPCfnnnt8fX1NRC/pmjrk/zprC+8D7tBy9DHgBXoWfQ44Av8t4Bj4Z8CLtBL9CniJluPXASf0Lm4CXqFX8Q84dOLnMB17N4c7tBo1AS/Qi+hTwBH4rwHHwN8DXqQ30XXAS7QaLwSc0Gn8NuAVWou/gFmnjLrEaEh9GmDdDGgL3B4JsrRPDU2hTOiMSuJUIdKQQayiAth69r6akSSFqIJuA19TrzCIaY8sIoxyrNIrL//pw7A2iMygkX5vDj+G+kuoLdX4GlGK/8Lnlz6/h9MpmoO9rafrz7ILXEHHaAx95s9lsI7AHNMBWEZHULnfAXwG9/ZqdzLI08iuwRloXE8kfhXYAvE23+23DU3t626rbs8/8adv+9DWknsHp3E17oCf+Z48rvEQNZ78paYM38qfk3v/u3l3u3GXN2Dmvmvpf1Srwk3pB/VSsp512bA/GG5i2WJ7wu430yQ5K3nFGiOqgtmSB5pJVSizwaacmUZzZhXLlZTq8qGGFY2YcSkqbth6aW1tRmlaCFs2016m5qn36SbJrqosG4uMV4aP2PHBmB3tjtmgN2izkGQyLWprekbIntJFing32a5rKWCN/SdSoga45EJykyQ7asZvHQ8PTm6cslIpwyeyjbVltNikc2HTR7YKh9LBl9DADC0U/jLcBZDKrMhUBfQBvXRzLtFtjU9eNHKin0x5InTqb8lNpfKv1s1xHzTXRqgKzek/mb7nB8RZTCDhGEX3kK/8Q75AmUM/eLkfA+0Hi908Kx4eNsMgudg5GLdRD7a84npi+YxNr5i5KIbW5izXas7cHXIMAau1OueZhfj+cOcP3P8MNIWLyYOBuxL6DRylJ4cAAAB4nGNgYoAALjDJyIAOWMCiTIxMLDmZedkABtIBygAAAA==) format('woff');\n}\n\nbody  {\n  -webkit-text-size-adjust: 100%;\n  -ms-text-size-adjust: 100%;\n  text-size-adjust: 100%;\n  color: #333;\n  font-family: \"Helvetica Neue\", Helvetica, \"Segoe UI\", Arial, freesans, sans-serif;\n  font-size: 16px;\n  line-height: 1.6;\n  word-wrap: break-word;\n  padding: 1em;\n}\n\na {\n  background-color: transparent;\n}\n\na:active,\na:hover {\n  outline: 0;\n}\n\nstrong {\n  font-weight: bold;\n}\n\nh1 {\n  font-size: 2em;\n  margin: 0.67em 0;\n}\n\nimg {\n  border: 0;\n}\n\nhr {\n  box-sizing: content-box;\n  height: 0;\n}\n\npre {\n  overflow: auto;\n}\n\ncode,\nkbd,\npre {\n  font-family: monospace, monospace;\n  font-size: 1em;\n}\n\ninput {\n  color: inherit;\n  font: inherit;\n  margin: 0;\n}\n\nhtml input[disabled] {\n  cursor: default;\n}\n\ninput {\n  line-height: normal;\n}\n\ninput[type=\"checkbox\"] {\n  box-sizing: border-box;\n  padding: 0;\n}\n\ntable {\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\ntd,\nth {\n  padding: 0;\n}\n\n* {\n  box-sizing: border-box;\n}\n\ninput {\n  font: 13px/1.4 Helvetica, arial, nimbussansl, liberationsans, freesans, clean, sans-serif, \"Segoe UI Emoji\", \"Segoe UI Symbol\";\n}\n\na {\n  color: #4078c0;\n  text-decoration: none;\n}\n\na:hover,\na:active {\n  text-decoration: underline;\n}\n\nhr {\n  height: 0;\n  margin: 15px 0;\n  overflow: hidden;\n  background: transparent;\n  border: 0;\n  border-bottom: 1px solid #ddd;\n}\n\nhr:before {\n  display: table;\n  content: \"\";\n}\n\nhr:after {\n  display: table;\n  clear: both;\n  content: \"\";\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  margin-top: 15px;\n  margin-bottom: 15px;\n  line-height: 1.1;\n}\n\nh1 {\n  font-size: 30px;\n}\nh1:first-child {\n  margin-top: 0;\n}\n\nh2 {\n  font-size: 21px;\n}\n\nh3 {\n  font-size: 16px;\n}\n\nh4 {\n  font-size: 14px;\n}\n\nh5 {\n  font-size: 12px;\n}\n\nh6 {\n  font-size: 11px;\n}\n\nblockquote {\n  margin: 0;\n}\n\nul,\nol {\n  padding: 0;\n  margin-top: 0;\n  margin-bottom: 0;\n}\n\nol ol,\nul ol {\n  list-style-type: lower-roman;\n}\n\nul ul ol,\nul ol ol,\nol ul ol,\nol ol ol {\n  list-style-type: lower-alpha;\n}\n\ndd {\n  margin-left: 0;\n}\n\ncode {\n  font-family: Consolas, \"Liberation Mono\", Menlo, Courier, monospace;\n  font-size: 12px;\n}\n\npre {\n  margin-top: 0;\n  margin-bottom: 0;\n  font: 12px Consolas, \"Liberation Mono\", Menlo, Courier, monospace;\n}\n\n.octicon {\n  font: normal normal normal 16px/1 octicons-anchor;\n  display: inline-block;\n  text-decoration: none;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-user-select: none;\n  -moz-user-select: none;\n  -ms-user-select: none;\n  user-select: none;\n}\n\n.octicon-link:before {\n  content: '\\f05c';\n}\n\n.markdown-body>*:first-child {\n  margin-top: 0 !important;\n}\n\n.markdown-body>*:last-child {\n  margin-bottom: 0 !important;\n}\n\na:not([href]) {\n  cursor: pointer;\n  text-decoration: none;\n}\n\n.anchor {\n  position: absolute;\n  top: 0;\n  left: 0;\n  display: block;\n  padding-right: 6px;\n  padding-left: 30px;\n  margin-left: -30px;\n}\n\n.anchor:focus {\n  outline: none;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  position: relative;\n  margin-top: 1em;\n  margin-bottom: 16px;\n  font-weight: bold;\n  line-height: 1.4;\n}\n\nh1 .octicon-link,\nh2 .octicon-link,\nh3 .octicon-link,\nh4 .octicon-link,\nh5 .octicon-link,\nh6 .octicon-link {\n  display: none;\n  color: #000;\n  vertical-align: middle;\n}\n\nh1:hover .anchor,\nh2:hover .anchor,\nh3:hover .anchor,\nh4:hover .anchor,\nh5:hover .anchor,\nh6:hover .anchor {\n  padding-left: 8px;\n  margin-left: -30px;\n  text-decoration: none;\n}\n\nh1:hover .anchor .octicon-link,\nh2:hover .anchor .octicon-link,\nh3:hover .anchor .octicon-link,\nh4:hover .anchor .octicon-link,\nh5:hover .anchor .octicon-link,\nh6:hover .anchor .octicon-link {\n  display: inline-block;\n}\n\nh1 {\n  padding-bottom: 0.3em;\n  font-size: 2.25em;\n  line-height: 1.2;\n  border-bottom: 1px solid #eee;\n}\n\nh1 .anchor {\n  line-height: 1;\n}\n\nh2 {\n  padding-bottom: 0.3em;\n  font-size: 1.75em;\n  line-height: 1.225;\n  border-bottom: 1px solid #eee;\n}\n\nh2 .anchor {\n  line-height: 1;\n}\n\nh3 {\n  font-size: 1.5em;\n  line-height: 1.43;\n}\n\nh3 .anchor {\n  line-height: 1.2;\n}\n\nh4 {\n  font-size: 1.25em;\n}\n\nh4 .anchor {\n  line-height: 1.2;\n}\n\nh5 {\n  font-size: 1em;\n}\n\nh5 .anchor {\n  line-height: 1.1;\n}\n\nh6 {\n  font-size: 1em;\n  color: #777;\n}\n\nh6 .anchor {\n  line-height: 1.1;\n}\n\np,\nblockquote,\nul,\nol,\ndl,\ntable,\npre {\n  margin-top: 0;\n  margin-bottom: 16px;\n}\n\nhr {\n  height: 4px;\n  padding: 0;\n  margin: 16px 0;\n  background-color: #e7e7e7;\n  border: 0 none;\n}\n\nul,\nol {\n  padding-left: 2em;\n}\n\nul ul,\nul ol,\nol ol,\nol ul {\n  margin-top: 0;\n  margin-bottom: 0;\n}\n\nli>p {\n  margin-top: 16px;\n}\n\ndl {\n  padding: 0;\n}\n\ndl dt {\n  padding: 0;\n  margin-top: 16px;\n  font-size: 1em;\n  font-style: italic;\n  font-weight: bold;\n}\n\ndl dd {\n  padding: 0 16px;\n  margin-bottom: 16px;\n}\n\nblockquote {\n  padding: 0 15px;\n  color: #777;\n  border-left: 4px solid #ddd;\n}\n\nblockquote>:first-child {\n  margin-top: 0;\n}\n\nblockquote>:last-child {\n  margin-bottom: 0;\n}\n\ntable {\n  display: block;\n  width: 100%;\n  overflow: auto;\n  word-break: normal;\n  word-break: keep-all;\n}\n\ntable th {\n  font-weight: bold;\n}\n\ntable th,\ntable td {\n  padding: 6px 13px;\n  border: 1px solid #ddd;\n}\n\ntable tr {\n  background-color: #fff;\n  border-top: 1px solid #ccc;\n}\n\ntable tr:nth-child(2n) {\n  background-color: #f8f8f8;\n}\n\nimg {\n  max-width: 100%;\n  box-sizing: border-box;\n}\n\ncode {\n  padding: 0;\n  padding-top: 0.2em;\n  padding-bottom: 0.2em;\n  margin: 0;\n  font-size: 85%;\n  background-color: rgba(0,0,0,0.04);\n  border-radius: 3px;\n}\n\ncode:before,\ncode:after {\n  letter-spacing: -0.2em;\n  content: \"\\00a0\";\n}\n\npre>code {\n  padding: 0;\n  margin: 0;\n  font-size: 100%;\n  word-break: normal;\n  white-space: pre;\n  background: transparent;\n  border: 0;\n}\n\n.highlight {\n  margin-bottom: 16px;\n}\n\n.highlight pre,\npre {\n  padding: 16px;\n  overflow: auto;\n  font-size: 85%;\n  line-height: 1.45;\n  background-color: #f7f7f7;\n  border-radius: 3px;\n}\n\n.highlight pre {\n  margin-bottom: 0;\n  word-break: normal;\n}\n\npre {\n  word-wrap: normal;\n}\n\npre code {\n  display: inline;\n  max-width: initial;\n  padding: 0;\n  margin: 0;\n  overflow: initial;\n  line-height: inherit;\n  word-wrap: normal;\n  background-color: transparent;\n  border: 0;\n}\n\npre code:before,\npre code:after {\n  content: normal;\n}\n\nkbd {\n  display: inline-block;\n  padding: 3px 5px;\n  font-size: 11px;\n  line-height: 10px;\n  color: #555;\n  vertical-align: middle;\n  background-color: #fcfcfc;\n  border: solid 1px #ccc;\n  border-bottom-color: #bbb;\n  border-radius: 3px;\n  box-shadow: inset 0 -1px 0 #bbb;\n}\n\nkbd {\n  display: inline-block;\n  padding: 3px 5px;\n  font: 11px Consolas, \"Liberation Mono\", Menlo, Courier, monospace;\n  line-height: 10px;\n  color: #555;\n  vertical-align: middle;\n  background-color: #fcfcfc;\n  border: solid 1px #ccc;\n  border-bottom-color: #bbb;\n  border-radius: 3px;\n  box-shadow: inset 0 -1px 0 #bbb;\n}\n\n.task-list-item {\n  list-style-type: none;\n}\n\n.task-list-item+.task-list-item {\n  margin-top: 3px;\n}\n\n.task-list-item input {\n  margin: 0 0.35em 0.25em -1.6em;\n  vertical-align: middle;\n}\n\n:checked+.radio-label {\n  z-index: 1;\n  position: relative;\n  border-color: #4078c0;\n}\n"
  },
  {
    "path": "benchmarks/dbmon/ENV.js",
    "content": "var ENV = ENV || (function() {\n\n  var first = true;\n  var counter = 0;\n  var data;\n  var _base;\n  (_base = String.prototype).lpad || (_base.lpad = function(padding, toLength) {\n    return padding.repeat((toLength - this.length) / padding.length).concat(this);\n  });\n\n  function formatElapsed(value) {\n    var str = parseFloat(value).toFixed(2);\n    if (value > 60) {\n      minutes = Math.floor(value / 60);\n      comps = (value % 60).toFixed(2).split('.');\n      seconds = comps[0].lpad('0', 2);\n      ms = comps[1];\n      str = minutes + \":\" + seconds + \".\" + ms;\n    }\n    return str;\n  }\n\n  function getElapsedClassName(elapsed) {\n    var className = 'Query elapsed';\n    if (elapsed >= 10.0) {\n      className += ' warn_long';\n    }\n    else if (elapsed >= 1.0) {\n      className += ' warn';\n    }\n    else {\n      className += ' short';\n    }\n    return className;\n  }\n\n  function countClassName(queries) {\n    var countClassName = \"label\";\n    if (queries >= 20) {\n      countClassName += \" label-important\";\n    }\n    else if (queries >= 10) {\n      countClassName += \" label-warning\";\n    }\n    else {\n      countClassName += \" label-success\";\n    }\n    return countClassName;\n  }\n\n  function updateQuery(object) {\n    if (!object) {\n      object = {};\n    }\n    var elapsed = Math.random() * 15;\n    object.elapsed = elapsed;\n    object.formatElapsed = formatElapsed(elapsed);\n    object.elapsedClassName = getElapsedClassName(elapsed);\n    object.query = \"SELECT blah FROM something\";\n    object.waiting = Math.random() < 0.5;\n    if (Math.random() < 0.2) {\n      object.query = \"<IDLE> in transaction\";\n    }\n    if (Math.random() < 0.1) {\n      object.query = \"vacuum\";\n    }\n    return object;\n  }\n\n  function cleanQuery(value) {\n    if (value) {\n      value.formatElapsed = \"\";\n      value.elapsedClassName = \"\";\n      value.query = \"\";\n      value.elapsed = null;\n      value.waiting = null;\n    } else {\n      return {\n        query: \"***\",\n        formatElapsed: \"\",\n        elapsedClassName: \"\"\n      };\n    }\n  }\n\n  function generateRow(object, keepIdentity, counter) {\n    var nbQueries = Math.floor((Math.random() * 10) + 1);\n    if (!object) {\n      object = {};\n    }\n    object.lastMutationId = counter;\n    object.nbQueries = nbQueries;\n    if (!object.lastSample) {\n      object.lastSample = {};\n    }\n    if (!object.lastSample.topFiveQueries) {\n      object.lastSample.topFiveQueries = [];\n    }\n    if (keepIdentity) {\n      // for Angular optimization\n      if (!object.lastSample.queries) {\n        object.lastSample.queries = [];\n        for (var l = 0; l < 12; l++) {\n          object.lastSample.queries[l] = cleanQuery();\n        }\n      }\n      for (var j in object.lastSample.queries) {\n        var value = object.lastSample.queries[j];\n        if (j <= nbQueries) {\n          updateQuery(value);\n        } else {\n          cleanQuery(value);\n        }\n      }\n    } else {\n      object.lastSample.queries = [];\n      for (var j = 0; j < 12; j++) {\n        if (j < nbQueries) {\n          var value = updateQuery(cleanQuery());\n          object.lastSample.queries.push(value);\n        } else {\n          object.lastSample.queries.push(cleanQuery());\n        }\n      }\n    }\n    for (var i = 0; i < 5; i++) {\n      var source = object.lastSample.queries[i];\n      object.lastSample.topFiveQueries[i] = source;\n    }\n    object.lastSample.nbQueries = nbQueries;\n    object.lastSample.countClassName = countClassName(nbQueries);\n    return object;\n  }\n\n  function getData(keepIdentity) {\n    var oldData = data;\n    if (!keepIdentity) { // reset for each tick when !keepIdentity\n      data = [];\n      for (var i = 1; i <= ENV.rows; i++) {\n        data.push({ dbname: 'cluster' + i, query: \"\", formatElapsed: \"\", elapsedClassName: \"\" });\n        data.push({ dbname: 'cluster' + i + ' slave', query: \"\", formatElapsed: \"\", elapsedClassName: \"\" });\n      }\n    }\n    if (!data) { // first init when keepIdentity\n      data = [];\n      for (var i = 1; i <= ENV.rows; i++) {\n        data.push({ dbname: 'cluster' + i });\n        data.push({ dbname: 'cluster' + i + ' slave' });\n      }\n      oldData = data;\n    }\n    for (var i in data) {\n      var row = data[i];\n      if (!keepIdentity && oldData && oldData[i]) {\n        row.lastSample = oldData[i].lastSample;\n      }\n      if (!row.lastSample || Math.random() < ENV.mutations()) {\n        counter = counter + 1;\n        if (!keepIdentity) {\n          row.lastSample = null;\n        }\n        generateRow(row, keepIdentity, counter);\n      } else {\n        data[i] = oldData[i];\n      }\n    }\n    first = false;\n    return {\n      toArray: function() {\n        return data;\n      }\n    };\n  }\n\n  var mutationsValue = 0.5;\n\n  function mutations(value) {\n    if (value) {\n      mutationsValue = value;\n      return mutationsValue;\n    } else {\n      return mutationsValue;\n    }\n  }\n\n  var body = document.querySelector('body');\n  var theFirstChild = body.firstChild;\n\n  var sliderContainer = document.createElement( 'div' );\n  sliderContainer.style.cssText = \"display: flex\";\n  var slider = document.createElement('input');\n  var text = document.createElement('label');\n  text.innerHTML = 'mutations : ' + (mutationsValue * 100).toFixed(0) + '%';\n  text.id = \"ratioval\";\n  slider.setAttribute(\"type\", \"range\");\n  slider.style.cssText = 'margin-bottom: 10px; margin-top: 5px';\n  slider.addEventListener('change', function(e) {\n    ENV.mutations(e.target.value / 100);\n    document.querySelector('#ratioval').innerHTML = 'mutations : ' + (ENV.mutations() * 100).toFixed(0) + '%';\n  });\n  sliderContainer.appendChild( text );\n  sliderContainer.appendChild( slider );\n  body.insertBefore( sliderContainer, theFirstChild );\n\n  return  {\n    generateData: getData,\n    rows: 50,\n    timeout: 0,\n    mutations: mutations\n  };\n})();\n"
  },
  {
    "path": "benchmarks/dbmon/app.js",
    "content": "var app = new Vue({\n  el: '#app',\n  data: {\n    databases: []\n  }\n})\n\nfunction loadSamples() {\n  app.databases = Object.freeze(ENV.generateData().toArray());\n  Monitoring.renderRate.ping();\n  setTimeout(loadSamples, ENV.timeout);\n}\n\nloadSamples()\n"
  },
  {
    "path": "benchmarks/dbmon/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<meta name=\"description\" content=\"dbmon vue\" />\n<link href=\"./lib/styles.css\" rel=\"stylesheet\" type=\"text/css\" />\n<title>dbmon (Vue)</title>\n</head>\n<body>\n  <h2>\n    Reference: <a href=\"http://mathieuancelin.github.io/js-repaint-perfs/\">js-repaint-perfs</a>\n  </h2>\n  <div id=\"app\">\n    <table class=\"table table-striped lastest-data\">\n      <tbody>\n        <tr v-for=\"db in databases\">\n          <td class=\"dbname\">{{db.dbname}}</td>\n          <td class=\"query-count\">\n            <span :class=\"db.lastSample.countClassName\">{{db.lastSample.nbQueries}}</span>\n          </td>\n          <td v-for=\"q in db.lastSample.topFiveQueries\" :class=\"'Query ' + q.elapsedClassName\">\n            {{q.formatElapsed}}\n            <div class=\"popover left\">\n              <div class=\"popover-content\">{{q.query}}</div>\n              <div class=\"arrow\"></div>\n            </div>\n          </td>\n        </tr>\n      </tbody>\n    </table>\n  </div>\n\n  <script src=\"./ENV.js\"></script>\n  <script src=\"./lib/memory-stats.js\"></script>\n  <script src=\"./lib/monitor.js\"></script>\n  <script src=\"../../dist/vue.min.js\"></script>\n  <script src=\"./app.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "benchmarks/dbmon/lib/memory-stats.js",
    "content": "/**\n * @author mrdoob / http://mrdoob.com/\n * @author jetienne / http://jetienne.com/\n * @author paulirish / http://paulirish.com/\n */\nvar MemoryStats = function (){\n\n\tvar msMin\t= 100;\n\tvar msMax\t= 0;\n\n\tvar container\t= document.createElement( 'div' );\n\tcontainer.id\t= 'stats';\n\tcontainer.style.cssText = 'width:80px;opacity:0.9;cursor:pointer';\n\n\tvar msDiv\t= document.createElement( 'div' );\n\tmsDiv.id\t= 'ms';\n\tmsDiv.style.cssText = 'padding:0 0 3px 3px;text-align:left;background-color:#020;';\n\tcontainer.appendChild( msDiv );\n\n\tvar msText\t= document.createElement( 'div' );\n\tmsText.id\t= 'msText';\n\tmsText.style.cssText = 'color:#0f0;font-family:Helvetica,Arial,sans-serif;font-size:9px;font-weight:bold;line-height:15px';\n\tmsText.innerHTML= 'Memory';\n\tmsDiv.appendChild( msText );\n\n\tvar msGraph\t= document.createElement( 'div' );\n\tmsGraph.id\t= 'msGraph';\n\tmsGraph.style.cssText = 'position:relative;width:74px;height:30px;background-color:#0f0';\n\tmsDiv.appendChild( msGraph );\n\n\twhile ( msGraph.children.length < 74 ) {\n\n\t\tvar bar = document.createElement( 'span' );\n\t\tbar.style.cssText = 'width:1px;height:30px;float:left;background-color:#131';\n\t\tmsGraph.appendChild( bar );\n\n\t}\n\n\tvar updateGraph = function ( dom, height, color ) {\n\n\t\tvar child = dom.appendChild( dom.firstChild );\n\t\tchild.style.height = height + 'px';\n\t\tif( color ) child.style.backgroundColor = color;\n\n\t}\n\n\tvar perf = window.performance || {};\n\t// polyfill usedJSHeapSize\n\tif (!perf && !perf.memory){\n\t\tperf.memory = { usedJSHeapSize : 0 };\n\t}\n\tif (perf && !perf.memory){\n\t\tperf.memory = { usedJSHeapSize : 0 };\n\t}\n\n\t// support of the API?\n\tif( perf.memory.totalJSHeapSize === 0 ){\n\t\tconsole.warn('totalJSHeapSize === 0... performance.memory is only available in Chrome .')\n\t}\n\t\n\t// TODO, add a sanity check to see if values are bucketed.\n\t// If so, reminde user to adopt the --enable-precise-memory-info flag.\n\t// open -a \"/Applications/Google Chrome.app\" --args --enable-precise-memory-info\n\n\tvar lastTime\t= Date.now();\n\tvar lastUsedHeap= perf.memory.usedJSHeapSize;\n\treturn {\n\t\tdomElement: container,\n\n\t\tupdate: function () {\n\n\t\t\t// refresh only 30time per second\n\t\t\tif( Date.now() - lastTime < 1000/30 )\treturn;\n\t\t\tlastTime\t= Date.now()\n\n\t\t\tvar delta\t= perf.memory.usedJSHeapSize - lastUsedHeap;\n\t\t\tlastUsedHeap\t= perf.memory.usedJSHeapSize;\n\t\t\tvar color\t= delta < 0 ? '#830' : '#131';\n\t\t\t\n\t\t\tvar ms\t= perf.memory.usedJSHeapSize;\n\t\t\tmsMin\t= Math.min( msMin, ms );\n\t\t\tmsMax\t= Math.max( msMax, ms );\n\t\t\tmsText.textContent = \"Mem: \" + bytesToSize(ms, 2);\n\t\t\t\n\t\t\tvar normValue\t= ms / (30*1024*1024);\n\t\t\tvar height\t= Math.min( 30, 30 - normValue * 30 );\n\t\t\tupdateGraph( msGraph, height, color);\n\t\t\t\n\t\t\tfunction bytesToSize( bytes, nFractDigit ){\n\t\t\t\tvar sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];\n\t\t\t\tif (bytes == 0) return 'n/a';\n\t\t\t\tnFractDigit\t= nFractDigit !== undefined ? nFractDigit : 0;\n\t\t\t\tvar precision\t= Math.pow(10, nFractDigit);\n\t\t\t\tvar i \t\t= Math.floor(Math.log(bytes) / Math.log(1024));\n\t\t\t\treturn Math.round(bytes*precision / Math.pow(1024, i))/precision + ' ' + sizes[i];\n\t\t\t};\n\t\t}\n\n\t}\n\t\n};"
  },
  {
    "path": "benchmarks/dbmon/lib/monitor.js",
    "content": "var Monitoring = Monitoring || (function() {\n\n  var stats = new MemoryStats();\n  stats.domElement.style.position = 'fixed';\n  stats.domElement.style.right        = '0px';\n  stats.domElement.style.bottom       = '0px';\n  document.body.appendChild( stats.domElement );\n  requestAnimationFrame(function rAFloop(){\n      stats.update();\n      requestAnimationFrame(rAFloop);\n  });\n\n  var RenderRate = function () {\n    var container = document.createElement( 'div' );\n    container.id  = 'stats';\n    container.style.cssText = 'width:150px;opacity:0.9;cursor:pointer;position:fixed;right:80px;bottom:0px;';\n\n    var msDiv = document.createElement( 'div' );\n    msDiv.id  = 'ms';\n    msDiv.style.cssText = 'padding:0 0 3px 3px;text-align:left;background-color:#020;';\n    container.appendChild( msDiv );\n\n    var msText  = document.createElement( 'div' );\n    msText.id = 'msText';\n    msText.style.cssText = 'color:#0f0;font-family:Helvetica,Arial,sans-serif;font-size:9px;font-weight:bold;line-height:15px';\n    msText.innerHTML= 'Repaint rate: 0/sec';\n    msDiv.appendChild( msText );\n\n    var bucketSize = 20;\n    var bucket = [];\n    var lastTime  = Date.now();\n    return {\n      domElement: container,\n      ping: function () {\n        var start = lastTime;\n        var stop = Date.now();\n        var rate = 1000 / (stop - start);\n        bucket.push(rate);\n        if (bucket.length > bucketSize) {\n          bucket.shift();\n        }\n        var sum = 0;\n        for (var i = 0; i < bucket.length; i++) {\n          sum = sum + bucket[i];\n        }\n        msText.textContent = \"Repaint rate: \" + (sum / bucket.length).toFixed(2) + \"/sec\";\n        lastTime = stop;\n      }\n    }\n  };\n\n  var renderRate = new RenderRate();\n  document.body.appendChild( renderRate.domElement );\n\n  return {\n    memoryStats: stats,\n    renderRate: renderRate\n  };\n  \n})();\n"
  },
  {
    "path": "benchmarks/dbmon/lib/styles.css",
    "content": "body {color:#333;font-family:\"Helvetica Neue\",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;margin:0;}\nlabel {display:inline-block;font-weight:700;margin-bottom:5px;}\ninput[type=range] {display:block;width:100%;}\ntable {border-collapse:collapse;border-spacing:0;}\n:before,:after {box-sizing: border-box;}\n\n.table > thead > tr > th,.table > tbody > tr > th,.table > tfoot > tr > th,.table > thead > tr > td,.table > tbody > tr > td,.table > tfoot > tr > td {border-top:1px solid #ddd;line-height:1.42857143;padding:8px;vertical-align:top;}\n.table {width:100%;}\n.table-striped > tbody > tr:nth-child(odd) > td,.table-striped > tbody > tr:nth-child(odd) > th {background:#f9f9f9;}\n\n.label {border-radius:.25em;color:#fff;display:inline;font-size:75%;font-weight:700;line-height:1;padding:.2em .6em .3em;text-align:center;vertical-align:baseline;white-space:nowrap;}\n.label-success {background-color:#5cb85c;}\n.label-warning {background-color:#f0ad4e;}\n\n.popover {background-color:#fff;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;box-shadow:0 5px 10px rgba(0,0,0,.2);display:none;left:0;max-width:276px;padding:1px;position:absolute;text-align:left;top:0;white-space:normal;z-index:1010;}\n.popover>.arrow:after {border-width:10px;content:\"\";}\n.popover.left {margin-left:-10px;}\n.popover.left > .arrow {border-right-width:0;border-left-color:rgba(0,0,0,.25);margin-top:-11px;right:-11px;top:50%;}\n.popover.left > .arrow:after {border-left-color:#fff;border-right-width:0;bottom:-10px;content:\" \";right:1px;}\n.popover > .arrow {border-width:11px;}\n.popover > .arrow,.popover>.arrow:after {border-color:transparent;border-style:solid;display:block;height:0;position:absolute;width:0;}\n\n.popover-content {padding:9px 14px;}\n\n.Query {position:relative;}\n.Query:hover .popover {display:block;left:-100%;width:100%;}\n"
  },
  {
    "path": "benchmarks/reorder-list/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <title>Vue benchmark</title>\n  </head>\n  <body>\n    <script src=\"https://cdn.jsdelivr.net/lodash/4.10.0/lodash.min.js\"></script>\n    <script src=\"../../dist/vue.min.js\"></script>\n    <style>\n    .danger {\n      background-color: red;\n    }\n    </style>\n\n    <script type=\"text/x-template\" id=\"t\">\n      <div>\n        <h1>{{ total }} Components</h1>\n        <p>{{ action }} took {{time}}ms.</p>\n        <button @click=\"shuffle\">shuffle</button>\n        <button @click=\"add\">add</button>\n        <table class=\"table table-hover table-striped test-data\">\n          <row v-for=\"item in items\" :key=\"item.id\"\n            :class=\"{ danger: item.id === selected }\"\n            :item=\"item\"\n            @select=\"select(item)\"\n            @remove=\"remove(item)\">\n          </row>\n        </table>\n      </div>\n    </script>\n\n    <script type=\"text/x-template\" id=\"row\">\n      <tr>\n        <td class=\"col-md-1\">{{item.id}}</td>\n        <td class=\"col-md-4\">\n            <a @click=\"$emit('select')\">{{item.label}}</a>\n        </td>\n        <td class=\"col-md-1\">\n          <button @click=\"$emit('remove')\">remove</button>\n        </td>\n      </tr>\n    </script>\n\n    <div id=\"el\">\n    </div>\n\n    <script>\n    var total = 1000\n    var items = []\n    for (var i = 0; i < total; i++) {\n      items.push({\n        id: i,\n        label: String(Math.random()).slice(0, 5)\n      })\n    }\n\n    var s = window.performance.now()\n    console.profile('render')\n    var vm = new Vue({\n      el: '#el',\n      template: '#t',\n      data: {\n        total: total,\n        time: 0,\n        action: 'Render',\n        items: items,\n        selected: null\n      },\n      methods: {\n        shuffle: monitor('shuffle', function () {\n          this.items = _.shuffle(this.items)\n        }),\n        add: monitor('add', function () {\n          this.items.push({\n            id: total++,\n            label: String(Math.random()).slice(0, 5)\n          })\n        }),\n        select: monitor('select', function (item) {\n          this.selected = item.id\n        }),\n        remove: monitor('remove', function (item) {\n          this.items.splice(this.items.indexOf(item), 1)\n        })\n      },\n      components: {\n        row: {\n          props: ['item'],\n          template: '#row'\n        }\n      }\n    })\n    setTimeout(function () {\n      vm.time = window.performance.now() - s\n      console.profileEnd('render')\n    }, 0)\n\n    function monitor (action, fn) {\n      return function () {\n        var s = window.performance.now()\n        fn.apply(this, arguments)\n        Vue.nextTick(function () {\n          vm.action = action\n          vm.time = window.performance.now() - s\n        })\n      }\n    }\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "benchmarks/ssr/README.md",
    "content": "# Vue.js SSR benchmark\n\nThis benchmark renders a table of 1000 rows with 10 columns (10k components), with around 30k normal elements on the page. Note this is not something likely to be seen in a typical app. This benchmark is mostly for stress/regression testing and comparing between `renderToString` and `renderToStream`.\n\nTo view the results follow the run section. Note that the overall completion time for the results are variable, this is due to other system related variants at run time (available memory, processing ect). In ideal circumstances both should finish within similar results.\n\n`renderToStream` pipes the content through a stream which provides considerable performance benefits (faster time-to-first-byte and non-event-loop-blocking) over renderToString. This can be observed through the benchmark.\n\n### run\n\n``` bash\nnpm run bench:ssr\n```\n"
  },
  {
    "path": "benchmarks/ssr/common.js",
    "content": "'use strict'\n\nconst self = (global || root)\n\nself.performance = {\n  now: function () {\n    var hrtime = process.hrtime()\n    return ((hrtime[0] * 1000000 + hrtime[1] / 1000) / 1000)\n  }\n}\n\nfunction generateGrid (rowCount, columnCount) {\n  var grid = []\n\n  for (var r = 0; r < rowCount; r++) {\n    var row = { id: r, items: [] }\n    for (var c = 0; c < columnCount; c++) {\n      row.items.push({ id: (r + '-' + c) })\n    }\n    grid.push(row)\n  }\n\n  return grid\n}\n\nconst gridData = generateGrid(1000, 10)\n\nmodule.exports = {\n  template: '<div><h1>{{ Math.random() }}</h1><my-table></my-table></div>',\n  components: {\n    myTable: {\n      data: function () {\n        return {\n          grid: gridData\n        }\n      },\n      // template: '<table><tr v-for=\"row in grid\"><th>123</th><td v-for=\"item in row.items\">{{ item.id }}</td></tr></table>',\n      template: '<table width=\"100%\" cellspacing=\"2\"><row v-for=\"row in grid\" :row=\"row\"></row></table>',\n      components: {\n        row: {\n          props: ['row'],\n          template: '<tr><th>{{ Math.random() }}</th><column v-for=\"item in row.items\"></column></tr>',\n          components: {\n            column: {\n              template: '<td class=\"item\">' +\n                // 25 plain elements for each cell\n                '<ul class=\"yoyo\">' +\n                  '<li class=\"hihi\" v-for=\"i in 5\">' +\n                    '<span v-for=\"i in 5\">fsefs</span>' +\n                    '</li>' +\n                '</ul>' +\n              '</td>'\n            }\n          }\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "benchmarks/ssr/renderToStream.js",
    "content": "/* eslint-disable no-unused-vars */\n\n'use strict'\n\nprocess.env.NODE_ENV = 'production'\n\nconst Vue = require('../../dist/vue.runtime.common.js')\nconst createRenderer = require('../../packages/vue-server-renderer').createRenderer\nconst renderToStream = createRenderer().renderToStream\nconst gridComponent = require('./common.js')\n\nconsole.log('--- renderToStream --- ')\nconst self = (global || root)\nconst s = self.performance.now()\n\nconst stream = renderToStream(new Vue(gridComponent))\nlet str = ''\nlet first\nlet complete\nstream.once('data', () => {\n  first = self.performance.now() - s\n})\nstream.on('data', chunk => {\n  str += chunk\n})\nstream.on('end', () => {\n  complete = self.performance.now() - s\n  console.log(`first chunk: ${first.toFixed(2)}ms`)\n  console.log(`complete: ${complete.toFixed(2)}ms`)\n  console.log()\n})\n"
  },
  {
    "path": "benchmarks/ssr/renderToString.js",
    "content": "'use strict'\n\nprocess.env.NODE_ENV = 'production'\n\nconst Vue = require('../../dist/vue.runtime.common.js')\nconst createRenderer = require('../../packages/vue-server-renderer').createRenderer\nconst renderToString = createRenderer().renderToString\nconst gridComponent = require('./common.js')\n\nconsole.log('--- renderToString --- ')\nconst self = (global || root)\nself.s = self.performance.now()\n\nrenderToString(new Vue(gridComponent), (err, res) => {\n  if (err) throw err\n  // console.log(res)\n  console.log('Complete time: ' + (self.performance.now() - self.s).toFixed(2) + 'ms')\n  console.log()\n})\n"
  },
  {
    "path": "benchmarks/svg/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <title>vue.js version</title>\n  <script src=\"https://cdn.jsdelivr.net/stats.js/r11/stats.min.js\"></script>\n  <script src=\"../../dist/vue.min.js\"></script>\n  <style>\n  html, body {\n    height: 100%;\n    width: 100%;\n    padding: 0;\n    margin: 0;\n  }\n  svg {\n    width: 800px;\n    height: 600px;\n  }\n  </style>\n</head>\n<body>\n  <h1>Animating 1000 SVG dots</h1>\n  <div id=\"app\">\n    <p>\n      <button @click=\"toggleOptimization\">\n        {{ optimized ? 'disable' : 'enable' }} optimization (Object.freeze)\n      </button>\n    </p>\n    <svg>\n      <circle  v-for='point in model.points' :cx='point.x' :cy='point.y' r='2px' fill='#FC309D'></circle>\n    </svg>\n  </div>\n<script type=\"text/javascript\" charset=\"utf-8\">\nvar stats = new Stats()\nstats.setMode(0)\nstats.domElement.style.position = 'absolute'\nstats.domElement.style.right = '0px'\nstats.domElement.style.top = '0px'\ndocument.body.appendChild(stats.domElement)\n\nvar WIDTH = 800\nvar HEIGHT = 600\n\nnew Vue({\n  el: '#app',\n  data: {\n    model: createModel(1000),\n    optimized: false\n  },\n  created: function () {\n    var self = this\n    requestAnimationFrame(render)\n    stats.begin()\n    function render () {\n      stats.end()\n      stats.begin()\n      requestAnimationFrame(render)\n      self.model.step()\n      if (self.optimized) {\n        self.$forceUpdate()\n      }\n    }\n  },\n  methods: {\n    toggleOptimization: function () {\n      this.model = this.optimized\n        ? createModel(1000)\n        : Object.freeze(createModel(1000))\n      this.optimized = !this.optimized\n    }\n  }\n});\n\nfunction createModel (count) {\n  var points = []\n  for (var i = 0; i < count; ++i) {\n    points.push({\n      x: Math.random() * WIDTH,\n      y: Math.random() * HEIGHT,\n      vx: Math.random() * 4 - 2,\n      vy: Math.random() * 4 - 2\n    })\n  }\n\n  return {\n    points: points,\n    step: step\n  }\n\n  function step () {\n    points.forEach(move)\n  }\n\n  function move (p) {\n    if (p.x > WIDTH || p.x < 0) p.vx *= -1\n    if (p.y > HEIGHT || p.y < 0) p.vy *= -1\n    p.y += p.vy\n    p.x += p.vx\n  }\n}\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "benchmarks/uptime/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <title>Vue benchmark</title>\n    <style type=\"text/css\">\n      html, body {\n        margin: 0;\n        padding: 0 10px;\n        font-family: sans-serif;\n      }\n\n      #fps {\n        position: fixed;\n        top: 0px;\n        right: 0px;\n        padding: 32px;\n        font-size: 32px;\n        text-align: right;\n      }\n\n      * {\n        box-sizing: border-box;\n      }\n\n      .server-uptime {\n        display: block;\n        overflow: hidden;\n        margin: 0 auto;\n        width: 50%;\n      }\n\n      .server-uptime + .server-uptime {\n        margin: 20px auto 0 auto;\n        border-top: 1px solid #999;\n      }\n\n      .days {\n        display: flex;\n        flex-direction: row;\n        flex-flow: wrap;\n      }\n\n      .uptime-day {\n        display: flex;\n      }\n\n      span.uptime-day-status {\n        width: 10px;\n        height: 10px;\n        margin: 1px;\n      }\n\n      .hover {\n        display: none;\n      }\n\n      .uptime-day-status:hover + .hover {\n        display: flex;\n        position: absolute;\n        margin-top: -35px;\n        margin-left: -30px;\n        border-radius: 4px;\n        color: #eee;\n        background-color: #333;\n        padding: 10px;\n        font-size: 11px;\n      }\n    </style>\n  </head>\n  <body>\n    <p>Reference: <a href=\"https://github.com/tildeio/glimmer/blob/master/packages/glimmer-demos/lib/uptime.ts\">Ember Glimmer 2 demo</a></p>\n    <div id=\"app\">\n      <p>FPS: {{ fps }}</p>\n      <button @click=\"toggle\">{{ playing ? 'pause' : 'play' }}</button>\n      <server-uptime\n        v-for=\"server in servers\"\n        :key=\"server.name\"\n        :name=\"server.name\"\n        :days=\"server.days\">\n      </server-uptime>\n    </div>\n    <script src=\"../../dist/vue.min.js\"></script>\n    <script>\n      // functional components are prefect for small, presentational components\n      // and they are much more efficient than stateful ones.\n      Vue.component('uptime-day', {\n        props: ['day'],\n        functional: true,\n        render (h, ctx) {\n          var day = ctx.props.day\n          return h('div', { staticClass: 'uptime-day'}, [\n            h('span', { staticClass: 'uptime-day-status', style: { backgroundColor: day.up ? '#8cc665' : '#ccc' } }),\n            h('span', { staticClass: 'hover' }, [day.number + ': ' + day.up ? 'Servers operational!' : 'Red alert!'])\n          ])\n        }\n      })\n\n      Vue.component('server-uptime', {\n        props: ['name', 'days'],\n        computed: {\n          upDays () {\n            return this.days.reduce(function (upDays, day) {\n              return upDays += (day.up ? 1 : 0)\n            }, 0)\n          },\n          maxStreak () {\n            var streak = this.days.reduce(([max, streak], day) => {\n              if (day.up && streak + 1 > max) {\n                return [streak + 1, streak + 1]\n              } else if (day.up) {\n                return [max, streak + 1]\n              } else {\n                return [max, 0]\n              }\n            }, [0, 0])\n\n            return streak.max\n          }\n        },\n        template: `\n          <div class=\"server-uptime\">\n            <h1>{{name}}</h1>\n            <h2>{{upDays}} Days Up</h2>\n            <h2>Biggest Streak: {{maxStreak}}</h2>\n            <div class=\"days\">\n              <uptime-day\n                v-for=\"day in days\"\n                :key=\"day.number\"\n                :day=\"day\">\n              </uptime-day>\n            </div>\n          </div>\n        `\n      })\n\n      function generateServer (name) {\n        var days = []\n        for (var i=0; i<=364; i++) {\n          var up = Math.random() > 0.2\n          days.push({ number: i, up })\n        }\n        return { name, days }\n      }\n\n      function generateServers () {\n        return [\n          generateServer(\"Stefan's Server\"),\n          generateServer(\"Godfrey's Server\"),\n          generateServer(\"Yehuda's Server\")\n        ]\n      }\n\n      var s = window.performance.now()\n      var app = new Vue({\n        el: '#app',\n        data: {\n          fps: 0,\n          playing: false,\n          servers: Object.freeze(generateServers())\n        },\n        methods: {\n          toggle () {\n            this.playing = !this.playing\n            if (this.playing) {\n              update()\n            } else {\n              clearTimeout(timeoutId)\n            }\n          }\n        }\n      })\n      console.log('initial render: ' + (window.performance.now() - s) + 'ms')\n\n      var fpsMeter = {\n        alpha: 2/121,\n        lastValue: null,\n        push (dataPoint) {\n          if (this.lastValue) {\n            return this.lastValue = this.lastValue + this.alpha * (dataPoint - this.lastValue)\n          } else {\n            return this.lastValue = dataPoint\n          }\n        }\n      }\n\n      var timeoutId\n      var lastFrame = null\n      function update () {\n        var thisFrame = window.performance.now()\n        if (lastFrame) {\n          app.fps = Math.round(fpsMeter.push(1000 / (thisFrame - lastFrame)))\n        }\n        app.servers = Object.freeze(generateServers())\n        timeoutId = setTimeout(update, 0) // not using rAF because that limits us to 60fps!\n        lastFrame = thisFrame\n      }\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "build/alias.js",
    "content": "const path = require('path')\n\nmodule.exports = {\n  vue: path.resolve(__dirname, '../src/platforms/web/entry-runtime-with-compiler'),\n  compiler: path.resolve(__dirname, '../src/compiler'),\n  core: path.resolve(__dirname, '../src/core'),\n  shared: path.resolve(__dirname, '../src/shared'),\n  web: path.resolve(__dirname, '../src/platforms/web'),\n  weex: path.resolve(__dirname, '../src/platforms/weex'),\n  mp: path.resolve(__dirname, '../src/platforms/mp'),\n  server: path.resolve(__dirname, '../src/server'),\n  entries: path.resolve(__dirname, '../src/entries'),\n  sfc: path.resolve(__dirname, '../src/sfc')\n}\n"
  },
  {
    "path": "build/build.js",
    "content": "const fs = require('fs')\nconst path = require('path')\nconst zlib = require('zlib')\nconst rollup = require('rollup')\nconst uglify = require('uglify-js')\n\nif (!fs.existsSync('dist')) {\n  fs.mkdirSync('dist')\n}\n\nlet builds = require('./config').getAllBuilds()\n\n// filter builds via command line arg\nif (process.argv[2]) {\n  const filters = process.argv[2].split(',')\n  builds = builds.filter(b => {\n    // fix the project name === floder name\n    // return filters.some(f => b.dest.indexOf(f) > -1)\n    return filters.some(f => b.dest.slice(path.resolve(__dirname, '../').length).indexOf(f) > -1)\n  })\n} else {\n  // filter out weex builds by default\n  builds = builds.filter(b => {\n    return b.dest.indexOf('weex') === -1\n  })\n}\n\nbuild(builds)\n\nfunction build (builds) {\n  let built = 0\n  const total = builds.length\n  const next = () => {\n    buildEntry(builds[built]).then(() => {\n      built++\n      if (built < total) {\n        next()\n      }\n    }).catch(logError)\n  }\n\n  next()\n}\n\nfunction buildEntry (config) {\n  const isProd = /min\\.js$/.test(config.dest)\n  return rollup.rollup(config)\n    .then(bundle => bundle.generate(config))\n    .then(({ code }) => {\n      if (isProd) {\n        var minified = (config.banner ? config.banner + '\\n' : '') + uglify.minify(code, {\n          output: {\n            ascii_only: true\n          },\n          compress: {\n            pure_funcs: ['makeMap']\n          }\n        }).code\n        return write(config.dest, minified, true)\n      } else {\n        return write(config.dest, code)\n      }\n    })\n}\n\nfunction write (dest, code, zip) {\n  return new Promise((resolve, reject) => {\n    function report (extra) {\n      console.log(blue(path.relative(process.cwd(), dest)) + ' ' + getSize(code) + (extra || ''))\n      resolve()\n    }\n\n    fs.writeFile(dest, code, err => {\n      if (err) return reject(err)\n      if (zip) {\n        zlib.gzip(code, (err, zipped) => {\n          if (err) return reject(err)\n          report(' (gzipped: ' + getSize(zipped) + ')')\n        })\n      } else {\n        report()\n      }\n    })\n  })\n}\n\nfunction getSize (code) {\n  return (code.length / 1024).toFixed(2) + 'kb'\n}\n\nfunction logError (e) {\n  console.log(e)\n}\n\nfunction blue (str) {\n  return '\\x1b[1m\\x1b[34m' + str + '\\x1b[39m\\x1b[22m'\n}\n"
  },
  {
    "path": "build/ci.sh",
    "content": "set -e\nnpm test\n\n# report coverage stats for non-PRs\nif [[ -z $CI_PULL_REQUEST ]]; then\n  cat ./coverage/lcov.info | ./node_modules/.bin/codecov\nfi\n"
  },
  {
    "path": "build/config.js",
    "content": "const path = require('path')\nconst buble = require('rollup-plugin-buble')\nconst alias = require('rollup-plugin-alias')\nconst cjs = require('rollup-plugin-commonjs')\nconst replace = require('rollup-plugin-replace')\nconst node = require('rollup-plugin-node-resolve')\nconst flow = require('rollup-plugin-flow-no-whitespace')\nconst version = process.env.VERSION || require('../package.json').version\nconst weexVersion = process.env.WEEX_VERSION || require('../packages/weex-vue-framework/package.json').version\nconst mpVueVersion = process.env.MP_VUE_VERSION || require('../packages/mpvue/package.json').version\n\nconst banner =\n  '/*!\\n' +\n  ' * Vue.js v' + version + '\\n' +\n  ' * (c) 2014-' + new Date().getFullYear() + ' Evan You\\n' +\n  ' * Released under the MIT License.\\n' +\n  ' */'\n\nconst { mpBanner, mpLifecycleHooks } = require('../src/platforms/mp/join-code-in-build')\n\nconst weexFactoryPlugin = {\n  intro () {\n    return 'module.exports = function weexFactory (exports, renderer) {'\n  },\n  outro () {\n    return '}'\n  }\n}\n\nconst aliases = require('./alias')\nconst resolve = p => {\n  const base = p.split('/')[0]\n  if (aliases[base]) {\n    return path.resolve(aliases[base], p.slice(base.length + 1))\n  } else {\n    return path.resolve(__dirname, '../', p)\n  }\n}\n\nconst builds = {\n  // Runtime only (CommonJS). Used by bundlers e.g. Webpack & Browserify\n  'web-runtime-cjs': {\n    entry: resolve('web/entry-runtime.js'),\n    dest: resolve('dist/vue.runtime.common.js'),\n    format: 'cjs',\n    banner\n  },\n  // Runtime+compiler CommonJS build (CommonJS)\n  'web-full-cjs': {\n    entry: resolve('web/entry-runtime-with-compiler.js'),\n    dest: resolve('dist/vue.common.js'),\n    format: 'cjs',\n    alias: { he: './entity-decoder' },\n    banner\n  },\n  // Runtime only (ES Modules). Used by bundlers that support ES Modules,\n  // e.g. Rollup & Webpack 2\n  'web-runtime-esm': {\n    entry: resolve('web/entry-runtime.js'),\n    dest: resolve('dist/vue.runtime.esm.js'),\n    format: 'es',\n    banner\n  },\n  // Runtime+compiler CommonJS build (ES Modules)\n  'web-full-esm': {\n    entry: resolve('web/entry-runtime-with-compiler.js'),\n    dest: resolve('dist/vue.esm.js'),\n    format: 'es',\n    alias: { he: './entity-decoder' },\n    banner\n  },\n  // runtime-only build (Browser)\n  'web-runtime-dev': {\n    entry: resolve('web/entry-runtime.js'),\n    dest: resolve('dist/vue.runtime.js'),\n    format: 'umd',\n    env: 'development',\n    banner\n  },\n  // runtime-only production build (Browser)\n  'web-runtime-prod': {\n    entry: resolve('web/entry-runtime.js'),\n    dest: resolve('dist/vue.runtime.min.js'),\n    format: 'umd',\n    env: 'production',\n    banner\n  },\n  // Runtime+compiler development build (Browser)\n  'web-full-dev': {\n    entry: resolve('web/entry-runtime-with-compiler.js'),\n    dest: resolve('dist/vue.js'),\n    format: 'umd',\n    env: 'development',\n    alias: { he: './entity-decoder' },\n    banner\n  },\n  // Runtime+compiler production build  (Browser)\n  'web-full-prod': {\n    entry: resolve('web/entry-runtime-with-compiler.js'),\n    dest: resolve('dist/vue.min.js'),\n    format: 'umd',\n    env: 'production',\n    alias: { he: './entity-decoder' },\n    banner\n  },\n  // Web compiler (CommonJS).\n  'web-compiler': {\n    entry: resolve('web/entry-compiler.js'),\n    dest: resolve('packages/vue-template-compiler/build.js'),\n    format: 'cjs',\n    external: Object.keys(require('../packages/vue-template-compiler/package.json').dependencies)\n  },\n  // Web server renderer (CommonJS).\n  'web-server-renderer': {\n    entry: resolve('web/entry-server-renderer.js'),\n    dest: resolve('packages/vue-server-renderer/build.js'),\n    format: 'cjs',\n    external: Object.keys(require('../packages/vue-server-renderer/package.json').dependencies)\n  },\n  'web-server-basic-renderer': {\n    entry: resolve('web/entry-server-basic-renderer.js'),\n    dest: resolve('packages/vue-server-renderer/basic.js'),\n    format: 'umd',\n    env: 'development',\n    moduleName: 'renderVueComponentToString',\n    plugins: [node(), cjs()]\n  },\n  'web-server-renderer-webpack-server-plugin': {\n    entry: resolve('server/webpack-plugin/server.js'),\n    dest: resolve('packages/vue-server-renderer/server-plugin.js'),\n    format: 'cjs',\n    external: Object.keys(require('../packages/vue-server-renderer/package.json').dependencies)\n  },\n  'web-server-renderer-webpack-client-plugin': {\n    entry: resolve('server/webpack-plugin/client.js'),\n    dest: resolve('packages/vue-server-renderer/client-plugin.js'),\n    format: 'cjs',\n    external: Object.keys(require('../packages/vue-server-renderer/package.json').dependencies)\n  },\n  // Weex runtime factory\n  'weex-factory': {\n    weex: true,\n    entry: resolve('weex/entry-runtime-factory.js'),\n    dest: resolve('packages/weex-vue-framework/factory.js'),\n    format: 'cjs',\n    plugins: [weexFactoryPlugin]\n  },\n  // Weex runtime framework (CommonJS).\n  'weex-framework': {\n    weex: true,\n    entry: resolve('weex/entry-framework.js'),\n    dest: resolve('packages/weex-vue-framework/index.js'),\n    format: 'cjs'\n  },\n  // Weex compiler (CommonJS). Used by Weex's Webpack loader.\n  'weex-compiler': {\n    weex: true,\n    entry: resolve('weex/entry-compiler.js'),\n    dest: resolve('packages/weex-template-compiler/build.js'),\n    format: 'cjs',\n    external: Object.keys(require('../packages/weex-template-compiler/package.json').dependencies)\n  },\n  // Runtime only (ES Modules). Used by bundlers that support ES Modules,\n  // e.g. Rollup & Webpack 2\n  'mpvue': {\n    mp: true,\n    entry: resolve('mp/entry-runtime.js'),\n    dest: resolve('packages/mpvue/index.js'),\n    format: 'umd',\n    env: 'production',\n    banner: mpBanner\n  },\n  // MP compiler (CommonJS). Used by mpvue's Webpack loader.\n  'mpvue-template-compiler': {\n    mp: true,\n    entry: resolve('mp/entry-compiler.js'),\n    dest: resolve('packages/mpvue-template-compiler/build.js'),\n    format: 'cjs',\n    external: Object.keys(require('../packages/mpvue-template-compiler/package.json').dependencies)\n  }\n}\n\nfunction genConfig (opts) {\n  const config = {\n    entry: opts.entry,\n    dest: opts.dest,\n    external: opts.external,\n    format: opts.format,\n    banner: opts.banner,\n    moduleName: opts.moduleName || 'Vue',\n    plugins: [\n      replace({\n        __WEEX__: !!opts.weex,\n        __MPVUE__: !!opts.mp,\n        __WEEX_VERSION__: weexVersion,\n        __MPVUE_VERSION__: mpVueVersion,\n        __VERSION__: version\n      }),\n      flow(),\n      buble(),\n      alias(Object.assign({}, aliases, opts.alias))\n    ].concat(opts.plugins || [])\n  }\n\n  if (opts.env) {\n    config.plugins.push(replace({\n      'process.env.NODE_ENV': JSON.stringify(opts.env)\n    }))\n  }\n\n  // hack fix MP LIFECYCLE_HOOKS\n  if (opts.mp) {\n    config.plugins.push(replace({\n      \"'deactivated'\\n]\": `'deactivated', ${mpLifecycleHooks}\\n]`\n    }))\n    config.plugins.push(replace({\n      'inBrowser && window.navigator.userAgent.toLowerCase': `['mpvue-runtime'].join`\n    }))\n  }\n\n  return config\n}\n\nif (process.env.TARGET) {\n  module.exports = genConfig(builds[process.env.TARGET])\n} else {\n  exports.getBuild = name => genConfig(builds[name])\n  exports.getAllBuilds = () => Object.keys(builds).map(name => genConfig(builds[name]))\n}\n"
  },
  {
    "path": "build/gen-release-note.js",
    "content": "const version = process.argv[2] || process.env.VERSION\nconst cc = require('conventional-changelog')\nconst file = `./RELEASE_NOTE_${version}.md`\nconst fileStream = require('fs').createWriteStream(file)\n\ncc({\n  preset: 'angular',\n  pkg: {\n    transform (pkg) {\n      pkg.version = `v${version}`\n      return pkg\n    }\n  }\n}).pipe(fileStream).on('close', () => {\n  console.log(`Generated release note at ${file}`)\n})\n"
  },
  {
    "path": "build/get-weex-version.js",
    "content": "var coreVersion = require('../package.json').version\nvar weexVersion = require('../packages/weex-vue-framework/package.json').version\nvar weexBaseVersion = weexVersion.match(/^[\\d.]+/)[0]\nvar weexSubVersion = Number(weexVersion.match(/-weex\\.(\\d+)$/)[1])\n\nif (weexBaseVersion === coreVersion) {\n  // same core version, increment sub version\n  weexSubVersion++\n} else {\n  // new core version, reset sub version\n  weexBaseVersion = coreVersion\n  weexSubVersion = 1\n}\n\nif (process.argv[2] === '-c') {\n  console.log(weexVersion)\n} else {\n  console.log(weexBaseVersion + '-weex.' + weexSubVersion)\n}\n\nmodule.exports = {\n  base: weexBaseVersion,\n  sub: weexSubVersion\n}\n"
  },
  {
    "path": "build/git-hooks/commit-msg",
    "content": "#!/usr/bin/env bash\n\n# Validate commit log\ncommit_regex='^Merge.+|(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\\(.+\\))?: .{1,50}'\n\nif ! grep -iqE \"$commit_regex\" \"$1\"; then\n    echo\n    echo \"  Error: proper commit message format is required for automated changelog generation.\"\n    echo\n    echo \"  - Use \\`npm run commit\\` to interactively generate a commit message.\"\n    echo \"  - See .github/COMMIT_CONVENTION.md for more details.\"\n    echo\n    exit 1\nfi\n"
  },
  {
    "path": "build/git-hooks/pre-commit",
    "content": "#!/usr/bin/env bash\n\nfiles_to_lint=$(git diff --cached --name-only --diff-filter=ACM | grep '\\.js$')\n\nif [ -n \"$files_to_lint\" ]; then\n  NODE_ENV=production eslint --quiet $files_to_lint\nfi\n"
  },
  {
    "path": "build/install-hooks.js",
    "content": "const { test, ln, chmod } = require('shelljs')\n\nif (test('-e', '.git/hooks')) {\n  ln('-sf', '../../build/git-hooks/pre-commit', '.git/hooks/pre-commit')\n  chmod('+x', '.git/hooks/pre-commit')\n  ln('-sf', '../../build/git-hooks/commit-msg', '.git/hooks/commit-msg')\n  chmod('+x', '.git/hooks/commit-msg')\n}\n"
  },
  {
    "path": "build/release-weex.sh",
    "content": "set -e\nCUR_VERSION=`node build/get-weex-version.js -c`\nNEXT_VERSION=`node build/get-weex-version.js`\n\necho \"Current: $CUR_VERSION\"\nread -p \"Enter new version ($NEXT_VERSION): \" -n 1 -r\nif ! [[ -z $REPLY ]]; then\n  NEXT_VERSION=$REPLY\nfi\n\nread -p \"Releasing weex-vue-framework@$NEXT_VERSION - are you sure? (y/n) \" -n 1 -r\necho\nif [[ $REPLY =~ ^[Yy]$ ]]; then\n  echo \"Releasing weex-vue-framework@$NEXT_VERSION ...\"\n  npm run lint\n  npm run flow\n  npm run test:weex\n\n  # build\n  WEEX_VERSION=$NEXT_VERSION npm run build:weex\n\n  # update package\n  cd packages/weex-vue-framework\n  npm version $NEXT_VERSION\n  npm publish\n  cd -\n\n  cd packages/weex-template-compiler\n  npm version $NEXT_VERSION\n  npm publish\n  cd -\n\n  # commit\n  git add src/entries/weex*\n  git add packages/weex*\n  git commit -m \"[release] weex-vue-framework@$NEXT_VERSION\"\nfi\n"
  },
  {
    "path": "build/release.sh",
    "content": "set -e\n\nif [[ -z $1 ]]; then\n  echo \"Enter new version: \"\n  read VERSION\nelse\n  VERSION=$1\nfi\n\nread -p \"Releasing $VERSION - are you sure? (y/n) \" -n 1 -r\necho\nif [[ $REPLY =~ ^[Yy]$ ]]; then\n  echo \"Releasing $VERSION ...\"\n\n  if [[ -z $SKIP_TESTS ]]; then\n    npm run lint\n    npm run flow\n    npm run test:cover\n    npm run test:e2e\n    npm run test:ssr\n  fi\n\n  if [[ -z $SKIP_SAUCE ]]; then\n    export SAUCE_BUILD_ID=$VERSION:`date +\"%s\"`\n    npm run test:sauce\n  fi\n\n  # build\n  VERSION=$VERSION npm run build\n\n  # update packages\n  cd packages/vue-template-compiler\n  npm version $VERSION\n  if [[ -z $RELEASE_TAG ]]; then\n    npm publish\n  else\n    npm publish --tag $RELEASE_TAG\n  fi\n  cd -\n\n  cd packages/vue-server-renderer\n  npm version $VERSION\n  if [[ -z $RELEASE_TAG ]]; then\n    npm publish\n  else\n    npm publish --tag $RELEASE_TAG\n  fi\n  cd -\n\n  # commit\n  git add -A\n  git add -f \\\n    dist/*.js \\\n    packages/vue-server-renderer/basic.js \\\n    packages/vue-server-renderer/build.js \\\n    packages/vue-server-renderer/server-plugin.js \\\n    packages/vue-server-renderer/client-plugin.js \\\n    packages/vue-template-compiler/build.js\n  git commit -m \"build: build $VERSION\"\n  npm version $VERSION --message \"build: release $VERSION\"\n\n  # publish\n  git push origin refs/tags/v$VERSION\n  git push\n  if [[ -z $RELEASE_TAG ]]; then\n    npm publish\n  else\n    npm publish --tag $RELEASE_TAG\n  fi\nfi\n"
  },
  {
    "path": "circle.yml",
    "content": "machine:\n  node:\n    version: 6\n\ntest:\n  override:\n    - bash build/ci.sh\n"
  },
  {
    "path": "dist/README.md",
    "content": "## Explanation of Build Files\n\n| | UMD | CommonJS | ES Module |\n| --- | --- | --- | --- |\n| **Full** | vue.js | vue.common.js | vue.esm.js |\n| **Runtime-only** | vue.runtime.js | vue.runtime.common.js | vue.runtime.esm.js |\n| **Full (production)** | vue.min.js | | |\n| **Runtime-only (production)** | vue.runtime.min.js | | |\n\n### Terms\n\n- **Full**: builds that contains both the compiler and the runtime.\n\n- **Compiler**: code that is responsible for compiling template strings into JavaScript render functions.\n\n- **Runtime**: code that is responsible for creating Vue instances, rendering and patching virtual DOM, etc. Basically everything minus the compiler.\n\n- **[UMD](https://github.com/umdjs/umd)**: UMD builds can be used directly in the browser via a `<script>` tag. The default file from Unpkg CDN at [https://unpkg.com/vue](https://unpkg.com/vue) is the Runtime + Compiler UMD build (`vue.js`).\n\n- **[CommonJS](http://wiki.commonjs.org/wiki/Modules/1.1)**: CommonJS builds are intended for use with older bundlers like [browserify](http://browserify.org/) or [webpack 1](https://webpack.github.io). The default file for these bundlers (`pkg.main`) is the Runtime only CommonJS build (`vue.runtime.common.js`).\n\n- **[ES Module](http://exploringjs.com/es6/ch_modules.html)**: ES module builds are intended for use with modern bundlers like [webpack 2](https://webpack.js.org) or [rollup](http://rollupjs.org/). The default file for these bundlers (`pkg.module`) is the Runtime only ES Module build (`vue.runtime.esm.js`).\n\n### Runtime + Compiler vs. Runtime-only\n\nIf you need to compile templates on the fly (e.g. passing a string to the `template` option, or mounting to an element using its in-DOM HTML as the template), you will need the compiler and thus the full build.\n\nWhen using `vue-loader` or `vueify`, templates inside `*.vue` files are compiled into JavaScript at build time. You don't really need the compiler in the final bundle, and can therefore use the runtime-only build.\n\nSince the runtime-only builds are roughly 30% lighter-weight than their full-build counterparts, you should use it whenever you can. If you wish to use the full build instead, you need to configure an alias in your bundler.\n\n#### Webpack\n\n``` js\nmodule.exports = {\n  // ...\n  resolve: {\n    alias: {\n      'vue$': 'vue/dist/vue.esm.js' // 'vue/dist/vue.common.js' for webpack 1\n    }\n  }\n}\n````\n\n#### Rollup\n\n``` js\nconst alias = require('rollup-plugin-alias')\n\nrollup({\n  // ...\n  plugins: [\n    alias({\n      'vue': 'vue/dist/vue.esm.js'\n    })\n  ]\n})\n```\n\n#### Browserify\n\nAdd to your project's `package.json`:\n\n``` js\n{\n  // ...\n  \"browser\": {\n    \"vue\": \"vue/dist/vue.common.js\"\n  }\n}\n```\n\n### Development vs. Production Mode\n\nDevelopment/production modes are hard-coded for the UMD builds: the un-minified files are for development, and the minified files are for production.\n\nCommonJS and ES Module builds are intended for bundlers, therefore we don't provide minified versions for them. You will be responsible for minifying the final bundle yourself.\n\nCommonJS and ES Module builds also preserve raw checks for `process.env.NODE_ENV` to determine the mode they should run in. You should use appropriate bundler configurations to replace these environment variables in order to control which mode Vue will run in. Replacing `process.env.NODE_ENV` with string literals also allows minifiers like UglifyJS to completely drop the development-only code blocks, reducing final file size.\n\n#### Webpack\n\nUse Webpack's [DefinePlugin](https://webpack.js.org/plugins/define-plugin/):\n\n``` js\nvar webpack = require('webpack')\n\nmodule.exports = {\n  // ...\n  plugins: [\n    // ...\n    new webpack.DefinePlugin({\n      'process.env': {\n        NODE_ENV: JSON.stringify('production')\n      }\n    })\n  ]\n}\n```\n\n#### Rollup\n\nUse [rollup-plugin-replace](https://github.com/rollup/rollup-plugin-replace):\n\n``` js\nconst replace = require('rollup-plugin-replace')\n\nrollup({\n  // ...\n  plugins: [\n    replace({\n      'process.env.NODE_ENV': JSON.stringify('production')\n    })\n  ]\n}).then(...)\n```\n\n#### Browserify\n\nApply a global [envify](https://github.com/hughsk/envify) transform to your bundle.\n\n``` bash\nNODE_ENV=production browserify -g envify -e main.js | uglifyjs -c -m > build.js\n```\n"
  },
  {
    "path": "examples/commits/app.js",
    "content": "var apiURL = 'https://api.github.com/repos/vuejs/vue/commits?per_page=3&sha='\n\n/**\n * Actual demo\n */\n\nvar demo = new Vue({\n\n  el: '#demo',\n\n  data: {\n    branches: ['master', 'dev'],\n    currentBranch: 'master',\n    commits: null\n  },\n\n  created: function () {\n    this.fetchData()\n  },\n\n  watch: {\n    currentBranch: 'fetchData'\n  },\n\n  filters: {\n    truncate: function (v) {\n      var newline = v.indexOf('\\n')\n      return newline > 0 ? v.slice(0, newline) : v\n    },\n    formatDate: function (v) {\n      return v.replace(/T|Z/g, ' ')\n    }\n  },\n\n  methods: {\n    fetchData: function () {\n      var xhr = new XMLHttpRequest()\n      var self = this\n      xhr.open('GET', apiURL + self.currentBranch)\n      xhr.onload = function () {\n        self.commits = JSON.parse(xhr.responseText)\n        console.log(self.commits[0].html_url)\n      }\n      xhr.send()\n    }\n  }\n})\n"
  },
  {
    "path": "examples/commits/index.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>Vue.js github commits example</title>\n    <style>\n      #demo {\n        font-family: 'Helvetica', Arial, sans-serif;\n      }\n      a {\n        text-decoration: none;\n        color: #f66;\n      }\n      li {\n        line-height: 1.5em;\n        margin-bottom: 20px;\n      }\n      .author, .date {\n        font-weight: bold;\n      }\n    </style>\n    <!-- Delete \".min\" for console warnings in development -->\n    <script src=\"../../dist/vue.min.js\"></script>\n  </head>\n  <body>\n    <div id=\"demo\">\n      <h1>Latest Vue.js Commits</h1>\n      <template v-for=\"branch in branches\">\n        <input type=\"radio\"\n          :id=\"branch\"\n          :value=\"branch\"\n          name=\"branch\"\n          v-model=\"currentBranch\">\n        <label :for=\"branch\">{{ branch }}</label>\n      </template>\n      <p>vuejs/vue@{{ currentBranch }}</p>\n      <ul>\n        <li v-for=\"record in commits\">\n          <a :href=\"record.html_url\" target=\"_blank\" class=\"commit\">{{ record.sha.slice(0, 7) }}</a>\n          - <span class=\"message\">{{ record.commit.message | truncate }}</span><br>\n          by <span class=\"author\"><a :href=\"record.author.html_url\" target=\"_blank\">{{ record.commit.author.name }}</a></span>\n          at <span class=\"date\">{{ record.commit.author.date | formatDate }}</span>\n        </li>\n      </ul>\n    </div>\n    <script src=\"app.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/elastic-header/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"initial-scale=1, maximum-scale=1, user-scalable=no\">\n    <title>Vue.js elastic header example</title>\n    <!-- Delete \".min\" for console warnings in development -->\n    <script src=\"../../dist/vue.min.js\"></script>\n    <script src=\"http://dynamicsjs.com/lib/dynamics.js\"></script>\n    <link rel=\"stylesheet\" href=\"style.css\">\n    <!-- template for the component -->\n    <script type=\"text/x-template\" id=\"header-view-template\">\n      <div class=\"draggable-header-view\"\n        @mousedown=\"startDrag\" @touchstart=\"startDrag\"\n        @mousemove=\"onDrag\" @touchmove=\"onDrag\"\n        @mouseup=\"stopDrag\" @touchend=\"stopDrag\" @mouseleave=\"stopDrag\">\n        <svg class=\"bg\" width=\"320\" height=\"560\">\n          <path :d=\"headerPath\" fill=\"#3F51B5\"></path>\n        </svg>\n        <div class=\"header\">\n          <slot name=\"header\"></slot>\n        </div>\n        <div class=\"content\" :style=\"contentPosition\">\n          <slot name=\"content\"></slot>\n        </div>\n      </div>\n    </script>\n  </head>\n  <body>\n\n    <div id=\"app\" @touchmove.prevent>\n      <draggable-header-view>\n        <template slot=\"header\">\n          <h1>Elastic Draggable SVG Header</h1>\n          <p>with <a href=\"https://vuejs.org\">Vue.js</a> + <a href=\"http://dynamicsjs.com\">dynamics.js</a></p>\n        </template>\n        <template slot=\"content\">\n          <p>Note this is just an effect demo - there are of course many additional details if you want to use this in production, e.g. handling responsive sizes, reload threshold and content scrolling. Those are out of scope for this quick little hack. However, the idea is that you can hide them as internal details of a Vue.js component and expose a simple Web-Component-like interface.</p>\n        </template>\n      </draggable-header-view>\n    </div>\n\n    <script>\n    Vue.component('draggable-header-view', {\n      template: '#header-view-template',\n      data: function () {\n        return {\n          dragging: false,\n          // quadratic bezier control point\n          c: { x: 160, y: 160 },\n          // record drag start point\n          start: { x: 0, y: 0 }\n        }\n      },\n      computed: {\n        headerPath: function () {\n          return 'M0,0 L320,0 320,160' +\n            'Q' + this.c.x + ',' + this.c.y +\n            ' 0,160'\n        },\n        contentPosition: function () {\n          var dy = this.c.y - 160\n          var dampen = dy > 0 ? 2 : 4\n          return {\n            transform: 'translate3d(0,' + dy / dampen + 'px,0)'\n          }\n        }\n      },\n      methods: {\n        startDrag: function (e) {\n          e = e.changedTouches ? e.changedTouches[0] : e\n          this.dragging = true\n          this.start.x = e.pageX\n          this.start.y = e.pageY\n        },\n        onDrag: function (e) {\n          e = e.changedTouches ? e.changedTouches[0] : e\n          if (this.dragging) {\n            this.c.x = 160 + (e.pageX - this.start.x)\n            // dampen vertical drag by a factor\n            var dy = e.pageY - this.start.y\n            var dampen = dy > 0 ? 1.5 : 4\n            this.c.y = 160 + dy / dampen\n          }\n        },\n        stopDrag: function () {\n          if (this.dragging) {\n            this.dragging = false\n            dynamics.animate(this.c, {\n              x: 160,\n              y: 160\n            }, {\n              type: dynamics.spring,\n              duration: 700,\n              friction: 280\n            })\n          }\n        }\n      }\n    })\n\n    new Vue({ el: '#app' })\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/elastic-header/style.css",
    "content": "h1 {\n  font-weight: 300;\n  font-size: 1.8em;\n  margin-top: 0;\n}\na {\n  color: #fff;\n}\n.draggable-header-view {\n  background-color: #fff;\n  box-shadow: 0 4px 16px rgba(0,0,0,.15);\n  width: 320px;\n  height: 560px;\n  overflow: hidden;\n  margin: 30px auto;\n  position: relative;\n  font-family: 'Roboto', Helvetica, Arial, sans-serif;\n  color: #fff;\n  font-size: 14px;\n  font-weight: 300;\n  -webkit-user-select: none;\n  -moz-user-select: none;\n  -ms-user-select: none;\n  user-select: none;\n}\n.draggable-header-view .bg {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 0;\n}\n.draggable-header-view .header, .draggable-header-view .content {\n  position: relative;\n  z-index: 1;\n  padding: 30px;\n  box-sizing: border-box;\n}\n.draggable-header-view .header {\n  height: 160px;\n}\n.draggable-header-view .content {\n  color: #333;\n  line-height: 1.5em;\n}\n"
  },
  {
    "path": "examples/firebase/app.js",
    "content": "var emailRE = /^(([^<>()[\\]\\\\.,;:\\s@\\\"]+(\\.[^<>()[\\]\\\\.,;:\\s@\\\"]+)*)|(\\\".+\\\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$/\n\n// Setup Firebase\nvar config = {\n  apiKey: \"AIzaSyAi_yuJciPXLFr_PYPeU3eTvtXf8jbJ8zw\",\n  authDomain: \"vue-demo-537e6.firebaseapp.com\",\n  databaseURL: \"https://vue-demo-537e6.firebaseio.com\"\n}\nfirebase.initializeApp(config)\n\nvar usersRef = firebase.database().ref('users')\n\n// create Vue app\nvar app = new Vue({\n  // element to mount to\n  el: '#app',\n  // initial data\n  data: {\n    newUser: {\n      name: '',\n      email: ''\n    }\n  },\n  // firebase binding\n  // https://github.com/vuejs/vuefire\n  firebase: {\n    users: usersRef\n  },\n  // computed property for form validation state\n  computed: {\n    validation: function () {\n      return {\n        name: !!this.newUser.name.trim(),\n        email: emailRE.test(this.newUser.email)\n      }\n    },\n    isValid: function () {\n      var validation = this.validation\n      return Object.keys(validation).every(function (key) {\n        return validation[key]\n      })\n    }\n  },\n  // methods\n  methods: {\n    addUser: function () {\n      if (this.isValid) {\n        usersRef.push(this.newUser)\n        this.newUser.name = ''\n        this.newUser.email = ''\n      }\n    },\n    removeUser: function (user) {\n      usersRef.child(user['.key']).remove()\n    }\n  }\n})\n"
  },
  {
    "path": "examples/firebase/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <title>Vue.js firebase + validation example</title>\n    <meta charset=\"utf-8\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\">\n    <!-- Vue -->\n    <!-- Delete \".min\" for console warnings in development -->\n    <script src=\"../../dist/vue.min.js\"></script>\n    <!-- Firebase -->\n    <script src=\"https://www.gstatic.com/firebasejs/3.4.0/firebase.js\"></script>\n    <!-- VueFire -->\n    <script src=\"https://unpkg.com/vuefire@1.3.0\"></script>\n  </head>\n  <body>\n    <div id=\"app\">\n      <ul is=\"transition-group\">\n        <li v-for=\"user in users\" class=\"user\" :key=\"user['.key']\">\n          <span>{{user.name}} - {{user.email}}</span>\n          <button v-on:click=\"removeUser(user)\">X</button>\n        </li>\n      </ul>\n      <form id=\"form\" v-on:submit.prevent=\"addUser\">\n        <input v-model=\"newUser.name\">\n        <input v-model=\"newUser.email\">\n        <input type=\"submit\" value=\"Add User\">\n      </form>\n      <ul class=\"errors\">\n        <li v-show=\"!validation.name\">Name cannot be empty.</li>\n        <li v-show=\"!validation.email\">Please provide a valid email address.</li>\n      </ul>\n    </div>\n    <script src=\"app.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/firebase/style.css",
    "content": "body {\n  font-family: Helvetica, Arial, sans-serif;\n}\n\nul {\n  padding: 0;\n}\n\n.user {\n  height: 30px;\n  line-height: 30px;\n  padding: 10px;\n  border-top: 1px solid #eee;\n  overflow: hidden;\n  transition: all .25s ease;\n}\n\n.user:last-child {\n  border-bottom: 1px solid #eee;\n}\n\n.v-enter, .v-leave-to {\n  height: 0;\n  padding-top: 0;\n  padding-bottom: 0;\n  border-top-width: 0;\n  border-bottom-width: 0;\n}\n\n.errors {\n  color: #f00;\n}\n"
  },
  {
    "path": "examples/grid/grid.js",
    "content": "// register the grid component\nVue.component('demo-grid', {\n  template: '#grid-template',\n  replace: true,\n  props: {\n    data: Array,\n    columns: Array,\n    filterKey: String\n  },\n  data: function () {\n    var sortOrders = {}\n    this.columns.forEach(function (key) {\n      sortOrders[key] = 1\n    })\n    return {\n      sortKey: '',\n      sortOrders: sortOrders\n    }\n  },\n  computed: {\n    filteredData: function () {\n      var sortKey = this.sortKey\n      var filterKey = this.filterKey && this.filterKey.toLowerCase()\n      var order = this.sortOrders[sortKey] || 1\n      var data = this.data\n      if (filterKey) {\n        data = data.filter(function (row) {\n          return Object.keys(row).some(function (key) {\n            return String(row[key]).toLowerCase().indexOf(filterKey) > -1\n          })\n        })\n      }\n      if (sortKey) {\n        data = data.slice().sort(function (a, b) {\n          a = a[sortKey]\n          b = b[sortKey]\n          return (a === b ? 0 : a > b ? 1 : -1) * order\n        })\n      }\n      return data\n    }\n  },\n  filters: {\n    capitalize: function (str) {\n      return str.charAt(0).toUpperCase() + str.slice(1)\n    }\n  },\n  methods: {\n    sortBy: function (key) {\n      this.sortKey = key\n      this.sortOrders[key] = this.sortOrders[key] * -1\n    }\n  }\n})\n\n// bootstrap the demo\nvar demo = new Vue({\n  el: '#demo',\n  data: {\n    searchQuery: '',\n    gridColumns: ['name', 'power'],\n    gridData: [\n      { name: 'Chuck Norris', power: Infinity },\n      { name: 'Bruce Lee', power: 9000 },\n      { name: 'Jackie Chan', power: 7000 },\n      { name: 'Jet Li', power: 8000 }\n    ]\n  }\n})\n"
  },
  {
    "path": "examples/grid/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <title>Vue.js grid component example</title>\n    <link rel=\"stylesheet\" href=\"style.css\">\n    <!-- Delete \".min\" for console warnings in development -->\n    <script src=\"../../dist/vue.min.js\"></script>\n    </head>\n  <body>\n\n    <!-- component template -->\n    <script type=\"text/x-template\" id=\"grid-template\">\n      <table v-if=\"filteredData.length\">\n        <thead>\n          <tr>\n            <th v-for=\"key in columns\"\n              @click=\"sortBy(key)\"\n              :class=\"{ active: sortKey == key }\">\n              {{ key | capitalize }}\n              <span class=\"arrow\" :class=\"sortOrders[key] > 0 ? 'asc' : 'dsc'\">\n              </span>\n            </th>\n          </tr>\n        </thead>\n        <tbody>\n          <tr v-for=\"entry in filteredData\">\n            <td v-for=\"key in columns\">\n              {{entry[key]}}\n            </td>\n          </tr>\n        </tbody>\n      </table>\n      <p v-else>No matches found.</p>\n    </script>\n\n    <!-- demo root element -->\n    <div id=\"demo\">\n      <form id=\"search\">\n        Search <input name=\"query\" v-model=\"searchQuery\">\n      </form>\n      <demo-grid\n        :data=\"gridData\"\n        :columns=\"gridColumns\"\n        :filter-key=\"searchQuery\">\n      </demo-grid>\n    </div>\n\n    <script src=\"grid.js\"></script>\n\n  </body>\n</html>\n"
  },
  {
    "path": "examples/grid/style.css",
    "content": "body {\n  font-family: Helvetica Neue, Arial, sans-serif;\n  font-size: 14px;\n  color: #444;\n}\n\ntable {\n  border: 2px solid #42b983;\n  border-radius: 3px;\n  background-color: #fff;\n}\n\nth {\n  background-color: #42b983;\n  color: rgba(255,255,255,0.66);\n  cursor: pointer;\n  -webkit-user-select: none;\n  -moz-user-select: none;\n  -ms-user-select: none;\n  user-select: none;\n}\n\ntd {\n  background-color: #f9f9f9;\n}\n\nth, td {\n  min-width: 120px;\n  padding: 10px 20px;\n}\n\nth.active {\n  color: #fff;\n}\n\nth.active .arrow {\n  opacity: 1;\n}\n\n.arrow {\n  display: inline-block;\n  vertical-align: middle;\n  width: 0;\n  height: 0;\n  margin-left: 5px;\n  opacity: 0.66;\n}\n\n.arrow.asc {\n  border-left: 4px solid transparent;\n  border-right: 4px solid transparent;\n  border-bottom: 4px solid #fff;\n}\n\n.arrow.dsc {\n  border-left: 4px solid transparent;\n  border-right: 4px solid transparent;\n  border-top: 4px solid #fff;\n}\n"
  },
  {
    "path": "examples/markdown/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <title>Vue.js markdown editor example</title>\n    <link rel=\"stylesheet\" href=\"style.css\">\n    <script src=\"https://unpkg.com/marked@0.3.6\"></script>\n    <script src=\"https://unpkg.com/lodash@4.16.0\"></script>\n    <!-- Delete \".min\" for console warnings in development -->\n    <script src=\"../../dist/vue.min.js\"></script>\n  </head>\n  <body>\n\n    <div id=\"editor\">\n      <textarea :value=\"input\" @input=\"update\"></textarea>\n      <div v-html=\"compiledMarkdown\"></div>\n    </div>\n\n    <script>\n      new Vue({\n        el: '#editor',\n        data: {\n          input: '# hello'\n        },\n        computed: {\n          compiledMarkdown: function () {\n            return marked(this.input, { sanitize: true })\n          }\n        },\n        methods: {\n          update: _.debounce(function (e) {\n            this.input = e.target.value\n          }, 300)\n        }\n      })\n    </script>\n\n  </body>\n</html>\n"
  },
  {
    "path": "examples/markdown/style.css",
    "content": "html, body, #editor {\n  margin: 0;\n  height: 100%;\n  font-family: 'Helvetica Neue', Arial, sans-serif;\n  color: #333;\n}\n\ntextarea, #editor div {\n  display: inline-block;\n  width: 49%;\n  height: 100%;\n  vertical-align: top;\n  -webkit-box-sizing: border-box;\n  -moz-box-sizing: border-box;\n  box-sizing: border-box;\n  padding: 0 20px;\n}\n\ntextarea {\n  border: none;\n  border-right: 1px solid #ccc;\n  resize: none;\n  outline: none;\n  background-color: #f6f6f6;\n  font-size: 14px;\n  font-family: 'Monaco', courier, monospace;\n  padding: 20px;\n}\n\ncode {\n  color: #f66;\n}"
  },
  {
    "path": "examples/modal/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <title>Vue.js modal component example</title>\n    <!-- Delete \".min\" for console warnings in development -->\n    <script src=\"../../dist/vue.min.js\"></script>\n    <link rel=\"stylesheet\" href=\"style.css\">\n  </head>\n  <body>\n    <!-- template for the modal component -->\n    <script type=\"text/x-template\" id=\"modal-template\">\n      <transition name=\"modal\">\n        <div class=\"modal-mask\">\n          <div class=\"modal-wrapper\">\n            <div class=\"modal-container\">\n\n              <div class=\"modal-header\">\n                <slot name=\"header\">\n                  default header\n                </slot>\n              </div>\n\n              <div class=\"modal-body\">\n                <slot name=\"body\">\n                  default body\n                </slot>\n              </div>\n\n              <div class=\"modal-footer\">\n                <slot name=\"footer\">\n                  default footer\n                  <button class=\"modal-default-button\" @click=\"$emit('close')\">\n                    OK\n                  </button>\n                </slot>\n              </div>\n            </div>\n          </div>\n        </div>\n      </transition>\n    </script>\n\n    <!-- app -->\n    <div id=\"app\">\n      <button id=\"show-modal\" @click=\"showModal = true\">Show Modal</button>\n      <!-- use the modal component, pass in the prop -->\n      <modal v-if=\"showModal\" @close=\"showModal = false\">\n        <!--\n          you can use custom content here to overwrite\n          default content\n        -->\n        <h3 slot=\"header\">custom header</h3>\n      </modal>\n    </div>\n\n    <script>\n      // register modal component\n      Vue.component('modal', {\n        template: '#modal-template'\n      })\n\n      // start app\n      new Vue({\n        el: '#app',\n        data: {\n          showModal: false\n        }\n      })\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/modal/style.css",
    "content": ".modal-mask {\n  position: fixed;\n  z-index: 9998;\n  top: 0;\n  left: 0;\n  width: 100%;\n  height: 100%;\n  background-color: rgba(0, 0, 0, .5);\n  display: table;\n  transition: opacity .3s ease;\n}\n\n.modal-wrapper {\n  display: table-cell;\n  vertical-align: middle;\n}\n\n.modal-container {\n  width: 300px;\n  margin: 0px auto;\n  padding: 20px 30px;\n  background-color: #fff;\n  border-radius: 2px;\n  box-shadow: 0 2px 8px rgba(0, 0, 0, .33);\n  transition: all .3s ease;\n  font-family: Helvetica, Arial, sans-serif;\n}\n\n.modal-header h3 {\n  margin-top: 0;\n  color: #42b983;\n}\n\n.modal-body {\n  margin: 20px 0;\n}\n\n.modal-default-button {\n  float: right;\n}\n\n/*\n * The following styles are auto-applied to elements with\n * transition=\"modal\" when their visibility is toggled\n * by Vue.js.\n *\n * You can easily play with the modal transition by editing\n * these styles.\n */\n\n.modal-enter {\n  opacity: 0;\n}\n\n.modal-leave-to {\n  opacity: 0;\n}\n\n.modal-enter .modal-container,\n.modal-leave-to .modal-container {\n  -webkit-transform: scale(1.1);\n  transform: scale(1.1);\n}\n"
  },
  {
    "path": "examples/move-animations/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <title>Move Animations</title>\n    <style>\n      .container {\n        position: relative;\n        padding: 0;\n      }\n      .item {\n        width: 100%;\n        height: 30px;\n        background-color: #f3f3f3;\n        border: 1px solid #666;\n        box-sizing: border-box;\n      }\n      /* 1. declare transition */\n      .fade-move, .fade-enter-active, .fade-leave-active {\n        transition: all .5s cubic-bezier(.55,0,.1,1);\n      }\n      /* 2. declare enter from and leave to state */\n      .fade-enter, .fade-leave-to {\n        opacity: 0;\n        transform: scaleY(0.01) translate(30px, 0);\n      }\n      /* 3. ensure leaving items are taken out of layout flow so that moving\n            animations can be calculated correctly. */\n      .fade-leave-active {\n        position: absolute;\n      }\n    </style>\n    <script src=\"https://cdn.jsdelivr.net/lodash/4.3.0/lodash.min.js\"></script>\n    <!-- Delete \".min\" for console warnings in development -->\n    <script src=\"../../dist/vue.min.js\"></script>\n  </head>\n  <body>\n    <div id=\"el\">\n      <button @click=\"insert\">insert at random index</button>\n      <button @click=\"reset\">reset</button>\n      <button @click=\"shuffle\">shuffle</button>\n      <transition-group tag=\"ul\" name=\"fade\" class=\"container\">\n        <item v-for=\"item in items\"\n          class=\"item\"\n          :msg=\"item\"\n          :key=\"item\"\n          @rm=\"remove(item)\">\n        </item>\n      </transition-group>\n    </div>\n\n    <script>\n      var items = [1, 2, 3, 4, 5]\n      var id = items.length + 1\n\n      var vm = new Vue({\n        el: '#el',\n        data: {\n          items: items\n        },\n        components: {\n          item: {\n            props: ['msg'],\n            template: `<div>{{ msg }} <button @click=\"$emit('rm')\">x</button></div>`\n          }\n        },\n        methods: {\n          insert () {\n            var i = Math.round(Math.random() * this.items.length)\n            this.items.splice(i, 0, id++)\n          },\n          reset () {\n            this.items = [1, 2, 3, 4, 5]\n          },\n          shuffle () {\n            this.items = _.shuffle(this.items)\n          },\n          remove (item) {\n            var i = this.items.indexOf(item)\n            if (i > -1) {\n              this.items.splice(i, 1)\n            }\n          }\n        }\n      })\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/select2/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <title>Vue.js wrapper component example (jquery plugin: select2)</title>\n    <!-- Delete \".min\" for console warnings in development -->\n    <script src=\"../../dist/vue.min.js\"></script>\n    <script src=\"https://unpkg.com/jquery\"></script>\n    <script src=\"https://unpkg.com/select2@4.0.3\"></script>\n    <link href=\"https://unpkg.com/select2@4.0.3/dist/css/select2.min.css\" rel=\"stylesheet\">\n    <style>\n      html, body {\n        font: 13px/18px sans-serif;\n      }\n      select {\n        min-width: 300px;\n      }\n    </style>\n  </head>\n  <body>\n\n    <div id=\"el\">\n    </div>\n\n    <!-- using string template here to work around HTML <option> placement restriction -->\n    <script type=\"text/x-template\" id=\"demo-template\">\n      <div>\n        <p>Selected: {{ selected }}</p>\n        <select2 :options=\"options\" v-model=\"selected\">\n          <option disabled value=\"0\">Select one</option>\n        </select2>\n      </div>\n    </script>\n\n    <script type=\"text/x-template\" id=\"select2-template\">\n      <select>\n        <slot></slot>\n      </select>\n    </script>\n\n    <script>\n    Vue.component('select2', {\n      props: ['options', 'value'],\n      template: '#select2-template',\n      mounted: function () {\n        var vm = this\n        $(this.$el)\n          .val(this.value)\n          // init select2\n          .select2({ data: this.options })\n          // emit event on change.\n          .on('change', function () {\n            vm.$emit('input', this.value)\n          })\n      },\n      watch: {\n        value: function (value) {\n          // update value\n          $(this.$el).val(value).trigger('change')\n        },\n        options: function (options) {\n          // update options\n          $(this.$el).select2({ data: options })\n        }\n      },\n      destroyed: function () {\n        $(this.$el).off().select2('destroy')\n      }\n    })\n\n    var vm = new Vue({\n      el: '#el',\n      template: '#demo-template',\n      data: {\n        selected: 0,\n        options: [\n          { id: 1, text: 'Hello' },\n          { id: 2, text: 'World' }\n        ]\n      }\n    })\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/svg/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <title>Vue.js SVG graph example</title>\n    <link rel=\"stylesheet\" href=\"style.css\">\n    <!-- Delete \".min\" for console warnings in development -->\n    <script src=\"../../dist/vue.min.js\"></script>\n    <script src=\"https://unpkg.com/marky/dist/marky.min.js\"></script>\n  </head>\n  <body>\n\n    <!-- template for the polygraph component. -->\n    <script type=\"text/x-template\" id=\"polygraph-template\">\n      <g>\n        <polygon :points=\"points\"></polygon>\n        <circle cx=\"100\" cy=\"100\" r=\"80\"></circle>\n        <axis-label\n          v-for=\"(stat, index) in stats\"\n          :stat=\"stat\"\n          :index=\"index\"\n          :total=\"stats.length\">\n        </axis-label>\n      </g>\n    </script>\n\n    <!-- template for the axis label component. -->\n    <script type=\"text/x-template\" id=\"axis-label-template\">\n      <text :x=\"point.x\" :y=\"point.y\">{{stat.label}}</text>\n    </script>\n\n    <!-- demo root element -->\n    <div id=\"demo\">\n      <!-- Use the component -->\n      <svg width=\"200\" height=\"200\">\n        <polygraph :stats=\"stats\"></polygraph>\n      </svg>\n      <!-- controls -->\n      <div v-for=\"stat in stats\">\n        <label>{{stat.label}}</label>\n        <input type=\"range\" v-model=\"stat.value\" min=\"0\" max=\"100\">\n        <span>{{stat.value}}</span>\n        <button @click=\"remove(stat)\" class=\"remove\">X</button>\n      </div>\n      <form id=\"add\">\n        <input name=\"newlabel\" v-model=\"newLabel\">\n        <button @click=\"add\">Add a Stat</button>\n      </form>\n      <pre id=\"raw\">{{ stats }}</pre>\n    </div>\n\n    <p style=\"font-size:12px\">* input[type=\"range\"] requires IE10 or above.</p>\n\n    <script src=\"svg.js\"></script>\n\n  </body>\n</html>\n"
  },
  {
    "path": "examples/svg/style.css",
    "content": "body {\n    font-family: Helvetica Neue, Arial, sans-serif;\n}\n\npolygon {\n    fill: #42b983;\n    opacity: .75;\n}\n\ncircle {\n    fill: transparent;\n    stroke: #999;\n}\n\ntext {\n    font-family: Helvetica Neue, Arial, sans-serif;\n    font-size: 10px;\n    fill: #666;\n}\n\nlabel {\n    display: inline-block;\n    margin-left: 10px;\n    width: 20px;\n}\n\n#raw {\n    position: absolute;\n    top: 0;\n    left: 300px;\n}"
  },
  {
    "path": "examples/svg/svg.js",
    "content": "// The raw data to observe\nvar stats = [\n  { label: 'A', value: 100 },\n  { label: 'B', value: 100 },\n  { label: 'C', value: 100 },\n  { label: 'D', value: 100 },\n  { label: 'E', value: 100 },\n  { label: 'F', value: 100 }\n]\n\n// A resusable polygon graph component\nVue.component('polygraph', {\n  props: ['stats'],\n  template: '#polygraph-template',\n  computed: {\n    // a computed property for the polygon's points\n    points: function () {\n      var total = this.stats.length\n      return this.stats.map(function (stat, i) {\n        var point = valueToPoint(stat.value, i, total)\n        return point.x + ',' + point.y\n      }).join(' ')\n    }\n  },\n  components: {\n    // a sub component for the labels\n    'axis-label': {\n      props: {\n        stat: Object,\n        index: Number,\n        total: Number\n      },\n      template: '#axis-label-template',\n      computed: {\n        point: function () {\n          return valueToPoint(\n            +this.stat.value + 10,\n            this.index,\n            this.total\n          )\n        }\n      }\n    }\n  }\n})\n\n// math helper...\nfunction valueToPoint (value, index, total) {\n  var x     = 0\n  var y     = -value * 0.8\n  var angle = Math.PI * 2 / total * index\n  var cos   = Math.cos(angle)\n  var sin   = Math.sin(angle)\n  var tx    = x * cos - y * sin + 100\n  var ty    = x * sin + y * cos + 100\n  return {\n    x: tx,\n    y: ty\n  }\n}\n\n// bootstrap the demo\nnew Vue({\n  el: '#demo',\n  data: {\n    newLabel: '',\n    stats: stats\n  },\n  methods: {\n    add: function (e) {\n      e.preventDefault()\n      if (!this.newLabel) return\n      this.stats.push({\n        label: this.newLabel,\n        value: 100\n      })\n      this.newLabel = ''\n    },\n    remove: function (stat) {\n      if (this.stats.length > 3) {\n        this.stats.splice(this.stats.indexOf(stat), 1)\n      } else {\n        alert('Can\\'t delete more!')\n      }\n    }\n  }\n})\n"
  },
  {
    "path": "examples/todomvc/app.js",
    "content": "// Full spec-compliant TodoMVC with localStorage persistence\n// and hash-based routing in ~150 lines.\n\n// localStorage persistence\nvar STORAGE_KEY = 'todos-vuejs-2.0'\nvar todoStorage = {\n  fetch: function () {\n    var todos = JSON.parse(localStorage.getItem(STORAGE_KEY) || '[]')\n    todos.forEach(function (todo, index) {\n      todo.id = index\n    })\n    todoStorage.uid = todos.length\n    return todos\n  },\n  save: function (todos) {\n    localStorage.setItem(STORAGE_KEY, JSON.stringify(todos))\n  }\n}\n\n// visibility filters\nvar filters = {\n  all: function (todos) {\n    return todos\n  },\n  active: function (todos) {\n    return todos.filter(function (todo) {\n      return !todo.completed\n    })\n  },\n  completed: function (todos) {\n    return todos.filter(function (todo) {\n      return todo.completed\n    })\n  }\n}\n\n// app Vue instance\nvar app = new Vue({\n  // app initial state\n  data: {\n    todos: todoStorage.fetch(),\n    newTodo: '',\n    editedTodo: null,\n    visibility: 'all'\n  },\n\n  // watch todos change for localStorage persistence\n  watch: {\n    todos: {\n      handler: function (todos) {\n        todoStorage.save(todos)\n      },\n      deep: true\n    }\n  },\n\n  // computed properties\n  // https://vuejs.org/guide/computed.html\n  computed: {\n    filteredTodos: function () {\n      return filters[this.visibility](this.todos)\n    },\n    remaining: function () {\n      return filters.active(this.todos).length\n    },\n    allDone: {\n      get: function () {\n        return this.remaining === 0\n      },\n      set: function (value) {\n        this.todos.forEach(function (todo) {\n          todo.completed = value\n        })\n      }\n    }\n  },\n\n  filters: {\n    pluralize: function (n) {\n      return n === 1 ? 'item' : 'items'\n    }\n  },\n\n  // methods that implement data logic.\n  // note there's no DOM manipulation here at all.\n  methods: {\n    addTodo: function () {\n      var value = this.newTodo && this.newTodo.trim()\n      if (!value) {\n        return\n      }\n      this.todos.push({\n        id: todoStorage.uid++,\n        title: value,\n        completed: false\n      })\n      this.newTodo = ''\n    },\n\n    removeTodo: function (todo) {\n      this.todos.splice(this.todos.indexOf(todo), 1)\n    },\n\n    editTodo: function (todo) {\n      this.beforeEditCache = todo.title\n      this.editedTodo = todo\n    },\n\n    doneEdit: function (todo) {\n      if (!this.editedTodo) {\n        return\n      }\n      this.editedTodo = null\n      todo.title = todo.title.trim()\n      if (!todo.title) {\n        this.removeTodo(todo)\n      }\n    },\n\n    cancelEdit: function (todo) {\n      this.editedTodo = null\n      todo.title = this.beforeEditCache\n    },\n\n    removeCompleted: function () {\n      this.todos = filters.active(this.todos)\n    }\n  },\n\n  // a custom directive to wait for the DOM to be updated\n  // before focusing on the input field.\n  // https://vuejs.org/guide/custom-directive.html\n  directives: {\n    'todo-focus': function (el, binding) {\n      if (binding.value) {\n        el.focus()\n      }\n    }\n  }\n})\n\n// handle routing\nfunction onHashChange () {\n  var visibility = window.location.hash.replace(/#\\/?/, '')\n  if (filters[visibility]) {\n    app.visibility = visibility\n  } else {\n    window.location.hash = ''\n    app.visibility = 'all'\n  }\n}\n\nwindow.addEventListener('hashchange', onHashChange)\nonHashChange()\n\n// mount\napp.$mount('.todoapp')\n"
  },
  {
    "path": "examples/todomvc/index.html",
    "content": "<!doctype html>\n<html data-framework=\"vue\">\n  <head>\n    <meta charset=\"utf-8\">\n    <title>Vue.js • TodoMVC</title>\n    <link rel=\"stylesheet\" href=\"https://unpkg.com/todomvc-app-css@2.0.4/index.css\">\n    <script src=\"https://unpkg.com/director@1.2.8/build/director.js\"></script>\n    <style>[v-cloak] { display: none; }</style>\n  </head>\n  <body>\n    <section class=\"todoapp\">\n      <header class=\"header\">\n        <h1>todos</h1>\n        <input class=\"new-todo\"\n          autofocus autocomplete=\"off\"\n          placeholder=\"What needs to be done?\"\n          v-model=\"newTodo\"\n          @keyup.enter=\"addTodo\">\n      </header>\n      <section class=\"main\" v-show=\"todos.length\" v-cloak>\n        <input class=\"toggle-all\" type=\"checkbox\" v-model=\"allDone\">\n        <ul class=\"todo-list\">\n          <li v-for=\"todo in filteredTodos\"\n            class=\"todo\"\n            :key=\"todo.id\"\n            :class=\"{ completed: todo.completed, editing: todo == editedTodo }\">\n            <div class=\"view\">\n              <input class=\"toggle\" type=\"checkbox\" v-model=\"todo.completed\">\n              <label @dblclick=\"editTodo(todo)\">{{ todo.title }}</label>\n              <button class=\"destroy\" @click=\"removeTodo(todo)\"></button>\n            </div>\n            <input class=\"edit\" type=\"text\"\n              v-model=\"todo.title\"\n              v-todo-focus=\"todo == editedTodo\"\n              @blur=\"doneEdit(todo)\"\n              @keyup.enter=\"doneEdit(todo)\"\n              @keyup.esc=\"cancelEdit(todo)\">\n          </li>\n        </ul>\n      </section>\n      <footer class=\"footer\" v-show=\"todos.length\" v-cloak>\n        <span class=\"todo-count\">\n          <strong>{{ remaining }}</strong> {{ remaining | pluralize }} left\n        </span>\n        <ul class=\"filters\">\n          <li><a href=\"#/all\" :class=\"{ selected: visibility == 'all' }\">All</a></li>\n          <li><a href=\"#/active\" :class=\"{ selected: visibility == 'active' }\">Active</a></li>\n          <li><a href=\"#/completed\" :class=\"{ selected: visibility == 'completed' }\">Completed</a></li>\n        </ul>\n        <button class=\"clear-completed\" @click=\"removeCompleted\" v-show=\"todos.length > remaining\">\n          Clear completed\n        </button>\n      </footer>\n    </section>\n    <footer class=\"info\">\n      <p>Double-click to edit a todo</p>\n      <p>Written by <a href=\"http://evanyou.me\">Evan You</a></p>\n      <p>Part of <a href=\"http://todomvc.com\">TodoMVC</a></p>\n    </footer>\n\n    <script>\n    // for testing\n    if (navigator.userAgent.indexOf('PhantomJS') > -1) localStorage.clear()\n    </script>\n    <!-- Delete \".min\" for console warnings in development -->\n    <script src=\"../../dist/vue.min.js\"></script>\n    <script src=\"app.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/todomvc/readme.md",
    "content": "# Vue.js TodoMVC Example\n\n> Vue.js is a library for building interactive web interfaces. \nIt provides data-driven, nestable view components with a simple and flexible API.\n\n> _[Vue.js - vuejs.org](https://vuejs.org)_\n\n## Learning Vue.js\nThe [Vue.js website](https://vuejs.org/) is a great resource to get started.\n\nHere are some links you may find helpful:\n\n* [Official Guide](https://vuejs.org/guide/)\n* [API Reference](https://vuejs.org/api/)\n* [Examples](https://vuejs.org/examples/)\n\nGet help from other Vue.js users:\n\n* [Vue.js official forum](http://forum.vuejs.org)\n* [Vue.js on Twitter](https://twitter.com/vuejs)\n* [Vue.js on Gitter](https://gitter.im/vuejs/vue)\n\n_If you have other helpful links to share, or find any of the links above no longer work, please [let us know](https://github.com/tastejs/todomvc/issues)._\n\n## Credit\n\nThis TodoMVC application was created by [Evan You](http://evanyou.me).\n"
  },
  {
    "path": "examples/tree/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <title>Vue.js tree view example</title>\n    <style>\n      body {\n        font-family: Menlo, Consolas, monospace;\n        color: #444;\n      }\n      .item {\n        cursor: pointer;\n      }\n      .bold {\n        font-weight: bold;\n      }\n      ul {\n        padding-left: 1em;\n        line-height: 1.5em;\n        list-style-type: dot;\n      }\n    </style>\n    <!-- Delete \".min\" for console warnings in development -->\n    <script src=\"../../dist/vue.min.js\"></script>\n  </head>\n  <body>\n\n    <!-- item template -->\n    <script type=\"text/x-template\" id=\"item-template\">\n      <li>\n        <div\n          :class=\"{bold: isFolder}\"\n          @click=\"toggle\"\n          @dblclick=\"changeType\">\n          {{model.name}}\n          <span v-if=\"isFolder\">[{{open ? '-' : '+'}}]</span>\n        </div>\n        <ul v-show=\"open\" v-if=\"isFolder\">\n          <item\n            class=\"item\"\n            v-for=\"model in model.children\"\n            :model=\"model\">\n          </item>\n          <li class=\"add\" @click=\"addChild\">+</li>\n        </ul>\n      </li>\n    </script>\n\n    <p>(You can double click on an item to turn it into a folder.)</p>\n\n    <!-- the demo root element -->\n    <ul id=\"demo\">\n      <item\n        class=\"item\"\n        :model=\"treeData\">\n      </item>\n    </ul>\n\n    <!-- demo code -->\n    <script src=\"tree.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/tree/tree.js",
    "content": "// demo data\nvar data = {\n  name: 'My Tree',\n  children: [\n    { name: 'hello' },\n    { name: 'wat' },\n    {\n      name: 'child folder',\n      children: [\n        {\n          name: 'child folder',\n          children: [\n            { name: 'hello' },\n            { name: 'wat' }\n          ]\n        },\n        { name: 'hello' },\n        { name: 'wat' },\n        {\n          name: 'child folder',\n          children: [\n            { name: 'hello' },\n            { name: 'wat' }\n          ]\n        }\n      ]\n    }\n  ]\n}\n\n// define the item component\nVue.component('item', {\n  template: '#item-template',\n  props: {\n    model: Object\n  },\n  data: function () {\n    return {\n      open: false\n    }\n  },\n  computed: {\n    isFolder: function () {\n      return this.model.children &&\n        this.model.children.length\n    }\n  },\n  methods: {\n    toggle: function () {\n      if (this.isFolder) {\n        this.open = !this.open\n      }\n    },\n    changeType: function () {\n      if (!this.isFolder) {\n        Vue.set(this.model, 'children', [])\n        this.addChild()\n        this.open = true\n      }\n    },\n    addChild: function () {\n      this.model.children.push({\n        name: 'new stuff'\n      })\n    }\n  }\n})\n\n// boot up the demo\nvar demo = new Vue({\n  el: '#demo',\n  data: {\n    treeData: data\n  }\n})\n"
  },
  {
    "path": "flow/compiler.js",
    "content": "declare type CompilerOptions = {\n  warn?: Function; // allow customizing warning in different environments; e.g. node\n  expectHTML?: boolean; // only false for non-web builds\n  modules?: Array<ModuleOptions>; // platform specific modules; e.g. style; class\n  staticKeys?: string; // a list of AST properties to be considered static; for optimization\n  directives?: { [key: string]: Function }; // platform specific directives\n  isUnaryTag?: (tag: string) => ?boolean; // check if a tag is unary for the platform\n  canBeLeftOpenTag?: (tag: string) => ?boolean; // check if a tag can be left opened\n  isReservedTag?: (tag: string) => ?boolean; // check if a tag is a native for the platform\n  mustUseProp?: (tag: string, type: ?string, name: string) => boolean; // check if an attribute should be bound as a property\n  isPreTag?: (attr: string) => ?boolean; // check if a tag needs to preserve whitespace\n  getTagNamespace?: (tag: string) => ?string; // check the namespace for a tag\n  transforms?: Array<Function>; // a list of transforms on parsed AST before codegen\n  preserveWhitespace?: boolean;\n  isFromDOM?: boolean;\n  shouldDecodeTags?: boolean;\n  shouldDecodeNewlines?: boolean;\n\n  // for ssr optimization compiler\n  scopeId?: string;\n\n  // runtime user-configurable\n  delimiters?: [string, string]; // template delimiters\n\n  // allow user kept comments\n  comments?: boolean\n};\n\ndeclare type CompiledResult = {\n  ast: ?ASTElement;\n  render: string;\n  staticRenderFns: Array<string>;\n  stringRenderFns?: Array<string>;\n  errors?: Array<string>;\n  tips?: Array<string>;\n};\n\ndeclare type ModuleOptions = {\n  preTransformNode: (el: ASTElement) => void;\n  transformNode: (el: ASTElement) => void; // transform an element's AST node\n  postTransformNode: (el: ASTElement) => void;\n  genData: (el: ASTElement) => string; // generate extra data string for an element\n  transformCode?: (el: ASTElement, code: string) => string; // further transform generated code for an element\n  staticKeys?: Array<string>; // AST properties to be considered static\n};\n\ndeclare type ASTModifiers = { [key: string]: boolean };\ndeclare type ASTIfConditions = Array<{ exp: ?string; block: ASTElement }>;\n\ndeclare type ASTElementHandler = {\n  value: string;\n  modifiers: ?ASTModifiers;\n};\n\ndeclare type ASTElementHandlers = {\n  [key: string]: ASTElementHandler | Array<ASTElementHandler>;\n};\n\ndeclare type ASTDirective = {\n  name: string;\n  rawName: string;\n  value: string;\n  arg: ?string;\n  modifiers: ?ASTModifiers;\n};\n\ndeclare type ASTNode = ASTElement | ASTText | ASTExpression;\n\ndeclare type ASTElement = {\n  type: 1;\n  tag: string;\n  attrsList: Array<{ name: string; value: string }>;\n  attrsMap: { [key: string]: string | null };\n  parent: ASTElement | void;\n  children: Array<ASTNode>;\n\n  static?: boolean;\n  staticRoot?: boolean;\n  staticInFor?: boolean;\n  staticProcessed?: boolean;\n  hasBindings?: boolean;\n\n  text?: string;\n  attrs?: Array<{ name: string; value: string }>;\n  props?: Array<{ name: string; value: string }>;\n  plain?: boolean;\n  pre?: true;\n  ns?: string;\n\n  component?: string;\n  inlineTemplate?: true;\n  transitionMode?: string | null;\n  slotName?: ?string;\n  slotTarget?: ?string;\n  slotScope?: ?string;\n  scopedSlots?: { [name: string]: ASTElement };\n\n  ref?: string;\n  refInFor?: boolean;\n\n  if?: string;\n  ifProcessed?: boolean;\n  elseif?: string;\n  else?: true;\n  ifConditions?: ASTIfConditions;\n\n  for?: string;\n  forProcessed?: boolean;\n  key?: string;\n  alias?: string;\n  iterator1?: string;\n  iterator2?: string;\n\n  staticClass?: string;\n  classBinding?: string;\n  staticStyle?: string;\n  styleBinding?: string;\n  events?: ASTElementHandlers;\n  nativeEvents?: ASTElementHandlers;\n\n  transition?: string | true;\n  transitionOnAppear?: boolean;\n\n  model?: {\n    value: string;\n    callback: string;\n    expression: string;\n  };\n\n  directives?: Array<ASTDirective>;\n\n  forbidden?: true;\n  once?: true;\n  onceProcessed?: boolean;\n  wrapData?: (code: string) => string;\n  wrapListeners?: (code: string) => string;\n\n  // 2.4 ssr optimization\n  ssrOptimizability?: number;\n\n  // weex specific\n  appendAsTree?: boolean;\n};\n\ndeclare type ASTExpression = {\n  type: 2;\n  expression: string;\n  text: string;\n  static?: boolean;\n  // 2.4 ssr optimization\n  ssrOptimizability?: number;\n};\n\ndeclare type ASTText = {\n  type: 3;\n  text: string;\n  static?: boolean;\n  isComment?: boolean;\n  // 2.4 ssr optimization\n  ssrOptimizability?: number;\n};\n\n// SFC-parser related declarations\n\n// an object format describing a single-file component.\ndeclare type SFCDescriptor = {\n  template: ?SFCBlock;\n  script: ?SFCBlock;\n  styles: Array<SFCBlock>;\n  customBlocks: Array<SFCCustomBlock>;\n}\n\ndeclare type SFCCustomBlock = {\n  type: string;\n  content: string;\n  start?: number;\n  end?: number;\n  src?: string;\n  attrs: {[attribute:string]: string};\n};\n\ndeclare type SFCBlock = {\n  type: string;\n  content: string;\n  start?: number;\n  end?: number;\n  lang?: string;\n  src?: string;\n  scoped?: boolean;\n  module?: string | boolean;\n};\n"
  },
  {
    "path": "flow/component.js",
    "content": "import type { Config } from '../src/core/config'\nimport type VNode from '../src/core/vdom/vnode'\nimport type Watcher from '../src/core/observer/watcher'\n\ndeclare interface Component {\n  // constructor information\n  static cid: number;\n  static options: Object;\n  // extend\n  static extend: (options: Object) => Function;\n  static superOptions: Object;\n  static extendOptions: Object;\n  static sealedOptions: Object;\n  static super: Class<Component>;\n  // assets\n  static directive: (id: string, def?: Function | Object) => Function | Object | void;\n  static component: (id: string, def?: Class<Component> | Object) => Class<Component>;\n  static filter: (id: string, def?: Function) => Function | void;\n\n  // public properties\n  $el: any; // so that we can attach __vue__ to it\n  $data: Object;\n  $props: Object;\n  $options: ComponentOptions;\n  $parent: Component | void;\n  $root: Component;\n  $children: Array<Component>;\n  $refs: { [key: string]: Component | Element | Array<Component | Element> | void };\n  $slots: { [key: string]: Array<VNode> };\n  $scopedSlots: { [key: string]: () => VNodeChildren };\n  $vnode: VNode; // the placeholder node for the component in parent's render tree\n  $attrs: ?{ [key: string] : string };\n  $listeners: ?{ [key: string]: Function | Array<Function> };\n  $isServer: boolean;\n\n  // public methods\n  $mount: (el?: Element | string, hydrating?: boolean) => Component;\n  $forceUpdate: () => void;\n  $destroy: () => void;\n  $set: <T>(target: Object | Array<T>, key: string | number, val: T) => T;\n  $delete: <T>(target: Object | Array<T>, key: string | number) => void;\n  $watch: (expOrFn: string | Function, cb: Function, options?: Object) => Function;\n  $on: (event: string | Array<string>, fn: Function) => Component;\n  $once: (event: string, fn: Function) => Component;\n  $off: (event?: string | Array<string>, fn?: Function) => Component;\n  $emit: (event: string, ...args: Array<mixed>) => Component;\n  $nextTick: (fn: Function) => void | Promise<*>;\n  $createElement: (tag?: string | Component, data?: Object, children?: VNodeChildren) => VNode;\n\n  // private properties\n  _uid: number;\n  _name: string; // this only exists in dev mode\n  _isVue: true;\n  _self: Component;\n  _renderProxy: Component;\n  _renderContext: ?Component;\n  _watcher: Watcher;\n  _watchers: Array<Watcher>;\n  _computedWatchers: { [key: string]: Watcher };\n  _data: Object;\n  _props: Object;\n  _events: Object;\n  _inactive: boolean | null;\n  _directInactive: boolean;\n  _isMounted: boolean;\n  _isDestroyed: boolean;\n  _isBeingDestroyed: boolean;\n  _vnode: ?VNode; // self root node\n  _staticTrees: ?Array<VNode>;\n  _hasHookEvent: boolean;\n  _provided: ?Object;\n\n  // private methods\n\n  // lifecycle\n  _init: Function;\n  _mount: (el?: Element | void, hydrating?: boolean) => Component;\n  _update: (vnode: VNode, hydrating?: boolean) => void;\n\n  // rendering\n  _render: () => VNode;\n\n  __patch__: (\n    a: Element | VNode | void,\n    b: VNode,\n    hydrating?: boolean,\n    removeOnly?: boolean,\n    parentElm?: any,\n    refElm?: any\n  ) => any;\n\n  // createElement\n\n  // _c is internal that accepts `normalizationType` optimization hint\n  _c: (\n    vnode?: VNode,\n    data?: VNodeData,\n    children?: VNodeChildren,\n    normalizationType?: number\n  ) => VNode | void;\n\n  // renderStatic\n  _m: (index: number, isInFor?: boolean) => VNode | VNodeChildren;\n  // markOnce\n  _o: (vnode: VNode | Array<VNode>, index: number, key: string) => VNode | VNodeChildren;\n  // toString\n  _s: (value: mixed) => string;\n  // text to VNode\n  _v: (value: string | number) => VNode;\n  // toNumber\n  _n: (value: string) => number | string;\n  // empty vnode\n  _e: () => VNode;\n  // loose equal\n  _q: (a: mixed, b: mixed) => boolean;\n  // loose indexOf\n  _i: (arr: Array<mixed>, val: mixed) => number;\n  // resolveFilter\n  _f: (id: string) => Function;\n  // renderList\n  _l: (val: mixed, render: Function) => ?Array<VNode>;\n  // renderSlot\n  _t: (name: string, fallback: ?Array<VNode>, props: ?Object) => ?Array<VNode>;\n  // apply v-bind object\n  _b: (data: any, tag: string, value: any, asProp: boolean, isSync?: boolean) => VNodeData;\n  // apply v-on object\n  _g: (data: any, value: any) => VNodeData;\n  // check custom keyCode\n  _k: (eventKeyCode: number, key: string, builtInAlias: number | Array<number> | void) => boolean;\n  // resolve scoped slots\n  _u: (scopedSlots: ScopedSlotsData, res?: Object) => { [key: string]: Function };\n\n  // SSR specific\n  _ssrNode: Function;\n  _ssrList: Function;\n  _ssrEscape: Function;\n  _ssrAttr: Function;\n  _ssrAttrs: Function;\n  _ssrDOMProps: Function;\n  _ssrClass: Function;\n  _ssrStyle: Function;\n\n  // allow dynamic method registration\n  [key: string]: any\n};\n"
  },
  {
    "path": "flow/global-api.js",
    "content": "declare interface GlobalAPI {\n  cid: number;\n  options: Object;\n  config: Config;\n  util: Object;\n\n  extend: (options: Object) => Function;\n  set: <T>(target: Object | Array<T>, key: string | number, value: T) => T;\n  delete: <T>(target: Object| Array<T>, key: string | number) => void;\n  nextTick: (fn: Function, context?: Object) => void | Promise<*>;\n  use: (plugin: Function | Object) => void;\n  mixin: (mixin: Object) => void;\n  compile: (template: string) => { render: Function, staticRenderFns: Array<Function> };\n\n  directive: (id: string, def?: Function | Object) => Function | Object | void;\n  component: (id: string, def?: Class<Component> | Object) => Class<Component>;\n  filter: (id: string, def?: Function) => Function | void;\n\n  // allow dynamic method registration\n  [key: string]: any\n};\n"
  },
  {
    "path": "flow/modules.js",
    "content": "declare module 'he' {\n  declare function escape(html: string): string;\n  declare function decode(html: string): string;\n}\n\ndeclare module 'source-map' {\n  declare class SourceMapGenerator {\n    setSourceContent(filename: string, content: string): void;\n    addMapping(mapping: Object): void;\n    toString(): string;\n  }\n  declare class SourceMapConsumer {\n    constructor (map: Object): void;\n    originalPositionFor(position: { line: number; column: number; }): {\n      source: ?string;\n      line: ?number;\n      column: ?number;\n    };\n  }\n}\n\ndeclare module 'lru-cache' {\n  declare var exports: {\n    (): any\n  }\n}\n\ndeclare module 'de-indent' {\n  declare var exports: {\n    (input: string): string\n  }\n}\n\ndeclare module 'serialize-javascript' {\n  declare var exports: {\n    (input: string, options: { isJSON: boolean }): string\n  }\n}\n\ndeclare module 'lodash.template' {\n  declare var exports: {\n    (input: string, options: { interpolate: RegExp, escape: RegExp }): Function\n  }\n}\n"
  },
  {
    "path": "flow/options.js",
    "content": "declare type InternalComponentOptions = {\n  _isComponent: true;\n  parent: Component;\n  propsData: ?Object;\n  _parentVnode: VNode;\n  _parentListeners: ?Object;\n  _renderChildren: ?Array<VNode>;\n  _componentTag: ?string;\n  _parentElm: ?Node;\n  _refElm: ?Node;\n  render?: Function;\n  staticRenderFns?: Array<Function>\n};\n\ndeclare type ComponentOptions = {\n  // data\n  data: Object | Function | void;\n  props?: { [key: string]: PropOptions };\n  propsData?: ?Object;\n  computed?: {\n    [key: string]: Function | {\n      get?: Function;\n      set?: Function;\n      cache?: boolean\n    }\n  };\n  methods?: { [key: string]: Function };\n  watch?: { [key: string]: Function | string };\n\n  // DOM\n  el?: string | Element;\n  template?: string;\n  render: (h: () => VNode) => VNode;\n  renderError?: (h: () => VNode, err: Error) => VNode;\n  staticRenderFns?: Array<() => VNode>;\n\n  // lifecycle\n  beforeCreate?: Function;\n  created?: Function;\n  beforeMount?: Function;\n  mounted?: Function;\n  beforeUpdate?: Function;\n  updated?: Function;\n  activated?: Function;\n  deactivated?: Function;\n  beforeDestroy?: Function;\n  destroyed?: Function;\n\n  // assets\n  directives?: { [key: string]: Object };\n  components?: { [key: string]: Class<Component> };\n  transitions?: { [key: string]: Object };\n  filters?: { [key: string]: Function };\n\n  // context\n  provide?: { [key: string | Symbol]: any } | () => { [key: string | Symbol]: any };\n  inject?: { [key: string]: string | Symbol } | Array<string>;\n\n  // component v-model customization\n  model?: {\n    prop?: string;\n    event?: string;\n  };\n\n  // misc\n  parent?: Component;\n  mixins?: Array<Object>;\n  name?: string;\n  extends?: Class<Component> | Object;\n  delimiters?: [string, string];\n  comments?: boolean;\n  inheritAttrs?: boolean;\n\n  // private\n  _isComponent?: true;\n  _propKeys?: Array<string>;\n  _parentVnode?: VNode;\n  _parentListeners?: ?Object;\n  _renderChildren?: ?Array<VNode>;\n  _componentTag: ?string;\n  _scopeId: ?string;\n  _base: Class<Component>;\n  _parentElm: ?Node;\n  _refElm: ?Node;\n};\n\ndeclare type PropOptions = {\n  type: Function | Array<Function> | null;\n  default: any;\n  required: ?boolean;\n  validator: ?Function;\n}\n"
  },
  {
    "path": "flow/ssr.js",
    "content": "declare type ComponentWithCacheContext = {\n  type: 'ComponentWithCache';\n  bufferIndex: number;\n  buffer: Array<string>;\n  key: string;\n};\n\ndeclare type ElementContext = {\n  type: 'Element';\n  children: Array<VNode>;\n  rendered: number;\n  endTag: string;\n  total: number;\n};\n\ndeclare type ComponentContext = {\n  type: 'Component';\n  prevActive: Component;\n};\n\ndeclare type RenderState = ComponentContext | ComponentWithCacheContext | ElementContext;\n"
  },
  {
    "path": "flow/vnode.js",
    "content": "declare type VNodeChildren = Array<?VNode | string | VNodeChildren> | string;\n\ndeclare type VNodeComponentOptions = {\n  Ctor: Class<Component>;\n  propsData: ?Object;\n  listeners: ?Object;\n  children: ?Array<VNode>;\n  tag?: string;\n};\n\ndeclare type MountedComponentVNode = {\n  context: Component;\n  componentOptions: VNodeComponentOptions;\n  componentInstance: Component;\n  parent: VNode;\n  data: VNodeData;\n};\n\n// interface for vnodes in update modules\ndeclare type VNodeWithData = {\n  tag: string;\n  data: VNodeData;\n  children: ?Array<VNode>;\n  text: void;\n  elm: any;\n  ns: string | void;\n  context: Component;\n  key: string | number | void;\n  parent?: VNodeWithData;\n  componentOptions?: VNodeComponentOptions;\n  componentInstance?: Component;\n  isRootInsert: boolean;\n};\n\ndeclare interface VNodeData {\n  key?: string | number;\n  slot?: string;\n  ref?: string;\n  is?: string;\n  pre?: boolean;\n  tag?: string;\n  staticClass?: string;\n  class?: any;\n  staticStyle?: { [key: string]: any };\n  style?: Array<Object> | Object;\n  normalizedStyle?: Object;\n  props?: { [key: string]: any };\n  attrs?: { [key: string]: string };\n  domProps?: { [key: string]: any };\n  hook?: { [key: string]: Function };\n  on?: ?{ [key: string]: Function | Array<Function> };\n  nativeOn?: { [key: string]: Function | Array<Function> };\n  transition?: Object;\n  show?: boolean; // marker for v-show\n  inlineTemplate?: {\n    render: Function;\n    staticRenderFns: Array<Function>;\n  };\n  directives?: Array<VNodeDirective>;\n  keepAlive?: boolean;\n  scopedSlots?: { [key: string]: Function };\n  model?: {\n    value: any;\n    callback: Function;\n  };\n};\n\ndeclare type VNodeDirective = {\n  name: string;\n  rawName: string;\n  value?: any;\n  oldValue?: any;\n  arg?: string;\n  modifiers?: ASTModifiers;\n  def?: Object;\n};\n\ndeclare type ScopedSlotsData = Array<{ key: string, fn: Function } | ScopedSlotsData>;\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"vue\",\n  \"version\": \"2.4.1\",\n  \"description\": \"Vue.js in mini program\",\n  \"main\": \"dist/vue.runtime.common.js\",\n  \"module\": \"dist/vue.runtime.esm.js\",\n  \"unpkg\": \"dist/vue.js\",\n  \"typings\": \"types/index.d.ts\",\n  \"files\": [\n    \"dist/*.js\",\n    \"types/*.d.ts\"\n  ],\n  \"scripts\": {\n    \"dev\": \"rollup -w -c build/config.js --environment TARGET:web-full-dev\",\n    \"dev:cjs\": \"rollup -w -c build/config.js --environment TARGET:web-runtime-cjs\",\n    \"dev:esm\": \"rollup -w -c build/config.js --environment TARGET:web-runtime-esm\",\n    \"dev:test\": \"karma start test/unit/karma.dev.config.js\",\n    \"dev:ssr\": \"rollup -w -c build/config.js --environment TARGET:web-server-renderer\",\n    \"dev:compiler\": \"rollup -w -c build/config.js --environment TARGET:web-compiler \",\n    \"dev:weex\": \"rollup -w -c build/config.js --environment TARGET:weex-framework \",\n    \"dev:weex:compiler\": \"rollup -w -c build/config.js --environment TARGET:weex-compiler \",\n    \"dev:mpvue\": \"rollup -w -c build/config.js --environment TARGET:mpvue \",\n    \"dev:mpvue:compiler\": \"rollup -w -c build/config.js --environment TARGET:mpvue-template-compiler \",\n    \"build\": \"node build/build.js\",\n    \"build:ssr\": \"npm run build -- vue.runtime.common.js,vue-server-renderer\",\n    \"build:weex\": \"npm run build -- weex-vue-framework,weex-template-compiler\",\n    \"build:mpvue\": \"npm run build -- mpvue,mpvue-template-compiler\",\n    \"test\": \"npm run lint && flow check && npm run test:types && npm run test:cover && npm run test:e2e -- --env phantomjs && npm run test:ssr && npm run test:weex && npm run test:mpvue\",\n    \"test:unit\": \"karma start test/unit/karma.unit.config.js\",\n    \"test:cover\": \"karma start test/unit/karma.cover.config.js\",\n    \"test:e2e\": \"npm run build -- vue.min.js && node test/e2e/runner.js\",\n    \"test:weex\": \"npm run build:weex && jasmine JASMINE_CONFIG_PATH=test/weex/jasmine.json\",\n    \"test:mpvue\": \"npm run build:mpvue && jasmine JASMINE_CONFIG_PATH=test/mp/jasmine.json\",\n    \"test:ssr\": \"npm run build:ssr && jasmine JASMINE_CONFIG_PATH=test/ssr/jasmine.json\",\n    \"test:sauce\": \"npm run sauce -- 0 && npm run sauce -- 1 && npm run sauce -- 2\",\n    \"test:types\": \"tsc -p ./types/test/tsconfig.json\",\n    \"lint\": \"eslint src build test\",\n    \"flow\": \"flow check\",\n    \"sauce\": \"karma start test/unit/karma.sauce.config.js\",\n    \"bench:ssr\": \"npm run build:ssr && node benchmarks/ssr/renderToString.js && node benchmarks/ssr/renderToStream.js\",\n    \"release\": \"bash build/release.sh\",\n    \"release:weex\": \"bash build/release-weex.sh\",\n    \"release:note\": \"node build/gen-release-note.js\",\n    \"setup\": \"node build/install-hooks.js\",\n    \"commit\": \"git-cz\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/Meituan-Dianping/mpvue.git\"\n  },\n  \"keywords\": [\n    \"vue\"\n  ],\n  \"author\": \"anchengjian\",\n  \"contributors\": [\n    {\n      \"name\": \"hucq\"\n    },\n    {\n      \"name\": \"aOrz\"\n    }\n  ],\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/Meituan-Dianping/mpvue/issues\"\n  },\n  \"homepage\": \"https://github.com/Meituan-Dianping/mpvue\",\n  \"devDependencies\": {\n    \"babel-core\": \"^6.25.0\",\n    \"babel-eslint\": \"^7.2.3\",\n    \"babel-helper-vue-jsx-merge-props\": \"^2.0.2\",\n    \"babel-loader\": \"^7.0.0\",\n    \"babel-plugin-istanbul\": \"^4.1.4\",\n    \"babel-plugin-syntax-dynamic-import\": \"^6.18.0\",\n    \"babel-plugin-syntax-jsx\": \"^6.18.0\",\n    \"babel-plugin-transform-vue-jsx\": \"^3.4.3\",\n    \"babel-preset-es2015\": \"^6.24.1\",\n    \"babel-preset-flow-vue\": \"^1.0.0\",\n    \"buble\": \"^0.15.2\",\n    \"chalk\": \"^1.1.3\",\n    \"chromedriver\": \"^2.30.1\",\n    \"codecov.io\": \"^0.1.6\",\n    \"commitizen\": \"^2.9.6\",\n    \"conventional-changelog\": \"^1.1.3\",\n    \"cross-spawn\": \"^5.1.0\",\n    \"cz-conventional-changelog\": \"^2.0.0\",\n    \"de-indent\": \"^1.0.2\",\n    \"es6-promise\": \"^4.1.0\",\n    \"eslint\": \"^3.0.0\",\n    \"eslint-loader\": \"^1.7.1\",\n    \"eslint-plugin-flowtype\": \"^2.34.0\",\n    \"eslint-plugin-jasmine\": \"^2.2.0\",\n    \"eslint-plugin-vue-libs\": \"^1.2.0\",\n    \"file-loader\": \"^0.11.2\",\n    \"flow-bin\": \"^0.48.0\",\n    \"hash-sum\": \"^1.0.2\",\n    \"he\": \"^1.1.1\",\n    \"http-server\": \"^0.10.0\",\n    \"jasmine\": \"^2.6.0\",\n    \"jasmine-core\": \"^2.6.3\",\n    \"karma\": \"^1.7.0\",\n    \"karma-chrome-launcher\": \"^2.1.1\",\n    \"karma-coverage\": \"^1.1.1\",\n    \"karma-firefox-launcher\": \"^1.0.1\",\n    \"karma-jasmine\": \"^1.1.0\",\n    \"karma-mocha-reporter\": \"^2.2.3\",\n    \"karma-phantomjs-launcher\": \"^1.0.4\",\n    \"karma-safari-launcher\": \"^1.0.0\",\n    \"karma-sauce-launcher\": \"^1.1.0\",\n    \"karma-sourcemap-loader\": \"^0.3.7\",\n    \"karma-webpack\": \"^2.0.3\",\n    \"lodash\": \"^4.17.4\",\n    \"lodash.template\": \"^4.4.0\",\n    \"lodash.uniq\": \"^4.5.0\",\n    \"lru-cache\": \"^4.1.1\",\n    \"nightwatch\": \"^0.9.16\",\n    \"nightwatch-helpers\": \"^1.2.0\",\n    \"phantomjs-prebuilt\": \"^2.1.14\",\n    \"prettier\": \"^1.11.1\",\n    \"resolve\": \"^1.3.3\",\n    \"rollup\": \"^0.45.1\",\n    \"rollup-plugin-alias\": \"^1.4.0\",\n    \"rollup-plugin-babel\": \"^2.7.1\",\n    \"rollup-plugin-buble\": \"^0.15.0\",\n    \"rollup-plugin-commonjs\": \"^8.0.2\",\n    \"rollup-plugin-flow-no-whitespace\": \"^1.0.0\",\n    \"rollup-plugin-node-resolve\": \"^3.0.0\",\n    \"rollup-plugin-replace\": \"^1.1.1\",\n    \"rollup-watch\": \"^4.0.0\",\n    \"selenium-server\": \"^2.53.1\",\n    \"serialize-javascript\": \"^1.3.0\",\n    \"shelljs\": \"^0.7.8\",\n    \"typescript\": \"^2.3.4\",\n    \"uglify-js\": \"^3.0.15\",\n    \"webpack\": \"^2.6.1\",\n    \"weex-js-runtime\": \"^0.20.5\",\n    \"weex-vdom-tester\": \"^0.2.0\"\n  },\n  \"config\": {\n    \"commitizen\": {\n      \"path\": \"./node_modules/cz-conventional-changelog\"\n    }\n  }\n}\n"
  },
  {
    "path": "packages/mpvue/README.md",
    "content": "# mpvue\n\n> This package is auto-generated. For pull requests please see [src/platforms/mp/entry-runtime.js](https://github.com/Meituan-Dianping/mpvue/blob/master/src/platforms/mp/entry-runtime.js).\n"
  },
  {
    "path": "packages/mpvue/index.js",
    "content": "// fix env\ntry {\n  if (!global) global = {};\n  global.process = global.process || {};\n  global.process.env = global.process.env || {};\n  global.App = global.App || App;\n  global.Page = global.Page || Page;\n  global.Component = global.Component || Component;\n  global.getApp = global.getApp || getApp;\n\n  if (typeof wx !== 'undefined') {\n    global.mpvue = wx;\n    global.mpvuePlatform = 'wx';\n  } else if (typeof swan !== 'undefined') {\n    global.mpvue = swan;\n    global.mpvuePlatform = 'swan';\n  }else if (typeof tt !== 'undefined') {\n    global.mpvue = tt;\n    global.mpvuePlatform = 'tt';\n  }else if (typeof my !== 'undefined') {\n    global.mpvue = my;\n    global.mpvuePlatform = 'my';\n  }\n} catch (e) {}\n\n(function (global, factory) {\n\ttypeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :\n\ttypeof define === 'function' && define.amd ? define(factory) :\n\t(global.Vue = factory());\n}(this, (function () { 'use strict';\n\n/*  */\n\n// these helpers produces better vm code in JS engines due to their\n// explicitness and function inlining\nfunction isUndef (v) {\n  return v === undefined || v === null\n}\n\nfunction isDef (v) {\n  return v !== undefined && v !== null\n}\n\nfunction isTrue (v) {\n  return v === true\n}\n\nfunction isFalse (v) {\n  return v === false\n}\n\n/**\n * Check if value is primitive\n */\nfunction isPrimitive (value) {\n  return typeof value === 'string' || typeof value === 'number'\n}\n\n/**\n * Quick object check - this is primarily used to tell\n * Objects from primitive values when we know the value\n * is a JSON-compliant type.\n */\nfunction isObject (obj) {\n  return obj !== null && typeof obj === 'object'\n}\n\nvar _toString = Object.prototype.toString;\n\n/**\n * Strict object type check. Only returns true\n * for plain JavaScript objects.\n */\nfunction isPlainObject (obj) {\n  return _toString.call(obj) === '[object Object]'\n}\n\nfunction isRegExp (v) {\n  return _toString.call(v) === '[object RegExp]'\n}\n\n/**\n * Check if val is a valid array index.\n */\nfunction isValidArrayIndex (val) {\n  var n = parseFloat(val);\n  return n >= 0 && Math.floor(n) === n && isFinite(val)\n}\n\n/**\n * Convert a value to a string that is actually rendered.\n */\nfunction toString (val) {\n  return val == null\n    ? ''\n    : typeof val === 'object'\n      ? JSON.stringify(val, null, 2)\n      : String(val)\n}\n\n/**\n * Convert a input value to a number for persistence.\n * If the conversion fails, return original string.\n */\nfunction toNumber (val) {\n  var n = parseFloat(val);\n  return isNaN(n) ? val : n\n}\n\n/**\n * Make a map and return a function for checking if a key\n * is in that map.\n */\nfunction makeMap (\n  str,\n  expectsLowerCase\n) {\n  var map = Object.create(null);\n  var list = str.split(',');\n  for (var i = 0; i < list.length; i++) {\n    map[list[i]] = true;\n  }\n  return expectsLowerCase\n    ? function (val) { return map[val.toLowerCase()]; }\n    : function (val) { return map[val]; }\n}\n\n/**\n * Check if a tag is a built-in tag.\n */\nvar isBuiltInTag = makeMap('slot,component', true);\n\n/**\n * Check if a attribute is a reserved attribute.\n */\nvar isReservedAttribute = makeMap('key,ref,slot,is');\n\n/**\n * Remove an item from an array\n */\nfunction remove (arr, item) {\n  if (arr.length) {\n    var index = arr.indexOf(item);\n    if (index > -1) {\n      return arr.splice(index, 1)\n    }\n  }\n}\n\n/**\n * Check whether the object has the property.\n */\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\nfunction hasOwn (obj, key) {\n  return hasOwnProperty.call(obj, key)\n}\n\n/**\n * Create a cached version of a pure function.\n */\nfunction cached (fn) {\n  var cache = Object.create(null);\n  return (function cachedFn (str) {\n    var hit = cache[str];\n    return hit || (cache[str] = fn(str))\n  })\n}\n\n/**\n * Camelize a hyphen-delimited string.\n */\nvar camelizeRE = /-(\\w)/g;\nvar camelize = cached(function (str) {\n  return str.replace(camelizeRE, function (_, c) { return c ? c.toUpperCase() : ''; })\n});\n\n/**\n * Capitalize a string.\n */\nvar capitalize = cached(function (str) {\n  return str.charAt(0).toUpperCase() + str.slice(1)\n});\n\n/**\n * Hyphenate a camelCase string.\n */\nvar hyphenateRE = /([^-])([A-Z])/g;\nvar hyphenate = cached(function (str) {\n  return str\n    .replace(hyphenateRE, '$1-$2')\n    .replace(hyphenateRE, '$1-$2')\n    .toLowerCase()\n});\n\n/**\n * Simple bind, faster than native\n */\nfunction bind (fn, ctx) {\n  function boundFn (a) {\n    var l = arguments.length;\n    return l\n      ? l > 1\n        ? fn.apply(ctx, arguments)\n        : fn.call(ctx, a)\n      : fn.call(ctx)\n  }\n  // record original fn length\n  boundFn._length = fn.length;\n  return boundFn\n}\n\n/**\n * Convert an Array-like object to a real Array.\n */\nfunction toArray (list, start) {\n  start = start || 0;\n  var i = list.length - start;\n  var ret = new Array(i);\n  while (i--) {\n    ret[i] = list[i + start];\n  }\n  return ret\n}\n\n/**\n * Mix properties into target object.\n */\nfunction extend (to, _from) {\n  for (var key in _from) {\n    to[key] = _from[key];\n  }\n  return to\n}\n\n/**\n * Merge an Array of Objects into a single Object.\n */\nfunction toObject (arr) {\n  var res = {};\n  for (var i = 0; i < arr.length; i++) {\n    if (arr[i]) {\n      extend(res, arr[i]);\n    }\n  }\n  return res\n}\n\n/**\n * Perform no operation.\n * Stubbing args to make Flow happy without leaving useless transpiled code\n * with ...rest (https://flow.org/blog/2017/05/07/Strict-Function-Call-Arity/)\n */\nfunction noop (a, b, c) {}\n\n/**\n * Always return false.\n */\nvar no = function (a, b, c) { return false; };\n\n/**\n * Return same value\n */\nvar identity = function (_) { return _; };\n\n/**\n * Generate a static keys string from compiler modules.\n */\n\n\n/**\n * Check if two values are loosely equal - that is,\n * if they are plain objects, do they have the same shape?\n */\nfunction looseEqual (a, b) {\n  var isObjectA = isObject(a);\n  var isObjectB = isObject(b);\n  if (isObjectA && isObjectB) {\n    try {\n      return JSON.stringify(a) === JSON.stringify(b)\n    } catch (e) {\n      // possible circular reference\n      return a === b\n    }\n  } else if (!isObjectA && !isObjectB) {\n    return String(a) === String(b)\n  } else {\n    return false\n  }\n}\n\nfunction looseIndexOf (arr, val) {\n  for (var i = 0; i < arr.length; i++) {\n    if (looseEqual(arr[i], val)) { return i }\n  }\n  return -1\n}\n\n/**\n * Ensure a function is called only once.\n */\nfunction once (fn) {\n  var called = false;\n  return function () {\n    if (!called) {\n      called = true;\n      fn.apply(this, arguments);\n    }\n  }\n}\n\nvar SSR_ATTR = 'data-server-rendered';\n\nvar ASSET_TYPES = [\n  'component',\n  'directive',\n  'filter'\n];\n\nvar LIFECYCLE_HOOKS = [\n  'beforeCreate',\n  'created',\n  'beforeMount',\n  'mounted',\n  'beforeUpdate',\n  'updated',\n  'beforeDestroy',\n  'destroyed',\n  'activated',\n  'deactivated', 'onLaunch',\n  'onLoad',\n  'onShow',\n  'onReady',\n  'onHide',\n  'onUnload',\n  'onPullDownRefresh',\n  'onReachBottom',\n  'onShareAppMessage',\n  'onPageScroll',\n  'onTabItemTap',\n  'attached',\n  'ready',\n  'moved',\n  'detached'\n];\n\n/*  */\n\nvar config = ({\n  /**\n   * Option merge strategies (used in core/util/options)\n   */\n  optionMergeStrategies: Object.create(null),\n\n  /**\n   * Whether to suppress warnings.\n   */\n  silent: false,\n\n  /**\n   * Show production mode tip message on boot?\n   */\n  productionTip: \"production\" !== 'production',\n\n  /**\n   * Whether to enable devtools\n   */\n  devtools: \"production\" !== 'production',\n\n  /**\n   * Whether to record perf\n   */\n  performance: false,\n\n  /**\n   * Error handler for watcher errors\n   */\n  errorHandler: null,\n\n  /**\n   * Warn handler for watcher warns\n   */\n  warnHandler: null,\n\n  /**\n   * Ignore certain custom elements\n   */\n  ignoredElements: [],\n\n  /**\n   * Custom user key aliases for v-on\n   */\n  keyCodes: Object.create(null),\n\n  /**\n   * Check if a tag is reserved so that it cannot be registered as a\n   * component. This is platform-dependent and may be overwritten.\n   */\n  isReservedTag: no,\n\n  /**\n   * Check if an attribute is reserved so that it cannot be used as a component\n   * prop. This is platform-dependent and may be overwritten.\n   */\n  isReservedAttr: no,\n\n  /**\n   * Check if a tag is an unknown element.\n   * Platform-dependent.\n   */\n  isUnknownElement: no,\n\n  /**\n   * Get the namespace of an element\n   */\n  getTagNamespace: noop,\n\n  /**\n   * Parse the real tag name for the specific platform.\n   */\n  parsePlatformTagName: identity,\n\n  /**\n   * Check if an attribute must be bound using property, e.g. value\n   * Platform-dependent.\n   */\n  mustUseProp: no,\n\n  /**\n   * Exposed for legacy reasons\n   */\n  _lifecycleHooks: LIFECYCLE_HOOKS\n});\n\n/*  */\n\nvar emptyObject = Object.freeze({});\n\n/**\n * Check if a string starts with $ or _\n */\nfunction isReserved (str) {\n  var c = (str + '').charCodeAt(0);\n  return c === 0x24 || c === 0x5F\n}\n\n/**\n * Define a property.\n */\nfunction def (obj, key, val, enumerable) {\n  Object.defineProperty(obj, key, {\n    value: val,\n    enumerable: !!enumerable,\n    writable: true,\n    configurable: true\n  });\n}\n\n/**\n * Parse simple path.\n */\nvar bailRE = /[^\\w.$]/;\nfunction parsePath (path) {\n  if (bailRE.test(path)) {\n    return\n  }\n  var segments = path.split('.');\n  return function (obj) {\n    for (var i = 0; i < segments.length; i++) {\n      if (!obj) { return }\n      obj = obj[segments[i]];\n    }\n    return obj\n  }\n}\n\n/*  */\n\nvar warn = noop;\n\nvar formatComponentName = (null); // work around flow check\n\n/*  */\n\nfunction handleError (err, vm, info) {\n  if (config.errorHandler) {\n    config.errorHandler.call(null, err, vm, info);\n  } else {\n    if (inBrowser && typeof console !== 'undefined') {\n      console.error(err);\n    } else {\n      throw err\n    }\n  }\n}\n\n/*  */\n\n// can we use __proto__?\nvar hasProto = '__proto__' in {};\n\n// Browser environment sniffing\nvar inBrowser = typeof window !== 'undefined';\nvar UA = ['mpvue-runtime'].join();\nvar isIE = UA && /msie|trident/.test(UA);\nvar isIE9 = UA && UA.indexOf('msie 9.0') > 0;\nvar isEdge = UA && UA.indexOf('edge/') > 0;\nvar isAndroid = UA && UA.indexOf('android') > 0;\nvar isIOS = UA && /iphone|ipad|ipod|ios/.test(UA);\nvar isChrome = UA && /chrome\\/\\d+/.test(UA) && !isEdge;\n\n// Firefix has a \"watch\" function on Object.prototype...\nvar nativeWatch = ({}).watch;\n\nvar supportsPassive = false;\nif (inBrowser) {\n  try {\n    var opts = {};\n    Object.defineProperty(opts, 'passive', ({\n      get: function get () {\n        /* istanbul ignore next */\n        supportsPassive = true;\n      }\n    })); // https://github.com/facebook/flow/issues/285\n    window.addEventListener('test-passive', null, opts);\n  } catch (e) {}\n}\n\n// this needs to be lazy-evaled because vue may be required before\n// vue-server-renderer can set VUE_ENV\nvar _isServer;\nvar isServerRendering = function () {\n  if (_isServer === undefined) {\n    /* istanbul ignore if */\n    if (!inBrowser && typeof global !== 'undefined') {\n      // detect presence of vue-server-renderer and avoid\n      // Webpack shimming the process\n      _isServer = global['process'].env.VUE_ENV === 'server';\n    } else {\n      _isServer = false;\n    }\n  }\n  return _isServer\n};\n\n// detect devtools\nvar devtools = inBrowser && window.__VUE_DEVTOOLS_GLOBAL_HOOK__;\n\n/* istanbul ignore next */\nfunction isNative (Ctor) {\n  return typeof Ctor === 'function' && /native code/.test(Ctor.toString())\n}\n\nvar hasSymbol =\n  typeof Symbol !== 'undefined' && isNative(Symbol) &&\n  typeof Reflect !== 'undefined' && isNative(Reflect.ownKeys);\n\n/**\n * Defer a task to execute it asynchronously.\n */\nvar nextTick = (function () {\n  var callbacks = [];\n  var pending = false;\n  var timerFunc;\n\n  function nextTickHandler () {\n    pending = false;\n    var copies = callbacks.slice(0);\n    callbacks.length = 0;\n    for (var i = 0; i < copies.length; i++) {\n      copies[i]();\n    }\n  }\n\n  // the nextTick behavior leverages the microtask queue, which can be accessed\n  // via either native Promise.then or MutationObserver.\n  // MutationObserver has wider support, however it is seriously bugged in\n  // UIWebView in iOS >= 9.3.3 when triggered in touch event handlers. It\n  // completely stops working after triggering a few times... so, if native\n  // Promise is available, we will use it:\n  /* istanbul ignore if */\n  if (typeof Promise !== 'undefined' && isNative(Promise)) {\n    var p = Promise.resolve();\n    var logError = function (err) { console.error(err); };\n    timerFunc = function () {\n      p.then(nextTickHandler).catch(logError);\n      // in problematic UIWebViews, Promise.then doesn't completely break, but\n      // it can get stuck in a weird state where callbacks are pushed into the\n      // microtask queue but the queue isn't being flushed, until the browser\n      // needs to do some other work, e.g. handle a timer. Therefore we can\n      // \"force\" the microtask queue to be flushed by adding an empty timer.\n      if (isIOS) { setTimeout(noop); }\n    };\n  // } else if (typeof MutationObserver !== 'undefined' && (\n  //   isNative(MutationObserver) ||\n  //   // PhantomJS and iOS 7.x\n  //   MutationObserver.toString() === '[object MutationObserverConstructor]'\n  // )) {\n  //   // use MutationObserver where native Promise is not available,\n  //   // e.g. PhantomJS IE11, iOS7, Android 4.4\n  //   var counter = 1\n  //   var observer = new MutationObserver(nextTickHandler)\n  //   var textNode = document.createTextNode(String(counter))\n  //   observer.observe(textNode, {\n  //     characterData: true\n  //   })\n  //   timerFunc = () => {\n  //     counter = (counter + 1) % 2\n  //     textNode.data = String(counter)\n  //   }\n  } else {\n    // fallback to setTimeout\n    /* istanbul ignore next */\n    timerFunc = function () {\n      setTimeout(nextTickHandler, 0);\n    };\n  }\n\n  return function queueNextTick (cb, ctx) {\n    var _resolve;\n    callbacks.push(function () {\n      if (cb) {\n        try {\n          cb.call(ctx);\n        } catch (e) {\n          handleError(e, ctx, 'nextTick');\n        }\n      } else if (_resolve) {\n        _resolve(ctx);\n      }\n    });\n    if (!pending) {\n      pending = true;\n      timerFunc();\n    }\n    if (!cb && typeof Promise !== 'undefined') {\n      return new Promise(function (resolve, reject) {\n        _resolve = resolve;\n      })\n    }\n  }\n})();\n\nvar _Set;\n/* istanbul ignore if */\nif (typeof Set !== 'undefined' && isNative(Set)) {\n  // use native Set when available.\n  _Set = Set;\n} else {\n  // a non-standard Set polyfill that only works with primitive keys.\n  _Set = (function () {\n    function Set () {\n      this.set = Object.create(null);\n    }\n    Set.prototype.has = function has (key) {\n      return this.set[key] === true\n    };\n    Set.prototype.add = function add (key) {\n      this.set[key] = true;\n    };\n    Set.prototype.clear = function clear () {\n      this.set = Object.create(null);\n    };\n\n    return Set;\n  }());\n}\n\n/*  */\n\n\nvar uid$1 = 0;\n\n/**\n * A dep is an observable that can have multiple\n * directives subscribing to it.\n */\nvar Dep = function Dep () {\n  this.id = uid$1++;\n  this.subs = [];\n};\n\nDep.prototype.addSub = function addSub (sub) {\n  this.subs.push(sub);\n};\n\nDep.prototype.removeSub = function removeSub (sub) {\n  remove(this.subs, sub);\n};\n\nDep.prototype.depend = function depend () {\n  if (Dep.target) {\n    Dep.target.addDep(this);\n  }\n};\n\nDep.prototype.notify = function notify () {\n  // stabilize the subscriber list first\n  var subs = this.subs.slice();\n  for (var i = 0, l = subs.length; i < l; i++) {\n    subs[i].update();\n  }\n};\n\n// the current target watcher being evaluated.\n// this is globally unique because there could be only one\n// watcher being evaluated at any time.\nDep.target = null;\nvar targetStack = [];\n\nfunction pushTarget (_target) {\n  if (Dep.target) { targetStack.push(Dep.target); }\n  Dep.target = _target;\n}\n\nfunction popTarget () {\n  Dep.target = targetStack.pop();\n}\n\n/*\n * not type checking this file because flow doesn't play well with\n * dynamically accessing methods on Array prototype\n */\n\nvar arrayProto = Array.prototype;\nvar arrayMethods = Object.create(arrayProto);[\n  'push',\n  'pop',\n  'shift',\n  'unshift',\n  'splice',\n  'sort',\n  'reverse'\n]\n.forEach(function (method) {\n  // cache original method\n  var original = arrayProto[method];\n  def(arrayMethods, method, function mutator () {\n    var args = [], len = arguments.length;\n    while ( len-- ) args[ len ] = arguments[ len ];\n\n    var result = original.apply(this, args);\n    var ob = this.__ob__;\n    var inserted;\n    switch (method) {\n      case 'push':\n      case 'unshift':\n        inserted = args;\n        break\n      case 'splice':\n        inserted = args.slice(2);\n        break\n    }\n    if (inserted) { ob.observeArray(inserted); }\n    // notify change\n    ob.dep.notify();\n    return result\n  });\n});\n\n/*  */\n\nvar arrayKeys = Object.getOwnPropertyNames(arrayMethods);\n\n/**\n * By default, when a reactive property is set, the new value is\n * also converted to become reactive. However when passing down props,\n * we don't want to force conversion because the value may be a nested value\n * under a frozen data structure. Converting it would defeat the optimization.\n */\nvar observerState = {\n  shouldConvert: true\n};\n\n/**\n * Observer class that are attached to each observed\n * object. Once attached, the observer converts target\n * object's property keys into getter/setters that\n * collect dependencies and dispatches updates.\n */\nvar Observer = function Observer (value, key) {\n  this.value = value;\n  this.dep = new Dep();\n  this.vmCount = 0;\n  if (key) {\n    this.key = key;\n  }\n  def(value, '__ob__', this);\n  if (Array.isArray(value)) {\n    var augment = hasProto\n      ? protoAugment\n      : copyAugment;\n    augment(value, arrayMethods, arrayKeys);\n    this.observeArray(value);\n  } else {\n    this.walk(value);\n  }\n};\n\n/**\n * Walk through each property and convert them into\n * getter/setters. This method should only be called when\n * value type is Object.\n */\nObserver.prototype.walk = function walk (obj) {\n  var keys = Object.keys(obj);\n  for (var i = 0; i < keys.length; i++) {\n    defineReactive$$1(obj, keys[i], obj[keys[i]]);\n  }\n};\n\n/**\n * Observe a list of Array items.\n */\nObserver.prototype.observeArray = function observeArray (items) {\n  for (var i = 0, l = items.length; i < l; i++) {\n    observe(items[i]);\n  }\n};\n\n// helpers\n\n/**\n * Augment an target Object or Array by intercepting\n * the prototype chain using __proto__\n */\nfunction protoAugment (target, src, keys) {\n  /* eslint-disable no-proto */\n  target.__proto__ = src;\n  /* eslint-enable no-proto */\n}\n\n/**\n * Augment an target Object or Array by defining\n * hidden properties.\n */\n/* istanbul ignore next */\nfunction copyAugment (target, src, keys) {\n  for (var i = 0, l = keys.length; i < l; i++) {\n    var key = keys[i];\n    def(target, key, src[key]);\n  }\n}\n\n/**\n * Attempt to create an observer instance for a value,\n * returns the new observer if successfully observed,\n * or the existing observer if the value already has one.\n */\nfunction observe (value, asRootData, key) {\n  if (!isObject(value)) {\n    return\n  }\n  var ob;\n  if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) {\n    ob = value.__ob__;\n  } else if (\n    observerState.shouldConvert &&\n    !isServerRendering() &&\n    (Array.isArray(value) || isPlainObject(value)) &&\n    Object.isExtensible(value) &&\n    !value._isVue\n  ) {\n    ob = new Observer(value, key);\n  }\n  if (asRootData && ob) {\n    ob.vmCount++;\n  }\n  return ob\n}\n\n/**\n * Define a reactive property on an Object.\n */\nfunction defineReactive$$1 (\n  obj,\n  key,\n  val,\n  customSetter,\n  shallow\n) {\n  var dep = new Dep();\n\n  var property = Object.getOwnPropertyDescriptor(obj, key);\n  if (property && property.configurable === false) {\n    return\n  }\n\n  // cater for pre-defined getter/setters\n  var getter = property && property.get;\n  var setter = property && property.set;\n\n  var childOb = !shallow && observe(val, undefined, key);\n  Object.defineProperty(obj, key, {\n    enumerable: true,\n    configurable: true,\n    get: function reactiveGetter () {\n      var value = getter ? getter.call(obj) : val;\n      if (Dep.target) {\n        dep.depend();\n        if (childOb) {\n          childOb.dep.depend();\n        }\n        if (Array.isArray(value)) {\n          dependArray(value);\n        }\n      }\n      return value\n    },\n    set: function reactiveSetter (newVal) {\n      var value = getter ? getter.call(obj) : val;\n      /* eslint-disable no-self-compare */\n      if (newVal === value || (newVal !== newVal && value !== value)) {\n        return\n      }\n\n      /* eslint-enable no-self-compare */\n      if (\"production\" !== 'production' && customSetter) {\n        customSetter();\n      }\n      if (setter) {\n        setter.call(obj, newVal);\n      } else {\n        val = newVal;\n      }\n      childOb = !shallow && observe(newVal, undefined, key);\n      dep.notify();\n\n      if (!obj.__keyPath) {\n        def(obj, '__keyPath', {}, false);\n      }\n      obj.__keyPath[key] = true;\n      if (newVal instanceof Object && !(newVal instanceof Array)) {\n        // 标记是否是通过this.Obj = {} 赋值印发的改动，解决少更新问题#1305\n        def(newVal, '__newReference', true, false);\n      }\n    }\n  });\n}\n\n/**\n * Set a property on an object. Adds the new property and\n * triggers change notification if the property doesn't\n * already exist.\n */\nfunction set (target, key, val) {\n  if (Array.isArray(target) && isValidArrayIndex(key)) {\n    target.length = Math.max(target.length, key);\n    target.splice(key, 1, val);\n    return val\n  }\n  if (hasOwn(target, key)) {\n    target[key] = val;\n    return val\n  }\n  var ob = (target).__ob__;\n  if (target._isVue || (ob && ob.vmCount)) {\n    \"production\" !== 'production' && warn(\n      'Avoid adding reactive properties to a Vue instance or its root $data ' +\n      'at runtime - declare it upfront in the data option.'\n    );\n    return val\n  }\n  if (!ob) {\n    target[key] = val;\n    return val\n  }\n  defineReactive$$1(ob.value, key, val);\n  // Vue.set 添加对象属性，渲染时候把 val 传给小程序渲染\n  if (!target.__keyPath) {\n    def(target, '__keyPath', {}, false);\n  }\n  target.__keyPath[key] = true;\n  ob.dep.notify();\n  return val\n}\n\n/**\n * Delete a property and trigger change if necessary.\n */\nfunction del (target, key) {\n  if (Array.isArray(target) && isValidArrayIndex(key)) {\n    target.splice(key, 1);\n    return\n  }\n  var ob = (target).__ob__;\n  if (target._isVue || (ob && ob.vmCount)) {\n    \"production\" !== 'production' && warn(\n      'Avoid deleting properties on a Vue instance or its root $data ' +\n      '- just set it to null.'\n    );\n    return\n  }\n  if (!hasOwn(target, key)) {\n    return\n  }\n  delete target[key];\n  if (!ob) {\n    return\n  }\n  if (!target.__keyPath) {\n    def(target, '__keyPath', {}, false);\n  }\n  // Vue.del 删除对象属性，渲染时候把这个属性设置为 undefined\n  target.__keyPath[key] = 'del';\n  ob.dep.notify();\n}\n\n/**\n * Collect dependencies on array elements when the array is touched, since\n * we cannot intercept array element access like property getters.\n */\nfunction dependArray (value) {\n  for (var e = (void 0), i = 0, l = value.length; i < l; i++) {\n    e = value[i];\n    e && e.__ob__ && e.__ob__.dep.depend();\n    if (Array.isArray(e)) {\n      dependArray(e);\n    }\n  }\n}\n\n/*  */\n\n/**\n * Option overwriting strategies are functions that handle\n * how to merge a parent option value and a child option\n * value into the final value.\n */\nvar strats = config.optionMergeStrategies;\n\n/**\n * Options with restrictions\n */\n/**\n * Helper that recursively merges two data objects together.\n */\nfunction mergeData (to, from) {\n  if (!from) { return to }\n  var key, toVal, fromVal;\n  var keys = Object.keys(from);\n  for (var i = 0; i < keys.length; i++) {\n    key = keys[i];\n    toVal = to[key];\n    fromVal = from[key];\n    if (!hasOwn(to, key)) {\n      set(to, key, fromVal);\n    } else if (isPlainObject(toVal) && isPlainObject(fromVal)) {\n      mergeData(toVal, fromVal);\n    }\n  }\n  return to\n}\n\n/**\n * Data\n */\nfunction mergeDataOrFn (\n  parentVal,\n  childVal,\n  vm\n) {\n  if (!vm) {\n    // in a Vue.extend merge, both should be functions\n    if (!childVal) {\n      return parentVal\n    }\n    if (!parentVal) {\n      return childVal\n    }\n    // when parentVal & childVal are both present,\n    // we need to return a function that returns the\n    // merged result of both functions... no need to\n    // check if parentVal is a function here because\n    // it has to be a function to pass previous merges.\n    return function mergedDataFn () {\n      return mergeData(\n        typeof childVal === 'function' ? childVal.call(this) : childVal,\n        parentVal.call(this)\n      )\n    }\n  } else if (parentVal || childVal) {\n    return function mergedInstanceDataFn () {\n      // instance merge\n      var instanceData = typeof childVal === 'function'\n        ? childVal.call(vm)\n        : childVal;\n      var defaultData = typeof parentVal === 'function'\n        ? parentVal.call(vm)\n        : undefined;\n      if (instanceData) {\n        return mergeData(instanceData, defaultData)\n      } else {\n        return defaultData\n      }\n    }\n  }\n}\n\nstrats.data = function (\n  parentVal,\n  childVal,\n  vm\n) {\n  if (!vm) {\n    if (childVal && typeof childVal !== 'function') {\n      \"production\" !== 'production' && warn(\n        'The \"data\" option should be a function ' +\n        'that returns a per-instance value in component ' +\n        'definitions.',\n        vm\n      );\n\n      return parentVal\n    }\n    return mergeDataOrFn.call(this, parentVal, childVal)\n  }\n\n  return mergeDataOrFn(parentVal, childVal, vm)\n};\n\n/**\n * Hooks and props are merged as arrays.\n */\nfunction mergeHook (\n  parentVal,\n  childVal\n) {\n  return childVal\n    ? parentVal\n      ? parentVal.concat(childVal)\n      : Array.isArray(childVal)\n        ? childVal\n        : [childVal]\n    : parentVal\n}\n\nLIFECYCLE_HOOKS.forEach(function (hook) {\n  strats[hook] = mergeHook;\n});\n\n/**\n * Assets\n *\n * When a vm is present (instance creation), we need to do\n * a three-way merge between constructor options, instance\n * options and parent options.\n */\nfunction mergeAssets (parentVal, childVal) {\n  var res = Object.create(parentVal || null);\n  return childVal\n    ? extend(res, childVal)\n    : res\n}\n\nASSET_TYPES.forEach(function (type) {\n  strats[type + 's'] = mergeAssets;\n});\n\n/**\n * Watchers.\n *\n * Watchers hashes should not overwrite one\n * another, so we merge them as arrays.\n */\nstrats.watch = function (parentVal, childVal) {\n  // work around Firefox's Object.prototype.watch...\n  if (parentVal === nativeWatch) { parentVal = undefined; }\n  if (childVal === nativeWatch) { childVal = undefined; }\n  /* istanbul ignore if */\n  if (!childVal) { return Object.create(parentVal || null) }\n  if (!parentVal) { return childVal }\n  var ret = {};\n  extend(ret, parentVal);\n  for (var key in childVal) {\n    var parent = ret[key];\n    var child = childVal[key];\n    if (parent && !Array.isArray(parent)) {\n      parent = [parent];\n    }\n    ret[key] = parent\n      ? parent.concat(child)\n      : Array.isArray(child) ? child : [child];\n  }\n  return ret\n};\n\n/**\n * Other object hashes.\n */\nstrats.props =\nstrats.methods =\nstrats.inject =\nstrats.computed = function (parentVal, childVal) {\n  if (!childVal) { return Object.create(parentVal || null) }\n  if (!parentVal) { return childVal }\n  var ret = Object.create(null);\n  extend(ret, parentVal);\n  extend(ret, childVal);\n  return ret\n};\nstrats.provide = mergeDataOrFn;\n\n/**\n * Default strategy.\n */\nvar defaultStrat = function (parentVal, childVal) {\n  return childVal === undefined\n    ? parentVal\n    : childVal\n};\n\n/**\n * Ensure all props option syntax are normalized into the\n * Object-based format.\n */\nfunction normalizeProps (options) {\n  var props = options.props;\n  if (!props) { return }\n  var res = {};\n  var i, val, name;\n  if (Array.isArray(props)) {\n    i = props.length;\n    while (i--) {\n      val = props[i];\n      if (typeof val === 'string') {\n        name = camelize(val);\n        res[name] = { type: null };\n      } else {}\n    }\n  } else if (isPlainObject(props)) {\n    for (var key in props) {\n      val = props[key];\n      name = camelize(key);\n      res[name] = isPlainObject(val)\n        ? val\n        : { type: val };\n    }\n  }\n  options.props = res;\n}\n\n/**\n * Normalize all injections into Object-based format\n */\nfunction normalizeInject (options) {\n  var inject = options.inject;\n  if (Array.isArray(inject)) {\n    var normalized = options.inject = {};\n    for (var i = 0; i < inject.length; i++) {\n      normalized[inject[i]] = inject[i];\n    }\n  }\n}\n\n/**\n * Normalize raw function directives into object format.\n */\nfunction normalizeDirectives (options) {\n  var dirs = options.directives;\n  if (dirs) {\n    for (var key in dirs) {\n      var def = dirs[key];\n      if (typeof def === 'function') {\n        dirs[key] = { bind: def, update: def };\n      }\n    }\n  }\n}\n\n/**\n * Merge two option objects into a new one.\n * Core utility used in both instantiation and inheritance.\n */\nfunction mergeOptions (\n  parent,\n  child,\n  vm\n) {\n  if (typeof child === 'function') {\n    child = child.options;\n  }\n\n  normalizeProps(child);\n  normalizeInject(child);\n  normalizeDirectives(child);\n  var extendsFrom = child.extends;\n  if (extendsFrom) {\n    parent = mergeOptions(parent, extendsFrom, vm);\n  }\n  if (child.mixins) {\n    for (var i = 0, l = child.mixins.length; i < l; i++) {\n      parent = mergeOptions(parent, child.mixins[i], vm);\n    }\n  }\n  var options = {};\n  var key;\n  for (key in parent) {\n    mergeField(key);\n  }\n  for (key in child) {\n    if (!hasOwn(parent, key)) {\n      mergeField(key);\n    }\n  }\n  function mergeField (key) {\n    var strat = strats[key] || defaultStrat;\n    options[key] = strat(parent[key], child[key], vm, key);\n  }\n  return options\n}\n\n/**\n * Resolve an asset.\n * This function is used because child instances need access\n * to assets defined in its ancestor chain.\n */\nfunction resolveAsset (\n  options,\n  type,\n  id,\n  warnMissing\n) {\n  /* istanbul ignore if */\n  if (typeof id !== 'string') {\n    return\n  }\n  var assets = options[type];\n  // check local registration variations first\n  if (hasOwn(assets, id)) { return assets[id] }\n  var camelizedId = camelize(id);\n  if (hasOwn(assets, camelizedId)) { return assets[camelizedId] }\n  var PascalCaseId = capitalize(camelizedId);\n  if (hasOwn(assets, PascalCaseId)) { return assets[PascalCaseId] }\n  // fallback to prototype chain\n  var res = assets[id] || assets[camelizedId] || assets[PascalCaseId];\n  if (\"production\" !== 'production' && warnMissing && !res) {\n    warn(\n      'Failed to resolve ' + type.slice(0, -1) + ': ' + id,\n      options\n    );\n  }\n  return res\n}\n\n/*  */\n\nfunction validateProp (\n  key,\n  propOptions,\n  propsData,\n  vm\n) {\n  var prop = propOptions[key];\n  var absent = !hasOwn(propsData, key);\n  var value = propsData[key];\n  // handle boolean props\n  if (isType(Boolean, prop.type)) {\n    if (absent && !hasOwn(prop, 'default')) {\n      value = false;\n    } else if (!isType(String, prop.type) && (value === '' || value === hyphenate(key))) {\n      value = true;\n    }\n  }\n  // check default value\n  if (value === undefined) {\n    value = getPropDefaultValue(vm, prop, key);\n    // since the default value is a fresh copy,\n    // make sure to observe it.\n    var prevShouldConvert = observerState.shouldConvert;\n    observerState.shouldConvert = true;\n    observe(value);\n    observerState.shouldConvert = prevShouldConvert;\n  }\n  return value\n}\n\n/**\n * Get the default value of a prop.\n */\nfunction getPropDefaultValue (vm, prop, key) {\n  // no default, return undefined\n  if (!hasOwn(prop, 'default')) {\n    return undefined\n  }\n  var def = prop.default;\n  // warn against non-factory defaults for Object & Array\n  if (\"production\" !== 'production' && isObject(def)) {\n    warn(\n      'Invalid default value for prop \"' + key + '\": ' +\n      'Props with type Object/Array must use a factory function ' +\n      'to return the default value.',\n      vm\n    );\n  }\n  // the raw prop value was also undefined from previous render,\n  // return previous default value to avoid unnecessary watcher trigger\n  if (vm && vm.$options.propsData &&\n    vm.$options.propsData[key] === undefined &&\n    vm._props[key] !== undefined\n  ) {\n    return vm._props[key]\n  }\n  // call factory function for non-Function types\n  // a value is Function if its prototype is function even across different execution context\n  return typeof def === 'function' && getType(prop.type) !== 'Function'\n    ? def.call(vm)\n    : def\n}\n\n/**\n * Use function string name to check built-in types,\n * because a simple equality check will fail when running\n * across different vms / iframes.\n */\nfunction getType (fn) {\n  var match = fn && fn.toString().match(/^\\s*function (\\w+)/);\n  return match ? match[1] : ''\n}\n\nfunction isType (type, fn) {\n  if (!Array.isArray(fn)) {\n    return getType(fn) === getType(type)\n  }\n  for (var i = 0, len = fn.length; i < len; i++) {\n    if (getType(fn[i]) === getType(type)) {\n      return true\n    }\n  }\n  /* istanbul ignore next */\n  return false\n}\n\n/*  */\n\n/* not type checking this file because flow doesn't play well with Proxy */\n\nvar mark;\nvar measure;\n\n/*  */\n\nvar VNode = function VNode (\n  tag,\n  data,\n  children,\n  text,\n  elm,\n  context,\n  componentOptions,\n  asyncFactory\n) {\n  this.tag = tag;\n  this.data = data;\n  this.children = children;\n  this.text = text;\n  this.elm = elm;\n  this.ns = undefined;\n  this.context = context;\n  this.functionalContext = undefined;\n  this.key = data && data.key;\n  this.componentOptions = componentOptions;\n  this.componentInstance = undefined;\n  this.parent = undefined;\n  this.raw = false;\n  this.isStatic = false;\n  this.isRootInsert = true;\n  this.isComment = false;\n  this.isCloned = false;\n  this.isOnce = false;\n  this.asyncFactory = asyncFactory;\n  this.asyncMeta = undefined;\n  this.isAsyncPlaceholder = false;\n};\n\nvar prototypeAccessors = { child: {} };\n\n// DEPRECATED: alias for componentInstance for backwards compat.\n/* istanbul ignore next */\nprototypeAccessors.child.get = function () {\n  return this.componentInstance\n};\n\nObject.defineProperties( VNode.prototype, prototypeAccessors );\n\nvar createEmptyVNode = function (text) {\n  if ( text === void 0 ) text = '';\n\n  var node = new VNode();\n  node.text = text;\n  node.isComment = true;\n  return node\n};\n\nfunction createTextVNode (val) {\n  return new VNode(undefined, undefined, undefined, String(val))\n}\n\n// optimized shallow clone\n// used for static nodes and slot nodes because they may be reused across\n// multiple renders, cloning them avoids errors when DOM manipulations rely\n// on their elm reference.\nfunction cloneVNode (vnode) {\n  var cloned = new VNode(\n    vnode.tag,\n    vnode.data,\n    vnode.children,\n    vnode.text,\n    vnode.elm,\n    vnode.context,\n    vnode.componentOptions,\n    vnode.asyncFactory\n  );\n  cloned.ns = vnode.ns;\n  cloned.isStatic = vnode.isStatic;\n  cloned.key = vnode.key;\n  cloned.isComment = vnode.isComment;\n  cloned.isCloned = true;\n  return cloned\n}\n\nfunction cloneVNodes (vnodes) {\n  var len = vnodes.length;\n  var res = new Array(len);\n  for (var i = 0; i < len; i++) {\n    res[i] = cloneVNode(vnodes[i]);\n  }\n  return res\n}\n\n/*  */\n\nvar normalizeEvent = cached(function (name) {\n  var passive = name.charAt(0) === '&';\n  name = passive ? name.slice(1) : name;\n  var once$$1 = name.charAt(0) === '~'; // Prefixed last, checked first\n  name = once$$1 ? name.slice(1) : name;\n  var capture = name.charAt(0) === '!';\n  name = capture ? name.slice(1) : name;\n  return {\n    name: name,\n    once: once$$1,\n    capture: capture,\n    passive: passive\n  }\n});\n\nfunction createFnInvoker (fns) {\n  function invoker () {\n    var arguments$1 = arguments;\n\n    var fns = invoker.fns;\n    if (Array.isArray(fns)) {\n      var cloned = fns.slice();\n      for (var i = 0; i < cloned.length; i++) {\n        cloned[i].apply(null, arguments$1);\n      }\n    } else {\n      // return handler return value for single handlers\n      return fns.apply(null, arguments)\n    }\n  }\n  invoker.fns = fns;\n  return invoker\n}\n\nfunction updateListeners (\n  on,\n  oldOn,\n  add,\n  remove$$1,\n  vm\n) {\n  var name, cur, old, event;\n  for (name in on) {\n    cur = on[name];\n    old = oldOn[name];\n    event = normalizeEvent(name);\n    if (isUndef(cur)) {\n      \"production\" !== 'production' && warn(\n        \"Invalid handler for event \\\"\" + (event.name) + \"\\\": got \" + String(cur),\n        vm\n      );\n    } else if (isUndef(old)) {\n      if (isUndef(cur.fns)) {\n        cur = on[name] = createFnInvoker(cur);\n      }\n      add(event.name, cur, event.once, event.capture, event.passive);\n    } else if (cur !== old) {\n      old.fns = cur;\n      on[name] = old;\n    }\n  }\n  for (name in oldOn) {\n    if (isUndef(on[name])) {\n      event = normalizeEvent(name);\n      remove$$1(event.name, oldOn[name], event.capture);\n    }\n  }\n}\n\n/*  */\n\n/*  */\n\nfunction extractPropsFromVNodeData (\n  data,\n  Ctor,\n  tag\n) {\n  // we are only extracting raw values here.\n  // validation and default values are handled in the child\n  // component itself.\n  var propOptions = Ctor.options.props;\n  if (isUndef(propOptions)) {\n    return\n  }\n  var res = {};\n  var attrs = data.attrs;\n  var props = data.props;\n  if (isDef(attrs) || isDef(props)) {\n    for (var key in propOptions) {\n      var altKey = hyphenate(key);\n      checkProp(res, props, key, altKey, true) ||\n      checkProp(res, attrs, key, altKey, false);\n    }\n  }\n  return res\n}\n\nfunction checkProp (\n  res,\n  hash,\n  key,\n  altKey,\n  preserve\n) {\n  if (isDef(hash)) {\n    if (hasOwn(hash, key)) {\n      res[key] = hash[key];\n      if (!preserve) {\n        delete hash[key];\n      }\n      return true\n    } else if (hasOwn(hash, altKey)) {\n      res[key] = hash[altKey];\n      if (!preserve) {\n        delete hash[altKey];\n      }\n      return true\n    }\n  }\n  return false\n}\n\n/*  */\n\n// The template compiler attempts to minimize the need for normalization by\n// statically analyzing the template at compile time.\n//\n// For plain HTML markup, normalization can be completely skipped because the\n// generated render function is guaranteed to return Array<VNode>. There are\n// two cases where extra normalization is needed:\n\n// 1. When the children contains components - because a functional component\n// may return an Array instead of a single root. In this case, just a simple\n// normalization is needed - if any child is an Array, we flatten the whole\n// thing with Array.prototype.concat. It is guaranteed to be only 1-level deep\n// because functional components already normalize their own children.\nfunction simpleNormalizeChildren (children) {\n  for (var i = 0; i < children.length; i++) {\n    if (Array.isArray(children[i])) {\n      return Array.prototype.concat.apply([], children)\n    }\n  }\n  return children\n}\n\n// 2. When the children contains constructs that always generated nested Arrays,\n// e.g. <template>, <slot>, v-for, or when the children is provided by user\n// with hand-written render functions / JSX. In such cases a full normalization\n// is needed to cater to all possible types of children values.\nfunction normalizeChildren (children) {\n  return isPrimitive(children)\n    ? [createTextVNode(children)]\n    : Array.isArray(children)\n      ? normalizeArrayChildren(children)\n      : undefined\n}\n\nfunction isTextNode (node) {\n  return isDef(node) && isDef(node.text) && isFalse(node.isComment)\n}\n\nfunction normalizeArrayChildren (children, nestedIndex) {\n  var res = [];\n  var i, c, last;\n  for (i = 0; i < children.length; i++) {\n    c = children[i];\n    if (isUndef(c) || typeof c === 'boolean') { continue }\n    last = res[res.length - 1];\n    //  nested\n    if (Array.isArray(c)) {\n      res.push.apply(res, normalizeArrayChildren(c, ((nestedIndex || '') + \"_\" + i)));\n    } else if (isPrimitive(c)) {\n      if (isTextNode(last)) {\n        // merge adjacent text nodes\n        // this is necessary for SSR hydration because text nodes are\n        // essentially merged when rendered to HTML strings\n        (last).text += String(c);\n      } else if (c !== '') {\n        // convert primitive to vnode\n        res.push(createTextVNode(c));\n      }\n    } else {\n      if (isTextNode(c) && isTextNode(last)) {\n        // merge adjacent text nodes\n        res[res.length - 1] = createTextVNode(last.text + c.text);\n      } else {\n        // default key for nested array children (likely generated by v-for)\n        if (isTrue(children._isVList) &&\n          isDef(c.tag) &&\n          isUndef(c.key) &&\n          isDef(nestedIndex)) {\n          c.key = \"__vlist\" + nestedIndex + \"_\" + i + \"__\";\n        }\n        res.push(c);\n      }\n    }\n  }\n  return res\n}\n\n/*  */\n\nfunction ensureCtor (comp, base) {\n  if (comp.__esModule && comp.default) {\n    comp = comp.default;\n  }\n  return isObject(comp)\n    ? base.extend(comp)\n    : comp\n}\n\nfunction createAsyncPlaceholder (\n  factory,\n  data,\n  context,\n  children,\n  tag\n) {\n  var node = createEmptyVNode();\n  node.asyncFactory = factory;\n  node.asyncMeta = { data: data, context: context, children: children, tag: tag };\n  return node\n}\n\nfunction resolveAsyncComponent (\n  factory,\n  baseCtor,\n  context\n) {\n  if (isTrue(factory.error) && isDef(factory.errorComp)) {\n    return factory.errorComp\n  }\n\n  if (isDef(factory.resolved)) {\n    return factory.resolved\n  }\n\n  if (isTrue(factory.loading) && isDef(factory.loadingComp)) {\n    return factory.loadingComp\n  }\n\n  if (isDef(factory.contexts)) {\n    // already pending\n    factory.contexts.push(context);\n  } else {\n    var contexts = factory.contexts = [context];\n    var sync = true;\n\n    var forceRender = function () {\n      for (var i = 0, l = contexts.length; i < l; i++) {\n        contexts[i].$forceUpdate();\n      }\n    };\n\n    var resolve = once(function (res) {\n      // cache resolved\n      factory.resolved = ensureCtor(res, baseCtor);\n      // invoke callbacks only if this is not a synchronous resolve\n      // (async resolves are shimmed as synchronous during SSR)\n      if (!sync) {\n        forceRender();\n      }\n    });\n\n    var reject = once(function (reason) {\n      \"production\" !== 'production' && warn(\n        \"Failed to resolve async component: \" + (String(factory)) +\n        (reason ? (\"\\nReason: \" + reason) : '')\n      );\n      if (isDef(factory.errorComp)) {\n        factory.error = true;\n        forceRender();\n      }\n    });\n\n    var res = factory(resolve, reject);\n\n    if (isObject(res)) {\n      if (typeof res.then === 'function') {\n        // () => Promise\n        if (isUndef(factory.resolved)) {\n          res.then(resolve, reject);\n        }\n      } else if (isDef(res.component) && typeof res.component.then === 'function') {\n        res.component.then(resolve, reject);\n\n        if (isDef(res.error)) {\n          factory.errorComp = ensureCtor(res.error, baseCtor);\n        }\n\n        if (isDef(res.loading)) {\n          factory.loadingComp = ensureCtor(res.loading, baseCtor);\n          if (res.delay === 0) {\n            factory.loading = true;\n          } else {\n            setTimeout(function () {\n              if (isUndef(factory.resolved) && isUndef(factory.error)) {\n                factory.loading = true;\n                forceRender();\n              }\n            }, res.delay || 200);\n          }\n        }\n\n        if (isDef(res.timeout)) {\n          setTimeout(function () {\n            if (isUndef(factory.resolved)) {\n              reject(\n                null\n              );\n            }\n          }, res.timeout);\n        }\n      }\n    }\n\n    sync = false;\n    // return in case resolved synchronously\n    return factory.loading\n      ? factory.loadingComp\n      : factory.resolved\n  }\n}\n\n/*  */\n\nfunction getFirstComponentChild (children) {\n  if (Array.isArray(children)) {\n    for (var i = 0; i < children.length; i++) {\n      var c = children[i];\n      if (isDef(c) && isDef(c.componentOptions)) {\n        return c\n      }\n    }\n  }\n}\n\n/*  */\n\n/*  */\n\nfunction initEvents (vm) {\n  vm._events = Object.create(null);\n  vm._hasHookEvent = false;\n  // init parent attached events\n  var listeners = vm.$options._parentListeners;\n  if (listeners) {\n    updateComponentListeners(vm, listeners);\n  }\n}\n\nvar target;\n\nfunction add (event, fn, once$$1) {\n  if (once$$1) {\n    target.$once(event, fn);\n  } else {\n    target.$on(event, fn);\n  }\n}\n\nfunction remove$1 (event, fn) {\n  target.$off(event, fn);\n}\n\nfunction updateComponentListeners (\n  vm,\n  listeners,\n  oldListeners\n) {\n  target = vm;\n  updateListeners(listeners, oldListeners || {}, add, remove$1, vm);\n}\n\nfunction eventsMixin (Vue) {\n  var hookRE = /^hook:/;\n  Vue.prototype.$on = function (event, fn) {\n    var this$1 = this;\n\n    var vm = this;\n    if (Array.isArray(event)) {\n      for (var i = 0, l = event.length; i < l; i++) {\n        this$1.$on(event[i], fn);\n      }\n    } else {\n      (vm._events[event] || (vm._events[event] = [])).push(fn);\n      // optimize hook:event cost by using a boolean flag marked at registration\n      // instead of a hash lookup\n      if (hookRE.test(event)) {\n        vm._hasHookEvent = true;\n      }\n    }\n    return vm\n  };\n\n  Vue.prototype.$once = function (event, fn) {\n    var vm = this;\n    function on () {\n      vm.$off(event, on);\n      fn.apply(vm, arguments);\n    }\n    on.fn = fn;\n    vm.$on(event, on);\n    return vm\n  };\n\n  Vue.prototype.$off = function (event, fn) {\n    var this$1 = this;\n\n    var vm = this;\n    // all\n    if (!arguments.length) {\n      vm._events = Object.create(null);\n      return vm\n    }\n    // array of events\n    if (Array.isArray(event)) {\n      for (var i$1 = 0, l = event.length; i$1 < l; i$1++) {\n        this$1.$off(event[i$1], fn);\n      }\n      return vm\n    }\n    // specific event\n    var cbs = vm._events[event];\n    if (!cbs) {\n      return vm\n    }\n    if (arguments.length === 1) {\n      vm._events[event] = null;\n      return vm\n    }\n    // specific handler\n    var cb;\n    var i = cbs.length;\n    while (i--) {\n      cb = cbs[i];\n      if (cb === fn || cb.fn === fn) {\n        cbs.splice(i, 1);\n        break\n      }\n    }\n    return vm\n  };\n\n  Vue.prototype.$emit = function (event) {\n    var vm = this;\n    var cbs = vm._events[event];\n    if (cbs) {\n      cbs = cbs.length > 1 ? toArray(cbs) : cbs;\n      var args = toArray(arguments, 1);\n      for (var i = 0, l = cbs.length; i < l; i++) {\n        try {\n          cbs[i].apply(vm, args);\n        } catch (e) {\n          handleError(e, vm, (\"event handler for \\\"\" + event + \"\\\"\"));\n        }\n      }\n    }\n    return vm\n  };\n}\n\n/*  */\n\n/**\n * Runtime helper for resolving raw children VNodes into a slot object.\n */\nfunction resolveSlots (\n  children,\n  context\n) {\n  var slots = {};\n  if (!children) {\n    return slots\n  }\n  var defaultSlot = [];\n  for (var i = 0, l = children.length; i < l; i++) {\n    var child = children[i];\n    // named slots should only be respected if the vnode was rendered in the\n    // same context.\n    if ((child.context === context || child.functionalContext === context) &&\n      child.data && child.data.slot != null\n    ) {\n      var name = child.data.slot;\n      var slot = (slots[name] || (slots[name] = []));\n      if (child.tag === 'template') {\n        slot.push.apply(slot, child.children);\n      } else {\n        slot.push(child);\n      }\n    } else {\n      defaultSlot.push(child);\n    }\n  }\n  // ignore whitespace\n  if (!defaultSlot.every(isWhitespace)) {\n    slots.default = defaultSlot;\n  }\n  return slots\n}\n\nfunction isWhitespace (node) {\n  return node.isComment || node.text === ' '\n}\n\nfunction resolveScopedSlots (\n  fns, // see flow/vnode\n  res\n) {\n  res = res || {};\n  for (var i = 0; i < fns.length; i++) {\n    if (Array.isArray(fns[i])) {\n      resolveScopedSlots(fns[i], res);\n    } else {\n      res[fns[i].key] = fns[i].fn;\n    }\n  }\n  return res\n}\n\n/*  */\n\nvar activeInstance = null;\n\n\nfunction initLifecycle (vm) {\n  var options = vm.$options;\n\n  // locate first non-abstract parent\n  var parent = options.parent;\n  if (parent && !options.abstract) {\n    while (parent.$options.abstract && parent.$parent) {\n      parent = parent.$parent;\n    }\n    parent.$children.push(vm);\n  }\n\n  vm.$parent = parent;\n  vm.$root = parent ? parent.$root : vm;\n\n  vm.$children = [];\n  vm.$refs = {};\n\n  vm._watcher = null;\n  vm._inactive = null;\n  vm._directInactive = false;\n  vm._isMounted = false;\n  vm._isDestroyed = false;\n  vm._isBeingDestroyed = false;\n}\n\nfunction lifecycleMixin (Vue) {\n  Vue.prototype._update = function (vnode, hydrating) {\n    var vm = this;\n    if (vm._isMounted) {\n      callHook(vm, 'beforeUpdate');\n    }\n    var prevEl = vm.$el;\n    var prevVnode = vm._vnode;\n    var prevActiveInstance = activeInstance;\n    activeInstance = vm;\n    vm._vnode = vnode;\n    // Vue.prototype.__patch__ is injected in entry points\n    // based on the rendering backend used.\n    if (!prevVnode) {\n      // initial render\n      vm.$el = vm.__patch__(\n        vm.$el, vnode, hydrating, false /* removeOnly */,\n        vm.$options._parentElm,\n        vm.$options._refElm\n      );\n      // no need for the ref nodes after initial patch\n      // this prevents keeping a detached DOM tree in memory (#5851)\n      vm.$options._parentElm = vm.$options._refElm = null;\n    } else {\n      // updates\n      vm.$el = vm.__patch__(prevVnode, vnode);\n    }\n    activeInstance = prevActiveInstance;\n    // update __vue__ reference\n    if (prevEl) {\n      prevEl.__vue__ = null;\n    }\n    if (vm.$el) {\n      vm.$el.__vue__ = vm;\n    }\n    // if parent is an HOC, update its $el as well\n    if (vm.$vnode && vm.$parent && vm.$vnode === vm.$parent._vnode) {\n      vm.$parent.$el = vm.$el;\n    }\n    // updated hook is called by the scheduler to ensure that children are\n    // updated in a parent's updated hook.\n  };\n\n  Vue.prototype.$forceUpdate = function () {\n    var vm = this;\n    if (vm._watcher) {\n      vm._watcher.update();\n    }\n  };\n\n  Vue.prototype.$destroy = function () {\n    var vm = this;\n    if (vm._isBeingDestroyed) {\n      return\n    }\n    callHook(vm, 'beforeDestroy');\n    vm._isBeingDestroyed = true;\n    // remove self from parent\n    var parent = vm.$parent;\n    if (parent && !parent._isBeingDestroyed && !vm.$options.abstract) {\n      remove(parent.$children, vm);\n    }\n    // teardown watchers\n    if (vm._watcher) {\n      vm._watcher.teardown();\n    }\n    var i = vm._watchers.length;\n    while (i--) {\n      vm._watchers[i].teardown();\n    }\n    // remove reference from data ob\n    // frozen object may not have observer.\n    if (vm._data.__ob__) {\n      vm._data.__ob__.vmCount--;\n    }\n    // call the last hook...\n    vm._isDestroyed = true;\n    // invoke destroy hooks on current rendered tree\n    vm.__patch__(vm._vnode, null);\n    // fire destroyed hook\n    callHook(vm, 'destroyed');\n    // turn off all instance listeners.\n    vm.$off();\n    // remove __vue__ reference\n    if (vm.$el) {\n      vm.$el.__vue__ = null;\n    }\n  };\n}\n\nfunction mountComponent (\n  vm,\n  el,\n  hydrating\n) {\n  vm.$el = el;\n  if (!vm.$options.render) {\n    vm.$options.render = createEmptyVNode;\n    \n  }\n  callHook(vm, 'beforeMount');\n\n  var updateComponent;\n  /* istanbul ignore if */\n  if (\"production\" !== 'production' && config.performance && mark) {\n    updateComponent = function () {\n      var name = vm._name;\n      var id = vm._uid;\n      var startTag = \"vue-perf-start:\" + id;\n      var endTag = \"vue-perf-end:\" + id;\n\n      mark(startTag);\n      var vnode = vm._render();\n      mark(endTag);\n      measure((name + \" render\"), startTag, endTag);\n\n      mark(startTag);\n      vm._update(vnode, hydrating);\n      mark(endTag);\n      measure((name + \" patch\"), startTag, endTag);\n    };\n  } else {\n    updateComponent = function () {\n      vm._update(vm._render(), hydrating);\n    };\n  }\n\n  vm._watcher = new Watcher(vm, updateComponent, noop);\n  hydrating = false;\n\n  // manually mounted instance, call mounted on self\n  // mounted is called for render-created child components in its inserted hook\n  if (vm.$vnode == null) {\n    vm._isMounted = true;\n    callHook(vm, 'mounted');\n  }\n  return vm\n}\n\nfunction updateChildComponent (\n  vm,\n  propsData,\n  listeners,\n  parentVnode,\n  renderChildren\n) {\n  var hasChildren = !!(\n    renderChildren ||               // has new static slots\n    vm.$options._renderChildren ||  // has old static slots\n    parentVnode.data.scopedSlots || // has new scoped slots\n    vm.$scopedSlots !== emptyObject // has old scoped slots\n  );\n\n  vm.$options._parentVnode = parentVnode;\n  vm.$vnode = parentVnode; // update vm's placeholder node without re-render\n\n  if (vm._vnode) { // update child tree's parent\n    vm._vnode.parent = parentVnode;\n  }\n  vm.$options._renderChildren = renderChildren;\n\n  // update $attrs and $listensers hash\n  // these are also reactive so they may trigger child update if the child\n  // used them during render\n  vm.$attrs = parentVnode.data && parentVnode.data.attrs;\n  vm.$listeners = listeners;\n\n  // update props\n  if (propsData && vm.$options.props) {\n    observerState.shouldConvert = false;\n    var props = vm._props;\n    var propKeys = vm.$options._propKeys || [];\n    for (var i = 0; i < propKeys.length; i++) {\n      var key = propKeys[i];\n      props[key] = validateProp(key, vm.$options.props, propsData, vm);\n    }\n    observerState.shouldConvert = true;\n    // keep a copy of raw propsData\n    vm.$options.propsData = propsData;\n  }\n\n  // update listeners\n  if (listeners) {\n    var oldListeners = vm.$options._parentListeners;\n    vm.$options._parentListeners = listeners;\n    updateComponentListeners(vm, listeners, oldListeners);\n  }\n  // resolve slots + force update if has children\n  if (hasChildren) {\n    vm.$slots = resolveSlots(renderChildren, parentVnode.context);\n    vm.$forceUpdate();\n  }\n\n  \n}\n\nfunction isInInactiveTree (vm) {\n  while (vm && (vm = vm.$parent)) {\n    if (vm._inactive) { return true }\n  }\n  return false\n}\n\nfunction activateChildComponent (vm, direct) {\n  if (direct) {\n    vm._directInactive = false;\n    if (isInInactiveTree(vm)) {\n      return\n    }\n  } else if (vm._directInactive) {\n    return\n  }\n  if (vm._inactive || vm._inactive === null) {\n    vm._inactive = false;\n    for (var i = 0; i < vm.$children.length; i++) {\n      activateChildComponent(vm.$children[i]);\n    }\n    callHook(vm, 'activated');\n  }\n}\n\nfunction deactivateChildComponent (vm, direct) {\n  if (direct) {\n    vm._directInactive = true;\n    if (isInInactiveTree(vm)) {\n      return\n    }\n  }\n  if (!vm._inactive) {\n    vm._inactive = true;\n    for (var i = 0; i < vm.$children.length; i++) {\n      deactivateChildComponent(vm.$children[i]);\n    }\n    callHook(vm, 'deactivated');\n  }\n}\n\nfunction callHook (vm, hook) {\n  var handlers = vm.$options[hook];\n  if (handlers) {\n    for (var i = 0, j = handlers.length; i < j; i++) {\n      try {\n        handlers[i].call(vm);\n      } catch (e) {\n        handleError(e, vm, (hook + \" hook\"));\n      }\n    }\n  }\n  if (vm._hasHookEvent) {\n    vm.$emit('hook:' + hook);\n  }\n}\n\n/*  */\n\n\nvar MAX_UPDATE_COUNT = 100;\n\nvar queue = [];\nvar activatedChildren = [];\nvar has = {};\nvar circular = {};\nvar waiting = false;\nvar flushing = false;\nvar index = 0;\n\n/**\n * Reset the scheduler's state.\n */\nfunction resetSchedulerState () {\n  index = queue.length = activatedChildren.length = 0;\n  has = {};\n  waiting = flushing = false;\n}\n\n/**\n * Flush both queues and run the watchers.\n */\nfunction flushSchedulerQueue () {\n  flushing = true;\n  var watcher, id;\n\n  // Sort queue before flush.\n  // This ensures that:\n  // 1. Components are updated from parent to child. (because parent is always\n  //    created before the child)\n  // 2. A component's user watchers are run before its render watcher (because\n  //    user watchers are created before the render watcher)\n  // 3. If a component is destroyed during a parent component's watcher run,\n  //    its watchers can be skipped.\n  queue.sort(function (a, b) { return a.id - b.id; });\n\n  // do not cache length because more watchers might be pushed\n  // as we run existing watchers\n  for (index = 0; index < queue.length; index++) {\n    watcher = queue[index];\n    id = watcher.id;\n    has[id] = null;\n    watcher.run();\n    // in dev build, check and stop circular updates.\n    if (\"production\" !== 'production' && has[id] != null) {\n      circular[id] = (circular[id] || 0) + 1;\n      if (circular[id] > MAX_UPDATE_COUNT) {\n        warn(\n          'You may have an infinite update loop ' + (\n            watcher.user\n              ? (\"in watcher with expression \\\"\" + (watcher.expression) + \"\\\"\")\n              : \"in a component render function.\"\n          ),\n          watcher.vm\n        );\n        break\n      }\n    }\n  }\n\n  // keep copies of post queues before resetting state\n  var activatedQueue = activatedChildren.slice();\n  var updatedQueue = queue.slice();\n\n  resetSchedulerState();\n\n  // call component updated and activated hooks\n  callActivatedHooks(activatedQueue);\n  callUpdatedHooks(updatedQueue);\n\n  // devtool hook\n  /* istanbul ignore if */\n  if (devtools && config.devtools) {\n    devtools.emit('flush');\n  }\n}\n\nfunction callUpdatedHooks (queue) {\n  var i = queue.length;\n  while (i--) {\n    var watcher = queue[i];\n    var vm = watcher.vm;\n    if (vm._watcher === watcher && vm._isMounted) {\n      callHook(vm, 'updated');\n    }\n  }\n}\n\n/**\n * Queue a kept-alive component that was activated during patch.\n * The queue will be processed after the entire tree has been patched.\n */\nfunction queueActivatedComponent (vm) {\n  // setting _inactive to false here so that a render function can\n  // rely on checking whether it's in an inactive tree (e.g. router-view)\n  vm._inactive = false;\n  activatedChildren.push(vm);\n}\n\nfunction callActivatedHooks (queue) {\n  for (var i = 0; i < queue.length; i++) {\n    queue[i]._inactive = true;\n    activateChildComponent(queue[i], true /* true */);\n  }\n}\n\n/**\n * Push a watcher into the watcher queue.\n * Jobs with duplicate IDs will be skipped unless it's\n * pushed when the queue is being flushed.\n */\nfunction queueWatcher (watcher) {\n  var id = watcher.id;\n  if (has[id] == null) {\n    has[id] = true;\n    if (!flushing) {\n      queue.push(watcher);\n    } else {\n      // if already flushing, splice the watcher based on its id\n      // if already past its id, it will be run next immediately.\n      var i = queue.length - 1;\n      while (i > index && queue[i].id > watcher.id) {\n        i--;\n      }\n      queue.splice(i + 1, 0, watcher);\n    }\n    // queue the flush\n    if (!waiting) {\n      waiting = true;\n      nextTick(flushSchedulerQueue);\n    }\n  }\n}\n\n/*  */\n\nvar uid$2 = 0;\n\n/**\n * A watcher parses an expression, collects dependencies,\n * and fires callback when the expression value changes.\n * This is used for both the $watch() api and directives.\n */\nvar Watcher = function Watcher (\n  vm,\n  expOrFn,\n  cb,\n  options\n) {\n  this.vm = vm;\n  vm._watchers.push(this);\n  // options\n  if (options) {\n    this.deep = !!options.deep;\n    this.user = !!options.user;\n    this.lazy = !!options.lazy;\n    this.sync = !!options.sync;\n  } else {\n    this.deep = this.user = this.lazy = this.sync = false;\n  }\n  this.cb = cb;\n  this.id = ++uid$2; // uid for batching\n  this.active = true;\n  this.dirty = this.lazy; // for lazy watchers\n  this.deps = [];\n  this.newDeps = [];\n  this.depIds = new _Set();\n  this.newDepIds = new _Set();\n  this.expression = '';\n  // parse expression for getter\n  if (typeof expOrFn === 'function') {\n    this.getter = expOrFn;\n  } else {\n    this.getter = parsePath(expOrFn);\n    if (!this.getter) {\n      this.getter = function () {};\n      \"production\" !== 'production' && warn(\n        \"Failed watching path: \\\"\" + expOrFn + \"\\\" \" +\n        'Watcher only accepts simple dot-delimited paths. ' +\n        'For full control, use a function instead.',\n        vm\n      );\n    }\n  }\n  this.value = this.lazy\n    ? undefined\n    : this.get();\n};\n\n/**\n * Evaluate the getter, and re-collect dependencies.\n */\nWatcher.prototype.get = function get () {\n  pushTarget(this);\n  var value;\n  var vm = this.vm;\n  try {\n    value = this.getter.call(vm, vm);\n  } catch (e) {\n    if (this.user) {\n      handleError(e, vm, (\"getter for watcher \\\"\" + (this.expression) + \"\\\"\"));\n    } else {\n      throw e\n    }\n  } finally {\n    // \"touch\" every property so they are all tracked as\n    // dependencies for deep watching\n    if (this.deep) {\n      traverse(value);\n    }\n    popTarget();\n    this.cleanupDeps();\n  }\n  return value\n};\n\n/**\n * Add a dependency to this directive.\n */\nWatcher.prototype.addDep = function addDep (dep) {\n  var id = dep.id;\n  if (!this.newDepIds.has(id)) {\n    this.newDepIds.add(id);\n    this.newDeps.push(dep);\n    if (!this.depIds.has(id)) {\n      dep.addSub(this);\n    }\n  }\n};\n\n/**\n * Clean up for dependency collection.\n */\nWatcher.prototype.cleanupDeps = function cleanupDeps () {\n    var this$1 = this;\n\n  var i = this.deps.length;\n  while (i--) {\n    var dep = this$1.deps[i];\n    if (!this$1.newDepIds.has(dep.id)) {\n      dep.removeSub(this$1);\n    }\n  }\n  var tmp = this.depIds;\n  this.depIds = this.newDepIds;\n  this.newDepIds = tmp;\n  this.newDepIds.clear();\n  tmp = this.deps;\n  this.deps = this.newDeps;\n  this.newDeps = tmp;\n  this.newDeps.length = 0;\n};\n\n/**\n * Subscriber interface.\n * Will be called when a dependency changes.\n */\nWatcher.prototype.update = function update () {\n  /* istanbul ignore else */\n  if (this.lazy) {\n    this.dirty = true;\n  } else if (this.sync) {\n    this.run();\n  } else {\n    queueWatcher(this);\n  }\n};\n\n/**\n * Scheduler job interface.\n * Will be called by the scheduler.\n */\nWatcher.prototype.run = function run () {\n  if (this.active) {\n    var value = this.get();\n    if (\n      value !== this.value ||\n      // Deep watchers and watchers on Object/Arrays should fire even\n      // when the value is the same, because the value may\n      // have mutated.\n      isObject(value) ||\n      this.deep\n    ) {\n      // set new value\n      var oldValue = this.value;\n      this.value = value;\n      if (this.user) {\n        try {\n          this.cb.call(this.vm, value, oldValue);\n        } catch (e) {\n          handleError(e, this.vm, (\"callback for watcher \\\"\" + (this.expression) + \"\\\"\"));\n        }\n      } else {\n        this.cb.call(this.vm, value, oldValue);\n      }\n    }\n  }\n};\n\n/**\n * Evaluate the value of the watcher.\n * This only gets called for lazy watchers.\n */\nWatcher.prototype.evaluate = function evaluate () {\n  this.value = this.get();\n  this.dirty = false;\n};\n\n/**\n * Depend on all deps collected by this watcher.\n */\nWatcher.prototype.depend = function depend () {\n    var this$1 = this;\n\n  var i = this.deps.length;\n  while (i--) {\n    this$1.deps[i].depend();\n  }\n};\n\n/**\n * Remove self from all dependencies' subscriber list.\n */\nWatcher.prototype.teardown = function teardown () {\n    var this$1 = this;\n\n  if (this.active) {\n    // remove self from vm's watcher list\n    // this is a somewhat expensive operation so we skip it\n    // if the vm is being destroyed.\n    if (!this.vm._isBeingDestroyed) {\n      remove(this.vm._watchers, this);\n    }\n    var i = this.deps.length;\n    while (i--) {\n      this$1.deps[i].removeSub(this$1);\n    }\n    this.active = false;\n  }\n};\n\n/**\n * Recursively traverse an object to evoke all converted\n * getters, so that every nested property inside the object\n * is collected as a \"deep\" dependency.\n */\nvar seenObjects = new _Set();\nfunction traverse (val) {\n  seenObjects.clear();\n  _traverse(val, seenObjects);\n}\n\nfunction _traverse (val, seen) {\n  var i, keys;\n  var isA = Array.isArray(val);\n  if ((!isA && !isObject(val)) || !Object.isExtensible(val)) {\n    return\n  }\n  if (val.__ob__) {\n    var depId = val.__ob__.dep.id;\n    if (seen.has(depId)) {\n      return\n    }\n    seen.add(depId);\n  }\n  if (isA) {\n    i = val.length;\n    while (i--) { _traverse(val[i], seen); }\n  } else {\n    keys = Object.keys(val);\n    i = keys.length;\n    while (i--) { _traverse(val[keys[i]], seen); }\n  }\n}\n\n/*  */\n\nvar sharedPropertyDefinition = {\n  enumerable: true,\n  configurable: true,\n  get: noop,\n  set: noop\n};\n\nfunction proxy (target, sourceKey, key) {\n  sharedPropertyDefinition.get = function proxyGetter () {\n    return this[sourceKey][key]\n  };\n  sharedPropertyDefinition.set = function proxySetter (val) {\n    this[sourceKey][key] = val;\n  };\n  Object.defineProperty(target, key, sharedPropertyDefinition);\n}\n\nfunction initState (vm) {\n  vm._watchers = [];\n  var opts = vm.$options;\n  if (opts.props) { initProps(vm, opts.props); }\n  if (opts.methods) { initMethods(vm, opts.methods); }\n  if (opts.data) {\n    initData(vm);\n  } else {\n    observe(vm._data = {}, true /* asRootData */);\n  }\n  if (opts.computed) { initComputed(vm, opts.computed); }\n  if (opts.watch && opts.watch !== nativeWatch) {\n    initWatch(vm, opts.watch);\n  }\n}\n\nfunction checkOptionType (vm, name) {\n  var option = vm.$options[name];\n  if (!isPlainObject(option)) {\n    warn(\n      (\"component option \\\"\" + name + \"\\\" should be an object.\"),\n      vm\n    );\n  }\n}\n\nfunction initProps (vm, propsOptions) {\n  var propsData = vm.$options.propsData || {};\n  var props = vm._props = {};\n  // cache prop keys so that future props updates can iterate using Array\n  // instead of dynamic object key enumeration.\n  var keys = vm.$options._propKeys = [];\n  var isRoot = !vm.$parent;\n  // root instance props should be converted\n  observerState.shouldConvert = isRoot;\n  var loop = function ( key ) {\n    keys.push(key);\n    var value = validateProp(key, propsOptions, propsData, vm);\n    /* istanbul ignore else */\n    {\n      defineReactive$$1(props, key, value);\n    }\n    // static props are already proxied on the component's prototype\n    // during Vue.extend(). We only need to proxy props defined at\n    // instantiation here.\n    if (!(key in vm)) {\n      proxy(vm, \"_props\", key);\n    }\n  };\n\n  for (var key in propsOptions) loop( key );\n  observerState.shouldConvert = true;\n}\n\nfunction initData (vm) {\n  var data = vm.$options.data;\n  data = vm._data = typeof data === 'function'\n    ? getData(data, vm)\n    : data || {};\n  if (!isPlainObject(data)) {\n    data = {};\n    \"production\" !== 'production' && warn(\n      'data functions should return an object:\\n' +\n      'https://vuejs.org/v2/guide/components.html#data-Must-Be-a-Function',\n      vm\n    );\n  }\n  // proxy data on instance\n  var keys = Object.keys(data);\n  var props = vm.$options.props;\n  var methods = vm.$options.methods;\n  var i = keys.length;\n  while (i--) {\n    var key = keys[i];\n    if (props && hasOwn(props, key)) {\n      \"production\" !== 'production' && warn(\n        \"The data property \\\"\" + key + \"\\\" is already declared as a prop. \" +\n        \"Use prop default value instead.\",\n        vm\n      );\n    } else if (!isReserved(key)) {\n      proxy(vm, \"_data\", key);\n    }\n  }\n  // observe data\n  observe(data, true /* asRootData */);\n}\n\nfunction getData (data, vm) {\n  try {\n    return data.call(vm)\n  } catch (e) {\n    handleError(e, vm, \"data()\");\n    return {}\n  }\n}\n\nvar computedWatcherOptions = { lazy: true };\n\nfunction initComputed (vm, computed) {\n  \"production\" !== 'production' && checkOptionType(vm, 'computed');\n  var watchers = vm._computedWatchers = Object.create(null);\n\n  for (var key in computed) {\n    var userDef = computed[key];\n    var getter = typeof userDef === 'function' ? userDef : userDef.get;\n    watchers[key] = new Watcher(vm, getter, noop, computedWatcherOptions);\n\n    // component-defined computed properties are already defined on the\n    // component prototype. We only need to define computed properties defined\n    // at instantiation here.\n    if (!(key in vm)) {\n      defineComputed(vm, key, userDef);\n    } else {}\n  }\n}\n\nfunction defineComputed (target, key, userDef) {\n  if (typeof userDef === 'function') {\n    sharedPropertyDefinition.get = createComputedGetter(key);\n    sharedPropertyDefinition.set = noop;\n  } else {\n    sharedPropertyDefinition.get = userDef.get\n      ? userDef.cache !== false\n        ? createComputedGetter(key)\n        : userDef.get\n      : noop;\n    sharedPropertyDefinition.set = userDef.set\n      ? userDef.set\n      : noop;\n  }\n  Object.defineProperty(target, key, sharedPropertyDefinition);\n}\n\nfunction createComputedGetter (key) {\n  return function computedGetter () {\n    var watcher = this._computedWatchers && this._computedWatchers[key];\n    if (watcher) {\n      if (watcher.dirty) {\n        watcher.evaluate();\n      }\n      if (Dep.target) {\n        watcher.depend();\n      }\n      return watcher.value\n    }\n  }\n}\n\nfunction initMethods (vm, methods) {\n  \"production\" !== 'production' && checkOptionType(vm, 'methods');\n  var props = vm.$options.props;\n  for (var key in methods) {\n    vm[key] = methods[key] == null ? noop : bind(methods[key], vm);\n    \n  }\n}\n\nfunction initWatch (vm, watch) {\n  \"production\" !== 'production' && checkOptionType(vm, 'watch');\n  for (var key in watch) {\n    var handler = watch[key];\n    if (Array.isArray(handler)) {\n      for (var i = 0; i < handler.length; i++) {\n        createWatcher(vm, key, handler[i]);\n      }\n    } else {\n      createWatcher(vm, key, handler);\n    }\n  }\n}\n\nfunction createWatcher (\n  vm,\n  keyOrFn,\n  handler,\n  options\n) {\n  if (isPlainObject(handler)) {\n    options = handler;\n    handler = handler.handler;\n  }\n  if (typeof handler === 'string') {\n    handler = vm[handler];\n  }\n  return vm.$watch(keyOrFn, handler, options)\n}\n\nfunction stateMixin (Vue) {\n  // flow somehow has problems with directly declared definition object\n  // when using Object.defineProperty, so we have to procedurally build up\n  // the object here.\n  var dataDef = {};\n  dataDef.get = function () { return this._data };\n  var propsDef = {};\n  propsDef.get = function () { return this._props };\n  Object.defineProperty(Vue.prototype, '$data', dataDef);\n  Object.defineProperty(Vue.prototype, '$props', propsDef);\n\n  Vue.prototype.$set = set;\n  Vue.prototype.$delete = del;\n\n  Vue.prototype.$watch = function (\n    expOrFn,\n    cb,\n    options\n  ) {\n    var vm = this;\n    if (isPlainObject(cb)) {\n      return createWatcher(vm, expOrFn, cb, options)\n    }\n    options = options || {};\n    options.user = true;\n    var watcher = new Watcher(vm, expOrFn, cb, options);\n    if (options.immediate) {\n      cb.call(vm, watcher.value);\n    }\n    return function unwatchFn () {\n      watcher.teardown();\n    }\n  };\n}\n\n/*  */\n\nfunction initProvide (vm) {\n  var provide = vm.$options.provide;\n  if (provide) {\n    vm._provided = typeof provide === 'function'\n      ? provide.call(vm)\n      : provide;\n  }\n}\n\nfunction initInjections (vm) {\n  var result = resolveInject(vm.$options.inject, vm);\n  if (result) {\n    observerState.shouldConvert = false;\n    Object.keys(result).forEach(function (key) {\n      /* istanbul ignore else */\n      {\n        defineReactive$$1(vm, key, result[key]);\n      }\n    });\n    observerState.shouldConvert = true;\n  }\n}\n\nfunction resolveInject (inject, vm) {\n  if (inject) {\n    // inject is :any because flow is not smart enough to figure out cached\n    var result = Object.create(null);\n    var keys = hasSymbol\n        ? Reflect.ownKeys(inject)\n        : Object.keys(inject);\n\n    for (var i = 0; i < keys.length; i++) {\n      var key = keys[i];\n      var provideKey = inject[key];\n      var source = vm;\n      while (source) {\n        if (source._provided && provideKey in source._provided) {\n          result[key] = source._provided[provideKey];\n          break\n        }\n        source = source.$parent;\n      }\n      if (\"production\" !== 'production' && !hasOwn(result, key)) {\n        warn((\"Injection \\\"\" + key + \"\\\" not found\"), vm);\n      }\n    }\n    return result\n  }\n}\n\n/*  */\n\nfunction createFunctionalComponent (\n  Ctor,\n  propsData,\n  data,\n  context,\n  children\n) {\n  var props = {};\n  var propOptions = Ctor.options.props;\n  if (isDef(propOptions)) {\n    for (var key in propOptions) {\n      props[key] = validateProp(key, propOptions, propsData || {});\n    }\n  } else {\n    if (isDef(data.attrs)) { mergeProps(props, data.attrs); }\n    if (isDef(data.props)) { mergeProps(props, data.props); }\n  }\n  // ensure the createElement function in functional components\n  // gets a unique context - this is necessary for correct named slot check\n  var _context = Object.create(context);\n  var h = function (a, b, c, d) { return createElement(_context, a, b, c, d, true); };\n  var vnode = Ctor.options.render.call(null, h, {\n    data: data,\n    props: props,\n    children: children,\n    parent: context,\n    listeners: data.on || {},\n    injections: resolveInject(Ctor.options.inject, context),\n    slots: function () { return resolveSlots(children, context); }\n  });\n  if (vnode instanceof VNode) {\n    vnode.functionalContext = context;\n    vnode.functionalOptions = Ctor.options;\n    if (data.slot) {\n      (vnode.data || (vnode.data = {})).slot = data.slot;\n    }\n  }\n  return vnode\n}\n\nfunction mergeProps (to, from) {\n  for (var key in from) {\n    to[camelize(key)] = from[key];\n  }\n}\n\n/*  */\n\n// hooks to be invoked on component VNodes during patch\nvar componentVNodeHooks = {\n  init: function init (\n    vnode,\n    hydrating,\n    parentElm,\n    refElm\n  ) {\n    if (!vnode.componentInstance || vnode.componentInstance._isDestroyed) {\n      var child = vnode.componentInstance = createComponentInstanceForVnode(\n        vnode,\n        activeInstance,\n        parentElm,\n        refElm\n      );\n      child.$mount(hydrating ? vnode.elm : undefined, hydrating);\n    } else if (vnode.data.keepAlive) {\n      // kept-alive components, treat as a patch\n      var mountedNode = vnode; // work around flow\n      componentVNodeHooks.prepatch(mountedNode, mountedNode);\n    }\n  },\n\n  prepatch: function prepatch (oldVnode, vnode) {\n    var options = vnode.componentOptions;\n    var child = vnode.componentInstance = oldVnode.componentInstance;\n    updateChildComponent(\n      child,\n      options.propsData, // updated props\n      options.listeners, // updated listeners\n      vnode, // new parent vnode\n      options.children // new children\n    );\n  },\n\n  insert: function insert (vnode) {\n    var context = vnode.context;\n    var componentInstance = vnode.componentInstance;\n\n    if (!componentInstance._isMounted) {\n      componentInstance._isMounted = true;\n      callHook(componentInstance, 'mounted');\n    }\n    if (vnode.data.keepAlive) {\n      if (context._isMounted) {\n        // vue-router#1212\n        // During updates, a kept-alive component's child components may\n        // change, so directly walking the tree here may call activated hooks\n        // on incorrect children. Instead we push them into a queue which will\n        // be processed after the whole patch process ended.\n        queueActivatedComponent(componentInstance);\n      } else {\n        activateChildComponent(componentInstance, true /* direct */);\n      }\n    }\n  },\n\n  destroy: function destroy (vnode) {\n    var componentInstance = vnode.componentInstance;\n    if (!componentInstance._isDestroyed) {\n      if (!vnode.data.keepAlive) {\n        componentInstance.$destroy();\n      } else {\n        deactivateChildComponent(componentInstance, true /* direct */);\n      }\n    }\n  }\n};\n\nvar hooksToMerge = Object.keys(componentVNodeHooks);\n\nfunction createComponent (\n  Ctor,\n  data,\n  context,\n  children,\n  tag\n) {\n  if (isUndef(Ctor)) {\n    return\n  }\n\n  var baseCtor = context.$options._base;\n\n  // plain options object: turn it into a constructor\n  if (isObject(Ctor)) {\n    Ctor = baseCtor.extend(Ctor);\n  }\n\n  // if at this stage it's not a constructor or an async component factory,\n  // reject.\n  if (typeof Ctor !== 'function') {\n    return\n  }\n\n  // async component\n  var asyncFactory;\n  if (isUndef(Ctor.cid)) {\n    asyncFactory = Ctor;\n    Ctor = resolveAsyncComponent(asyncFactory, baseCtor, context);\n    if (Ctor === undefined) {\n      // return a placeholder node for async component, which is rendered\n      // as a comment node but preserves all the raw information for the node.\n      // the information will be used for async server-rendering and hydration.\n      return createAsyncPlaceholder(\n        asyncFactory,\n        data,\n        context,\n        children,\n        tag\n      )\n    }\n  }\n\n  data = data || {};\n\n  // resolve constructor options in case global mixins are applied after\n  // component constructor creation\n  resolveConstructorOptions(Ctor);\n\n  // transform component v-model data into props & events\n  if (isDef(data.model)) {\n    transformModel(Ctor.options, data);\n  }\n\n  // extract props\n  var propsData = extractPropsFromVNodeData(data, Ctor, tag);\n\n  // functional component\n  if (isTrue(Ctor.options.functional)) {\n    return createFunctionalComponent(Ctor, propsData, data, context, children)\n  }\n\n  // keep listeners\n  var listeners = data.on;\n\n  if (isTrue(Ctor.options.abstract)) {\n    // abstract components do not keep anything\n    // other than props & listeners & slot\n\n    // work around flow\n    var slot = data.slot;\n    data = {};\n    if (slot) {\n      data.slot = slot;\n    }\n  }\n\n  // merge component management hooks onto the placeholder node\n  mergeHooks(data);\n\n  // return a placeholder vnode\n  var name = Ctor.options.name || tag;\n  var vnode = new VNode(\n    (\"vue-component-\" + (Ctor.cid) + (name ? (\"-\" + name) : '')),\n    data, undefined, undefined, undefined, context,\n    { Ctor: Ctor, propsData: propsData, listeners: listeners, tag: tag, children: children },\n    asyncFactory\n  );\n  return vnode\n}\n\nfunction createComponentInstanceForVnode (\n  vnode, // we know it's MountedComponentVNode but flow doesn't\n  parent, // activeInstance in lifecycle state\n  parentElm,\n  refElm\n) {\n  var vnodeComponentOptions = vnode.componentOptions;\n  var options = {\n    _isComponent: true,\n    parent: parent,\n    propsData: vnodeComponentOptions.propsData,\n    _componentTag: vnodeComponentOptions.tag,\n    _parentVnode: vnode,\n    _parentListeners: vnodeComponentOptions.listeners,\n    _renderChildren: vnodeComponentOptions.children,\n    _parentElm: parentElm || null,\n    _refElm: refElm || null\n  };\n  // check inline-template render functions\n  var inlineTemplate = vnode.data.inlineTemplate;\n  if (isDef(inlineTemplate)) {\n    options.render = inlineTemplate.render;\n    options.staticRenderFns = inlineTemplate.staticRenderFns;\n  }\n  return new vnodeComponentOptions.Ctor(options)\n}\n\nfunction mergeHooks (data) {\n  if (!data.hook) {\n    data.hook = {};\n  }\n  for (var i = 0; i < hooksToMerge.length; i++) {\n    var key = hooksToMerge[i];\n    var fromParent = data.hook[key];\n    var ours = componentVNodeHooks[key];\n    data.hook[key] = fromParent ? mergeHook$1(ours, fromParent) : ours;\n  }\n}\n\nfunction mergeHook$1 (one, two) {\n  return function (a, b, c, d) {\n    one(a, b, c, d);\n    two(a, b, c, d);\n  }\n}\n\n// transform component v-model info (value and callback) into\n// prop and event handler respectively.\nfunction transformModel (options, data) {\n  var prop = (options.model && options.model.prop) || 'value';\n  var event = (options.model && options.model.event) || 'input';(data.props || (data.props = {}))[prop] = data.model.value;\n  var on = data.on || (data.on = {});\n  if (isDef(on[event])) {\n    on[event] = [data.model.callback].concat(on[event]);\n  } else {\n    on[event] = data.model.callback;\n  }\n}\n\n/*  */\n\nvar SIMPLE_NORMALIZE = 1;\nvar ALWAYS_NORMALIZE = 2;\n\n// wrapper function for providing a more flexible interface\n// without getting yelled at by flow\nfunction createElement (\n  context,\n  tag,\n  data,\n  children,\n  normalizationType,\n  alwaysNormalize\n) {\n  if (Array.isArray(data) || isPrimitive(data)) {\n    normalizationType = children;\n    children = data;\n    data = undefined;\n  }\n  if (isTrue(alwaysNormalize)) {\n    normalizationType = ALWAYS_NORMALIZE;\n  }\n  return _createElement(context, tag, data, children, normalizationType)\n}\n\nfunction _createElement (\n  context,\n  tag,\n  data,\n  children,\n  normalizationType\n) {\n  if (isDef(data) && isDef((data).__ob__)) {\n    \"production\" !== 'production' && warn(\n      \"Avoid using observed data object as vnode data: \" + (JSON.stringify(data)) + \"\\n\" +\n      'Always create fresh vnode data objects in each render!',\n      context\n    );\n    return createEmptyVNode()\n  }\n  // object syntax in v-bind\n  if (isDef(data) && isDef(data.is)) {\n    tag = data.is;\n  }\n  if (!tag) {\n    // in case of component :is set to falsy value\n    return createEmptyVNode()\n  }\n  // warn against non-primitive key\n  if (\"production\" !== 'production' &&\n    isDef(data) && isDef(data.key) && !isPrimitive(data.key)\n  ) {\n    warn(\n      'Avoid using non-primitive value as key, ' +\n      'use string/number value instead.',\n      context\n    );\n  }\n  // support single function children as default scoped slot\n  if (Array.isArray(children) &&\n    typeof children[0] === 'function'\n  ) {\n    data = data || {};\n    data.scopedSlots = { default: children[0] };\n    children.length = 0;\n  }\n  if (normalizationType === ALWAYS_NORMALIZE) {\n    children = normalizeChildren(children);\n  } else if (normalizationType === SIMPLE_NORMALIZE) {\n    children = simpleNormalizeChildren(children);\n  }\n  var vnode, ns;\n  if (typeof tag === 'string') {\n    var Ctor;\n    ns = config.getTagNamespace(tag);\n    if (config.isReservedTag(tag)) {\n      // platform built-in elements\n      vnode = new VNode(\n        config.parsePlatformTagName(tag), data, children,\n        undefined, undefined, context\n      );\n    } else if (isDef(Ctor = resolveAsset(context.$options, 'components', tag))) {\n      // component\n      vnode = createComponent(Ctor, data, context, children, tag);\n    } else {\n      // unknown or unlisted namespaced elements\n      // check at runtime because it may get assigned a namespace when its\n      // parent normalizes children\n      vnode = new VNode(\n        tag, data, children,\n        undefined, undefined, context\n      );\n    }\n  } else {\n    // direct component options / constructor\n    vnode = createComponent(tag, data, context, children);\n  }\n  if (isDef(vnode)) {\n    if (ns) { applyNS(vnode, ns); }\n    return vnode\n  } else {\n    return createEmptyVNode()\n  }\n}\n\nfunction applyNS (vnode, ns) {\n  vnode.ns = ns;\n  if (vnode.tag === 'foreignObject') {\n    // use default namespace inside foreignObject\n    return\n  }\n  if (isDef(vnode.children)) {\n    for (var i = 0, l = vnode.children.length; i < l; i++) {\n      var child = vnode.children[i];\n      if (isDef(child.tag) && isUndef(child.ns)) {\n        applyNS(child, ns);\n      }\n    }\n  }\n}\n\n/*  */\n\n/**\n * Runtime helper for rendering v-for lists.\n */\nfunction renderList (\n  val,\n  render\n) {\n  var ret, i, l, keys, key;\n  if (Array.isArray(val) || typeof val === 'string') {\n    ret = new Array(val.length);\n    for (i = 0, l = val.length; i < l; i++) {\n      ret[i] = render(val[i], i);\n    }\n  } else if (typeof val === 'number') {\n    ret = new Array(val);\n    for (i = 0; i < val; i++) {\n      ret[i] = render(i + 1, i);\n    }\n  } else if (isObject(val)) {\n    keys = Object.keys(val);\n    ret = new Array(keys.length);\n    for (i = 0, l = keys.length; i < l; i++) {\n      key = keys[i];\n      ret[i] = render(val[key], key, i);\n    }\n  }\n  if (isDef(ret)) {\n    (ret)._isVList = true;\n  }\n  return ret\n}\n\n/*  */\n\n/**\n * Runtime helper for rendering <slot>\n */\nfunction renderSlot (\n  name,\n  fallback,\n  props,\n  bindObject\n) {\n  var scopedSlotFn = this.$scopedSlots[name];\n  if (scopedSlotFn) { // scoped slot\n    props = props || {};\n    if (bindObject) {\n      props = extend(extend({}, bindObject), props);\n    }\n    return scopedSlotFn(props) || fallback\n  } else {\n    var slotNodes = this.$slots[name];\n    // warn duplicate slot usage\n    if (slotNodes && \"production\" !== 'production') {\n      slotNodes._rendered && warn(\n        \"Duplicate presence of slot \\\"\" + name + \"\\\" found in the same render tree \" +\n        \"- this will likely cause render errors.\",\n        this\n      );\n      slotNodes._rendered = true;\n    }\n    return slotNodes || fallback\n  }\n}\n\n/*  */\n\n/**\n * Runtime helper for resolving filters\n */\nfunction resolveFilter (id) {\n  return resolveAsset(this.$options, 'filters', id, true) || identity\n}\n\n/*  */\n\n/**\n * Runtime helper for checking keyCodes from config.\n */\nfunction checkKeyCodes (\n  eventKeyCode,\n  key,\n  builtInAlias\n) {\n  var keyCodes = config.keyCodes[key] || builtInAlias;\n  if (Array.isArray(keyCodes)) {\n    return keyCodes.indexOf(eventKeyCode) === -1\n  } else {\n    return keyCodes !== eventKeyCode\n  }\n}\n\n/*  */\n\n/**\n * Runtime helper for merging v-bind=\"object\" into a VNode's data.\n */\nfunction bindObjectProps (\n  data,\n  tag,\n  value,\n  asProp,\n  isSync\n) {\n  if (value) {\n    if (!isObject(value)) {\n      \"production\" !== 'production' && warn(\n        'v-bind without argument expects an Object or Array value',\n        this\n      );\n    } else {\n      if (Array.isArray(value)) {\n        value = toObject(value);\n      }\n      var hash;\n      var loop = function ( key ) {\n        if (\n          key === 'class' ||\n          key === 'style' ||\n          isReservedAttribute(key)\n        ) {\n          hash = data;\n        } else {\n          var type = data.attrs && data.attrs.type;\n          hash = asProp || config.mustUseProp(tag, type, key)\n            ? data.domProps || (data.domProps = {})\n            : data.attrs || (data.attrs = {});\n        }\n        if (!(key in hash)) {\n          hash[key] = value[key];\n\n          if (isSync) {\n            var on = data.on || (data.on = {});\n            on[(\"update:\" + key)] = function ($event) {\n              value[key] = $event;\n            };\n          }\n        }\n      };\n\n      for (var key in value) loop( key );\n    }\n  }\n  return data\n}\n\n/*  */\n\n/**\n * Runtime helper for rendering static trees.\n */\nfunction renderStatic (\n  index,\n  isInFor\n) {\n  var tree = this._staticTrees[index];\n  // if has already-rendered static tree and not inside v-for,\n  // we can reuse the same tree by doing a shallow clone.\n  if (tree && !isInFor) {\n    return Array.isArray(tree)\n      ? cloneVNodes(tree)\n      : cloneVNode(tree)\n  }\n  // otherwise, render a fresh tree.\n  tree = this._staticTrees[index] =\n    this.$options.staticRenderFns[index].call(this._renderProxy);\n  markStatic(tree, (\"__static__\" + index), false);\n  return tree\n}\n\n/**\n * Runtime helper for v-once.\n * Effectively it means marking the node as static with a unique key.\n */\nfunction markOnce (\n  tree,\n  index,\n  key\n) {\n  markStatic(tree, (\"__once__\" + index + (key ? (\"_\" + key) : \"\")), true);\n  return tree\n}\n\nfunction markStatic (\n  tree,\n  key,\n  isOnce\n) {\n  if (Array.isArray(tree)) {\n    for (var i = 0; i < tree.length; i++) {\n      if (tree[i] && typeof tree[i] !== 'string') {\n        markStaticNode(tree[i], (key + \"_\" + i), isOnce);\n      }\n    }\n  } else {\n    markStaticNode(tree, key, isOnce);\n  }\n}\n\nfunction markStaticNode (node, key, isOnce) {\n  node.isStatic = true;\n  node.key = key;\n  node.isOnce = isOnce;\n}\n\n/*  */\n\nfunction bindObjectListeners (data, value) {\n  if (value) {\n    if (!isPlainObject(value)) {\n      \"production\" !== 'production' && warn(\n        'v-on without argument expects an Object value',\n        this\n      );\n    } else {\n      var on = data.on = data.on ? extend({}, data.on) : {};\n      for (var key in value) {\n        var existing = on[key];\n        var ours = value[key];\n        on[key] = existing ? [].concat(ours, existing) : ours;\n      }\n    }\n  }\n  return data\n}\n\n/*  */\n\nfunction initRender (vm) {\n  vm._vnode = null; // the root of the child tree\n  vm._staticTrees = null;\n  var parentVnode = vm.$vnode = vm.$options._parentVnode; // the placeholder node in parent tree\n  var renderContext = parentVnode && parentVnode.context;\n  vm.$slots = resolveSlots(vm.$options._renderChildren, renderContext);\n  vm.$scopedSlots = emptyObject;\n  // bind the createElement fn to this instance\n  // so that we get proper render context inside it.\n  // args order: tag, data, children, normalizationType, alwaysNormalize\n  // internal version is used by render functions compiled from templates\n  vm._c = function (a, b, c, d) { return createElement(vm, a, b, c, d, false); };\n  // normalization is always applied for the public version, used in\n  // user-written render functions.\n  vm.$createElement = function (a, b, c, d) { return createElement(vm, a, b, c, d, true); };\n\n  // $attrs & $listeners are exposed for easier HOC creation.\n  // they need to be reactive so that HOCs using them are always updated\n  var parentData = parentVnode && parentVnode.data;\n  /* istanbul ignore else */\n  {\n    defineReactive$$1(vm, '$attrs', parentData && parentData.attrs, null, true);\n    defineReactive$$1(vm, '$listeners', parentData && parentData.on, null, true);\n  }\n}\n\nfunction renderMixin (Vue) {\n  Vue.prototype.$nextTick = function (fn) {\n    return nextTick(fn, this)\n  };\n\n  Vue.prototype._render = function () {\n    var vm = this;\n    var ref = vm.$options;\n    var render = ref.render;\n    var staticRenderFns = ref.staticRenderFns;\n    var _parentVnode = ref._parentVnode;\n\n    if (vm._isMounted) {\n      // clone slot nodes on re-renders\n      for (var key in vm.$slots) {\n        vm.$slots[key] = cloneVNodes(vm.$slots[key]);\n      }\n    }\n\n    vm.$scopedSlots = (_parentVnode && _parentVnode.data.scopedSlots) || emptyObject;\n\n    if (staticRenderFns && !vm._staticTrees) {\n      vm._staticTrees = [];\n    }\n    // set parent vnode. this allows render functions to have access\n    // to the data on the placeholder node.\n    vm.$vnode = _parentVnode;\n    // render self\n    var vnode;\n    try {\n      vnode = render.call(vm._renderProxy, vm.$createElement);\n    } catch (e) {\n      handleError(e, vm, \"render function\");\n      // return error render result,\n      // or previous vnode to prevent render error causing blank component\n      /* istanbul ignore else */\n      {\n        vnode = vm._vnode;\n      }\n    }\n    // return empty vnode in case the render function errored out\n    if (!(vnode instanceof VNode)) {\n      if (\"production\" !== 'production' && Array.isArray(vnode)) {\n        warn(\n          'Multiple root nodes returned from render function. Render function ' +\n          'should return a single root node.',\n          vm\n        );\n      }\n      vnode = createEmptyVNode();\n    }\n    // set parent\n    vnode.parent = _parentVnode;\n    return vnode\n  };\n\n  // internal render helpers.\n  // these are exposed on the instance prototype to reduce generated render\n  // code size.\n  Vue.prototype._o = markOnce;\n  Vue.prototype._n = toNumber;\n  Vue.prototype._s = toString;\n  Vue.prototype._l = renderList;\n  Vue.prototype._t = renderSlot;\n  Vue.prototype._q = looseEqual;\n  Vue.prototype._i = looseIndexOf;\n  Vue.prototype._m = renderStatic;\n  Vue.prototype._f = resolveFilter;\n  Vue.prototype._k = checkKeyCodes;\n  Vue.prototype._b = bindObjectProps;\n  Vue.prototype._v = createTextVNode;\n  Vue.prototype._e = createEmptyVNode;\n  Vue.prototype._u = resolveScopedSlots;\n  Vue.prototype._g = bindObjectListeners;\n}\n\n/*  */\n\nvar uid = 0;\n\nfunction initMixin (Vue) {\n  Vue.prototype._init = function (options) {\n    var vm = this;\n    // a uid\n    vm._uid = uid++;\n\n    var startTag, endTag;\n    /* istanbul ignore if */\n    if (\"production\" !== 'production' && config.performance && mark) {\n      startTag = \"vue-perf-init:\" + (vm._uid);\n      endTag = \"vue-perf-end:\" + (vm._uid);\n      mark(startTag);\n    }\n\n    // a flag to avoid this being observed\n    vm._isVue = true;\n    // merge options\n    if (options && options._isComponent) {\n      // optimize internal component instantiation\n      // since dynamic options merging is pretty slow, and none of the\n      // internal component options needs special treatment.\n      initInternalComponent(vm, options);\n    } else {\n      vm.$options = mergeOptions(\n        resolveConstructorOptions(vm.constructor),\n        options || {},\n        vm\n      );\n    }\n    /* istanbul ignore else */\n    {\n      vm._renderProxy = vm;\n    }\n    // expose real self\n    vm._self = vm;\n    initLifecycle(vm);\n    initEvents(vm);\n    initRender(vm);\n    callHook(vm, 'beforeCreate');\n    initInjections(vm); // resolve injections before data/props\n    initState(vm);\n    initProvide(vm); // resolve provide after data/props\n    callHook(vm, 'created');\n\n    /* istanbul ignore if */\n    if (\"production\" !== 'production' && config.performance && mark) {\n      vm._name = formatComponentName(vm, false);\n      mark(endTag);\n      measure(((vm._name) + \" init\"), startTag, endTag);\n    }\n\n    if (vm.$options.el) {\n      vm.$mount(vm.$options.el);\n    }\n  };\n}\n\nfunction initInternalComponent (vm, options) {\n  var opts = vm.$options = Object.create(vm.constructor.options);\n  // doing this because it's faster than dynamic enumeration.\n  opts.parent = options.parent;\n  opts.propsData = options.propsData;\n  opts._parentVnode = options._parentVnode;\n  opts._parentListeners = options._parentListeners;\n  opts._renderChildren = options._renderChildren;\n  opts._componentTag = options._componentTag;\n  opts._parentElm = options._parentElm;\n  opts._refElm = options._refElm;\n  if (options.render) {\n    opts.render = options.render;\n    opts.staticRenderFns = options.staticRenderFns;\n  }\n}\n\nfunction resolveConstructorOptions (Ctor) {\n  var options = Ctor.options;\n  if (Ctor.super) {\n    var superOptions = resolveConstructorOptions(Ctor.super);\n    var cachedSuperOptions = Ctor.superOptions;\n    if (superOptions !== cachedSuperOptions) {\n      // super option changed,\n      // need to resolve new options.\n      Ctor.superOptions = superOptions;\n      // check if there are any late-modified/attached options (#4976)\n      var modifiedOptions = resolveModifiedOptions(Ctor);\n      // update base extend options\n      if (modifiedOptions) {\n        extend(Ctor.extendOptions, modifiedOptions);\n      }\n      options = Ctor.options = mergeOptions(superOptions, Ctor.extendOptions);\n      if (options.name) {\n        options.components[options.name] = Ctor;\n      }\n    }\n  }\n  return options\n}\n\nfunction resolveModifiedOptions (Ctor) {\n  var modified;\n  var latest = Ctor.options;\n  var extended = Ctor.extendOptions;\n  var sealed = Ctor.sealedOptions;\n  for (var key in latest) {\n    if (latest[key] !== sealed[key]) {\n      if (!modified) { modified = {}; }\n      modified[key] = dedupe(latest[key], extended[key], sealed[key]);\n    }\n  }\n  return modified\n}\n\nfunction dedupe (latest, extended, sealed) {\n  // compare latest and sealed to ensure lifecycle hooks won't be duplicated\n  // between merges\n  if (Array.isArray(latest)) {\n    var res = [];\n    sealed = Array.isArray(sealed) ? sealed : [sealed];\n    extended = Array.isArray(extended) ? extended : [extended];\n    for (var i = 0; i < latest.length; i++) {\n      // push original options and not sealed options to exclude duplicated options\n      if (extended.indexOf(latest[i]) >= 0 || sealed.indexOf(latest[i]) < 0) {\n        res.push(latest[i]);\n      }\n    }\n    return res\n  } else {\n    return latest\n  }\n}\n\nfunction Vue$3 (options) {\n  if (\"production\" !== 'production' &&\n    !(this instanceof Vue$3)\n  ) {\n    warn('Vue is a constructor and should be called with the `new` keyword');\n  }\n  this._init(options);\n}\n\ninitMixin(Vue$3);\nstateMixin(Vue$3);\neventsMixin(Vue$3);\nlifecycleMixin(Vue$3);\nrenderMixin(Vue$3);\n\n/*  */\n\nfunction initUse (Vue) {\n  Vue.use = function (plugin) {\n    var installedPlugins = (this._installedPlugins || (this._installedPlugins = []));\n    if (installedPlugins.indexOf(plugin) > -1) {\n      return this\n    }\n\n    // additional parameters\n    var args = toArray(arguments, 1);\n    args.unshift(this);\n    if (typeof plugin.install === 'function') {\n      plugin.install.apply(plugin, args);\n    } else if (typeof plugin === 'function') {\n      plugin.apply(null, args);\n    }\n    installedPlugins.push(plugin);\n    return this\n  };\n}\n\n/*  */\n\nfunction initMixin$1 (Vue) {\n  Vue.mixin = function (mixin) {\n    this.options = mergeOptions(this.options, mixin);\n    return this\n  };\n}\n\n/*  */\n\nfunction initExtend (Vue) {\n  /**\n   * Each instance constructor, including Vue, has a unique\n   * cid. This enables us to create wrapped \"child\n   * constructors\" for prototypal inheritance and cache them.\n   */\n  Vue.cid = 0;\n  var cid = 1;\n\n  /**\n   * Class inheritance\n   */\n  Vue.extend = function (extendOptions) {\n    extendOptions = extendOptions || {};\n    var Super = this;\n    var SuperId = Super.cid;\n    var cachedCtors = extendOptions._Ctor || (extendOptions._Ctor = {});\n    if (cachedCtors[SuperId]) {\n      return cachedCtors[SuperId]\n    }\n\n    var name = extendOptions.name || Super.options.name;\n    var Sub = function VueComponent (options) {\n      this._init(options);\n    };\n    Sub.prototype = Object.create(Super.prototype);\n    Sub.prototype.constructor = Sub;\n    Sub.cid = cid++;\n    Sub.options = mergeOptions(\n      Super.options,\n      extendOptions\n    );\n    Sub['super'] = Super;\n\n    // For props and computed properties, we define the proxy getters on\n    // the Vue instances at extension time, on the extended prototype. This\n    // avoids Object.defineProperty calls for each instance created.\n    if (Sub.options.props) {\n      initProps$1(Sub);\n    }\n    if (Sub.options.computed) {\n      initComputed$1(Sub);\n    }\n\n    // allow further extension/mixin/plugin usage\n    Sub.extend = Super.extend;\n    Sub.mixin = Super.mixin;\n    Sub.use = Super.use;\n\n    // create asset registers, so extended classes\n    // can have their private assets too.\n    ASSET_TYPES.forEach(function (type) {\n      Sub[type] = Super[type];\n    });\n    // enable recursive self-lookup\n    if (name) {\n      Sub.options.components[name] = Sub;\n    }\n\n    // keep a reference to the super options at extension time.\n    // later at instantiation we can check if Super's options have\n    // been updated.\n    Sub.superOptions = Super.options;\n    Sub.extendOptions = extendOptions;\n    Sub.sealedOptions = extend({}, Sub.options);\n\n    // cache constructor\n    cachedCtors[SuperId] = Sub;\n    return Sub\n  };\n}\n\nfunction initProps$1 (Comp) {\n  var props = Comp.options.props;\n  for (var key in props) {\n    proxy(Comp.prototype, \"_props\", key);\n  }\n}\n\nfunction initComputed$1 (Comp) {\n  var computed = Comp.options.computed;\n  for (var key in computed) {\n    defineComputed(Comp.prototype, key, computed[key]);\n  }\n}\n\n/*  */\n\nfunction initAssetRegisters (Vue) {\n  /**\n   * Create asset registration methods.\n   */\n  ASSET_TYPES.forEach(function (type) {\n    Vue[type] = function (\n      id,\n      definition\n    ) {\n      if (!definition) {\n        return this.options[type + 's'][id]\n      } else {\n        /* istanbul ignore if */\n        if (type === 'component' && isPlainObject(definition)) {\n          definition.name = definition.name || id;\n          definition = this.options._base.extend(definition);\n        }\n        if (type === 'directive' && typeof definition === 'function') {\n          definition = { bind: definition, update: definition };\n        }\n        this.options[type + 's'][id] = definition;\n        return definition\n      }\n    };\n  });\n}\n\n/*  */\n\nvar patternTypes = [String, RegExp, Array];\n\nfunction getComponentName (opts) {\n  return opts && (opts.Ctor.options.name || opts.tag)\n}\n\nfunction matches (pattern, name) {\n  if (Array.isArray(pattern)) {\n    return pattern.indexOf(name) > -1\n  } else if (typeof pattern === 'string') {\n    return pattern.split(',').indexOf(name) > -1\n  } else if (isRegExp(pattern)) {\n    return pattern.test(name)\n  }\n  /* istanbul ignore next */\n  return false\n}\n\nfunction pruneCache (cache, current, filter) {\n  for (var key in cache) {\n    var cachedNode = cache[key];\n    if (cachedNode) {\n      var name = getComponentName(cachedNode.componentOptions);\n      if (name && !filter(name)) {\n        if (cachedNode !== current) {\n          pruneCacheEntry(cachedNode);\n        }\n        cache[key] = null;\n      }\n    }\n  }\n}\n\nfunction pruneCacheEntry (vnode) {\n  if (vnode) {\n    vnode.componentInstance.$destroy();\n  }\n}\n\nvar KeepAlive = {\n  name: 'keep-alive',\n  abstract: true,\n\n  props: {\n    include: patternTypes,\n    exclude: patternTypes\n  },\n\n  created: function created () {\n    this.cache = Object.create(null);\n  },\n\n  destroyed: function destroyed () {\n    var this$1 = this;\n\n    for (var key in this$1.cache) {\n      pruneCacheEntry(this$1.cache[key]);\n    }\n  },\n\n  watch: {\n    include: function include (val) {\n      pruneCache(this.cache, this._vnode, function (name) { return matches(val, name); });\n    },\n    exclude: function exclude (val) {\n      pruneCache(this.cache, this._vnode, function (name) { return !matches(val, name); });\n    }\n  },\n\n  render: function render () {\n    var vnode = getFirstComponentChild(this.$slots.default);\n    var componentOptions = vnode && vnode.componentOptions;\n    if (componentOptions) {\n      // check pattern\n      var name = getComponentName(componentOptions);\n      if (name && (\n        (this.include && !matches(this.include, name)) ||\n        (this.exclude && matches(this.exclude, name))\n      )) {\n        return vnode\n      }\n      var key = vnode.key == null\n        // same constructor may get registered as different local components\n        // so cid alone is not enough (#3269)\n        ? componentOptions.Ctor.cid + (componentOptions.tag ? (\"::\" + (componentOptions.tag)) : '')\n        : vnode.key;\n      if (this.cache[key]) {\n        vnode.componentInstance = this.cache[key].componentInstance;\n      } else {\n        this.cache[key] = vnode;\n      }\n      vnode.data.keepAlive = true;\n    }\n    return vnode\n  }\n};\n\nvar builtInComponents = {\n  KeepAlive: KeepAlive\n};\n\n/*  */\n\nfunction initGlobalAPI (Vue) {\n  // config\n  var configDef = {};\n  configDef.get = function () { return config; };\n  Object.defineProperty(Vue, 'config', configDef);\n\n  // exposed util methods.\n  // NOTE: these are not considered part of the public API - avoid relying on\n  // them unless you are aware of the risk.\n  Vue.util = {\n    warn: warn,\n    extend: extend,\n    mergeOptions: mergeOptions,\n    defineReactive: defineReactive$$1\n  };\n\n  Vue.set = set;\n  Vue.delete = del;\n  Vue.nextTick = nextTick;\n\n  Vue.options = Object.create(null);\n  ASSET_TYPES.forEach(function (type) {\n    Vue.options[type + 's'] = Object.create(null);\n  });\n\n  // this is used to identify the \"base\" constructor to extend all plain-object\n  // components with in Weex's multi-instance scenarios.\n  Vue.options._base = Vue;\n\n  extend(Vue.options.components, builtInComponents);\n\n  initUse(Vue);\n  initMixin$1(Vue);\n  initExtend(Vue);\n  initAssetRegisters(Vue);\n}\n\ninitGlobalAPI(Vue$3);\n\nObject.defineProperty(Vue$3.prototype, '$isServer', {\n  get: isServerRendering\n});\n\nObject.defineProperty(Vue$3.prototype, '$ssrContext', {\n  get: function get () {\n    /* istanbul ignore next */\n    return this.$vnode && this.$vnode.ssrContext\n  }\n});\n\nVue$3.version = '2.4.1';\nVue$3.mpvueVersion = '2.0.6';\n\n/* globals renderer */\n\n\n\nvar isReservedTag = makeMap(\n  'template,script,style,element,content,slot,link,meta,svg,view,' +\n  'a,div,img,image,text,span,richtext,input,switch,textarea,spinner,select,' +\n  'slider,slider-neighbor,indicator,trisition,trisition-group,canvas,' +\n  'list,cell,header,loading,loading-indicator,refresh,scrollable,scroller,' +\n  'video,web,embed,tabbar,tabheader,datepicker,timepicker,marquee,countdown',\n  true\n);\n\n// these are reserved for web because they are directly compiled away\n// during template compilation\nvar isReservedAttr = makeMap('style,class');\n\n// Elements that you can, intentionally, leave open (and which close themselves)\n// more flexable than web\nvar canBeLeftOpenTag = makeMap(\n  'web,spinner,switch,video,textarea,canvas,' +\n  'indicator,marquee,countdown',\n  true\n);\n\nvar isUnaryTag = makeMap(\n  'embed,img,image,input,link,meta',\n  true\n);\n\nfunction mustUseProp () { /* console.log('mustUseProp') */ }\nfunction getTagNamespace () { /* console.log('getTagNamespace') */ }\nfunction isUnknownElement () { /* console.log('isUnknownElement') */ }\n\n\n\nfunction getComKey (vm) {\n  return vm && vm.$attrs ? vm.$attrs['mpcomid'] : '0'\n}\n\n// 用于小程序的 event type 到 web 的 event\nvar eventTypeMap = {\n  tap: ['tap', 'click'],\n  touchstart: ['touchstart'],\n  touchmove: ['touchmove'],\n  touchcancel: ['touchcancel'],\n  touchend: ['touchend'],\n  longtap: ['longtap'],\n  input: ['input'],\n  blur: ['change', 'blur'],\n  submit: ['submit'],\n  focus: ['focus'],\n  scrolltoupper: ['scrolltoupper'],\n  scrolltolower: ['scrolltolower'],\n  scroll: ['scroll']\n};\n\n/*  */\n\n// import { namespaceMap } from 'mp/util/index'\n\nvar obj = {};\n\nfunction createElement$1 (tagName, vnode) {\n  return obj\n}\n\nfunction createElementNS (namespace, tagName) {\n  return obj\n}\n\nfunction createTextNode (text) {\n  return obj\n}\n\nfunction createComment (text) {\n  return obj\n}\n\nfunction insertBefore (parentNode, newNode, referenceNode) {}\n\nfunction removeChild (node, child) {}\n\nfunction appendChild (node, child) {}\n\nfunction parentNode (node) {\n  return obj\n}\n\nfunction nextSibling (node) {\n  return obj\n}\n\nfunction tagName (node) {\n  return 'div'\n}\n\nfunction setTextContent (node, text) {\n  return obj\n}\n\nfunction setAttribute (node, key, val) {\n  return obj\n}\n\n\nvar nodeOps = Object.freeze({\n\tcreateElement: createElement$1,\n\tcreateElementNS: createElementNS,\n\tcreateTextNode: createTextNode,\n\tcreateComment: createComment,\n\tinsertBefore: insertBefore,\n\tremoveChild: removeChild,\n\tappendChild: appendChild,\n\tparentNode: parentNode,\n\tnextSibling: nextSibling,\n\ttagName: tagName,\n\tsetTextContent: setTextContent,\n\tsetAttribute: setAttribute\n});\n\n/*  */\n\nvar ref = {\n  create: function create (_, vnode) {\n    registerRef(vnode);\n  },\n  update: function update (oldVnode, vnode) {\n    if (oldVnode.data.ref !== vnode.data.ref) {\n      registerRef(oldVnode, true);\n      registerRef(vnode);\n    }\n  },\n  destroy: function destroy (vnode) {\n    registerRef(vnode, true);\n  }\n};\n\nfunction registerRef (vnode, isRemoval) {\n  var key = vnode.data.ref;\n  if (!key) { return }\n\n  var vm = vnode.context;\n  var ref = vnode.componentInstance || vnode.elm;\n  var refs = vm.$refs;\n  if (isRemoval) {\n    if (Array.isArray(refs[key])) {\n      remove(refs[key], ref);\n    } else if (refs[key] === ref) {\n      refs[key] = undefined;\n    }\n  } else {\n    if (vnode.data.refInFor) {\n      if (!Array.isArray(refs[key])) {\n        refs[key] = [ref];\n      } else if (refs[key].indexOf(ref) < 0) {\n        // $flow-disable-line\n        refs[key].push(ref);\n      }\n    } else {\n      refs[key] = ref;\n    }\n  }\n}\n\n/**\n * Virtual DOM patching algorithm based on Snabbdom by\n * Simon Friis Vindum (@paldepind)\n * Licensed under the MIT License\n * https://github.com/paldepind/snabbdom/blob/master/LICENSE\n *\n * modified by Evan You (@yyx990803)\n *\n\n/*\n * Not type-checking this because this file is perf-critical and the cost\n * of making flow understand it is not worth it.\n */\n\nvar emptyNode = new VNode('', {}, []);\n\nvar hooks = ['create', 'activate', 'update', 'remove', 'destroy'];\n\nfunction sameVnode (a, b) {\n  return (\n    a.key === b.key && (\n      (\n        a.tag === b.tag &&\n        a.isComment === b.isComment &&\n        isDef(a.data) === isDef(b.data) &&\n        sameInputType(a, b)\n      ) || (\n        isTrue(a.isAsyncPlaceholder) &&\n        a.asyncFactory === b.asyncFactory &&\n        isUndef(b.asyncFactory.error)\n      )\n    )\n  )\n}\n\n// Some browsers do not support dynamically changing type for <input>\n// so they need to be treated as different nodes\nfunction sameInputType (a, b) {\n  if (a.tag !== 'input') { return true }\n  var i;\n  var typeA = isDef(i = a.data) && isDef(i = i.attrs) && i.type;\n  var typeB = isDef(i = b.data) && isDef(i = i.attrs) && i.type;\n  return typeA === typeB\n}\n\nfunction createKeyToOldIdx (children, beginIdx, endIdx) {\n  var i, key;\n  var map = {};\n  for (i = beginIdx; i <= endIdx; ++i) {\n    key = children[i].key;\n    if (isDef(key)) { map[key] = i; }\n  }\n  return map\n}\n\nfunction createPatchFunction (backend) {\n  var i, j;\n  var cbs = {};\n\n  var modules = backend.modules;\n  var nodeOps = backend.nodeOps;\n\n  for (i = 0; i < hooks.length; ++i) {\n    cbs[hooks[i]] = [];\n    for (j = 0; j < modules.length; ++j) {\n      if (isDef(modules[j][hooks[i]])) {\n        cbs[hooks[i]].push(modules[j][hooks[i]]);\n      }\n    }\n  }\n\n  function emptyNodeAt (elm) {\n    return new VNode(nodeOps.tagName(elm).toLowerCase(), {}, [], undefined, elm)\n  }\n\n  function createRmCb (childElm, listeners) {\n    function remove$$1 () {\n      if (--remove$$1.listeners === 0) {\n        removeNode(childElm);\n      }\n    }\n    remove$$1.listeners = listeners;\n    return remove$$1\n  }\n\n  function removeNode (el) {\n    var parent = nodeOps.parentNode(el);\n    // element may have already been removed due to v-html / v-text\n    if (isDef(parent)) {\n      nodeOps.removeChild(parent, el);\n    }\n  }\n\n  var inPre = 0;\n  function createElm (vnode, insertedVnodeQueue, parentElm, refElm, nested) {\n    vnode.isRootInsert = !nested; // for transition enter check\n    if (createComponent(vnode, insertedVnodeQueue, parentElm, refElm)) {\n      return\n    }\n\n    var data = vnode.data;\n    var children = vnode.children;\n    var tag = vnode.tag;\n    if (isDef(tag)) {\n      vnode.elm = vnode.ns\n        ? nodeOps.createElementNS(vnode.ns, tag)\n        : nodeOps.createElement(tag, vnode);\n      setScope(vnode);\n\n      /* istanbul ignore if */\n      {\n        createChildren(vnode, children, insertedVnodeQueue);\n        if (isDef(data)) {\n          invokeCreateHooks(vnode, insertedVnodeQueue);\n        }\n        insert(parentElm, vnode.elm, refElm);\n      }\n\n      if (\"production\" !== 'production' && data && data.pre) {\n        inPre--;\n      }\n    } else if (isTrue(vnode.isComment)) {\n      vnode.elm = nodeOps.createComment(vnode.text);\n      insert(parentElm, vnode.elm, refElm);\n    } else {\n      vnode.elm = nodeOps.createTextNode(vnode.text);\n      insert(parentElm, vnode.elm, refElm);\n    }\n  }\n\n  function createComponent (vnode, insertedVnodeQueue, parentElm, refElm) {\n    var i = vnode.data;\n    if (isDef(i)) {\n      var isReactivated = isDef(vnode.componentInstance) && i.keepAlive;\n      if (isDef(i = i.hook) && isDef(i = i.init)) {\n        i(vnode, false /* hydrating */, parentElm, refElm);\n      }\n      // after calling the init hook, if the vnode is a child component\n      // it should've created a child instance and mounted it. the child\n      // component also has set the placeholder vnode's elm.\n      // in that case we can just return the element and be done.\n      if (isDef(vnode.componentInstance)) {\n        initComponent(vnode, insertedVnodeQueue);\n        if (isTrue(isReactivated)) {\n          reactivateComponent(vnode, insertedVnodeQueue, parentElm, refElm);\n        }\n        return true\n      }\n    }\n  }\n\n  function initComponent (vnode, insertedVnodeQueue) {\n    if (isDef(vnode.data.pendingInsert)) {\n      insertedVnodeQueue.push.apply(insertedVnodeQueue, vnode.data.pendingInsert);\n      vnode.data.pendingInsert = null;\n    }\n    vnode.elm = vnode.componentInstance.$el;\n    if (isPatchable(vnode)) {\n      invokeCreateHooks(vnode, insertedVnodeQueue);\n      setScope(vnode);\n    } else {\n      // empty component root.\n      // skip all element-related modules except for ref (#3455)\n      registerRef(vnode);\n      // make sure to invoke the insert hook\n      insertedVnodeQueue.push(vnode);\n    }\n  }\n\n  function reactivateComponent (vnode, insertedVnodeQueue, parentElm, refElm) {\n    var i;\n    // hack for #4339: a reactivated component with inner transition\n    // does not trigger because the inner node's created hooks are not called\n    // again. It's not ideal to involve module-specific logic in here but\n    // there doesn't seem to be a better way to do it.\n    var innerNode = vnode;\n    while (innerNode.componentInstance) {\n      innerNode = innerNode.componentInstance._vnode;\n      if (isDef(i = innerNode.data) && isDef(i = i.transition)) {\n        for (i = 0; i < cbs.activate.length; ++i) {\n          cbs.activate[i](emptyNode, innerNode);\n        }\n        insertedVnodeQueue.push(innerNode);\n        break\n      }\n    }\n    // unlike a newly created component,\n    // a reactivated keep-alive component doesn't insert itself\n    insert(parentElm, vnode.elm, refElm);\n  }\n\n  function insert (parent, elm, ref$$1) {\n    if (isDef(parent)) {\n      if (isDef(ref$$1)) {\n        if (ref$$1.parentNode === parent) {\n          nodeOps.insertBefore(parent, elm, ref$$1);\n        }\n      } else {\n        nodeOps.appendChild(parent, elm);\n      }\n    }\n  }\n\n  function createChildren (vnode, children, insertedVnodeQueue) {\n    if (Array.isArray(children)) {\n      for (var i = 0; i < children.length; ++i) {\n        createElm(children[i], insertedVnodeQueue, vnode.elm, null, true);\n      }\n    } else if (isPrimitive(vnode.text)) {\n      nodeOps.appendChild(vnode.elm, nodeOps.createTextNode(vnode.text));\n    }\n  }\n\n  function isPatchable (vnode) {\n    while (vnode.componentInstance) {\n      vnode = vnode.componentInstance._vnode;\n    }\n    return isDef(vnode.tag)\n  }\n\n  function invokeCreateHooks (vnode, insertedVnodeQueue) {\n    for (var i$1 = 0; i$1 < cbs.create.length; ++i$1) {\n      cbs.create[i$1](emptyNode, vnode);\n    }\n    i = vnode.data.hook; // Reuse variable\n    if (isDef(i)) {\n      if (isDef(i.create)) { i.create(emptyNode, vnode); }\n      if (isDef(i.insert)) { insertedVnodeQueue.push(vnode); }\n    }\n  }\n\n  // set scope id attribute for scoped CSS.\n  // this is implemented as a special case to avoid the overhead\n  // of going through the normal attribute patching process.\n  function setScope (vnode) {\n    var i;\n    var ancestor = vnode;\n    while (ancestor) {\n      if (isDef(i = ancestor.context) && isDef(i = i.$options._scopeId)) {\n        nodeOps.setAttribute(vnode.elm, i, '');\n      }\n      ancestor = ancestor.parent;\n    }\n    // for slot content they should also get the scopeId from the host instance.\n    if (isDef(i = activeInstance) &&\n      i !== vnode.context &&\n      isDef(i = i.$options._scopeId)\n    ) {\n      nodeOps.setAttribute(vnode.elm, i, '');\n    }\n  }\n\n  function addVnodes (parentElm, refElm, vnodes, startIdx, endIdx, insertedVnodeQueue) {\n    for (; startIdx <= endIdx; ++startIdx) {\n      createElm(vnodes[startIdx], insertedVnodeQueue, parentElm, refElm);\n    }\n  }\n\n  function invokeDestroyHook (vnode) {\n    var i, j;\n    var data = vnode.data;\n    if (isDef(data)) {\n      if (isDef(i = data.hook) && isDef(i = i.destroy)) { i(vnode); }\n      for (i = 0; i < cbs.destroy.length; ++i) { cbs.destroy[i](vnode); }\n    }\n    if (isDef(i = vnode.children)) {\n      for (j = 0; j < vnode.children.length; ++j) {\n        invokeDestroyHook(vnode.children[j]);\n      }\n    }\n  }\n\n  function removeVnodes (parentElm, vnodes, startIdx, endIdx) {\n    for (; startIdx <= endIdx; ++startIdx) {\n      var ch = vnodes[startIdx];\n      if (isDef(ch)) {\n        if (isDef(ch.tag)) {\n          removeAndInvokeRemoveHook(ch);\n          invokeDestroyHook(ch);\n        } else { // Text node\n          removeNode(ch.elm);\n        }\n      }\n    }\n  }\n\n  function removeAndInvokeRemoveHook (vnode, rm) {\n    if (isDef(rm) || isDef(vnode.data)) {\n      var i;\n      var listeners = cbs.remove.length + 1;\n      if (isDef(rm)) {\n        // we have a recursively passed down rm callback\n        // increase the listeners count\n        rm.listeners += listeners;\n      } else {\n        // directly removing\n        rm = createRmCb(vnode.elm, listeners);\n      }\n      // recursively invoke hooks on child component root node\n      if (isDef(i = vnode.componentInstance) && isDef(i = i._vnode) && isDef(i.data)) {\n        removeAndInvokeRemoveHook(i, rm);\n      }\n      for (i = 0; i < cbs.remove.length; ++i) {\n        cbs.remove[i](vnode, rm);\n      }\n      if (isDef(i = vnode.data.hook) && isDef(i = i.remove)) {\n        i(vnode, rm);\n      } else {\n        rm();\n      }\n    } else {\n      removeNode(vnode.elm);\n    }\n  }\n\n  function updateChildren (parentElm, oldCh, newCh, insertedVnodeQueue, removeOnly) {\n    var oldStartIdx = 0;\n    var newStartIdx = 0;\n    var oldEndIdx = oldCh.length - 1;\n    var oldStartVnode = oldCh[0];\n    var oldEndVnode = oldCh[oldEndIdx];\n    var newEndIdx = newCh.length - 1;\n    var newStartVnode = newCh[0];\n    var newEndVnode = newCh[newEndIdx];\n    var oldKeyToIdx, idxInOld, elmToMove, refElm;\n\n    // removeOnly is a special flag used only by <transition-group>\n    // to ensure removed elements stay in correct relative positions\n    // during leaving transitions\n    var canMove = !removeOnly;\n\n    while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {\n      if (isUndef(oldStartVnode)) {\n        oldStartVnode = oldCh[++oldStartIdx]; // Vnode has been moved left\n      } else if (isUndef(oldEndVnode)) {\n        oldEndVnode = oldCh[--oldEndIdx];\n      } else if (sameVnode(oldStartVnode, newStartVnode)) {\n        patchVnode(oldStartVnode, newStartVnode, insertedVnodeQueue);\n        oldStartVnode = oldCh[++oldStartIdx];\n        newStartVnode = newCh[++newStartIdx];\n      } else if (sameVnode(oldEndVnode, newEndVnode)) {\n        patchVnode(oldEndVnode, newEndVnode, insertedVnodeQueue);\n        oldEndVnode = oldCh[--oldEndIdx];\n        newEndVnode = newCh[--newEndIdx];\n      } else if (sameVnode(oldStartVnode, newEndVnode)) { // Vnode moved right\n        patchVnode(oldStartVnode, newEndVnode, insertedVnodeQueue);\n        canMove && nodeOps.insertBefore(parentElm, oldStartVnode.elm, nodeOps.nextSibling(oldEndVnode.elm));\n        oldStartVnode = oldCh[++oldStartIdx];\n        newEndVnode = newCh[--newEndIdx];\n      } else if (sameVnode(oldEndVnode, newStartVnode)) { // Vnode moved left\n        patchVnode(oldEndVnode, newStartVnode, insertedVnodeQueue);\n        canMove && nodeOps.insertBefore(parentElm, oldEndVnode.elm, oldStartVnode.elm);\n        oldEndVnode = oldCh[--oldEndIdx];\n        newStartVnode = newCh[++newStartIdx];\n      } else {\n        if (isUndef(oldKeyToIdx)) { oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx); }\n        idxInOld = isDef(newStartVnode.key) ? oldKeyToIdx[newStartVnode.key] : null;\n        if (isUndef(idxInOld)) { // New element\n          createElm(newStartVnode, insertedVnodeQueue, parentElm, oldStartVnode.elm);\n          newStartVnode = newCh[++newStartIdx];\n        } else {\n          elmToMove = oldCh[idxInOld];\n          /* istanbul ignore if */\n          if (\"production\" !== 'production' && !elmToMove) {\n            warn(\n              'It seems there are duplicate keys that is causing an update error. ' +\n              'Make sure each v-for item has a unique key.'\n            );\n          }\n          if (sameVnode(elmToMove, newStartVnode)) {\n            patchVnode(elmToMove, newStartVnode, insertedVnodeQueue);\n            oldCh[idxInOld] = undefined;\n            canMove && nodeOps.insertBefore(parentElm, elmToMove.elm, oldStartVnode.elm);\n            newStartVnode = newCh[++newStartIdx];\n          } else {\n            // same key but different element. treat as new element\n            createElm(newStartVnode, insertedVnodeQueue, parentElm, oldStartVnode.elm);\n            newStartVnode = newCh[++newStartIdx];\n          }\n        }\n      }\n    }\n    if (oldStartIdx > oldEndIdx) {\n      refElm = isUndef(newCh[newEndIdx + 1]) ? null : newCh[newEndIdx + 1].elm;\n      addVnodes(parentElm, refElm, newCh, newStartIdx, newEndIdx, insertedVnodeQueue);\n    } else if (newStartIdx > newEndIdx) {\n      removeVnodes(parentElm, oldCh, oldStartIdx, oldEndIdx);\n    }\n  }\n\n  function patchVnode (oldVnode, vnode, insertedVnodeQueue, removeOnly) {\n    if (oldVnode === vnode) {\n      return\n    }\n\n    var elm = vnode.elm = oldVnode.elm;\n\n    if (isTrue(oldVnode.isAsyncPlaceholder)) {\n      if (isDef(vnode.asyncFactory.resolved)) {\n        hydrate(oldVnode.elm, vnode, insertedVnodeQueue);\n      } else {\n        vnode.isAsyncPlaceholder = true;\n      }\n      return\n    }\n\n    // reuse element for static trees.\n    // note we only do this if the vnode is cloned -\n    // if the new node is not cloned it means the render functions have been\n    // reset by the hot-reload-api and we need to do a proper re-render.\n    if (isTrue(vnode.isStatic) &&\n      isTrue(oldVnode.isStatic) &&\n      vnode.key === oldVnode.key &&\n      (isTrue(vnode.isCloned) || isTrue(vnode.isOnce))\n    ) {\n      vnode.componentInstance = oldVnode.componentInstance;\n      return\n    }\n\n    var i;\n    var data = vnode.data;\n    if (isDef(data) && isDef(i = data.hook) && isDef(i = i.prepatch)) {\n      i(oldVnode, vnode);\n    }\n\n    var oldCh = oldVnode.children;\n    var ch = vnode.children;\n    if (isDef(data) && isPatchable(vnode)) {\n      for (i = 0; i < cbs.update.length; ++i) { cbs.update[i](oldVnode, vnode); }\n      if (isDef(i = data.hook) && isDef(i = i.update)) { i(oldVnode, vnode); }\n    }\n    if (isUndef(vnode.text)) {\n      if (isDef(oldCh) && isDef(ch)) {\n        if (oldCh !== ch) { updateChildren(elm, oldCh, ch, insertedVnodeQueue, removeOnly); }\n      } else if (isDef(ch)) {\n        if (isDef(oldVnode.text)) { nodeOps.setTextContent(elm, ''); }\n        addVnodes(elm, null, ch, 0, ch.length - 1, insertedVnodeQueue);\n      } else if (isDef(oldCh)) {\n        removeVnodes(elm, oldCh, 0, oldCh.length - 1);\n      } else if (isDef(oldVnode.text)) {\n        nodeOps.setTextContent(elm, '');\n      }\n    } else if (oldVnode.text !== vnode.text) {\n      nodeOps.setTextContent(elm, vnode.text);\n    }\n    if (isDef(data)) {\n      if (isDef(i = data.hook) && isDef(i = i.postpatch)) { i(oldVnode, vnode); }\n    }\n  }\n\n  function invokeInsertHook (vnode, queue, initial) {\n    // delay insert hooks for component root nodes, invoke them after the\n    // element is really inserted\n    if (isTrue(initial) && isDef(vnode.parent)) {\n      vnode.parent.data.pendingInsert = queue;\n    } else {\n      for (var i = 0; i < queue.length; ++i) {\n        queue[i].data.hook.insert(queue[i]);\n      }\n    }\n  }\n\n  var bailed = false;\n  // list of modules that can skip create hook during hydration because they\n  // are already rendered on the client or has no need for initialization\n  var isRenderedModule = makeMap('attrs,style,class,staticClass,staticStyle,key');\n\n  // Note: this is a browser-only function so we can assume elms are DOM nodes.\n  function hydrate (elm, vnode, insertedVnodeQueue) {\n    if (isTrue(vnode.isComment) && isDef(vnode.asyncFactory)) {\n      vnode.elm = elm;\n      vnode.isAsyncPlaceholder = true;\n      return true\n    }\n    vnode.elm = elm;\n    var tag = vnode.tag;\n    var data = vnode.data;\n    var children = vnode.children;\n    if (isDef(data)) {\n      if (isDef(i = data.hook) && isDef(i = i.init)) { i(vnode, true /* hydrating */); }\n      if (isDef(i = vnode.componentInstance)) {\n        // child component. it should have hydrated its own tree.\n        initComponent(vnode, insertedVnodeQueue);\n        return true\n      }\n    }\n    if (isDef(tag)) {\n      if (isDef(children)) {\n        // empty element, allow client to pick up and populate children\n        if (!elm.hasChildNodes()) {\n          createChildren(vnode, children, insertedVnodeQueue);\n        } else {\n          var childrenMatch = true;\n          var childNode = elm.firstChild;\n          for (var i$1 = 0; i$1 < children.length; i$1++) {\n            if (!childNode || !hydrate(childNode, children[i$1], insertedVnodeQueue)) {\n              childrenMatch = false;\n              break\n            }\n            childNode = childNode.nextSibling;\n          }\n          // if childNode is not null, it means the actual childNodes list is\n          // longer than the virtual children list.\n          if (!childrenMatch || childNode) {\n            if (\"production\" !== 'production' &&\n              typeof console !== 'undefined' &&\n              !bailed\n            ) {\n              bailed = true;\n              console.warn('Parent: ', elm);\n              console.warn('Mismatching childNodes vs. VNodes: ', elm.childNodes, children);\n            }\n            return false\n          }\n        }\n      }\n      if (isDef(data)) {\n        for (var key in data) {\n          if (!isRenderedModule(key)) {\n            invokeCreateHooks(vnode, insertedVnodeQueue);\n            break\n          }\n        }\n      }\n    } else if (elm.data !== vnode.text) {\n      elm.data = vnode.text;\n    }\n    return true\n  }\n\n  return function patch (oldVnode, vnode, hydrating, removeOnly, parentElm, refElm) {\n    if (isUndef(vnode)) {\n      if (isDef(oldVnode)) { invokeDestroyHook(oldVnode); }\n      return\n    }\n\n    var isInitialPatch = false;\n    var insertedVnodeQueue = [];\n\n    if (isUndef(oldVnode)) {\n      // empty mount (likely as component), create new root element\n      isInitialPatch = true;\n      createElm(vnode, insertedVnodeQueue, parentElm, refElm);\n    } else {\n      var isRealElement = isDef(oldVnode.nodeType);\n      if (!isRealElement && sameVnode(oldVnode, vnode)) {\n        // patch existing root node\n        patchVnode(oldVnode, vnode, insertedVnodeQueue, removeOnly);\n      } else {\n        if (isRealElement) {\n          // mounting to a real element\n          // check if this is server-rendered content and if we can perform\n          // a successful hydration.\n          if (oldVnode.nodeType === 1 && oldVnode.hasAttribute(SSR_ATTR)) {\n            oldVnode.removeAttribute(SSR_ATTR);\n            hydrating = true;\n          }\n          if (isTrue(hydrating)) {\n            if (hydrate(oldVnode, vnode, insertedVnodeQueue)) {\n              invokeInsertHook(vnode, insertedVnodeQueue, true);\n              return oldVnode\n            } else {}\n          }\n          // either not server-rendered, or hydration failed.\n          // create an empty node and replace it\n          oldVnode = emptyNodeAt(oldVnode);\n        }\n        // replacing existing element\n        var oldElm = oldVnode.elm;\n        var parentElm$1 = nodeOps.parentNode(oldElm);\n        createElm(\n          vnode,\n          insertedVnodeQueue,\n          // extremely rare edge case: do not insert if old element is in a\n          // leaving transition. Only happens when combining transition +\n          // keep-alive + HOCs. (#4590)\n          oldElm._leaveCb ? null : parentElm$1,\n          nodeOps.nextSibling(oldElm)\n        );\n\n        if (isDef(vnode.parent)) {\n          // component root element replaced.\n          // update parent placeholder node element, recursively\n          var ancestor = vnode.parent;\n          while (ancestor) {\n            ancestor.elm = vnode.elm;\n            ancestor = ancestor.parent;\n          }\n          if (isPatchable(vnode)) {\n            for (var i = 0; i < cbs.create.length; ++i) {\n              cbs.create[i](emptyNode, vnode.parent);\n            }\n          }\n        }\n\n        if (isDef(parentElm$1)) {\n          removeVnodes(parentElm$1, [oldVnode], 0, 0);\n        } else if (isDef(oldVnode.tag)) {\n          invokeDestroyHook(oldVnode);\n        }\n      }\n    }\n\n    invokeInsertHook(vnode, insertedVnodeQueue, isInitialPatch);\n    return vnode.elm\n  }\n}\n\n/*  */\n\n// import baseModules from 'core/vdom/modules/index'\n// const platformModules = []\n// import platformModules from 'web/runtime/modules/index'\n\n// the directive module should be applied last, after all\n// built-in modules have been applied.\n// const modules = platformModules.concat(baseModules)\nvar modules = [ref];\n\nvar corePatch = createPatchFunction({ nodeOps: nodeOps, modules: modules });\n\nfunction patch () {\n  corePatch.apply(this, arguments);\n  this.$updateDataToMP();\n}\n\nfunction callHook$1 (vm, hook, params) {\n  var handlers = vm.$options[hook];\n  if (hook === 'onError' && handlers) {\n    handlers = [handlers];\n  } else if (hook === 'onPageNotFound' && handlers) {\n    handlers = [handlers];\n  }\n\n  var ret;\n  if (handlers) {\n    for (var i = 0, j = handlers.length; i < j; i++) {\n      try {\n        ret = handlers[i].call(vm, params);\n      } catch (e) {\n        handleError(e, vm, (hook + \" hook\"));\n      }\n    }\n  }\n  if (vm._hasHookEvent) {\n    vm.$emit('hook:' + hook);\n  }\n\n  // for child\n  if (vm.$children.length) {\n    vm.$children.forEach(function (v) { return callHook$1(v, hook, params); });\n  }\n\n  return ret\n}\n\n// mpType 小程序实例的类型，可能的值是 'app', 'page'\n// rootVueVM 是 vue 的根组件实例，子组件中访问 this.$root 可得\nfunction getGlobalData (app, rootVueVM) {\n  var mp = rootVueVM.$mp;\n  if (app && app.globalData) {\n    mp.appOptions = app.globalData.appOptions;\n  }\n}\n\n// 格式化 properties 属性，并给每个属性加上 observer 方法\n\n// properties 的 一些类型 https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/component.html\n// properties: {\n//   paramA: Number,\n//   myProperty: { // 属性名\n//     type: String, // 类型（必填），目前接受的类型包括：String, Number, Boolean, Object, Array, null（表示任意类型）\n//     value: '', // 属性初始值（可选），如果未指定则会根据类型选择一个\n//     observer: function(newVal, oldVal, changedPath) {\n//        // 属性被改变时执行的函数（可选），也可以写成在methods段中定义的方法名字符串, 如：'_propertyChange'\n//        // 通常 newVal 就是新设置的数据， oldVal 是旧数据\n//     }\n//   },\n// }\n\n// props 的一些类型 https://cn.vuejs.org/v2/guide/components-props.html#ad\n// props: {\n//   // 基础的类型检查 (`null` 匹配任何类型)\n//   propA: Number,\n//   // 多个可能的类型\n//   propB: [String, Number],\n//   // 必填的字符串\n//   propC: {\n//     type: String,\n//     required: true\n//   },\n//   // 带有默认值的数字\n//   propD: {\n//     type: Number,\n//     default: 100\n//   },\n//   // 带有默认值的对象\n//   propE: {\n//     type: Object,\n//     // 对象或数组且一定会从一个工厂函数返回默认值\n//     default: function () {\n//       return { message: 'hello' }\n//     }\n//   },\n//   // 自定义验证函数\n//   propF: {\n//     validator: function (value) {\n//       // 这个值必须匹配下列字符串中的一个\n//       return ['success', 'warning', 'danger'].indexOf(value) !== -1\n//     }\n//   }\n// }\n\n// core/util/options\nfunction normalizeProps$1 (props, res, vm) {\n  if (!props) { return }\n  var i, val, name;\n  if (Array.isArray(props)) {\n    i = props.length;\n    while (i--) {\n      val = props[i];\n      if (typeof val === 'string') {\n        name = camelize(val);\n        res[name] = { type: null };\n      } else {}\n    }\n  } else if (isPlainObject(props)) {\n    for (var key in props) {\n      val = props[key];\n      name = camelize(key);\n      res[name] = isPlainObject(val)\n        ? val\n        : { type: val };\n    }\n  }\n\n  // fix vueProps to properties\n  for (var key$1 in res) {\n    if (res.hasOwnProperty(key$1)) {\n      var item = res[key$1];\n      if (item.default) {\n        item.value = item.default;\n      }\n      var oldObserver = item.observer;\n      item.observer = function (newVal, oldVal) {\n        vm[name] = newVal;\n        // 先修改值再触发原始的 observer，跟 watch 行为保持一致\n        if (typeof oldObserver === 'function') {\n          oldObserver.call(vm, newVal, oldVal);\n        }\n      };\n    }\n  }\n\n  return res\n}\n\nfunction normalizeProperties (vm) {\n  var properties = vm.$options.properties;\n  var vueProps = vm.$options.props;\n  var res = {};\n\n  normalizeProps$1(properties, res, vm);\n  normalizeProps$1(vueProps, res, vm);\n\n  return res\n}\n\n/**\n * 把 properties 中的属性 proxy 到 vm 上\n */\nfunction initMpProps (vm) {\n  var mpProps = vm._mpProps = {};\n  var keys = Object.keys(vm.$options.properties || {});\n  keys.forEach(function (key) {\n    if (!(key in vm)) {\n      proxy(vm, '_mpProps', key);\n      mpProps[key] = undefined; // for observe\n    }\n  });\n  observe(mpProps, true);\n}\n\nfunction initMP (mpType, next) {\n  var rootVueVM = this.$root;\n  if (!rootVueVM.$mp) {\n    rootVueVM.$mp = {};\n  }\n\n  var mp = rootVueVM.$mp;\n\n  // Please do not register multiple Pages\n  // if (mp.registered) {\n  if (mp.status) {\n    // 处理子组件的小程序生命周期\n    if (mpType === 'app') {\n      callHook$1(this, 'onLaunch', mp.appOptions);\n    } else {\n      callHook$1(this, 'onLoad', mp.query);\n      callHook$1(this, 'onReady');\n    }\n    return next()\n  }\n  // mp.registered = true\n\n  mp.mpType = mpType;\n  mp.status = 'register';\n\n  if (mpType === 'app') {\n    global.App({\n      // 页面的初始数据\n      globalData: {\n        appOptions: {}\n      },\n\n      handleProxy: function handleProxy (e) {\n        return rootVueVM.$handleProxyWithVue(e)\n      },\n\n      // Do something initial when launch.\n      onLaunch: function onLaunch (options) {\n        if ( options === void 0 ) options = {};\n\n        mp.app = this;\n        mp.status = 'launch';\n        this.globalData.appOptions = mp.appOptions = options;\n        callHook$1(rootVueVM, 'onLaunch', options);\n        next();\n      },\n\n      // Do something when app show.\n      onShow: function onShow (options) {\n        if ( options === void 0 ) options = {};\n\n        mp.status = 'show';\n        this.globalData.appOptions = mp.appOptions = options;\n        callHook$1(rootVueVM, 'onShow', options);\n      },\n\n      // Do something when app hide.\n      onHide: function onHide () {\n        mp.status = 'hide';\n        callHook$1(rootVueVM, 'onHide');\n      },\n\n      onError: function onError (err) {\n        callHook$1(rootVueVM, 'onError', err);\n      },\n\n      onPageNotFound: function onPageNotFound (err) {\n        callHook$1(rootVueVM, 'onPageNotFound', err);\n      }\n    });\n  } else if (mpType === 'component') {\n    initMpProps(rootVueVM);\n\n    global.Component({\n      // 小程序原生的组件属性\n      properties: normalizeProperties(rootVueVM),\n      // 页面的初始数据\n      data: {\n        $root: {}\n      },\n      methods: {\n        handleProxy: function handleProxy (e) {\n          return rootVueVM.$handleProxyWithVue(e)\n        }\n      },\n      // mp lifecycle for vue\n      // 组件生命周期函数，在组件实例进入页面节点树时执行，注意此时不能调用 setData\n      created: function created () {\n        mp.status = 'created';\n        mp.page = this;\n      },\n      // 组件生命周期函数，在组件实例进入页面节点树时执行\n      attached: function attached () {\n        mp.status = 'attached';\n        callHook$1(rootVueVM, 'attached');\n      },\n      // 组件生命周期函数，在组件布局完成后执行，此时可以获取节点信息（使用 SelectorQuery ）\n      ready: function ready () {\n        mp.status = 'ready';\n\n        callHook$1(rootVueVM, 'ready');\n        next();\n\n        // 只有页面需要 setData\n        rootVueVM.$nextTick(function () {\n          rootVueVM._initDataToMP();\n        });\n      },\n      // 组件生命周期函数，在组件实例被移动到节点树另一个位置时执行\n      moved: function moved () {\n        callHook$1(rootVueVM, 'moved');\n      },\n      // 组件生命周期函数，在组件实例被从页面节点树移除时执行\n      detached: function detached () {\n        mp.status = 'detached';\n        callHook$1(rootVueVM, 'detached');\n      }\n    });\n  } else {\n    var app = global.getApp();\n    global.Page({\n      // 页面的初始数据\n      data: {\n        $root: {}\n      },\n\n      handleProxy: function handleProxy (e) {\n        return rootVueVM.$handleProxyWithVue(e)\n      },\n\n      // mp lifecycle for vue\n      // 生命周期函数--监听页面加载\n      onLoad: function onLoad (query) {\n        mp.page = this;\n        mp.query = query;\n        mp.status = 'load';\n        getGlobalData(app, rootVueVM);\n        callHook$1(rootVueVM, 'onLoad', query);\n      },\n\n      // 生命周期函数--监听页面显示\n      onShow: function onShow () {\n        mp.page = this;\n        mp.status = 'show';\n        callHook$1(rootVueVM, 'onShow');\n\n        // 只有页面需要 setData\n        rootVueVM.$nextTick(function () {\n          rootVueVM._initDataToMP();\n        });\n      },\n\n      // 生命周期函数--监听页面初次渲染完成\n      onReady: function onReady () {\n        mp.status = 'ready';\n\n        callHook$1(rootVueVM, 'onReady');\n        next();\n      },\n\n      // 生命周期函数--监听页面隐藏\n      onHide: function onHide () {\n        mp.status = 'hide';\n        callHook$1(rootVueVM, 'onHide');\n        mp.page = null;\n      },\n\n      // 生命周期函数--监听页面卸载\n      onUnload: function onUnload () {\n        mp.status = 'unload';\n        callHook$1(rootVueVM, 'onUnload');\n        mp.page = null;\n      },\n\n      // 页面相关事件处理函数--监听用户下拉动作\n      onPullDownRefresh: function onPullDownRefresh () {\n        callHook$1(rootVueVM, 'onPullDownRefresh');\n      },\n\n      // 页面上拉触底事件的处理函数\n      onReachBottom: function onReachBottom () {\n        callHook$1(rootVueVM, 'onReachBottom');\n      },\n\n      // 用户点击右上角分享\n      onShareAppMessage: rootVueVM.$options.onShareAppMessage\n        ? function (options) { return callHook$1(rootVueVM, 'onShareAppMessage', options); } : null,\n\n      // Do something when page scroll\n      onPageScroll: function onPageScroll (options) {\n        callHook$1(rootVueVM, 'onPageScroll', options);\n      },\n\n      // 当前是 tab 页时，点击 tab 时触发\n      onTabItemTap: function onTabItemTap (options) {\n        callHook$1(rootVueVM, 'onTabItemTap', options);\n      }\n    });\n  }\n}\n\nvar updateDataTotal = 0; // 总共更新的数据量\nfunction diffLog (updateData) {\n  updateData = JSON.stringify(updateData);\n  if (!Vue$3._mpvueTraceTimer) {\n    Vue$3._mpvueTraceTimer = setTimeout(function () {\n      clearTimeout(Vue$3._mpvueTraceTimer);\n      updateDataTotal = (updateDataTotal / 1024).toFixed(1);\n      console.log('这次操作引发500ms内数据更新量:' + updateDataTotal + 'kb');\n      Vue$3._mpvueTraceTimer = 0;\n      updateDataTotal = 0;\n    }, 500);\n  } else if (Vue$3._mpvueTraceTimer) {\n    updateData = updateData.replace(/[^\\u0000-\\u00ff]/g, 'aa'); // 中文占2字节，中文替换成两个字母计算占用空间\n    updateDataTotal += updateData.length;\n  }\n}\n\nvar KEY_SEP$1 = '_';\n\nfunction getDeepData (keyList, viewData) {\n  if (keyList.length > 1) {\n    var _key = keyList.splice(0, 1);\n    var _viewData = viewData[_key];\n    if (_viewData) {\n      return getDeepData(keyList, _viewData)\n    } else {\n      return null\n    }\n  } else {\n    if (viewData[keyList[0]]) {\n      return viewData[keyList[0]]\n    } else {\n      return null\n    }\n  }\n}\n\nfunction compareAndSetDeepData (key, newData, vm, data, forceUpdate) {\n  // 比较引用类型数据\n  try {\n    var keyList = key.split('.');\n    // page.__viewData__老版小程序不存在，使用mpvue里绑的data比对\n    var oldData = getDeepData(keyList, vm.$root.$mp.page.data);\n    if (oldData === null || JSON.stringify(oldData) !== JSON.stringify(newData) || forceUpdate) {\n      data[key] = newData;\n    } else {\n      var keys = Object.keys(oldData);\n      keys.forEach(function (_key) {\n        var properties = Object.getOwnPropertyDescriptor(oldData, _key);\n        if (!properties['get'] && !properties['set']) {\n          data[key + '.' + _key] = newData[_key];\n        }\n      });\n    }\n  } catch (e) {\n    console.log(e, key, newData, vm);\n  }\n}\n\nfunction cleanKeyPath (vm) {\n  if (vm.__mpKeyPath) {\n    Object.keys(vm.__mpKeyPath).forEach(function (_key) {\n      delete vm.__mpKeyPath[_key]['__keyPath'];\n    });\n  }\n}\n\nfunction minifyDeepData (rootKey, originKey, vmData, data, _mpValueSet, vm) {\n  try {\n    if (vmData instanceof Array) {\n       // 数组\n      compareAndSetDeepData(rootKey + '.' + originKey, vmData, vm, data, true);\n    } else {\n      // Object\n      var _keyPathOnThis = {}; // 存储这层对象的keyPath\n      if (vmData.__keyPath && !vmData.__newReference) {\n        // 有更新列表 ，按照更新列表更新\n        _keyPathOnThis = vmData.__keyPath;\n        Object.keys(vmData).forEach(function (_key) {\n          if (vmData[_key] instanceof Object) {\n            // 引用类型 递归\n            if (_key === '__keyPath') {\n              return\n            }\n            minifyDeepData(rootKey + '.' + originKey, _key, vmData[_key], data, null, vm);\n          } else {\n            // 更新列表中的 加入data\n            if (_keyPathOnThis[_key] === true) {\n              if (originKey) {\n                data[rootKey + '.' + originKey + '.' + _key] = vmData[_key];\n              } else {\n                data[rootKey + '.' + _key] = vmData[_key];\n              }\n            }\n          }\n        });\n         // 根节点可能有父子引用同一个引用类型数据，依赖树都遍历完后清理\n        vm['__mpKeyPath'] = vm['__mpKeyPath'] || {};\n        vm['__mpKeyPath'][vmData.__ob__.dep.id] = vmData;\n      } else {\n        // 没有更新列表\n        compareAndSetDeepData(rootKey + '.' + originKey, vmData, vm, data);\n      }\n      // 标记是否是通过this.Obj = {} 赋值印发的改动，解决少更新问题#1305\n      def(vmData, '__newReference', false, false);\n    }\n  } catch (e) {\n    console.log(e, rootKey, originKey, vmData, data);\n  }\n}\n\nfunction getRootKey (vm, rootKey) {\n  if (!vm.$parent.$attrs) {\n    rootKey = '$root.0' + KEY_SEP$1 + rootKey;\n    return rootKey\n  } else {\n    rootKey = vm.$parent.$attrs.mpcomid + KEY_SEP$1 + rootKey;\n    return getRootKey(vm.$parent, rootKey)\n  }\n}\n\nfunction diffData (vm, data) {\n  var vmData = vm._data || {};\n  var vmProps = vm._props || {};\n  var rootKey = '';\n  if (!vm.$attrs) {\n    rootKey = '$root.0';\n  } else {\n    rootKey = getRootKey(vm, vm.$attrs.mpcomid);\n  }\n  Vue$3.nextTick(function () {\n    cleanKeyPath(vm);\n  });\n  // console.log(rootKey)\n\n  // 值类型变量不考虑优化，还是直接更新\n  var __keyPathOnThis = vmData.__keyPath || vm.__keyPath || {};\n  delete vm.__keyPath;\n  delete vmData.__keyPath;\n  delete vmProps.__keyPath;\n  if (vm._mpValueSet === 'done') {\n    // 第二次赋值才进行缩减操作\n    Object.keys(vmData).forEach(function (vmDataItemKey) {\n      if (vmData[vmDataItemKey] instanceof Object) {\n        // 引用类型\n        minifyDeepData(rootKey, vmDataItemKey, vmData[vmDataItemKey], data, vm._mpValueSet, vm);\n      } else if (vmData[vmDataItemKey] !== undefined) {\n        // _data上的值属性只有要更新的时候才赋值\n        if (__keyPathOnThis[vmDataItemKey] === true) {\n          data[rootKey + '.' + vmDataItemKey] = vmData[vmDataItemKey];\n        }\n      }\n    });\n\n    Object.keys(vmProps).forEach(function (vmPropsItemKey) {\n      if (vmProps[vmPropsItemKey] instanceof Object) {\n        // 引用类型\n        minifyDeepData(rootKey, vmPropsItemKey, vmProps[vmPropsItemKey], data, vm._mpValueSet, vm);\n      } else if (vmProps[vmPropsItemKey] !== undefined) {\n        data[rootKey + '.' + vmPropsItemKey] = vmProps[vmPropsItemKey];\n      }\n      // _props上的值属性只有要更新的时候才赋值\n    });\n\n    // 检查完data和props,最后补上_mpProps & _computedWatchers\n    var vmMpProps = vm._mpProps || {};\n    var vmComputedWatchers = vm._computedWatchers || {};\n    Object.keys(vmMpProps).forEach(function (mpItemKey) {\n      data[rootKey + '.' + mpItemKey] = vm[mpItemKey];\n    });\n    Object.keys(vmComputedWatchers).forEach(function (computedItemKey) {\n      data[rootKey + '.' + computedItemKey] = vm[computedItemKey];\n    });\n    // 更新的时候要删除$root.0:{},否则会覆盖原正确数据\n    delete data[rootKey];\n  }\n  if (vm._mpValueSet === undefined) {\n    // 第一次设置数据成功后，标记位置true,再更新到这个节点如果没有keyPath数组认为不需要更新\n    vm._mpValueSet = 'done';\n  }\n  if (Vue$3.config._mpTrace) {\n    // console.log('更新VM节点', vm)\n    // console.log('实际传到Page.setData数据', data)\n    diffLog(data);\n  }\n}\n\n// 节流方法，性能优化\n// 全局的命名约定，为了节省编译的包大小一律采取形象的缩写，说明如下。\n// $c === $child\n// $k === $comKey\n\n// 新型的被拍平的数据结构\n// {\n//   $root: {\n//     '1-1'{\n//       // ... data\n//     },\n//     '1.2-1': {\n//       // ... data1\n//     },\n//     '1.2-2': {\n//       // ... data2\n//     }\n//   }\n// }\n\nvar KEY_SEP = '_';\n\nfunction getVmData (vm) {\n  // 确保当前 vm 所有数据被同步\n  var dataKeys = [].concat(\n    Object.keys(vm._data || {}),\n    Object.keys(vm._props || {}),\n    Object.keys(vm._mpProps || {}),\n    Object.keys(vm._computedWatchers || {})\n  );\n  return dataKeys.reduce(function (res, key) {\n    res[key] = vm[key];\n    return res\n  }, {})\n}\n\nfunction getParentComKey (vm, res) {\n  if ( res === void 0 ) res = [];\n\n  var ref = vm || {};\n  var $parent = ref.$parent;\n  if (!$parent) { return res }\n  res.unshift(getComKey($parent));\n  if ($parent.$parent) {\n    return getParentComKey($parent, res)\n  }\n  return res\n}\n\nfunction formatVmData (vm) {\n  var $p = getParentComKey(vm).join(KEY_SEP);\n  var $k = $p + ($p ? KEY_SEP : '') + getComKey(vm);\n\n  // getVmData 这儿获取当前组件内的所有数据，包含 props、computed 的数据\n  // 改动 vue.runtime 所获的的核心能力\n  var data = Object.assign(getVmData(vm), { $k: $k, $kk: (\"\" + $k + KEY_SEP), $p: $p });\n  var key = '$root.' + $k;\n  var res = {};\n  res[key] = data;\n  return res\n}\n\nfunction collectVmData (vm, res) {\n  if ( res === void 0 ) res = {};\n\n  var vms = vm.$children;\n  if (vms && vms.length) {\n    vms.forEach(function (v) { return collectVmData(v, res); });\n  }\n  return Object.assign(res, formatVmData(vm))\n}\n\n/**\n * 频率控制 返回函数连续调用时，func 执行频率限定为 次 / wait\n * 自动合并 data\n *\n * @param  {function}   func      传入函数\n * @param  {number}     wait      表示时间窗口的间隔\n * @param  {object}     options   如果想忽略开始边界上的调用，传入{leading: false}。\n *                                如果想忽略结尾边界上的调用，传入{trailing: false}\n * @return {function}             返回客户调用函数\n */\nfunction throttle (func, wait, options) {\n  var context, args, result;\n  var timeout = null;\n  // 上次执行时间点\n  var previous = 0;\n  if (!options) { options = {}; }\n  // 延迟执行函数\n  function later () {\n    // 若设定了开始边界不执行选项，上次执行时间始终为0\n    previous = options.leading === false ? 0 : Date.now();\n    timeout = null;\n    result = func.apply(context, args);\n    if (!timeout) { context = args = null; }\n  }\n  return function (handle, data) {\n    var now = Date.now();\n    // 首次执行时，如果设定了开始边界不执行选项，将上次执行时间设定为当前时间。\n    if (!previous && options.leading === false) { previous = now; }\n    // 延迟执行时间间隔\n    var remaining = wait - (now - previous);\n    context = this;\n    args = args ? [handle, Object.assign(args[1], data)] : [handle, data];\n    // 延迟时间间隔remaining小于等于0，表示上次执行至此所间隔时间已经超过一个时间窗口\n    // remaining大于时间窗口wait，表示客户端系统时间被调整过\n    if (remaining <= 0 || remaining > wait) {\n      clearTimeout(timeout);\n      timeout = null;\n      previous = now;\n      result = func.apply(context, args);\n      if (!timeout) { context = args = null; }\n    // 如果延迟执行不存在，且没有设定结尾边界不执行选项\n    } else if (!timeout && options.trailing !== false) {\n      timeout = setTimeout(later, remaining);\n    }\n    return result\n  }\n}\n\n// 优化频繁的 setData: https://mp.weixin.qq.com/debug/wxadoc/dev/framework/performance/tips.html\nvar throttleSetData = throttle(function (handle, data) {\n  handle(data);\n}, 50);\n\nfunction getPage (vm) {\n  var rootVueVM = vm.$root;\n  var ref = rootVueVM.$mp || {};\n  var mpType = ref.mpType; if ( mpType === void 0 ) mpType = '';\n  var page = ref.page;\n\n  // 优化后台态页面进行 setData: https://mp.weixin.qq.com/debug/wxadoc/dev/framework/performance/tips.html\n  if (mpType === 'app' || !page || typeof page.setData !== 'function') {\n    return\n  }\n  return page\n}\n\n// 优化js变量动态变化时候引起全量更新\n// 优化每次 setData 都传递大量新数据\nfunction updateDataToMP () {\n  var page = getPage(this);\n  if (!page) {\n    return\n  }\n\n  var data = formatVmData(this);\n  diffData(this, data);\n  throttleSetData(page.setData.bind(page), data);\n}\n\nfunction initDataToMP () {\n  var page = getPage(this);\n  if (!page) {\n    return\n  }\n\n  var data = collectVmData(this.$root);\n  page.setData(data);\n}\n\n// 虚拟dom的compid与真实dom的comkey匹配，多层嵌套的先补齐虚拟dom的compid直到完全匹配为止\nfunction isVmKeyMatchedCompkey (k, comkey) {\n  if (!k || !comkey) {\n    return false\n  }\n  // 完全匹配 comkey = '1_0_1', k = '1_0_1'\n  // 部分匹配 comkey = '1_0_10_1', k = '1_0_10'\n  // k + KEY_SEP防止k = '1_0_1'误匹配comkey = '1_0_10_1'\n  return comkey === k || comkey.indexOf(k + KEY_SEP$2) === 0\n}\n\nfunction getVM (vm, comkeys) {\n  if ( comkeys === void 0 ) comkeys = [];\n\n  var keys = comkeys.slice(1);\n  if (!keys.length) { return vm }\n\n  // bugfix #1375: 虚拟dom的compid和真实dom的comkey在组件嵌套时匹配出错，comid会丢失前缀，需要从父节点补充\n  var comkey = keys.join(KEY_SEP$2);\n  var comidPrefix = '';\n  return keys.reduce(function (res, key) {\n    var len = res.$children.length;\n    for (var i = 0; i < len; i++) {\n      var v = res.$children[i];\n      var k = getComKey(v);\n      if (comidPrefix) {\n        k = comidPrefix + KEY_SEP$2 + k;\n      }\n      // 找到匹配的父节点\n      if (isVmKeyMatchedCompkey(k, comkey)) {\n        comidPrefix = k;\n        res = v;\n        return res\n      }\n    }\n    return res\n  }, vm)\n}\n\nfunction getHandle (vnode, eventid, eventTypes) {\n  if ( eventTypes === void 0 ) eventTypes = [];\n\n  var res = [];\n  if (!vnode || !vnode.tag) {\n    return res\n  }\n\n  var ref = vnode || {};\n  var data = ref.data; if ( data === void 0 ) data = {};\n  var children = ref.children; if ( children === void 0 ) children = [];\n  var componentInstance = ref.componentInstance;\n  if (componentInstance) {\n    // 增加 slot 情况的处理\n    // Object.values 会多增加几行编译后的代码\n    Object.keys(componentInstance.$slots).forEach(function (slotKey) {\n      var slot = componentInstance.$slots[slotKey];\n      var slots = Array.isArray(slot) ? slot : [slot];\n      slots.forEach(function (node) {\n        res = res.concat(getHandle(node, eventid, eventTypes));\n      });\n    });\n  } else {\n    // 避免遍历超出当前组件的 vm\n    children.forEach(function (node) {\n      res = res.concat(getHandle(node, eventid, eventTypes));\n    });\n  }\n\n  var attrs = data.attrs;\n  var on = data.on;\n  if (attrs && on && attrs['eventid'] === eventid) {\n    eventTypes.forEach(function (et) {\n      var h = on[et];\n      if (typeof h === 'function') {\n        res.push(h);\n      } else if (Array.isArray(h)) {\n        res = res.concat(h);\n      }\n    });\n    return res\n  }\n\n  return res\n}\n\nfunction getWebEventByMP (e) {\n  var type = e.type;\n  var timeStamp = e.timeStamp;\n  var touches = e.touches;\n  var detail = e.detail; if ( detail === void 0 ) detail = {};\n  var target = e.target; if ( target === void 0 ) target = {};\n  var currentTarget = e.currentTarget; if ( currentTarget === void 0 ) currentTarget = {};\n  var x = detail.x;\n  var y = detail.y;\n  var event = {\n    mp: e,\n    type: type,\n    timeStamp: timeStamp,\n    x: x,\n    y: y,\n    target: Object.assign({}, target, detail),\n    currentTarget: currentTarget,\n    stopPropagation: noop,\n    preventDefault: noop\n  };\n\n  if (touches && touches.length) {\n    Object.assign(event, touches[0]);\n    event.touches = touches;\n  }\n  return event\n}\n\nvar KEY_SEP$2 = '_';\nfunction handleProxyWithVue (e) {\n  var rootVueVM = this.$root;\n  var type = e.type;\n  var target = e.target; if ( target === void 0 ) target = {};\n  var currentTarget = e.currentTarget;\n  var ref = currentTarget || target;\n  var dataset = ref.dataset; if ( dataset === void 0 ) dataset = {};\n  var comkey = dataset.comkey; if ( comkey === void 0 ) comkey = '';\n  var eventid = dataset.eventid;\n  var vm = getVM(rootVueVM, comkey.split(KEY_SEP$2));\n\n  if (!vm) {\n    return\n  }\n\n  var webEventTypes = eventTypeMap[type] || [type];\n  var handles = getHandle(vm._vnode, eventid, webEventTypes);\n\n  // TODO, enevt 还需要处理更多\n  // https://developer.mozilla.org/zh-CN/docs/Web/API/Event\n  if (handles.length) {\n    var event = getWebEventByMP(e);\n    if (handles.length === 1) {\n      var result = handles[0](event);\n      return result\n    }\n    handles.forEach(function (h) { return h(event); });\n  }\n}\n\n// for platforms\n// import config from 'core/config'\n// install platform specific utils\nVue$3.config.mustUseProp = mustUseProp;\nVue$3.config.isReservedTag = isReservedTag;\nVue$3.config.isReservedAttr = isReservedAttr;\nVue$3.config.getTagNamespace = getTagNamespace;\nVue$3.config.isUnknownElement = isUnknownElement;\n\n// install platform patch function\nVue$3.prototype.__patch__ = patch;\n\n// public mount method\nVue$3.prototype.$mount = function (el, hydrating) {\n  var this$1 = this;\n\n  // el = el && inBrowser ? query(el) : undefined\n  // return mountComponent(this, el, hydrating)\n\n  // 初始化小程序生命周期相关\n  var options = this.$options;\n\n  if (options && (options.render || options.mpType)) {\n    var mpType = options.mpType; if ( mpType === void 0 ) mpType = 'page';\n    return this._initMP(mpType, function () {\n      return mountComponent(this$1, undefined, undefined)\n    })\n  } else {\n    return mountComponent(this, undefined, undefined)\n  }\n};\n\n// for mp\nVue$3.prototype._initMP = initMP;\n\nVue$3.prototype.$updateDataToMP = updateDataToMP;\nVue$3.prototype._initDataToMP = initDataToMP;\n\nVue$3.prototype.$handleProxyWithVue = handleProxyWithVue;\n\n/*  */\n\nreturn Vue$3;\n\n})));\n"
  },
  {
    "path": "packages/mpvue/package.json",
    "content": "{\n  \"name\": \"mpvue\",\n  \"version\": \"2.0.6\",\n  \"description\": \"Vue Runtime for mini program\",\n  \"main\": \"index.js\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/Meituan-Dianping/mpvue.git\"\n  },\n  \"keywords\": [\n    \"vue\",\n    \"compiler\",\n    \"mp\",\n    \"mp\",\n    \"antmp\"\n  ],\n  \"author\": \"meituan.com\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/Meituan-Dianping/mpvue/issues\"\n  },\n  \"homepage\": \"https://github.com/Meituan-Dianping/mpvue/\"\n}\n"
  },
  {
    "path": "packages/mpvue-template-compiler/README.md",
    "content": "# mpvue-template-compiler\n\n> This package is auto-generated. For pull requests please see [src/platforms/mp/entry-compiler.js](https://github.com/Meituan-Dianping/mpvue/blob/master/src/platforms/mp/entry-compiler.js).\n"
  },
  {
    "path": "packages/mpvue-template-compiler/build.js",
    "content": "'use strict';\n\nObject.defineProperty(exports, '__esModule', { value: true });\n\nfunction _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }\n\nvar deindent = _interopDefault(require('de-indent'));\nvar he = _interopDefault(require('he'));\nvar babel = _interopDefault(require('babel-core'));\nvar prettier = _interopDefault(require('prettier'));\nvar t = require('babel-types');\nvar generate = _interopDefault(require('babel-generator'));\nvar template = _interopDefault(require('babel-template'));\n\n/*  */\n\n// these helpers produces better vm code in JS engines due to their\n// explicitness and function inlining\n\n\n\n\n\n\n\n\n/**\n * Check if value is primitive\n */\n\n\n/**\n * Quick object check - this is primarily used to tell\n * Objects from primitive values when we know the value\n * is a JSON-compliant type.\n */\nfunction isObject (obj) {\n  return obj !== null && typeof obj === 'object'\n}\n\nvar _toString = Object.prototype.toString;\n\n/**\n * Strict object type check. Only returns true\n * for plain JavaScript objects.\n */\nfunction isPlainObject (obj) {\n  return _toString.call(obj) === '[object Object]'\n}\n\n\n\n/**\n * Check if val is a valid array index.\n */\nfunction isValidArrayIndex (val) {\n  var n = parseFloat(val);\n  return n >= 0 && Math.floor(n) === n && isFinite(val)\n}\n\n/**\n * Convert a value to a string that is actually rendered.\n */\n\n\n/**\n * Convert a input value to a number for persistence.\n * If the conversion fails, return original string.\n */\n\n\n/**\n * Make a map and return a function for checking if a key\n * is in that map.\n */\nfunction makeMap (\n  str,\n  expectsLowerCase\n) {\n  var map = Object.create(null);\n  var list = str.split(',');\n  for (var i = 0; i < list.length; i++) {\n    map[list[i]] = true;\n  }\n  return expectsLowerCase\n    ? function (val) { return map[val.toLowerCase()]; }\n    : function (val) { return map[val]; }\n}\n\n/**\n * Check if a tag is a built-in tag.\n */\nvar isBuiltInTag = makeMap('slot,component', true);\n\n/**\n * Check if a attribute is a reserved attribute.\n */\nvar isReservedAttribute = makeMap('key,ref,slot,is');\n\n/**\n * Remove an item from an array\n */\nfunction remove (arr, item) {\n  if (arr.length) {\n    var index = arr.indexOf(item);\n    if (index > -1) {\n      return arr.splice(index, 1)\n    }\n  }\n}\n\n/**\n * Check whether the object has the property.\n */\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\nfunction hasOwn (obj, key) {\n  return hasOwnProperty.call(obj, key)\n}\n\n/**\n * Create a cached version of a pure function.\n */\nfunction cached (fn) {\n  var cache = Object.create(null);\n  return (function cachedFn (str) {\n    var hit = cache[str];\n    return hit || (cache[str] = fn(str))\n  })\n}\n\n/**\n * Camelize a hyphen-delimited string.\n */\nvar camelizeRE = /-(\\w)/g;\nvar camelize = cached(function (str) {\n  return str.replace(camelizeRE, function (_, c) { return c ? c.toUpperCase() : ''; })\n});\n\n/**\n * Capitalize a string.\n */\n\n\n/**\n * Hyphenate a camelCase string.\n */\nvar hyphenateRE = /([^-])([A-Z])/g;\nvar hyphenate = cached(function (str) {\n  return str\n    .replace(hyphenateRE, '$1-$2')\n    .replace(hyphenateRE, '$1-$2')\n    .toLowerCase()\n});\n\n/**\n * Simple bind, faster than native\n */\n\n\n/**\n * Convert an Array-like object to a real Array.\n */\n\n\n/**\n * Mix properties into target object.\n */\nfunction extend (to, _from) {\n  for (var key in _from) {\n    to[key] = _from[key];\n  }\n  return to\n}\n\n/**\n * Merge an Array of Objects into a single Object.\n */\n\n\n/**\n * Perform no operation.\n * Stubbing args to make Flow happy without leaving useless transpiled code\n * with ...rest (https://flow.org/blog/2017/05/07/Strict-Function-Call-Arity/)\n */\nfunction noop (a, b, c) {}\n\n/**\n * Always return false.\n */\nvar no = function (a, b, c) { return false; };\n\n/**\n * Return same value\n */\nvar identity = function (_) { return _; };\n\n/**\n * Generate a static keys string from compiler modules.\n */\nfunction genStaticKeys (modules) {\n  return modules.reduce(function (keys, m) {\n    return keys.concat(m.staticKeys || [])\n  }, []).join(',')\n}\n\n/**\n * Check if two values are loosely equal - that is,\n * if they are plain objects, do they have the same shape?\n */\n\n\n\n\n/**\n * Ensure a function is called only once.\n */\n\n/*  */\n\nvar isUnaryTag = makeMap(\n  'area,base,br,col,embed,frame,hr,img,input,isindex,keygen,' +\n  'link,meta,param,source,track,wbr'\n);\n\n// Elements that you can, intentionally, leave open\n// (and which close themselves)\nvar canBeLeftOpenTag = makeMap(\n  'colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr,source'\n);\n\n// HTML5 tags https://html.spec.whatwg.org/multipage/indices.html#elements-3\n// Phrasing Content https://html.spec.whatwg.org/multipage/dom.html#phrasing-content\nvar isNonPhrasingTag = makeMap(\n  'address,article,aside,base,blockquote,body,caption,col,colgroup,dd,' +\n  'details,dialog,div,dl,dt,fieldset,figcaption,figure,footer,form,' +\n  'h1,h2,h3,h4,h5,h6,head,header,hgroup,hr,html,legend,li,menuitem,meta,' +\n  'optgroup,option,param,rp,rt,source,style,summary,tbody,td,tfoot,th,thead,' +\n  'title,tr,track'\n);\n\n/**\n * Not type-checking this file because it's mostly vendor code.\n */\n\n/*!\n * HTML Parser By John Resig (ejohn.org)\n * Modified by Juriy \"kangax\" Zaytsev\n * Original code by Erik Arvidsson, Mozilla Public License\n * http://erik.eae.net/simplehtmlparser/simplehtmlparser.js\n */\n\n// Regular Expressions for parsing tags and attributes\nvar singleAttrIdentifier = /([^\\s\"'<>/=]+)/;\nvar singleAttrAssign = /(?:=)/;\nvar singleAttrValues = [\n  // attr value double quotes\n  /\"([^\"]*)\"+/.source,\n  // attr value, single quotes\n  /'([^']*)'+/.source,\n  // attr value, no quotes\n  /([^\\s\"'=<>`]+)/.source\n];\nvar attribute = new RegExp(\n  '^\\\\s*' + singleAttrIdentifier.source +\n  '(?:\\\\s*(' + singleAttrAssign.source + ')' +\n  '\\\\s*(?:' + singleAttrValues.join('|') + '))?'\n);\n\n// could use https://www.w3.org/TR/1999/REC-xml-names-19990114/#NT-QName\n// but for Vue templates we can enforce a simple charset\nvar ncname = '[a-zA-Z_][\\\\w\\\\-\\\\.]*';\nvar qnameCapture = '((?:' + ncname + '\\\\:)?' + ncname + ')';\nvar startTagOpen = new RegExp('^<' + qnameCapture);\nvar startTagClose = /^\\s*(\\/?)>/;\nvar endTag = new RegExp('^<\\\\/' + qnameCapture + '[^>]*>');\nvar doctype = /^<!DOCTYPE [^>]+>/i;\nvar comment = /^<!--/;\nvar conditionalComment = /^<!\\[/;\n\nvar IS_REGEX_CAPTURING_BROKEN = false;\n'x'.replace(/x(.)?/g, function (m, g) {\n  IS_REGEX_CAPTURING_BROKEN = g === '';\n});\n\n// Special Elements (can contain anything)\nvar isPlainTextElement = makeMap('script,style,textarea', true);\nvar reCache = {};\n\nvar decodingMap = {\n  '&lt;': '<',\n  '&gt;': '>',\n  '&quot;': '\"',\n  '&amp;': '&',\n  '&#10;': '\\n'\n};\nvar encodedAttr = /&(?:lt|gt|quot|amp);/g;\nvar encodedAttrWithNewLines = /&(?:lt|gt|quot|amp|#10);/g;\n\n// #5992\nvar isIgnoreNewlineTag = makeMap('pre,textarea', true);\nvar shouldIgnoreFirstNewline = function (tag, html) { return tag && isIgnoreNewlineTag(tag) && html[0] === '\\n'; };\n\nfunction decodeAttr (value, shouldDecodeNewlines) {\n  var re = shouldDecodeNewlines ? encodedAttrWithNewLines : encodedAttr;\n  return value.replace(re, function (match) { return decodingMap[match]; })\n}\n\nfunction parseHTML (html, options) {\n  var stack = [];\n  var expectHTML = options.expectHTML;\n  var isUnaryTag$$1 = options.isUnaryTag || no;\n  var canBeLeftOpenTag$$1 = options.canBeLeftOpenTag || no;\n  var index = 0;\n  var last, lastTag;\n  while (html) {\n    last = html;\n    // Make sure we're not in a plaintext content element like script/style\n    if (!lastTag || !isPlainTextElement(lastTag)) {\n      if (shouldIgnoreFirstNewline(lastTag, html)) {\n        advance(1);\n      }\n      var textEnd = html.indexOf('<');\n      if (textEnd === 0) {\n        // Comment:\n        if (comment.test(html)) {\n          var commentEnd = html.indexOf('-->');\n\n          if (commentEnd >= 0) {\n            if (options.shouldKeepComment) {\n              options.comment(html.substring(4, commentEnd));\n            }\n            advance(commentEnd + 3);\n            continue\n          }\n        }\n\n        // http://en.wikipedia.org/wiki/Conditional_comment#Downlevel-revealed_conditional_comment\n        if (conditionalComment.test(html)) {\n          var conditionalEnd = html.indexOf(']>');\n\n          if (conditionalEnd >= 0) {\n            advance(conditionalEnd + 2);\n            continue\n          }\n        }\n\n        // Doctype:\n        var doctypeMatch = html.match(doctype);\n        if (doctypeMatch) {\n          advance(doctypeMatch[0].length);\n          continue\n        }\n\n        // End tag:\n        var endTagMatch = html.match(endTag);\n        if (endTagMatch) {\n          var curIndex = index;\n          advance(endTagMatch[0].length);\n          parseEndTag(endTagMatch[1], curIndex, index);\n          continue\n        }\n\n        // Start tag:\n        var startTagMatch = parseStartTag();\n        if (startTagMatch) {\n          handleStartTag(startTagMatch);\n          continue\n        }\n      }\n\n      var text = (void 0), rest = (void 0), next = (void 0);\n      if (textEnd >= 0) {\n        rest = html.slice(textEnd);\n        while (\n          !endTag.test(rest) &&\n          !startTagOpen.test(rest) &&\n          !comment.test(rest) &&\n          !conditionalComment.test(rest)\n        ) {\n          // < in plain text, be forgiving and treat it as text\n          next = rest.indexOf('<', 1);\n          if (next < 0) { break }\n          textEnd += next;\n          rest = html.slice(textEnd);\n        }\n        text = html.substring(0, textEnd);\n        advance(textEnd);\n      }\n\n      if (textEnd < 0) {\n        text = html;\n        html = '';\n      }\n\n      if (options.chars && text) {\n        options.chars(text);\n      }\n    } else {\n      var endTagLength = 0;\n      var stackedTag = lastTag.toLowerCase();\n      var reStackedTag = reCache[stackedTag] || (reCache[stackedTag] = new RegExp('([\\\\s\\\\S]*?)(</' + stackedTag + '[^>]*>)', 'i'));\n      var rest$1 = html.replace(reStackedTag, function (all, text, endTag) {\n        endTagLength = endTag.length;\n        if (!isPlainTextElement(stackedTag) && stackedTag !== 'noscript') {\n          text = text\n            .replace(/<!--([\\s\\S]*?)-->/g, '$1')\n            .replace(/<!\\[CDATA\\[([\\s\\S]*?)]]>/g, '$1');\n        }\n        if (shouldIgnoreFirstNewline(stackedTag, text)) {\n          text = text.slice(1);\n        }\n        if (options.chars) {\n          options.chars(text);\n        }\n        return ''\n      });\n      index += html.length - rest$1.length;\n      html = rest$1;\n      parseEndTag(stackedTag, index - endTagLength, index);\n    }\n\n    if (html === last) {\n      options.chars && options.chars(html);\n      if (process.env.NODE_ENV !== 'production' && !stack.length && options.warn) {\n        options.warn((\"Mal-formatted tag at end of template: \\\"\" + html + \"\\\"\"));\n      }\n      break\n    }\n  }\n\n  // Clean up any remaining tags\n  parseEndTag();\n\n  function advance (n) {\n    index += n;\n    html = html.substring(n);\n  }\n\n  function parseStartTag () {\n    var start = html.match(startTagOpen);\n    if (start) {\n      var match = {\n        tagName: start[1],\n        attrs: [],\n        start: index\n      };\n      advance(start[0].length);\n      var end, attr;\n      while (!(end = html.match(startTagClose)) && (attr = html.match(attribute))) {\n        advance(attr[0].length);\n        match.attrs.push(attr);\n      }\n      if (end) {\n        match.unarySlash = end[1];\n        advance(end[0].length);\n        match.end = index;\n        return match\n      }\n    }\n  }\n\n  function handleStartTag (match) {\n    var tagName = match.tagName;\n    var unarySlash = match.unarySlash;\n\n    if (expectHTML) {\n      if (lastTag === 'p' && isNonPhrasingTag(tagName)) {\n        parseEndTag(lastTag);\n      }\n      if (canBeLeftOpenTag$$1(tagName) && lastTag === tagName) {\n        parseEndTag(tagName);\n      }\n    }\n\n    var unary = isUnaryTag$$1(tagName) || !!unarySlash;\n\n    var l = match.attrs.length;\n    var attrs = new Array(l);\n    for (var i = 0; i < l; i++) {\n      var args = match.attrs[i];\n      // hackish work around FF bug https://bugzilla.mozilla.org/show_bug.cgi?id=369778\n      if (IS_REGEX_CAPTURING_BROKEN && args[0].indexOf('\"\"') === -1) {\n        if (args[3] === '') { delete args[3]; }\n        if (args[4] === '') { delete args[4]; }\n        if (args[5] === '') { delete args[5]; }\n      }\n      var value = args[3] || args[4] || args[5] || '';\n      attrs[i] = {\n        name: args[1],\n        value: decodeAttr(\n          value,\n          options.shouldDecodeNewlines\n        )\n      };\n    }\n\n    if (!unary) {\n      stack.push({ tag: tagName, lowerCasedTag: tagName.toLowerCase(), attrs: attrs });\n      lastTag = tagName;\n    }\n\n    if (options.start) {\n      options.start(tagName, attrs, unary, match.start, match.end);\n    }\n  }\n\n  function parseEndTag (tagName, start, end) {\n    var pos, lowerCasedTagName;\n    if (start == null) { start = index; }\n    if (end == null) { end = index; }\n\n    if (tagName) {\n      lowerCasedTagName = tagName.toLowerCase();\n    }\n\n    // Find the closest opened tag of the same type\n    if (tagName) {\n      for (pos = stack.length - 1; pos >= 0; pos--) {\n        if (stack[pos].lowerCasedTag === lowerCasedTagName) {\n          break\n        }\n      }\n    } else {\n      // If no tag name is provided, clean shop\n      pos = 0;\n    }\n\n    if (pos >= 0) {\n      // Close all the open elements, up the stack\n      for (var i = stack.length - 1; i >= pos; i--) {\n        if (process.env.NODE_ENV !== 'production' &&\n          (i > pos || !tagName) &&\n          options.warn\n        ) {\n          options.warn(\n            (\"tag <\" + (stack[i].tag) + \"> has no matching end tag.\")\n          );\n        }\n        if (options.end) {\n          options.end(stack[i].tag, start, end);\n        }\n      }\n\n      // Remove the open elements from the stack\n      stack.length = pos;\n      lastTag = pos && stack[pos - 1].tag;\n    } else if (lowerCasedTagName === 'br') {\n      if (options.start) {\n        options.start(tagName, [], true, start, end);\n      }\n    } else if (lowerCasedTagName === 'p') {\n      if (options.start) {\n        options.start(tagName, [], false, start, end);\n      }\n      if (options.end) {\n        options.end(tagName, start, end);\n      }\n    }\n  }\n}\n\n/*  */\n\nvar splitRE = /\\r?\\n/g;\nvar replaceRE = /./g;\nvar isSpecialTag = makeMap('script,style,template', true);\n\n\n\n/**\n * Parse a single-file component (*.vue) file into an SFC Descriptor Object.\n */\nfunction parseComponent (\n  content,\n  options\n ) {\n  if ( options === void 0 ) options = {};\n\n  var sfc = {\n    template: null,\n    script: null,\n    styles: [],\n    customBlocks: []\n  };\n  var depth = 0;\n  var currentBlock = null;\n\n  function start (\n    tag,\n    attrs,\n    unary,\n    start,\n    end\n  ) {\n    if (depth === 0) {\n      currentBlock = {\n        type: tag,\n        content: '',\n        start: end,\n        attrs: attrs.reduce(function (cumulated, ref) {\n          var name = ref.name;\n          var value = ref.value;\n\n          cumulated[name] = value || true;\n          return cumulated\n        }, Object.create(null))\n      };\n      if (isSpecialTag(tag)) {\n        checkAttrs(currentBlock, attrs);\n        if (tag === 'style') {\n          sfc.styles.push(currentBlock);\n        } else {\n          sfc[tag] = currentBlock;\n        }\n      } else { // custom blocks\n        sfc.customBlocks.push(currentBlock);\n      }\n    }\n    if (!unary) {\n      depth++;\n    }\n  }\n\n  function checkAttrs (block, attrs) {\n    for (var i = 0; i < attrs.length; i++) {\n      var attr = attrs[i];\n      if (attr.name === 'lang') {\n        block.lang = attr.value;\n      }\n      if (attr.name === 'scoped') {\n        block.scoped = true;\n      }\n      if (attr.name === 'module') {\n        block.module = attr.value || true;\n      }\n      if (attr.name === 'src') {\n        block.src = attr.value;\n      }\n    }\n  }\n\n  function end (tag, start, end) {\n    if (depth === 1 && currentBlock) {\n      currentBlock.end = start;\n      var text = deindent(content.slice(currentBlock.start, currentBlock.end));\n      // pad content so that linters and pre-processors can output correct\n      // line numbers in errors and warnings\n      if (currentBlock.type !== 'template' && options.pad) {\n        text = padContent(currentBlock, options.pad) + text;\n      }\n      currentBlock.content = text;\n      currentBlock = null;\n    }\n    depth--;\n  }\n\n  function padContent (block, pad) {\n    if (pad === 'space') {\n      return content.slice(0, block.start).replace(replaceRE, ' ')\n    } else {\n      var offset = content.slice(0, block.start).split(splitRE).length;\n      var padChar = block.type === 'script' && !block.lang\n        ? '//\\n'\n        : '\\n';\n      return Array(offset).join(padChar)\n    }\n  }\n\n  parseHTML(content, {\n    start: start,\n    end: end\n  });\n\n  return sfc\n}\n\n/* globals renderer */\n\nvar isPreTag = function (tag) { return tag === 'pre'; };\n\nvar isReservedTag = makeMap(\n  'template,script,style,element,content,slot,link,meta,svg,view,' +\n  'a,div,img,image,text,span,richtext,input,switch,textarea,spinner,select,' +\n  'slider,slider-neighbor,indicator,trisition,trisition-group,canvas,' +\n  'list,cell,header,loading,loading-indicator,refresh,scrollable,scroller,' +\n  'video,web,embed,tabbar,tabheader,datepicker,timepicker,marquee,countdown',\n  true\n);\n\n// these are reserved for web because they are directly compiled away\n// during template compilation\nvar isReservedAttr = makeMap('style,class');\n\n// Elements that you can, intentionally, leave open (and which close themselves)\n// more flexable than web\nvar canBeLeftOpenTag$1 = makeMap(\n  'web,spinner,switch,video,textarea,canvas,' +\n  'indicator,marquee,countdown',\n  true\n);\n\nvar isUnaryTag$1 = makeMap(\n  'embed,img,image,input,link,meta',\n  true\n);\n\nfunction mustUseProp () { /* console.log('mustUseProp') */ }\nfunction getTagNamespace () { /* console.log('getTagNamespace') */ }\n\n\n\n\n\n\n// 用于小程序的 event type 到 web 的 event\n\n/*  */\n\nvar validDivisionCharRE = /[\\w).+\\-_$\\]]/;\n\nfunction parseFilters (exp) {\n  var inSingle = false;\n  var inDouble = false;\n  var inTemplateString = false;\n  var inRegex = false;\n  var curly = 0;\n  var square = 0;\n  var paren = 0;\n  var lastFilterIndex = 0;\n  var c, prev, i, expression, filters;\n\n  for (i = 0; i < exp.length; i++) {\n    prev = c;\n    c = exp.charCodeAt(i);\n    if (inSingle) {\n      if (c === 0x27 && prev !== 0x5C) { inSingle = false; }\n    } else if (inDouble) {\n      if (c === 0x22 && prev !== 0x5C) { inDouble = false; }\n    } else if (inTemplateString) {\n      if (c === 0x60 && prev !== 0x5C) { inTemplateString = false; }\n    } else if (inRegex) {\n      if (c === 0x2f && prev !== 0x5C) { inRegex = false; }\n    } else if (\n      c === 0x7C && // pipe\n      exp.charCodeAt(i + 1) !== 0x7C &&\n      exp.charCodeAt(i - 1) !== 0x7C &&\n      !curly && !square && !paren\n    ) {\n      if (expression === undefined) {\n        // first filter, end of expression\n        lastFilterIndex = i + 1;\n        expression = exp.slice(0, i).trim();\n      } else {\n        pushFilter();\n      }\n    } else {\n      switch (c) {\n        case 0x22: inDouble = true; break         // \"\n        case 0x27: inSingle = true; break         // '\n        case 0x60: inTemplateString = true; break // `\n        case 0x28: paren++; break                 // (\n        case 0x29: paren--; break                 // )\n        case 0x5B: square++; break                // [\n        case 0x5D: square--; break                // ]\n        case 0x7B: curly++; break                 // {\n        case 0x7D: curly--; break                 // }\n      }\n      if (c === 0x2f) { // /\n        var j = i - 1;\n        var p = (void 0);\n        // find first non-whitespace prev char\n        for (; j >= 0; j--) {\n          p = exp.charAt(j);\n          if (p !== ' ') { break }\n        }\n        if (!p || !validDivisionCharRE.test(p)) {\n          inRegex = true;\n        }\n      }\n    }\n  }\n\n  if (expression === undefined) {\n    expression = exp.slice(0, i).trim();\n  } else if (lastFilterIndex !== 0) {\n    pushFilter();\n  }\n\n  function pushFilter () {\n    (filters || (filters = [])).push(exp.slice(lastFilterIndex, i).trim());\n    lastFilterIndex = i + 1;\n  }\n\n  if (filters) {\n    for (i = 0; i < filters.length; i++) {\n      expression = wrapFilter(expression, filters[i]);\n    }\n  }\n\n  return expression\n}\n\nfunction wrapFilter (exp, filter) {\n  var i = filter.indexOf('(');\n  if (i < 0) {\n    // _f: resolveFilter\n    return (\"_f(\\\"\" + filter + \"\\\")(\" + exp + \")\")\n  } else {\n    var name = filter.slice(0, i);\n    var args = filter.slice(i + 1);\n    return (\"_f(\\\"\" + name + \"\\\")(\" + exp + \",\" + args)\n  }\n}\n\n/*  */\n\nvar defaultTagRE = /\\{\\{((?:.|\\n)+?)\\}\\}/g;\nvar regexEscapeRE = /[-.*+?^${}()|[\\]\\/\\\\]/g;\n\nvar buildRegex = cached(function (delimiters) {\n  var open = delimiters[0].replace(regexEscapeRE, '\\\\$&');\n  var close = delimiters[1].replace(regexEscapeRE, '\\\\$&');\n  return new RegExp(open + '((?:.|\\\\n)+?)' + close, 'g')\n});\n\nfunction parseText (\n  text,\n  delimiters\n) {\n  var tagRE = delimiters ? buildRegex(delimiters) : defaultTagRE;\n  if (!tagRE.test(text)) {\n    return\n  }\n  var tokens = [];\n  var lastIndex = tagRE.lastIndex = 0;\n  var match, index;\n  while ((match = tagRE.exec(text))) {\n    index = match.index;\n    // push text token\n    if (index > lastIndex) {\n      tokens.push(JSON.stringify(text.slice(lastIndex, index)));\n    }\n    // tag token\n    var exp = parseFilters(match[1].trim());\n    tokens.push((\"_s(\" + exp + \")\"));\n    lastIndex = index + match[0].length;\n  }\n  if (lastIndex < text.length) {\n    tokens.push(JSON.stringify(text.slice(lastIndex)));\n  }\n  return tokens.join('+')\n}\n\n/*  */\n\nfunction baseWarn (msg) {\n  console.error((\"[Vue compiler]: \" + msg));\n}\n\nfunction pluckModuleFunction (\n  modules,\n  key\n) {\n  return modules\n    ? modules.map(function (m) { return m[key]; }).filter(function (_) { return _; })\n    : []\n}\n\nfunction addProp (el, name, value) {\n  (el.props || (el.props = [])).push({ name: name, value: value });\n}\n\nfunction addAttr (el, name, value) {\n  (el.attrs || (el.attrs = [])).push({ name: name, value: value });\n}\n\nfunction addDirective (\n  el,\n  name,\n  rawName,\n  value,\n  arg,\n  modifiers\n) {\n  (el.directives || (el.directives = [])).push({ name: name, rawName: rawName, value: value, arg: arg, modifiers: modifiers });\n}\n\nfunction addHandler (\n  el,\n  name,\n  value,\n  modifiers,\n  important,\n  warn\n) {\n  // warn prevent and passive modifier\n  /* istanbul ignore if */\n  if (\n    process.env.NODE_ENV !== 'production' && warn &&\n    modifiers && modifiers.prevent && modifiers.passive\n  ) {\n    warn(\n      'passive and prevent can\\'t be used together. ' +\n      'Passive handler can\\'t prevent default event.'\n    );\n  }\n  // check capture modifier\n  if (modifiers && modifiers.capture) {\n    delete modifiers.capture;\n    name = '!' + name; // mark the event as captured\n  }\n  if (modifiers && modifiers.once) {\n    delete modifiers.once;\n    name = '~' + name; // mark the event as once\n  }\n  /* istanbul ignore if */\n  if (modifiers && modifiers.passive) {\n    delete modifiers.passive;\n    name = '&' + name; // mark the event as passive\n  }\n  var events;\n  if (modifiers && modifiers.native) {\n    delete modifiers.native;\n    events = el.nativeEvents || (el.nativeEvents = {});\n  } else {\n    events = el.events || (el.events = {});\n  }\n  var newHandler = { value: value, modifiers: modifiers };\n  var handlers = events[name];\n  /* istanbul ignore if */\n  if (Array.isArray(handlers)) {\n    important ? handlers.unshift(newHandler) : handlers.push(newHandler);\n  } else if (handlers) {\n    events[name] = important ? [newHandler, handlers] : [handlers, newHandler];\n  } else {\n    events[name] = newHandler;\n  }\n}\n\nfunction getBindingAttr (\n  el,\n  name,\n  getStatic\n) {\n  var dynamicValue =\n    getAndRemoveAttr(el, ':' + name) ||\n    getAndRemoveAttr(el, 'v-bind:' + name);\n  if (dynamicValue != null) {\n    return parseFilters(dynamicValue)\n  } else if (getStatic !== false) {\n    var staticValue = getAndRemoveAttr(el, name);\n    if (staticValue != null) {\n      return JSON.stringify(staticValue)\n    }\n  }\n}\n\nfunction getAndRemoveAttr (el, name) {\n  var val;\n  if ((val = el.attrsMap[name]) != null) {\n    var list = el.attrsList;\n    for (var i = 0, l = list.length; i < l; i++) {\n      if (list[i].name === name) {\n        list.splice(i, 1);\n        break\n      }\n    }\n  }\n  return val\n}\n\n/*  */\n\nfunction transformNode (el, options) {\n  var warn = options.warn || baseWarn;\n  var staticClass = getAndRemoveAttr(el, 'class');\n  if (process.env.NODE_ENV !== 'production' && staticClass) {\n    var expression = parseText(staticClass, options.delimiters);\n    if (expression) {\n      warn(\n        \"class=\\\"\" + staticClass + \"\\\": \" +\n        'Interpolation inside attributes has been removed. ' +\n        'Use v-bind or the colon shorthand instead. For example, ' +\n        'instead of <div class=\"{{ val }}\">, use <div :class=\"val\">.'\n      );\n    }\n  }\n  if (staticClass) {\n    el.staticClass = JSON.stringify(staticClass);\n  }\n  var classBinding = getBindingAttr(el, 'class', false /* getStatic */);\n  if (classBinding) {\n    el.classBinding = classBinding;\n  }\n}\n\nfunction genData (el) {\n  var data = '';\n  if (el.staticClass) {\n    data += \"staticClass:\" + (el.staticClass) + \",\";\n  }\n  if (el.classBinding) {\n    data += \"class:\" + (el.classBinding) + \",\";\n  }\n  return data\n}\n\nvar klass = {\n  staticKeys: ['staticClass'],\n  transformNode: transformNode,\n  genData: genData\n};\n\n/*  */\n\nvar parseStyleText = cached(function (cssText) {\n  var res = {};\n  var listDelimiter = /;(?![^(]*\\))/g;\n  var propertyDelimiter = /:(.+)/;\n  cssText.split(listDelimiter).forEach(function (item) {\n    if (item) {\n      var tmp = item.split(propertyDelimiter);\n      tmp.length > 1 && (res[tmp[0].trim()] = tmp[1].trim());\n    }\n  });\n  return res\n});\n\n// normalize possible array / string values into Object\n\n\n/**\n * parent component style should be after child's\n * so that parent component's style could override it\n */\n\n/*  */\n\nfunction transformNode$1 (el, options) {\n  var warn = options.warn || baseWarn;\n  var staticStyle = getAndRemoveAttr(el, 'style');\n  if (staticStyle) {\n    /* istanbul ignore if */\n    if (process.env.NODE_ENV !== 'production') {\n      var expression = parseText(staticStyle, options.delimiters);\n      if (expression) {\n        warn(\n          \"style=\\\"\" + staticStyle + \"\\\": \" +\n          'Interpolation inside attributes has been removed. ' +\n          'Use v-bind or the colon shorthand instead. For example, ' +\n          'instead of <div style=\"{{ val }}\">, use <div :style=\"val\">.'\n        );\n      }\n    }\n    el.staticStyle = JSON.stringify(parseStyleText(staticStyle));\n  }\n\n  var styleBinding = getBindingAttr(el, 'style', false /* getStatic */);\n  if (styleBinding) {\n    el.styleBinding = styleBinding;\n  }\n}\n\nfunction genData$1 (el) {\n  var data = '';\n  if (el.staticStyle) {\n    data += \"staticStyle:\" + (el.staticStyle) + \",\";\n  }\n  if (el.styleBinding) {\n    data += \"style:(\" + (el.styleBinding) + \"),\";\n  }\n  return data\n}\n\nvar style = {\n  staticKeys: ['staticStyle'],\n  transformNode: transformNode$1,\n  genData: genData$1\n};\n\nvar modules = [\n  klass,\n  style\n];\n\nvar ASSET_TYPES = [\n  'component',\n  'directive',\n  'filter'\n];\n\nvar LIFECYCLE_HOOKS = [\n  'beforeCreate',\n  'created',\n  'beforeMount',\n  'mounted',\n  'beforeUpdate',\n  'updated',\n  'beforeDestroy',\n  'destroyed',\n  'activated',\n  'deactivated', 'onLaunch',\n  'onLoad',\n  'onShow',\n  'onReady',\n  'onHide',\n  'onUnload',\n  'onPullDownRefresh',\n  'onReachBottom',\n  'onShareAppMessage',\n  'onPageScroll',\n  'onTabItemTap',\n  'attached',\n  'ready',\n  'moved',\n  'detached'\n];\n\n/*  */\n\nvar config = ({\n  /**\n   * Option merge strategies (used in core/util/options)\n   */\n  optionMergeStrategies: Object.create(null),\n\n  /**\n   * Whether to suppress warnings.\n   */\n  silent: false,\n\n  /**\n   * Show production mode tip message on boot?\n   */\n  productionTip: process.env.NODE_ENV !== 'production',\n\n  /**\n   * Whether to enable devtools\n   */\n  devtools: process.env.NODE_ENV !== 'production',\n\n  /**\n   * Whether to record perf\n   */\n  performance: false,\n\n  /**\n   * Error handler for watcher errors\n   */\n  errorHandler: null,\n\n  /**\n   * Warn handler for watcher warns\n   */\n  warnHandler: null,\n\n  /**\n   * Ignore certain custom elements\n   */\n  ignoredElements: [],\n\n  /**\n   * Custom user key aliases for v-on\n   */\n  keyCodes: Object.create(null),\n\n  /**\n   * Check if a tag is reserved so that it cannot be registered as a\n   * component. This is platform-dependent and may be overwritten.\n   */\n  isReservedTag: no,\n\n  /**\n   * Check if an attribute is reserved so that it cannot be used as a component\n   * prop. This is platform-dependent and may be overwritten.\n   */\n  isReservedAttr: no,\n\n  /**\n   * Check if a tag is an unknown element.\n   * Platform-dependent.\n   */\n  isUnknownElement: no,\n\n  /**\n   * Get the namespace of an element\n   */\n  getTagNamespace: noop,\n\n  /**\n   * Parse the real tag name for the specific platform.\n   */\n  parsePlatformTagName: identity,\n\n  /**\n   * Check if an attribute must be bound using property, e.g. value\n   * Platform-dependent.\n   */\n  mustUseProp: no,\n\n  /**\n   * Exposed for legacy reasons\n   */\n  _lifecycleHooks: LIFECYCLE_HOOKS\n});\n\n/*  */\n\n/**\n * Cross-platform code generation for component v-model\n */\nfunction genComponentModel (\n  el,\n  value,\n  modifiers\n) {\n  var ref = modifiers || {};\n  var number = ref.number;\n  var trim = ref.trim;\n\n  var baseValueExpression = '$$v';\n  var valueExpression = baseValueExpression;\n  if (trim) {\n    valueExpression =\n      \"(typeof \" + baseValueExpression + \" === 'string'\" +\n        \"? \" + baseValueExpression + \".trim()\" +\n        \": \" + baseValueExpression + \")\";\n  }\n  if (number) {\n    valueExpression = \"_n(\" + valueExpression + \")\";\n  }\n  var assignment = genAssignmentCode(value, valueExpression);\n\n  el.model = {\n    value: (\"(\" + value + \")\"),\n    expression: (\"\\\"\" + value + \"\\\"\"),\n    callback: (\"function (\" + baseValueExpression + \") {\" + assignment + \"}\")\n  };\n}\n\n/**\n * Cross-platform codegen helper for generating v-model value assignment code.\n */\nfunction genAssignmentCode (\n  value,\n  assignment\n) {\n  var modelRs = parseModel(value);\n  if (modelRs.idx === null) {\n    return (value + \"=\" + assignment)\n  } else {\n    return (\"$set(\" + (modelRs.exp) + \", \" + (modelRs.idx) + \", \" + assignment + \")\")\n  }\n}\n\n/**\n * parse directive model to do the array update transform. a[idx] = val => $$a.splice($$idx, 1, val)\n *\n * for loop possible cases:\n *\n * - test\n * - test[idx]\n * - test[test1[idx]]\n * - test[\"a\"][idx]\n * - xxx.test[a[a].test1[idx]]\n * - test.xxx.a[\"asa\"][test1[idx]]\n *\n */\n\nvar len;\nvar str;\nvar chr;\nvar index;\nvar expressionPos;\nvar expressionEndPos;\n\nfunction parseModel (val) {\n  str = val;\n  len = str.length;\n  index = expressionPos = expressionEndPos = 0;\n\n  if (val.indexOf('[') < 0 || val.lastIndexOf(']') < len - 1) {\n    return {\n      exp: val,\n      idx: null\n    }\n  }\n\n  while (!eof()) {\n    chr = next();\n    /* istanbul ignore if */\n    if (isStringStart(chr)) {\n      parseString(chr);\n    } else if (chr === 0x5B) {\n      parseBracket(chr);\n    }\n  }\n\n  return {\n    exp: val.substring(0, expressionPos),\n    idx: val.substring(expressionPos + 1, expressionEndPos)\n  }\n}\n\nfunction next () {\n  return str.charCodeAt(++index)\n}\n\nfunction eof () {\n  return index >= len\n}\n\nfunction isStringStart (chr) {\n  return chr === 0x22 || chr === 0x27\n}\n\nfunction parseBracket (chr) {\n  var inBracket = 1;\n  expressionPos = index;\n  while (!eof()) {\n    chr = next();\n    if (isStringStart(chr)) {\n      parseString(chr);\n      continue\n    }\n    if (chr === 0x5B) { inBracket++; }\n    if (chr === 0x5D) { inBracket--; }\n    if (inBracket === 0) {\n      expressionEndPos = index;\n      break\n    }\n  }\n}\n\nfunction parseString (chr) {\n  var stringQuote = chr;\n  while (!eof()) {\n    chr = next();\n    if (chr === stringQuote) {\n      break\n    }\n  }\n}\n\n/*  */\n\nvar warn;\n\n// in some cases, the event used has to be determined at runtime\n// so we used some reserved tokens during compile.\nvar RANGE_TOKEN = '__r';\nvar CHECKBOX_RADIO_TOKEN = '__c';\n\nfunction model (\n  el,\n  dir,\n  _warn\n) {\n  warn = _warn;\n  var value = dir.value;\n  var modifiers = dir.modifiers;\n  var tag = el.tag;\n  var type = el.attrsMap.type;\n\n  if (process.env.NODE_ENV !== 'production') {\n    var dynamicType = el.attrsMap['v-bind:type'] || el.attrsMap[':type'];\n    if (tag === 'input' && dynamicType) {\n      warn(\n        \"<input :type=\\\"\" + dynamicType + \"\\\" v-model=\\\"\" + value + \"\\\">:\\n\" +\n        \"v-model does not support dynamic input types. Use v-if branches instead.\"\n      );\n    }\n    // inputs with type=\"file\" are read only and setting the input's\n    // value will throw an error.\n    if (tag === 'input' && type === 'file') {\n      warn(\n        \"<\" + (el.tag) + \" v-model=\\\"\" + value + \"\\\" type=\\\"file\\\">:\\n\" +\n        \"File inputs are read only. Use a v-on:change listener instead.\"\n      );\n    }\n  }\n\n  if (el.component) {\n    genComponentModel(el, value, modifiers);\n    // component v-model doesn't need extra runtime\n    return false\n  } else if (tag === 'select') {\n    genSelect(el, value, modifiers);\n  } else if (tag === 'input' && type === 'checkbox') {\n    genCheckboxModel(el, value, modifiers);\n  } else if (tag === 'input' && type === 'radio') {\n    genRadioModel(el, value, modifiers);\n  } else if (tag === 'input' || tag === 'textarea') {\n    genDefaultModel(el, value, modifiers);\n  } else if (!config.isReservedTag(tag)) {\n    genComponentModel(el, value, modifiers);\n    // component v-model doesn't need extra runtime\n    return false\n  } else if (process.env.NODE_ENV !== 'production') {\n    warn(\n      \"<\" + (el.tag) + \" v-model=\\\"\" + value + \"\\\">: \" +\n      \"v-model is not supported on this element type. \" +\n      'If you are working with contenteditable, it\\'s recommended to ' +\n      'wrap a library dedicated for that purpose inside a custom component.'\n    );\n  }\n\n  // ensure runtime directive metadata\n  return true\n}\n\nfunction genCheckboxModel (\n  el,\n  value,\n  modifiers\n) {\n  var number = modifiers && modifiers.number;\n  var valueBinding = getBindingAttr(el, 'value') || 'null';\n  var trueValueBinding = getBindingAttr(el, 'true-value') || 'true';\n  var falseValueBinding = getBindingAttr(el, 'false-value') || 'false';\n  addProp(el, 'checked',\n    \"Array.isArray(\" + value + \")\" +\n      \"?_i(\" + value + \",\" + valueBinding + \")>-1\" + (\n        trueValueBinding === 'true'\n          ? (\":(\" + value + \")\")\n          : (\":_q(\" + value + \",\" + trueValueBinding + \")\")\n      )\n  );\n  addHandler(el, CHECKBOX_RADIO_TOKEN,\n    \"var $$a=\" + value + \",\" +\n        '$$el=$event.target,' +\n        \"$$c=$$el.checked?(\" + trueValueBinding + \"):(\" + falseValueBinding + \");\" +\n    'if(Array.isArray($$a)){' +\n      \"var $$v=\" + (number ? '_n(' + valueBinding + ')' : valueBinding) + \",\" +\n          '$$i=_i($$a,$$v);' +\n      \"if($$c){$$i<0&&(\" + value + \"=$$a.concat($$v))}\" +\n      \"else{$$i>-1&&(\" + value + \"=$$a.slice(0,$$i).concat($$a.slice($$i+1)))}\" +\n    \"}else{\" + (genAssignmentCode(value, '$$c')) + \"}\",\n    null, true\n  );\n}\n\nfunction genRadioModel (\n    el,\n    value,\n    modifiers\n) {\n  var number = modifiers && modifiers.number;\n  var valueBinding = getBindingAttr(el, 'value') || 'null';\n  valueBinding = number ? (\"_n(\" + valueBinding + \")\") : valueBinding;\n  addProp(el, 'checked', (\"_q(\" + value + \",\" + valueBinding + \")\"));\n  addHandler(el, CHECKBOX_RADIO_TOKEN, genAssignmentCode(value, valueBinding), null, true);\n}\n\nfunction genSelect (\n    el,\n    value,\n    modifiers\n) {\n  var number = modifiers && modifiers.number;\n  var selectedVal = \"Array.prototype.filter\" +\n    \".call($event.target.options,function(o){return o.selected})\" +\n    \".map(function(o){var val = \\\"_value\\\" in o ? o._value : o.value;\" +\n    \"return \" + (number ? '_n(val)' : 'val') + \"})\";\n\n  var assignment = '$event.target.multiple ? $$selectedVal : $$selectedVal[0]';\n  var code = \"var $$selectedVal = \" + selectedVal + \";\";\n  code = code + \" \" + (genAssignmentCode(value, assignment));\n  addHandler(el, 'change', code, null, true);\n}\n\nfunction genDefaultModel (\n  el,\n  value,\n  modifiers\n) {\n  var type = el.attrsMap.type;\n  var ref = modifiers || {};\n  var lazy = ref.lazy;\n  var number = ref.number;\n  var trim = ref.trim;\n  var needCompositionGuard = !lazy && type !== 'range';\n  var event = lazy\n    ? 'change'\n    : type === 'range'\n      ? RANGE_TOKEN\n      : 'input';\n\n  var valueExpression = '$event.target.value';\n  if (trim) {\n    valueExpression = \"$event.target.value.trim()\";\n  }\n  if (number) {\n    valueExpression = \"_n(\" + valueExpression + \")\";\n  }\n\n  var code = genAssignmentCode(value, valueExpression);\n  if (needCompositionGuard) {\n    code = \"if($event.target.composing)return;\" + code;\n  }\n\n  addProp(el, 'value', (\"(\" + value + \")\"));\n  addHandler(el, event, code, null, true);\n  if (trim || number) {\n    addHandler(el, 'blur', '$forceUpdate()');\n  }\n}\n\n/*  */\n\nfunction text (el, dir) {\n  if (dir.value) {\n    addProp(el, 'textContent', (\"_s(\" + (dir.value) + \")\"));\n  }\n}\n\n/*  */\n\nfunction html (el, dir) {\n  if (dir.value) {\n    addProp(el, 'innerHTML', (\"_s(\" + (dir.value) + \")\"));\n  }\n}\n\nvar directives = {\n  model: model,\n  text: text,\n  html: html\n};\n\n/*  */\n\nvar isUnaryTag$2 = makeMap(\n  'area,base,br,col,embed,frame,hr,img,input,isindex,keygen,' +\n  'link,meta,param,source,track,wbr'\n);\n\n// Elements that you can, intentionally, leave open\n// (and which close themselves)\nvar canBeLeftOpenTag$2 = makeMap(\n  'colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr,source'\n);\n\n// HTML5 tags https://html.spec.whatwg.org/multipage/indices.html#elements-3\n// Phrasing Content https://html.spec.whatwg.org/multipage/dom.html#phrasing-content\nvar isNonPhrasingTag$1 = makeMap(\n  'address,article,aside,base,blockquote,body,caption,col,colgroup,dd,' +\n  'details,dialog,div,dl,dt,fieldset,figcaption,figure,footer,form,' +\n  'h1,h2,h3,h4,h5,h6,head,header,hgroup,hr,html,legend,li,menuitem,meta,' +\n  'optgroup,option,param,rp,rt,source,style,summary,tbody,td,tfoot,th,thead,' +\n  'title,tr,track'\n);\n\n/*  */\n\nvar baseOptions = {\n  expectHTML: true,\n  modules: modules,\n  directives: directives,\n  isPreTag: isPreTag,\n  isUnaryTag: isUnaryTag$2,\n  mustUseProp: mustUseProp,\n  canBeLeftOpenTag: canBeLeftOpenTag$2,\n  isReservedTag: isReservedTag,\n  getTagNamespace: getTagNamespace,\n  staticKeys: genStaticKeys(modules)\n};\n\n/*  */\n\nvar warn$2 = noop;\nvar tip = noop;\nvar formatComponentName = (null); // work around flow check\n\nif (process.env.NODE_ENV !== 'production') {\n  var hasConsole = typeof console !== 'undefined';\n  var classifyRE = /(?:^|[-_])(\\w)/g;\n  var classify = function (str) { return str\n    .replace(classifyRE, function (c) { return c.toUpperCase(); })\n    .replace(/[-_]/g, ''); };\n\n  warn$2 = function (msg, vm) {\n    var trace = vm ? generateComponentTrace(vm) : '';\n\n    if (config.warnHandler) {\n      config.warnHandler.call(null, msg, vm, trace);\n    } else if (hasConsole && (!config.silent)) {\n      console.error((\"[Vue warn]: \" + msg + trace));\n    }\n  };\n\n  tip = function (msg, vm) {\n    if (hasConsole && (!config.silent)) {\n      console.warn(\"[Vue tip]: \" + msg + (\n        vm ? generateComponentTrace(vm) : ''\n      ));\n    }\n  };\n\n  formatComponentName = function (vm, includeFile) {\n    if (vm.$root === vm) {\n      return '<Root>'\n    }\n    var name = typeof vm === 'string'\n      ? vm\n      : typeof vm === 'function' && vm.options\n        ? vm.options.name\n        : vm._isVue\n          ? vm.$options.name || vm.$options._componentTag\n          : vm.name;\n\n    var file = vm._isVue && vm.$options.__file;\n    if (!name && file) {\n      var match = file.match(/([^/\\\\]+)\\.vue$/);\n      name = match && match[1];\n    }\n\n    return (\n      (name ? (\"<\" + (classify(name)) + \">\") : \"<Anonymous>\") +\n      (file && includeFile !== false ? (\" at \" + file) : '')\n    )\n  };\n\n  var repeat = function (str, n) {\n    var res = '';\n    while (n) {\n      if (n % 2 === 1) { res += str; }\n      if (n > 1) { str += str; }\n      n >>= 1;\n    }\n    return res\n  };\n\n  var generateComponentTrace = function (vm) {\n    if (vm._isVue && vm.$parent) {\n      var tree = [];\n      var currentRecursiveSequence = 0;\n      while (vm) {\n        if (tree.length > 0) {\n          var last = tree[tree.length - 1];\n          if (last.constructor === vm.constructor) {\n            currentRecursiveSequence++;\n            vm = vm.$parent;\n            continue\n          } else if (currentRecursiveSequence > 0) {\n            tree[tree.length - 1] = [last, currentRecursiveSequence];\n            currentRecursiveSequence = 0;\n          }\n        }\n        tree.push(vm);\n        vm = vm.$parent;\n      }\n      return '\\n\\nfound in\\n\\n' + tree\n        .map(function (vm, i) { return (\"\" + (i === 0 ? '---> ' : repeat(' ', 5 + i * 2)) + (Array.isArray(vm)\n            ? ((formatComponentName(vm[0])) + \"... (\" + (vm[1]) + \" recursive calls)\")\n            : formatComponentName(vm))); })\n        .join('\\n')\n    } else {\n      return (\"\\n\\n(found in \" + (formatComponentName(vm)) + \")\")\n    }\n  };\n}\n\n/*  */\n\nfunction handleError (err, vm, info) {\n  if (config.errorHandler) {\n    config.errorHandler.call(null, err, vm, info);\n  } else {\n    if (process.env.NODE_ENV !== 'production') {\n      warn$2((\"Error in \" + info + \": \\\"\" + (err.toString()) + \"\\\"\"), vm);\n    }\n    /* istanbul ignore else */\n    if (inBrowser && typeof console !== 'undefined') {\n      console.error(err);\n    } else {\n      throw err\n    }\n  }\n}\n\n/*  */\n\n// can we use __proto__?\nvar hasProto = '__proto__' in {};\n\n// Browser environment sniffing\nvar inBrowser = typeof window !== 'undefined';\nvar UA = ['mpvue-runtime'].join();\nvar isIE = UA && /msie|trident/.test(UA);\nvar isIE9 = UA && UA.indexOf('msie 9.0') > 0;\nvar isEdge = UA && UA.indexOf('edge/') > 0;\nvar isAndroid = UA && UA.indexOf('android') > 0;\nvar isIOS = UA && /iphone|ipad|ipod|ios/.test(UA);\nvar isChrome = UA && /chrome\\/\\d+/.test(UA) && !isEdge;\n\n// Firefix has a \"watch\" function on Object.prototype...\nvar nativeWatch = ({}).watch;\n\nvar supportsPassive = false;\nif (inBrowser) {\n  try {\n    var opts = {};\n    Object.defineProperty(opts, 'passive', ({\n      get: function get () {\n        /* istanbul ignore next */\n        supportsPassive = true;\n      }\n    })); // https://github.com/facebook/flow/issues/285\n    window.addEventListener('test-passive', null, opts);\n  } catch (e) {}\n}\n\n// this needs to be lazy-evaled because vue may be required before\n// vue-server-renderer can set VUE_ENV\nvar _isServer;\nvar isServerRendering = function () {\n  if (_isServer === undefined) {\n    /* istanbul ignore if */\n    if (!inBrowser && typeof global !== 'undefined') {\n      // detect presence of vue-server-renderer and avoid\n      // Webpack shimming the process\n      _isServer = global['process'].env.VUE_ENV === 'server';\n    } else {\n      _isServer = false;\n    }\n  }\n  return _isServer\n};\n\n// detect devtools\n\n\n/* istanbul ignore next */\nfunction isNative (Ctor) {\n  return typeof Ctor === 'function' && /native code/.test(Ctor.toString())\n}\n\nvar hasSymbol =\n  typeof Symbol !== 'undefined' && isNative(Symbol) &&\n  typeof Reflect !== 'undefined' && isNative(Reflect.ownKeys);\n\n/**\n * Defer a task to execute it asynchronously.\n */\nvar nextTick = (function () {\n  var callbacks = [];\n  var pending = false;\n  var timerFunc;\n\n  function nextTickHandler () {\n    pending = false;\n    var copies = callbacks.slice(0);\n    callbacks.length = 0;\n    for (var i = 0; i < copies.length; i++) {\n      copies[i]();\n    }\n  }\n\n  // the nextTick behavior leverages the microtask queue, which can be accessed\n  // via either native Promise.then or MutationObserver.\n  // MutationObserver has wider support, however it is seriously bugged in\n  // UIWebView in iOS >= 9.3.3 when triggered in touch event handlers. It\n  // completely stops working after triggering a few times... so, if native\n  // Promise is available, we will use it:\n  /* istanbul ignore if */\n  if (typeof Promise !== 'undefined' && isNative(Promise)) {\n    var p = Promise.resolve();\n    var logError = function (err) { console.error(err); };\n    timerFunc = function () {\n      p.then(nextTickHandler).catch(logError);\n      // in problematic UIWebViews, Promise.then doesn't completely break, but\n      // it can get stuck in a weird state where callbacks are pushed into the\n      // microtask queue but the queue isn't being flushed, until the browser\n      // needs to do some other work, e.g. handle a timer. Therefore we can\n      // \"force\" the microtask queue to be flushed by adding an empty timer.\n      if (isIOS) { setTimeout(noop); }\n    };\n  // } else if (typeof MutationObserver !== 'undefined' && (\n  //   isNative(MutationObserver) ||\n  //   // PhantomJS and iOS 7.x\n  //   MutationObserver.toString() === '[object MutationObserverConstructor]'\n  // )) {\n  //   // use MutationObserver where native Promise is not available,\n  //   // e.g. PhantomJS IE11, iOS7, Android 4.4\n  //   var counter = 1\n  //   var observer = new MutationObserver(nextTickHandler)\n  //   var textNode = document.createTextNode(String(counter))\n  //   observer.observe(textNode, {\n  //     characterData: true\n  //   })\n  //   timerFunc = () => {\n  //     counter = (counter + 1) % 2\n  //     textNode.data = String(counter)\n  //   }\n  } else {\n    // fallback to setTimeout\n    /* istanbul ignore next */\n    timerFunc = function () {\n      setTimeout(nextTickHandler, 0);\n    };\n  }\n\n  return function queueNextTick (cb, ctx) {\n    var _resolve;\n    callbacks.push(function () {\n      if (cb) {\n        try {\n          cb.call(ctx);\n        } catch (e) {\n          handleError(e, ctx, 'nextTick');\n        }\n      } else if (_resolve) {\n        _resolve(ctx);\n      }\n    });\n    if (!pending) {\n      pending = true;\n      timerFunc();\n    }\n    if (!cb && typeof Promise !== 'undefined') {\n      return new Promise(function (resolve, reject) {\n        _resolve = resolve;\n      })\n    }\n  }\n})();\n\nvar _Set;\n/* istanbul ignore if */\nif (typeof Set !== 'undefined' && isNative(Set)) {\n  // use native Set when available.\n  _Set = Set;\n} else {\n  // a non-standard Set polyfill that only works with primitive keys.\n  _Set = (function () {\n    function Set () {\n      this.set = Object.create(null);\n    }\n    Set.prototype.has = function has (key) {\n      return this.set[key] === true\n    };\n    Set.prototype.add = function add (key) {\n      this.set[key] = true;\n    };\n    Set.prototype.clear = function clear () {\n      this.set = Object.create(null);\n    };\n\n    return Set;\n  }());\n}\n\n/*  */\n\nvar onRE = /^@|^v-on:/;\nvar dirRE = /^v-|^@|^:/;\nvar forAliasRE = /(.*?)\\s+(?:in|of)\\s+(.*)/;\nvar forIteratorRE = /\\((\\{[^}]*\\}|[^,]*),([^,]*)(?:,([^,]*))?\\)/;\n\nvar argRE = /:(.*)$/;\nvar bindRE = /^:|^v-bind:/;\nvar modifierRE = /\\.[^.]+/g;\n\nvar decodeHTMLCached = cached(he.decode);\n\n// configurable state\nvar warn$1;\nvar delimiters;\nvar transforms;\nvar preTransforms;\nvar postTransforms;\nvar platformIsPreTag;\nvar platformMustUseProp;\nvar platformGetTagNamespace;\n\n/**\n * Convert HTML string to AST.\n */\nfunction parse (\n  template$$1,\n  options\n) {\n  warn$1 = options.warn || baseWarn;\n\n  platformIsPreTag = options.isPreTag || no;\n  platformMustUseProp = options.mustUseProp || no;\n  platformGetTagNamespace = options.getTagNamespace || no;\n\n  transforms = pluckModuleFunction(options.modules, 'transformNode');\n  preTransforms = pluckModuleFunction(options.modules, 'preTransformNode');\n  postTransforms = pluckModuleFunction(options.modules, 'postTransformNode');\n\n  delimiters = options.delimiters;\n\n  var stack = [];\n  var preserveWhitespace = options.preserveWhitespace !== false;\n  var root;\n  var currentParent;\n  var inVPre = false;\n  var inPre = false;\n  var warned = false;\n\n  function warnOnce (msg) {\n    if (!warned) {\n      warned = true;\n      warn$1(msg);\n    }\n  }\n\n  function endPre (element) {\n    // check pre state\n    if (element.pre) {\n      inVPre = false;\n    }\n    if (platformIsPreTag(element.tag)) {\n      inPre = false;\n    }\n  }\n\n  parseHTML(template$$1, {\n    warn: warn$1,\n    expectHTML: options.expectHTML,\n    isUnaryTag: options.isUnaryTag,\n    canBeLeftOpenTag: options.canBeLeftOpenTag,\n    shouldDecodeNewlines: options.shouldDecodeNewlines,\n    shouldKeepComment: options.comments,\n    start: function start (tag, attrs, unary) {\n      // check namespace.\n      // inherit parent ns if there is one\n      var ns = (currentParent && currentParent.ns) || platformGetTagNamespace(tag);\n\n      // handle IE svg bug\n      /* istanbul ignore if */\n      if (isIE && ns === 'svg') {\n        attrs = guardIESVGBug(attrs);\n      }\n\n      var element = {\n        type: 1,\n        tag: tag,\n        attrsList: attrs,\n        attrsMap: makeAttrsMap(attrs),\n        parent: currentParent,\n        children: []\n      };\n      if (ns) {\n        element.ns = ns;\n      }\n\n      if (isForbiddenTag(element) && !isServerRendering()) {\n        element.forbidden = true;\n        process.env.NODE_ENV !== 'production' && warn$1(\n          'Templates should only be responsible for mapping the state to the ' +\n          'UI. Avoid placing tags with side-effects in your templates, such as ' +\n          \"<\" + tag + \">\" + ', as they will not be parsed.'\n        );\n      }\n\n      // apply pre-transforms\n      for (var i = 0; i < preTransforms.length; i++) {\n        preTransforms[i](element, options);\n      }\n\n      if (!inVPre) {\n        processPre(element);\n        if (element.pre) {\n          inVPre = true;\n        }\n      }\n      if (platformIsPreTag(element.tag)) {\n        inPre = true;\n      }\n      if (inVPre) {\n        processRawAttrs(element);\n      } else {\n        processFor(element);\n        processIf(element);\n        processOnce(element);\n        processKey(element);\n\n        // determine whether this is a plain element after\n        // removing structural attributes\n        element.plain = !element.key && !attrs.length;\n\n        processRef(element);\n        processSlot(element);\n        processComponent(element);\n        for (var i$1 = 0; i$1 < transforms.length; i$1++) {\n          transforms[i$1](element, options);\n        }\n        processAttrs(element);\n      }\n\n      function checkRootConstraints (el) {\n        if (process.env.NODE_ENV !== 'production') {\n          if (el.tag === 'slot' || el.tag === 'template') {\n            warnOnce(\n              \"Cannot use <\" + (el.tag) + \"> as component root element because it may \" +\n              'contain multiple nodes.'\n            );\n          }\n          if (el.attrsMap.hasOwnProperty('v-for')) {\n            warnOnce(\n              'Cannot use v-for on stateful component root element because ' +\n              'it renders multiple elements.'\n            );\n          }\n        }\n      }\n\n      // tree management\n      if (!root) {\n        root = element;\n        checkRootConstraints(root);\n      } else if (!stack.length) {\n        // allow root elements with v-if, v-else-if and v-else\n        if (root.if && (element.elseif || element.else)) {\n          checkRootConstraints(element);\n          addIfCondition(root, {\n            exp: element.elseif,\n            block: element\n          });\n        } else if (process.env.NODE_ENV !== 'production') {\n          warnOnce(\n            \"Component template should contain exactly one root element. \" +\n            \"If you are using v-if on multiple elements, \" +\n            \"use v-else-if to chain them instead.\"\n          );\n        }\n      }\n      if (currentParent && !element.forbidden) {\n        if (element.elseif || element.else) {\n          processIfConditions(element, currentParent);\n        } else if (element.slotScope) { // scoped slot\n          currentParent.plain = false;\n          var name = element.slotTarget || '\"default\"';(currentParent.scopedSlots || (currentParent.scopedSlots = {}))[name] = element;\n        } else {\n          currentParent.children.push(element);\n          element.parent = currentParent;\n        }\n      }\n      if (!unary) {\n        currentParent = element;\n        stack.push(element);\n      } else {\n        endPre(element);\n      }\n      // apply post-transforms\n      for (var i$2 = 0; i$2 < postTransforms.length; i$2++) {\n        postTransforms[i$2](element, options);\n      }\n    },\n\n    end: function end () {\n      // remove trailing whitespace\n      var element = stack[stack.length - 1];\n      var lastNode = element.children[element.children.length - 1];\n      if (lastNode && lastNode.type === 3 && lastNode.text === ' ' && !inPre) {\n        element.children.pop();\n      }\n      // pop stack\n      stack.length -= 1;\n      currentParent = stack[stack.length - 1];\n      endPre(element);\n    },\n\n    chars: function chars (text) {\n      if (!currentParent) {\n        if (process.env.NODE_ENV !== 'production') {\n          if (text === template$$1) {\n            warnOnce(\n              'Component template requires a root element, rather than just text.'\n            );\n          } else if ((text = text.trim())) {\n            warnOnce(\n              (\"text \\\"\" + text + \"\\\" outside root element will be ignored.\")\n            );\n          }\n        }\n        return\n      }\n      // IE textarea placeholder bug\n      /* istanbul ignore if */\n      if (isIE &&\n        currentParent.tag === 'textarea' &&\n        currentParent.attrsMap.placeholder === text\n      ) {\n        return\n      }\n      var children = currentParent.children;\n      text = inPre || text.trim()\n        ? isTextTag(currentParent) ? text : decodeHTMLCached(text)\n        // only preserve whitespace if its not right after a starting tag\n        : preserveWhitespace && children.length ? ' ' : '';\n      if (text) {\n        var expression;\n        if (!inVPre && text !== ' ' && (expression = parseText(text, delimiters))) {\n          children.push({\n            type: 2,\n            expression: expression,\n            text: text\n          });\n        } else if (text !== ' ' || !children.length || children[children.length - 1].text !== ' ') {\n          children.push({\n            type: 3,\n            text: text\n          });\n        }\n      }\n    },\n    comment: function comment (text) {\n      currentParent.children.push({\n        type: 3,\n        text: text,\n        isComment: true\n      });\n    }\n  });\n  return root\n}\n\nfunction processPre (el) {\n  if (getAndRemoveAttr(el, 'v-pre') != null) {\n    el.pre = true;\n  }\n}\n\nfunction processRawAttrs (el) {\n  var l = el.attrsList.length;\n  if (l) {\n    var attrs = el.attrs = new Array(l);\n    for (var i = 0; i < l; i++) {\n      attrs[i] = {\n        name: el.attrsList[i].name,\n        value: JSON.stringify(el.attrsList[i].value)\n      };\n    }\n  } else if (!el.pre) {\n    // non root node in pre blocks with no attributes\n    el.plain = true;\n  }\n}\n\nfunction processKey (el) {\n  var exp = getBindingAttr(el, 'key');\n  if (exp) {\n    if (process.env.NODE_ENV !== 'production' && el.tag === 'template') {\n      warn$1(\"<template> cannot be keyed. Place the key on real elements instead.\");\n    }\n    el.key = exp;\n  }\n}\n\nfunction processRef (el) {\n  var ref = getBindingAttr(el, 'ref');\n  if (ref) {\n    el.ref = ref;\n    el.refInFor = checkInFor(el);\n  }\n}\n\nfunction processFor (el) {\n  var exp;\n  if ((exp = getAndRemoveAttr(el, 'v-for'))) {\n    var inMatch = exp.match(forAliasRE);\n    if (!inMatch) {\n      process.env.NODE_ENV !== 'production' && warn$1(\n        (\"Invalid v-for expression: \" + exp)\n      );\n      return\n    }\n    el.for = inMatch[2].trim();\n    var alias = inMatch[1].trim();\n    var iteratorMatch = alias.match(forIteratorRE);\n    if (iteratorMatch) {\n      el.alias = iteratorMatch[1].trim();\n      el.iterator1 = iteratorMatch[2].trim();\n      if (iteratorMatch[3]) {\n        el.iterator2 = iteratorMatch[3].trim();\n      }\n    } else {\n      el.alias = alias;\n    }\n  }\n}\n\nfunction processIf (el) {\n  var exp = getAndRemoveAttr(el, 'v-if');\n  if (exp) {\n    el.if = exp;\n    addIfCondition(el, {\n      exp: exp,\n      block: el\n    });\n  } else {\n    if (getAndRemoveAttr(el, 'v-else') != null) {\n      el.else = true;\n    }\n    var elseif = getAndRemoveAttr(el, 'v-else-if');\n    if (elseif) {\n      el.elseif = elseif;\n    }\n  }\n}\n\nfunction processIfConditions (el, parent) {\n  var prev = findPrevElement(parent.children);\n  if (prev && prev.if) {\n    addIfCondition(prev, {\n      exp: el.elseif,\n      block: el\n    });\n  } else if (process.env.NODE_ENV !== 'production') {\n    warn$1(\n      \"v-\" + (el.elseif ? ('else-if=\"' + el.elseif + '\"') : 'else') + \" \" +\n      \"used on element <\" + (el.tag) + \"> without corresponding v-if.\"\n    );\n  }\n}\n\nfunction findPrevElement (children) {\n  var i = children.length;\n  while (i--) {\n    if (children[i].type === 1) {\n      return children[i]\n    } else {\n      if (process.env.NODE_ENV !== 'production' && children[i].text !== ' ') {\n        warn$1(\n          \"text \\\"\" + (children[i].text.trim()) + \"\\\" between v-if and v-else(-if) \" +\n          \"will be ignored.\"\n        );\n      }\n      children.pop();\n    }\n  }\n}\n\nfunction addIfCondition (el, condition) {\n  if (!el.ifConditions) {\n    el.ifConditions = [];\n  }\n  el.ifConditions.push(condition);\n}\n\nfunction processOnce (el) {\n  var once$$1 = getAndRemoveAttr(el, 'v-once');\n  if (once$$1 != null) {\n    el.once = true;\n  }\n}\n\nfunction processSlot (el) {\n  if (el.tag === 'slot') {\n    el.slotName = getBindingAttr(el, 'name');\n    if (process.env.NODE_ENV !== 'production' && el.key) {\n      warn$1(\n        \"`key` does not work on <slot> because slots are abstract outlets \" +\n        \"and can possibly expand into multiple elements. \" +\n        \"Use the key on a wrapping element instead.\"\n      );\n    }\n  } else {\n    var slotTarget = getBindingAttr(el, 'slot');\n    if (slotTarget) {\n      el.slotTarget = slotTarget === '\"\"' ? '\"default\"' : slotTarget;\n    }\n    if (el.tag === 'template') {\n      el.slotScope = getAndRemoveAttr(el, 'scope');\n    }\n  }\n}\n\nfunction processComponent (el) {\n  var binding;\n  if ((binding = getBindingAttr(el, 'is'))) {\n    el.component = binding;\n  }\n  if (getAndRemoveAttr(el, 'inline-template') != null) {\n    el.inlineTemplate = true;\n  }\n}\n\nfunction processAttrs (el) {\n  var list = el.attrsList;\n  var i, l, name, rawName, value, modifiers, isProp;\n  for (i = 0, l = list.length; i < l; i++) {\n    name = rawName = list[i].name;\n    value = list[i].value;\n    if (dirRE.test(name)) {\n      // mark element as dynamic\n      el.hasBindings = true;\n      // modifiers\n      modifiers = parseModifiers(name);\n      if (modifiers) {\n        name = name.replace(modifierRE, '');\n      }\n      if (bindRE.test(name)) { // v-bind\n        name = name.replace(bindRE, '');\n        value = parseFilters(value);\n        isProp = false;\n        if (modifiers) {\n          if (modifiers.prop) {\n            isProp = true;\n            name = camelize(name);\n            if (name === 'innerHtml') { name = 'innerHTML'; }\n          }\n          if (modifiers.camel) {\n            name = camelize(name);\n          }\n          if (modifiers.sync) {\n            addHandler(\n              el,\n              (\"update:\" + (camelize(name))),\n              genAssignmentCode(value, \"$event\")\n            );\n          }\n        }\n        if (!el.component && (\n          isProp || platformMustUseProp(el.tag, el.attrsMap.type, name)\n        )) {\n          addProp(el, name, value);\n        } else {\n          addAttr(el, name, value);\n        }\n      } else if (onRE.test(name)) { // v-on\n        name = name.replace(onRE, '');\n        addHandler(el, name, value, modifiers, false, warn$1);\n      } else { // normal directives\n        name = name.replace(dirRE, '');\n        // parse arg\n        var argMatch = name.match(argRE);\n        var arg = argMatch && argMatch[1];\n        if (arg) {\n          name = name.slice(0, -(arg.length + 1));\n        }\n        addDirective(el, name, rawName, value, arg, modifiers);\n        if (process.env.NODE_ENV !== 'production' && name === 'model') {\n          checkForAliasModel(el, value);\n        }\n      }\n    } else {\n      // literal attribute\n      if (process.env.NODE_ENV !== 'production') {\n        var expression = parseText(value, delimiters);\n        if (expression) {\n          warn$1(\n            name + \"=\\\"\" + value + \"\\\": \" +\n            'Interpolation inside attributes has been removed. ' +\n            'Use v-bind or the colon shorthand instead. For example, ' +\n            'instead of <div id=\"{{ val }}\">, use <div :id=\"val\">.'\n          );\n        }\n      }\n      addAttr(el, name, JSON.stringify(value));\n    }\n  }\n}\n\nfunction checkInFor (el) {\n  var parent = el;\n  while (parent) {\n    if (parent.for !== undefined) {\n      return true\n    }\n    parent = parent.parent;\n  }\n  return false\n}\n\nfunction parseModifiers (name) {\n  var match = name.match(modifierRE);\n  if (match) {\n    var ret = {};\n    match.forEach(function (m) { ret[m.slice(1)] = true; });\n    return ret\n  }\n}\n\nfunction makeAttrsMap (attrs) {\n  var map = {};\n  for (var i = 0, l = attrs.length; i < l; i++) {\n    if (\n      process.env.NODE_ENV !== 'production' &&\n      map[attrs[i].name] && !isIE && !isEdge\n    ) {\n      warn$1('duplicate attribute: ' + attrs[i].name);\n    }\n    map[attrs[i].name] = attrs[i].value;\n  }\n  return map\n}\n\n// for script (e.g. type=\"x/template\") or style, do not decode content\nfunction isTextTag (el) {\n  return el.tag === 'script' || el.tag === 'style'\n}\n\nfunction isForbiddenTag (el) {\n  return (\n    el.tag === 'style' ||\n    (el.tag === 'script' && (\n      !el.attrsMap.type ||\n      el.attrsMap.type === 'text/javascript'\n    ))\n  )\n}\n\nvar ieNSBug = /^xmlns:NS\\d+/;\nvar ieNSPrefix = /^NS\\d+:/;\n\n/* istanbul ignore next */\nfunction guardIESVGBug (attrs) {\n  var res = [];\n  for (var i = 0; i < attrs.length; i++) {\n    var attr = attrs[i];\n    if (!ieNSBug.test(attr.name)) {\n      attr.name = attr.name.replace(ieNSPrefix, '');\n      res.push(attr);\n    }\n  }\n  return res\n}\n\nfunction checkForAliasModel (el, value) {\n  var _el = el;\n  while (_el) {\n    if (_el.for && _el.alias === value) {\n      warn$1(\n        \"<\" + (el.tag) + \" v-model=\\\"\" + value + \"\\\">: \" +\n        \"You are binding v-model directly to a v-for iteration alias. \" +\n        \"This will not be able to modify the v-for source array because \" +\n        \"writing to the alias is like modifying a function local variable. \" +\n        \"Consider using an array of objects and use v-model on an object property instead.\"\n      );\n    }\n    _el = _el.parent;\n  }\n}\n\n/*  */\n\nvar isStaticKey;\nvar isPlatformReservedTag;\n\nvar genStaticKeysCached = cached(genStaticKeys$1);\n\n/**\n * Goal of the optimizer: walk the generated template AST tree\n * and detect sub-trees that are purely static, i.e. parts of\n * the DOM that never needs to change.\n *\n * Once we detect these sub-trees, we can:\n *\n * 1. Hoist them into constants, so that we no longer need to\n *    create fresh nodes for them on each re-render;\n * 2. Completely skip them in the patching process.\n */\nfunction optimize (root, options) {\n  if (!root) { return }\n  isStaticKey = genStaticKeysCached(options.staticKeys || '');\n  isPlatformReservedTag = options.isReservedTag || no;\n  // first pass: mark all non-static nodes.\n  markStatic(root);\n  // second pass: mark static roots.\n  markStaticRoots(root, false);\n}\n\nfunction genStaticKeys$1 (keys) {\n  return makeMap(\n    'type,tag,attrsList,attrsMap,plain,parent,children,attrs' +\n    (keys ? ',' + keys : '')\n  )\n}\n\nfunction markStatic (node) {\n  node.static = isStatic(node);\n  if (node.type === 1) {\n    // do not make component slot content static. this avoids\n    // 1. components not able to mutate slot nodes\n    // 2. static slot content fails for hot-reloading\n    if (\n      !isPlatformReservedTag(node.tag) &&\n      node.tag !== 'slot' &&\n      node.attrsMap['inline-template'] == null\n    ) {\n      return\n    }\n    for (var i = 0, l = node.children.length; i < l; i++) {\n      var child = node.children[i];\n      markStatic(child);\n      if (!child.static) {\n        node.static = false;\n      }\n    }\n    if (node.ifConditions) {\n      for (var i$1 = 1, l$1 = node.ifConditions.length; i$1 < l$1; i$1++) {\n        var block = node.ifConditions[i$1].block;\n        markStatic(block);\n        if (!block.static) {\n          node.static = false;\n        }\n      }\n    }\n  }\n}\n\nfunction markStaticRoots (node, isInFor) {\n  if (node.type === 1) {\n    if (node.static || node.once) {\n      node.staticInFor = isInFor;\n    }\n    // For a node to qualify as a static root, it should have children that\n    // are not just static text. Otherwise the cost of hoisting out will\n    // outweigh the benefits and it's better off to just always render it fresh.\n    if (node.static && node.children.length && !(\n      node.children.length === 1 &&\n      node.children[0].type === 3\n    )) {\n      node.staticRoot = true;\n      return\n    } else {\n      node.staticRoot = false;\n    }\n    if (node.children) {\n      for (var i = 0, l = node.children.length; i < l; i++) {\n        markStaticRoots(node.children[i], isInFor || !!node.for);\n      }\n    }\n    if (node.ifConditions) {\n      for (var i$1 = 1, l$1 = node.ifConditions.length; i$1 < l$1; i$1++) {\n        markStaticRoots(node.ifConditions[i$1].block, isInFor);\n      }\n    }\n  }\n}\n\nfunction isStatic (node) {\n  if (node.type === 2) { // expression\n    return false\n  }\n  if (node.type === 3) { // text\n    return true\n  }\n  return !!(node.pre || (\n    !node.hasBindings && // no dynamic bindings\n    !node.if && !node.for && // not v-if or v-for or v-else\n    !isBuiltInTag(node.tag) && // not a built-in\n    isPlatformReservedTag(node.tag) && // not a component\n    !isDirectChildOfTemplateFor(node) &&\n    Object.keys(node).every(isStaticKey)\n  ))\n}\n\nfunction isDirectChildOfTemplateFor (node) {\n  while (node.parent) {\n    node = node.parent;\n    if (node.tag !== 'template') {\n      return false\n    }\n    if (node.for) {\n      return true\n    }\n  }\n  return false\n}\n\n/*  */\n\nvar fnExpRE = /^\\s*([\\w$_]+|\\([^)]*?\\))\\s*=>|^function\\s*\\(/;\nvar simplePathRE = /^\\s*[A-Za-z_$][\\w$]*(?:\\.[A-Za-z_$][\\w$]*|\\['.*?']|\\[\".*?\"]|\\[\\d+]|\\[[A-Za-z_$][\\w$]*])*\\s*$/;\n\n// keyCode aliases\nvar keyCodes = {\n  esc: 27,\n  tab: 9,\n  enter: 13,\n  space: 32,\n  up: 38,\n  left: 37,\n  right: 39,\n  down: 40,\n  'delete': [8, 46]\n};\n\n// #4868: modifiers that prevent the execution of the listener\n// need to explicitly return null so that we can determine whether to remove\n// the listener for .once\nvar genGuard = function (condition) { return (\"if(\" + condition + \")return null;\"); };\n\nvar modifierCode = {\n  stop: '$event.stopPropagation();',\n  prevent: '$event.preventDefault();',\n  self: genGuard(\"$event.target !== $event.currentTarget\"),\n  ctrl: genGuard(\"!$event.ctrlKey\"),\n  shift: genGuard(\"!$event.shiftKey\"),\n  alt: genGuard(\"!$event.altKey\"),\n  meta: genGuard(\"!$event.metaKey\"),\n  left: genGuard(\"'button' in $event && $event.button !== 0\"),\n  middle: genGuard(\"'button' in $event && $event.button !== 1\"),\n  right: genGuard(\"'button' in $event && $event.button !== 2\")\n};\n\nfunction genHandlers (\n  events,\n  isNative,\n  warn\n) {\n  var res = isNative ? 'nativeOn:{' : 'on:{';\n  for (var name in events) {\n    var handler = events[name];\n    // #5330: warn click.right, since right clicks do not actually fire click events.\n    if (process.env.NODE_ENV !== 'production' &&\n      name === 'click' &&\n      handler && handler.modifiers && handler.modifiers.right\n    ) {\n      warn(\n        \"Use \\\"contextmenu\\\" instead of \\\"click.right\\\" since right clicks \" +\n        \"do not actually fire \\\"click\\\" events.\"\n      );\n    }\n    res += \"\\\"\" + name + \"\\\":\" + (genHandler(name, handler)) + \",\";\n  }\n  return res.slice(0, -1) + '}'\n}\n\nfunction genHandler (\n  name,\n  handler\n) {\n  if (!handler) {\n    return 'function(){}'\n  }\n\n  if (Array.isArray(handler)) {\n    return (\"[\" + (handler.map(function (handler) { return genHandler(name, handler); }).join(',')) + \"]\")\n  }\n\n  var isMethodPath = simplePathRE.test(handler.value);\n  var isFunctionExpression = fnExpRE.test(handler.value);\n\n  if (!handler.modifiers) {\n    return isMethodPath || isFunctionExpression\n      ? handler.value\n      : (\"function($event){\" + (handler.value) + \"}\") // inline statement\n  } else {\n    var code = '';\n    var genModifierCode = '';\n    var keys = [];\n    for (var key in handler.modifiers) {\n      if (modifierCode[key]) {\n        genModifierCode += modifierCode[key];\n        // left/right\n        if (keyCodes[key]) {\n          keys.push(key);\n        }\n      } else {\n        keys.push(key);\n      }\n    }\n    if (keys.length) {\n      code += genKeyFilter(keys);\n    }\n    // Make sure modifiers like prevent and stop get executed after key filtering\n    if (genModifierCode) {\n      code += genModifierCode;\n    }\n    var handlerCode = isMethodPath\n      ? handler.value + '($event)'\n      : isFunctionExpression\n        ? (\"(\" + (handler.value) + \")($event)\")\n        : handler.value;\n    return (\"function($event){\" + code + handlerCode + \"}\")\n  }\n}\n\nfunction genKeyFilter (keys) {\n  return (\"if(!('button' in $event)&&\" + (keys.map(genFilterCode).join('&&')) + \")return null;\")\n}\n\nfunction genFilterCode (key) {\n  var keyVal = parseInt(key, 10);\n  if (keyVal) {\n    return (\"$event.keyCode!==\" + keyVal)\n  }\n  var alias = keyCodes[key];\n  return (\"_k($event.keyCode,\" + (JSON.stringify(key)) + (alias ? ',' + JSON.stringify(alias) : '') + \")\")\n}\n\n/*  */\n\nvar emptyObject = Object.freeze({});\n\n/**\n * Check if a string starts with $ or _\n */\n\n\n/**\n * Define a property.\n */\nfunction def (obj, key, val, enumerable) {\n  Object.defineProperty(obj, key, {\n    value: val,\n    enumerable: !!enumerable,\n    writable: true,\n    configurable: true\n  });\n}\n\n/*  */\n\n\nvar uid = 0;\n\n/**\n * A dep is an observable that can have multiple\n * directives subscribing to it.\n */\nvar Dep = function Dep () {\n  this.id = uid++;\n  this.subs = [];\n};\n\nDep.prototype.addSub = function addSub (sub) {\n  this.subs.push(sub);\n};\n\nDep.prototype.removeSub = function removeSub (sub) {\n  remove(this.subs, sub);\n};\n\nDep.prototype.depend = function depend () {\n  if (Dep.target) {\n    Dep.target.addDep(this);\n  }\n};\n\nDep.prototype.notify = function notify () {\n  // stabilize the subscriber list first\n  var subs = this.subs.slice();\n  for (var i = 0, l = subs.length; i < l; i++) {\n    subs[i].update();\n  }\n};\n\n// the current target watcher being evaluated.\n// this is globally unique because there could be only one\n// watcher being evaluated at any time.\nDep.target = null;\n\n/*\n * not type checking this file because flow doesn't play well with\n * dynamically accessing methods on Array prototype\n */\n\nvar arrayProto = Array.prototype;\nvar arrayMethods = Object.create(arrayProto);[\n  'push',\n  'pop',\n  'shift',\n  'unshift',\n  'splice',\n  'sort',\n  'reverse'\n]\n.forEach(function (method) {\n  // cache original method\n  var original = arrayProto[method];\n  def(arrayMethods, method, function mutator () {\n    var args = [], len = arguments.length;\n    while ( len-- ) args[ len ] = arguments[ len ];\n\n    var result = original.apply(this, args);\n    var ob = this.__ob__;\n    var inserted;\n    switch (method) {\n      case 'push':\n      case 'unshift':\n        inserted = args;\n        break\n      case 'splice':\n        inserted = args.slice(2);\n        break\n    }\n    if (inserted) { ob.observeArray(inserted); }\n    // notify change\n    ob.dep.notify();\n    return result\n  });\n});\n\n/*  */\n\nvar arrayKeys = Object.getOwnPropertyNames(arrayMethods);\n\n/**\n * By default, when a reactive property is set, the new value is\n * also converted to become reactive. However when passing down props,\n * we don't want to force conversion because the value may be a nested value\n * under a frozen data structure. Converting it would defeat the optimization.\n */\nvar observerState = {\n  shouldConvert: true\n};\n\n/**\n * Observer class that are attached to each observed\n * object. Once attached, the observer converts target\n * object's property keys into getter/setters that\n * collect dependencies and dispatches updates.\n */\nvar Observer = function Observer (value, key) {\n  this.value = value;\n  this.dep = new Dep();\n  this.vmCount = 0;\n  if (key) {\n    this.key = key;\n  }\n  def(value, '__ob__', this);\n  if (Array.isArray(value)) {\n    var augment = hasProto\n      ? protoAugment\n      : copyAugment;\n    augment(value, arrayMethods, arrayKeys);\n    this.observeArray(value);\n  } else {\n    this.walk(value);\n  }\n};\n\n/**\n * Walk through each property and convert them into\n * getter/setters. This method should only be called when\n * value type is Object.\n */\nObserver.prototype.walk = function walk (obj) {\n  var keys = Object.keys(obj);\n  for (var i = 0; i < keys.length; i++) {\n    defineReactive$$1(obj, keys[i], obj[keys[i]]);\n  }\n};\n\n/**\n * Observe a list of Array items.\n */\nObserver.prototype.observeArray = function observeArray (items) {\n  for (var i = 0, l = items.length; i < l; i++) {\n    observe(items[i]);\n  }\n};\n\n// helpers\n\n/**\n * Augment an target Object or Array by intercepting\n * the prototype chain using __proto__\n */\nfunction protoAugment (target, src, keys) {\n  /* eslint-disable no-proto */\n  target.__proto__ = src;\n  /* eslint-enable no-proto */\n}\n\n/**\n * Augment an target Object or Array by defining\n * hidden properties.\n */\n/* istanbul ignore next */\nfunction copyAugment (target, src, keys) {\n  for (var i = 0, l = keys.length; i < l; i++) {\n    var key = keys[i];\n    def(target, key, src[key]);\n  }\n}\n\n/**\n * Attempt to create an observer instance for a value,\n * returns the new observer if successfully observed,\n * or the existing observer if the value already has one.\n */\nfunction observe (value, asRootData, key) {\n  if (!isObject(value)) {\n    return\n  }\n  var ob;\n  if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) {\n    ob = value.__ob__;\n  } else if (\n    observerState.shouldConvert &&\n    !isServerRendering() &&\n    (Array.isArray(value) || isPlainObject(value)) &&\n    Object.isExtensible(value) &&\n    !value._isVue\n  ) {\n    ob = new Observer(value, key);\n  }\n  if (asRootData && ob) {\n    ob.vmCount++;\n  }\n  return ob\n}\n\n/**\n * Define a reactive property on an Object.\n */\nfunction defineReactive$$1 (\n  obj,\n  key,\n  val,\n  customSetter,\n  shallow\n) {\n  var dep = new Dep();\n\n  var property = Object.getOwnPropertyDescriptor(obj, key);\n  if (property && property.configurable === false) {\n    return\n  }\n\n  // cater for pre-defined getter/setters\n  var getter = property && property.get;\n  var setter = property && property.set;\n\n  var childOb = !shallow && observe(val, undefined, key);\n  Object.defineProperty(obj, key, {\n    enumerable: true,\n    configurable: true,\n    get: function reactiveGetter () {\n      var value = getter ? getter.call(obj) : val;\n      if (Dep.target) {\n        dep.depend();\n        if (childOb) {\n          childOb.dep.depend();\n        }\n        if (Array.isArray(value)) {\n          dependArray(value);\n        }\n      }\n      return value\n    },\n    set: function reactiveSetter (newVal) {\n      var value = getter ? getter.call(obj) : val;\n      /* eslint-disable no-self-compare */\n      if (newVal === value || (newVal !== newVal && value !== value)) {\n        return\n      }\n\n      /* eslint-enable no-self-compare */\n      if (process.env.NODE_ENV !== 'production' && customSetter) {\n        customSetter();\n      }\n      if (setter) {\n        setter.call(obj, newVal);\n      } else {\n        val = newVal;\n      }\n      childOb = !shallow && observe(newVal, undefined, key);\n      dep.notify();\n\n      if (!obj.__keyPath) {\n        def(obj, '__keyPath', {}, false);\n      }\n      obj.__keyPath[key] = true;\n      if (newVal instanceof Object && !(newVal instanceof Array)) {\n        // 标记是否是通过this.Obj = {} 赋值印发的改动，解决少更新问题#1305\n        def(newVal, '__newReference', true, false);\n      }\n    }\n  });\n}\n\n/**\n * Set a property on an object. Adds the new property and\n * triggers change notification if the property doesn't\n * already exist.\n */\nfunction set (target, key, val) {\n  if (Array.isArray(target) && isValidArrayIndex(key)) {\n    target.length = Math.max(target.length, key);\n    target.splice(key, 1, val);\n    return val\n  }\n  if (hasOwn(target, key)) {\n    target[key] = val;\n    return val\n  }\n  var ob = (target).__ob__;\n  if (target._isVue || (ob && ob.vmCount)) {\n    process.env.NODE_ENV !== 'production' && warn$2(\n      'Avoid adding reactive properties to a Vue instance or its root $data ' +\n      'at runtime - declare it upfront in the data option.'\n    );\n    return val\n  }\n  if (!ob) {\n    target[key] = val;\n    return val\n  }\n  defineReactive$$1(ob.value, key, val);\n  // Vue.set 添加对象属性，渲染时候把 val 传给小程序渲染\n  if (!target.__keyPath) {\n    def(target, '__keyPath', {}, false);\n  }\n  target.__keyPath[key] = true;\n  ob.dep.notify();\n  return val\n}\n\n/**\n * Delete a property and trigger change if necessary.\n */\n\n\n/**\n * Collect dependencies on array elements when the array is touched, since\n * we cannot intercept array element access like property getters.\n */\nfunction dependArray (value) {\n  for (var e = (void 0), i = 0, l = value.length; i < l; i++) {\n    e = value[i];\n    e && e.__ob__ && e.__ob__.dep.depend();\n    if (Array.isArray(e)) {\n      dependArray(e);\n    }\n  }\n}\n\n/*  */\n\n/**\n * Option overwriting strategies are functions that handle\n * how to merge a parent option value and a child option\n * value into the final value.\n */\nvar strats = config.optionMergeStrategies;\n\n/**\n * Options with restrictions\n */\nif (process.env.NODE_ENV !== 'production') {\n  strats.el = strats.propsData = function (parent, child, vm, key) {\n    if (!vm) {\n      warn$2(\n        \"option \\\"\" + key + \"\\\" can only be used during instance \" +\n        'creation with the `new` keyword.'\n      );\n    }\n    return defaultStrat(parent, child)\n  };\n}\n\n/**\n * Helper that recursively merges two data objects together.\n */\nfunction mergeData (to, from) {\n  if (!from) { return to }\n  var key, toVal, fromVal;\n  var keys = Object.keys(from);\n  for (var i = 0; i < keys.length; i++) {\n    key = keys[i];\n    toVal = to[key];\n    fromVal = from[key];\n    if (!hasOwn(to, key)) {\n      set(to, key, fromVal);\n    } else if (isPlainObject(toVal) && isPlainObject(fromVal)) {\n      mergeData(toVal, fromVal);\n    }\n  }\n  return to\n}\n\n/**\n * Data\n */\nfunction mergeDataOrFn (\n  parentVal,\n  childVal,\n  vm\n) {\n  if (!vm) {\n    // in a Vue.extend merge, both should be functions\n    if (!childVal) {\n      return parentVal\n    }\n    if (!parentVal) {\n      return childVal\n    }\n    // when parentVal & childVal are both present,\n    // we need to return a function that returns the\n    // merged result of both functions... no need to\n    // check if parentVal is a function here because\n    // it has to be a function to pass previous merges.\n    return function mergedDataFn () {\n      return mergeData(\n        typeof childVal === 'function' ? childVal.call(this) : childVal,\n        parentVal.call(this)\n      )\n    }\n  } else if (parentVal || childVal) {\n    return function mergedInstanceDataFn () {\n      // instance merge\n      var instanceData = typeof childVal === 'function'\n        ? childVal.call(vm)\n        : childVal;\n      var defaultData = typeof parentVal === 'function'\n        ? parentVal.call(vm)\n        : undefined;\n      if (instanceData) {\n        return mergeData(instanceData, defaultData)\n      } else {\n        return defaultData\n      }\n    }\n  }\n}\n\nstrats.data = function (\n  parentVal,\n  childVal,\n  vm\n) {\n  if (!vm) {\n    if (childVal && typeof childVal !== 'function') {\n      process.env.NODE_ENV !== 'production' && warn$2(\n        'The \"data\" option should be a function ' +\n        'that returns a per-instance value in component ' +\n        'definitions.',\n        vm\n      );\n\n      return parentVal\n    }\n    return mergeDataOrFn.call(this, parentVal, childVal)\n  }\n\n  return mergeDataOrFn(parentVal, childVal, vm)\n};\n\n/**\n * Hooks and props are merged as arrays.\n */\nfunction mergeHook (\n  parentVal,\n  childVal\n) {\n  return childVal\n    ? parentVal\n      ? parentVal.concat(childVal)\n      : Array.isArray(childVal)\n        ? childVal\n        : [childVal]\n    : parentVal\n}\n\nLIFECYCLE_HOOKS.forEach(function (hook) {\n  strats[hook] = mergeHook;\n});\n\n/**\n * Assets\n *\n * When a vm is present (instance creation), we need to do\n * a three-way merge between constructor options, instance\n * options and parent options.\n */\nfunction mergeAssets (parentVal, childVal) {\n  var res = Object.create(parentVal || null);\n  return childVal\n    ? extend(res, childVal)\n    : res\n}\n\nASSET_TYPES.forEach(function (type) {\n  strats[type + 's'] = mergeAssets;\n});\n\n/**\n * Watchers.\n *\n * Watchers hashes should not overwrite one\n * another, so we merge them as arrays.\n */\nstrats.watch = function (parentVal, childVal) {\n  // work around Firefox's Object.prototype.watch...\n  if (parentVal === nativeWatch) { parentVal = undefined; }\n  if (childVal === nativeWatch) { childVal = undefined; }\n  /* istanbul ignore if */\n  if (!childVal) { return Object.create(parentVal || null) }\n  if (!parentVal) { return childVal }\n  var ret = {};\n  extend(ret, parentVal);\n  for (var key in childVal) {\n    var parent = ret[key];\n    var child = childVal[key];\n    if (parent && !Array.isArray(parent)) {\n      parent = [parent];\n    }\n    ret[key] = parent\n      ? parent.concat(child)\n      : Array.isArray(child) ? child : [child];\n  }\n  return ret\n};\n\n/**\n * Other object hashes.\n */\nstrats.props =\nstrats.methods =\nstrats.inject =\nstrats.computed = function (parentVal, childVal) {\n  if (!childVal) { return Object.create(parentVal || null) }\n  if (!parentVal) { return childVal }\n  var ret = Object.create(null);\n  extend(ret, parentVal);\n  extend(ret, childVal);\n  return ret\n};\nstrats.provide = mergeDataOrFn;\n\n/**\n * Default strategy.\n */\nvar defaultStrat = function (parentVal, childVal) {\n  return childVal === undefined\n    ? parentVal\n    : childVal\n};\n\n/**\n * Merge two option objects into a new one.\n * Core utility used in both instantiation and inheritance.\n */\n\n\n/**\n * Resolve an asset.\n * This function is used because child instances need access\n * to assets defined in its ancestor chain.\n */\n\n/*  */\n\n/*  */\n\n/*  */\n\nfunction on (el, dir) {\n  if (process.env.NODE_ENV !== 'production' && dir.modifiers) {\n    warn$2(\"v-on without argument does not support modifiers.\");\n  }\n  el.wrapListeners = function (code) { return (\"_g(\" + code + \",\" + (dir.value) + \")\"); };\n}\n\n/*  */\n\nfunction bind$1 (el, dir) {\n  el.wrapData = function (code) {\n    return (\"_b(\" + code + \",'\" + (el.tag) + \"',\" + (dir.value) + \",\" + (dir.modifiers && dir.modifiers.prop ? 'true' : 'false') + (dir.modifiers && dir.modifiers.sync ? ',true' : '') + \")\")\n  };\n}\n\n/*  */\n\nvar baseDirectives = {\n  on: on,\n  bind: bind$1,\n  cloak: noop\n};\n\n/*  */\n\nvar CodegenState = function CodegenState (options) {\n  this.options = options;\n  this.warn = options.warn || baseWarn;\n  this.transforms = pluckModuleFunction(options.modules, 'transformCode');\n  this.dataGenFns = pluckModuleFunction(options.modules, 'genData');\n  this.directives = extend(extend({}, baseDirectives), options.directives);\n  var isReservedTag = options.isReservedTag || no;\n  this.maybeComponent = function (el) { return !isReservedTag(el.tag); };\n  this.onceId = 0;\n  this.staticRenderFns = [];\n};\n\n\n\nfunction generate$1 (\n  ast,\n  options\n) {\n  var state = new CodegenState(options);\n  var code = ast ? genElement(ast, state) : '_c(\"div\")';\n  return {\n    render: (\"with(this){return \" + code + \"}\"),\n    staticRenderFns: state.staticRenderFns\n  }\n}\n\nfunction genElement (el, state) {\n  if (el.staticRoot && !el.staticProcessed) {\n    return genStatic(el, state)\n  } else if (el.once && !el.onceProcessed) {\n    return genOnce(el, state)\n  } else if (el.for && !el.forProcessed) {\n    return genFor(el, state)\n  } else if (el.if && !el.ifProcessed) {\n    return genIf(el, state)\n  } else if (el.tag === 'template' && !el.slotTarget) {\n    return genChildren(el, state) || 'void 0'\n  } else if (el.tag === 'slot') {\n    return genSlot(el, state)\n  } else {\n    // component or element\n    var code;\n    if (el.component) {\n      code = genComponent(el.component, el, state);\n    } else {\n      var data = el.plain ? undefined : genData$2(el, state);\n\n      var children = el.inlineTemplate ? null : genChildren(el, state, true);\n      code = \"_c('\" + (el.tag) + \"'\" + (data ? (\",\" + data) : '') + (children ? (\",\" + children) : '') + \")\";\n    }\n    // module transforms\n    for (var i = 0; i < state.transforms.length; i++) {\n      code = state.transforms[i](el, code);\n    }\n    return code\n  }\n}\n\n// hoist static sub-trees out\nfunction genStatic (el, state) {\n  el.staticProcessed = true;\n  state.staticRenderFns.push((\"with(this){return \" + (genElement(el, state)) + \"}\"));\n  return (\"_m(\" + (state.staticRenderFns.length - 1) + (el.staticInFor ? ',true' : '') + \")\")\n}\n\n// v-once\nfunction genOnce (el, state) {\n  el.onceProcessed = true;\n  if (el.if && !el.ifProcessed) {\n    return genIf(el, state)\n  } else if (el.staticInFor) {\n    var key = '';\n    var parent = el.parent;\n    while (parent) {\n      if (parent.for) {\n        key = parent.key;\n        break\n      }\n      parent = parent.parent;\n    }\n    if (!key) {\n      process.env.NODE_ENV !== 'production' && state.warn(\n        \"v-once can only be used inside v-for that is keyed. \"\n      );\n      return genElement(el, state)\n    }\n    return (\"_o(\" + (genElement(el, state)) + \",\" + (state.onceId++) + (key ? (\",\" + key) : \"\") + \")\")\n  } else {\n    return genStatic(el, state)\n  }\n}\n\nfunction genIf (\n  el,\n  state,\n  altGen,\n  altEmpty\n) {\n  el.ifProcessed = true; // avoid recursion\n  return genIfConditions(el.ifConditions.slice(), state, altGen, altEmpty)\n}\n\nfunction genIfConditions (\n  conditions,\n  state,\n  altGen,\n  altEmpty\n) {\n  if (!conditions.length) {\n    return altEmpty || '_e()'\n  }\n\n  var condition = conditions.shift();\n  if (condition.exp) {\n    return (\"(\" + (condition.exp) + \")?\" + (genTernaryExp(condition.block)) + \":\" + (genIfConditions(conditions, state, altGen, altEmpty)))\n  } else {\n    return (\"\" + (genTernaryExp(condition.block)))\n  }\n\n  // v-if with v-once should generate code like (a)?_m(0):_m(1)\n  function genTernaryExp (el) {\n    return altGen\n      ? altGen(el, state)\n      : el.once\n        ? genOnce(el, state)\n        : genElement(el, state)\n  }\n}\n\nfunction genFor (\n  el,\n  state,\n  altGen,\n  altHelper\n) {\n  var exp = el.for;\n  var alias = el.alias;\n  var iterator1 = el.iterator1 ? (\",\" + (el.iterator1)) : '';\n  var iterator2 = el.iterator2 ? (\",\" + (el.iterator2)) : '';\n\n  if (process.env.NODE_ENV !== 'production' &&\n    state.maybeComponent(el) &&\n    el.tag !== 'slot' &&\n    el.tag !== 'template' &&\n    !el.key\n  ) {\n    state.warn(\n      \"<\" + (el.tag) + \" v-for=\\\"\" + alias + \" in \" + exp + \"\\\">: component lists rendered with \" +\n      \"v-for should have explicit keys. \" +\n      \"See https://vuejs.org/guide/list.html#key for more info.\",\n      true /* tip */\n    );\n  }\n\n  el.forProcessed = true; // avoid recursion\n  return (altHelper || '_l') + \"((\" + exp + \"),\" +\n    \"function(\" + alias + iterator1 + iterator2 + \"){\" +\n      \"return \" + ((altGen || genElement)(el, state)) +\n    '})'\n}\n\nfunction genData$2 (el, state) {\n  var data = '{';\n\n  // directives first.\n  // directives may mutate the el's other properties before they are generated.\n  var dirs = genDirectives(el, state);\n  if (dirs) { data += dirs + ','; }\n\n  // key\n  if (el.key) {\n    data += \"key:\" + (el.key) + \",\";\n  }\n  // ref\n  if (el.ref) {\n    data += \"ref:\" + (el.ref) + \",\";\n  }\n  if (el.refInFor) {\n    data += \"refInFor:true,\";\n  }\n  // pre\n  if (el.pre) {\n    data += \"pre:true,\";\n  }\n  // record original tag name for components using \"is\" attribute\n  if (el.component) {\n    data += \"tag:\\\"\" + (el.tag) + \"\\\",\";\n  }\n  // module data generation functions\n  for (var i = 0; i < state.dataGenFns.length; i++) {\n    data += state.dataGenFns[i](el);\n  }\n  // attributes\n  if (el.attrs) {\n    data += \"attrs:{\" + (genProps(el.attrs)) + \"},\";\n  }\n  // DOM props\n  if (el.props) {\n    data += \"domProps:{\" + (genProps(el.props)) + \"},\";\n  }\n  // event handlers\n  if (el.events) {\n    data += (genHandlers(el.events, false, state.warn)) + \",\";\n  }\n  if (el.nativeEvents) {\n    data += (genHandlers(el.nativeEvents, true, state.warn)) + \",\";\n  }\n  // slot target\n  if (el.slotTarget) {\n    data += \"slot:\" + (el.slotTarget) + \",\";\n  }\n  // scoped slots\n  if (el.scopedSlots) {\n    data += (genScopedSlots(el.scopedSlots, state)) + \",\";\n  }\n  // component v-model\n  if (el.model) {\n    data += \"model:{value:\" + (el.model.value) + \",callback:\" + (el.model.callback) + \",expression:\" + (el.model.expression) + \"},\";\n  }\n  // inline-template\n  if (el.inlineTemplate) {\n    var inlineTemplate = genInlineTemplate(el, state);\n    if (inlineTemplate) {\n      data += inlineTemplate + \",\";\n    }\n  }\n  data = data.replace(/,$/, '') + '}';\n  // v-bind data wrap\n  if (el.wrapData) {\n    data = el.wrapData(data);\n  }\n  // v-on data wrap\n  if (el.wrapListeners) {\n    data = el.wrapListeners(data);\n  }\n  return data\n}\n\nfunction genDirectives (el, state) {\n  var dirs = el.directives;\n  if (!dirs) { return }\n  var res = 'directives:[';\n  var hasRuntime = false;\n  var i, l, dir, needRuntime;\n  for (i = 0, l = dirs.length; i < l; i++) {\n    dir = dirs[i];\n    needRuntime = true;\n    var gen = state.directives[dir.name];\n    if (gen) {\n      // compile-time directive that manipulates AST.\n      // returns true if it also needs a runtime counterpart.\n      needRuntime = !!gen(el, dir, state.warn);\n    }\n    if (needRuntime) {\n      hasRuntime = true;\n      res += \"{name:\\\"\" + (dir.name) + \"\\\",rawName:\\\"\" + (dir.rawName) + \"\\\"\" + (dir.value ? (\",value:(\" + (dir.value) + \"),expression:\" + (JSON.stringify(dir.value))) : '') + (dir.arg ? (\",arg:\\\"\" + (dir.arg) + \"\\\"\") : '') + (dir.modifiers ? (\",modifiers:\" + (JSON.stringify(dir.modifiers))) : '') + \"},\";\n    }\n  }\n  if (hasRuntime) {\n    return res.slice(0, -1) + ']'\n  }\n}\n\nfunction genInlineTemplate (el, state) {\n  var ast = el.children[0];\n  if (process.env.NODE_ENV !== 'production' && (\n    el.children.length > 1 || ast.type !== 1\n  )) {\n    state.warn('Inline-template components must have exactly one child element.');\n  }\n  if (ast.type === 1) {\n    var inlineRenderFns = generate$1(ast, state.options);\n    return (\"inlineTemplate:{render:function(){\" + (inlineRenderFns.render) + \"},staticRenderFns:[\" + (inlineRenderFns.staticRenderFns.map(function (code) { return (\"function(){\" + code + \"}\"); }).join(',')) + \"]}\")\n  }\n}\n\nfunction genScopedSlots (\n  slots,\n  state\n) {\n  return (\"scopedSlots:_u([\" + (Object.keys(slots).map(function (key) {\n      return genScopedSlot(key, slots[key], state)\n    }).join(',')) + \"])\")\n}\n\nfunction genScopedSlot (\n  key,\n  el,\n  state\n) {\n  if (el.for && !el.forProcessed) {\n    return genForScopedSlot(key, el, state)\n  }\n  return \"{key:\" + key + \",fn:function(\" + (String(el.attrsMap.scope)) + \"){\" +\n    \"return \" + (el.tag === 'template'\n      ? genChildren(el, state) || 'void 0'\n      : genElement(el, state)) + \"}}\"\n}\n\nfunction genForScopedSlot (\n  key,\n  el,\n  state\n) {\n  var exp = el.for;\n  var alias = el.alias;\n  var iterator1 = el.iterator1 ? (\",\" + (el.iterator1)) : '';\n  var iterator2 = el.iterator2 ? (\",\" + (el.iterator2)) : '';\n  el.forProcessed = true; // avoid recursion\n  return \"_l((\" + exp + \"),\" +\n    \"function(\" + alias + iterator1 + iterator2 + \"){\" +\n      \"return \" + (genScopedSlot(key, el, state)) +\n    '})'\n}\n\nfunction genChildren (\n  el,\n  state,\n  checkSkip,\n  altGenElement,\n  altGenNode\n) {\n  var children = el.children;\n  if (children.length) {\n    var el$1 = children[0];\n    // optimize single v-for\n    if (children.length === 1 &&\n      el$1.for &&\n      el$1.tag !== 'template' &&\n      el$1.tag !== 'slot'\n    ) {\n      return (altGenElement || genElement)(el$1, state)\n    }\n    var normalizationType = checkSkip\n      ? getNormalizationType(children, state.maybeComponent)\n      : 0;\n    var gen = altGenNode || genNode;\n    return (\"[\" + (children.map(function (c) { return gen(c, state); }).join(',')) + \"]\" + (normalizationType ? (\",\" + normalizationType) : ''))\n  }\n}\n\n// determine the normalization needed for the children array.\n// 0: no normalization needed\n// 1: simple normalization needed (possible 1-level deep nested array)\n// 2: full normalization needed\nfunction getNormalizationType (\n  children,\n  maybeComponent\n) {\n  var res = 0;\n  for (var i = 0; i < children.length; i++) {\n    var el = children[i];\n    if (el.type !== 1) {\n      continue\n    }\n    if (needsNormalization(el) ||\n        (el.ifConditions && el.ifConditions.some(function (c) { return needsNormalization(c.block); }))) {\n      res = 2;\n      break\n    }\n    if (maybeComponent(el) ||\n        (el.ifConditions && el.ifConditions.some(function (c) { return maybeComponent(c.block); }))) {\n      res = 1;\n    }\n  }\n  return res\n}\n\nfunction needsNormalization (el) {\n  return el.for !== undefined || el.tag === 'template' || el.tag === 'slot'\n}\n\nfunction genNode (node, state) {\n  if (node.type === 1) {\n    return genElement(node, state)\n  } if (node.type === 3 && node.isComment) {\n    return genComment(node)\n  } else {\n    return genText(node)\n  }\n}\n\nfunction genText (text) {\n  return (\"_v(\" + (text.type === 2\n    ? text.expression // no need for () because already wrapped in _s()\n    : transformSpecialNewlines(JSON.stringify(text.text))) + \")\")\n}\n\nfunction genComment (comment) {\n  return (\"_e('\" + (comment.text) + \"')\")\n}\n\nfunction genSlot (el, state) {\n  var slotName = el.slotName || '\"default\"';\n  var children = genChildren(el, state);\n  var res = \"_t(\" + slotName + (children ? (\",\" + children) : '');\n  var attrs = el.attrs && (\"{\" + (el.attrs.map(function (a) { return ((camelize(a.name)) + \":\" + (a.value)); }).join(',')) + \"}\");\n  var bind$$1 = el.attrsMap['v-bind'];\n  if ((attrs || bind$$1) && !children) {\n    res += \",null\";\n  }\n  if (attrs) {\n    res += \",\" + attrs;\n  }\n  if (bind$$1) {\n    res += (attrs ? '' : ',null') + \",\" + bind$$1;\n  }\n  return res + ')'\n}\n\n// componentName is el.component, take it as argument to shun flow's pessimistic refinement\nfunction genComponent (\n  componentName,\n  el,\n  state\n) {\n  var children = el.inlineTemplate ? null : genChildren(el, state, true);\n  return (\"_c(\" + componentName + \",\" + (genData$2(el, state)) + (children ? (\",\" + children) : '') + \")\")\n}\n\nfunction genProps (props) {\n  var res = '';\n  for (var i = 0; i < props.length; i++) {\n    var prop = props[i];\n    res += \"\\\"\" + (prop.name) + \"\\\":\" + (transformSpecialNewlines(prop.value)) + \",\";\n  }\n  return res.slice(0, -1)\n}\n\n// #3895, #4268\nfunction transformSpecialNewlines (text) {\n  return text\n    .replace(/\\u2028/g, '\\\\u2028')\n    .replace(/\\u2029/g, '\\\\u2029')\n}\n\n/*  */\n\n// these keywords should not appear inside expressions, but operators like\n// typeof, instanceof and in are allowed\nvar prohibitedKeywordRE = new RegExp('\\\\b' + (\n  'do,if,for,let,new,try,var,case,else,with,await,break,catch,class,const,' +\n  'super,throw,while,yield,delete,export,import,return,switch,default,' +\n  'extends,finally,continue,debugger,function,arguments'\n).split(',').join('\\\\b|\\\\b') + '\\\\b');\n\n// these unary operators should not be used as property/method names\nvar unaryOperatorsRE = new RegExp('\\\\b' + (\n  'delete,typeof,void'\n).split(',').join('\\\\s*\\\\([^\\\\)]*\\\\)|\\\\b') + '\\\\s*\\\\([^\\\\)]*\\\\)');\n\n// check valid identifier for v-for\nvar identRE = /[A-Za-z_$][\\w$]*/;\n\n// strip strings in expressions\nvar stripStringRE = /'(?:[^'\\\\]|\\\\.)*'|\"(?:[^\"\\\\]|\\\\.)*\"|`(?:[^`\\\\]|\\\\.)*\\$\\{|\\}(?:[^`\\\\]|\\\\.)*`|`(?:[^`\\\\]|\\\\.)*`/g;\n\n// detect problematic expressions in a template\nfunction detectErrors (ast) {\n  var errors = [];\n  if (ast) {\n    checkNode(ast, errors);\n  }\n  return errors\n}\n\nfunction checkNode (node, errors) {\n  if (node.type === 1) {\n    for (var name in node.attrsMap) {\n      if (dirRE.test(name)) {\n        var value = node.attrsMap[name];\n        if (value) {\n          if (name === 'v-for') {\n            checkFor(node, (\"v-for=\\\"\" + value + \"\\\"\"), errors);\n          } else if (onRE.test(name)) {\n            checkEvent(value, (name + \"=\\\"\" + value + \"\\\"\"), errors);\n          } else {\n            checkExpression(value, (name + \"=\\\"\" + value + \"\\\"\"), errors);\n          }\n        }\n      }\n    }\n    if (node.children) {\n      for (var i = 0; i < node.children.length; i++) {\n        checkNode(node.children[i], errors);\n      }\n    }\n  } else if (node.type === 2) {\n    checkExpression(node.expression, node.text, errors);\n  }\n}\n\nfunction checkEvent (exp, text, errors) {\n  var stipped = exp.replace(stripStringRE, '');\n  var keywordMatch = stipped.match(unaryOperatorsRE);\n  if (keywordMatch && stipped.charAt(keywordMatch.index - 1) !== '$') {\n    errors.push(\n      \"avoid using JavaScript unary operator as property name: \" +\n      \"\\\"\" + (keywordMatch[0]) + \"\\\" in expression \" + (text.trim())\n    );\n  }\n  checkExpression(exp, text, errors);\n}\n\nfunction checkFor (node, text, errors) {\n  checkExpression(node.for || '', text, errors);\n  checkIdentifier(node.alias, 'v-for alias', text, errors);\n  checkIdentifier(node.iterator1, 'v-for iterator', text, errors);\n  checkIdentifier(node.iterator2, 'v-for iterator', text, errors);\n}\n\nfunction checkIdentifier (ident, type, text, errors) {\n  if (typeof ident === 'string' && !identRE.test(ident)) {\n    errors.push((\"invalid \" + type + \" \\\"\" + ident + \"\\\" in expression: \" + (text.trim())));\n  }\n}\n\nfunction checkExpression (exp, text, errors) {\n  try {\n    new Function((\"return \" + exp));\n  } catch (e) {\n    var keywordMatch = exp.replace(stripStringRE, '').match(prohibitedKeywordRE);\n    if (keywordMatch) {\n      errors.push(\n        \"avoid using JavaScript keyword as property name: \" +\n        \"\\\"\" + (keywordMatch[0]) + \"\\\" in expression \" + (text.trim())\n      );\n    } else {\n      errors.push((\"invalid expression: \" + (text.trim())));\n    }\n  }\n}\n\n/*  */\n\nfunction createFunction (code, errors) {\n  try {\n    return new Function(code)\n  } catch (err) {\n    errors.push({ err: err, code: code });\n    return noop\n  }\n}\n\nfunction createCompileToFunctionFn (compile) {\n  var cache = Object.create(null);\n\n  return function compileToFunctions (\n    template$$1,\n    options,\n    vm\n  ) {\n    options = options || {};\n\n    /* istanbul ignore if */\n    if (process.env.NODE_ENV !== 'production') {\n      // detect possible CSP restriction\n      try {\n        new Function('return 1');\n      } catch (e) {\n        if (e.toString().match(/unsafe-eval|CSP/)) {\n          warn$2(\n            'It seems you are using the standalone build of Vue.js in an ' +\n            'environment with Content Security Policy that prohibits unsafe-eval. ' +\n            'The template compiler cannot work in this environment. Consider ' +\n            'relaxing the policy to allow unsafe-eval or pre-compiling your ' +\n            'templates into render functions.'\n          );\n        }\n      }\n    }\n\n    // check cache\n    var key = options.delimiters\n      ? String(options.delimiters) + template$$1\n      : template$$1;\n    if (cache[key]) {\n      return cache[key]\n    }\n\n    // compile\n    var compiled = compile(template$$1, options);\n\n    // check compilation errors/tips\n    if (process.env.NODE_ENV !== 'production') {\n      if (compiled.errors && compiled.errors.length) {\n        warn$2(\n          \"Error compiling template:\\n\\n\" + template$$1 + \"\\n\\n\" +\n          compiled.errors.map(function (e) { return (\"- \" + e); }).join('\\n') + '\\n',\n          vm\n        );\n      }\n      if (compiled.tips && compiled.tips.length) {\n        compiled.tips.forEach(function (msg) { return tip(msg, vm); });\n      }\n    }\n\n    // turn code into functions\n    var res = {};\n    var fnGenErrors = [];\n    res.render = createFunction(compiled.render, fnGenErrors);\n    res.staticRenderFns = compiled.staticRenderFns.map(function (code) {\n      return createFunction(code, fnGenErrors)\n    });\n\n    // check function generation errors.\n    // this should only happen if there is a bug in the compiler itself.\n    // mostly for codegen development use\n    /* istanbul ignore if */\n    if (process.env.NODE_ENV !== 'production') {\n      if ((!compiled.errors || !compiled.errors.length) && fnGenErrors.length) {\n        warn$2(\n          \"Failed to generate render function:\\n\\n\" +\n          fnGenErrors.map(function (ref) {\n            var err = ref.err;\n            var code = ref.code;\n\n            return ((err.toString()) + \" in\\n\\n\" + code + \"\\n\");\n        }).join('\\n'),\n          vm\n        );\n      }\n    }\n\n    return (cache[key] = res)\n  }\n}\n\n/*  */\n\nfunction createCompilerCreator (baseCompile) {\n  return function createCompiler (baseOptions) {\n    function compile (\n      template$$1,\n      options\n    ) {\n      var finalOptions = Object.create(baseOptions);\n      var errors = [];\n      var tips = [];\n      finalOptions.warn = function (msg, tip) {\n        (tip ? tips : errors).push(msg);\n      };\n\n      if (options) {\n        // merge custom modules\n        if (options.modules) {\n          finalOptions.modules =\n            (baseOptions.modules || []).concat(options.modules);\n        }\n        // merge custom directives\n        if (options.directives) {\n          finalOptions.directives = extend(\n            Object.create(baseOptions.directives),\n            options.directives\n          );\n        }\n        // copy other options\n        for (var key in options) {\n          if (key !== 'modules' && key !== 'directives') {\n            finalOptions[key] = options[key];\n          }\n        }\n      }\n\n      var compiled = baseCompile(template$$1, finalOptions);\n      if (process.env.NODE_ENV !== 'production') {\n        errors.push.apply(errors, detectErrors(compiled.ast));\n      }\n      compiled.errors = errors;\n      compiled.tips = tips;\n      return compiled\n    }\n\n    return {\n      compile: compile,\n      compileToFunctions: createCompileToFunctionFn(compile)\n    }\n  }\n}\n\nvar tagMap = {\n  'br': 'view',\n  'hr': 'view',\n\n  'p': 'view',\n  'h1': 'view',\n  'h2': 'view',\n  'h3': 'view',\n  'h4': 'view',\n  'h5': 'view',\n  'h6': 'view',\n  'abbr': 'view',\n  'address': 'view',\n  'b': 'view',\n  'bdi': 'view',\n  'bdo': 'view',\n  'blockquote': 'view',\n  'cite': 'view',\n  'code': 'view',\n  'del': 'view',\n  'ins': 'view',\n  'dfn': 'view',\n  'em': 'view',\n  'strong': 'view',\n  'samp': 'view',\n  'kbd': 'view',\n  'var': 'view',\n  'i': 'view',\n  'mark': 'view',\n  'pre': 'view',\n  'q': 'view',\n  'ruby': 'view',\n  'rp': 'view',\n  'rt': 'view',\n  's': 'view',\n  'small': 'view',\n  'sub': 'view',\n  'sup': 'view',\n  'time': 'view',\n  'u': 'view',\n  'wbr': 'view',\n\n  // 表单元素\n  'form': 'form',\n  'input': 'input',\n  'textarea': 'textarea',\n  'button': 'button',\n  'select': 'picker',\n  'option': 'view',\n  'optgroup': 'view',\n  'label': 'label',\n  'fieldset': 'view',\n  'datalist': 'picker',\n  'legend': 'view',\n  'output': 'view',\n\n  // 框架\n  'iframe': 'view',\n  // 图像\n  'img': 'image',\n  'canvas': 'canvas',\n  'figure': 'view',\n  'figcaption': 'view',\n\n  // 音视频\n  'audio': 'audio',\n  'source': 'audio',\n  'video': 'video',\n  'track': 'video',\n  // 链接\n  'a': 'navigator',\n  'nav': 'view',\n  'link': 'navigator',\n  // 列表\n  'ul': 'view',\n  'ol': 'view',\n  'li': 'view',\n  'dl': 'view',\n  'dt': 'view',\n  'dd': 'view',\n  'menu': 'view',\n  'command': 'view',\n\n  // 表格table\n  'table': 'view',\n  'caption': 'view',\n  'th': 'view',\n  'td': 'view',\n  'tr': 'view',\n  'thead': 'view',\n  'tbody': 'view',\n  'tfoot': 'view',\n  'col': 'view',\n  'colgroup': 'view',\n\n  // 样式\n  'div': 'view',\n  'main': 'view',\n  'span': 'label',\n  'header': 'view',\n  'footer': 'view',\n  'section': 'view',\n  'article': 'view',\n  'aside': 'view',\n  'details': 'view',\n  'dialog': 'view',\n  'summary': 'view',\n\n  'progress': 'progress',\n  'meter': 'progress',\n  'head': 'view',\n  'meta': 'view',\n  'base': 'text',\n  'area': 'navigator',\n\n  'script': 'view',\n  'noscript': 'view',\n  'embed': 'view',\n  'object': 'view',\n  'param': 'view',\n\n  // https://mp.weixin.qq.com/debug/wxadoc/dev/component/\n  // [...document.querySelectorAll('.markdown-section tbody td:first-child')].map(v => v.textContent).join(',\\n')\n  'view': 'view',\n  'scroll-view': 'scroll-view',\n  'swiper': 'swiper',\n  'icon': 'icon',\n  'text': 'text',\n  'checkbox': 'checkbox',\n  'radio': 'radio',\n  'picker': 'picker',\n  'picker-view': 'picker-view',\n  'slider': 'slider',\n  'switch': 'switch',\n  'navigator': 'navigator',\n  'image': 'image',\n  'map': 'map',\n  'contact-button': 'contact-button',\n  'block': 'block'\n};\n\nfunction maybeTag (tagName) {\n  return tagMap[tagName]\n}\n\nfunction getWxEleId (index, arr) {\n  if (!arr || !arr.length) {\n    return (\"'\" + index + \"'\")\n  }\n\n  var str = arr.join(\"+'-'+\");\n  return (\"'\" + index + \"_'+\" + str)\n}\n\n// 检查不允许在 v-for 的时候出现2个及其以上相同 iterator1\nfunction checkRepeatIterator (arr, options) {\n  var len = arr.length;\n  if (len > 1 && len !== new Set(arr).size) {\n    options.warn((\"同一组件内嵌套的 v-for 不能连续使用相同的索引，目前为: \" + arr), false);\n  }\n}\n\nfunction fixDefaultIterator (path) {\n  var forText = path.for;\n  var iterator1 = path.iterator1;\n  if (forText && !iterator1) {\n    path.iterator1 = 'index';\n  }\n}\n\nfunction addAttr$1 (path, key, value, inVdom) {\n  path[key] = value;\n  path.plain = false;\n  // path.attrsMap[key] = value\n  if (!inVdom) {\n    path.attrsMap[(\"data-\" + key)] = \"{{\" + value + \"}}\";\n  }\n\n  // if (!path.attrsList) {\n  //   path.attrsList = []\n  // }\n  // path.attrsList.push({ name: `':${key}'`, value })\n\n  if (!path.attrs) {\n    path.attrs = [];\n  }\n  path.attrs.push({ name: key, value: value });\n}\n\nfunction mark (path, options, deps, iteratorArr) {\n  if ( iteratorArr === void 0 ) iteratorArr = [];\n\n  fixDefaultIterator(path);\n\n  var tag = path.tag;\n  var children = path.children;\n  var iterator1 = path.iterator1;\n  var events = path.events;\n  var directives = path.directives;\n  var ifConditions = path.ifConditions;\n\n  var currentArr = Object.assign([], iteratorArr);\n\n  if (iterator1) {\n    currentArr.push(iterator1);\n  }\n\n  checkRepeatIterator(currentArr, options);\n\n  // 递归子节点\n  if (children && children.length) {\n    children.forEach(function (v, i) {\n      // const counterIterator = children.slice(0, i).filter(v => v.for).map(v => v.for + '.length').join(`+'-'+`)\n      mark(v, options, deps, currentArr);\n    });\n  }\n\n  // fix: v-else events\n  if (ifConditions && ifConditions.length > 1) {\n    ifConditions.slice(1).forEach(function (v, i) {\n      mark(v.block, options, deps, currentArr);\n    });\n  }\n\n  // for mpvue-template-compiler\n  // events || v-model\n  var hasModel = directives && directives.find(function (v) { return v.name === 'model'; });\n  var needEventsID = events || hasModel;\n\n  if (needEventsID) {\n    var eventId = getWxEleId(deps.eventIndex, currentArr);\n    // const eventId = getWxEleId(eIndex, currentArr)\n    addAttr$1(path, 'eventid', eventId);\n    path.attrsMap['data-comkey'] = '{{$k}}';\n    deps.eventIndex += 1;\n    // eIndex += 1\n  }\n\n  // 子组件\n  if (!tag || maybeTag(tag)) {\n    return\n  }\n\n  // eg. '1-'+i+'-'+j\n  var value = getWxEleId(deps.comIndex, currentArr);\n  addAttr$1(path, 'mpcomid', value, true);\n  path['mpcomid'] = value;\n  deps.comIndex += 1;\n}\n\n// 全局的事件触发器 ID\n// let eIndex = 0\nfunction markComponent (ast, options) {\n  var deps = { comIndex: 0, eventIndex: 0 };\n  mark(ast, options, deps);\n\n  return ast\n}\n\n/*  */\n\n// for mp\n// `createCompilerCreator` allows creating compilers that use alternative\n// parser/optimizer/codegen, e.g the SSR optimizing compiler.\n// Here we just export a default compiler using the default parts.\nvar createCompiler = createCompilerCreator(function baseCompile (\n  template$$1,\n  options\n) {\n  var originAst = parse(template$$1.trim(), options);\n  var ast = markComponent(originAst, options);\n  optimize(ast, options);\n  var code = generate$1(ast, options);\n  return {\n    ast: ast,\n    render: code.render,\n    staticRenderFns: code.staticRenderFns\n  }\n});\n\n// type：\n// 0, 默认值, 拼接 ${name}={{ ${content} }}\n// 1, 拼接 ${name}\n// 2, 拼接 ${map[key]}={{ '${content}' }}\n// 3, 拼接 {{ ${content} }}\n// 4, 拼接为空字符串\n// 5, 不需要在wxml上表现出来，可直接清除\n\nvar noSupport = {\n  type: 4,\n  check: function check (k, v, errors) {\n    errors((\"不支持此指令: \" + k + \"=\\\"\" + v + \"\\\"\"));\n    return false\n  }\n};\nvar directiveMap = {\n  'v-if': {\n    name: 'wx:if',\n    type: 0\n  },\n  'v-else-if': {\n    name: 'wx:elif',\n    type: 0\n  },\n  'v-else': {\n    name: 'wx:else',\n    type: 1\n  },\n  'v-text': {\n    name: '',\n    type: 1\n  },\n  'v-html': {\n    name: '',\n    type: 1\n  },\n  'v-on': {\n    name: '',\n    map: {\n      click: 'tap',\n      touchstart: 'touchstart',\n      touchmove: 'touchmove',\n      touchcancel: 'touchcancel',\n      touchend: 'touchend',\n      tap: 'tap',\n      longtap: 'longtap',\n      input: 'input',\n      change: 'change',\n      submit: 'submit',\n      blur: 'blur',\n      focus: 'focus',\n      reset: 'reset',\n      confirm: 'confirm',\n      columnchange: 'columnchange',\n      linechange: 'linechange',\n      error: 'error',\n      scrolltoupper: 'scrolltoupper',\n      scrolltolower: 'scrolltolower',\n      scroll: 'scroll',\n      load: 'load'\n    },\n    type: 2\n  },\n  'v-bind': {\n    name: '',\n    map: {\n      'href': 'url'\n    },\n    type: 3\n  },\n  'href': {\n    name: 'url',\n    type: 2\n  },\n  'v-pre': noSupport,\n  'v-cloak': noSupport,\n  'v-once': {\n    name: '',\n    type: 5\n  }\n};\n\nvar tagConfig = {\n  virtualTag: ['slot', 'template', 'block']\n};\n\n// babel-plugin-transform-object-to-ternary-operator.js\n\nfunction getStrByNode (node, onlyStr) {\n  if ( onlyStr === void 0 ) onlyStr = false;\n\n  if (onlyStr) {\n    return node.value || node.name || ''\n  }\n  return node.type === 'StringLiteral' ? node : t.stringLiteral(node.name || '')\n}\n\n// 把 { key: value } 转换成 [ value ? 'key' : '' ]\nvar objectVisitor = {\n  ObjectExpression: function ObjectExpression (path) {\n    var elements = path.node.properties.map(function (propertyItem) {\n      return t.conditionalExpression(propertyItem.value, getStrByNode(propertyItem.key), t.stringLiteral(''))\n    });\n    path.replaceWith(t.arrayExpression(elements));\n  }\n};\n\nfunction transformObjectToTernaryOperator (babel$$1) {\n  return { visitor: objectVisitor }\n}\n\n// 把 { key: value } 转换成 'key:' + value + ';'\nvar objectToStringVisitor = {\n  ObjectExpression: function ObjectExpression (path) {\n    var expression = path.node.properties.map(function (propertyItem) {\n      var keyStr = getStrByNode(propertyItem.key, true);\n      var key = keyStr ? hyphenate(keyStr) : keyStr;\n      var ref = generate(t.ExpressionStatement(propertyItem.value));\n      var val = ref.code;\n      return (\"'\" + key + \":' + (\" + (val.slice(0, -1)) + \") + ';'\")\n    }).join('+');\n\n    var p = template(expression)({});\n    path.replaceWith(p.expression);\n  }\n};\n\nfunction transformObjectToString (babel$$1) {\n  return { visitor: objectToStringVisitor }\n}\n\nfunction transformDynamicClass (staticClass, clsBinding) {\n  if ( staticClass === void 0 ) staticClass = '';\n\n  var result = babel.transform((\"!\" + clsBinding), { plugins: [transformObjectToTernaryOperator] });\n  // 先实现功能，再优化代码\n  // https://github.com/babel/babel/issues/7138\n  var cls = prettier.format(result.code, { semi: false, singleQuote: true }).slice(1).slice(0, -1).replace(/\\n|\\r/g, '');\n  return (staticClass + \" {{\" + cls + \"}}\")\n}\n\nfunction transformDynamicStyle (staticStyle, styleBinding) {\n  if ( staticStyle === void 0 ) staticStyle = '';\n\n  var result = babel.transform((\"!\" + styleBinding), { plugins: [transformObjectToString] });\n  var cls = prettier.format(result.code, { semi: false, singleQuote: true }).slice(1).slice(0, -1).replace(/\\n|\\r/g, '');\n  return (staticStyle + \" {{\" + cls + \"}}\")\n}\n\nvar attrs = {\n  format: function format (attrs) {\n    if ( attrs === void 0 ) attrs = {};\n\n    var obj = {};\n\n    Object.keys(attrs).map(function (key) {\n      var val = attrs[key];\n      obj[key.replace('@', 'v-on:').replace(/^:/, 'v-bind:')] = val;\n    });\n\n    return obj\n  },\n\n  convertAttr: function convertAttr (ast, log) {\n    var this$1 = this;\n\n    var attrsMap = ast.attrsMap; if ( attrsMap === void 0 ) attrsMap = {};\n    var tag = ast.tag;\n    var staticClass = ast.staticClass;\n    var attrs = {};\n    var wxClass = this.classObj(attrsMap['v-bind:class'], staticClass);\n    wxClass.length ? attrsMap['class'] = wxClass : '';\n    var wxStyle = this.styleObj(attrsMap['v-bind:style'], attrsMap['style']);\n    wxStyle.length ? attrsMap['style'] = wxStyle : '';\n\n    Object.keys(attrsMap).map(function (key) {\n      var val = attrsMap[key];\n      if (key === 'v-bind:class' || key === 'v-bind:style') {\n        return\n      }\n      if (key === 'v-text') {\n        ast.children.unshift({\n          text: (\"{{\" + val + \"}}\"),\n          type: 3\n        });\n      } else if (key === 'v-html') {\n        ast.tag = 'rich-text';\n        attrs['nodes'] = \"{{\" + val + \"}}\";\n      } else if (key === 'v-show') {\n        attrs['hidden'] = \"{{!(\" + val + \")}}\";\n      } else if (/^v\\-on\\:/i.test(key)) {\n        attrs = this$1.event(key, val, attrs, tag);\n      } else if (/^v\\-bind\\:/i.test(key)) {\n        attrs = this$1.bind(key, val, attrs, tag, attrsMap['wx:key']);\n      } else if (/^v\\-model/.test(key)) {\n        attrs = this$1.model(key, val, attrs, tag, log);\n      } else if (directiveMap[key]) {\n        var ref = directiveMap[key] || {};\n        var name = ref.name; if ( name === void 0 ) name = '';\n        var type = ref.type;\n        var map = ref.map; if ( map === void 0 ) map = {};\n        var check = ref.check;\n        if (!(check && !check(key, val, log)) && !(!name || typeof type !== 'number')) {\n          // 见 ./directiveMap.js 注释\n          if (type === 0) {\n            attrs[name] = \"{{\" + val + \"}}\";\n          }\n\n          if (type === 1) {\n            attrs[name] = undefined;\n          }\n\n          if (type === 2) {\n            attrs[name] = val;\n          }\n\n          if (type === 3) {\n            attrs[map[name] || name] = \"{{\" + val + \"}}\";\n            return\n          }\n        }\n      } else if (/^v\\-/.test(key)) {\n        log((\"不支持此属性-> \" + key + \"=\\\"\" + val + \"\\\"\"), 'waring');\n      } else {\n        if ((tagConfig.virtualTag.indexOf(tag) > -1) && (key === 'class' || key === 'style' || key === 'data-mpcomid')) {\n          if (key !== 'data-mpcomid') {\n            log((\"template 不支持此属性-> \" + key + \"=\\\"\" + val + \"\\\"\"), 'waring');\n          }\n        } else {\n          attrs[key] = val;\n        }\n      }\n    });\n    ast.attrsMap = attrs;\n    return ast\n  },\n\n  event: function event (key, val, attrs, tag) {\n    // 小程序能力所致，bind 和 catch 事件同时绑定时候，只会触发 bind ,catch 不会被触发。\n    // .stop 的使用会阻止冒泡，但是同时绑定了一个非冒泡事件，会导致该元素上的 catchEventName 失效！\n    // .prevent 可以直接干掉，因为小程序里没有什么默认事件，比如submit并不会跳转页面\n    // .capture 不能做，因为小程序没有捕获类型的事件\n    // .self 没有可以判断的标识\n    // .once 也不能做，因为小程序没有 removeEventListener, 虽然可以直接在 handleProxy 中处理，但非常的不优雅，违背了原意，暂不考虑\n    var name = key.replace(/^v\\-on\\:/i, '').replace(/\\.prevent/i, '');\n    var ref = name.split('.');\n    var eventName = ref[0];\n    var eventNameMap = ref.slice(1);\n    var eventMap = directiveMap['v-on'];\n    var check = directiveMap.check;\n\n    if (check) {\n      check(key, val);\n    }\n    var wxmlEventName = '';\n    if (eventName === 'change' && (tag === 'input' || tag === 'textarea')) {\n      wxmlEventName = 'blur';\n    } else {\n      wxmlEventName = eventMap.map[eventName];\n    }\n\n    var eventType = 'bind';\n    var isStop = eventNameMap.includes('stop');\n    if (eventNameMap.includes('capture')) {\n      eventType = isStop ? 'capture-catch:' : 'capture-bind:';\n    } else if (isStop) {\n      eventType = 'catch';\n    }\n\n    wxmlEventName = eventType + (wxmlEventName || eventName);\n    attrs[wxmlEventName] = 'handleProxy';\n\n    return attrs\n  },\n\n  bind: function bind (key, val, attrs, tag, isIf) {\n    var name = key.replace(/^v\\-bind\\:/i, '');\n\n    if (isIf && name === 'key') {\n      attrs['wx:key'] = val;\n    }\n\n    if (tag === 'template') {\n      return attrs\n    }\n\n    if (name === 'href') {\n      attrs['url'] = \"{{\" + val + \"}}\";\n    } else {\n      attrs[name] = \"{{\" + val + \"}}\";\n    }\n\n    return attrs\n  },\n\n  classObj: function classObj (clsBinding, staticCls) {\n    if ( clsBinding === void 0 ) clsBinding = '';\n\n    if (!clsBinding && !staticCls) {\n      return ''\n    }\n    if (!clsBinding && staticCls) {\n      return staticCls\n    }\n\n    return transformDynamicClass(staticCls, clsBinding)\n  },\n\n  styleObj: function styleObj (styleBinding, staticStyle) {\n    if ( styleBinding === void 0 ) styleBinding = '';\n\n    if (!styleBinding && !staticStyle) {\n      return ''\n    }\n    if (!styleBinding && staticStyle) {\n      return staticStyle\n    }\n\n    return transformDynamicStyle(staticStyle, styleBinding)\n  },\n\n  model: function model (key, val, attrs, tag) {\n    var isFormInput = tag === 'input' || tag === 'textarea';\n    attrs['value'] = \"{{\" + val + \"}}\";\n    if (key === 'v-model.lazy') {\n      if (isFormInput) {\n        attrs['bindblur'] = 'handleProxy';\n      } else {\n        attrs['bindchange'] = 'handleProxy';\n      }\n    } else {\n      if (isFormInput) {\n        attrs['bindinput'] = 'handleProxy';\n      } else {\n        attrs['bindchange'] = 'handleProxy';\n      }\n    }\n\n    return attrs\n  }\n};\n\nfunction getSlotsName (obj) {\n  if (!obj) {\n    return ''\n  }\n  // wxml模板中 data=\"{{ a:{a1:'string2'}, b:'string'}}\" 键a不能放在最后，会出错\n  return tmplateSlotsObj(obj)\n    .concat(\n      Object.keys(obj).map(function(k) {\n        return '$slot' + k + \":'\" + obj[k] + \"'\"\n      })\n    )\n    .join(',')\n}\n\nfunction tmplateSlotsObj(obj) {\n  if (!obj) {\n    return []\n  }\n  // wxml模板中 data=\"{{ a:{a1:'string2'}, b:'string'}}\" 键a1不能写成 'a1' 带引号的形式，会出错\n  var $for = Object.keys(obj)\n    .map(function(k) {\n      return (k + \":'\" + (obj[k]) + \"'\")\n    })\n    .join(',');\n  return $for ? [(\"$for:{\" + $for + \"}\")] : []\n}\n\nvar component = {\n  isComponent: function isComponent (tagName, components) {\n    if ( components === void 0 ) components = {};\n\n    return !!components[tagName]\n  },\n  convertComponent: function convertComponent (ast, components, slotName) {\n    var attrsMap = ast.attrsMap;\n    var tag = ast.tag;\n    var mpcomid = ast.mpcomid;\n    var slots = ast.slots;\n    if (slotName) {\n      attrsMap['data'] = \"{{...$root[$p], ...$root[$k], $root}}\";\n      // bindedName is available when rendering slot in v-for\n      var bindedName = attrsMap['v-bind:name'];\n      if(bindedName) {\n        attrsMap['is'] = \"{{$for[\" + bindedName + \"]}}\";\n      } else {\n        attrsMap['is'] = \"{{\" + slotName + \"}}\";\n      }\n    } else {\n      var slotsName = getSlotsName(slots);\n      var restSlotsName = slotsName ? (\", \" + slotsName) : '';\n      attrsMap['data'] = \"{{...$root[$kk+\" + mpcomid + \"], $root\" + restSlotsName + \"}}\";\n      attrsMap['is'] = components[tag].name;\n    }\n    return ast\n  }\n};\n\nvar astMap = {\n  'if': 'wx:if',\n  'iterator1': 'wx:for-index',\n  'key': 'wx:key',\n  'alias': 'wx:for-item',\n  'v-for': 'wx:for'\n};\n\nvar convertFor = function (ast) {\n  var iterator1 = ast.iterator1;\n  var forText = ast.for;\n  var key = ast.key;\n  var alias = ast.alias;\n  var attrsMap = ast.attrsMap;\n\n  if (forText) {\n    attrsMap[astMap['v-for']] = \"{{\" + forText + \"}}\";\n    if (iterator1) {\n      attrsMap[astMap['iterator1']] = iterator1;\n    }\n    if (key) {\n      attrsMap[astMap['key']] = key;\n    }\n    if (alias) {\n      attrsMap[astMap['alias']] = alias;\n    }\n\n    delete attrsMap['v-for'];\n  }\n\n  return ast\n};\n\n// import component from './component'\nvar tag = function (ast, options, component) {\n  var tag = ast.tag;\n  var elseif = ast.elseif;\n  var elseText = ast.else;\n  var forText = ast.for;\n  var staticClass = ast.staticClass; if ( staticClass === void 0 ) staticClass = '';\n  var attrsMap = ast.attrsMap; if ( attrsMap === void 0 ) attrsMap = {};\n  var components = options.components;\n  var ifText = attrsMap['v-if'];\n  var href = attrsMap.href;\n  var bindHref = attrsMap['v-bind:href'];\n  var name = attrsMap.name;\n\n  if (!tag) {\n    return ast\n  }\n  var isComponent = component.isComponent(tag, components);\n  if (tag !== 'template' && tag !== 'block' && tag !== 'slot' && !isComponent) {\n    ast.staticClass = staticClass ? (\"_\" + tag + \" \" + staticClass) : (\"_\" + tag);\n  }\n  ast.tag = tagMap[tag] || tag;\n\n  var isSlot = tag === 'slot';\n\n  if ((ifText || elseif || elseText || forText) && tag === 'template') {\n    ast.tag = 'block';\n  } else if (isComponent || isSlot) {\n    var originSlotName = name || 'default';\n    var slotName = isSlot ? (\"$slot\" + originSlotName + \" || '\" + originSlotName + \"'\") : undefined;\n\n    // 用完必须删除，不然会被编译成 <template name=\"xxx\"> 在小程序中就会表示这是一个模版申明而不是使用，小程序中不能同时申明和使用模版\n    delete ast.attrsMap.name;\n    ast = component.convertComponent(ast, components, slotName);\n    ast.tag = 'template';\n  } else if (tag === 'a' && !(href || bindHref)) {\n    ast.tag = 'view';\n  } else if (ast.events && ast.events.scroll) {\n    ast.tag = 'scroll-view';\n  } else if (tag === 'input') {\n    var type = attrsMap.type;\n    if (type && ['button', 'checkbox', 'radio'].indexOf(type) > -1) {\n      delete ast.attrsMap.type;\n      ast.tag = type;\n    }\n    if (type === 'button') {\n      ast.children.push({\n        text: attrsMap.value || '',\n        type: 3\n      });\n      delete ast.attrsMap.value;\n    }\n  }\n  return ast\n};\n\nfunction convertAst (node, options, util, conventRule) {\n  if ( options === void 0 ) options = {};\n\n  var children = node.children;\n  var ifConditions = node.ifConditions;\n  var staticClass = node.staticClass; if ( staticClass === void 0 ) staticClass = '';\n  var mpcomid = node.mpcomid;\n  var tagName = node.tag;\n  var log = util.log;\n  var deps = util.deps;\n  var slots = util.slots;\n  var slotTemplates = util.slotTemplates;\n  var mpmlAst = Object.assign({}, node);\n  var moduleId = options.moduleId;\n  var components = options.components;\n  mpmlAst.tag = tagName = tagName ? hyphenate(tagName) : tagName;\n  // 引入 import, isSlot 是使用 slot 的编译地方，意即 <slot></slot> 的地方\n  var isSlot = tagName === 'slot';\n  if (isSlot) {\n    deps.slots = 'slots';\n    // 把当前 slot 节点包裹 template\n    var defSlot = Object.assign({}, mpmlAst);\n    defSlot.tag = 'template';\n    var templateName = \"\" + (defSlot.attrsMap.name || 'default');\n    defSlot.attrsMap.name = templateName;\n    mpmlAst.children = [];\n    defSlot.parent = node.parent.parent;\n    slotTemplates[templateName] = defSlot;\n  }\n\n  var currentIsComponent = conventRule.component.isComponent(tagName, components);\n  if (currentIsComponent) {\n    deps[tagName] = tagName;\n  }\n\n  if (moduleId && !currentIsComponent && tagConfig.virtualTag.indexOf(tagName) < 0) {\n    mpmlAst.staticClass = staticClass ? (moduleId + \" \" + staticClass).replace(/\\\"/g, '') : moduleId;\n  } else {\n    mpmlAst.staticClass = staticClass.replace(/\\\"/g, '');\n  }\n\n  // 组件内部的node节点全部是 slot\n  mpmlAst.slots = {};\n  if (currentIsComponent && children && children.length) {\n    // 只检查组件下的子节点（不检查孙子节点）是不是具名 slot，不然就是 default slot\n    children\n      .reduce(function (res, n) {\n        var ref = n.attrsMap || {};\n        var slot = ref.slot;\n        // 不是具名的，全部放在第一个数组元素中\n        var arr = slot ? res : res[0];\n        arr.push(n);\n        return res\n      }, [[]])\n      .forEach(function (n) {\n        var isDefault = Array.isArray(n);\n        var slotName = isDefault ? 'default' : n.attrsMap.slot;\n        var slotId = moduleId + \"-\" + slotName + \"-\" + (mpcomid.replace(/\\'/g, ''));\n        var node = isDefault ? { tag: 'slot', attrsMap: {}, children: n } : n;\n\n        node.tag = 'template';\n        node.attrsMap.name = slotId;\n        delete node.attrsMap.slot;\n        // 缓存，会集中生成一个 slots 文件\n        slots[slotId] = { node: convertAst(node, options, util, conventRule), name: slotName, slotId: slotId };\n        mpmlAst.slots[slotName] = slotId;\n      });\n    // 清理当前组件下的节点信息，因为 slot 都被转移了\n    children.length = 0;\n    mpmlAst.children.length = 0;\n  }\n\n  mpmlAst.attrsMap = conventRule.attrs.format(mpmlAst.attrsMap);\n  mpmlAst = tag(mpmlAst, options, conventRule.component);\n  mpmlAst = conventRule.convertFor(mpmlAst, options);\n  mpmlAst = conventRule.attrs.convertAttr(mpmlAst, log);\n  if (children && !isSlot) {\n    mpmlAst.children = children.map(function (k) { return convertAst(k, options, util, conventRule); });\n  }\n\n  if (ifConditions) {\n    var length = ifConditions.length;\n    for (var i = 1; i < length; i++) {\n      mpmlAst.ifConditions[i].block = convertAst(ifConditions[i].block, options, util, conventRule);\n    }\n  }\n\n  return mpmlAst\n}\n\nfunction getAstCommon (compiled, options, log, conventRule) {\n  if ( options === void 0 ) options = {};\n\n  var ast = compiled.ast;\n  var deps = {\n    // slots: 'slots'\n  };\n  var slots = {\n    // slotId: nodeAst\n  };\n  var slotTemplates = {\n  };\n\n  var wxast = convertAst(ast, options, { log: log, deps: deps, slots: slots, slotTemplates: slotTemplates }, conventRule);\n  var children = Object.keys(slotTemplates).map(function (k) { return convertAst(slotTemplates[k], options, { log: log, deps: deps, slots: slots, slotTemplates: slotTemplates }, conventRule); });\n  wxast.children = children.concat(wxast.children);\n  return {\n    wxast: wxast,\n    deps: deps,\n    slots: slots\n  }\n}\n\nfunction mpmlAst (compiled, options, log) {\n  if ( options === void 0 ) options = {};\n\n  var conventRule = { attrs: attrs, component: component, convertFor: convertFor };\n  return getAstCommon(compiled, options, log, conventRule)\n}\n\nvar utils = {\n  toLowerCase: function toLowerCase (str) {\n    return str.replace(/([A-Z])/g, '-$1').toLowerCase().trim()\n  },\n\n  getChar: function getChar (index) {\n    return String.fromCharCode(0x61 + index)\n  },\n\n  log: function log (compiled) {\n    compiled.mpErrors = [];\n    compiled.mpTips = [];\n\n    return function (str, type) {\n      if (type === 'waring') {\n        compiled.mpTips.push(str);\n      } else {\n        compiled.mpErrors.push(str);\n      }\n    }\n  }\n};\n\nvar autoEndTags = [\n  'progress',\n  'checkbox',\n  'switch',\n  'input',\n  'radio',\n  'slider',\n  'textarea'\n];\n\nfunction convertAttr (key, val) {\n  return (val === '' || typeof val === 'undefined') ? key : (key + \"=\\\"\" + val + \"\\\"\")\n}\n\nfunction generateCode (nodeAst, options) {\n  if ( options === void 0 ) options = {};\n\n  var tag = nodeAst.tag;\n  var attrsMap = nodeAst.attrsMap; if ( attrsMap === void 0 ) attrsMap = {};\n  var children = nodeAst.children; if ( children === void 0 ) children = [];\n  var text = nodeAst.text;\n  var ifConditions = nodeAst.ifConditions; if ( ifConditions === void 0 ) ifConditions = [];\n  if (!tag) {\n    return text\n  }\n  // v-if 指令\n  var ifConditionsArr = [];\n  if (ifConditions) {\n    var length = ifConditions.length;\n    for (var i = 1; i < length; i++) {\n      ifConditionsArr.push(generateCode(ifConditions[i].block, options));\n    }\n  }\n  var childrenContent = children.map(function (childAst) { return generateCode(childAst, options); }).join('');\n  var attrs = Object.keys(attrsMap).map(function (key) { return convertAttr(key, attrsMap[key]); }).join(' ');\n  attrs = attrs ? (\" \" + attrs) : '';\n\n  if (autoEndTags.indexOf(tag) > -1 && !childrenContent) {\n    return (\"<\" + tag + attrs + \" />\" + (ifConditionsArr.join('')))\n  }\n  return (\"<\" + tag + attrs + \">\" + childrenContent + \"</\" + tag + \">\" + (ifConditionsArr.join('')))\n\n  // if (autoEndTags.indexOf(tag) > -1 && !children.length) {\n  //   return `<${tag}${attrs ? ' ' + attrs : ''} />${ifConditionsArr.join('')}`\n  // }\n  // return `<${tag}${attrs ? ' ' + attrs : ''}>${childrenContent}</${tag}>${ifConditionsArr.join('')}`\n}\n\n\nfunction compileToMPMLCommon (compiled, options, getAst) {\n  if ( options === void 0 ) options = {};\n\n  // TODO, compiled is undefined\n  var components = options.components; if ( components === void 0 ) components = {};\n  var log = utils.log(compiled);\n\n  var ref = getAst(compiled, options, log);\n  var wxast = ref.wxast;\n  var deps = ref.deps; if ( deps === void 0 ) deps = {};\n  var slots = ref.slots; if ( slots === void 0 ) slots = {};\n  var code = generateCode(wxast, options);\n\n  // 引用子模版\n  var importCode = Object.keys(deps).map(function (k) { return components[k] ? (\"<import src=\\\"\" + (components[k].src) + \"\\\" />\") : ''; }).join('');\n  code = importCode + \"<template name=\\\"\" + (options.name) + \"\\\">\" + code + \"</template>\";\n\n  // 生成 slots code\n  Object.keys(slots).forEach(function (k) {\n    var slot = slots[k];\n    slot.code = generateCode(slot.node, options);\n  });\n\n  // TODO: 后期优化掉这种暴力全部 import，虽然对性能没啥大影响\n  return { code: code, compiled: compiled, slots: slots, importCode: importCode }\n}\n\nfunction compileToMPML$1 (compiled, options) {\n  if ( options === void 0 ) options = {};\n\n  return compileToMPMLCommon(compiled, options, mpmlAst)\n}\n\n// type：\n// 0, 默认值, 拼接 ${name}={{ ${content} }}\n// 1, 拼接 ${name}\n// 2, 拼接 ${map[key]}={{ '${content}' }}\n// 3, 拼接 {{ ${content} }}\n// 4, 拼接为空字符串\n// 5, 不需要在wxml上表现出来，可直接清除\n\nvar noSupport$1 = {\n  type: 4,\n  check: function check (k, v, errors) {\n    errors((\"不支持此指令: \" + k + \"=\\\"\" + v + \"\\\"\"));\n    return false\n  }\n};\nvar directiveMap$1 = {\n  'v-if': {\n    name: 's-if',\n    type: 2\n  },\n  'v-else-if': {\n    name: 's-elif',\n    type: 2\n  },\n  'v-else': {\n    name: 's-else',\n    type: 1\n  },\n  'v-text': {\n    name: '',\n    type: 1\n  },\n  'v-html': {\n    name: '',\n    type: 1\n  },\n  'v-on': {\n    name: '',\n    map: {\n      click: 'tap',\n      touchstart: 'touchstart',\n      touchmove: 'touchmove',\n      touchcancel: 'touchcancel',\n      touchend: 'touchend',\n      tap: 'tap',\n      longtap: 'longtap',\n      input: 'input',\n      change: 'change',\n      submit: 'submit',\n      blur: 'blur',\n      focus: 'focus',\n      reset: 'reset',\n      confirm: 'confirm',\n      columnchange: 'columnchange',\n      linechange: 'linechange',\n      error: 'error',\n      scrolltoupper: 'scrolltoupper',\n      scrolltolower: 'scrolltolower',\n      scroll: 'scroll',\n      load: 'load'\n    },\n    type: 2\n  },\n  'v-bind': {\n    name: '',\n    map: {\n      'href': 'url'\n    },\n    type: 3\n  },\n  'href': {\n    name: 'url',\n    type: 2\n  },\n  'v-pre': noSupport$1,\n  'v-cloak': noSupport$1,\n  'v-once': {\n    name: '',\n    type: 5\n  }\n};\n\nfunction transformDynamicClass$1 (staticClass, clsBinding) {\n  if ( staticClass === void 0 ) staticClass = '';\n\n  var result = babel.transform((\"!\" + clsBinding), { plugins: [transformObjectToTernaryOperator] });\n  // 先实现功能，再优化代码\n  // https://github.com/babel/babel/issues/7138\n  var cls = prettier.format(result.code, { semi: false, singleQuote: true }).slice(1).slice(0, -1).replace(/\\n|\\r/g, '');\n  return (staticClass + \" {{\" + cls + \"}}\")\n}\n\nfunction transformDynamicStyle$1 (staticStyle, styleBinding) {\n  if ( staticStyle === void 0 ) staticStyle = '';\n\n  var result = babel.transform((\"!\" + styleBinding), { plugins: [transformObjectToString] });\n  var cls = prettier.format(result.code, { semi: false, singleQuote: true }).slice(1).slice(0, -1).replace(/\\n|\\r/g, '');\n  return (staticStyle + \" {{\" + cls + \"}}\")\n}\n\nvar attrs$1 = {\n  format: function format (attrs) {\n    if ( attrs === void 0 ) attrs = {};\n\n    var obj = {};\n\n    Object.keys(attrs).map(function (key) {\n      var val = attrs[key];\n      obj[key.replace('@', 'v-on:').replace(/^:/, 'v-bind:')] = val;\n    });\n\n    return obj\n  },\n\n  convertAttr: function convertAttr (ast, log) {\n    var this$1 = this;\n\n    var attrsMap = ast.attrsMap; if ( attrsMap === void 0 ) attrsMap = {};\n    var tag = ast.tag;\n    var staticClass = ast.staticClass;\n    var attrs = {};\n    var wxClass = this.classObj(attrsMap['v-bind:class'], staticClass);\n    wxClass.length ? attrsMap['class'] = wxClass : '';\n    var wxStyle = this.styleObj(attrsMap['v-bind:style'], attrsMap['style']);\n    wxStyle.length ? attrsMap['style'] = wxStyle : '';\n\n    Object.keys(attrsMap).map(function (key) {\n      var val = attrsMap[key];\n      if (key === 'v-bind:class' || key === 'v-bind:style') {\n        return\n      }\n      if (key === 'v-text') {\n        ast.children.unshift({\n          text: (\"{{\" + val + \"}}\"),\n          type: 3\n        });\n      } else if (key === 'v-html') {\n        ast.tag = 'rich-text';\n        attrs['nodes'] = \"{{\" + val + \"}}\";\n      } else if (key === 'v-show') {\n        attrs['hidden'] = \"{{!(\" + val + \")}}\";\n      } else if (/^v\\-on\\:/i.test(key)) {\n        attrs = this$1.event(key, val, attrs, tag);\n      } else if (/^v\\-bind\\:/i.test(key)) {\n        attrs = this$1.bind(key, val, attrs, tag, attrsMap['wx:key']);\n      } else if (/^v\\-model/.test(key)) {\n        attrs = this$1.model(key, val, attrs, tag, log);\n      } else if (directiveMap$1[key]) {\n        var ref = directiveMap$1[key] || {};\n        var name = ref.name; if ( name === void 0 ) name = '';\n        var type = ref.type;\n        var map = ref.map; if ( map === void 0 ) map = {};\n        var check = ref.check;\n        if (!(check && !check(key, val, log)) && !(!name || typeof type !== 'number')) {\n          // 见 ./directiveMap.js 注释\n          if (type === 0) {\n            attrs[name] = \"{{\" + val + \"}}\";\n          }\n\n          if (type === 1) {\n            attrs[name] = undefined;\n          }\n\n          if (type === 2) {\n            attrs[name] = val;\n          }\n\n          if (type === 3) {\n            attrs[map[name] || name] = \"{{\" + val + \"}}\";\n            return\n          }\n        }\n      } else if (/^v\\-/.test(key)) {\n        log((\"不支持此属性-> \" + key + \"=\\\"\" + val + \"\\\"\"), 'waring');\n      } else {\n        if ((tagConfig.virtualTag.indexOf(tag) > -1) && (key === 'class' || key === 'style' || key === 'data-mpcomid')) {\n          if (key !== 'data-mpcomid') {\n            log((\"template 不支持此属性-> \" + key + \"=\\\"\" + val + \"\\\"\"), 'waring');\n          }\n        } else {\n          attrs[key] = val;\n        }\n      }\n    });\n    ast.attrsMap = attrs;\n    return ast\n  },\n\n  event: function event (key, val, attrs, tag) {\n    // 小程序能力所致，bind 和 catch 事件同时绑定时候，只会触发 bind ,catch 不会被触发。\n    // .stop 的使用会阻止冒泡，但是同时绑定了一个非冒泡事件，会导致该元素上的 catchEventName 失效！\n    // .prevent 可以直接干掉，因为小程序里没有什么默认事件，比如submit并不会跳转页面\n    // .capture 不能做，因为小程序没有捕获类型的事件\n    // .self 没有可以判断的标识\n    // .once 也不能做，因为小程序没有 removeEventListener, 虽然可以直接在 handleProxy 中处理，但非常的不优雅，违背了原意，暂不考虑\n    var name = key.replace(/^v\\-on\\:/i, '').replace(/\\.prevent/i, '');\n    var ref = name.split('.');\n    var eventName = ref[0];\n    var eventNameMap = ref.slice(1);\n    var eventMap = directiveMap$1['v-on'];\n    var check = directiveMap$1.check;\n\n    if (check) {\n      check(key, val);\n    }\n    var wxmlEventName = '';\n    if (eventName === 'change' && (tag === 'input' || tag === 'textarea')) {\n      wxmlEventName = 'blur';\n    } else {\n      wxmlEventName = eventMap.map[eventName];\n    }\n\n    var eventType = 'bind';\n    var isStop = eventNameMap.includes('stop');\n    if (eventNameMap.includes('capture')) {\n      eventType = isStop ? 'capture-catch:' : 'capture-bind:';\n    } else if (isStop) {\n      eventType = 'catch';\n    }\n\n    wxmlEventName = eventType + (wxmlEventName || eventName);\n    attrs[wxmlEventName] = 'handleProxy';\n\n    return attrs\n  },\n\n  bind: function bind (key, val, attrs, tag, isIf) {\n    var name = key.replace(/^v\\-bind\\:/i, '');\n\n    if (isIf && name === 'key') {\n      attrs['wx:key'] = val;\n    }\n\n    if (tag === 'template') {\n      return attrs\n    }\n\n    if (name === 'href') {\n      attrs['url'] = \"{{\" + val + \"}}\";\n    } else {\n      attrs[name] = \"{{\" + val + \"}}\";\n    }\n\n    if (tag === 'scroll-view') {\n      if (name === 'scroll-top' || name === 'scroll-left' || name === 'scroll-into-view') {\n        attrs[name] = \"{=\" + val + \"=}\";\n      }\n    }\n\n    if (tag === 'input' || tag === 'textarea' || tag === 'slider') {\n      if (name === 'value') {\n        attrs[name] = \"{=\" + val + \"=}\";\n      }\n    }\n\n    if (tag === 'movable-view' && (name === 'x' || name === 'y')) {\n      attrs[name] = \"{=\" + val + \"=}\";\n    }\n\n    return attrs\n  },\n\n  classObj: function classObj (clsBinding, staticCls) {\n    if ( clsBinding === void 0 ) clsBinding = '';\n\n    if (!clsBinding && !staticCls) {\n      return ''\n    }\n    if (!clsBinding && staticCls) {\n      return staticCls\n    }\n\n    return transformDynamicClass$1(staticCls, clsBinding)\n  },\n\n  styleObj: function styleObj (styleBinding, staticStyle) {\n    if ( styleBinding === void 0 ) styleBinding = '';\n\n    if (!styleBinding && !staticStyle) {\n      return ''\n    }\n    if (!styleBinding && staticStyle) {\n      return staticStyle\n    }\n\n    return transformDynamicStyle$1(staticStyle, styleBinding)\n  },\n\n  model: function model (key, val, attrs, tag) {\n    var isFormInput = tag === 'input' || tag === 'textarea';\n    attrs['value'] = \"{{\" + val + \"}}\";\n    if (key === 'v-model.lazy') {\n      if (isFormInput) {\n        attrs['bindblur'] = 'handleProxy';\n      } else {\n        attrs['bindchange'] = 'handleProxy';\n      }\n    } else {\n      if (isFormInput) {\n        attrs['bindinput'] = 'handleProxy';\n      } else {\n        attrs['bindchange'] = 'handleProxy';\n      }\n    }\n\n    return attrs\n  }\n};\n\nfunction getSlotsName$1 (obj) {\n  if (!obj) {\n    return ''\n  }\n  // wxml模板中 data=\"{{ a:{a1:'string2'}, b:'string'}}\" 键a不能放在最后，会出错\n  return tmplateSlotsObj$1(obj)\n    .concat(\n      Object.keys(obj).map(function (k) { return (\"$slot\" + k + \":'\" + (obj[k]) + \"'\"); })\n    )\n    .join(',')\n}\n\nfunction tmplateSlotsObj$1 (obj) {\n  if (!obj) {\n    return []\n  }\n  // wxml模板中 data=\"{{ a:{a1:'string2'}, b:'string'}}\" 键a1不能写成 'a1' 带引号的形式，会出错\n  var $for = Object.keys(obj)\n    .map(function (k) { return (k + \":'\" + (obj[k]) + \"'\"); })\n    .join(',');\n  return $for ? [(\"$for:{\" + $for + \"}\")] : []\n}\n\nvar component$1 = {\n  isComponent: function isComponent (tagName, components) {\n    if ( components === void 0 ) components = {};\n\n    return !!components[tagName]\n  },\n  convertComponent: function convertComponent (ast, components, slotName) {\n    var attrsMap = ast.attrsMap;\n    var tag = ast.tag;\n    var mpcomid = ast.mpcomid;\n    var slots = ast.slots;\n    if (slotName) {\n      attrsMap['data'] = '{{{...$root[$k], $root}}}';\n      // bindedName is available when rendering slot in v-for\n      var bindedName = attrsMap['v-bind:name'];\n      if (bindedName) {\n        attrsMap['is'] = '{{$for[' + bindedName + ']}}';\n      } else {\n        attrsMap['is'] = '{{' + slotName + '}}';\n      }\n    } else {\n      var slotsName = getSlotsName$1(slots);\n      var restSlotsName = slotsName ? (\", \" + slotsName) : '';\n      attrsMap['data'] = \"{{{...$root[$kk+\" + mpcomid + \"], $root\" + restSlotsName + \"}}}\";\n      attrsMap['is'] = components[tag].name;\n    }\n    return ast\n  }\n};\n\nvar astMap$1 = {\n  'if': 's-if',\n  'v-for': 's-for',\n  'alias': 's-for-item',\n  'iterator1': 's-for-index',\n  'key': 's-key'\n};\n\nvar convertFor$1 = function (ast) {\n  var iterator1 = ast.iterator1;\n  var forText = ast.for;\n  var key = ast.key;\n  var alias = ast.alias;\n  var attrsMap = ast.attrsMap;\n\n  // 缩写：<view s-for=\"p,index in persons\">\n  // 全写：<view s-for=\"persons\" s-for-index=\"index\" s-for-item=\"p\">\n\n  if (forText) {\n    attrsMap[astMap$1['v-for']] = alias + \",\" + iterator1 + \" in \" + forText;\n    // attrsMap[astMap['v-for']] = forText\n    // if (iterator1) {\n    //   attrsMap[astMap['iterator1']] = iterator1\n    // }\n    // if (alias) {\n    //   attrsMap[astMap['alias']] = alias\n    // }\n    // if (key) {\n    //   attrsMap[astMap['key']] = key\n    // }\n    delete attrsMap['v-for'];\n  }\n\n\n  return ast\n};\n\nfunction mpmlAst$1 (compiled, options, log) {\n  if ( options === void 0 ) options = {};\n\n  var conventRule = { attrs: attrs$1, component: component$1, convertFor: convertFor$1 };\n  return getAstCommon(compiled, options, log, conventRule)\n}\n\nfunction compileToMPML$2 (compiled, options) {\n  if ( options === void 0 ) options = {};\n\n  return compileToMPMLCommon(compiled, options, mpmlAst$1)\n}\n\n// type：\n// 0, 默认值, 拼接 ${name}={{ ${content} }}\n// 1, 拼接 ${name}\n// 2, 拼接 ${map[key]}={{ '${content}' }}\n// 3, 拼接 {{ ${content} }}\n// 4, 拼接为空字符串\n// 5, 不需要在wxml上表现出来，可直接清除\n\nvar noSupport$2 = {\n  type: 4,\n  check: function check (k, v, errors) {\n    errors((\"不支持此指令: \" + k + \"=\\\"\" + v + \"\\\"\"));\n    return false\n  }\n};\nvar directiveMap$2 = {\n  'v-if': {\n    name: 'tt:if',\n    type: 0\n  },\n  'v-else-if': {\n    name: 'tt:elif',\n    type: 0\n  },\n  'v-else': {\n    name: 'tt:else',\n    type: 1\n  },\n  'v-text': {\n    name: '',\n    type: 1\n  },\n  'v-html': {\n    name: '',\n    type: 1\n  },\n  'v-on': {\n    name: '',\n    map: {\n      click: 'tap',\n      touchstart: 'touchstart',\n      touchmove: 'touchmove',\n      touchcancel: 'touchcancel',\n      touchend: 'touchend',\n      tap: 'tap',\n      longtap: 'longtap',\n      input: 'input',\n      change: 'change',\n      submit: 'submit',\n      blur: 'blur',\n      focus: 'focus',\n      reset: 'reset',\n      confirm: 'confirm',\n      columnchange: 'columnchange',\n      linechange: 'linechange',\n      error: 'error',\n      scrolltoupper: 'scrolltoupper',\n      scrolltolower: 'scrolltolower',\n      scroll: 'scroll',\n      load: 'load'\n    },\n    type: 2\n  },\n  'v-bind': {\n    name: '',\n    map: {\n      'href': 'url'\n    },\n    type: 3\n  },\n  'href': {\n    name: 'url',\n    type: 2\n  },\n  'v-pre': noSupport$2,\n  'v-cloak': noSupport$2,\n  'v-once': {\n    name: '',\n    type: 5\n  }\n};\n\nfunction transformDynamicClass$2 (staticClass, clsBinding) {\n  if ( staticClass === void 0 ) staticClass = '';\n\n  var result = babel.transform((\"!\" + clsBinding), { plugins: [transformObjectToTernaryOperator] });\n  // 先实现功能，再优化代码\n  // https://github.com/babel/babel/issues/7138\n  var cls = prettier.format(result.code, { semi: false, singleQuote: true }).slice(1).slice(0, -1).replace(/\\n|\\r/g, '');\n  return (staticClass + \" {{\" + cls + \"}}\")\n}\n\nfunction transformDynamicStyle$2 (staticStyle, styleBinding) {\n  if ( staticStyle === void 0 ) staticStyle = '';\n\n  var result = babel.transform((\"!\" + styleBinding), { plugins: [transformObjectToString] });\n  var cls = prettier.format(result.code, { semi: false, singleQuote: true }).slice(1).slice(0, -1).replace(/\\n|\\r/g, '');\n  return (staticStyle + \" {{\" + cls + \"}}\")\n}\n\nvar attrs$2 = {\n  format: function format (attrs) {\n    if ( attrs === void 0 ) attrs = {};\n\n    var obj = {};\n\n    Object.keys(attrs).map(function (key) {\n      var val = attrs[key];\n      obj[key.replace('@', 'v-on:').replace(/^:/, 'v-bind:')] = val;\n    });\n\n    return obj\n  },\n\n  convertAttr: function convertAttr (ast, log) {\n    var this$1 = this;\n\n    var attrsMap = ast.attrsMap; if ( attrsMap === void 0 ) attrsMap = {};\n    var tag = ast.tag;\n    var staticClass = ast.staticClass;\n    var attrs = {};\n    var wxClass = this.classObj(attrsMap['v-bind:class'], staticClass);\n    wxClass.length ? attrsMap['class'] = wxClass : '';\n    var wxStyle = this.styleObj(attrsMap['v-bind:style'], attrsMap['style']);\n    wxStyle.length ? attrsMap['style'] = wxStyle : '';\n\n    Object.keys(attrsMap).map(function (key) {\n      var val = attrsMap[key];\n      if (key === 'v-bind:class' || key === 'v-bind:style') {\n        return\n      }\n      if (key === 'v-text') {\n        ast.children.unshift({\n          text: (\"{{\" + val + \"}}\"),\n          type: 3\n        });\n      } else if (key === 'v-html') {\n        ast.tag = 'rich-text';\n        attrs['nodes'] = \"{{\" + val + \"}}\";\n      } else if (key === 'v-show') {\n        attrs['hidden'] = \"{{!(\" + val + \")}}\";\n      } else if (/^v\\-on\\:/i.test(key)) {\n        attrs = this$1.event(key, val, attrs, tag);\n      } else if (/^v\\-bind\\:/i.test(key)) {\n        attrs = this$1.bind(key, val, attrs, tag, attrsMap['tt:key']);\n      } else if (/^v\\-model/.test(key)) {\n        attrs = this$1.model(key, val, attrs, tag, log);\n      } else if (directiveMap$2[key]) {\n        var ref = directiveMap$2[key] || {};\n        var name = ref.name; if ( name === void 0 ) name = '';\n        var type = ref.type;\n        var map = ref.map; if ( map === void 0 ) map = {};\n        var check = ref.check;\n        if (!(check && !check(key, val, log)) && !(!name || typeof type !== 'number')) {\n          // 见 ./directiveMap.js 注释\n          if (type === 0) {\n            attrs[name] = \"{{\" + val + \"}}\";\n          }\n\n          if (type === 1) {\n            attrs[name] = undefined;\n          }\n\n          if (type === 2) {\n            attrs[name] = val;\n          }\n\n          if (type === 3) {\n            attrs[map[name] || name] = \"{{\" + val + \"}}\";\n            return\n          }\n        }\n      } else if (/^v\\-/.test(key)) {\n        log((\"不支持此属性-> \" + key + \"=\\\"\" + val + \"\\\"\"), 'waring');\n      } else {\n        if ((tagConfig.virtualTag.indexOf(tag) > -1) && (key === 'class' || key === 'style' || key === 'data-mpcomid')) {\n          if (key !== 'data-mpcomid') {\n            log((\"template 不支持此属性-> \" + key + \"=\\\"\" + val + \"\\\"\"), 'waring');\n          }\n        } else {\n          attrs[key] = val;\n        }\n      }\n    });\n    ast.attrsMap = attrs;\n    return ast\n  },\n\n  event: function event (key, val, attrs, tag) {\n    // 小程序能力所致，bind 和 catch 事件同时绑定时候，只会触发 bind ,catch 不会被触发。\n    // .stop 的使用会阻止冒泡，但是同时绑定了一个非冒泡事件，会导致该元素上的 catchEventName 失效！\n    // .prevent 可以直接干掉，因为小程序里没有什么默认事件，比如submit并不会跳转页面\n    // .capture 不能做，因为小程序没有捕获类型的事件\n    // .self 没有可以判断的标识\n    // .once 也不能做，因为小程序没有 removeEventListener, 虽然可以直接在 handleProxy 中处理，但非常的不优雅，违背了原意，暂不考虑\n    var name = key.replace(/^v\\-on\\:/i, '').replace(/\\.prevent/i, '');\n    var ref = name.split('.');\n    var eventName = ref[0];\n    var eventNameMap = ref.slice(1);\n    var eventMap = directiveMap$2['v-on'];\n    var check = directiveMap$2.check;\n\n    if (check) {\n      check(key, val);\n    }\n    var wxmlEventName = '';\n    if (eventName === 'change' && (tag === 'input' || tag === 'textarea')) {\n      wxmlEventName = 'blur';\n    } else {\n      wxmlEventName = eventMap.map[eventName];\n    }\n\n    var eventType = 'bind';\n    var isStop = eventNameMap.includes('stop');\n    if (eventNameMap.includes('capture')) {\n      eventType = isStop ? 'capture-catch:' : 'capture-bind:';\n    } else if (isStop) {\n      eventType = 'catch';\n    }\n\n    wxmlEventName = eventType + (wxmlEventName || eventName);\n    attrs[wxmlEventName] = 'handleProxy';\n\n    return attrs\n  },\n\n  bind: function bind (key, val, attrs, tag, isIf) {\n    var name = key.replace(/^v\\-bind\\:/i, '');\n\n    if (isIf && name === 'key') {\n      attrs['tt:key'] = val;\n    }\n\n    if (tag === 'template') {\n      return attrs\n    }\n\n    if (name === 'href') {\n      attrs['url'] = \"{{\" + val + \"}}\";\n    } else {\n      attrs[name] = \"{{\" + val + \"}}\";\n    }\n\n    return attrs\n  },\n\n  classObj: function classObj (clsBinding, staticCls) {\n    if ( clsBinding === void 0 ) clsBinding = '';\n\n    if (!clsBinding && !staticCls) {\n      return ''\n    }\n    if (!clsBinding && staticCls) {\n      return staticCls\n    }\n\n    return transformDynamicClass$2(staticCls, clsBinding)\n  },\n\n  styleObj: function styleObj (styleBinding, staticStyle) {\n    if ( styleBinding === void 0 ) styleBinding = '';\n\n    if (!styleBinding && !staticStyle) {\n      return ''\n    }\n    if (!styleBinding && staticStyle) {\n      return staticStyle\n    }\n\n    return transformDynamicStyle$2(staticStyle, styleBinding)\n  },\n\n  model: function model (key, val, attrs, tag) {\n    var isFormInput = tag === 'input' || tag === 'textarea';\n    attrs['value'] = \"{{\" + val + \"}}\";\n    if (key === 'v-model.lazy') {\n      if (isFormInput) {\n        attrs['bindblur'] = 'handleProxy';\n      } else {\n        attrs['bindchange'] = 'handleProxy';\n      }\n    } else {\n      if (isFormInput) {\n        attrs['bindinput'] = 'handleProxy';\n      } else {\n        attrs['bindchange'] = 'handleProxy';\n      }\n    }\n\n    return attrs\n  }\n};\n\nfunction getSlotsName$2 (obj) {\n  if (!obj) {\n    return ''\n  }\n  // wxml模板中 data=\"{{ a:{a1:'string2'}, b:'string'}}\" 键a不能放在最后，会出错\n  return tmplateSlotsObj$2(obj)\n    .concat(\n      Object.keys(obj).map(function(k) {\n        return '$slot' + k + \":'\" + obj[k] + \"'\"\n      })\n    )\n    .join(',')\n}\n\nfunction tmplateSlotsObj$2(obj) {\n  if (!obj) {\n    return []\n  }\n  // wxml模板中 data=\"{{ a:{a1:'string2'}, b:'string'}}\" 键a1不能写成 'a1' 带引号的形式，会出错\n  var $for = Object.keys(obj)\n    .map(function(k) {\n      return (k + \":'\" + (obj[k]) + \"'\")\n    })\n    .join(',');\n  return $for ? [(\"$for:{\" + $for + \"}\")] : []\n}\n\nvar component$2 = {\n  isComponent: function isComponent (tagName, components) {\n    if ( components === void 0 ) components = {};\n\n    return !!components[tagName]\n  },\n  convertComponent: function convertComponent (ast, components, slotName) {\n    var attrsMap = ast.attrsMap;\n    var tag = ast.tag;\n    var mpcomid = ast.mpcomid;\n    var slots = ast.slots;\n    if (slotName) {\n      attrsMap['data'] = \"{{...$root[$p], ...$root[$k], $root}}\";\n      // bindedName is available when rendering slot in v-for\n      var bindedName = attrsMap['v-bind:name'];\n      if(bindedName) {\n        attrsMap['is'] = \"{{$for[\" + bindedName + \"]}}\";\n      } else {\n        attrsMap['is'] = \"{{\" + slotName + \"}}\";\n      }\n    } else {\n      var slotsName = getSlotsName$2(slots);\n      var restSlotsName = slotsName ? (\", \" + slotsName) : '';\n      attrsMap['data'] = \"{{...$root[$kk+\" + mpcomid + \"], $root\" + restSlotsName + \"}}\";\n      attrsMap['is'] = components[tag].name;\n    }\n    return ast\n  }\n};\n\nvar astMap$2 = {\n  'if': 'tt:if',\n  'iterator1': 'tt:for-index',\n  'key': 'tt:key',\n  'alias': 'tt:for-item',\n  'v-for': 'tt:for'\n};\n\nvar convertFor$2 = function (ast) {\n  var iterator1 = ast.iterator1;\n  var forText = ast.for;\n  var key = ast.key;\n  var alias = ast.alias;\n  var attrsMap = ast.attrsMap;\n  if (forText) {\n    attrsMap[astMap$2['v-for']] = \"{{\" + forText + \"}}\";\n    if (iterator1) {\n      attrsMap[astMap$2['iterator1']] = iterator1;\n    }\n    if (key) {\n      attrsMap[astMap$2['key']] = key;\n    }\n    if (alias) {\n      attrsMap[astMap$2['alias']] = alias;\n    }\n\n    delete attrsMap['v-for'];\n  }\n\n  return ast\n};\n\nfunction mpmlAst$2 (compiled, options, log) {\n  if ( options === void 0 ) options = {};\n\n  var conventRule = { attrs: attrs$2, component: component$2, convertFor: convertFor$2 };\n  return getAstCommon(compiled, options, log, conventRule)\n}\n\nfunction compileToMPML$3 (compiled, options) {\n  if ( options === void 0 ) options = {};\n\n  return compileToMPMLCommon(compiled, options, mpmlAst$2)\n}\n\n// type：\n// 0, 默认值, 拼接 ${name}={{ ${content} }}\n// 1, 拼接 ${name}\n// 2, 拼接 ${map[key]}={{ '${content}' }}\n// 3, 拼接 {{ ${content} }}\n// 4, 拼接为空字符串\n// 5, 不需要在wxml上表现出来，可直接清除\n\nvar noSupport$3 = {\n  type: 4,\n  check: function (k, v, errors) {\n    errors((\"不支持此指令: \" + k + \"=\\\"\" + v + \"\\\"\"));\n    return false\n  }\n};\n\nvar directiveMap$3 = {\n  'v-if': {\n    name: 'a:if',\n    type: 0\n  },\n  'v-else-if': {\n    name: 'a:elif',\n    type: 0\n  },\n  'v-else': {\n    name: 'a:else',\n    type: 1\n  },\n  'v-text': {\n    name: '',\n    type: 1\n  },\n  'v-html': {\n    name: '',\n    type: 1\n  },\n  'v-on': {\n    name: '',\n    map: {\n      click: 'tap',\n      touchstart: 'touchStart',\n      touchmove: 'touchMove',\n      touchcancel: 'touchCancel',\n      touchend: 'touchEnd',\n      tap: 'tap',\n      longtap: 'longTap',\n      input: 'input',\n      change: 'change',\n      submit: 'submit',\n      blur: 'blur',\n      focus: 'focus',\n      reset: 'reset',\n      confirm: 'confirm',\n      columnchange: 'columnChange',\n      linechange: 'lineChange',\n      error: 'error',\n      scrolltoupper: 'scrollToUpper',\n      scrolltolower: 'scrollToLower',\n      scroll: 'scroll',\n      load: 'load'\n    },\n    type: 2\n  },\n  'v-bind': {\n    name: '',\n    map: {\n      'href': 'url'\n    },\n    type: 3\n  },\n  'href': {\n    name: 'url',\n    type: 2\n  },\n  'v-pre': noSupport$3,\n  'v-cloak': noSupport$3,\n  'v-once': {\n    name: '',\n    type: 5\n  }\n};\n\nfunction transformDynamicClass$3 (staticClass, clsBinding) {\n  if ( staticClass === void 0 ) staticClass = '';\n\n  var result = babel.transform((\"!\" + clsBinding), { plugins: [transformObjectToTernaryOperator] });\n  // 先实现功能，再优化代码\n  // https://github.com/babel/babel/issues/7138\n  var cls = prettier.format(result.code, { semi: false, singleQuote: true }).slice(1).slice(0, -1).replace(/\\n|\\r/g, '');\n  return (staticClass + \" {{\" + cls + \"}}\")\n}\n\nfunction transformDynamicStyle$3 (staticStyle, styleBinding) {\n  if ( staticStyle === void 0 ) staticStyle = '';\n\n  var result = babel.transform((\"!\" + styleBinding), { plugins: [transformObjectToString] });\n  var cls = prettier.format(result.code, { semi: false, singleQuote: true }).slice(1).slice(0, -1).replace(/\\n|\\r/g, '');\n  return (staticStyle + \" {{\" + cls + \"}}\")\n}\n\nvar attrs$3 = {\n  format: function format (attrs) {\n    if ( attrs === void 0 ) attrs = {};\n\n    var obj = {};\n\n    Object.keys(attrs).map(function (key) {\n      var val = attrs[key];\n      obj[key.replace('@', 'v-on:').replace(/^:/, 'v-bind:')] = val;\n    });\n    return obj\n  },\n\n  convertAttr: function convertAttr (ast, log) {\n    var this$1 = this;\n\n    var attrsMap = ast.attrsMap; if ( attrsMap === void 0 ) attrsMap = {};\n    var tag = ast.tag;\n    var staticClass = ast.staticClass;\n    var attrs = {};\n    var wxClass = this.classObj(attrsMap['v-bind:class'], staticClass);\n    wxClass.length ? attrsMap['class'] = wxClass : '';\n    var wxStyle = this.styleObj(attrsMap['v-bind:style'], attrsMap['style']);\n    wxStyle.length ? attrsMap['style'] = wxStyle : '';\n\n    Object.keys(attrsMap).map(function (key) {\n      var val = attrsMap[key];\n      if (key === 'v-bind:class' || key === 'v-bind:style') {\n        return\n      }\n      if (key === 'v-text') {\n        ast.children.unshift({\n          text: (\"{{\" + val + \"}}\"),\n          type: 3\n        });\n      } else if (key === 'v-html') {\n        ast.tag = 'rich-text';\n        attrs['nodes'] = \"{{\" + val + \"}}\";\n      } else if (key === 'v-show') {\n        attrs['hidden'] = \"{{!(\" + val + \")}}\";\n      } else if (/^v\\-on\\:/i.test(key)) {\n        attrs = this$1.event(key, val, attrs, tag, log);\n      } else if (/^v\\-bind\\:/i.test(key)) {\n        attrs = this$1.bind(key, val, attrs, tag, attrsMap['a:key']);\n      } else if (/^v\\-model/.test(key)) {\n        attrs = this$1.model(key, val, attrs, tag, log);\n      } else if (directiveMap$3[key]) {\n        var ref = directiveMap$3[key] || {};\n        var name = ref.name; if ( name === void 0 ) name = '';\n        var type = ref.type;\n        var map = ref.map; if ( map === void 0 ) map = {};\n        var check = ref.check;\n        if (!(check && !check(key, val, log)) && !(!name || typeof type !== 'number')) {\n          // 见 ./directiveMap.js 注释\n          if (type === 0) {\n            attrs[name] = \"{{\" + val + \"}}\";\n          }\n\n          if (type === 1) {\n            attrs[name] = undefined;\n          }\n\n          if (type === 2) {\n            attrs[name] = val;\n          }\n\n          if (type === 3) {\n            attrs[map[name] || name] = \"{{\" + val + \"}}\";\n            return\n          }\n        }\n      } else if (/^v\\-/.test(key)) {\n        log((\"不支持此属性-> \" + key + \"=\\\"\" + val + \"\\\"\"), 'waring');\n      } else {\n        if ((tagConfig.virtualTag.indexOf(tag) > -1) && (key === 'class' || key === 'style' || key === 'data-mpcomid')) {\n          if (key !== 'data-mpcomid') {\n            log((\"template 不支持此属性-> \" + key + \"=\\\"\" + val + \"\\\"\"), 'waring');\n          }\n        } else {\n          attrs[key] = val;\n        }\n      }\n    });\n    ast.attrsMap = attrs;\n    return ast\n  },\n\n  event: function event (key, val, attrs, tag, log) {\n    // 小程序能力所致，bind 和 catch 事件同时绑定时候，只会触发 bind ,catch 不会被触发。\n    // .stop 的使用会阻止冒泡，但是同时绑定了一个非冒泡事件，会导致该元素上的 catchEventName 失效！\n    // .prevent 可以直接干掉，因为小程序里没有什么默认事件，比如submit并不会跳转页面\n    // .capture 不能做，因为小程序没有捕获类型的事件\n    // .self 没有可以判断的标识\n    // .once 也不能做，因为小程序没有 removeEventListener, 虽然可以直接在 handleProxy 中处理，但非常的不优雅，违背了原意，暂不考虑\n    var name = key.replace(/^v\\-on\\:/i, '').replace(/\\.prevent/i, '');\n    var ref = name.split('.');\n    var eventName = ref[0];\n    var eventNameMap = ref.slice(1);\n    var eventMap = directiveMap$3['v-on'];\n    var check = directiveMap$3.check;\n\n    if (check) {\n      check(key, val);\n    }\n    var wxmlEventName = '';\n    if (eventName === 'change' && (tag === 'input' || tag === 'textarea')) {\n      wxmlEventName = 'blur';\n    } else {\n      wxmlEventName = eventMap.map[eventName];\n    }\n\n    var eventType = 'on';\n    var isStop = eventNameMap.includes('stop');\n    if (eventNameMap.includes('capture')) {\n      log('支付宝小程序不支持事件捕获');\n    } else if (isStop) {\n      eventType = 'catch';\n    }\n    var camelCaseEvent = (wxmlEventName || eventName).replace(/^\\S/, function (letter) { return letter.toUpperCase(); });\n    wxmlEventName = eventType + camelCaseEvent;\n    attrs[wxmlEventName] = 'handleProxy';\n\n    return attrs\n  },\n\n  bind: function bind (key, val, attrs, tag, isIf) {\n    var name = key.replace(/^v\\-bind\\:/i, '');\n\n    if (isIf && name === 'key') {\n      attrs['a:key'] = val;\n    }\n\n    if (tag === 'template') {\n      return attrs\n    }\n\n    if (name === 'href') {\n      attrs['url'] = \"{{\" + val + \"}}\";\n    } else {\n      attrs[name] = \"{{\" + val + \"}}\";\n    }\n\n    return attrs\n  },\n\n  classObj: function classObj (clsBinding, staticCls) {\n    if ( clsBinding === void 0 ) clsBinding = '';\n\n    if (!clsBinding && !staticCls) {\n      return ''\n    }\n    if (!clsBinding && staticCls) {\n      return staticCls\n    }\n\n    return transformDynamicClass$3(staticCls, clsBinding)\n  },\n\n  styleObj: function styleObj (styleBinding, staticStyle) {\n    if ( styleBinding === void 0 ) styleBinding = '';\n\n    if (!styleBinding && !staticStyle) {\n      return ''\n    }\n    if (!styleBinding && staticStyle) {\n      return staticStyle\n    }\n\n    return transformDynamicStyle$3(staticStyle, styleBinding)\n  },\n\n  model: function model (key, val, attrs, tag) {\n    var isFormInput = tag === 'input' || tag === 'textarea';\n    attrs['value'] = \"{{\" + val + \"}}\";\n    if (key === 'v-model.lazy') {\n      if (isFormInput) {\n        attrs['onBlur'] = 'handleProxy';\n      } else {\n        attrs['onChange'] = 'handleProxy';\n      }\n    } else {\n      if (isFormInput) {\n        attrs['onInput'] = 'handleProxy';\n      } else {\n        attrs['onChange'] = 'handleProxy';\n      }\n    }\n    return attrs\n  }\n};\n\nfunction getSlotsName$3 (obj) {\n  if (!obj) {\n    return ''\n  }\n  // wxml模板中 data=\"{{ a:{a1:'string2'}, b:'string'}}\" 键a不能放在最后，会出错\n  return tmplateSlotsObj$3(obj)\n    .concat(\n      Object.keys(obj).map(function (k) {\n        return '$slot' + k + \":'\" + obj[k] + \"'\"\n      })\n    )\n    .join(',')\n}\n\nfunction tmplateSlotsObj$3 (obj) {\n  if (!obj) {\n    return []\n  }\n  // wxml模板中 data=\"{{ a:{a1:'string2'}, b:'string'}}\" 键a1不能写成 'a1' 带引号的形式，会出错\n  var $for = Object.keys(obj)\n    .map(function (k) {\n      return (k + \":'\" + (obj[k]) + \"'\")\n    })\n    .join(',');\n  return $for ? [(\"$for:{\" + $for + \"}\")] : []\n}\n\nvar component$3 = {\n  isComponent: function isComponent (tagName, components) {\n    if ( components === void 0 ) components = {};\n\n    return !!components[tagName]\n  },\n  convertComponent: function convertComponent (ast, components, slotName) {\n    var attrsMap = ast.attrsMap;\n    var tag = ast.tag;\n    var mpcomid = ast.mpcomid;\n    var slots = ast.slots;\n    if (slotName) {\n      attrsMap['data'] = \"{{...$root[$p], ...$root[$k], $root}}\";\n      // bindedName is available when rendering slot in v-for\n      var bindedName = attrsMap['v-bind:name'];\n      if (bindedName) {\n        attrsMap['is'] = \"{{$for[\" + bindedName + \"]}}\";\n      } else {\n        attrsMap['is'] = \"{{\" + slotName + \"}}\";\n      }\n    } else {\n      var slotsName = getSlotsName$3(slots);\n      var restSlotsName = slotsName ? (\", \" + slotsName) : '';\n      attrsMap['data'] = \"{{...$root[$kk+\" + mpcomid + \"], $root\" + restSlotsName + \"}}\";\n      attrsMap['is'] = components[tag].name;\n    }\n    return ast\n  }\n};\n\nvar astMap$3 = {\n  'if': 'a:if',\n  'iterator1': 'a:for-index',\n  'key': 'a:key',\n  'alias': 'a:for-item',\n  'v-for': 'a:for'\n};\n\nvar convertFor$3 = function (ast) {\n  var iterator1 = ast.iterator1;\n  var forText = ast.for;\n  var key = ast.key;\n  var alias = ast.alias;\n  var attrsMap = ast.attrsMap;\n\n  if (forText) {\n    attrsMap[astMap$3['v-for']] = \"{{\" + forText + \"}}\";\n    if (iterator1) {\n      attrsMap[astMap$3['iterator1']] = iterator1;\n    }\n    if (key) {\n      attrsMap[astMap$3['key']] = key;\n    }\n    if (alias) {\n      attrsMap[astMap$3['alias']] = alias;\n    }\n\n    delete attrsMap['v-for'];\n  }\n\n  return ast\n};\n\nfunction mpmlAst$3 (compiled, options, log) {\n  if ( options === void 0 ) options = {};\n\n  var conventRule = { attrs: attrs$3, component: component$3, convertFor: convertFor$3 };\n  return getAstCommon(compiled, options, log, conventRule)\n}\n\nfunction compileToMPML$4 (compiled, options) {\n  if ( options === void 0 ) options = {};\n\n  return compileToMPMLCommon(compiled, options, mpmlAst$3)\n}\n\nfunction compileToMPML (compiled, options, fileExt) {\n  var code;\n  switch (fileExt.platform) {\n    case 'swan':\n      code = compileToMPML$2(compiled, options);\n      break\n    case 'wx':\n      code = compileToMPML$1(compiled, options);\n      break\n    case 'tt':\n      code = compileToMPML$3(compiled, options);\n      break\n    case 'my':\n      code = compileToMPML$4(compiled, options);\n      break\n    default:\n      code = compileToMPML$1(compiled, options);\n  }\n  return code\n}\n\nvar ref = createCompiler(baseOptions);\nvar compile = ref.compile;\nvar compileToFunctions = ref.compileToFunctions;\n\n/*  */\n\nexports.parseComponent = parseComponent;\nexports.compile = compile;\nexports.compileToFunctions = compileToFunctions;\nexports.compileToMPML = compileToMPML;\n"
  },
  {
    "path": "packages/mpvue-template-compiler/index.js",
    "content": "try {\n  var vueVersion = require('mpvue/package.json').version\n} catch (e) {}\n\nvar packageName = require('./package.json').name\nvar packageVersion = require('./package.json').version\nif (vueVersion && vueVersion !== packageVersion) {\n  throw new Error(\n    '\\n\\nVue packages version mismatch:\\n\\n' +\n    '- vue@' + vueVersion + '\\n' +\n    '- ' + packageName + '@' + packageVersion + '\\n\\n' +\n    'This may cause things to work incorrectly. Make sure to use the same version for both.\\n' +\n    'If you are using mpvue-loader, re-installing them should bump ' + packageName + ' to the latest.\\n'\n  )\n}\n\nmodule.exports = require('./build')\n"
  },
  {
    "path": "packages/mpvue-template-compiler/package.json",
    "content": "{\n  \"name\": \"mpvue-template-compiler\",\n  \"version\": \"2.0.6\",\n  \"description\": \"mpvue template compiler for Vue\",\n  \"main\": \"index.js\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/Meituan-Dianping/mpvue.git\"\n  },\n  \"keywords\": [\n    \"vue\",\n    \"compiler\",\n    \"mp\",\n    \"mp\",\n    \"antmp\"\n  ],\n  \"author\": \"meituan.com\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/Meituan-Dianping/mpvue/issues\"\n  },\n  \"homepage\": \"https://github.com/Meituan-Dianping/mpvue/\",\n  \"dependencies\": {\n    \"he\": \"^1.1.0\",\n    \"de-indent\": \"^1.0.2\"\n  }\n}\n"
  },
  {
    "path": "packages/vue-server-renderer/README.md",
    "content": "# vue-server-renderer\n\n> This package is auto-generated. For pull requests please see [src/entries/web-server-renderer.js](https://github.com/vuejs/vue/blob/dev/src/platforms/web/server-renderer.js).\n\nThis package offers Node.js server-side rendering for Vue 2.0.\n\n- [API Reference](https://ssr.vuejs.org/en/api.html)\n- [Vue.js Server-Side Rendering Guide](https://ssr.vuejs.org)\n"
  },
  {
    "path": "packages/vue-server-renderer/index.js",
    "content": "try {\n  var vueVersion = require('vue').version\n} catch (e) {}\n\nvar packageName = require('./package.json').name\nvar packageVersion = require('./package.json').version\nif (vueVersion && vueVersion !== packageVersion) {\n  throw new Error(\n    '\\n\\nVue packages version mismatch:\\n\\n' +\n    '- vue@' + vueVersion + '\\n' +\n    '- ' + packageName + '@' + packageVersion + '\\n\\n' +\n    'This may cause things to work incorrectly. Make sure to use the same version for both.\\n'\n  )\n}\n\nmodule.exports = require('./build')\n"
  },
  {
    "path": "packages/vue-server-renderer/package.json",
    "content": "{\n  \"name\": \"vue-server-renderer\",\n  \"version\": \"2.4.1\",\n  \"description\": \"server renderer for Vue 2.0\",\n  \"main\": \"index.js\",\n  \"types\": \"types/index.d.ts\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/vuejs/vue.git\"\n  },\n  \"keywords\": [\n    \"vue\",\n    \"server\",\n    \"ssr\"\n  ],\n  \"author\": \"Evan You\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/vuejs/vue/issues\"\n  },\n  \"scripts\": {\n    \"test:types\": \"tsc -p types\"\n  },\n  \"dependencies\": {\n    \"chalk\": \"^1.1.3\",\n    \"hash-sum\": \"^1.0.2\",\n    \"he\": \"^1.1.0\",\n    \"lodash.template\": \"^4.4.0\",\n    \"lodash.uniq\": \"^4.5.0\",\n    \"resolve\": \"^1.2.0\",\n    \"source-map\": \"0.5.6\",\n    \"serialize-javascript\": \"^1.3.0\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^7.0.22\",\n    \"typescript\": \"^2.3.3\",\n    \"vue\": \"file:../..\"\n  },\n  \"homepage\": \"https://github.com/vuejs/vue/tree/dev/packages/vue-server-renderer#readme\"\n}\n"
  },
  {
    "path": "packages/vue-server-renderer/types/index.d.ts",
    "content": "import Vue = require('vue');\nimport { Readable } from 'stream';\n\nexport declare function createRenderer(options?: RendererOptions): Renderer;\n\nexport declare function createBundleRenderer(bundle: string | object, options?: BundleRendererOptions): BundleRenderer;\n\ntype RenderCallback = (err: Error | null, html: string) => void;\n\ninterface Renderer {\n  renderToString(vm: Vue, callback: RenderCallback): void;\n  renderToString(vm: Vue, context: object, callback: RenderCallback): void;\n\n  renderToStream(vm: Vue, context?: object): Readable;\n}\n\ninterface BundleRenderer {\n  renderToString(callback: RenderCallback): void;\n  renderToString(context: object, callback: RenderCallback): void;\n\n  renderToStream(context?: object): Readable;\n}\n\ninterface RendererOptions {\n  template?: string;\n  inject?: boolean;\n  shouldPreload?: (file: string, type: string) => boolean;\n  cache?: RenderCache;\n  directives?: {\n    [key: string]: (vnode: Vue.VNode, dir: Vue.VNodeDirective) => void\n  };\n}\n\ninterface BundleRendererOptions extends RendererOptions {\n  clientManifest?: object;\n  runInNewContext?: boolean | 'once';\n  basedir?: string;\n}\n\ninterface RenderCache {\n  get: (key: string, cb?: (res: string) => void) => string | void;\n  set: (key: string, val: string) => void;\n  has?: (key: string, cb?: (hit: boolean) => void) => boolean | void;\n}\n"
  },
  {
    "path": "packages/vue-server-renderer/types/test.ts",
    "content": "import Vue = require('vue');\nimport { readFileSync } from 'fs';\nimport { createRenderer, createBundleRenderer } from '../';\n\nfunction createApp (context: any) {\n  return new Vue({\n    data: {\n      url: context.url\n    },\n    template: `<div>The visited URL is: {{ url }}</div>`\n  });\n}\n\n// Renderer test\nconst app = createApp({ url: 'http://localhost:8000/' });\n\nconst renderer = createRenderer({\n  template: readFileSync('./index.template.html', 'utf-8')\n});\n\nconst context = {\n  title: 'Hello',\n  meta: `\n    <meta name=\"description\" content=\"Vue.js SSR Example\">\n  `\n};\n\nrenderer.renderToString(app, context, (err, html) => {\n  if (err) throw err;\n  const res: string = html;\n});\n\nrenderer.renderToStream(app, context).on('data', chunk => {\n  const html = chunk.toString();\n});\n\n// Bundle renderer test\ndeclare const cacheClient: { [key: string]: string };\n\nconst bundleRenderer = createBundleRenderer('/path/to/vue-ssr-server-bundle.json', {\n  inject: false,\n  runInNewContext: 'once',\n  basedir: '/path/to/base',\n\n  shouldPreload: (file, type) => {\n    if (type === 'script' || type === 'style') {\n      return true;\n    }\n    if (type === 'font') {\n      return /\\.woff2$/.test(file);\n    }\n    if (type === 'image') {\n      return file === 'hero.jpg';\n    }\n    return false;\n  },\n\n  cache: {\n    get: key => {\n      return cacheClient[key];\n    },\n    set: (key, val) => {\n      cacheClient[key] = val;\n    },\n    has: key => {\n      return !!cacheClient[key];\n    }\n  },\n\n  directives: {\n    example (vnode: Vue.VNode, directiveMeta: Vue.VNodeDirective) {\n      // transform vnode based on directive binding metadata\n    }\n  }\n});\n\nbundleRenderer.renderToString(context, (err, html) => {\n  if (err) throw err;\n  const res: string = html;\n});\n\nbundleRenderer.renderToStream(context).on('data', chunk => {\n  const html = chunk.toString();\n});\n"
  },
  {
    "path": "packages/vue-server-renderer/types/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"es5\",\n    \"module\": \"commonjs\",\n    \"moduleResolution\": \"node\",\n    \"strict\": true,\n    \"noEmit\": true\n  },\n  \"compileOnSave\": false,\n  \"include\": [\n    \"**/*.ts\"\n  ]\n}\n"
  },
  {
    "path": "packages/vue-template-compiler/README.md",
    "content": "# vue-template-compiler\n\n> This package is auto-generated. For pull requests please see [src/entries/web-compiler.js](https://github.com/vuejs/vue/tree/dev/src/platforms/web/compiler).\n\nThis package can be used to pre-compile Vue 2.0 templates into render functions to avoid runtime-compilation overhead and CSP restrictions. You will only need it if you are writing build tools with very specific needs. In most cases you should be using [vue-loader](https://github.com/vuejs/vue-loader) or [vueify](https://github.com/vuejs/vueify) instead, both of which use this package internally.\n\n## Installation\n\n``` bash\nnpm install vue-template-compiler\n```\n\n``` js\nconst compiler = require('vue-template-compiler')\n```\n\n## API\n\n### compiler.compile(template, [options])\n\nCompiles a template string and returns compiled JavaScript code. The returned result is an object of the following format:\n\n``` js\n{\n  ast: ?ASTElement, // parsed template elements to AST\n  render: string, // main render function code\n  staticRenderFns: Array<string>, // render code for static sub trees, if any\n  errors: Array<string> // template syntax errors, if any\n}\n```\n\nNote the returned function code uses `with` and thus cannot be used in strict mode code.\n\n#### Options\n\nIt's possible to hook into the compilation process to support custom template features. **However, beware that by injecting custom compile-time modules, your templates will not work with other build tools built on standard built-in modules, e.g `vue-loader` and `vueify`.**\n\nThe optional `options` object can contain the following:\n\n- `modules`\n\n  An array of compiler modules. For details on compiler modules, refer to the `ModuleOptions` type in [flow declarations](https://github.com/vuejs/vue/blob/dev/flow/compiler.js) and the [built-in modules](https://github.com/vuejs/vue/tree/dev/src/platforms/web/compiler/modules).\n\n- `directives`\n\n  An object where the key is the directive name and the value is a function that transforms an template AST node. For example:\n\n  ``` js\n  compiler.compile('<div v-test></div>', {\n    directives: {\n      test (node, directiveMeta) {\n        // transform node based on directiveMeta\n      }\n  })\n  ```\n\n  By default, a compile-time directive will extract the directive and the directive will not be present at runtime. If you want the directive to also be handled by a runtime definition, return `true` in the transform function.\n\n  Refer to the implementation of some [built-in compile-time directives](https://github.com/vuejs/vue/tree/dev/src/platforms/web/compiler/directives).\n\n- `preserveWhitespace`\n\n  Defaults to `true`. This means the compiled render function respects all the whitespaces between HTML tags. If set to `false`, all whitespaces between tags will be ignored. This can result in slightly better performance but may affect layout for inline elements.\n\n---\n\n### compiler.compileToFunctions(template)\n\nSimilar to `compiler.compile`, but directly returns instantiated functions:\n\n``` js\n{\n  render: Function,\n  staticRenderFns: Array<Function>\n}\n```\n\nThis is only useful at runtime with pre-configured builds, so it doesn't accept any compile-time options. In addition, this method uses `new Function()` so it is not CSP-compliant.\n\n---\n\n### compiler.ssrCompile(template, [options])\n\n> 2.4.0+\n\nSame as `compiler.compile` but generates SSR-specific render function code by optimizing parts of the template into string concatenation in order to improve SSR performance.\n\nThis is used by default in `vue-loader@>=12` and can be disabled using the [optimizeSSR](https://vue-loader.vuejs.org/en/options.html#optimizessr) option.\n\n---\n\n### compiler.ssrCompileToFunction(template)\n\n> 2.4.0+\n\nSame as `compiler.compileToFunction` but generates SSR-specific render function code by optimizing parts of the template into string concatenation in order to improve SSR performance.\n\n---\n\n### compiler.parseComponent(file, [options])\n\nParse a SFC (single-file component, or `*.vue` file) into a descriptor (refer to the `SFCDescriptor` type in [flow declarations](https://github.com/vuejs/vue/blob/dev/flow/compiler.js)). This is used in SFC build tools like `vue-loader` and `vueify`.\n\n#### Options\n\n#### `pad`\n\n`pad` is useful when you are piping the extracted content into other pre-processors, as you will get correct line numbers or character indices if there are any syntax errors.\n\n- with `{ pad: \"line\" }`, the extracted content for each block will be prefixed with one newline for each line in the leading content from the original file to ensure that the line numbers align with the original file.\n- with `{ pad: \"space\" }`, the extracted content for each block will be prefixed with one space for each character in the leading content from the original file to ensure that the character count remains the same as the original file.\n"
  },
  {
    "path": "packages/vue-template-compiler/index.js",
    "content": "try {\n  var vueVersion = require('vue').version\n} catch (e) {}\n\nvar packageName = require('./package.json').name\nvar packageVersion = require('./package.json').version\nif (vueVersion && vueVersion !== packageVersion) {\n  throw new Error(\n    '\\n\\nVue packages version mismatch:\\n\\n' +\n    '- vue@' + vueVersion + '\\n' +\n    '- ' + packageName + '@' + packageVersion + '\\n\\n' +\n    'This may cause things to work incorrectly. Make sure to use the same version for both.\\n' +\n    'If you are using vue-loader@>=10.0, simply update vue-template-compiler.\\n' +\n    'If you are using vue-loader@<10.0 or vueify, re-installing vue-loader/vueify should bump ' + packageName + ' to the latest.\\n'\n  )\n}\n\nmodule.exports = require('./build')\n"
  },
  {
    "path": "packages/vue-template-compiler/package.json",
    "content": "{\n  \"name\": \"vue-template-compiler\",\n  \"version\": \"2.4.1\",\n  \"description\": \"template compiler for Vue 2.0\",\n  \"main\": \"index.js\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/vuejs/vue.git\"\n  },\n  \"keywords\": [\n    \"vue\",\n    \"compiler\"\n  ],\n  \"author\": \"Evan You\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/vuejs/vue/issues\"\n  },\n  \"homepage\": \"https://github.com/vuejs/vue/tree/dev/packages/vue-template-compiler#readme\",\n  \"dependencies\": {\n    \"he\": \"^1.1.0\",\n    \"de-indent\": \"^1.0.2\"\n  }\n}\n"
  },
  {
    "path": "packages/weex-template-compiler/README.md",
    "content": "# weex-template-compiler\n\n> This package is auto-generated. For pull requests please see [src/entries/weex-compiler.js](https://github.com/vuejs/vue/tree/dev/src/platforms/weex/compiler).\n"
  },
  {
    "path": "packages/weex-template-compiler/build.js",
    "content": "'use strict';\n\nObject.defineProperty(exports, '__esModule', { value: true });\n\nfunction _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }\n\nvar he = _interopDefault(require('he'));\n\n/*  */\n\n// these helpers produces better vm code in JS engines due to their\n// explicitness and function inlining\n\n\n\n\n\n\n\n\n/**\n * Check if value is primitive\n */\n\n\n/**\n * Quick object check - this is primarily used to tell\n * Objects from primitive values when we know the value\n * is a JSON-compliant type.\n */\nfunction isObject (obj) {\n  return obj !== null && typeof obj === 'object'\n}\n\nvar _toString = Object.prototype.toString;\n\n/**\n * Strict object type check. Only returns true\n * for plain JavaScript objects.\n */\nfunction isPlainObject (obj) {\n  return _toString.call(obj) === '[object Object]'\n}\n\n\n\n/**\n * Check if val is a valid array index.\n */\nfunction isValidArrayIndex (val) {\n  var n = parseFloat(val);\n  return n >= 0 && Math.floor(n) === n && isFinite(val)\n}\n\n/**\n * Convert a value to a string that is actually rendered.\n */\n\n\n/**\n * Convert a input value to a number for persistence.\n * If the conversion fails, return original string.\n */\n\n\n/**\n * Make a map and return a function for checking if a key\n * is in that map.\n */\nfunction makeMap (\n  str,\n  expectsLowerCase\n) {\n  var map = Object.create(null);\n  var list = str.split(',');\n  for (var i = 0; i < list.length; i++) {\n    map[list[i]] = true;\n  }\n  return expectsLowerCase\n    ? function (val) { return map[val.toLowerCase()]; }\n    : function (val) { return map[val]; }\n}\n\n/**\n * Check if a tag is a built-in tag.\n */\nvar isBuiltInTag = makeMap('slot,component', true);\n\n/**\n * Check if a attribute is a reserved attribute.\n */\nvar isReservedAttribute = makeMap('key,ref,slot,is');\n\n/**\n * Remove an item from an array\n */\nfunction remove (arr, item) {\n  if (arr.length) {\n    var index = arr.indexOf(item);\n    if (index > -1) {\n      return arr.splice(index, 1)\n    }\n  }\n}\n\n/**\n * Check whether the object has the property.\n */\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\nfunction hasOwn (obj, key) {\n  return hasOwnProperty.call(obj, key)\n}\n\n/**\n * Create a cached version of a pure function.\n */\nfunction cached (fn) {\n  var cache = Object.create(null);\n  return (function cachedFn (str) {\n    var hit = cache[str];\n    return hit || (cache[str] = fn(str))\n  })\n}\n\n/**\n * Camelize a hyphen-delimited string.\n */\nvar camelizeRE = /-(\\w)/g;\nvar camelize = cached(function (str) {\n  return str.replace(camelizeRE, function (_, c) { return c ? c.toUpperCase() : ''; })\n});\n\n/**\n * Capitalize a string.\n */\n\n\n\n\n/**\n * Simple bind, faster than native\n */\n\n\n/**\n * Convert an Array-like object to a real Array.\n */\n\n\n/**\n * Mix properties into target object.\n */\nfunction extend (to, _from) {\n  for (var key in _from) {\n    to[key] = _from[key];\n  }\n  return to\n}\n\n/**\n * Merge an Array of Objects into a single Object.\n */\n\n\n/**\n * Perform no operation.\n * Stubbing args to make Flow happy without leaving useless transpiled code\n * with ...rest (https://flow.org/blog/2017/05/07/Strict-Function-Call-Arity/)\n */\nfunction noop (a, b, c) {}\n\n/**\n * Always return false.\n */\nvar no = function (a, b, c) { return false; };\n\n/**\n * Return same value\n */\nvar identity = function (_) { return _; };\n\n/**\n * Generate a static keys string from compiler modules.\n */\nfunction genStaticKeys (modules) {\n  return modules.reduce(function (keys, m) {\n    return keys.concat(m.staticKeys || [])\n  }, []).join(',')\n}\n\n/**\n * Check if two values are loosely equal - that is,\n * if they are plain objects, do they have the same shape?\n */\n\n\n\n\n/**\n * Ensure a function is called only once.\n */\n\n/*  */\n\nvar isUnaryTag = makeMap(\n  'area,base,br,col,embed,frame,hr,img,input,isindex,keygen,' +\n  'link,meta,param,source,track,wbr'\n);\n\n// Elements that you can, intentionally, leave open\n// (and which close themselves)\nvar canBeLeftOpenTag = makeMap(\n  'colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr,source'\n);\n\n// HTML5 tags https://html.spec.whatwg.org/multipage/indices.html#elements-3\n// Phrasing Content https://html.spec.whatwg.org/multipage/dom.html#phrasing-content\nvar isNonPhrasingTag = makeMap(\n  'address,article,aside,base,blockquote,body,caption,col,colgroup,dd,' +\n  'details,dialog,div,dl,dt,fieldset,figcaption,figure,footer,form,' +\n  'h1,h2,h3,h4,h5,h6,head,header,hgroup,hr,html,legend,li,menuitem,meta,' +\n  'optgroup,option,param,rp,rt,source,style,summary,tbody,td,tfoot,th,thead,' +\n  'title,tr,track'\n);\n\n/**\n * Not type-checking this file because it's mostly vendor code.\n */\n\n/*!\n * HTML Parser By John Resig (ejohn.org)\n * Modified by Juriy \"kangax\" Zaytsev\n * Original code by Erik Arvidsson, Mozilla Public License\n * http://erik.eae.net/simplehtmlparser/simplehtmlparser.js\n */\n\n// Regular Expressions for parsing tags and attributes\nvar singleAttrIdentifier = /([^\\s\"'<>/=]+)/;\nvar singleAttrAssign = /(?:=)/;\nvar singleAttrValues = [\n  // attr value double quotes\n  /\"([^\"]*)\"+/.source,\n  // attr value, single quotes\n  /'([^']*)'+/.source,\n  // attr value, no quotes\n  /([^\\s\"'=<>`]+)/.source\n];\nvar attribute = new RegExp(\n  '^\\\\s*' + singleAttrIdentifier.source +\n  '(?:\\\\s*(' + singleAttrAssign.source + ')' +\n  '\\\\s*(?:' + singleAttrValues.join('|') + '))?'\n);\n\n// could use https://www.w3.org/TR/1999/REC-xml-names-19990114/#NT-QName\n// but for Vue templates we can enforce a simple charset\nvar ncname = '[a-zA-Z_][\\\\w\\\\-\\\\.]*';\nvar qnameCapture = '((?:' + ncname + '\\\\:)?' + ncname + ')';\nvar startTagOpen = new RegExp('^<' + qnameCapture);\nvar startTagClose = /^\\s*(\\/?)>/;\nvar endTag = new RegExp('^<\\\\/' + qnameCapture + '[^>]*>');\nvar doctype = /^<!DOCTYPE [^>]+>/i;\nvar comment = /^<!--/;\nvar conditionalComment = /^<!\\[/;\n\nvar IS_REGEX_CAPTURING_BROKEN = false;\n'x'.replace(/x(.)?/g, function (m, g) {\n  IS_REGEX_CAPTURING_BROKEN = g === '';\n});\n\n// Special Elements (can contain anything)\nvar isPlainTextElement = makeMap('script,style,textarea', true);\nvar reCache = {};\n\nvar decodingMap = {\n  '&lt;': '<',\n  '&gt;': '>',\n  '&quot;': '\"',\n  '&amp;': '&',\n  '&#10;': '\\n'\n};\nvar encodedAttr = /&(?:lt|gt|quot|amp);/g;\nvar encodedAttrWithNewLines = /&(?:lt|gt|quot|amp|#10);/g;\n\n// #5992\nvar isIgnoreNewlineTag = makeMap('pre,textarea', true);\nvar shouldIgnoreFirstNewline = function (tag, html) { return tag && isIgnoreNewlineTag(tag) && html[0] === '\\n'; };\n\nfunction decodeAttr (value, shouldDecodeNewlines) {\n  var re = shouldDecodeNewlines ? encodedAttrWithNewLines : encodedAttr;\n  return value.replace(re, function (match) { return decodingMap[match]; })\n}\n\nfunction parseHTML (html, options) {\n  var stack = [];\n  var expectHTML = options.expectHTML;\n  var isUnaryTag$$1 = options.isUnaryTag || no;\n  var canBeLeftOpenTag$$1 = options.canBeLeftOpenTag || no;\n  var index = 0;\n  var last, lastTag;\n  while (html) {\n    last = html;\n    // Make sure we're not in a plaintext content element like script/style\n    if (!lastTag || !isPlainTextElement(lastTag)) {\n      if (shouldIgnoreFirstNewline(lastTag, html)) {\n        advance(1);\n      }\n      var textEnd = html.indexOf('<');\n      if (textEnd === 0) {\n        // Comment:\n        if (comment.test(html)) {\n          var commentEnd = html.indexOf('-->');\n\n          if (commentEnd >= 0) {\n            if (options.shouldKeepComment) {\n              options.comment(html.substring(4, commentEnd));\n            }\n            advance(commentEnd + 3);\n            continue\n          }\n        }\n\n        // http://en.wikipedia.org/wiki/Conditional_comment#Downlevel-revealed_conditional_comment\n        if (conditionalComment.test(html)) {\n          var conditionalEnd = html.indexOf(']>');\n\n          if (conditionalEnd >= 0) {\n            advance(conditionalEnd + 2);\n            continue\n          }\n        }\n\n        // Doctype:\n        var doctypeMatch = html.match(doctype);\n        if (doctypeMatch) {\n          advance(doctypeMatch[0].length);\n          continue\n        }\n\n        // End tag:\n        var endTagMatch = html.match(endTag);\n        if (endTagMatch) {\n          var curIndex = index;\n          advance(endTagMatch[0].length);\n          parseEndTag(endTagMatch[1], curIndex, index);\n          continue\n        }\n\n        // Start tag:\n        var startTagMatch = parseStartTag();\n        if (startTagMatch) {\n          handleStartTag(startTagMatch);\n          continue\n        }\n      }\n\n      var text = (void 0), rest = (void 0), next = (void 0);\n      if (textEnd >= 0) {\n        rest = html.slice(textEnd);\n        while (\n          !endTag.test(rest) &&\n          !startTagOpen.test(rest) &&\n          !comment.test(rest) &&\n          !conditionalComment.test(rest)\n        ) {\n          // < in plain text, be forgiving and treat it as text\n          next = rest.indexOf('<', 1);\n          if (next < 0) { break }\n          textEnd += next;\n          rest = html.slice(textEnd);\n        }\n        text = html.substring(0, textEnd);\n        advance(textEnd);\n      }\n\n      if (textEnd < 0) {\n        text = html;\n        html = '';\n      }\n\n      if (options.chars && text) {\n        options.chars(text);\n      }\n    } else {\n      var endTagLength = 0;\n      var stackedTag = lastTag.toLowerCase();\n      var reStackedTag = reCache[stackedTag] || (reCache[stackedTag] = new RegExp('([\\\\s\\\\S]*?)(</' + stackedTag + '[^>]*>)', 'i'));\n      var rest$1 = html.replace(reStackedTag, function (all, text, endTag) {\n        endTagLength = endTag.length;\n        if (!isPlainTextElement(stackedTag) && stackedTag !== 'noscript') {\n          text = text\n            .replace(/<!--([\\s\\S]*?)-->/g, '$1')\n            .replace(/<!\\[CDATA\\[([\\s\\S]*?)]]>/g, '$1');\n        }\n        if (shouldIgnoreFirstNewline(stackedTag, text)) {\n          text = text.slice(1);\n        }\n        if (options.chars) {\n          options.chars(text);\n        }\n        return ''\n      });\n      index += html.length - rest$1.length;\n      html = rest$1;\n      parseEndTag(stackedTag, index - endTagLength, index);\n    }\n\n    if (html === last) {\n      options.chars && options.chars(html);\n      if (process.env.NODE_ENV !== 'production' && !stack.length && options.warn) {\n        options.warn((\"Mal-formatted tag at end of template: \\\"\" + html + \"\\\"\"));\n      }\n      break\n    }\n  }\n\n  // Clean up any remaining tags\n  parseEndTag();\n\n  function advance (n) {\n    index += n;\n    html = html.substring(n);\n  }\n\n  function parseStartTag () {\n    var start = html.match(startTagOpen);\n    if (start) {\n      var match = {\n        tagName: start[1],\n        attrs: [],\n        start: index\n      };\n      advance(start[0].length);\n      var end, attr;\n      while (!(end = html.match(startTagClose)) && (attr = html.match(attribute))) {\n        advance(attr[0].length);\n        match.attrs.push(attr);\n      }\n      if (end) {\n        match.unarySlash = end[1];\n        advance(end[0].length);\n        match.end = index;\n        return match\n      }\n    }\n  }\n\n  function handleStartTag (match) {\n    var tagName = match.tagName;\n    var unarySlash = match.unarySlash;\n\n    if (expectHTML) {\n      if (lastTag === 'p' && isNonPhrasingTag(tagName)) {\n        parseEndTag(lastTag);\n      }\n      if (canBeLeftOpenTag$$1(tagName) && lastTag === tagName) {\n        parseEndTag(tagName);\n      }\n    }\n\n    var unary = isUnaryTag$$1(tagName) || !!unarySlash;\n\n    var l = match.attrs.length;\n    var attrs = new Array(l);\n    for (var i = 0; i < l; i++) {\n      var args = match.attrs[i];\n      // hackish work around FF bug https://bugzilla.mozilla.org/show_bug.cgi?id=369778\n      if (IS_REGEX_CAPTURING_BROKEN && args[0].indexOf('\"\"') === -1) {\n        if (args[3] === '') { delete args[3]; }\n        if (args[4] === '') { delete args[4]; }\n        if (args[5] === '') { delete args[5]; }\n      }\n      var value = args[3] || args[4] || args[5] || '';\n      attrs[i] = {\n        name: args[1],\n        value: decodeAttr(\n          value,\n          options.shouldDecodeNewlines\n        )\n      };\n    }\n\n    if (!unary) {\n      stack.push({ tag: tagName, lowerCasedTag: tagName.toLowerCase(), attrs: attrs });\n      lastTag = tagName;\n    }\n\n    if (options.start) {\n      options.start(tagName, attrs, unary, match.start, match.end);\n    }\n  }\n\n  function parseEndTag (tagName, start, end) {\n    var pos, lowerCasedTagName;\n    if (start == null) { start = index; }\n    if (end == null) { end = index; }\n\n    if (tagName) {\n      lowerCasedTagName = tagName.toLowerCase();\n    }\n\n    // Find the closest opened tag of the same type\n    if (tagName) {\n      for (pos = stack.length - 1; pos >= 0; pos--) {\n        if (stack[pos].lowerCasedTag === lowerCasedTagName) {\n          break\n        }\n      }\n    } else {\n      // If no tag name is provided, clean shop\n      pos = 0;\n    }\n\n    if (pos >= 0) {\n      // Close all the open elements, up the stack\n      for (var i = stack.length - 1; i >= pos; i--) {\n        if (process.env.NODE_ENV !== 'production' &&\n          (i > pos || !tagName) &&\n          options.warn\n        ) {\n          options.warn(\n            (\"tag <\" + (stack[i].tag) + \"> has no matching end tag.\")\n          );\n        }\n        if (options.end) {\n          options.end(stack[i].tag, start, end);\n        }\n      }\n\n      // Remove the open elements from the stack\n      stack.length = pos;\n      lastTag = pos && stack[pos - 1].tag;\n    } else if (lowerCasedTagName === 'br') {\n      if (options.start) {\n        options.start(tagName, [], true, start, end);\n      }\n    } else if (lowerCasedTagName === 'p') {\n      if (options.start) {\n        options.start(tagName, [], false, start, end);\n      }\n      if (options.end) {\n        options.end(tagName, start, end);\n      }\n    }\n  }\n}\n\n/*  */\n\nvar validDivisionCharRE = /[\\w).+\\-_$\\]]/;\n\nfunction parseFilters (exp) {\n  var inSingle = false;\n  var inDouble = false;\n  var inTemplateString = false;\n  var inRegex = false;\n  var curly = 0;\n  var square = 0;\n  var paren = 0;\n  var lastFilterIndex = 0;\n  var c, prev, i, expression, filters;\n\n  for (i = 0; i < exp.length; i++) {\n    prev = c;\n    c = exp.charCodeAt(i);\n    if (inSingle) {\n      if (c === 0x27 && prev !== 0x5C) { inSingle = false; }\n    } else if (inDouble) {\n      if (c === 0x22 && prev !== 0x5C) { inDouble = false; }\n    } else if (inTemplateString) {\n      if (c === 0x60 && prev !== 0x5C) { inTemplateString = false; }\n    } else if (inRegex) {\n      if (c === 0x2f && prev !== 0x5C) { inRegex = false; }\n    } else if (\n      c === 0x7C && // pipe\n      exp.charCodeAt(i + 1) !== 0x7C &&\n      exp.charCodeAt(i - 1) !== 0x7C &&\n      !curly && !square && !paren\n    ) {\n      if (expression === undefined) {\n        // first filter, end of expression\n        lastFilterIndex = i + 1;\n        expression = exp.slice(0, i).trim();\n      } else {\n        pushFilter();\n      }\n    } else {\n      switch (c) {\n        case 0x22: inDouble = true; break         // \"\n        case 0x27: inSingle = true; break         // '\n        case 0x60: inTemplateString = true; break // `\n        case 0x28: paren++; break                 // (\n        case 0x29: paren--; break                 // )\n        case 0x5B: square++; break                // [\n        case 0x5D: square--; break                // ]\n        case 0x7B: curly++; break                 // {\n        case 0x7D: curly--; break                 // }\n      }\n      if (c === 0x2f) { // /\n        var j = i - 1;\n        var p = (void 0);\n        // find first non-whitespace prev char\n        for (; j >= 0; j--) {\n          p = exp.charAt(j);\n          if (p !== ' ') { break }\n        }\n        if (!p || !validDivisionCharRE.test(p)) {\n          inRegex = true;\n        }\n      }\n    }\n  }\n\n  if (expression === undefined) {\n    expression = exp.slice(0, i).trim();\n  } else if (lastFilterIndex !== 0) {\n    pushFilter();\n  }\n\n  function pushFilter () {\n    (filters || (filters = [])).push(exp.slice(lastFilterIndex, i).trim());\n    lastFilterIndex = i + 1;\n  }\n\n  if (filters) {\n    for (i = 0; i < filters.length; i++) {\n      expression = wrapFilter(expression, filters[i]);\n    }\n  }\n\n  return expression\n}\n\nfunction wrapFilter (exp, filter) {\n  var i = filter.indexOf('(');\n  if (i < 0) {\n    // _f: resolveFilter\n    return (\"_f(\\\"\" + filter + \"\\\")(\" + exp + \")\")\n  } else {\n    var name = filter.slice(0, i);\n    var args = filter.slice(i + 1);\n    return (\"_f(\\\"\" + name + \"\\\")(\" + exp + \",\" + args)\n  }\n}\n\n/*  */\n\nvar defaultTagRE = /\\{\\{((?:.|\\n)+?)\\}\\}/g;\nvar regexEscapeRE = /[-.*+?^${}()|[\\]\\/\\\\]/g;\n\nvar buildRegex = cached(function (delimiters) {\n  var open = delimiters[0].replace(regexEscapeRE, '\\\\$&');\n  var close = delimiters[1].replace(regexEscapeRE, '\\\\$&');\n  return new RegExp(open + '((?:.|\\\\n)+?)' + close, 'g')\n});\n\nfunction parseText (\n  text,\n  delimiters\n) {\n  var tagRE = delimiters ? buildRegex(delimiters) : defaultTagRE;\n  if (!tagRE.test(text)) {\n    return\n  }\n  var tokens = [];\n  var lastIndex = tagRE.lastIndex = 0;\n  var match, index;\n  while ((match = tagRE.exec(text))) {\n    index = match.index;\n    // push text token\n    if (index > lastIndex) {\n      tokens.push(JSON.stringify(text.slice(lastIndex, index)));\n    }\n    // tag token\n    var exp = parseFilters(match[1].trim());\n    tokens.push((\"_s(\" + exp + \")\"));\n    lastIndex = index + match[0].length;\n  }\n  if (lastIndex < text.length) {\n    tokens.push(JSON.stringify(text.slice(lastIndex)));\n  }\n  return tokens.join('+')\n}\n\n/*  */\n\n/**\n * Cross-platform code generation for component v-model\n */\nfunction genComponentModel (\n  el,\n  value,\n  modifiers\n) {\n  var ref = modifiers || {};\n  var number = ref.number;\n  var trim = ref.trim;\n\n  var baseValueExpression = '$$v';\n  var valueExpression = baseValueExpression;\n  if (trim) {\n    valueExpression =\n      \"(typeof \" + baseValueExpression + \" === 'string'\" +\n        \"? \" + baseValueExpression + \".trim()\" +\n        \": \" + baseValueExpression + \")\";\n  }\n  if (number) {\n    valueExpression = \"_n(\" + valueExpression + \")\";\n  }\n  var assignment = genAssignmentCode(value, valueExpression);\n\n  el.model = {\n    value: (\"(\" + value + \")\"),\n    expression: (\"\\\"\" + value + \"\\\"\"),\n    callback: (\"function (\" + baseValueExpression + \") {\" + assignment + \"}\")\n  };\n}\n\n/**\n * Cross-platform codegen helper for generating v-model value assignment code.\n */\nfunction genAssignmentCode (\n  value,\n  assignment\n) {\n  var modelRs = parseModel(value);\n  if (modelRs.idx === null) {\n    return (value + \"=\" + assignment)\n  } else {\n    return (\"$set(\" + (modelRs.exp) + \", \" + (modelRs.idx) + \", \" + assignment + \")\")\n  }\n}\n\n/**\n * parse directive model to do the array update transform. a[idx] = val => $$a.splice($$idx, 1, val)\n *\n * for loop possible cases:\n *\n * - test\n * - test[idx]\n * - test[test1[idx]]\n * - test[\"a\"][idx]\n * - xxx.test[a[a].test1[idx]]\n * - test.xxx.a[\"asa\"][test1[idx]]\n *\n */\n\nvar len;\nvar str;\nvar chr;\nvar index;\nvar expressionPos;\nvar expressionEndPos;\n\nfunction parseModel (val) {\n  str = val;\n  len = str.length;\n  index = expressionPos = expressionEndPos = 0;\n\n  if (val.indexOf('[') < 0 || val.lastIndexOf(']') < len - 1) {\n    return {\n      exp: val,\n      idx: null\n    }\n  }\n\n  while (!eof()) {\n    chr = next();\n    /* istanbul ignore if */\n    if (isStringStart(chr)) {\n      parseString(chr);\n    } else if (chr === 0x5B) {\n      parseBracket(chr);\n    }\n  }\n\n  return {\n    exp: val.substring(0, expressionPos),\n    idx: val.substring(expressionPos + 1, expressionEndPos)\n  }\n}\n\nfunction next () {\n  return str.charCodeAt(++index)\n}\n\nfunction eof () {\n  return index >= len\n}\n\nfunction isStringStart (chr) {\n  return chr === 0x22 || chr === 0x27\n}\n\nfunction parseBracket (chr) {\n  var inBracket = 1;\n  expressionPos = index;\n  while (!eof()) {\n    chr = next();\n    if (isStringStart(chr)) {\n      parseString(chr);\n      continue\n    }\n    if (chr === 0x5B) { inBracket++; }\n    if (chr === 0x5D) { inBracket--; }\n    if (inBracket === 0) {\n      expressionEndPos = index;\n      break\n    }\n  }\n}\n\nfunction parseString (chr) {\n  var stringQuote = chr;\n  while (!eof()) {\n    chr = next();\n    if (chr === stringQuote) {\n      break\n    }\n  }\n}\n\nvar ASSET_TYPES = [\n  'component',\n  'directive',\n  'filter'\n];\n\nvar LIFECYCLE_HOOKS = [\n  'beforeCreate',\n  'created',\n  'beforeMount',\n  'mounted',\n  'beforeUpdate',\n  'updated',\n  'beforeDestroy',\n  'destroyed',\n  'activated',\n  'deactivated'\n];\n\n/*  */\n\nvar config = ({\n  /**\n   * Option merge strategies (used in core/util/options)\n   */\n  optionMergeStrategies: Object.create(null),\n\n  /**\n   * Whether to suppress warnings.\n   */\n  silent: false,\n\n  /**\n   * Show production mode tip message on boot?\n   */\n  productionTip: process.env.NODE_ENV !== 'production',\n\n  /**\n   * Whether to enable devtools\n   */\n  devtools: process.env.NODE_ENV !== 'production',\n\n  /**\n   * Whether to record perf\n   */\n  performance: false,\n\n  /**\n   * Error handler for watcher errors\n   */\n  errorHandler: null,\n\n  /**\n   * Warn handler for watcher warns\n   */\n  warnHandler: null,\n\n  /**\n   * Ignore certain custom elements\n   */\n  ignoredElements: [],\n\n  /**\n   * Custom user key aliases for v-on\n   */\n  keyCodes: Object.create(null),\n\n  /**\n   * Check if a tag is reserved so that it cannot be registered as a\n   * component. This is platform-dependent and may be overwritten.\n   */\n  isReservedTag: no,\n\n  /**\n   * Check if an attribute is reserved so that it cannot be used as a component\n   * prop. This is platform-dependent and may be overwritten.\n   */\n  isReservedAttr: no,\n\n  /**\n   * Check if a tag is an unknown element.\n   * Platform-dependent.\n   */\n  isUnknownElement: no,\n\n  /**\n   * Get the namespace of an element\n   */\n  getTagNamespace: noop,\n\n  /**\n   * Parse the real tag name for the specific platform.\n   */\n  parsePlatformTagName: identity,\n\n  /**\n   * Check if an attribute must be bound using property, e.g. value\n   * Platform-dependent.\n   */\n  mustUseProp: no,\n\n  /**\n   * Exposed for legacy reasons\n   */\n  _lifecycleHooks: LIFECYCLE_HOOKS\n});\n\n/*  */\n\nvar warn$1 = noop;\nvar tip = noop;\nvar formatComponentName = (null); // work around flow check\n\nif (process.env.NODE_ENV !== 'production') {\n  var hasConsole = typeof console !== 'undefined';\n  var classifyRE = /(?:^|[-_])(\\w)/g;\n  var classify = function (str) { return str\n    .replace(classifyRE, function (c) { return c.toUpperCase(); })\n    .replace(/[-_]/g, ''); };\n\n  warn$1 = function (msg, vm) {\n    var trace = vm ? generateComponentTrace(vm) : '';\n\n    if (config.warnHandler) {\n      config.warnHandler.call(null, msg, vm, trace);\n    } else if (hasConsole && (!config.silent)) {\n      console.error((\"[Vue warn]: \" + msg + trace));\n    }\n  };\n\n  tip = function (msg, vm) {\n    if (hasConsole && (!config.silent)) {\n      console.warn(\"[Vue tip]: \" + msg + (\n        vm ? generateComponentTrace(vm) : ''\n      ));\n    }\n  };\n\n  formatComponentName = function (vm, includeFile) {\n    if (vm.$root === vm) {\n      return '<Root>'\n    }\n    var name = typeof vm === 'string'\n      ? vm\n      : typeof vm === 'function' && vm.options\n        ? vm.options.name\n        : vm._isVue\n          ? vm.$options.name || vm.$options._componentTag\n          : vm.name;\n\n    var file = vm._isVue && vm.$options.__file;\n    if (!name && file) {\n      var match = file.match(/([^/\\\\]+)\\.vue$/);\n      name = match && match[1];\n    }\n\n    return (\n      (name ? (\"<\" + (classify(name)) + \">\") : \"<Anonymous>\") +\n      (file && includeFile !== false ? (\" at \" + file) : '')\n    )\n  };\n\n  var repeat = function (str, n) {\n    var res = '';\n    while (n) {\n      if (n % 2 === 1) { res += str; }\n      if (n > 1) { str += str; }\n      n >>= 1;\n    }\n    return res\n  };\n\n  var generateComponentTrace = function (vm) {\n    if (vm._isVue && vm.$parent) {\n      var tree = [];\n      var currentRecursiveSequence = 0;\n      while (vm) {\n        if (tree.length > 0) {\n          var last = tree[tree.length - 1];\n          if (last.constructor === vm.constructor) {\n            currentRecursiveSequence++;\n            vm = vm.$parent;\n            continue\n          } else if (currentRecursiveSequence > 0) {\n            tree[tree.length - 1] = [last, currentRecursiveSequence];\n            currentRecursiveSequence = 0;\n          }\n        }\n        tree.push(vm);\n        vm = vm.$parent;\n      }\n      return '\\n\\nfound in\\n\\n' + tree\n        .map(function (vm, i) { return (\"\" + (i === 0 ? '---> ' : repeat(' ', 5 + i * 2)) + (Array.isArray(vm)\n            ? ((formatComponentName(vm[0])) + \"... (\" + (vm[1]) + \" recursive calls)\")\n            : formatComponentName(vm))); })\n        .join('\\n')\n    } else {\n      return (\"\\n\\n(found in \" + (formatComponentName(vm)) + \")\")\n    }\n  };\n}\n\n/*  */\n\nfunction handleError (err, vm, info) {\n  if (config.errorHandler) {\n    config.errorHandler.call(null, err, vm, info);\n  } else {\n    if (process.env.NODE_ENV !== 'production') {\n      warn$1((\"Error in \" + info + \": \\\"\" + (err.toString()) + \"\\\"\"), vm);\n    }\n    /* istanbul ignore else */\n    if (inBrowser && typeof console !== 'undefined') {\n      console.error(err);\n    } else {\n      throw err\n    }\n  }\n}\n\n/*  */\n/* globals MutationObserver */\n\n// can we use __proto__?\nvar hasProto = '__proto__' in {};\n\n// Browser environment sniffing\nvar inBrowser = typeof window !== 'undefined';\nvar UA = inBrowser && window.navigator.userAgent.toLowerCase();\nvar isIE = UA && /msie|trident/.test(UA);\nvar isIE9 = UA && UA.indexOf('msie 9.0') > 0;\nvar isEdge = UA && UA.indexOf('edge/') > 0;\nvar isAndroid = UA && UA.indexOf('android') > 0;\nvar isIOS = UA && /iphone|ipad|ipod|ios/.test(UA);\nvar isChrome = UA && /chrome\\/\\d+/.test(UA) && !isEdge;\n\n// Firefix has a \"watch\" function on Object.prototype...\nvar nativeWatch = ({}).watch;\n\nvar supportsPassive = false;\nif (inBrowser) {\n  try {\n    var opts = {};\n    Object.defineProperty(opts, 'passive', ({\n      get: function get () {\n        /* istanbul ignore next */\n        supportsPassive = true;\n      }\n    })); // https://github.com/facebook/flow/issues/285\n    window.addEventListener('test-passive', null, opts);\n  } catch (e) {}\n}\n\n// this needs to be lazy-evaled because vue may be required before\n// vue-server-renderer can set VUE_ENV\nvar _isServer;\nvar isServerRendering = function () {\n  if (_isServer === undefined) {\n    /* istanbul ignore if */\n    if (!inBrowser && typeof global !== 'undefined') {\n      // detect presence of vue-server-renderer and avoid\n      // Webpack shimming the process\n      _isServer = global['process'].env.VUE_ENV === 'server';\n    } else {\n      _isServer = false;\n    }\n  }\n  return _isServer\n};\n\n// detect devtools\n\n\n/* istanbul ignore next */\nfunction isNative (Ctor) {\n  return typeof Ctor === 'function' && /native code/.test(Ctor.toString())\n}\n\nvar hasSymbol =\n  typeof Symbol !== 'undefined' && isNative(Symbol) &&\n  typeof Reflect !== 'undefined' && isNative(Reflect.ownKeys);\n\n/**\n * Defer a task to execute it asynchronously.\n */\nvar nextTick = (function () {\n  var callbacks = [];\n  var pending = false;\n  var timerFunc;\n\n  function nextTickHandler () {\n    pending = false;\n    var copies = callbacks.slice(0);\n    callbacks.length = 0;\n    for (var i = 0; i < copies.length; i++) {\n      copies[i]();\n    }\n  }\n\n  // the nextTick behavior leverages the microtask queue, which can be accessed\n  // via either native Promise.then or MutationObserver.\n  // MutationObserver has wider support, however it is seriously bugged in\n  // UIWebView in iOS >= 9.3.3 when triggered in touch event handlers. It\n  // completely stops working after triggering a few times... so, if native\n  // Promise is available, we will use it:\n  /* istanbul ignore if */\n  if (typeof Promise !== 'undefined' && isNative(Promise)) {\n    var p = Promise.resolve();\n    var logError = function (err) { console.error(err); };\n    timerFunc = function () {\n      p.then(nextTickHandler).catch(logError);\n      // in problematic UIWebViews, Promise.then doesn't completely break, but\n      // it can get stuck in a weird state where callbacks are pushed into the\n      // microtask queue but the queue isn't being flushed, until the browser\n      // needs to do some other work, e.g. handle a timer. Therefore we can\n      // \"force\" the microtask queue to be flushed by adding an empty timer.\n      if (isIOS) { setTimeout(noop); }\n    };\n  } else if (typeof MutationObserver !== 'undefined' && (\n    isNative(MutationObserver) ||\n    // PhantomJS and iOS 7.x\n    MutationObserver.toString() === '[object MutationObserverConstructor]'\n  )) {\n    // use MutationObserver where native Promise is not available,\n    // e.g. PhantomJS IE11, iOS7, Android 4.4\n    var counter = 1;\n    var observer = new MutationObserver(nextTickHandler);\n    var textNode = document.createTextNode(String(counter));\n    observer.observe(textNode, {\n      characterData: true\n    });\n    timerFunc = function () {\n      counter = (counter + 1) % 2;\n      textNode.data = String(counter);\n    };\n  } else {\n    // fallback to setTimeout\n    /* istanbul ignore next */\n    timerFunc = function () {\n      setTimeout(nextTickHandler, 0);\n    };\n  }\n\n  return function queueNextTick (cb, ctx) {\n    var _resolve;\n    callbacks.push(function () {\n      if (cb) {\n        try {\n          cb.call(ctx);\n        } catch (e) {\n          handleError(e, ctx, 'nextTick');\n        }\n      } else if (_resolve) {\n        _resolve(ctx);\n      }\n    });\n    if (!pending) {\n      pending = true;\n      timerFunc();\n    }\n    if (!cb && typeof Promise !== 'undefined') {\n      return new Promise(function (resolve, reject) {\n        _resolve = resolve;\n      })\n    }\n  }\n})();\n\nvar _Set;\n/* istanbul ignore if */\nif (typeof Set !== 'undefined' && isNative(Set)) {\n  // use native Set when available.\n  _Set = Set;\n} else {\n  // a non-standard Set polyfill that only works with primitive keys.\n  _Set = (function () {\n    function Set () {\n      this.set = Object.create(null);\n    }\n    Set.prototype.has = function has (key) {\n      return this.set[key] === true\n    };\n    Set.prototype.add = function add (key) {\n      this.set[key] = true;\n    };\n    Set.prototype.clear = function clear () {\n      this.set = Object.create(null);\n    };\n\n    return Set;\n  }());\n}\n\n/*  */\n\nfunction baseWarn (msg) {\n  console.error((\"[Vue compiler]: \" + msg));\n}\n\nfunction pluckModuleFunction (\n  modules,\n  key\n) {\n  return modules\n    ? modules.map(function (m) { return m[key]; }).filter(function (_) { return _; })\n    : []\n}\n\nfunction addProp (el, name, value) {\n  (el.props || (el.props = [])).push({ name: name, value: value });\n}\n\nfunction addAttr (el, name, value) {\n  (el.attrs || (el.attrs = [])).push({ name: name, value: value });\n}\n\nfunction addDirective (\n  el,\n  name,\n  rawName,\n  value,\n  arg,\n  modifiers\n) {\n  (el.directives || (el.directives = [])).push({ name: name, rawName: rawName, value: value, arg: arg, modifiers: modifiers });\n}\n\nfunction addHandler (\n  el,\n  name,\n  value,\n  modifiers,\n  important,\n  warn\n) {\n  // warn prevent and passive modifier\n  /* istanbul ignore if */\n  if (\n    process.env.NODE_ENV !== 'production' && warn &&\n    modifiers && modifiers.prevent && modifiers.passive\n  ) {\n    warn(\n      'passive and prevent can\\'t be used together. ' +\n      'Passive handler can\\'t prevent default event.'\n    );\n  }\n  // check capture modifier\n  if (modifiers && modifiers.capture) {\n    delete modifiers.capture;\n    name = '!' + name; // mark the event as captured\n  }\n  if (modifiers && modifiers.once) {\n    delete modifiers.once;\n    name = '~' + name; // mark the event as once\n  }\n  /* istanbul ignore if */\n  if (modifiers && modifiers.passive) {\n    delete modifiers.passive;\n    name = '&' + name; // mark the event as passive\n  }\n  var events;\n  if (modifiers && modifiers.native) {\n    delete modifiers.native;\n    events = el.nativeEvents || (el.nativeEvents = {});\n  } else {\n    events = el.events || (el.events = {});\n  }\n  var newHandler = { value: value, modifiers: modifiers };\n  var handlers = events[name];\n  /* istanbul ignore if */\n  if (Array.isArray(handlers)) {\n    important ? handlers.unshift(newHandler) : handlers.push(newHandler);\n  } else if (handlers) {\n    events[name] = important ? [newHandler, handlers] : [handlers, newHandler];\n  } else {\n    events[name] = newHandler;\n  }\n}\n\nfunction getBindingAttr (\n  el,\n  name,\n  getStatic\n) {\n  var dynamicValue =\n    getAndRemoveAttr(el, ':' + name) ||\n    getAndRemoveAttr(el, 'v-bind:' + name);\n  if (dynamicValue != null) {\n    return parseFilters(dynamicValue)\n  } else if (getStatic !== false) {\n    var staticValue = getAndRemoveAttr(el, name);\n    if (staticValue != null) {\n      return JSON.stringify(staticValue)\n    }\n  }\n}\n\nfunction getAndRemoveAttr (el, name) {\n  var val;\n  if ((val = el.attrsMap[name]) != null) {\n    var list = el.attrsList;\n    for (var i = 0, l = list.length; i < l; i++) {\n      if (list[i].name === name) {\n        list.splice(i, 1);\n        break\n      }\n    }\n  }\n  return val\n}\n\n/*  */\n\nvar onRE = /^@|^v-on:/;\nvar dirRE = /^v-|^@|^:/;\nvar forAliasRE = /(.*?)\\s+(?:in|of)\\s+(.*)/;\nvar forIteratorRE = /\\((\\{[^}]*\\}|[^,]*),([^,]*)(?:,([^,]*))?\\)/;\n\nvar argRE = /:(.*)$/;\nvar bindRE = /^:|^v-bind:/;\nvar modifierRE = /\\.[^.]+/g;\n\nvar decodeHTMLCached = cached(he.decode);\n\n// configurable state\nvar warn;\nvar delimiters;\nvar transforms;\nvar preTransforms;\nvar postTransforms;\nvar platformIsPreTag;\nvar platformMustUseProp;\nvar platformGetTagNamespace;\n\n/**\n * Convert HTML string to AST.\n */\nfunction parse (\n  template,\n  options\n) {\n  warn = options.warn || baseWarn;\n\n  platformIsPreTag = options.isPreTag || no;\n  platformMustUseProp = options.mustUseProp || no;\n  platformGetTagNamespace = options.getTagNamespace || no;\n\n  transforms = pluckModuleFunction(options.modules, 'transformNode');\n  preTransforms = pluckModuleFunction(options.modules, 'preTransformNode');\n  postTransforms = pluckModuleFunction(options.modules, 'postTransformNode');\n\n  delimiters = options.delimiters;\n\n  var stack = [];\n  var preserveWhitespace = options.preserveWhitespace !== false;\n  var root;\n  var currentParent;\n  var inVPre = false;\n  var inPre = false;\n  var warned = false;\n\n  function warnOnce (msg) {\n    if (!warned) {\n      warned = true;\n      warn(msg);\n    }\n  }\n\n  function endPre (element) {\n    // check pre state\n    if (element.pre) {\n      inVPre = false;\n    }\n    if (platformIsPreTag(element.tag)) {\n      inPre = false;\n    }\n  }\n\n  parseHTML(template, {\n    warn: warn,\n    expectHTML: options.expectHTML,\n    isUnaryTag: options.isUnaryTag,\n    canBeLeftOpenTag: options.canBeLeftOpenTag,\n    shouldDecodeNewlines: options.shouldDecodeNewlines,\n    shouldKeepComment: options.comments,\n    start: function start (tag, attrs, unary) {\n      // check namespace.\n      // inherit parent ns if there is one\n      var ns = (currentParent && currentParent.ns) || platformGetTagNamespace(tag);\n\n      // handle IE svg bug\n      /* istanbul ignore if */\n      if (isIE && ns === 'svg') {\n        attrs = guardIESVGBug(attrs);\n      }\n\n      var element = {\n        type: 1,\n        tag: tag,\n        attrsList: attrs,\n        attrsMap: makeAttrsMap(attrs),\n        parent: currentParent,\n        children: []\n      };\n      if (ns) {\n        element.ns = ns;\n      }\n\n      if (isForbiddenTag(element) && !isServerRendering()) {\n        element.forbidden = true;\n        process.env.NODE_ENV !== 'production' && warn(\n          'Templates should only be responsible for mapping the state to the ' +\n          'UI. Avoid placing tags with side-effects in your templates, such as ' +\n          \"<\" + tag + \">\" + ', as they will not be parsed.'\n        );\n      }\n\n      // apply pre-transforms\n      for (var i = 0; i < preTransforms.length; i++) {\n        preTransforms[i](element, options);\n      }\n\n      if (!inVPre) {\n        processPre(element);\n        if (element.pre) {\n          inVPre = true;\n        }\n      }\n      if (platformIsPreTag(element.tag)) {\n        inPre = true;\n      }\n      if (inVPre) {\n        processRawAttrs(element);\n      } else {\n        processFor(element);\n        processIf(element);\n        processOnce(element);\n        processKey(element);\n\n        // determine whether this is a plain element after\n        // removing structural attributes\n        element.plain = !element.key && !attrs.length;\n\n        processRef(element);\n        processSlot(element);\n        processComponent(element);\n        for (var i$1 = 0; i$1 < transforms.length; i$1++) {\n          transforms[i$1](element, options);\n        }\n        processAttrs(element);\n      }\n\n      function checkRootConstraints (el) {\n        if (process.env.NODE_ENV !== 'production') {\n          if (el.tag === 'slot' || el.tag === 'template') {\n            warnOnce(\n              \"Cannot use <\" + (el.tag) + \"> as component root element because it may \" +\n              'contain multiple nodes.'\n            );\n          }\n          if (el.attrsMap.hasOwnProperty('v-for')) {\n            warnOnce(\n              'Cannot use v-for on stateful component root element because ' +\n              'it renders multiple elements.'\n            );\n          }\n        }\n      }\n\n      // tree management\n      if (!root) {\n        root = element;\n        checkRootConstraints(root);\n      } else if (!stack.length) {\n        // allow root elements with v-if, v-else-if and v-else\n        if (root.if && (element.elseif || element.else)) {\n          checkRootConstraints(element);\n          addIfCondition(root, {\n            exp: element.elseif,\n            block: element\n          });\n        } else if (process.env.NODE_ENV !== 'production') {\n          warnOnce(\n            \"Component template should contain exactly one root element. \" +\n            \"If you are using v-if on multiple elements, \" +\n            \"use v-else-if to chain them instead.\"\n          );\n        }\n      }\n      if (currentParent && !element.forbidden) {\n        if (element.elseif || element.else) {\n          processIfConditions(element, currentParent);\n        } else if (element.slotScope) { // scoped slot\n          currentParent.plain = false;\n          var name = element.slotTarget || '\"default\"';(currentParent.scopedSlots || (currentParent.scopedSlots = {}))[name] = element;\n        } else {\n          currentParent.children.push(element);\n          element.parent = currentParent;\n        }\n      }\n      if (!unary) {\n        currentParent = element;\n        stack.push(element);\n      } else {\n        endPre(element);\n      }\n      // apply post-transforms\n      for (var i$2 = 0; i$2 < postTransforms.length; i$2++) {\n        postTransforms[i$2](element, options);\n      }\n    },\n\n    end: function end () {\n      // remove trailing whitespace\n      var element = stack[stack.length - 1];\n      var lastNode = element.children[element.children.length - 1];\n      if (lastNode && lastNode.type === 3 && lastNode.text === ' ' && !inPre) {\n        element.children.pop();\n      }\n      // pop stack\n      stack.length -= 1;\n      currentParent = stack[stack.length - 1];\n      endPre(element);\n    },\n\n    chars: function chars (text) {\n      if (!currentParent) {\n        if (process.env.NODE_ENV !== 'production') {\n          if (text === template) {\n            warnOnce(\n              'Component template requires a root element, rather than just text.'\n            );\n          } else if ((text = text.trim())) {\n            warnOnce(\n              (\"text \\\"\" + text + \"\\\" outside root element will be ignored.\")\n            );\n          }\n        }\n        return\n      }\n      // IE textarea placeholder bug\n      /* istanbul ignore if */\n      if (isIE &&\n        currentParent.tag === 'textarea' &&\n        currentParent.attrsMap.placeholder === text\n      ) {\n        return\n      }\n      var children = currentParent.children;\n      text = inPre || text.trim()\n        ? isTextTag(currentParent) ? text : decodeHTMLCached(text)\n        // only preserve whitespace if its not right after a starting tag\n        : preserveWhitespace && children.length ? ' ' : '';\n      if (text) {\n        var expression;\n        if (!inVPre && text !== ' ' && (expression = parseText(text, delimiters))) {\n          children.push({\n            type: 2,\n            expression: expression,\n            text: text\n          });\n        } else if (text !== ' ' || !children.length || children[children.length - 1].text !== ' ') {\n          children.push({\n            type: 3,\n            text: text\n          });\n        }\n      }\n    },\n    comment: function comment (text) {\n      currentParent.children.push({\n        type: 3,\n        text: text,\n        isComment: true\n      });\n    }\n  });\n  return root\n}\n\nfunction processPre (el) {\n  if (getAndRemoveAttr(el, 'v-pre') != null) {\n    el.pre = true;\n  }\n}\n\nfunction processRawAttrs (el) {\n  var l = el.attrsList.length;\n  if (l) {\n    var attrs = el.attrs = new Array(l);\n    for (var i = 0; i < l; i++) {\n      attrs[i] = {\n        name: el.attrsList[i].name,\n        value: JSON.stringify(el.attrsList[i].value)\n      };\n    }\n  } else if (!el.pre) {\n    // non root node in pre blocks with no attributes\n    el.plain = true;\n  }\n}\n\nfunction processKey (el) {\n  var exp = getBindingAttr(el, 'key');\n  if (exp) {\n    if (process.env.NODE_ENV !== 'production' && el.tag === 'template') {\n      warn(\"<template> cannot be keyed. Place the key on real elements instead.\");\n    }\n    el.key = exp;\n  }\n}\n\nfunction processRef (el) {\n  var ref = getBindingAttr(el, 'ref');\n  if (ref) {\n    el.ref = ref;\n    el.refInFor = checkInFor(el);\n  }\n}\n\nfunction processFor (el) {\n  var exp;\n  if ((exp = getAndRemoveAttr(el, 'v-for'))) {\n    var inMatch = exp.match(forAliasRE);\n    if (!inMatch) {\n      process.env.NODE_ENV !== 'production' && warn(\n        (\"Invalid v-for expression: \" + exp)\n      );\n      return\n    }\n    el.for = inMatch[2].trim();\n    var alias = inMatch[1].trim();\n    var iteratorMatch = alias.match(forIteratorRE);\n    if (iteratorMatch) {\n      el.alias = iteratorMatch[1].trim();\n      el.iterator1 = iteratorMatch[2].trim();\n      if (iteratorMatch[3]) {\n        el.iterator2 = iteratorMatch[3].trim();\n      }\n    } else {\n      el.alias = alias;\n    }\n  }\n}\n\nfunction processIf (el) {\n  var exp = getAndRemoveAttr(el, 'v-if');\n  if (exp) {\n    el.if = exp;\n    addIfCondition(el, {\n      exp: exp,\n      block: el\n    });\n  } else {\n    if (getAndRemoveAttr(el, 'v-else') != null) {\n      el.else = true;\n    }\n    var elseif = getAndRemoveAttr(el, 'v-else-if');\n    if (elseif) {\n      el.elseif = elseif;\n    }\n  }\n}\n\nfunction processIfConditions (el, parent) {\n  var prev = findPrevElement(parent.children);\n  if (prev && prev.if) {\n    addIfCondition(prev, {\n      exp: el.elseif,\n      block: el\n    });\n  } else if (process.env.NODE_ENV !== 'production') {\n    warn(\n      \"v-\" + (el.elseif ? ('else-if=\"' + el.elseif + '\"') : 'else') + \" \" +\n      \"used on element <\" + (el.tag) + \"> without corresponding v-if.\"\n    );\n  }\n}\n\nfunction findPrevElement (children) {\n  var i = children.length;\n  while (i--) {\n    if (children[i].type === 1) {\n      return children[i]\n    } else {\n      if (process.env.NODE_ENV !== 'production' && children[i].text !== ' ') {\n        warn(\n          \"text \\\"\" + (children[i].text.trim()) + \"\\\" between v-if and v-else(-if) \" +\n          \"will be ignored.\"\n        );\n      }\n      children.pop();\n    }\n  }\n}\n\nfunction addIfCondition (el, condition) {\n  if (!el.ifConditions) {\n    el.ifConditions = [];\n  }\n  el.ifConditions.push(condition);\n}\n\nfunction processOnce (el) {\n  var once$$1 = getAndRemoveAttr(el, 'v-once');\n  if (once$$1 != null) {\n    el.once = true;\n  }\n}\n\nfunction processSlot (el) {\n  if (el.tag === 'slot') {\n    el.slotName = getBindingAttr(el, 'name');\n    if (process.env.NODE_ENV !== 'production' && el.key) {\n      warn(\n        \"`key` does not work on <slot> because slots are abstract outlets \" +\n        \"and can possibly expand into multiple elements. \" +\n        \"Use the key on a wrapping element instead.\"\n      );\n    }\n  } else {\n    var slotTarget = getBindingAttr(el, 'slot');\n    if (slotTarget) {\n      el.slotTarget = slotTarget === '\"\"' ? '\"default\"' : slotTarget;\n    }\n    if (el.tag === 'template') {\n      el.slotScope = getAndRemoveAttr(el, 'scope');\n    }\n  }\n}\n\nfunction processComponent (el) {\n  var binding;\n  if ((binding = getBindingAttr(el, 'is'))) {\n    el.component = binding;\n  }\n  if (getAndRemoveAttr(el, 'inline-template') != null) {\n    el.inlineTemplate = true;\n  }\n}\n\nfunction processAttrs (el) {\n  var list = el.attrsList;\n  var i, l, name, rawName, value, modifiers, isProp;\n  for (i = 0, l = list.length; i < l; i++) {\n    name = rawName = list[i].name;\n    value = list[i].value;\n    if (dirRE.test(name)) {\n      // mark element as dynamic\n      el.hasBindings = true;\n      // modifiers\n      modifiers = parseModifiers(name);\n      if (modifiers) {\n        name = name.replace(modifierRE, '');\n      }\n      if (bindRE.test(name)) { // v-bind\n        name = name.replace(bindRE, '');\n        value = parseFilters(value);\n        isProp = false;\n        if (modifiers) {\n          if (modifiers.prop) {\n            isProp = true;\n            name = camelize(name);\n            if (name === 'innerHtml') { name = 'innerHTML'; }\n          }\n          if (modifiers.camel) {\n            name = camelize(name);\n          }\n          if (modifiers.sync) {\n            addHandler(\n              el,\n              (\"update:\" + (camelize(name))),\n              genAssignmentCode(value, \"$event\")\n            );\n          }\n        }\n        if (!el.component && (\n          isProp || platformMustUseProp(el.tag, el.attrsMap.type, name)\n        )) {\n          addProp(el, name, value);\n        } else {\n          addAttr(el, name, value);\n        }\n      } else if (onRE.test(name)) { // v-on\n        name = name.replace(onRE, '');\n        addHandler(el, name, value, modifiers, false, warn);\n      } else { // normal directives\n        name = name.replace(dirRE, '');\n        // parse arg\n        var argMatch = name.match(argRE);\n        var arg = argMatch && argMatch[1];\n        if (arg) {\n          name = name.slice(0, -(arg.length + 1));\n        }\n        addDirective(el, name, rawName, value, arg, modifiers);\n        if (process.env.NODE_ENV !== 'production' && name === 'model') {\n          checkForAliasModel(el, value);\n        }\n      }\n    } else {\n      // literal attribute\n      if (process.env.NODE_ENV !== 'production') {\n        var expression = parseText(value, delimiters);\n        if (expression) {\n          warn(\n            name + \"=\\\"\" + value + \"\\\": \" +\n            'Interpolation inside attributes has been removed. ' +\n            'Use v-bind or the colon shorthand instead. For example, ' +\n            'instead of <div id=\"{{ val }}\">, use <div :id=\"val\">.'\n          );\n        }\n      }\n      addAttr(el, name, JSON.stringify(value));\n    }\n  }\n}\n\nfunction checkInFor (el) {\n  var parent = el;\n  while (parent) {\n    if (parent.for !== undefined) {\n      return true\n    }\n    parent = parent.parent;\n  }\n  return false\n}\n\nfunction parseModifiers (name) {\n  var match = name.match(modifierRE);\n  if (match) {\n    var ret = {};\n    match.forEach(function (m) { ret[m.slice(1)] = true; });\n    return ret\n  }\n}\n\nfunction makeAttrsMap (attrs) {\n  var map = {};\n  for (var i = 0, l = attrs.length; i < l; i++) {\n    if (\n      process.env.NODE_ENV !== 'production' &&\n      map[attrs[i].name] && !isIE && !isEdge\n    ) {\n      warn('duplicate attribute: ' + attrs[i].name);\n    }\n    map[attrs[i].name] = attrs[i].value;\n  }\n  return map\n}\n\n// for script (e.g. type=\"x/template\") or style, do not decode content\nfunction isTextTag (el) {\n  return el.tag === 'script' || el.tag === 'style'\n}\n\nfunction isForbiddenTag (el) {\n  return (\n    el.tag === 'style' ||\n    (el.tag === 'script' && (\n      !el.attrsMap.type ||\n      el.attrsMap.type === 'text/javascript'\n    ))\n  )\n}\n\nvar ieNSBug = /^xmlns:NS\\d+/;\nvar ieNSPrefix = /^NS\\d+:/;\n\n/* istanbul ignore next */\nfunction guardIESVGBug (attrs) {\n  var res = [];\n  for (var i = 0; i < attrs.length; i++) {\n    var attr = attrs[i];\n    if (!ieNSBug.test(attr.name)) {\n      attr.name = attr.name.replace(ieNSPrefix, '');\n      res.push(attr);\n    }\n  }\n  return res\n}\n\nfunction checkForAliasModel (el, value) {\n  var _el = el;\n  while (_el) {\n    if (_el.for && _el.alias === value) {\n      warn(\n        \"<\" + (el.tag) + \" v-model=\\\"\" + value + \"\\\">: \" +\n        \"You are binding v-model directly to a v-for iteration alias. \" +\n        \"This will not be able to modify the v-for source array because \" +\n        \"writing to the alias is like modifying a function local variable. \" +\n        \"Consider using an array of objects and use v-model on an object property instead.\"\n      );\n    }\n    _el = _el.parent;\n  }\n}\n\n/*  */\n\nvar isStaticKey;\nvar isPlatformReservedTag;\n\nvar genStaticKeysCached = cached(genStaticKeys$1);\n\n/**\n * Goal of the optimizer: walk the generated template AST tree\n * and detect sub-trees that are purely static, i.e. parts of\n * the DOM that never needs to change.\n *\n * Once we detect these sub-trees, we can:\n *\n * 1. Hoist them into constants, so that we no longer need to\n *    create fresh nodes for them on each re-render;\n * 2. Completely skip them in the patching process.\n */\nfunction optimize (root, options) {\n  if (!root) { return }\n  isStaticKey = genStaticKeysCached(options.staticKeys || '');\n  isPlatformReservedTag = options.isReservedTag || no;\n  // first pass: mark all non-static nodes.\n  markStatic(root);\n  // second pass: mark static roots.\n  markStaticRoots(root, false);\n}\n\nfunction genStaticKeys$1 (keys) {\n  return makeMap(\n    'type,tag,attrsList,attrsMap,plain,parent,children,attrs' +\n    (keys ? ',' + keys : '')\n  )\n}\n\nfunction markStatic (node) {\n  node.static = isStatic(node);\n  if (node.type === 1) {\n    // do not make component slot content static. this avoids\n    // 1. components not able to mutate slot nodes\n    // 2. static slot content fails for hot-reloading\n    if (\n      !isPlatformReservedTag(node.tag) &&\n      node.tag !== 'slot' &&\n      node.attrsMap['inline-template'] == null\n    ) {\n      return\n    }\n    for (var i = 0, l = node.children.length; i < l; i++) {\n      var child = node.children[i];\n      markStatic(child);\n      if (!child.static) {\n        node.static = false;\n      }\n    }\n    if (node.ifConditions) {\n      for (var i$1 = 1, l$1 = node.ifConditions.length; i$1 < l$1; i$1++) {\n        var block = node.ifConditions[i$1].block;\n        markStatic(block);\n        if (!block.static) {\n          node.static = false;\n        }\n      }\n    }\n  }\n}\n\nfunction markStaticRoots (node, isInFor) {\n  if (node.type === 1) {\n    if (node.static || node.once) {\n      node.staticInFor = isInFor;\n    }\n    // For a node to qualify as a static root, it should have children that\n    // are not just static text. Otherwise the cost of hoisting out will\n    // outweigh the benefits and it's better off to just always render it fresh.\n    if (node.static && node.children.length && !(\n      node.children.length === 1 &&\n      node.children[0].type === 3\n    )) {\n      node.staticRoot = true;\n      return\n    } else {\n      node.staticRoot = false;\n    }\n    if (node.children) {\n      for (var i = 0, l = node.children.length; i < l; i++) {\n        markStaticRoots(node.children[i], isInFor || !!node.for);\n      }\n    }\n    if (node.ifConditions) {\n      for (var i$1 = 1, l$1 = node.ifConditions.length; i$1 < l$1; i$1++) {\n        markStaticRoots(node.ifConditions[i$1].block, isInFor);\n      }\n    }\n  }\n}\n\nfunction isStatic (node) {\n  if (node.type === 2) { // expression\n    return false\n  }\n  if (node.type === 3) { // text\n    return true\n  }\n  return !!(node.pre || (\n    !node.hasBindings && // no dynamic bindings\n    !node.if && !node.for && // not v-if or v-for or v-else\n    !isBuiltInTag(node.tag) && // not a built-in\n    isPlatformReservedTag(node.tag) && // not a component\n    !isDirectChildOfTemplateFor(node) &&\n    Object.keys(node).every(isStaticKey)\n  ))\n}\n\nfunction isDirectChildOfTemplateFor (node) {\n  while (node.parent) {\n    node = node.parent;\n    if (node.tag !== 'template') {\n      return false\n    }\n    if (node.for) {\n      return true\n    }\n  }\n  return false\n}\n\n/*  */\n\nvar fnExpRE = /^\\s*([\\w$_]+|\\([^)]*?\\))\\s*=>|^function\\s*\\(/;\nvar simplePathRE = /^\\s*[A-Za-z_$][\\w$]*(?:\\.[A-Za-z_$][\\w$]*|\\['.*?']|\\[\".*?\"]|\\[\\d+]|\\[[A-Za-z_$][\\w$]*])*\\s*$/;\n\n// keyCode aliases\nvar keyCodes = {\n  esc: 27,\n  tab: 9,\n  enter: 13,\n  space: 32,\n  up: 38,\n  left: 37,\n  right: 39,\n  down: 40,\n  'delete': [8, 46]\n};\n\n// #4868: modifiers that prevent the execution of the listener\n// need to explicitly return null so that we can determine whether to remove\n// the listener for .once\nvar genGuard = function (condition) { return (\"if(\" + condition + \")return null;\"); };\n\nvar modifierCode = {\n  stop: '$event.stopPropagation();',\n  prevent: '$event.preventDefault();',\n  self: genGuard(\"$event.target !== $event.currentTarget\"),\n  ctrl: genGuard(\"!$event.ctrlKey\"),\n  shift: genGuard(\"!$event.shiftKey\"),\n  alt: genGuard(\"!$event.altKey\"),\n  meta: genGuard(\"!$event.metaKey\"),\n  left: genGuard(\"'button' in $event && $event.button !== 0\"),\n  middle: genGuard(\"'button' in $event && $event.button !== 1\"),\n  right: genGuard(\"'button' in $event && $event.button !== 2\")\n};\n\nfunction genHandlers (\n  events,\n  isNative,\n  warn\n) {\n  var res = isNative ? 'nativeOn:{' : 'on:{';\n  for (var name in events) {\n    var handler = events[name];\n    // #5330: warn click.right, since right clicks do not actually fire click events.\n    if (process.env.NODE_ENV !== 'production' &&\n      name === 'click' &&\n      handler && handler.modifiers && handler.modifiers.right\n    ) {\n      warn(\n        \"Use \\\"contextmenu\\\" instead of \\\"click.right\\\" since right clicks \" +\n        \"do not actually fire \\\"click\\\" events.\"\n      );\n    }\n    res += \"\\\"\" + name + \"\\\":\" + (genHandler(name, handler)) + \",\";\n  }\n  return res.slice(0, -1) + '}'\n}\n\nfunction genHandler (\n  name,\n  handler\n) {\n  if (!handler) {\n    return 'function(){}'\n  }\n\n  if (Array.isArray(handler)) {\n    return (\"[\" + (handler.map(function (handler) { return genHandler(name, handler); }).join(',')) + \"]\")\n  }\n\n  var isMethodPath = simplePathRE.test(handler.value);\n  var isFunctionExpression = fnExpRE.test(handler.value);\n\n  if (!handler.modifiers) {\n    return isMethodPath || isFunctionExpression\n      ? handler.value\n      : (\"function($event){\" + (handler.value) + \"}\") // inline statement\n  } else {\n    var code = '';\n    var genModifierCode = '';\n    var keys = [];\n    for (var key in handler.modifiers) {\n      if (modifierCode[key]) {\n        genModifierCode += modifierCode[key];\n        // left/right\n        if (keyCodes[key]) {\n          keys.push(key);\n        }\n      } else {\n        keys.push(key);\n      }\n    }\n    if (keys.length) {\n      code += genKeyFilter(keys);\n    }\n    // Make sure modifiers like prevent and stop get executed after key filtering\n    if (genModifierCode) {\n      code += genModifierCode;\n    }\n    var handlerCode = isMethodPath\n      ? handler.value + '($event)'\n      : isFunctionExpression\n        ? (\"(\" + (handler.value) + \")($event)\")\n        : handler.value;\n    return (\"function($event){\" + code + handlerCode + \"}\")\n  }\n}\n\nfunction genKeyFilter (keys) {\n  return (\"if(!('button' in $event)&&\" + (keys.map(genFilterCode).join('&&')) + \")return null;\")\n}\n\nfunction genFilterCode (key) {\n  var keyVal = parseInt(key, 10);\n  if (keyVal) {\n    return (\"$event.keyCode!==\" + keyVal)\n  }\n  var alias = keyCodes[key];\n  return (\"_k($event.keyCode,\" + (JSON.stringify(key)) + (alias ? ',' + JSON.stringify(alias) : '') + \")\")\n}\n\n/*  */\n\nvar emptyObject = Object.freeze({});\n\n/**\n * Check if a string starts with $ or _\n */\n\n\n/**\n * Define a property.\n */\nfunction def (obj, key, val, enumerable) {\n  Object.defineProperty(obj, key, {\n    value: val,\n    enumerable: !!enumerable,\n    writable: true,\n    configurable: true\n  });\n}\n\n/*  */\n\n\nvar uid = 0;\n\n/**\n * A dep is an observable that can have multiple\n * directives subscribing to it.\n */\nvar Dep = function Dep () {\n  this.id = uid++;\n  this.subs = [];\n};\n\nDep.prototype.addSub = function addSub (sub) {\n  this.subs.push(sub);\n};\n\nDep.prototype.removeSub = function removeSub (sub) {\n  remove(this.subs, sub);\n};\n\nDep.prototype.depend = function depend () {\n  if (Dep.target) {\n    Dep.target.addDep(this);\n  }\n};\n\nDep.prototype.notify = function notify () {\n  // stabilize the subscriber list first\n  var subs = this.subs.slice();\n  for (var i = 0, l = subs.length; i < l; i++) {\n    subs[i].update();\n  }\n};\n\n// the current target watcher being evaluated.\n// this is globally unique because there could be only one\n// watcher being evaluated at any time.\nDep.target = null;\n\n/*\n * not type checking this file because flow doesn't play well with\n * dynamically accessing methods on Array prototype\n */\n\nvar arrayProto = Array.prototype;\nvar arrayMethods = Object.create(arrayProto);[\n  'push',\n  'pop',\n  'shift',\n  'unshift',\n  'splice',\n  'sort',\n  'reverse'\n]\n.forEach(function (method) {\n  // cache original method\n  var original = arrayProto[method];\n  def(arrayMethods, method, function mutator () {\n    var args = [], len = arguments.length;\n    while ( len-- ) args[ len ] = arguments[ len ];\n\n    var result = original.apply(this, args);\n    var ob = this.__ob__;\n    var inserted;\n    switch (method) {\n      case 'push':\n      case 'unshift':\n        inserted = args;\n        break\n      case 'splice':\n        inserted = args.slice(2);\n        break\n    }\n    if (inserted) { ob.observeArray(inserted); }\n    // notify change\n    ob.dep.notify();\n    return result\n  });\n});\n\n/*  */\n\nvar arrayKeys = Object.getOwnPropertyNames(arrayMethods);\n\n/**\n * By default, when a reactive property is set, the new value is\n * also converted to become reactive. However when passing down props,\n * we don't want to force conversion because the value may be a nested value\n * under a frozen data structure. Converting it would defeat the optimization.\n */\nvar observerState = {\n  shouldConvert: true\n};\n\n/**\n * Observer class that are attached to each observed\n * object. Once attached, the observer converts target\n * object's property keys into getter/setters that\n * collect dependencies and dispatches updates.\n */\nvar Observer = function Observer (value) {\n  this.value = value;\n  this.dep = new Dep();\n  this.vmCount = 0;\n  def(value, '__ob__', this);\n  if (Array.isArray(value)) {\n    var augment = hasProto\n      ? protoAugment\n      : copyAugment;\n    augment(value, arrayMethods, arrayKeys);\n    this.observeArray(value);\n  } else {\n    this.walk(value);\n  }\n};\n\n/**\n * Walk through each property and convert them into\n * getter/setters. This method should only be called when\n * value type is Object.\n */\nObserver.prototype.walk = function walk (obj) {\n  var keys = Object.keys(obj);\n  for (var i = 0; i < keys.length; i++) {\n    defineReactive$$1(obj, keys[i], obj[keys[i]]);\n  }\n};\n\n/**\n * Observe a list of Array items.\n */\nObserver.prototype.observeArray = function observeArray (items) {\n  for (var i = 0, l = items.length; i < l; i++) {\n    observe(items[i]);\n  }\n};\n\n// helpers\n\n/**\n * Augment an target Object or Array by intercepting\n * the prototype chain using __proto__\n */\nfunction protoAugment (target, src, keys) {\n  /* eslint-disable no-proto */\n  target.__proto__ = src;\n  /* eslint-enable no-proto */\n}\n\n/**\n * Augment an target Object or Array by defining\n * hidden properties.\n */\n/* istanbul ignore next */\nfunction copyAugment (target, src, keys) {\n  for (var i = 0, l = keys.length; i < l; i++) {\n    var key = keys[i];\n    def(target, key, src[key]);\n  }\n}\n\n/**\n * Attempt to create an observer instance for a value,\n * returns the new observer if successfully observed,\n * or the existing observer if the value already has one.\n */\nfunction observe (value, asRootData) {\n  if (!isObject(value)) {\n    return\n  }\n  var ob;\n  if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) {\n    ob = value.__ob__;\n  } else if (\n    observerState.shouldConvert &&\n    !isServerRendering() &&\n    (Array.isArray(value) || isPlainObject(value)) &&\n    Object.isExtensible(value) &&\n    !value._isVue\n  ) {\n    ob = new Observer(value);\n  }\n  if (asRootData && ob) {\n    ob.vmCount++;\n  }\n  return ob\n}\n\n/**\n * Define a reactive property on an Object.\n */\nfunction defineReactive$$1 (\n  obj,\n  key,\n  val,\n  customSetter,\n  shallow\n) {\n  var dep = new Dep();\n\n  var property = Object.getOwnPropertyDescriptor(obj, key);\n  if (property && property.configurable === false) {\n    return\n  }\n\n  // cater for pre-defined getter/setters\n  var getter = property && property.get;\n  var setter = property && property.set;\n\n  var childOb = !shallow && observe(val);\n  Object.defineProperty(obj, key, {\n    enumerable: true,\n    configurable: true,\n    get: function reactiveGetter () {\n      var value = getter ? getter.call(obj) : val;\n      if (Dep.target) {\n        dep.depend();\n        if (childOb) {\n          childOb.dep.depend();\n        }\n        if (Array.isArray(value)) {\n          dependArray(value);\n        }\n      }\n      return value\n    },\n    set: function reactiveSetter (newVal) {\n      var value = getter ? getter.call(obj) : val;\n      /* eslint-disable no-self-compare */\n      if (newVal === value || (newVal !== newVal && value !== value)) {\n        return\n      }\n      /* eslint-enable no-self-compare */\n      if (process.env.NODE_ENV !== 'production' && customSetter) {\n        customSetter();\n      }\n      if (setter) {\n        setter.call(obj, newVal);\n      } else {\n        val = newVal;\n      }\n      childOb = !shallow && observe(newVal);\n      dep.notify();\n    }\n  });\n}\n\n/**\n * Set a property on an object. Adds the new property and\n * triggers change notification if the property doesn't\n * already exist.\n */\nfunction set (target, key, val) {\n  if (Array.isArray(target) && isValidArrayIndex(key)) {\n    target.length = Math.max(target.length, key);\n    target.splice(key, 1, val);\n    return val\n  }\n  if (hasOwn(target, key)) {\n    target[key] = val;\n    return val\n  }\n  var ob = (target).__ob__;\n  if (target._isVue || (ob && ob.vmCount)) {\n    process.env.NODE_ENV !== 'production' && warn$1(\n      'Avoid adding reactive properties to a Vue instance or its root $data ' +\n      'at runtime - declare it upfront in the data option.'\n    );\n    return val\n  }\n  if (!ob) {\n    target[key] = val;\n    return val\n  }\n  defineReactive$$1(ob.value, key, val);\n  ob.dep.notify();\n  return val\n}\n\n/**\n * Delete a property and trigger change if necessary.\n */\n\n\n/**\n * Collect dependencies on array elements when the array is touched, since\n * we cannot intercept array element access like property getters.\n */\nfunction dependArray (value) {\n  for (var e = (void 0), i = 0, l = value.length; i < l; i++) {\n    e = value[i];\n    e && e.__ob__ && e.__ob__.dep.depend();\n    if (Array.isArray(e)) {\n      dependArray(e);\n    }\n  }\n}\n\n/*  */\n\n/**\n * Option overwriting strategies are functions that handle\n * how to merge a parent option value and a child option\n * value into the final value.\n */\nvar strats = config.optionMergeStrategies;\n\n/**\n * Options with restrictions\n */\nif (process.env.NODE_ENV !== 'production') {\n  strats.el = strats.propsData = function (parent, child, vm, key) {\n    if (!vm) {\n      warn$1(\n        \"option \\\"\" + key + \"\\\" can only be used during instance \" +\n        'creation with the `new` keyword.'\n      );\n    }\n    return defaultStrat(parent, child)\n  };\n}\n\n/**\n * Helper that recursively merges two data objects together.\n */\nfunction mergeData (to, from) {\n  if (!from) { return to }\n  var key, toVal, fromVal;\n  var keys = Object.keys(from);\n  for (var i = 0; i < keys.length; i++) {\n    key = keys[i];\n    toVal = to[key];\n    fromVal = from[key];\n    if (!hasOwn(to, key)) {\n      set(to, key, fromVal);\n    } else if (isPlainObject(toVal) && isPlainObject(fromVal)) {\n      mergeData(toVal, fromVal);\n    }\n  }\n  return to\n}\n\n/**\n * Data\n */\nfunction mergeDataOrFn (\n  parentVal,\n  childVal,\n  vm\n) {\n  if (!vm) {\n    // in a Vue.extend merge, both should be functions\n    if (!childVal) {\n      return parentVal\n    }\n    if (!parentVal) {\n      return childVal\n    }\n    // when parentVal & childVal are both present,\n    // we need to return a function that returns the\n    // merged result of both functions... no need to\n    // check if parentVal is a function here because\n    // it has to be a function to pass previous merges.\n    return function mergedDataFn () {\n      return mergeData(\n        typeof childVal === 'function' ? childVal.call(this) : childVal,\n        parentVal.call(this)\n      )\n    }\n  } else if (parentVal || childVal) {\n    return function mergedInstanceDataFn () {\n      // instance merge\n      var instanceData = typeof childVal === 'function'\n        ? childVal.call(vm)\n        : childVal;\n      var defaultData = typeof parentVal === 'function'\n        ? parentVal.call(vm)\n        : undefined;\n      if (instanceData) {\n        return mergeData(instanceData, defaultData)\n      } else {\n        return defaultData\n      }\n    }\n  }\n}\n\nstrats.data = function (\n  parentVal,\n  childVal,\n  vm\n) {\n  if (!vm) {\n    if (childVal && typeof childVal !== 'function') {\n      process.env.NODE_ENV !== 'production' && warn$1(\n        'The \"data\" option should be a function ' +\n        'that returns a per-instance value in component ' +\n        'definitions.',\n        vm\n      );\n\n      return parentVal\n    }\n    return mergeDataOrFn.call(this, parentVal, childVal)\n  }\n\n  return mergeDataOrFn(parentVal, childVal, vm)\n};\n\n/**\n * Hooks and props are merged as arrays.\n */\nfunction mergeHook (\n  parentVal,\n  childVal\n) {\n  return childVal\n    ? parentVal\n      ? parentVal.concat(childVal)\n      : Array.isArray(childVal)\n        ? childVal\n        : [childVal]\n    : parentVal\n}\n\nLIFECYCLE_HOOKS.forEach(function (hook) {\n  strats[hook] = mergeHook;\n});\n\n/**\n * Assets\n *\n * When a vm is present (instance creation), we need to do\n * a three-way merge between constructor options, instance\n * options and parent options.\n */\nfunction mergeAssets (parentVal, childVal) {\n  var res = Object.create(parentVal || null);\n  return childVal\n    ? extend(res, childVal)\n    : res\n}\n\nASSET_TYPES.forEach(function (type) {\n  strats[type + 's'] = mergeAssets;\n});\n\n/**\n * Watchers.\n *\n * Watchers hashes should not overwrite one\n * another, so we merge them as arrays.\n */\nstrats.watch = function (parentVal, childVal) {\n  // work around Firefox's Object.prototype.watch...\n  if (parentVal === nativeWatch) { parentVal = undefined; }\n  if (childVal === nativeWatch) { childVal = undefined; }\n  /* istanbul ignore if */\n  if (!childVal) { return Object.create(parentVal || null) }\n  if (!parentVal) { return childVal }\n  var ret = {};\n  extend(ret, parentVal);\n  for (var key in childVal) {\n    var parent = ret[key];\n    var child = childVal[key];\n    if (parent && !Array.isArray(parent)) {\n      parent = [parent];\n    }\n    ret[key] = parent\n      ? parent.concat(child)\n      : Array.isArray(child) ? child : [child];\n  }\n  return ret\n};\n\n/**\n * Other object hashes.\n */\nstrats.props =\nstrats.methods =\nstrats.inject =\nstrats.computed = function (parentVal, childVal) {\n  if (!childVal) { return Object.create(parentVal || null) }\n  if (!parentVal) { return childVal }\n  var ret = Object.create(null);\n  extend(ret, parentVal);\n  extend(ret, childVal);\n  return ret\n};\nstrats.provide = mergeDataOrFn;\n\n/**\n * Default strategy.\n */\nvar defaultStrat = function (parentVal, childVal) {\n  return childVal === undefined\n    ? parentVal\n    : childVal\n};\n\n/**\n * Merge two option objects into a new one.\n * Core utility used in both instantiation and inheritance.\n */\n\n\n/**\n * Resolve an asset.\n * This function is used because child instances need access\n * to assets defined in its ancestor chain.\n */\n\n/*  */\n\n/*  */\n\n/*  */\n\nfunction on (el, dir) {\n  if (process.env.NODE_ENV !== 'production' && dir.modifiers) {\n    warn$1(\"v-on without argument does not support modifiers.\");\n  }\n  el.wrapListeners = function (code) { return (\"_g(\" + code + \",\" + (dir.value) + \")\"); };\n}\n\n/*  */\n\nfunction bind$1 (el, dir) {\n  el.wrapData = function (code) {\n    return (\"_b(\" + code + \",'\" + (el.tag) + \"',\" + (dir.value) + \",\" + (dir.modifiers && dir.modifiers.prop ? 'true' : 'false') + (dir.modifiers && dir.modifiers.sync ? ',true' : '') + \")\")\n  };\n}\n\n/*  */\n\nvar baseDirectives = {\n  on: on,\n  bind: bind$1,\n  cloak: noop\n};\n\n/*  */\n\nvar CodegenState = function CodegenState (options) {\n  this.options = options;\n  this.warn = options.warn || baseWarn;\n  this.transforms = pluckModuleFunction(options.modules, 'transformCode');\n  this.dataGenFns = pluckModuleFunction(options.modules, 'genData');\n  this.directives = extend(extend({}, baseDirectives), options.directives);\n  var isReservedTag = options.isReservedTag || no;\n  this.maybeComponent = function (el) { return !isReservedTag(el.tag); };\n  this.onceId = 0;\n  this.staticRenderFns = [];\n};\n\n\n\nfunction generate (\n  ast,\n  options\n) {\n  var state = new CodegenState(options);\n  var code = ast ? genElement(ast, state) : '_c(\"div\")';\n  return {\n    render: (\"with(this){return \" + code + \"}\"),\n    staticRenderFns: state.staticRenderFns\n  }\n}\n\nfunction genElement (el, state) {\n  if (el.staticRoot && !el.staticProcessed) {\n    return genStatic(el, state)\n  } else if (el.once && !el.onceProcessed) {\n    return genOnce(el, state)\n  } else if (el.for && !el.forProcessed) {\n    return genFor(el, state)\n  } else if (el.if && !el.ifProcessed) {\n    return genIf(el, state)\n  } else if (el.tag === 'template' && !el.slotTarget) {\n    return genChildren(el, state) || 'void 0'\n  } else if (el.tag === 'slot') {\n    return genSlot(el, state)\n  } else {\n    // component or element\n    var code;\n    if (el.component) {\n      code = genComponent(el.component, el, state);\n    } else {\n      var data = el.plain ? undefined : genData(el, state);\n\n      var children = el.inlineTemplate ? null : genChildren(el, state, true);\n      code = \"_c('\" + (el.tag) + \"'\" + (data ? (\",\" + data) : '') + (children ? (\",\" + children) : '') + \")\";\n    }\n    // module transforms\n    for (var i = 0; i < state.transforms.length; i++) {\n      code = state.transforms[i](el, code);\n    }\n    return code\n  }\n}\n\n// hoist static sub-trees out\nfunction genStatic (el, state) {\n  el.staticProcessed = true;\n  state.staticRenderFns.push((\"with(this){return \" + (genElement(el, state)) + \"}\"));\n  return (\"_m(\" + (state.staticRenderFns.length - 1) + (el.staticInFor ? ',true' : '') + \")\")\n}\n\n// v-once\nfunction genOnce (el, state) {\n  el.onceProcessed = true;\n  if (el.if && !el.ifProcessed) {\n    return genIf(el, state)\n  } else if (el.staticInFor) {\n    var key = '';\n    var parent = el.parent;\n    while (parent) {\n      if (parent.for) {\n        key = parent.key;\n        break\n      }\n      parent = parent.parent;\n    }\n    if (!key) {\n      process.env.NODE_ENV !== 'production' && state.warn(\n        \"v-once can only be used inside v-for that is keyed. \"\n      );\n      return genElement(el, state)\n    }\n    return (\"_o(\" + (genElement(el, state)) + \",\" + (state.onceId++) + (key ? (\",\" + key) : \"\") + \")\")\n  } else {\n    return genStatic(el, state)\n  }\n}\n\nfunction genIf (\n  el,\n  state,\n  altGen,\n  altEmpty\n) {\n  el.ifProcessed = true; // avoid recursion\n  return genIfConditions(el.ifConditions.slice(), state, altGen, altEmpty)\n}\n\nfunction genIfConditions (\n  conditions,\n  state,\n  altGen,\n  altEmpty\n) {\n  if (!conditions.length) {\n    return altEmpty || '_e()'\n  }\n\n  var condition = conditions.shift();\n  if (condition.exp) {\n    return (\"(\" + (condition.exp) + \")?\" + (genTernaryExp(condition.block)) + \":\" + (genIfConditions(conditions, state, altGen, altEmpty)))\n  } else {\n    return (\"\" + (genTernaryExp(condition.block)))\n  }\n\n  // v-if with v-once should generate code like (a)?_m(0):_m(1)\n  function genTernaryExp (el) {\n    return altGen\n      ? altGen(el, state)\n      : el.once\n        ? genOnce(el, state)\n        : genElement(el, state)\n  }\n}\n\nfunction genFor (\n  el,\n  state,\n  altGen,\n  altHelper\n) {\n  var exp = el.for;\n  var alias = el.alias;\n  var iterator1 = el.iterator1 ? (\",\" + (el.iterator1)) : '';\n  var iterator2 = el.iterator2 ? (\",\" + (el.iterator2)) : '';\n\n  if (process.env.NODE_ENV !== 'production' &&\n    state.maybeComponent(el) &&\n    el.tag !== 'slot' &&\n    el.tag !== 'template' &&\n    !el.key\n  ) {\n    state.warn(\n      \"<\" + (el.tag) + \" v-for=\\\"\" + alias + \" in \" + exp + \"\\\">: component lists rendered with \" +\n      \"v-for should have explicit keys. \" +\n      \"See https://vuejs.org/guide/list.html#key for more info.\",\n      true /* tip */\n    );\n  }\n\n  el.forProcessed = true; // avoid recursion\n  return (altHelper || '_l') + \"((\" + exp + \"),\" +\n    \"function(\" + alias + iterator1 + iterator2 + \"){\" +\n      \"return \" + ((altGen || genElement)(el, state)) +\n    '})'\n}\n\nfunction genData (el, state) {\n  var data = '{';\n\n  // directives first.\n  // directives may mutate the el's other properties before they are generated.\n  var dirs = genDirectives(el, state);\n  if (dirs) { data += dirs + ','; }\n\n  // key\n  if (el.key) {\n    data += \"key:\" + (el.key) + \",\";\n  }\n  // ref\n  if (el.ref) {\n    data += \"ref:\" + (el.ref) + \",\";\n  }\n  if (el.refInFor) {\n    data += \"refInFor:true,\";\n  }\n  // pre\n  if (el.pre) {\n    data += \"pre:true,\";\n  }\n  // record original tag name for components using \"is\" attribute\n  if (el.component) {\n    data += \"tag:\\\"\" + (el.tag) + \"\\\",\";\n  }\n  // module data generation functions\n  for (var i = 0; i < state.dataGenFns.length; i++) {\n    data += state.dataGenFns[i](el);\n  }\n  // attributes\n  if (el.attrs) {\n    data += \"attrs:{\" + (genProps(el.attrs)) + \"},\";\n  }\n  // DOM props\n  if (el.props) {\n    data += \"domProps:{\" + (genProps(el.props)) + \"},\";\n  }\n  // event handlers\n  if (el.events) {\n    data += (genHandlers(el.events, false, state.warn)) + \",\";\n  }\n  if (el.nativeEvents) {\n    data += (genHandlers(el.nativeEvents, true, state.warn)) + \",\";\n  }\n  // slot target\n  if (el.slotTarget) {\n    data += \"slot:\" + (el.slotTarget) + \",\";\n  }\n  // scoped slots\n  if (el.scopedSlots) {\n    data += (genScopedSlots(el.scopedSlots, state)) + \",\";\n  }\n  // component v-model\n  if (el.model) {\n    data += \"model:{value:\" + (el.model.value) + \",callback:\" + (el.model.callback) + \",expression:\" + (el.model.expression) + \"},\";\n  }\n  // inline-template\n  if (el.inlineTemplate) {\n    var inlineTemplate = genInlineTemplate(el, state);\n    if (inlineTemplate) {\n      data += inlineTemplate + \",\";\n    }\n  }\n  data = data.replace(/,$/, '') + '}';\n  // v-bind data wrap\n  if (el.wrapData) {\n    data = el.wrapData(data);\n  }\n  // v-on data wrap\n  if (el.wrapListeners) {\n    data = el.wrapListeners(data);\n  }\n  return data\n}\n\nfunction genDirectives (el, state) {\n  var dirs = el.directives;\n  if (!dirs) { return }\n  var res = 'directives:[';\n  var hasRuntime = false;\n  var i, l, dir, needRuntime;\n  for (i = 0, l = dirs.length; i < l; i++) {\n    dir = dirs[i];\n    needRuntime = true;\n    var gen = state.directives[dir.name];\n    if (gen) {\n      // compile-time directive that manipulates AST.\n      // returns true if it also needs a runtime counterpart.\n      needRuntime = !!gen(el, dir, state.warn);\n    }\n    if (needRuntime) {\n      hasRuntime = true;\n      res += \"{name:\\\"\" + (dir.name) + \"\\\",rawName:\\\"\" + (dir.rawName) + \"\\\"\" + (dir.value ? (\",value:(\" + (dir.value) + \"),expression:\" + (JSON.stringify(dir.value))) : '') + (dir.arg ? (\",arg:\\\"\" + (dir.arg) + \"\\\"\") : '') + (dir.modifiers ? (\",modifiers:\" + (JSON.stringify(dir.modifiers))) : '') + \"},\";\n    }\n  }\n  if (hasRuntime) {\n    return res.slice(0, -1) + ']'\n  }\n}\n\nfunction genInlineTemplate (el, state) {\n  var ast = el.children[0];\n  if (process.env.NODE_ENV !== 'production' && (\n    el.children.length > 1 || ast.type !== 1\n  )) {\n    state.warn('Inline-template components must have exactly one child element.');\n  }\n  if (ast.type === 1) {\n    var inlineRenderFns = generate(ast, state.options);\n    return (\"inlineTemplate:{render:function(){\" + (inlineRenderFns.render) + \"},staticRenderFns:[\" + (inlineRenderFns.staticRenderFns.map(function (code) { return (\"function(){\" + code + \"}\"); }).join(',')) + \"]}\")\n  }\n}\n\nfunction genScopedSlots (\n  slots,\n  state\n) {\n  return (\"scopedSlots:_u([\" + (Object.keys(slots).map(function (key) {\n      return genScopedSlot(key, slots[key], state)\n    }).join(',')) + \"])\")\n}\n\nfunction genScopedSlot (\n  key,\n  el,\n  state\n) {\n  if (el.for && !el.forProcessed) {\n    return genForScopedSlot(key, el, state)\n  }\n  return \"{key:\" + key + \",fn:function(\" + (String(el.attrsMap.scope)) + \"){\" +\n    \"return \" + (el.tag === 'template'\n      ? genChildren(el, state) || 'void 0'\n      : genElement(el, state)) + \"}}\"\n}\n\nfunction genForScopedSlot (\n  key,\n  el,\n  state\n) {\n  var exp = el.for;\n  var alias = el.alias;\n  var iterator1 = el.iterator1 ? (\",\" + (el.iterator1)) : '';\n  var iterator2 = el.iterator2 ? (\",\" + (el.iterator2)) : '';\n  el.forProcessed = true; // avoid recursion\n  return \"_l((\" + exp + \"),\" +\n    \"function(\" + alias + iterator1 + iterator2 + \"){\" +\n      \"return \" + (genScopedSlot(key, el, state)) +\n    '})'\n}\n\nfunction genChildren (\n  el,\n  state,\n  checkSkip,\n  altGenElement,\n  altGenNode\n) {\n  var children = el.children;\n  if (children.length) {\n    var el$1 = children[0];\n    // optimize single v-for\n    if (children.length === 1 &&\n      el$1.for &&\n      el$1.tag !== 'template' &&\n      el$1.tag !== 'slot'\n    ) {\n      return (altGenElement || genElement)(el$1, state)\n    }\n    var normalizationType = checkSkip\n      ? getNormalizationType(children, state.maybeComponent)\n      : 0;\n    var gen = altGenNode || genNode;\n    return (\"[\" + (children.map(function (c) { return gen(c, state); }).join(',')) + \"]\" + (normalizationType ? (\",\" + normalizationType) : ''))\n  }\n}\n\n// determine the normalization needed for the children array.\n// 0: no normalization needed\n// 1: simple normalization needed (possible 1-level deep nested array)\n// 2: full normalization needed\nfunction getNormalizationType (\n  children,\n  maybeComponent\n) {\n  var res = 0;\n  for (var i = 0; i < children.length; i++) {\n    var el = children[i];\n    if (el.type !== 1) {\n      continue\n    }\n    if (needsNormalization(el) ||\n        (el.ifConditions && el.ifConditions.some(function (c) { return needsNormalization(c.block); }))) {\n      res = 2;\n      break\n    }\n    if (maybeComponent(el) ||\n        (el.ifConditions && el.ifConditions.some(function (c) { return maybeComponent(c.block); }))) {\n      res = 1;\n    }\n  }\n  return res\n}\n\nfunction needsNormalization (el) {\n  return el.for !== undefined || el.tag === 'template' || el.tag === 'slot'\n}\n\nfunction genNode (node, state) {\n  if (node.type === 1) {\n    return genElement(node, state)\n  } if (node.type === 3 && node.isComment) {\n    return genComment(node)\n  } else {\n    return genText(node)\n  }\n}\n\nfunction genText (text) {\n  return (\"_v(\" + (text.type === 2\n    ? text.expression // no need for () because already wrapped in _s()\n    : transformSpecialNewlines(JSON.stringify(text.text))) + \")\")\n}\n\nfunction genComment (comment) {\n  return (\"_e('\" + (comment.text) + \"')\")\n}\n\nfunction genSlot (el, state) {\n  var slotName = el.slotName || '\"default\"';\n  var children = genChildren(el, state);\n  var res = \"_t(\" + slotName + (children ? (\",\" + children) : '');\n  var attrs = el.attrs && (\"{\" + (el.attrs.map(function (a) { return ((camelize(a.name)) + \":\" + (a.value)); }).join(',')) + \"}\");\n  var bind$$1 = el.attrsMap['v-bind'];\n  if ((attrs || bind$$1) && !children) {\n    res += \",null\";\n  }\n  if (attrs) {\n    res += \",\" + attrs;\n  }\n  if (bind$$1) {\n    res += (attrs ? '' : ',null') + \",\" + bind$$1;\n  }\n  return res + ')'\n}\n\n// componentName is el.component, take it as argument to shun flow's pessimistic refinement\nfunction genComponent (\n  componentName,\n  el,\n  state\n) {\n  var children = el.inlineTemplate ? null : genChildren(el, state, true);\n  return (\"_c(\" + componentName + \",\" + (genData(el, state)) + (children ? (\",\" + children) : '') + \")\")\n}\n\nfunction genProps (props) {\n  var res = '';\n  for (var i = 0; i < props.length; i++) {\n    var prop = props[i];\n    res += \"\\\"\" + (prop.name) + \"\\\":\" + (transformSpecialNewlines(prop.value)) + \",\";\n  }\n  return res.slice(0, -1)\n}\n\n// #3895, #4268\nfunction transformSpecialNewlines (text) {\n  return text\n    .replace(/\\u2028/g, '\\\\u2028')\n    .replace(/\\u2029/g, '\\\\u2029')\n}\n\n/*  */\n\n// these keywords should not appear inside expressions, but operators like\n// typeof, instanceof and in are allowed\nvar prohibitedKeywordRE = new RegExp('\\\\b' + (\n  'do,if,for,let,new,try,var,case,else,with,await,break,catch,class,const,' +\n  'super,throw,while,yield,delete,export,import,return,switch,default,' +\n  'extends,finally,continue,debugger,function,arguments'\n).split(',').join('\\\\b|\\\\b') + '\\\\b');\n\n// these unary operators should not be used as property/method names\nvar unaryOperatorsRE = new RegExp('\\\\b' + (\n  'delete,typeof,void'\n).split(',').join('\\\\s*\\\\([^\\\\)]*\\\\)|\\\\b') + '\\\\s*\\\\([^\\\\)]*\\\\)');\n\n// check valid identifier for v-for\nvar identRE = /[A-Za-z_$][\\w$]*/;\n\n// strip strings in expressions\nvar stripStringRE = /'(?:[^'\\\\]|\\\\.)*'|\"(?:[^\"\\\\]|\\\\.)*\"|`(?:[^`\\\\]|\\\\.)*\\$\\{|\\}(?:[^`\\\\]|\\\\.)*`|`(?:[^`\\\\]|\\\\.)*`/g;\n\n// detect problematic expressions in a template\nfunction detectErrors (ast) {\n  var errors = [];\n  if (ast) {\n    checkNode(ast, errors);\n  }\n  return errors\n}\n\nfunction checkNode (node, errors) {\n  if (node.type === 1) {\n    for (var name in node.attrsMap) {\n      if (dirRE.test(name)) {\n        var value = node.attrsMap[name];\n        if (value) {\n          if (name === 'v-for') {\n            checkFor(node, (\"v-for=\\\"\" + value + \"\\\"\"), errors);\n          } else if (onRE.test(name)) {\n            checkEvent(value, (name + \"=\\\"\" + value + \"\\\"\"), errors);\n          } else {\n            checkExpression(value, (name + \"=\\\"\" + value + \"\\\"\"), errors);\n          }\n        }\n      }\n    }\n    if (node.children) {\n      for (var i = 0; i < node.children.length; i++) {\n        checkNode(node.children[i], errors);\n      }\n    }\n  } else if (node.type === 2) {\n    checkExpression(node.expression, node.text, errors);\n  }\n}\n\nfunction checkEvent (exp, text, errors) {\n  var stipped = exp.replace(stripStringRE, '');\n  var keywordMatch = stipped.match(unaryOperatorsRE);\n  if (keywordMatch && stipped.charAt(keywordMatch.index - 1) !== '$') {\n    errors.push(\n      \"avoid using JavaScript unary operator as property name: \" +\n      \"\\\"\" + (keywordMatch[0]) + \"\\\" in expression \" + (text.trim())\n    );\n  }\n  checkExpression(exp, text, errors);\n}\n\nfunction checkFor (node, text, errors) {\n  checkExpression(node.for || '', text, errors);\n  checkIdentifier(node.alias, 'v-for alias', text, errors);\n  checkIdentifier(node.iterator1, 'v-for iterator', text, errors);\n  checkIdentifier(node.iterator2, 'v-for iterator', text, errors);\n}\n\nfunction checkIdentifier (ident, type, text, errors) {\n  if (typeof ident === 'string' && !identRE.test(ident)) {\n    errors.push((\"invalid \" + type + \" \\\"\" + ident + \"\\\" in expression: \" + (text.trim())));\n  }\n}\n\nfunction checkExpression (exp, text, errors) {\n  try {\n    new Function((\"return \" + exp));\n  } catch (e) {\n    var keywordMatch = exp.replace(stripStringRE, '').match(prohibitedKeywordRE);\n    if (keywordMatch) {\n      errors.push(\n        \"avoid using JavaScript keyword as property name: \" +\n        \"\\\"\" + (keywordMatch[0]) + \"\\\" in expression \" + (text.trim())\n      );\n    } else {\n      errors.push((\"invalid expression: \" + (text.trim())));\n    }\n  }\n}\n\n/*  */\n\nfunction createFunction (code, errors) {\n  try {\n    return new Function(code)\n  } catch (err) {\n    errors.push({ err: err, code: code });\n    return noop\n  }\n}\n\nfunction createCompileToFunctionFn (compile) {\n  var cache = Object.create(null);\n\n  return function compileToFunctions (\n    template,\n    options,\n    vm\n  ) {\n    options = options || {};\n\n    /* istanbul ignore if */\n    if (process.env.NODE_ENV !== 'production') {\n      // detect possible CSP restriction\n      try {\n        new Function('return 1');\n      } catch (e) {\n        if (e.toString().match(/unsafe-eval|CSP/)) {\n          warn$1(\n            'It seems you are using the standalone build of Vue.js in an ' +\n            'environment with Content Security Policy that prohibits unsafe-eval. ' +\n            'The template compiler cannot work in this environment. Consider ' +\n            'relaxing the policy to allow unsafe-eval or pre-compiling your ' +\n            'templates into render functions.'\n          );\n        }\n      }\n    }\n\n    // check cache\n    var key = options.delimiters\n      ? String(options.delimiters) + template\n      : template;\n    if (cache[key]) {\n      return cache[key]\n    }\n\n    // compile\n    var compiled = compile(template, options);\n\n    // check compilation errors/tips\n    if (process.env.NODE_ENV !== 'production') {\n      if (compiled.errors && compiled.errors.length) {\n        warn$1(\n          \"Error compiling template:\\n\\n\" + template + \"\\n\\n\" +\n          compiled.errors.map(function (e) { return (\"- \" + e); }).join('\\n') + '\\n',\n          vm\n        );\n      }\n      if (compiled.tips && compiled.tips.length) {\n        compiled.tips.forEach(function (msg) { return tip(msg, vm); });\n      }\n    }\n\n    // turn code into functions\n    var res = {};\n    var fnGenErrors = [];\n    res.render = createFunction(compiled.render, fnGenErrors);\n    res.staticRenderFns = compiled.staticRenderFns.map(function (code) {\n      return createFunction(code, fnGenErrors)\n    });\n\n    // check function generation errors.\n    // this should only happen if there is a bug in the compiler itself.\n    // mostly for codegen development use\n    /* istanbul ignore if */\n    if (process.env.NODE_ENV !== 'production') {\n      if ((!compiled.errors || !compiled.errors.length) && fnGenErrors.length) {\n        warn$1(\n          \"Failed to generate render function:\\n\\n\" +\n          fnGenErrors.map(function (ref) {\n            var err = ref.err;\n            var code = ref.code;\n\n            return ((err.toString()) + \" in\\n\\n\" + code + \"\\n\");\n        }).join('\\n'),\n          vm\n        );\n      }\n    }\n\n    return (cache[key] = res)\n  }\n}\n\n/*  */\n\nfunction createCompilerCreator (baseCompile) {\n  return function createCompiler (baseOptions) {\n    function compile (\n      template,\n      options\n    ) {\n      var finalOptions = Object.create(baseOptions);\n      var errors = [];\n      var tips = [];\n      finalOptions.warn = function (msg, tip) {\n        (tip ? tips : errors).push(msg);\n      };\n\n      if (options) {\n        // merge custom modules\n        if (options.modules) {\n          finalOptions.modules =\n            (baseOptions.modules || []).concat(options.modules);\n        }\n        // merge custom directives\n        if (options.directives) {\n          finalOptions.directives = extend(\n            Object.create(baseOptions.directives),\n            options.directives\n          );\n        }\n        // copy other options\n        for (var key in options) {\n          if (key !== 'modules' && key !== 'directives') {\n            finalOptions[key] = options[key];\n          }\n        }\n      }\n\n      var compiled = baseCompile(template, finalOptions);\n      if (process.env.NODE_ENV !== 'production') {\n        errors.push.apply(errors, detectErrors(compiled.ast));\n      }\n      compiled.errors = errors;\n      compiled.tips = tips;\n      return compiled\n    }\n\n    return {\n      compile: compile,\n      compileToFunctions: createCompileToFunctionFn(compile)\n    }\n  }\n}\n\n/*  */\n\n// `createCompilerCreator` allows creating compilers that use alternative\n// parser/optimizer/codegen, e.g the SSR optimizing compiler.\n// Here we just export a default compiler using the default parts.\nvar createCompiler = createCompilerCreator(function baseCompile (\n  template,\n  options\n) {\n  var ast = parse(template.trim(), options);\n  optimize(ast, options);\n  var code = generate(ast, options);\n  return {\n    ast: ast,\n    render: code.render,\n    staticRenderFns: code.staticRenderFns\n  }\n});\n\n/*  */\n\nfunction transformNode (el, options) {\n  var warn = options.warn || baseWarn;\n  var staticClass = getAndRemoveAttr(el, 'class');\n  var ref = parseStaticClass(staticClass, options);\n  var dynamic = ref.dynamic;\n  var classResult = ref.classResult;\n  if (process.env.NODE_ENV !== 'production' && dynamic && staticClass) {\n    warn(\n      \"class=\\\"\" + staticClass + \"\\\": \" +\n      'Interpolation inside attributes has been deprecated. ' +\n      'Use v-bind or the colon shorthand instead.'\n    );\n  }\n  if (!dynamic && classResult) {\n    el.staticClass = classResult;\n  }\n  var classBinding = getBindingAttr(el, 'class', false /* getStatic */);\n  if (classBinding) {\n    el.classBinding = classBinding;\n  } else if (dynamic) {\n    el.classBinding = classResult;\n  }\n}\n\nfunction genData$1 (el) {\n  var data = '';\n  if (el.staticClass) {\n    data += \"staticClass:\" + (el.staticClass) + \",\";\n  }\n  if (el.classBinding) {\n    data += \"class:\" + (el.classBinding) + \",\";\n  }\n  return data\n}\n\nfunction parseStaticClass (staticClass, options) {\n  // \"a b c\" -> [\"a\", \"b\", \"c\"] => staticClass: [\"a\", \"b\", \"c\"]\n  // \"a {{x}} c\" -> [\"a\", x, \"c\"] => classBinding: '[\"a\", x, \"c\"]'\n  var dynamic = false;\n  var classResult = '';\n  if (staticClass) {\n    var classList = staticClass.trim().split(' ').map(function (name) {\n      var result = parseText(name, options.delimiters);\n      if (result) {\n        dynamic = true;\n        return result\n      }\n      return JSON.stringify(name)\n    });\n    if (classList.length) {\n      classResult = '[' + classList.join(',') + ']';\n    }\n  }\n  return { dynamic: dynamic, classResult: classResult }\n}\n\nvar klass = {\n  staticKeys: ['staticClass'],\n  transformNode: transformNode,\n  genData: genData$1\n};\n\n/*  */\n\nvar normalize = cached(camelize);\n\nfunction transformNode$1 (el, options) {\n  var warn = options.warn || baseWarn;\n  var staticStyle = getAndRemoveAttr(el, 'style');\n  var ref = parseStaticStyle(staticStyle, options);\n  var dynamic = ref.dynamic;\n  var styleResult = ref.styleResult;\n  if (process.env.NODE_ENV !== 'production' && dynamic) {\n    warn(\n      \"style=\\\"\" + (String(staticStyle)) + \"\\\": \" +\n      'Interpolation inside attributes has been deprecated. ' +\n      'Use v-bind or the colon shorthand instead.'\n    );\n  }\n  if (!dynamic && styleResult) {\n    el.staticStyle = styleResult;\n  }\n  var styleBinding = getBindingAttr(el, 'style', false /* getStatic */);\n  if (styleBinding) {\n    el.styleBinding = styleBinding;\n  } else if (dynamic) {\n    el.styleBinding = styleResult;\n  }\n}\n\nfunction genData$2 (el) {\n  var data = '';\n  if (el.staticStyle) {\n    data += \"staticStyle:\" + (el.staticStyle) + \",\";\n  }\n  if (el.styleBinding) {\n    data += \"style:\" + (el.styleBinding) + \",\";\n  }\n  return data\n}\n\nfunction parseStaticStyle (staticStyle, options) {\n  // \"width: 200px; height: 200px;\" -> {width: 200, height: 200}\n  // \"width: 200px; height: {{y}}\" -> {width: 200, height: y}\n  var dynamic = false;\n  var styleResult = '';\n  if (staticStyle) {\n    var styleList = staticStyle.trim().split(';').map(function (style) {\n      var result = style.trim().split(':');\n      if (result.length !== 2) {\n        return\n      }\n      var key = normalize(result[0].trim());\n      var value = result[1].trim();\n      var dynamicValue = parseText(value, options.delimiters);\n      if (dynamicValue) {\n        dynamic = true;\n        return key + ':' + dynamicValue\n      }\n      return key + ':' + JSON.stringify(value)\n    }).filter(function (result) { return result; });\n    if (styleList.length) {\n      styleResult = '{' + styleList.join(',') + '}';\n    }\n  }\n  return { dynamic: dynamic, styleResult: styleResult }\n}\n\nvar style = {\n  staticKeys: ['staticStyle'],\n  transformNode: transformNode$1,\n  genData: genData$2\n};\n\n/*  */\n\nvar normalize$1 = cached(camelize);\n\nfunction normalizeKeyName (str) {\n  if (str.match(/^v\\-/)) {\n    return str.replace(/(v-[a-z\\-]+\\:)([a-z\\-]+)$/i, function ($, directive, prop) {\n      return directive + normalize$1(prop)\n    })\n  }\n  return normalize$1(str)\n}\n\nfunction transformNode$2 (el, options) {\n  if (Array.isArray(el.attrsList)) {\n    el.attrsList.forEach(function (attr) {\n      if (attr.name && attr.name.match(/\\-/)) {\n        var realName = normalizeKeyName(attr.name);\n        if (el.attrsMap) {\n          el.attrsMap[realName] = el.attrsMap[attr.name];\n          delete el.attrsMap[attr.name];\n        }\n        attr.name = realName;\n      }\n    });\n  }\n}\nvar props = {\n  transformNode: transformNode$2\n};\n\n/*  */\n\nfunction preTransformNode (el, options) {\n  if (el.tag === 'cell' && !el.attrsList.some(function (item) { return item.name === 'append'; })) {\n    el.attrsMap.append = 'tree';\n    el.attrsList.push({ name: 'append', value: 'tree' });\n  }\n  if (el.attrsMap.append === 'tree') {\n    el.appendAsTree = true;\n  }\n}\n\nfunction genData$3 (el) {\n  return el.appendAsTree ? \"appendAsTree:true,\" : ''\n}\n\nvar append = {\n  staticKeys: ['appendAsTree'],\n  preTransformNode: preTransformNode,\n  genData: genData$3\n};\n\nvar modules = [\n  klass,\n  style,\n  props,\n  append\n];\n\n/*  */\n\nfunction model (\n  el,\n  dir,\n  _warn\n) {\n  if (el.tag === 'input' || el.tag === 'textarea') {\n    genDefaultModel(el, dir.value, dir.modifiers);\n  } else {\n    genComponentModel(el, dir.value, dir.modifiers);\n  }\n}\n\nfunction genDefaultModel (\n  el,\n  value,\n  modifiers\n) {\n  var ref = modifiers || {};\n  var lazy = ref.lazy;\n  var trim = ref.trim;\n  var number = ref.number;\n  var event = lazy ? 'change' : 'input';\n\n  var valueExpression = \"$event.target.attr.value\" + (trim ? '.trim()' : '');\n  if (number) {\n    valueExpression = \"_n(\" + valueExpression + \")\";\n  }\n\n  var code = genAssignmentCode(value, valueExpression);\n  addAttr(el, 'value', (\"(\" + value + \")\"));\n  addHandler(el, event, code, null, true);\n}\n\nvar directives = {\n  model: model\n};\n\n/* globals renderer */\n\nvar isReservedTag = makeMap(\n  'template,script,style,element,content,slot,link,meta,svg,view,' +\n  'a,div,img,image,text,span,richtext,input,switch,textarea,spinner,select,' +\n  'slider,slider-neighbor,indicator,trisition,trisition-group,canvas,' +\n  'list,cell,header,loading,loading-indicator,refresh,scrollable,scroller,' +\n  'video,web,embed,tabbar,tabheader,datepicker,timepicker,marquee,countdown',\n  true\n);\n\n// Elements that you can, intentionally, leave open (and which close themselves)\n// more flexable than web\nvar canBeLeftOpenTag$1 = makeMap(\n  'web,spinner,switch,video,textarea,canvas,' +\n  'indicator,marquee,countdown',\n  true\n);\n\nvar isUnaryTag$1 = makeMap(\n  'embed,img,image,input,link,meta',\n  true\n);\n\nfunction mustUseProp () { /* console.log('mustUseProp') */ }\nfunction getTagNamespace () { /* console.log('getTagNamespace') */ }\n\n/*  */\n\nvar baseOptions = {\n  modules: modules,\n  directives: directives,\n  isUnaryTag: isUnaryTag$1,\n  mustUseProp: mustUseProp,\n  canBeLeftOpenTag: canBeLeftOpenTag$1,\n  isReservedTag: isReservedTag,\n  getTagNamespace: getTagNamespace,\n  preserveWhitespace: false,\n  staticKeys: genStaticKeys(modules)\n};\n\nvar ref = createCompiler(baseOptions);\nvar compile = ref.compile;\n\nexports.compile = compile;\n"
  },
  {
    "path": "packages/weex-template-compiler/index.js",
    "content": "try {\n  var vueVersion = require('weex-vue-framework').version\n} catch (e) {}\n\nvar packageName = require('./package.json').name\nvar packageVersion = require('./package.json').version\nif (vueVersion && vueVersion !== packageVersion) {\n  throw new Error(\n    '\\n\\nVue packages version mismatch:\\n\\n' +\n    '- vue@' + vueVersion + '\\n' +\n    '- ' + packageName + '@' + packageVersion + '\\n\\n' +\n    'This may cause things to work incorrectly. Make sure to use the same version for both.\\n' +\n    'If you are using weex-vue-loader, re-installing them should bump ' + packageName + ' to the latest.\\n'\n  )\n}\n\nmodule.exports = require('./build')\n"
  },
  {
    "path": "packages/weex-template-compiler/package.json",
    "content": "{\n  \"name\": \"weex-template-compiler\",\n  \"version\": \"2.1.9-weex.1\",\n  \"description\": \"Weex template compiler for Vue 2.0\",\n  \"main\": \"index.js\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/vuejs/vue.git\"\n  },\n  \"keywords\": [\n    \"vue\",\n    \"compiler\"\n  ],\n  \"author\": \"Evan You\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/vuejs/vue/issues\"\n  },\n  \"homepage\": \"https://github.com/vuejs/vue/tree/dev/packages/weex-template-compiler#readme\",\n  \"dependencies\": {\n    \"he\": \"^1.1.0\"\n  }\n}\n"
  },
  {
    "path": "packages/weex-vue-framework/README.md",
    "content": "# weex-vue-framework\n\n> This package is auto-generated. For pull requests please see [src/entries/weex-framework.js](https://github.com/vuejs/vue/blob/dev/src/platforms/weex/framework.js).\n"
  },
  {
    "path": "packages/weex-vue-framework/factory.js",
    "content": "'use strict';\n\nmodule.exports = function weexFactory (exports, renderer) {\n\n/*  */\n\n// these helpers produces better vm code in JS engines due to their\n// explicitness and function inlining\nfunction isUndef (v) {\n  return v === undefined || v === null\n}\n\nfunction isDef (v) {\n  return v !== undefined && v !== null\n}\n\nfunction isTrue (v) {\n  return v === true\n}\n\nfunction isFalse (v) {\n  return v === false\n}\n\n/**\n * Check if value is primitive\n */\nfunction isPrimitive (value) {\n  return typeof value === 'string' || typeof value === 'number'\n}\n\n/**\n * Quick object check - this is primarily used to tell\n * Objects from primitive values when we know the value\n * is a JSON-compliant type.\n */\nfunction isObject (obj) {\n  return obj !== null && typeof obj === 'object'\n}\n\nvar _toString = Object.prototype.toString;\n\n/**\n * Strict object type check. Only returns true\n * for plain JavaScript objects.\n */\nfunction isPlainObject (obj) {\n  return _toString.call(obj) === '[object Object]'\n}\n\nfunction isRegExp (v) {\n  return _toString.call(v) === '[object RegExp]'\n}\n\n/**\n * Check if val is a valid array index.\n */\nfunction isValidArrayIndex (val) {\n  var n = parseFloat(val);\n  return n >= 0 && Math.floor(n) === n && isFinite(val)\n}\n\n/**\n * Convert a value to a string that is actually rendered.\n */\nfunction toString (val) {\n  return val == null\n    ? ''\n    : typeof val === 'object'\n      ? JSON.stringify(val, null, 2)\n      : String(val)\n}\n\n/**\n * Convert a input value to a number for persistence.\n * If the conversion fails, return original string.\n */\nfunction toNumber (val) {\n  var n = parseFloat(val);\n  return isNaN(n) ? val : n\n}\n\n/**\n * Make a map and return a function for checking if a key\n * is in that map.\n */\nfunction makeMap (\n  str,\n  expectsLowerCase\n) {\n  var map = Object.create(null);\n  var list = str.split(',');\n  for (var i = 0; i < list.length; i++) {\n    map[list[i]] = true;\n  }\n  return expectsLowerCase\n    ? function (val) { return map[val.toLowerCase()]; }\n    : function (val) { return map[val]; }\n}\n\n/**\n * Check if a tag is a built-in tag.\n */\nvar isBuiltInTag = makeMap('slot,component', true);\n\n/**\n * Check if a attribute is a reserved attribute.\n */\nvar isReservedAttribute = makeMap('key,ref,slot,is');\n\n/**\n * Remove an item from an array\n */\nfunction remove (arr, item) {\n  if (arr.length) {\n    var index = arr.indexOf(item);\n    if (index > -1) {\n      return arr.splice(index, 1)\n    }\n  }\n}\n\n/**\n * Check whether the object has the property.\n */\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\nfunction hasOwn (obj, key) {\n  return hasOwnProperty.call(obj, key)\n}\n\n/**\n * Create a cached version of a pure function.\n */\nfunction cached (fn) {\n  var cache = Object.create(null);\n  return (function cachedFn (str) {\n    var hit = cache[str];\n    return hit || (cache[str] = fn(str))\n  })\n}\n\n/**\n * Camelize a hyphen-delimited string.\n */\nvar camelizeRE = /-(\\w)/g;\nvar camelize = cached(function (str) {\n  return str.replace(camelizeRE, function (_, c) { return c ? c.toUpperCase() : ''; })\n});\n\n/**\n * Capitalize a string.\n */\nvar capitalize = cached(function (str) {\n  return str.charAt(0).toUpperCase() + str.slice(1)\n});\n\n/**\n * Hyphenate a camelCase string.\n */\nvar hyphenateRE = /([^-])([A-Z])/g;\nvar hyphenate = cached(function (str) {\n  return str\n    .replace(hyphenateRE, '$1-$2')\n    .replace(hyphenateRE, '$1-$2')\n    .toLowerCase()\n});\n\n/**\n * Simple bind, faster than native\n */\nfunction bind (fn, ctx) {\n  function boundFn (a) {\n    var l = arguments.length;\n    return l\n      ? l > 1\n        ? fn.apply(ctx, arguments)\n        : fn.call(ctx, a)\n      : fn.call(ctx)\n  }\n  // record original fn length\n  boundFn._length = fn.length;\n  return boundFn\n}\n\n/**\n * Convert an Array-like object to a real Array.\n */\nfunction toArray (list, start) {\n  start = start || 0;\n  var i = list.length - start;\n  var ret = new Array(i);\n  while (i--) {\n    ret[i] = list[i + start];\n  }\n  return ret\n}\n\n/**\n * Mix properties into target object.\n */\nfunction extend (to, _from) {\n  for (var key in _from) {\n    to[key] = _from[key];\n  }\n  return to\n}\n\n/**\n * Merge an Array of Objects into a single Object.\n */\nfunction toObject (arr) {\n  var res = {};\n  for (var i = 0; i < arr.length; i++) {\n    if (arr[i]) {\n      extend(res, arr[i]);\n    }\n  }\n  return res\n}\n\n/**\n * Perform no operation.\n * Stubbing args to make Flow happy without leaving useless transpiled code\n * with ...rest (https://flow.org/blog/2017/05/07/Strict-Function-Call-Arity/)\n */\nfunction noop (a, b, c) {}\n\n/**\n * Always return false.\n */\nvar no = function (a, b, c) { return false; };\n\n/**\n * Return same value\n */\nvar identity = function (_) { return _; };\n\n/**\n * Generate a static keys string from compiler modules.\n */\n\n\n/**\n * Check if two values are loosely equal - that is,\n * if they are plain objects, do they have the same shape?\n */\nfunction looseEqual (a, b) {\n  var isObjectA = isObject(a);\n  var isObjectB = isObject(b);\n  if (isObjectA && isObjectB) {\n    try {\n      return JSON.stringify(a) === JSON.stringify(b)\n    } catch (e) {\n      // possible circular reference\n      return a === b\n    }\n  } else if (!isObjectA && !isObjectB) {\n    return String(a) === String(b)\n  } else {\n    return false\n  }\n}\n\nfunction looseIndexOf (arr, val) {\n  for (var i = 0; i < arr.length; i++) {\n    if (looseEqual(arr[i], val)) { return i }\n  }\n  return -1\n}\n\n/**\n * Ensure a function is called only once.\n */\nfunction once (fn) {\n  var called = false;\n  return function () {\n    if (!called) {\n      called = true;\n      fn.apply(this, arguments);\n    }\n  }\n}\n\nvar SSR_ATTR = 'data-server-rendered';\n\nvar ASSET_TYPES = [\n  'component',\n  'directive',\n  'filter'\n];\n\nvar LIFECYCLE_HOOKS = [\n  'beforeCreate',\n  'created',\n  'beforeMount',\n  'mounted',\n  'beforeUpdate',\n  'updated',\n  'beforeDestroy',\n  'destroyed',\n  'activated',\n  'deactivated'\n];\n\n/*  */\n\nvar config = ({\n  /**\n   * Option merge strategies (used in core/util/options)\n   */\n  optionMergeStrategies: Object.create(null),\n\n  /**\n   * Whether to suppress warnings.\n   */\n  silent: false,\n\n  /**\n   * Show production mode tip message on boot?\n   */\n  productionTip: process.env.NODE_ENV !== 'production',\n\n  /**\n   * Whether to enable devtools\n   */\n  devtools: process.env.NODE_ENV !== 'production',\n\n  /**\n   * Whether to record perf\n   */\n  performance: false,\n\n  /**\n   * Error handler for watcher errors\n   */\n  errorHandler: null,\n\n  /**\n   * Warn handler for watcher warns\n   */\n  warnHandler: null,\n\n  /**\n   * Ignore certain custom elements\n   */\n  ignoredElements: [],\n\n  /**\n   * Custom user key aliases for v-on\n   */\n  keyCodes: Object.create(null),\n\n  /**\n   * Check if a tag is reserved so that it cannot be registered as a\n   * component. This is platform-dependent and may be overwritten.\n   */\n  isReservedTag: no,\n\n  /**\n   * Check if an attribute is reserved so that it cannot be used as a component\n   * prop. This is platform-dependent and may be overwritten.\n   */\n  isReservedAttr: no,\n\n  /**\n   * Check if a tag is an unknown element.\n   * Platform-dependent.\n   */\n  isUnknownElement: no,\n\n  /**\n   * Get the namespace of an element\n   */\n  getTagNamespace: noop,\n\n  /**\n   * Parse the real tag name for the specific platform.\n   */\n  parsePlatformTagName: identity,\n\n  /**\n   * Check if an attribute must be bound using property, e.g. value\n   * Platform-dependent.\n   */\n  mustUseProp: no,\n\n  /**\n   * Exposed for legacy reasons\n   */\n  _lifecycleHooks: LIFECYCLE_HOOKS\n});\n\n/*  */\n\nvar emptyObject = Object.freeze({});\n\n/**\n * Check if a string starts with $ or _\n */\nfunction isReserved (str) {\n  var c = (str + '').charCodeAt(0);\n  return c === 0x24 || c === 0x5F\n}\n\n/**\n * Define a property.\n */\nfunction def (obj, key, val, enumerable) {\n  Object.defineProperty(obj, key, {\n    value: val,\n    enumerable: !!enumerable,\n    writable: true,\n    configurable: true\n  });\n}\n\n/**\n * Parse simple path.\n */\nvar bailRE = /[^\\w.$]/;\nfunction parsePath (path) {\n  if (bailRE.test(path)) {\n    return\n  }\n  var segments = path.split('.');\n  return function (obj) {\n    for (var i = 0; i < segments.length; i++) {\n      if (!obj) { return }\n      obj = obj[segments[i]];\n    }\n    return obj\n  }\n}\n\n/*  */\n\nvar warn = noop;\nvar tip = noop;\nvar formatComponentName = (null); // work around flow check\n\nif (process.env.NODE_ENV !== 'production') {\n  var hasConsole = typeof console !== 'undefined';\n  var classifyRE = /(?:^|[-_])(\\w)/g;\n  var classify = function (str) { return str\n    .replace(classifyRE, function (c) { return c.toUpperCase(); })\n    .replace(/[-_]/g, ''); };\n\n  warn = function (msg, vm) {\n    var trace = vm ? generateComponentTrace(vm) : '';\n\n    if (config.warnHandler) {\n      config.warnHandler.call(null, msg, vm, trace);\n    } else if (hasConsole && (!config.silent)) {\n      console.error((\"[Vue warn]: \" + msg + trace));\n    }\n  };\n\n  tip = function (msg, vm) {\n    if (hasConsole && (!config.silent)) {\n      console.warn(\"[Vue tip]: \" + msg + (\n        vm ? generateComponentTrace(vm) : ''\n      ));\n    }\n  };\n\n  formatComponentName = function (vm, includeFile) {\n    if (vm.$root === vm) {\n      return '<Root>'\n    }\n    var name = typeof vm === 'string'\n      ? vm\n      : typeof vm === 'function' && vm.options\n        ? vm.options.name\n        : vm._isVue\n          ? vm.$options.name || vm.$options._componentTag\n          : vm.name;\n\n    var file = vm._isVue && vm.$options.__file;\n    if (!name && file) {\n      var match = file.match(/([^/\\\\]+)\\.vue$/);\n      name = match && match[1];\n    }\n\n    return (\n      (name ? (\"<\" + (classify(name)) + \">\") : \"<Anonymous>\") +\n      (file && includeFile !== false ? (\" at \" + file) : '')\n    )\n  };\n\n  var repeat = function (str, n) {\n    var res = '';\n    while (n) {\n      if (n % 2 === 1) { res += str; }\n      if (n > 1) { str += str; }\n      n >>= 1;\n    }\n    return res\n  };\n\n  var generateComponentTrace = function (vm) {\n    if (vm._isVue && vm.$parent) {\n      var tree = [];\n      var currentRecursiveSequence = 0;\n      while (vm) {\n        if (tree.length > 0) {\n          var last = tree[tree.length - 1];\n          if (last.constructor === vm.constructor) {\n            currentRecursiveSequence++;\n            vm = vm.$parent;\n            continue\n          } else if (currentRecursiveSequence > 0) {\n            tree[tree.length - 1] = [last, currentRecursiveSequence];\n            currentRecursiveSequence = 0;\n          }\n        }\n        tree.push(vm);\n        vm = vm.$parent;\n      }\n      return '\\n\\nfound in\\n\\n' + tree\n        .map(function (vm, i) { return (\"\" + (i === 0 ? '---> ' : repeat(' ', 5 + i * 2)) + (Array.isArray(vm)\n            ? ((formatComponentName(vm[0])) + \"... (\" + (vm[1]) + \" recursive calls)\")\n            : formatComponentName(vm))); })\n        .join('\\n')\n    } else {\n      return (\"\\n\\n(found in \" + (formatComponentName(vm)) + \")\")\n    }\n  };\n}\n\n/*  */\n\nfunction handleError (err, vm, info) {\n  if (config.errorHandler) {\n    config.errorHandler.call(null, err, vm, info);\n  } else {\n    if (process.env.NODE_ENV !== 'production') {\n      warn((\"Error in \" + info + \": \\\"\" + (err.toString()) + \"\\\"\"), vm);\n    }\n    /* istanbul ignore else */\n    if (inBrowser && typeof console !== 'undefined') {\n      console.error(err);\n    } else {\n      throw err\n    }\n  }\n}\n\n/*  */\n/* globals MutationObserver */\n\n// can we use __proto__?\nvar hasProto = '__proto__' in {};\n\n// Browser environment sniffing\nvar inBrowser = typeof window !== 'undefined';\nvar UA = inBrowser && window.navigator.userAgent.toLowerCase();\nvar isIE = UA && /msie|trident/.test(UA);\nvar isIE9 = UA && UA.indexOf('msie 9.0') > 0;\nvar isEdge = UA && UA.indexOf('edge/') > 0;\nvar isAndroid = UA && UA.indexOf('android') > 0;\nvar isIOS = UA && /iphone|ipad|ipod|ios/.test(UA);\nvar isChrome = UA && /chrome\\/\\d+/.test(UA) && !isEdge;\n\n// Firefix has a \"watch\" function on Object.prototype...\nvar nativeWatch = ({}).watch;\n\nvar supportsPassive = false;\nif (inBrowser) {\n  try {\n    var opts = {};\n    Object.defineProperty(opts, 'passive', ({\n      get: function get () {\n        /* istanbul ignore next */\n        supportsPassive = true;\n      }\n    })); // https://github.com/facebook/flow/issues/285\n    window.addEventListener('test-passive', null, opts);\n  } catch (e) {}\n}\n\n// this needs to be lazy-evaled because vue may be required before\n// vue-server-renderer can set VUE_ENV\nvar _isServer;\nvar isServerRendering = function () {\n  if (_isServer === undefined) {\n    /* istanbul ignore if */\n    if (!inBrowser && typeof global !== 'undefined') {\n      // detect presence of vue-server-renderer and avoid\n      // Webpack shimming the process\n      _isServer = global['process'].env.VUE_ENV === 'server';\n    } else {\n      _isServer = false;\n    }\n  }\n  return _isServer\n};\n\n// detect devtools\nvar devtools = inBrowser && window.__VUE_DEVTOOLS_GLOBAL_HOOK__;\n\n/* istanbul ignore next */\nfunction isNative (Ctor) {\n  return typeof Ctor === 'function' && /native code/.test(Ctor.toString())\n}\n\nvar hasSymbol =\n  typeof Symbol !== 'undefined' && isNative(Symbol) &&\n  typeof Reflect !== 'undefined' && isNative(Reflect.ownKeys);\n\n/**\n * Defer a task to execute it asynchronously.\n */\nvar nextTick = (function () {\n  var callbacks = [];\n  var pending = false;\n  var timerFunc;\n\n  function nextTickHandler () {\n    pending = false;\n    var copies = callbacks.slice(0);\n    callbacks.length = 0;\n    for (var i = 0; i < copies.length; i++) {\n      copies[i]();\n    }\n  }\n\n  // the nextTick behavior leverages the microtask queue, which can be accessed\n  // via either native Promise.then or MutationObserver.\n  // MutationObserver has wider support, however it is seriously bugged in\n  // UIWebView in iOS >= 9.3.3 when triggered in touch event handlers. It\n  // completely stops working after triggering a few times... so, if native\n  // Promise is available, we will use it:\n  /* istanbul ignore if */\n  if (typeof Promise !== 'undefined' && isNative(Promise)) {\n    var p = Promise.resolve();\n    var logError = function (err) { console.error(err); };\n    timerFunc = function () {\n      p.then(nextTickHandler).catch(logError);\n      // in problematic UIWebViews, Promise.then doesn't completely break, but\n      // it can get stuck in a weird state where callbacks are pushed into the\n      // microtask queue but the queue isn't being flushed, until the browser\n      // needs to do some other work, e.g. handle a timer. Therefore we can\n      // \"force\" the microtask queue to be flushed by adding an empty timer.\n      if (isIOS) { setTimeout(noop); }\n    };\n  } else if (typeof MutationObserver !== 'undefined' && (\n    isNative(MutationObserver) ||\n    // PhantomJS and iOS 7.x\n    MutationObserver.toString() === '[object MutationObserverConstructor]'\n  )) {\n    // use MutationObserver where native Promise is not available,\n    // e.g. PhantomJS IE11, iOS7, Android 4.4\n    var counter = 1;\n    var observer = new MutationObserver(nextTickHandler);\n    var textNode = document.createTextNode(String(counter));\n    observer.observe(textNode, {\n      characterData: true\n    });\n    timerFunc = function () {\n      counter = (counter + 1) % 2;\n      textNode.data = String(counter);\n    };\n  } else {\n    // fallback to setTimeout\n    /* istanbul ignore next */\n    timerFunc = function () {\n      setTimeout(nextTickHandler, 0);\n    };\n  }\n\n  return function queueNextTick (cb, ctx) {\n    var _resolve;\n    callbacks.push(function () {\n      if (cb) {\n        try {\n          cb.call(ctx);\n        } catch (e) {\n          handleError(e, ctx, 'nextTick');\n        }\n      } else if (_resolve) {\n        _resolve(ctx);\n      }\n    });\n    if (!pending) {\n      pending = true;\n      timerFunc();\n    }\n    if (!cb && typeof Promise !== 'undefined') {\n      return new Promise(function (resolve, reject) {\n        _resolve = resolve;\n      })\n    }\n  }\n})();\n\nvar _Set;\n/* istanbul ignore if */\nif (typeof Set !== 'undefined' && isNative(Set)) {\n  // use native Set when available.\n  _Set = Set;\n} else {\n  // a non-standard Set polyfill that only works with primitive keys.\n  _Set = (function () {\n    function Set () {\n      this.set = Object.create(null);\n    }\n    Set.prototype.has = function has (key) {\n      return this.set[key] === true\n    };\n    Set.prototype.add = function add (key) {\n      this.set[key] = true;\n    };\n    Set.prototype.clear = function clear () {\n      this.set = Object.create(null);\n    };\n\n    return Set;\n  }());\n}\n\n/*  */\n\n\nvar uid$1 = 0;\n\n/**\n * A dep is an observable that can have multiple\n * directives subscribing to it.\n */\nvar Dep = function Dep () {\n  this.id = uid$1++;\n  this.subs = [];\n};\n\nDep.prototype.addSub = function addSub (sub) {\n  this.subs.push(sub);\n};\n\nDep.prototype.removeSub = function removeSub (sub) {\n  remove(this.subs, sub);\n};\n\nDep.prototype.depend = function depend () {\n  if (Dep.target) {\n    Dep.target.addDep(this);\n  }\n};\n\nDep.prototype.notify = function notify () {\n  // stabilize the subscriber list first\n  var subs = this.subs.slice();\n  for (var i = 0, l = subs.length; i < l; i++) {\n    subs[i].update();\n  }\n};\n\n// the current target watcher being evaluated.\n// this is globally unique because there could be only one\n// watcher being evaluated at any time.\nDep.target = null;\nvar targetStack = [];\n\nfunction pushTarget (_target) {\n  if (Dep.target) { targetStack.push(Dep.target); }\n  Dep.target = _target;\n}\n\nfunction popTarget () {\n  Dep.target = targetStack.pop();\n}\n\n/*\n * not type checking this file because flow doesn't play well with\n * dynamically accessing methods on Array prototype\n */\n\nvar arrayProto = Array.prototype;\nvar arrayMethods = Object.create(arrayProto);[\n  'push',\n  'pop',\n  'shift',\n  'unshift',\n  'splice',\n  'sort',\n  'reverse'\n]\n.forEach(function (method) {\n  // cache original method\n  var original = arrayProto[method];\n  def(arrayMethods, method, function mutator () {\n    var args = [], len = arguments.length;\n    while ( len-- ) args[ len ] = arguments[ len ];\n\n    var result = original.apply(this, args);\n    var ob = this.__ob__;\n    var inserted;\n    switch (method) {\n      case 'push':\n      case 'unshift':\n        inserted = args;\n        break\n      case 'splice':\n        inserted = args.slice(2);\n        break\n    }\n    if (inserted) { ob.observeArray(inserted); }\n    // notify change\n    ob.dep.notify();\n    return result\n  });\n});\n\n/*  */\n\nvar arrayKeys = Object.getOwnPropertyNames(arrayMethods);\n\n/**\n * By default, when a reactive property is set, the new value is\n * also converted to become reactive. However when passing down props,\n * we don't want to force conversion because the value may be a nested value\n * under a frozen data structure. Converting it would defeat the optimization.\n */\nvar observerState = {\n  shouldConvert: true\n};\n\n/**\n * Observer class that are attached to each observed\n * object. Once attached, the observer converts target\n * object's property keys into getter/setters that\n * collect dependencies and dispatches updates.\n */\nvar Observer = function Observer (value) {\n  this.value = value;\n  this.dep = new Dep();\n  this.vmCount = 0;\n  def(value, '__ob__', this);\n  if (Array.isArray(value)) {\n    var augment = hasProto\n      ? protoAugment\n      : copyAugment;\n    augment(value, arrayMethods, arrayKeys);\n    this.observeArray(value);\n  } else {\n    this.walk(value);\n  }\n};\n\n/**\n * Walk through each property and convert them into\n * getter/setters. This method should only be called when\n * value type is Object.\n */\nObserver.prototype.walk = function walk (obj) {\n  var keys = Object.keys(obj);\n  for (var i = 0; i < keys.length; i++) {\n    defineReactive$$1(obj, keys[i], obj[keys[i]]);\n  }\n};\n\n/**\n * Observe a list of Array items.\n */\nObserver.prototype.observeArray = function observeArray (items) {\n  for (var i = 0, l = items.length; i < l; i++) {\n    observe(items[i]);\n  }\n};\n\n// helpers\n\n/**\n * Augment an target Object or Array by intercepting\n * the prototype chain using __proto__\n */\nfunction protoAugment (target, src, keys) {\n  /* eslint-disable no-proto */\n  target.__proto__ = src;\n  /* eslint-enable no-proto */\n}\n\n/**\n * Augment an target Object or Array by defining\n * hidden properties.\n */\n/* istanbul ignore next */\nfunction copyAugment (target, src, keys) {\n  for (var i = 0, l = keys.length; i < l; i++) {\n    var key = keys[i];\n    def(target, key, src[key]);\n  }\n}\n\n/**\n * Attempt to create an observer instance for a value,\n * returns the new observer if successfully observed,\n * or the existing observer if the value already has one.\n */\nfunction observe (value, asRootData) {\n  if (!isObject(value)) {\n    return\n  }\n  var ob;\n  if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) {\n    ob = value.__ob__;\n  } else if (\n    observerState.shouldConvert &&\n    !isServerRendering() &&\n    (Array.isArray(value) || isPlainObject(value)) &&\n    Object.isExtensible(value) &&\n    !value._isVue\n  ) {\n    ob = new Observer(value);\n  }\n  if (asRootData && ob) {\n    ob.vmCount++;\n  }\n  return ob\n}\n\n/**\n * Define a reactive property on an Object.\n */\nfunction defineReactive$$1 (\n  obj,\n  key,\n  val,\n  customSetter,\n  shallow\n) {\n  var dep = new Dep();\n\n  var property = Object.getOwnPropertyDescriptor(obj, key);\n  if (property && property.configurable === false) {\n    return\n  }\n\n  // cater for pre-defined getter/setters\n  var getter = property && property.get;\n  var setter = property && property.set;\n\n  var childOb = !shallow && observe(val);\n  Object.defineProperty(obj, key, {\n    enumerable: true,\n    configurable: true,\n    get: function reactiveGetter () {\n      var value = getter ? getter.call(obj) : val;\n      if (Dep.target) {\n        dep.depend();\n        if (childOb) {\n          childOb.dep.depend();\n        }\n        if (Array.isArray(value)) {\n          dependArray(value);\n        }\n      }\n      return value\n    },\n    set: function reactiveSetter (newVal) {\n      var value = getter ? getter.call(obj) : val;\n      /* eslint-disable no-self-compare */\n      if (newVal === value || (newVal !== newVal && value !== value)) {\n        return\n      }\n      /* eslint-enable no-self-compare */\n      if (process.env.NODE_ENV !== 'production' && customSetter) {\n        customSetter();\n      }\n      if (setter) {\n        setter.call(obj, newVal);\n      } else {\n        val = newVal;\n      }\n      childOb = !shallow && observe(newVal);\n      dep.notify();\n    }\n  });\n}\n\n/**\n * Set a property on an object. Adds the new property and\n * triggers change notification if the property doesn't\n * already exist.\n */\nfunction set (target, key, val) {\n  if (Array.isArray(target) && isValidArrayIndex(key)) {\n    target.length = Math.max(target.length, key);\n    target.splice(key, 1, val);\n    return val\n  }\n  if (hasOwn(target, key)) {\n    target[key] = val;\n    return val\n  }\n  var ob = (target).__ob__;\n  if (target._isVue || (ob && ob.vmCount)) {\n    process.env.NODE_ENV !== 'production' && warn(\n      'Avoid adding reactive properties to a Vue instance or its root $data ' +\n      'at runtime - declare it upfront in the data option.'\n    );\n    return val\n  }\n  if (!ob) {\n    target[key] = val;\n    return val\n  }\n  defineReactive$$1(ob.value, key, val);\n  ob.dep.notify();\n  return val\n}\n\n/**\n * Delete a property and trigger change if necessary.\n */\nfunction del (target, key) {\n  if (Array.isArray(target) && isValidArrayIndex(key)) {\n    target.splice(key, 1);\n    return\n  }\n  var ob = (target).__ob__;\n  if (target._isVue || (ob && ob.vmCount)) {\n    process.env.NODE_ENV !== 'production' && warn(\n      'Avoid deleting properties on a Vue instance or its root $data ' +\n      '- just set it to null.'\n    );\n    return\n  }\n  if (!hasOwn(target, key)) {\n    return\n  }\n  delete target[key];\n  if (!ob) {\n    return\n  }\n  ob.dep.notify();\n}\n\n/**\n * Collect dependencies on array elements when the array is touched, since\n * we cannot intercept array element access like property getters.\n */\nfunction dependArray (value) {\n  for (var e = (void 0), i = 0, l = value.length; i < l; i++) {\n    e = value[i];\n    e && e.__ob__ && e.__ob__.dep.depend();\n    if (Array.isArray(e)) {\n      dependArray(e);\n    }\n  }\n}\n\n/*  */\n\n/**\n * Option overwriting strategies are functions that handle\n * how to merge a parent option value and a child option\n * value into the final value.\n */\nvar strats = config.optionMergeStrategies;\n\n/**\n * Options with restrictions\n */\nif (process.env.NODE_ENV !== 'production') {\n  strats.el = strats.propsData = function (parent, child, vm, key) {\n    if (!vm) {\n      warn(\n        \"option \\\"\" + key + \"\\\" can only be used during instance \" +\n        'creation with the `new` keyword.'\n      );\n    }\n    return defaultStrat(parent, child)\n  };\n}\n\n/**\n * Helper that recursively merges two data objects together.\n */\nfunction mergeData (to, from) {\n  if (!from) { return to }\n  var key, toVal, fromVal;\n  var keys = Object.keys(from);\n  for (var i = 0; i < keys.length; i++) {\n    key = keys[i];\n    toVal = to[key];\n    fromVal = from[key];\n    if (!hasOwn(to, key)) {\n      set(to, key, fromVal);\n    } else if (isPlainObject(toVal) && isPlainObject(fromVal)) {\n      mergeData(toVal, fromVal);\n    }\n  }\n  return to\n}\n\n/**\n * Data\n */\nfunction mergeDataOrFn (\n  parentVal,\n  childVal,\n  vm\n) {\n  if (!vm) {\n    // in a Vue.extend merge, both should be functions\n    if (!childVal) {\n      return parentVal\n    }\n    if (!parentVal) {\n      return childVal\n    }\n    // when parentVal & childVal are both present,\n    // we need to return a function that returns the\n    // merged result of both functions... no need to\n    // check if parentVal is a function here because\n    // it has to be a function to pass previous merges.\n    return function mergedDataFn () {\n      return mergeData(\n        typeof childVal === 'function' ? childVal.call(this) : childVal,\n        parentVal.call(this)\n      )\n    }\n  } else if (parentVal || childVal) {\n    return function mergedInstanceDataFn () {\n      // instance merge\n      var instanceData = typeof childVal === 'function'\n        ? childVal.call(vm)\n        : childVal;\n      var defaultData = typeof parentVal === 'function'\n        ? parentVal.call(vm)\n        : undefined;\n      if (instanceData) {\n        return mergeData(instanceData, defaultData)\n      } else {\n        return defaultData\n      }\n    }\n  }\n}\n\nstrats.data = function (\n  parentVal,\n  childVal,\n  vm\n) {\n  if (!vm) {\n    if (childVal && typeof childVal !== 'function') {\n      process.env.NODE_ENV !== 'production' && warn(\n        'The \"data\" option should be a function ' +\n        'that returns a per-instance value in component ' +\n        'definitions.',\n        vm\n      );\n\n      return parentVal\n    }\n    return mergeDataOrFn.call(this, parentVal, childVal)\n  }\n\n  return mergeDataOrFn(parentVal, childVal, vm)\n};\n\n/**\n * Hooks and props are merged as arrays.\n */\nfunction mergeHook (\n  parentVal,\n  childVal\n) {\n  return childVal\n    ? parentVal\n      ? parentVal.concat(childVal)\n      : Array.isArray(childVal)\n        ? childVal\n        : [childVal]\n    : parentVal\n}\n\nLIFECYCLE_HOOKS.forEach(function (hook) {\n  strats[hook] = mergeHook;\n});\n\n/**\n * Assets\n *\n * When a vm is present (instance creation), we need to do\n * a three-way merge between constructor options, instance\n * options and parent options.\n */\nfunction mergeAssets (parentVal, childVal) {\n  var res = Object.create(parentVal || null);\n  return childVal\n    ? extend(res, childVal)\n    : res\n}\n\nASSET_TYPES.forEach(function (type) {\n  strats[type + 's'] = mergeAssets;\n});\n\n/**\n * Watchers.\n *\n * Watchers hashes should not overwrite one\n * another, so we merge them as arrays.\n */\nstrats.watch = function (parentVal, childVal) {\n  // work around Firefox's Object.prototype.watch...\n  if (parentVal === nativeWatch) { parentVal = undefined; }\n  if (childVal === nativeWatch) { childVal = undefined; }\n  /* istanbul ignore if */\n  if (!childVal) { return Object.create(parentVal || null) }\n  if (!parentVal) { return childVal }\n  var ret = {};\n  extend(ret, parentVal);\n  for (var key in childVal) {\n    var parent = ret[key];\n    var child = childVal[key];\n    if (parent && !Array.isArray(parent)) {\n      parent = [parent];\n    }\n    ret[key] = parent\n      ? parent.concat(child)\n      : Array.isArray(child) ? child : [child];\n  }\n  return ret\n};\n\n/**\n * Other object hashes.\n */\nstrats.props =\nstrats.methods =\nstrats.inject =\nstrats.computed = function (parentVal, childVal) {\n  if (!childVal) { return Object.create(parentVal || null) }\n  if (!parentVal) { return childVal }\n  var ret = Object.create(null);\n  extend(ret, parentVal);\n  extend(ret, childVal);\n  return ret\n};\nstrats.provide = mergeDataOrFn;\n\n/**\n * Default strategy.\n */\nvar defaultStrat = function (parentVal, childVal) {\n  return childVal === undefined\n    ? parentVal\n    : childVal\n};\n\n/**\n * Validate component names\n */\nfunction checkComponents (options) {\n  for (var key in options.components) {\n    var lower = key.toLowerCase();\n    if (isBuiltInTag(lower) || config.isReservedTag(lower)) {\n      warn(\n        'Do not use built-in or reserved HTML elements as component ' +\n        'id: ' + key\n      );\n    }\n  }\n}\n\n/**\n * Ensure all props option syntax are normalized into the\n * Object-based format.\n */\nfunction normalizeProps (options) {\n  var props = options.props;\n  if (!props) { return }\n  var res = {};\n  var i, val, name;\n  if (Array.isArray(props)) {\n    i = props.length;\n    while (i--) {\n      val = props[i];\n      if (typeof val === 'string') {\n        name = camelize(val);\n        res[name] = { type: null };\n      } else if (process.env.NODE_ENV !== 'production') {\n        warn('props must be strings when using array syntax.');\n      }\n    }\n  } else if (isPlainObject(props)) {\n    for (var key in props) {\n      val = props[key];\n      name = camelize(key);\n      res[name] = isPlainObject(val)\n        ? val\n        : { type: val };\n    }\n  }\n  options.props = res;\n}\n\n/**\n * Normalize all injections into Object-based format\n */\nfunction normalizeInject (options) {\n  var inject = options.inject;\n  if (Array.isArray(inject)) {\n    var normalized = options.inject = {};\n    for (var i = 0; i < inject.length; i++) {\n      normalized[inject[i]] = inject[i];\n    }\n  }\n}\n\n/**\n * Normalize raw function directives into object format.\n */\nfunction normalizeDirectives (options) {\n  var dirs = options.directives;\n  if (dirs) {\n    for (var key in dirs) {\n      var def = dirs[key];\n      if (typeof def === 'function') {\n        dirs[key] = { bind: def, update: def };\n      }\n    }\n  }\n}\n\n/**\n * Merge two option objects into a new one.\n * Core utility used in both instantiation and inheritance.\n */\nfunction mergeOptions (\n  parent,\n  child,\n  vm\n) {\n  if (process.env.NODE_ENV !== 'production') {\n    checkComponents(child);\n  }\n\n  if (typeof child === 'function') {\n    child = child.options;\n  }\n\n  normalizeProps(child);\n  normalizeInject(child);\n  normalizeDirectives(child);\n  var extendsFrom = child.extends;\n  if (extendsFrom) {\n    parent = mergeOptions(parent, extendsFrom, vm);\n  }\n  if (child.mixins) {\n    for (var i = 0, l = child.mixins.length; i < l; i++) {\n      parent = mergeOptions(parent, child.mixins[i], vm);\n    }\n  }\n  var options = {};\n  var key;\n  for (key in parent) {\n    mergeField(key);\n  }\n  for (key in child) {\n    if (!hasOwn(parent, key)) {\n      mergeField(key);\n    }\n  }\n  function mergeField (key) {\n    var strat = strats[key] || defaultStrat;\n    options[key] = strat(parent[key], child[key], vm, key);\n  }\n  return options\n}\n\n/**\n * Resolve an asset.\n * This function is used because child instances need access\n * to assets defined in its ancestor chain.\n */\nfunction resolveAsset (\n  options,\n  type,\n  id,\n  warnMissing\n) {\n  /* istanbul ignore if */\n  if (typeof id !== 'string') {\n    return\n  }\n  var assets = options[type];\n  // check local registration variations first\n  if (hasOwn(assets, id)) { return assets[id] }\n  var camelizedId = camelize(id);\n  if (hasOwn(assets, camelizedId)) { return assets[camelizedId] }\n  var PascalCaseId = capitalize(camelizedId);\n  if (hasOwn(assets, PascalCaseId)) { return assets[PascalCaseId] }\n  // fallback to prototype chain\n  var res = assets[id] || assets[camelizedId] || assets[PascalCaseId];\n  if (process.env.NODE_ENV !== 'production' && warnMissing && !res) {\n    warn(\n      'Failed to resolve ' + type.slice(0, -1) + ': ' + id,\n      options\n    );\n  }\n  return res\n}\n\n/*  */\n\nfunction validateProp (\n  key,\n  propOptions,\n  propsData,\n  vm\n) {\n  var prop = propOptions[key];\n  var absent = !hasOwn(propsData, key);\n  var value = propsData[key];\n  // handle boolean props\n  if (isType(Boolean, prop.type)) {\n    if (absent && !hasOwn(prop, 'default')) {\n      value = false;\n    } else if (!isType(String, prop.type) && (value === '' || value === hyphenate(key))) {\n      value = true;\n    }\n  }\n  // check default value\n  if (value === undefined) {\n    value = getPropDefaultValue(vm, prop, key);\n    // since the default value is a fresh copy,\n    // make sure to observe it.\n    var prevShouldConvert = observerState.shouldConvert;\n    observerState.shouldConvert = true;\n    observe(value);\n    observerState.shouldConvert = prevShouldConvert;\n  }\n  if (process.env.NODE_ENV !== 'production') {\n    assertProp(prop, key, value, vm, absent);\n  }\n  return value\n}\n\n/**\n * Get the default value of a prop.\n */\nfunction getPropDefaultValue (vm, prop, key) {\n  // no default, return undefined\n  if (!hasOwn(prop, 'default')) {\n    return undefined\n  }\n  var def = prop.default;\n  // warn against non-factory defaults for Object & Array\n  if (process.env.NODE_ENV !== 'production' && isObject(def)) {\n    warn(\n      'Invalid default value for prop \"' + key + '\": ' +\n      'Props with type Object/Array must use a factory function ' +\n      'to return the default value.',\n      vm\n    );\n  }\n  // the raw prop value was also undefined from previous render,\n  // return previous default value to avoid unnecessary watcher trigger\n  if (vm && vm.$options.propsData &&\n    vm.$options.propsData[key] === undefined &&\n    vm._props[key] !== undefined\n  ) {\n    return vm._props[key]\n  }\n  // call factory function for non-Function types\n  // a value is Function if its prototype is function even across different execution context\n  return typeof def === 'function' && getType(prop.type) !== 'Function'\n    ? def.call(vm)\n    : def\n}\n\n/**\n * Assert whether a prop is valid.\n */\nfunction assertProp (\n  prop,\n  name,\n  value,\n  vm,\n  absent\n) {\n  if (prop.required && absent) {\n    warn(\n      'Missing required prop: \"' + name + '\"',\n      vm\n    );\n    return\n  }\n  if (value == null && !prop.required) {\n    return\n  }\n  var type = prop.type;\n  var valid = !type || type === true;\n  var expectedTypes = [];\n  if (type) {\n    if (!Array.isArray(type)) {\n      type = [type];\n    }\n    for (var i = 0; i < type.length && !valid; i++) {\n      var assertedType = assertType(value, type[i]);\n      expectedTypes.push(assertedType.expectedType || '');\n      valid = assertedType.valid;\n    }\n  }\n  if (!valid) {\n    warn(\n      'Invalid prop: type check failed for prop \"' + name + '\".' +\n      ' Expected ' + expectedTypes.map(capitalize).join(', ') +\n      ', got ' + Object.prototype.toString.call(value).slice(8, -1) + '.',\n      vm\n    );\n    return\n  }\n  var validator = prop.validator;\n  if (validator) {\n    if (!validator(value)) {\n      warn(\n        'Invalid prop: custom validator check failed for prop \"' + name + '\".',\n        vm\n      );\n    }\n  }\n}\n\nvar simpleCheckRE = /^(String|Number|Boolean|Function|Symbol)$/;\n\nfunction assertType (value, type) {\n  var valid;\n  var expectedType = getType(type);\n  if (simpleCheckRE.test(expectedType)) {\n    valid = typeof value === expectedType.toLowerCase();\n  } else if (expectedType === 'Object') {\n    valid = isPlainObject(value);\n  } else if (expectedType === 'Array') {\n    valid = Array.isArray(value);\n  } else {\n    valid = value instanceof type;\n  }\n  return {\n    valid: valid,\n    expectedType: expectedType\n  }\n}\n\n/**\n * Use function string name to check built-in types,\n * because a simple equality check will fail when running\n * across different vms / iframes.\n */\nfunction getType (fn) {\n  var match = fn && fn.toString().match(/^\\s*function (\\w+)/);\n  return match ? match[1] : ''\n}\n\nfunction isType (type, fn) {\n  if (!Array.isArray(fn)) {\n    return getType(fn) === getType(type)\n  }\n  for (var i = 0, len = fn.length; i < len; i++) {\n    if (getType(fn[i]) === getType(type)) {\n      return true\n    }\n  }\n  /* istanbul ignore next */\n  return false\n}\n\n/*  */\n\n/* not type checking this file because flow doesn't play well with Proxy */\n\nvar initProxy;\n\nif (process.env.NODE_ENV !== 'production') {\n  var allowedGlobals = makeMap(\n    'Infinity,undefined,NaN,isFinite,isNaN,' +\n    'parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,' +\n    'Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,' +\n    'require' // for Webpack/Browserify\n  );\n\n  var warnNonPresent = function (target, key) {\n    warn(\n      \"Property or method \\\"\" + key + \"\\\" is not defined on the instance but \" +\n      \"referenced during render. Make sure to declare reactive data \" +\n      \"properties in the data option.\",\n      target\n    );\n  };\n\n  var hasProxy =\n    typeof Proxy !== 'undefined' &&\n    Proxy.toString().match(/native code/);\n\n  if (hasProxy) {\n    var isBuiltInModifier = makeMap('stop,prevent,self,ctrl,shift,alt,meta');\n    config.keyCodes = new Proxy(config.keyCodes, {\n      set: function set (target, key, value) {\n        if (isBuiltInModifier(key)) {\n          warn((\"Avoid overwriting built-in modifier in config.keyCodes: .\" + key));\n          return false\n        } else {\n          target[key] = value;\n          return true\n        }\n      }\n    });\n  }\n\n  var hasHandler = {\n    has: function has (target, key) {\n      var has = key in target;\n      var isAllowed = allowedGlobals(key) || key.charAt(0) === '_';\n      if (!has && !isAllowed) {\n        warnNonPresent(target, key);\n      }\n      return has || !isAllowed\n    }\n  };\n\n  var getHandler = {\n    get: function get (target, key) {\n      if (typeof key === 'string' && !(key in target)) {\n        warnNonPresent(target, key);\n      }\n      return target[key]\n    }\n  };\n\n  initProxy = function initProxy (vm) {\n    if (hasProxy) {\n      // determine which proxy handler to use\n      var options = vm.$options;\n      var handlers = options.render && options.render._withStripped\n        ? getHandler\n        : hasHandler;\n      vm._renderProxy = new Proxy(vm, handlers);\n    } else {\n      vm._renderProxy = vm;\n    }\n  };\n}\n\nvar mark;\nvar measure;\n\nif (process.env.NODE_ENV !== 'production') {\n  var perf = inBrowser && window.performance;\n  /* istanbul ignore if */\n  if (\n    perf &&\n    perf.mark &&\n    perf.measure &&\n    perf.clearMarks &&\n    perf.clearMeasures\n  ) {\n    mark = function (tag) { return perf.mark(tag); };\n    measure = function (name, startTag, endTag) {\n      perf.measure(name, startTag, endTag);\n      perf.clearMarks(startTag);\n      perf.clearMarks(endTag);\n      perf.clearMeasures(name);\n    };\n  }\n}\n\n/*  */\n\nvar VNode = function VNode (\n  tag,\n  data,\n  children,\n  text,\n  elm,\n  context,\n  componentOptions,\n  asyncFactory\n) {\n  this.tag = tag;\n  this.data = data;\n  this.children = children;\n  this.text = text;\n  this.elm = elm;\n  this.ns = undefined;\n  this.context = context;\n  this.functionalContext = undefined;\n  this.key = data && data.key;\n  this.componentOptions = componentOptions;\n  this.componentInstance = undefined;\n  this.parent = undefined;\n  this.raw = false;\n  this.isStatic = false;\n  this.isRootInsert = true;\n  this.isComment = false;\n  this.isCloned = false;\n  this.isOnce = false;\n  this.asyncFactory = asyncFactory;\n  this.asyncMeta = undefined;\n  this.isAsyncPlaceholder = false;\n};\n\nvar prototypeAccessors = { child: {} };\n\n// DEPRECATED: alias for componentInstance for backwards compat.\n/* istanbul ignore next */\nprototypeAccessors.child.get = function () {\n  return this.componentInstance\n};\n\nObject.defineProperties( VNode.prototype, prototypeAccessors );\n\nvar createEmptyVNode = function (text) {\n  if ( text === void 0 ) text = '';\n\n  var node = new VNode();\n  node.text = text;\n  node.isComment = true;\n  return node\n};\n\nfunction createTextVNode (val) {\n  return new VNode(undefined, undefined, undefined, String(val))\n}\n\n// optimized shallow clone\n// used for static nodes and slot nodes because they may be reused across\n// multiple renders, cloning them avoids errors when DOM manipulations rely\n// on their elm reference.\nfunction cloneVNode (vnode) {\n  var cloned = new VNode(\n    vnode.tag,\n    vnode.data,\n    vnode.children,\n    vnode.text,\n    vnode.elm,\n    vnode.context,\n    vnode.componentOptions,\n    vnode.asyncFactory\n  );\n  cloned.ns = vnode.ns;\n  cloned.isStatic = vnode.isStatic;\n  cloned.key = vnode.key;\n  cloned.isComment = vnode.isComment;\n  cloned.isCloned = true;\n  return cloned\n}\n\nfunction cloneVNodes (vnodes) {\n  var len = vnodes.length;\n  var res = new Array(len);\n  for (var i = 0; i < len; i++) {\n    res[i] = cloneVNode(vnodes[i]);\n  }\n  return res\n}\n\n/*  */\n\nvar normalizeEvent = cached(function (name) {\n  var passive = name.charAt(0) === '&';\n  name = passive ? name.slice(1) : name;\n  var once$$1 = name.charAt(0) === '~'; // Prefixed last, checked first\n  name = once$$1 ? name.slice(1) : name;\n  var capture = name.charAt(0) === '!';\n  name = capture ? name.slice(1) : name;\n  return {\n    name: name,\n    once: once$$1,\n    capture: capture,\n    passive: passive\n  }\n});\n\nfunction createFnInvoker (fns) {\n  function invoker () {\n    var arguments$1 = arguments;\n\n    var fns = invoker.fns;\n    if (Array.isArray(fns)) {\n      var cloned = fns.slice();\n      for (var i = 0; i < cloned.length; i++) {\n        cloned[i].apply(null, arguments$1);\n      }\n    } else {\n      // return handler return value for single handlers\n      return fns.apply(null, arguments)\n    }\n  }\n  invoker.fns = fns;\n  return invoker\n}\n\nfunction updateListeners (\n  on,\n  oldOn,\n  add,\n  remove$$1,\n  vm\n) {\n  var name, cur, old, event;\n  for (name in on) {\n    cur = on[name];\n    old = oldOn[name];\n    event = normalizeEvent(name);\n    if (isUndef(cur)) {\n      process.env.NODE_ENV !== 'production' && warn(\n        \"Invalid handler for event \\\"\" + (event.name) + \"\\\": got \" + String(cur),\n        vm\n      );\n    } else if (isUndef(old)) {\n      if (isUndef(cur.fns)) {\n        cur = on[name] = createFnInvoker(cur);\n      }\n      add(event.name, cur, event.once, event.capture, event.passive);\n    } else if (cur !== old) {\n      old.fns = cur;\n      on[name] = old;\n    }\n  }\n  for (name in oldOn) {\n    if (isUndef(on[name])) {\n      event = normalizeEvent(name);\n      remove$$1(event.name, oldOn[name], event.capture);\n    }\n  }\n}\n\n/*  */\n\nfunction mergeVNodeHook (def, hookKey, hook) {\n  var invoker;\n  var oldHook = def[hookKey];\n\n  function wrappedHook () {\n    hook.apply(this, arguments);\n    // important: remove merged hook to ensure it's called only once\n    // and prevent memory leak\n    remove(invoker.fns, wrappedHook);\n  }\n\n  if (isUndef(oldHook)) {\n    // no existing hook\n    invoker = createFnInvoker([wrappedHook]);\n  } else {\n    /* istanbul ignore if */\n    if (isDef(oldHook.fns) && isTrue(oldHook.merged)) {\n      // already a merged invoker\n      invoker = oldHook;\n      invoker.fns.push(wrappedHook);\n    } else {\n      // existing plain hook\n      invoker = createFnInvoker([oldHook, wrappedHook]);\n    }\n  }\n\n  invoker.merged = true;\n  def[hookKey] = invoker;\n}\n\n/*  */\n\nfunction extractPropsFromVNodeData (\n  data,\n  Ctor,\n  tag\n) {\n  // we are only extracting raw values here.\n  // validation and default values are handled in the child\n  // component itself.\n  var propOptions = Ctor.options.props;\n  if (isUndef(propOptions)) {\n    return\n  }\n  var res = {};\n  var attrs = data.attrs;\n  var props = data.props;\n  if (isDef(attrs) || isDef(props)) {\n    for (var key in propOptions) {\n      var altKey = hyphenate(key);\n      if (process.env.NODE_ENV !== 'production') {\n        var keyInLowerCase = key.toLowerCase();\n        if (\n          key !== keyInLowerCase &&\n          attrs && hasOwn(attrs, keyInLowerCase)\n        ) {\n          tip(\n            \"Prop \\\"\" + keyInLowerCase + \"\\\" is passed to component \" +\n            (formatComponentName(tag || Ctor)) + \", but the declared prop name is\" +\n            \" \\\"\" + key + \"\\\". \" +\n            \"Note that HTML attributes are case-insensitive and camelCased \" +\n            \"props need to use their kebab-case equivalents when using in-DOM \" +\n            \"templates. You should probably use \\\"\" + altKey + \"\\\" instead of \\\"\" + key + \"\\\".\"\n          );\n        }\n      }\n      checkProp(res, props, key, altKey, true) ||\n      checkProp(res, attrs, key, altKey, false);\n    }\n  }\n  return res\n}\n\nfunction checkProp (\n  res,\n  hash,\n  key,\n  altKey,\n  preserve\n) {\n  if (isDef(hash)) {\n    if (hasOwn(hash, key)) {\n      res[key] = hash[key];\n      if (!preserve) {\n        delete hash[key];\n      }\n      return true\n    } else if (hasOwn(hash, altKey)) {\n      res[key] = hash[altKey];\n      if (!preserve) {\n        delete hash[altKey];\n      }\n      return true\n    }\n  }\n  return false\n}\n\n/*  */\n\n// The template compiler attempts to minimize the need for normalization by\n// statically analyzing the template at compile time.\n//\n// For plain HTML markup, normalization can be completely skipped because the\n// generated render function is guaranteed to return Array<VNode>. There are\n// two cases where extra normalization is needed:\n\n// 1. When the children contains components - because a functional component\n// may return an Array instead of a single root. In this case, just a simple\n// normalization is needed - if any child is an Array, we flatten the whole\n// thing with Array.prototype.concat. It is guaranteed to be only 1-level deep\n// because functional components already normalize their own children.\nfunction simpleNormalizeChildren (children) {\n  for (var i = 0; i < children.length; i++) {\n    if (Array.isArray(children[i])) {\n      return Array.prototype.concat.apply([], children)\n    }\n  }\n  return children\n}\n\n// 2. When the children contains constructs that always generated nested Arrays,\n// e.g. <template>, <slot>, v-for, or when the children is provided by user\n// with hand-written render functions / JSX. In such cases a full normalization\n// is needed to cater to all possible types of children values.\nfunction normalizeChildren (children) {\n  return isPrimitive(children)\n    ? [createTextVNode(children)]\n    : Array.isArray(children)\n      ? normalizeArrayChildren(children)\n      : undefined\n}\n\nfunction isTextNode (node) {\n  return isDef(node) && isDef(node.text) && isFalse(node.isComment)\n}\n\nfunction normalizeArrayChildren (children, nestedIndex) {\n  var res = [];\n  var i, c, last;\n  for (i = 0; i < children.length; i++) {\n    c = children[i];\n    if (isUndef(c) || typeof c === 'boolean') { continue }\n    last = res[res.length - 1];\n    //  nested\n    if (Array.isArray(c)) {\n      res.push.apply(res, normalizeArrayChildren(c, ((nestedIndex || '') + \"_\" + i)));\n    } else if (isPrimitive(c)) {\n      if (isTextNode(last)) {\n        // merge adjacent text nodes\n        // this is necessary for SSR hydration because text nodes are\n        // essentially merged when rendered to HTML strings\n        (last).text += String(c);\n      } else if (c !== '') {\n        // convert primitive to vnode\n        res.push(createTextVNode(c));\n      }\n    } else {\n      if (isTextNode(c) && isTextNode(last)) {\n        // merge adjacent text nodes\n        res[res.length - 1] = createTextVNode(last.text + c.text);\n      } else {\n        // default key for nested array children (likely generated by v-for)\n        if (isTrue(children._isVList) &&\n          isDef(c.tag) &&\n          isUndef(c.key) &&\n          isDef(nestedIndex)) {\n          c.key = \"__vlist\" + nestedIndex + \"_\" + i + \"__\";\n        }\n        res.push(c);\n      }\n    }\n  }\n  return res\n}\n\n/*  */\n\nfunction ensureCtor (comp, base) {\n  if (comp.__esModule && comp.default) {\n    comp = comp.default;\n  }\n  return isObject(comp)\n    ? base.extend(comp)\n    : comp\n}\n\nfunction createAsyncPlaceholder (\n  factory,\n  data,\n  context,\n  children,\n  tag\n) {\n  var node = createEmptyVNode();\n  node.asyncFactory = factory;\n  node.asyncMeta = { data: data, context: context, children: children, tag: tag };\n  return node\n}\n\nfunction resolveAsyncComponent (\n  factory,\n  baseCtor,\n  context\n) {\n  if (isTrue(factory.error) && isDef(factory.errorComp)) {\n    return factory.errorComp\n  }\n\n  if (isDef(factory.resolved)) {\n    return factory.resolved\n  }\n\n  if (isTrue(factory.loading) && isDef(factory.loadingComp)) {\n    return factory.loadingComp\n  }\n\n  if (isDef(factory.contexts)) {\n    // already pending\n    factory.contexts.push(context);\n  } else {\n    var contexts = factory.contexts = [context];\n    var sync = true;\n\n    var forceRender = function () {\n      for (var i = 0, l = contexts.length; i < l; i++) {\n        contexts[i].$forceUpdate();\n      }\n    };\n\n    var resolve = once(function (res) {\n      // cache resolved\n      factory.resolved = ensureCtor(res, baseCtor);\n      // invoke callbacks only if this is not a synchronous resolve\n      // (async resolves are shimmed as synchronous during SSR)\n      if (!sync) {\n        forceRender();\n      }\n    });\n\n    var reject = once(function (reason) {\n      process.env.NODE_ENV !== 'production' && warn(\n        \"Failed to resolve async component: \" + (String(factory)) +\n        (reason ? (\"\\nReason: \" + reason) : '')\n      );\n      if (isDef(factory.errorComp)) {\n        factory.error = true;\n        forceRender();\n      }\n    });\n\n    var res = factory(resolve, reject);\n\n    if (isObject(res)) {\n      if (typeof res.then === 'function') {\n        // () => Promise\n        if (isUndef(factory.resolved)) {\n          res.then(resolve, reject);\n        }\n      } else if (isDef(res.component) && typeof res.component.then === 'function') {\n        res.component.then(resolve, reject);\n\n        if (isDef(res.error)) {\n          factory.errorComp = ensureCtor(res.error, baseCtor);\n        }\n\n        if (isDef(res.loading)) {\n          factory.loadingComp = ensureCtor(res.loading, baseCtor);\n          if (res.delay === 0) {\n            factory.loading = true;\n          } else {\n            setTimeout(function () {\n              if (isUndef(factory.resolved) && isUndef(factory.error)) {\n                factory.loading = true;\n                forceRender();\n              }\n            }, res.delay || 200);\n          }\n        }\n\n        if (isDef(res.timeout)) {\n          setTimeout(function () {\n            if (isUndef(factory.resolved)) {\n              reject(\n                process.env.NODE_ENV !== 'production'\n                  ? (\"timeout (\" + (res.timeout) + \"ms)\")\n                  : null\n              );\n            }\n          }, res.timeout);\n        }\n      }\n    }\n\n    sync = false;\n    // return in case resolved synchronously\n    return factory.loading\n      ? factory.loadingComp\n      : factory.resolved\n  }\n}\n\n/*  */\n\nfunction getFirstComponentChild (children) {\n  if (Array.isArray(children)) {\n    for (var i = 0; i < children.length; i++) {\n      var c = children[i];\n      if (isDef(c) && isDef(c.componentOptions)) {\n        return c\n      }\n    }\n  }\n}\n\n/*  */\n\n/*  */\n\nfunction initEvents (vm) {\n  vm._events = Object.create(null);\n  vm._hasHookEvent = false;\n  // init parent attached events\n  var listeners = vm.$options._parentListeners;\n  if (listeners) {\n    updateComponentListeners(vm, listeners);\n  }\n}\n\nvar target;\n\nfunction add (event, fn, once$$1) {\n  if (once$$1) {\n    target.$once(event, fn);\n  } else {\n    target.$on(event, fn);\n  }\n}\n\nfunction remove$1 (event, fn) {\n  target.$off(event, fn);\n}\n\nfunction updateComponentListeners (\n  vm,\n  listeners,\n  oldListeners\n) {\n  target = vm;\n  updateListeners(listeners, oldListeners || {}, add, remove$1, vm);\n}\n\nfunction eventsMixin (Vue) {\n  var hookRE = /^hook:/;\n  Vue.prototype.$on = function (event, fn) {\n    var this$1 = this;\n\n    var vm = this;\n    if (Array.isArray(event)) {\n      for (var i = 0, l = event.length; i < l; i++) {\n        this$1.$on(event[i], fn);\n      }\n    } else {\n      (vm._events[event] || (vm._events[event] = [])).push(fn);\n      // optimize hook:event cost by using a boolean flag marked at registration\n      // instead of a hash lookup\n      if (hookRE.test(event)) {\n        vm._hasHookEvent = true;\n      }\n    }\n    return vm\n  };\n\n  Vue.prototype.$once = function (event, fn) {\n    var vm = this;\n    function on () {\n      vm.$off(event, on);\n      fn.apply(vm, arguments);\n    }\n    on.fn = fn;\n    vm.$on(event, on);\n    return vm\n  };\n\n  Vue.prototype.$off = function (event, fn) {\n    var this$1 = this;\n\n    var vm = this;\n    // all\n    if (!arguments.length) {\n      vm._events = Object.create(null);\n      return vm\n    }\n    // array of events\n    if (Array.isArray(event)) {\n      for (var i$1 = 0, l = event.length; i$1 < l; i$1++) {\n        this$1.$off(event[i$1], fn);\n      }\n      return vm\n    }\n    // specific event\n    var cbs = vm._events[event];\n    if (!cbs) {\n      return vm\n    }\n    if (arguments.length === 1) {\n      vm._events[event] = null;\n      return vm\n    }\n    // specific handler\n    var cb;\n    var i = cbs.length;\n    while (i--) {\n      cb = cbs[i];\n      if (cb === fn || cb.fn === fn) {\n        cbs.splice(i, 1);\n        break\n      }\n    }\n    return vm\n  };\n\n  Vue.prototype.$emit = function (event) {\n    var vm = this;\n    if (process.env.NODE_ENV !== 'production') {\n      var lowerCaseEvent = event.toLowerCase();\n      if (lowerCaseEvent !== event && vm._events[lowerCaseEvent]) {\n        tip(\n          \"Event \\\"\" + lowerCaseEvent + \"\\\" is emitted in component \" +\n          (formatComponentName(vm)) + \" but the handler is registered for \\\"\" + event + \"\\\". \" +\n          \"Note that HTML attributes are case-insensitive and you cannot use \" +\n          \"v-on to listen to camelCase events when using in-DOM templates. \" +\n          \"You should probably use \\\"\" + (hyphenate(event)) + \"\\\" instead of \\\"\" + event + \"\\\".\"\n        );\n      }\n    }\n    var cbs = vm._events[event];\n    if (cbs) {\n      cbs = cbs.length > 1 ? toArray(cbs) : cbs;\n      var args = toArray(arguments, 1);\n      for (var i = 0, l = cbs.length; i < l; i++) {\n        try {\n          cbs[i].apply(vm, args);\n        } catch (e) {\n          handleError(e, vm, (\"event handler for \\\"\" + event + \"\\\"\"));\n        }\n      }\n    }\n    return vm\n  };\n}\n\n/*  */\n\n/**\n * Runtime helper for resolving raw children VNodes into a slot object.\n */\nfunction resolveSlots (\n  children,\n  context\n) {\n  var slots = {};\n  if (!children) {\n    return slots\n  }\n  var defaultSlot = [];\n  for (var i = 0, l = children.length; i < l; i++) {\n    var child = children[i];\n    // named slots should only be respected if the vnode was rendered in the\n    // same context.\n    if ((child.context === context || child.functionalContext === context) &&\n      child.data && child.data.slot != null\n    ) {\n      var name = child.data.slot;\n      var slot = (slots[name] || (slots[name] = []));\n      if (child.tag === 'template') {\n        slot.push.apply(slot, child.children);\n      } else {\n        slot.push(child);\n      }\n    } else {\n      defaultSlot.push(child);\n    }\n  }\n  // ignore whitespace\n  if (!defaultSlot.every(isWhitespace)) {\n    slots.default = defaultSlot;\n  }\n  return slots\n}\n\nfunction isWhitespace (node) {\n  return node.isComment || node.text === ' '\n}\n\nfunction resolveScopedSlots (\n  fns, // see flow/vnode\n  res\n) {\n  res = res || {};\n  for (var i = 0; i < fns.length; i++) {\n    if (Array.isArray(fns[i])) {\n      resolveScopedSlots(fns[i], res);\n    } else {\n      res[fns[i].key] = fns[i].fn;\n    }\n  }\n  return res\n}\n\n/*  */\n\nvar activeInstance = null;\nvar isUpdatingChildComponent = false;\n\nfunction initLifecycle (vm) {\n  var options = vm.$options;\n\n  // locate first non-abstract parent\n  var parent = options.parent;\n  if (parent && !options.abstract) {\n    while (parent.$options.abstract && parent.$parent) {\n      parent = parent.$parent;\n    }\n    parent.$children.push(vm);\n  }\n\n  vm.$parent = parent;\n  vm.$root = parent ? parent.$root : vm;\n\n  vm.$children = [];\n  vm.$refs = {};\n\n  vm._watcher = null;\n  vm._inactive = null;\n  vm._directInactive = false;\n  vm._isMounted = false;\n  vm._isDestroyed = false;\n  vm._isBeingDestroyed = false;\n}\n\nfunction lifecycleMixin (Vue) {\n  Vue.prototype._update = function (vnode, hydrating) {\n    var vm = this;\n    if (vm._isMounted) {\n      callHook(vm, 'beforeUpdate');\n    }\n    var prevEl = vm.$el;\n    var prevVnode = vm._vnode;\n    var prevActiveInstance = activeInstance;\n    activeInstance = vm;\n    vm._vnode = vnode;\n    // Vue.prototype.__patch__ is injected in entry points\n    // based on the rendering backend used.\n    if (!prevVnode) {\n      // initial render\n      vm.$el = vm.__patch__(\n        vm.$el, vnode, hydrating, false /* removeOnly */,\n        vm.$options._parentElm,\n        vm.$options._refElm\n      );\n      // no need for the ref nodes after initial patch\n      // this prevents keeping a detached DOM tree in memory (#5851)\n      vm.$options._parentElm = vm.$options._refElm = null;\n    } else {\n      // updates\n      vm.$el = vm.__patch__(prevVnode, vnode);\n    }\n    activeInstance = prevActiveInstance;\n    // update __vue__ reference\n    if (prevEl) {\n      prevEl.__vue__ = null;\n    }\n    if (vm.$el) {\n      vm.$el.__vue__ = vm;\n    }\n    // if parent is an HOC, update its $el as well\n    if (vm.$vnode && vm.$parent && vm.$vnode === vm.$parent._vnode) {\n      vm.$parent.$el = vm.$el;\n    }\n    // updated hook is called by the scheduler to ensure that children are\n    // updated in a parent's updated hook.\n  };\n\n  Vue.prototype.$forceUpdate = function () {\n    var vm = this;\n    if (vm._watcher) {\n      vm._watcher.update();\n    }\n  };\n\n  Vue.prototype.$destroy = function () {\n    var vm = this;\n    if (vm._isBeingDestroyed) {\n      return\n    }\n    callHook(vm, 'beforeDestroy');\n    vm._isBeingDestroyed = true;\n    // remove self from parent\n    var parent = vm.$parent;\n    if (parent && !parent._isBeingDestroyed && !vm.$options.abstract) {\n      remove(parent.$children, vm);\n    }\n    // teardown watchers\n    if (vm._watcher) {\n      vm._watcher.teardown();\n    }\n    var i = vm._watchers.length;\n    while (i--) {\n      vm._watchers[i].teardown();\n    }\n    // remove reference from data ob\n    // frozen object may not have observer.\n    if (vm._data.__ob__) {\n      vm._data.__ob__.vmCount--;\n    }\n    // call the last hook...\n    vm._isDestroyed = true;\n    // invoke destroy hooks on current rendered tree\n    vm.__patch__(vm._vnode, null);\n    // fire destroyed hook\n    callHook(vm, 'destroyed');\n    // turn off all instance listeners.\n    vm.$off();\n    // remove __vue__ reference\n    if (vm.$el) {\n      vm.$el.__vue__ = null;\n    }\n  };\n}\n\nfunction mountComponent (\n  vm,\n  el,\n  hydrating\n) {\n  vm.$el = el;\n  if (!vm.$options.render) {\n    vm.$options.render = createEmptyVNode;\n    if (process.env.NODE_ENV !== 'production') {\n      /* istanbul ignore if */\n      if ((vm.$options.template && vm.$options.template.charAt(0) !== '#') ||\n        vm.$options.el || el) {\n        warn(\n          'You are using the runtime-only build of Vue where the template ' +\n          'compiler is not available. Either pre-compile the templates into ' +\n          'render functions, or use the compiler-included build.',\n          vm\n        );\n      } else {\n        warn(\n          'Failed to mount component: template or render function not defined.',\n          vm\n        );\n      }\n    }\n  }\n  callHook(vm, 'beforeMount');\n\n  var updateComponent;\n  /* istanbul ignore if */\n  if (process.env.NODE_ENV !== 'production' && config.performance && mark) {\n    updateComponent = function () {\n      var name = vm._name;\n      var id = vm._uid;\n      var startTag = \"vue-perf-start:\" + id;\n      var endTag = \"vue-perf-end:\" + id;\n\n      mark(startTag);\n      var vnode = vm._render();\n      mark(endTag);\n      measure((name + \" render\"), startTag, endTag);\n\n      mark(startTag);\n      vm._update(vnode, hydrating);\n      mark(endTag);\n      measure((name + \" patch\"), startTag, endTag);\n    };\n  } else {\n    updateComponent = function () {\n      vm._update(vm._render(), hydrating);\n    };\n  }\n\n  vm._watcher = new Watcher(vm, updateComponent, noop);\n  hydrating = false;\n\n  // manually mounted instance, call mounted on self\n  // mounted is called for render-created child components in its inserted hook\n  if (vm.$vnode == null) {\n    vm._isMounted = true;\n    callHook(vm, 'mounted');\n  }\n  return vm\n}\n\nfunction updateChildComponent (\n  vm,\n  propsData,\n  listeners,\n  parentVnode,\n  renderChildren\n) {\n  if (process.env.NODE_ENV !== 'production') {\n    isUpdatingChildComponent = true;\n  }\n\n  // determine whether component has slot children\n  // we need to do this before overwriting $options._renderChildren\n  var hasChildren = !!(\n    renderChildren ||               // has new static slots\n    vm.$options._renderChildren ||  // has old static slots\n    parentVnode.data.scopedSlots || // has new scoped slots\n    vm.$scopedSlots !== emptyObject // has old scoped slots\n  );\n\n  vm.$options._parentVnode = parentVnode;\n  vm.$vnode = parentVnode; // update vm's placeholder node without re-render\n\n  if (vm._vnode) { // update child tree's parent\n    vm._vnode.parent = parentVnode;\n  }\n  vm.$options._renderChildren = renderChildren;\n\n  // update $attrs and $listensers hash\n  // these are also reactive so they may trigger child update if the child\n  // used them during render\n  vm.$attrs = parentVnode.data && parentVnode.data.attrs;\n  vm.$listeners = listeners;\n\n  // update props\n  if (propsData && vm.$options.props) {\n    observerState.shouldConvert = false;\n    var props = vm._props;\n    var propKeys = vm.$options._propKeys || [];\n    for (var i = 0; i < propKeys.length; i++) {\n      var key = propKeys[i];\n      props[key] = validateProp(key, vm.$options.props, propsData, vm);\n    }\n    observerState.shouldConvert = true;\n    // keep a copy of raw propsData\n    vm.$options.propsData = propsData;\n  }\n\n  // update listeners\n  if (listeners) {\n    var oldListeners = vm.$options._parentListeners;\n    vm.$options._parentListeners = listeners;\n    updateComponentListeners(vm, listeners, oldListeners);\n  }\n  // resolve slots + force update if has children\n  if (hasChildren) {\n    vm.$slots = resolveSlots(renderChildren, parentVnode.context);\n    vm.$forceUpdate();\n  }\n\n  if (process.env.NODE_ENV !== 'production') {\n    isUpdatingChildComponent = false;\n  }\n}\n\nfunction isInInactiveTree (vm) {\n  while (vm && (vm = vm.$parent)) {\n    if (vm._inactive) { return true }\n  }\n  return false\n}\n\nfunction activateChildComponent (vm, direct) {\n  if (direct) {\n    vm._directInactive = false;\n    if (isInInactiveTree(vm)) {\n      return\n    }\n  } else if (vm._directInactive) {\n    return\n  }\n  if (vm._inactive || vm._inactive === null) {\n    vm._inactive = false;\n    for (var i = 0; i < vm.$children.length; i++) {\n      activateChildComponent(vm.$children[i]);\n    }\n    callHook(vm, 'activated');\n  }\n}\n\nfunction deactivateChildComponent (vm, direct) {\n  if (direct) {\n    vm._directInactive = true;\n    if (isInInactiveTree(vm)) {\n      return\n    }\n  }\n  if (!vm._inactive) {\n    vm._inactive = true;\n    for (var i = 0; i < vm.$children.length; i++) {\n      deactivateChildComponent(vm.$children[i]);\n    }\n    callHook(vm, 'deactivated');\n  }\n}\n\nfunction callHook (vm, hook) {\n  var handlers = vm.$options[hook];\n  if (handlers) {\n    for (var i = 0, j = handlers.length; i < j; i++) {\n      try {\n        handlers[i].call(vm);\n      } catch (e) {\n        handleError(e, vm, (hook + \" hook\"));\n      }\n    }\n  }\n  if (vm._hasHookEvent) {\n    vm.$emit('hook:' + hook);\n  }\n}\n\n/*  */\n\n\nvar MAX_UPDATE_COUNT = 100;\n\nvar queue = [];\nvar activatedChildren = [];\nvar has = {};\nvar circular = {};\nvar waiting = false;\nvar flushing = false;\nvar index = 0;\n\n/**\n * Reset the scheduler's state.\n */\nfunction resetSchedulerState () {\n  index = queue.length = activatedChildren.length = 0;\n  has = {};\n  if (process.env.NODE_ENV !== 'production') {\n    circular = {};\n  }\n  waiting = flushing = false;\n}\n\n/**\n * Flush both queues and run the watchers.\n */\nfunction flushSchedulerQueue () {\n  flushing = true;\n  var watcher, id;\n\n  // Sort queue before flush.\n  // This ensures that:\n  // 1. Components are updated from parent to child. (because parent is always\n  //    created before the child)\n  // 2. A component's user watchers are run before its render watcher (because\n  //    user watchers are created before the render watcher)\n  // 3. If a component is destroyed during a parent component's watcher run,\n  //    its watchers can be skipped.\n  queue.sort(function (a, b) { return a.id - b.id; });\n\n  // do not cache length because more watchers might be pushed\n  // as we run existing watchers\n  for (index = 0; index < queue.length; index++) {\n    watcher = queue[index];\n    id = watcher.id;\n    has[id] = null;\n    watcher.run();\n    // in dev build, check and stop circular updates.\n    if (process.env.NODE_ENV !== 'production' && has[id] != null) {\n      circular[id] = (circular[id] || 0) + 1;\n      if (circular[id] > MAX_UPDATE_COUNT) {\n        warn(\n          'You may have an infinite update loop ' + (\n            watcher.user\n              ? (\"in watcher with expression \\\"\" + (watcher.expression) + \"\\\"\")\n              : \"in a component render function.\"\n          ),\n          watcher.vm\n        );\n        break\n      }\n    }\n  }\n\n  // keep copies of post queues before resetting state\n  var activatedQueue = activatedChildren.slice();\n  var updatedQueue = queue.slice();\n\n  resetSchedulerState();\n\n  // call component updated and activated hooks\n  callActivatedHooks(activatedQueue);\n  callUpdatedHooks(updatedQueue);\n\n  // devtool hook\n  /* istanbul ignore if */\n  if (devtools && config.devtools) {\n    devtools.emit('flush');\n  }\n}\n\nfunction callUpdatedHooks (queue) {\n  var i = queue.length;\n  while (i--) {\n    var watcher = queue[i];\n    var vm = watcher.vm;\n    if (vm._watcher === watcher && vm._isMounted) {\n      callHook(vm, 'updated');\n    }\n  }\n}\n\n/**\n * Queue a kept-alive component that was activated during patch.\n * The queue will be processed after the entire tree has been patched.\n */\nfunction queueActivatedComponent (vm) {\n  // setting _inactive to false here so that a render function can\n  // rely on checking whether it's in an inactive tree (e.g. router-view)\n  vm._inactive = false;\n  activatedChildren.push(vm);\n}\n\nfunction callActivatedHooks (queue) {\n  for (var i = 0; i < queue.length; i++) {\n    queue[i]._inactive = true;\n    activateChildComponent(queue[i], true /* true */);\n  }\n}\n\n/**\n * Push a watcher into the watcher queue.\n * Jobs with duplicate IDs will be skipped unless it's\n * pushed when the queue is being flushed.\n */\nfunction queueWatcher (watcher) {\n  var id = watcher.id;\n  if (has[id] == null) {\n    has[id] = true;\n    if (!flushing) {\n      queue.push(watcher);\n    } else {\n      // if already flushing, splice the watcher based on its id\n      // if already past its id, it will be run next immediately.\n      var i = queue.length - 1;\n      while (i > index && queue[i].id > watcher.id) {\n        i--;\n      }\n      queue.splice(i + 1, 0, watcher);\n    }\n    // queue the flush\n    if (!waiting) {\n      waiting = true;\n      nextTick(flushSchedulerQueue);\n    }\n  }\n}\n\n/*  */\n\nvar uid$2 = 0;\n\n/**\n * A watcher parses an expression, collects dependencies,\n * and fires callback when the expression value changes.\n * This is used for both the $watch() api and directives.\n */\nvar Watcher = function Watcher (\n  vm,\n  expOrFn,\n  cb,\n  options\n) {\n  this.vm = vm;\n  vm._watchers.push(this);\n  // options\n  if (options) {\n    this.deep = !!options.deep;\n    this.user = !!options.user;\n    this.lazy = !!options.lazy;\n    this.sync = !!options.sync;\n  } else {\n    this.deep = this.user = this.lazy = this.sync = false;\n  }\n  this.cb = cb;\n  this.id = ++uid$2; // uid for batching\n  this.active = true;\n  this.dirty = this.lazy; // for lazy watchers\n  this.deps = [];\n  this.newDeps = [];\n  this.depIds = new _Set();\n  this.newDepIds = new _Set();\n  this.expression = process.env.NODE_ENV !== 'production'\n    ? expOrFn.toString()\n    : '';\n  // parse expression for getter\n  if (typeof expOrFn === 'function') {\n    this.getter = expOrFn;\n  } else {\n    this.getter = parsePath(expOrFn);\n    if (!this.getter) {\n      this.getter = function () {};\n      process.env.NODE_ENV !== 'production' && warn(\n        \"Failed watching path: \\\"\" + expOrFn + \"\\\" \" +\n        'Watcher only accepts simple dot-delimited paths. ' +\n        'For full control, use a function instead.',\n        vm\n      );\n    }\n  }\n  this.value = this.lazy\n    ? undefined\n    : this.get();\n};\n\n/**\n * Evaluate the getter, and re-collect dependencies.\n */\nWatcher.prototype.get = function get () {\n  pushTarget(this);\n  var value;\n  var vm = this.vm;\n  try {\n    value = this.getter.call(vm, vm);\n  } catch (e) {\n    if (this.user) {\n      handleError(e, vm, (\"getter for watcher \\\"\" + (this.expression) + \"\\\"\"));\n    } else {\n      throw e\n    }\n  } finally {\n    // \"touch\" every property so they are all tracked as\n    // dependencies for deep watching\n    if (this.deep) {\n      traverse(value);\n    }\n    popTarget();\n    this.cleanupDeps();\n  }\n  return value\n};\n\n/**\n * Add a dependency to this directive.\n */\nWatcher.prototype.addDep = function addDep (dep) {\n  var id = dep.id;\n  if (!this.newDepIds.has(id)) {\n    this.newDepIds.add(id);\n    this.newDeps.push(dep);\n    if (!this.depIds.has(id)) {\n      dep.addSub(this);\n    }\n  }\n};\n\n/**\n * Clean up for dependency collection.\n */\nWatcher.prototype.cleanupDeps = function cleanupDeps () {\n    var this$1 = this;\n\n  var i = this.deps.length;\n  while (i--) {\n    var dep = this$1.deps[i];\n    if (!this$1.newDepIds.has(dep.id)) {\n      dep.removeSub(this$1);\n    }\n  }\n  var tmp = this.depIds;\n  this.depIds = this.newDepIds;\n  this.newDepIds = tmp;\n  this.newDepIds.clear();\n  tmp = this.deps;\n  this.deps = this.newDeps;\n  this.newDeps = tmp;\n  this.newDeps.length = 0;\n};\n\n/**\n * Subscriber interface.\n * Will be called when a dependency changes.\n */\nWatcher.prototype.update = function update () {\n  /* istanbul ignore else */\n  if (this.lazy) {\n    this.dirty = true;\n  } else if (this.sync) {\n    this.run();\n  } else {\n    queueWatcher(this);\n  }\n};\n\n/**\n * Scheduler job interface.\n * Will be called by the scheduler.\n */\nWatcher.prototype.run = function run () {\n  if (this.active) {\n    var value = this.get();\n    if (\n      value !== this.value ||\n      // Deep watchers and watchers on Object/Arrays should fire even\n      // when the value is the same, because the value may\n      // have mutated.\n      isObject(value) ||\n      this.deep\n    ) {\n      // set new value\n      var oldValue = this.value;\n      this.value = value;\n      if (this.user) {\n        try {\n          this.cb.call(this.vm, value, oldValue);\n        } catch (e) {\n          handleError(e, this.vm, (\"callback for watcher \\\"\" + (this.expression) + \"\\\"\"));\n        }\n      } else {\n        this.cb.call(this.vm, value, oldValue);\n      }\n    }\n  }\n};\n\n/**\n * Evaluate the value of the watcher.\n * This only gets called for lazy watchers.\n */\nWatcher.prototype.evaluate = function evaluate () {\n  this.value = this.get();\n  this.dirty = false;\n};\n\n/**\n * Depend on all deps collected by this watcher.\n */\nWatcher.prototype.depend = function depend () {\n    var this$1 = this;\n\n  var i = this.deps.length;\n  while (i--) {\n    this$1.deps[i].depend();\n  }\n};\n\n/**\n * Remove self from all dependencies' subscriber list.\n */\nWatcher.prototype.teardown = function teardown () {\n    var this$1 = this;\n\n  if (this.active) {\n    // remove self from vm's watcher list\n    // this is a somewhat expensive operation so we skip it\n    // if the vm is being destroyed.\n    if (!this.vm._isBeingDestroyed) {\n      remove(this.vm._watchers, this);\n    }\n    var i = this.deps.length;\n    while (i--) {\n      this$1.deps[i].removeSub(this$1);\n    }\n    this.active = false;\n  }\n};\n\n/**\n * Recursively traverse an object to evoke all converted\n * getters, so that every nested property inside the object\n * is collected as a \"deep\" dependency.\n */\nvar seenObjects = new _Set();\nfunction traverse (val) {\n  seenObjects.clear();\n  _traverse(val, seenObjects);\n}\n\nfunction _traverse (val, seen) {\n  var i, keys;\n  var isA = Array.isArray(val);\n  if ((!isA && !isObject(val)) || !Object.isExtensible(val)) {\n    return\n  }\n  if (val.__ob__) {\n    var depId = val.__ob__.dep.id;\n    if (seen.has(depId)) {\n      return\n    }\n    seen.add(depId);\n  }\n  if (isA) {\n    i = val.length;\n    while (i--) { _traverse(val[i], seen); }\n  } else {\n    keys = Object.keys(val);\n    i = keys.length;\n    while (i--) { _traverse(val[keys[i]], seen); }\n  }\n}\n\n/*  */\n\nvar sharedPropertyDefinition = {\n  enumerable: true,\n  configurable: true,\n  get: noop,\n  set: noop\n};\n\nfunction proxy (target, sourceKey, key) {\n  sharedPropertyDefinition.get = function proxyGetter () {\n    return this[sourceKey][key]\n  };\n  sharedPropertyDefinition.set = function proxySetter (val) {\n    this[sourceKey][key] = val;\n  };\n  Object.defineProperty(target, key, sharedPropertyDefinition);\n}\n\nfunction initState (vm) {\n  vm._watchers = [];\n  var opts = vm.$options;\n  if (opts.props) { initProps(vm, opts.props); }\n  if (opts.methods) { initMethods(vm, opts.methods); }\n  if (opts.data) {\n    initData(vm);\n  } else {\n    observe(vm._data = {}, true /* asRootData */);\n  }\n  if (opts.computed) { initComputed(vm, opts.computed); }\n  if (opts.watch && opts.watch !== nativeWatch) {\n    initWatch(vm, opts.watch);\n  }\n}\n\nfunction checkOptionType (vm, name) {\n  var option = vm.$options[name];\n  if (!isPlainObject(option)) {\n    warn(\n      (\"component option \\\"\" + name + \"\\\" should be an object.\"),\n      vm\n    );\n  }\n}\n\nfunction initProps (vm, propsOptions) {\n  var propsData = vm.$options.propsData || {};\n  var props = vm._props = {};\n  // cache prop keys so that future props updates can iterate using Array\n  // instead of dynamic object key enumeration.\n  var keys = vm.$options._propKeys = [];\n  var isRoot = !vm.$parent;\n  // root instance props should be converted\n  observerState.shouldConvert = isRoot;\n  var loop = function ( key ) {\n    keys.push(key);\n    var value = validateProp(key, propsOptions, propsData, vm);\n    /* istanbul ignore else */\n    if (process.env.NODE_ENV !== 'production') {\n      if (isReservedAttribute(key) || config.isReservedAttr(key)) {\n        warn(\n          (\"\\\"\" + key + \"\\\" is a reserved attribute and cannot be used as component prop.\"),\n          vm\n        );\n      }\n      defineReactive$$1(props, key, value, function () {\n        if (vm.$parent && !isUpdatingChildComponent) {\n          warn(\n            \"Avoid mutating a prop directly since the value will be \" +\n            \"overwritten whenever the parent component re-renders. \" +\n            \"Instead, use a data or computed property based on the prop's \" +\n            \"value. Prop being mutated: \\\"\" + key + \"\\\"\",\n            vm\n          );\n        }\n      });\n    } else {\n      defineReactive$$1(props, key, value);\n    }\n    // static props are already proxied on the component's prototype\n    // during Vue.extend(). We only need to proxy props defined at\n    // instantiation here.\n    if (!(key in vm)) {\n      proxy(vm, \"_props\", key);\n    }\n  };\n\n  for (var key in propsOptions) loop( key );\n  observerState.shouldConvert = true;\n}\n\nfunction initData (vm) {\n  var data = vm.$options.data;\n  data = vm._data = typeof data === 'function'\n    ? getData(data, vm)\n    : data || {};\n  if (!isPlainObject(data)) {\n    data = {};\n    process.env.NODE_ENV !== 'production' && warn(\n      'data functions should return an object:\\n' +\n      'https://vuejs.org/v2/guide/components.html#data-Must-Be-a-Function',\n      vm\n    );\n  }\n  // proxy data on instance\n  var keys = Object.keys(data);\n  var props = vm.$options.props;\n  var methods = vm.$options.methods;\n  var i = keys.length;\n  while (i--) {\n    var key = keys[i];\n    if (process.env.NODE_ENV !== 'production') {\n      if (methods && hasOwn(methods, key)) {\n        warn(\n          (\"method \\\"\" + key + \"\\\" has already been defined as a data property.\"),\n          vm\n        );\n      }\n    }\n    if (props && hasOwn(props, key)) {\n      process.env.NODE_ENV !== 'production' && warn(\n        \"The data property \\\"\" + key + \"\\\" is already declared as a prop. \" +\n        \"Use prop default value instead.\",\n        vm\n      );\n    } else if (!isReserved(key)) {\n      proxy(vm, \"_data\", key);\n    }\n  }\n  // observe data\n  observe(data, true /* asRootData */);\n}\n\nfunction getData (data, vm) {\n  try {\n    return data.call(vm)\n  } catch (e) {\n    handleError(e, vm, \"data()\");\n    return {}\n  }\n}\n\nvar computedWatcherOptions = { lazy: true };\n\nfunction initComputed (vm, computed) {\n  process.env.NODE_ENV !== 'production' && checkOptionType(vm, 'computed');\n  var watchers = vm._computedWatchers = Object.create(null);\n\n  for (var key in computed) {\n    var userDef = computed[key];\n    var getter = typeof userDef === 'function' ? userDef : userDef.get;\n    if (process.env.NODE_ENV !== 'production') {\n      if (getter === undefined) {\n        warn(\n          (\"No getter function has been defined for computed property \\\"\" + key + \"\\\".\"),\n          vm\n        );\n        getter = noop;\n      }\n    }\n    // create internal watcher for the computed property.\n    watchers[key] = new Watcher(vm, getter, noop, computedWatcherOptions);\n\n    // component-defined computed properties are already defined on the\n    // component prototype. We only need to define computed properties defined\n    // at instantiation here.\n    if (!(key in vm)) {\n      defineComputed(vm, key, userDef);\n    } else if (process.env.NODE_ENV !== 'production') {\n      if (key in vm.$data) {\n        warn((\"The computed property \\\"\" + key + \"\\\" is already defined in data.\"), vm);\n      } else if (vm.$options.props && key in vm.$options.props) {\n        warn((\"The computed property \\\"\" + key + \"\\\" is already defined as a prop.\"), vm);\n      }\n    }\n  }\n}\n\nfunction defineComputed (target, key, userDef) {\n  if (typeof userDef === 'function') {\n    sharedPropertyDefinition.get = createComputedGetter(key);\n    sharedPropertyDefinition.set = noop;\n  } else {\n    sharedPropertyDefinition.get = userDef.get\n      ? userDef.cache !== false\n        ? createComputedGetter(key)\n        : userDef.get\n      : noop;\n    sharedPropertyDefinition.set = userDef.set\n      ? userDef.set\n      : noop;\n  }\n  Object.defineProperty(target, key, sharedPropertyDefinition);\n}\n\nfunction createComputedGetter (key) {\n  return function computedGetter () {\n    var watcher = this._computedWatchers && this._computedWatchers[key];\n    if (watcher) {\n      if (watcher.dirty) {\n        watcher.evaluate();\n      }\n      if (Dep.target) {\n        watcher.depend();\n      }\n      return watcher.value\n    }\n  }\n}\n\nfunction initMethods (vm, methods) {\n  process.env.NODE_ENV !== 'production' && checkOptionType(vm, 'methods');\n  var props = vm.$options.props;\n  for (var key in methods) {\n    vm[key] = methods[key] == null ? noop : bind(methods[key], vm);\n    if (process.env.NODE_ENV !== 'production') {\n      if (methods[key] == null) {\n        warn(\n          \"method \\\"\" + key + \"\\\" has an undefined value in the component definition. \" +\n          \"Did you reference the function correctly?\",\n          vm\n        );\n      }\n      if (props && hasOwn(props, key)) {\n        warn(\n          (\"method \\\"\" + key + \"\\\" has already been defined as a prop.\"),\n          vm\n        );\n      }\n    }\n  }\n}\n\nfunction initWatch (vm, watch) {\n  process.env.NODE_ENV !== 'production' && checkOptionType(vm, 'watch');\n  for (var key in watch) {\n    var handler = watch[key];\n    if (Array.isArray(handler)) {\n      for (var i = 0; i < handler.length; i++) {\n        createWatcher(vm, key, handler[i]);\n      }\n    } else {\n      createWatcher(vm, key, handler);\n    }\n  }\n}\n\nfunction createWatcher (\n  vm,\n  keyOrFn,\n  handler,\n  options\n) {\n  if (isPlainObject(handler)) {\n    options = handler;\n    handler = handler.handler;\n  }\n  if (typeof handler === 'string') {\n    handler = vm[handler];\n  }\n  return vm.$watch(keyOrFn, handler, options)\n}\n\nfunction stateMixin (Vue) {\n  // flow somehow has problems with directly declared definition object\n  // when using Object.defineProperty, so we have to procedurally build up\n  // the object here.\n  var dataDef = {};\n  dataDef.get = function () { return this._data };\n  var propsDef = {};\n  propsDef.get = function () { return this._props };\n  if (process.env.NODE_ENV !== 'production') {\n    dataDef.set = function (newData) {\n      warn(\n        'Avoid replacing instance root $data. ' +\n        'Use nested data properties instead.',\n        this\n      );\n    };\n    propsDef.set = function () {\n      warn(\"$props is readonly.\", this);\n    };\n  }\n  Object.defineProperty(Vue.prototype, '$data', dataDef);\n  Object.defineProperty(Vue.prototype, '$props', propsDef);\n\n  Vue.prototype.$set = set;\n  Vue.prototype.$delete = del;\n\n  Vue.prototype.$watch = function (\n    expOrFn,\n    cb,\n    options\n  ) {\n    var vm = this;\n    if (isPlainObject(cb)) {\n      return createWatcher(vm, expOrFn, cb, options)\n    }\n    options = options || {};\n    options.user = true;\n    var watcher = new Watcher(vm, expOrFn, cb, options);\n    if (options.immediate) {\n      cb.call(vm, watcher.value);\n    }\n    return function unwatchFn () {\n      watcher.teardown();\n    }\n  };\n}\n\n/*  */\n\nfunction initProvide (vm) {\n  var provide = vm.$options.provide;\n  if (provide) {\n    vm._provided = typeof provide === 'function'\n      ? provide.call(vm)\n      : provide;\n  }\n}\n\nfunction initInjections (vm) {\n  var result = resolveInject(vm.$options.inject, vm);\n  if (result) {\n    observerState.shouldConvert = false;\n    Object.keys(result).forEach(function (key) {\n      /* istanbul ignore else */\n      if (process.env.NODE_ENV !== 'production') {\n        defineReactive$$1(vm, key, result[key], function () {\n          warn(\n            \"Avoid mutating an injected value directly since the changes will be \" +\n            \"overwritten whenever the provided component re-renders. \" +\n            \"injection being mutated: \\\"\" + key + \"\\\"\",\n            vm\n          );\n        });\n      } else {\n        defineReactive$$1(vm, key, result[key]);\n      }\n    });\n    observerState.shouldConvert = true;\n  }\n}\n\nfunction resolveInject (inject, vm) {\n  if (inject) {\n    // inject is :any because flow is not smart enough to figure out cached\n    var result = Object.create(null);\n    var keys = hasSymbol\n        ? Reflect.ownKeys(inject)\n        : Object.keys(inject);\n\n    for (var i = 0; i < keys.length; i++) {\n      var key = keys[i];\n      var provideKey = inject[key];\n      var source = vm;\n      while (source) {\n        if (source._provided && provideKey in source._provided) {\n          result[key] = source._provided[provideKey];\n          break\n        }\n        source = source.$parent;\n      }\n      if (process.env.NODE_ENV !== 'production' && !hasOwn(result, key)) {\n        warn((\"Injection \\\"\" + key + \"\\\" not found\"), vm);\n      }\n    }\n    return result\n  }\n}\n\n/*  */\n\nfunction createFunctionalComponent (\n  Ctor,\n  propsData,\n  data,\n  context,\n  children\n) {\n  var props = {};\n  var propOptions = Ctor.options.props;\n  if (isDef(propOptions)) {\n    for (var key in propOptions) {\n      props[key] = validateProp(key, propOptions, propsData || {});\n    }\n  } else {\n    if (isDef(data.attrs)) { mergeProps(props, data.attrs); }\n    if (isDef(data.props)) { mergeProps(props, data.props); }\n  }\n  // ensure the createElement function in functional components\n  // gets a unique context - this is necessary for correct named slot check\n  var _context = Object.create(context);\n  var h = function (a, b, c, d) { return createElement(_context, a, b, c, d, true); };\n  var vnode = Ctor.options.render.call(null, h, {\n    data: data,\n    props: props,\n    children: children,\n    parent: context,\n    listeners: data.on || {},\n    injections: resolveInject(Ctor.options.inject, context),\n    slots: function () { return resolveSlots(children, context); }\n  });\n  if (vnode instanceof VNode) {\n    vnode.functionalContext = context;\n    vnode.functionalOptions = Ctor.options;\n    if (data.slot) {\n      (vnode.data || (vnode.data = {})).slot = data.slot;\n    }\n  }\n  return vnode\n}\n\nfunction mergeProps (to, from) {\n  for (var key in from) {\n    to[camelize(key)] = from[key];\n  }\n}\n\n/*  */\n\n// hooks to be invoked on component VNodes during patch\nvar componentVNodeHooks = {\n  init: function init (\n    vnode,\n    hydrating,\n    parentElm,\n    refElm\n  ) {\n    if (!vnode.componentInstance || vnode.componentInstance._isDestroyed) {\n      var child = vnode.componentInstance = createComponentInstanceForVnode(\n        vnode,\n        activeInstance,\n        parentElm,\n        refElm\n      );\n      child.$mount(hydrating ? vnode.elm : undefined, hydrating);\n    } else if (vnode.data.keepAlive) {\n      // kept-alive components, treat as a patch\n      var mountedNode = vnode; // work around flow\n      componentVNodeHooks.prepatch(mountedNode, mountedNode);\n    }\n  },\n\n  prepatch: function prepatch (oldVnode, vnode) {\n    var options = vnode.componentOptions;\n    var child = vnode.componentInstance = oldVnode.componentInstance;\n    updateChildComponent(\n      child,\n      options.propsData, // updated props\n      options.listeners, // updated listeners\n      vnode, // new parent vnode\n      options.children // new children\n    );\n  },\n\n  insert: function insert (vnode) {\n    var context = vnode.context;\n    var componentInstance = vnode.componentInstance;\n    if (!componentInstance._isMounted) {\n      componentInstance._isMounted = true;\n      callHook(componentInstance, 'mounted');\n    }\n    if (vnode.data.keepAlive) {\n      if (context._isMounted) {\n        // vue-router#1212\n        // During updates, a kept-alive component's child components may\n        // change, so directly walking the tree here may call activated hooks\n        // on incorrect children. Instead we push them into a queue which will\n        // be processed after the whole patch process ended.\n        queueActivatedComponent(componentInstance);\n      } else {\n        activateChildComponent(componentInstance, true /* direct */);\n      }\n    }\n  },\n\n  destroy: function destroy (vnode) {\n    var componentInstance = vnode.componentInstance;\n    if (!componentInstance._isDestroyed) {\n      if (!vnode.data.keepAlive) {\n        componentInstance.$destroy();\n      } else {\n        deactivateChildComponent(componentInstance, true /* direct */);\n      }\n    }\n  }\n};\n\nvar hooksToMerge = Object.keys(componentVNodeHooks);\n\nfunction createComponent (\n  Ctor,\n  data,\n  context,\n  children,\n  tag\n) {\n  if (isUndef(Ctor)) {\n    return\n  }\n\n  var baseCtor = context.$options._base;\n\n  // plain options object: turn it into a constructor\n  if (isObject(Ctor)) {\n    Ctor = baseCtor.extend(Ctor);\n  }\n\n  // if at this stage it's not a constructor or an async component factory,\n  // reject.\n  if (typeof Ctor !== 'function') {\n    if (process.env.NODE_ENV !== 'production') {\n      warn((\"Invalid Component definition: \" + (String(Ctor))), context);\n    }\n    return\n  }\n\n  // async component\n  var asyncFactory;\n  if (isUndef(Ctor.cid)) {\n    asyncFactory = Ctor;\n    Ctor = resolveAsyncComponent(asyncFactory, baseCtor, context);\n    if (Ctor === undefined) {\n      // return a placeholder node for async component, which is rendered\n      // as a comment node but preserves all the raw information for the node.\n      // the information will be used for async server-rendering and hydration.\n      return createAsyncPlaceholder(\n        asyncFactory,\n        data,\n        context,\n        children,\n        tag\n      )\n    }\n  }\n\n  data = data || {};\n\n  // resolve constructor options in case global mixins are applied after\n  // component constructor creation\n  resolveConstructorOptions(Ctor);\n\n  // transform component v-model data into props & events\n  if (isDef(data.model)) {\n    transformModel(Ctor.options, data);\n  }\n\n  // extract props\n  var propsData = extractPropsFromVNodeData(data, Ctor, tag);\n\n  // functional component\n  if (isTrue(Ctor.options.functional)) {\n    return createFunctionalComponent(Ctor, propsData, data, context, children)\n  }\n\n  // keep listeners\n  var listeners = data.on;\n\n  if (isTrue(Ctor.options.abstract)) {\n    // abstract components do not keep anything\n    // other than props & listeners & slot\n\n    // work around flow\n    var slot = data.slot;\n    data = {};\n    if (slot) {\n      data.slot = slot;\n    }\n  }\n\n  // merge component management hooks onto the placeholder node\n  mergeHooks(data);\n\n  // return a placeholder vnode\n  var name = Ctor.options.name || tag;\n  var vnode = new VNode(\n    (\"vue-component-\" + (Ctor.cid) + (name ? (\"-\" + name) : '')),\n    data, undefined, undefined, undefined, context,\n    { Ctor: Ctor, propsData: propsData, listeners: listeners, tag: tag, children: children },\n    asyncFactory\n  );\n  return vnode\n}\n\nfunction createComponentInstanceForVnode (\n  vnode, // we know it's MountedComponentVNode but flow doesn't\n  parent, // activeInstance in lifecycle state\n  parentElm,\n  refElm\n) {\n  var vnodeComponentOptions = vnode.componentOptions;\n  var options = {\n    _isComponent: true,\n    parent: parent,\n    propsData: vnodeComponentOptions.propsData,\n    _componentTag: vnodeComponentOptions.tag,\n    _parentVnode: vnode,\n    _parentListeners: vnodeComponentOptions.listeners,\n    _renderChildren: vnodeComponentOptions.children,\n    _parentElm: parentElm || null,\n    _refElm: refElm || null\n  };\n  // check inline-template render functions\n  var inlineTemplate = vnode.data.inlineTemplate;\n  if (isDef(inlineTemplate)) {\n    options.render = inlineTemplate.render;\n    options.staticRenderFns = inlineTemplate.staticRenderFns;\n  }\n  return new vnodeComponentOptions.Ctor(options)\n}\n\nfunction mergeHooks (data) {\n  if (!data.hook) {\n    data.hook = {};\n  }\n  for (var i = 0; i < hooksToMerge.length; i++) {\n    var key = hooksToMerge[i];\n    var fromParent = data.hook[key];\n    var ours = componentVNodeHooks[key];\n    data.hook[key] = fromParent ? mergeHook$1(ours, fromParent) : ours;\n  }\n}\n\nfunction mergeHook$1 (one, two) {\n  return function (a, b, c, d) {\n    one(a, b, c, d);\n    two(a, b, c, d);\n  }\n}\n\n// transform component v-model info (value and callback) into\n// prop and event handler respectively.\nfunction transformModel (options, data) {\n  var prop = (options.model && options.model.prop) || 'value';\n  var event = (options.model && options.model.event) || 'input';(data.props || (data.props = {}))[prop] = data.model.value;\n  var on = data.on || (data.on = {});\n  if (isDef(on[event])) {\n    on[event] = [data.model.callback].concat(on[event]);\n  } else {\n    on[event] = data.model.callback;\n  }\n}\n\n/*  */\n\nvar SIMPLE_NORMALIZE = 1;\nvar ALWAYS_NORMALIZE = 2;\n\n// wrapper function for providing a more flexible interface\n// without getting yelled at by flow\nfunction createElement (\n  context,\n  tag,\n  data,\n  children,\n  normalizationType,\n  alwaysNormalize\n) {\n  if (Array.isArray(data) || isPrimitive(data)) {\n    normalizationType = children;\n    children = data;\n    data = undefined;\n  }\n  if (isTrue(alwaysNormalize)) {\n    normalizationType = ALWAYS_NORMALIZE;\n  }\n  return _createElement(context, tag, data, children, normalizationType)\n}\n\nfunction _createElement (\n  context,\n  tag,\n  data,\n  children,\n  normalizationType\n) {\n  if (isDef(data) && isDef((data).__ob__)) {\n    process.env.NODE_ENV !== 'production' && warn(\n      \"Avoid using observed data object as vnode data: \" + (JSON.stringify(data)) + \"\\n\" +\n      'Always create fresh vnode data objects in each render!',\n      context\n    );\n    return createEmptyVNode()\n  }\n  // object syntax in v-bind\n  if (isDef(data) && isDef(data.is)) {\n    tag = data.is;\n  }\n  if (!tag) {\n    // in case of component :is set to falsy value\n    return createEmptyVNode()\n  }\n  // warn against non-primitive key\n  if (process.env.NODE_ENV !== 'production' &&\n    isDef(data) && isDef(data.key) && !isPrimitive(data.key)\n  ) {\n    warn(\n      'Avoid using non-primitive value as key, ' +\n      'use string/number value instead.',\n      context\n    );\n  }\n  // support single function children as default scoped slot\n  if (Array.isArray(children) &&\n    typeof children[0] === 'function'\n  ) {\n    data = data || {};\n    data.scopedSlots = { default: children[0] };\n    children.length = 0;\n  }\n  if (normalizationType === ALWAYS_NORMALIZE) {\n    children = normalizeChildren(children);\n  } else if (normalizationType === SIMPLE_NORMALIZE) {\n    children = simpleNormalizeChildren(children);\n  }\n  var vnode, ns;\n  if (typeof tag === 'string') {\n    var Ctor;\n    ns = config.getTagNamespace(tag);\n    if (config.isReservedTag(tag)) {\n      // platform built-in elements\n      vnode = new VNode(\n        config.parsePlatformTagName(tag), data, children,\n        undefined, undefined, context\n      );\n    } else if (isDef(Ctor = resolveAsset(context.$options, 'components', tag))) {\n      // component\n      vnode = createComponent(Ctor, data, context, children, tag);\n    } else {\n      // unknown or unlisted namespaced elements\n      // check at runtime because it may get assigned a namespace when its\n      // parent normalizes children\n      vnode = new VNode(\n        tag, data, children,\n        undefined, undefined, context\n      );\n    }\n  } else {\n    // direct component options / constructor\n    vnode = createComponent(tag, data, context, children);\n  }\n  if (isDef(vnode)) {\n    if (ns) { applyNS(vnode, ns); }\n    return vnode\n  } else {\n    return createEmptyVNode()\n  }\n}\n\nfunction applyNS (vnode, ns) {\n  vnode.ns = ns;\n  if (vnode.tag === 'foreignObject') {\n    // use default namespace inside foreignObject\n    return\n  }\n  if (isDef(vnode.children)) {\n    for (var i = 0, l = vnode.children.length; i < l; i++) {\n      var child = vnode.children[i];\n      if (isDef(child.tag) && isUndef(child.ns)) {\n        applyNS(child, ns);\n      }\n    }\n  }\n}\n\n/*  */\n\n/**\n * Runtime helper for rendering v-for lists.\n */\nfunction renderList (\n  val,\n  render\n) {\n  var ret, i, l, keys, key;\n  if (Array.isArray(val) || typeof val === 'string') {\n    ret = new Array(val.length);\n    for (i = 0, l = val.length; i < l; i++) {\n      ret[i] = render(val[i], i);\n    }\n  } else if (typeof val === 'number') {\n    ret = new Array(val);\n    for (i = 0; i < val; i++) {\n      ret[i] = render(i + 1, i);\n    }\n  } else if (isObject(val)) {\n    keys = Object.keys(val);\n    ret = new Array(keys.length);\n    for (i = 0, l = keys.length; i < l; i++) {\n      key = keys[i];\n      ret[i] = render(val[key], key, i);\n    }\n  }\n  if (isDef(ret)) {\n    (ret)._isVList = true;\n  }\n  return ret\n}\n\n/*  */\n\n/**\n * Runtime helper for rendering <slot>\n */\nfunction renderSlot (\n  name,\n  fallback,\n  props,\n  bindObject\n) {\n  var scopedSlotFn = this.$scopedSlots[name];\n  if (scopedSlotFn) { // scoped slot\n    props = props || {};\n    if (bindObject) {\n      props = extend(extend({}, bindObject), props);\n    }\n    return scopedSlotFn(props) || fallback\n  } else {\n    var slotNodes = this.$slots[name];\n    // warn duplicate slot usage\n    if (slotNodes && process.env.NODE_ENV !== 'production') {\n      slotNodes._rendered && warn(\n        \"Duplicate presence of slot \\\"\" + name + \"\\\" found in the same render tree \" +\n        \"- this will likely cause render errors.\",\n        this\n      );\n      slotNodes._rendered = true;\n    }\n    return slotNodes || fallback\n  }\n}\n\n/*  */\n\n/**\n * Runtime helper for resolving filters\n */\nfunction resolveFilter (id) {\n  return resolveAsset(this.$options, 'filters', id, true) || identity\n}\n\n/*  */\n\n/**\n * Runtime helper for checking keyCodes from config.\n */\nfunction checkKeyCodes (\n  eventKeyCode,\n  key,\n  builtInAlias\n) {\n  var keyCodes = config.keyCodes[key] || builtInAlias;\n  if (Array.isArray(keyCodes)) {\n    return keyCodes.indexOf(eventKeyCode) === -1\n  } else {\n    return keyCodes !== eventKeyCode\n  }\n}\n\n/*  */\n\n/**\n * Runtime helper for merging v-bind=\"object\" into a VNode's data.\n */\nfunction bindObjectProps (\n  data,\n  tag,\n  value,\n  asProp,\n  isSync\n) {\n  if (value) {\n    if (!isObject(value)) {\n      process.env.NODE_ENV !== 'production' && warn(\n        'v-bind without argument expects an Object or Array value',\n        this\n      );\n    } else {\n      if (Array.isArray(value)) {\n        value = toObject(value);\n      }\n      var hash;\n      var loop = function ( key ) {\n        if (\n          key === 'class' ||\n          key === 'style' ||\n          isReservedAttribute(key)\n        ) {\n          hash = data;\n        } else {\n          var type = data.attrs && data.attrs.type;\n          hash = asProp || config.mustUseProp(tag, type, key)\n            ? data.domProps || (data.domProps = {})\n            : data.attrs || (data.attrs = {});\n        }\n        if (!(key in hash)) {\n          hash[key] = value[key];\n\n          if (isSync) {\n            var on = data.on || (data.on = {});\n            on[(\"update:\" + key)] = function ($event) {\n              value[key] = $event;\n            };\n          }\n        }\n      };\n\n      for (var key in value) loop( key );\n    }\n  }\n  return data\n}\n\n/*  */\n\n/**\n * Runtime helper for rendering static trees.\n */\nfunction renderStatic (\n  index,\n  isInFor\n) {\n  var tree = this._staticTrees[index];\n  // if has already-rendered static tree and not inside v-for,\n  // we can reuse the same tree by doing a shallow clone.\n  if (tree && !isInFor) {\n    return Array.isArray(tree)\n      ? cloneVNodes(tree)\n      : cloneVNode(tree)\n  }\n  // otherwise, render a fresh tree.\n  tree = this._staticTrees[index] =\n    this.$options.staticRenderFns[index].call(this._renderProxy);\n  markStatic(tree, (\"__static__\" + index), false);\n  return tree\n}\n\n/**\n * Runtime helper for v-once.\n * Effectively it means marking the node as static with a unique key.\n */\nfunction markOnce (\n  tree,\n  index,\n  key\n) {\n  markStatic(tree, (\"__once__\" + index + (key ? (\"_\" + key) : \"\")), true);\n  return tree\n}\n\nfunction markStatic (\n  tree,\n  key,\n  isOnce\n) {\n  if (Array.isArray(tree)) {\n    for (var i = 0; i < tree.length; i++) {\n      if (tree[i] && typeof tree[i] !== 'string') {\n        markStaticNode(tree[i], (key + \"_\" + i), isOnce);\n      }\n    }\n  } else {\n    markStaticNode(tree, key, isOnce);\n  }\n}\n\nfunction markStaticNode (node, key, isOnce) {\n  node.isStatic = true;\n  node.key = key;\n  node.isOnce = isOnce;\n}\n\n/*  */\n\nfunction bindObjectListeners (data, value) {\n  if (value) {\n    if (!isPlainObject(value)) {\n      process.env.NODE_ENV !== 'production' && warn(\n        'v-on without argument expects an Object value',\n        this\n      );\n    } else {\n      var on = data.on = data.on ? extend({}, data.on) : {};\n      for (var key in value) {\n        var existing = on[key];\n        var ours = value[key];\n        on[key] = existing ? [].concat(ours, existing) : ours;\n      }\n    }\n  }\n  return data\n}\n\n/*  */\n\nfunction initRender (vm) {\n  vm._vnode = null; // the root of the child tree\n  vm._staticTrees = null;\n  var parentVnode = vm.$vnode = vm.$options._parentVnode; // the placeholder node in parent tree\n  var renderContext = parentVnode && parentVnode.context;\n  vm.$slots = resolveSlots(vm.$options._renderChildren, renderContext);\n  vm.$scopedSlots = emptyObject;\n  // bind the createElement fn to this instance\n  // so that we get proper render context inside it.\n  // args order: tag, data, children, normalizationType, alwaysNormalize\n  // internal version is used by render functions compiled from templates\n  vm._c = function (a, b, c, d) { return createElement(vm, a, b, c, d, false); };\n  // normalization is always applied for the public version, used in\n  // user-written render functions.\n  vm.$createElement = function (a, b, c, d) { return createElement(vm, a, b, c, d, true); };\n\n  // $attrs & $listeners are exposed for easier HOC creation.\n  // they need to be reactive so that HOCs using them are always updated\n  var parentData = parentVnode && parentVnode.data;\n  /* istanbul ignore else */\n  if (process.env.NODE_ENV !== 'production') {\n    defineReactive$$1(vm, '$attrs', parentData && parentData.attrs, function () {\n      !isUpdatingChildComponent && warn(\"$attrs is readonly.\", vm);\n    }, true);\n    defineReactive$$1(vm, '$listeners', parentData && parentData.on, function () {\n      !isUpdatingChildComponent && warn(\"$listeners is readonly.\", vm);\n    }, true);\n  } else {\n    defineReactive$$1(vm, '$attrs', parentData && parentData.attrs, null, true);\n    defineReactive$$1(vm, '$listeners', parentData && parentData.on, null, true);\n  }\n}\n\nfunction renderMixin (Vue) {\n  Vue.prototype.$nextTick = function (fn) {\n    return nextTick(fn, this)\n  };\n\n  Vue.prototype._render = function () {\n    var vm = this;\n    var ref = vm.$options;\n    var render = ref.render;\n    var staticRenderFns = ref.staticRenderFns;\n    var _parentVnode = ref._parentVnode;\n\n    if (vm._isMounted) {\n      // clone slot nodes on re-renders\n      for (var key in vm.$slots) {\n        vm.$slots[key] = cloneVNodes(vm.$slots[key]);\n      }\n    }\n\n    vm.$scopedSlots = (_parentVnode && _parentVnode.data.scopedSlots) || emptyObject;\n\n    if (staticRenderFns && !vm._staticTrees) {\n      vm._staticTrees = [];\n    }\n    // set parent vnode. this allows render functions to have access\n    // to the data on the placeholder node.\n    vm.$vnode = _parentVnode;\n    // render self\n    var vnode;\n    try {\n      vnode = render.call(vm._renderProxy, vm.$createElement);\n    } catch (e) {\n      handleError(e, vm, \"render function\");\n      // return error render result,\n      // or previous vnode to prevent render error causing blank component\n      /* istanbul ignore else */\n      if (process.env.NODE_ENV !== 'production') {\n        vnode = vm.$options.renderError\n          ? vm.$options.renderError.call(vm._renderProxy, vm.$createElement, e)\n          : vm._vnode;\n      } else {\n        vnode = vm._vnode;\n      }\n    }\n    // return empty vnode in case the render function errored out\n    if (!(vnode instanceof VNode)) {\n      if (process.env.NODE_ENV !== 'production' && Array.isArray(vnode)) {\n        warn(\n          'Multiple root nodes returned from render function. Render function ' +\n          'should return a single root node.',\n          vm\n        );\n      }\n      vnode = createEmptyVNode();\n    }\n    // set parent\n    vnode.parent = _parentVnode;\n    return vnode\n  };\n\n  // internal render helpers.\n  // these are exposed on the instance prototype to reduce generated render\n  // code size.\n  Vue.prototype._o = markOnce;\n  Vue.prototype._n = toNumber;\n  Vue.prototype._s = toString;\n  Vue.prototype._l = renderList;\n  Vue.prototype._t = renderSlot;\n  Vue.prototype._q = looseEqual;\n  Vue.prototype._i = looseIndexOf;\n  Vue.prototype._m = renderStatic;\n  Vue.prototype._f = resolveFilter;\n  Vue.prototype._k = checkKeyCodes;\n  Vue.prototype._b = bindObjectProps;\n  Vue.prototype._v = createTextVNode;\n  Vue.prototype._e = createEmptyVNode;\n  Vue.prototype._u = resolveScopedSlots;\n  Vue.prototype._g = bindObjectListeners;\n}\n\n/*  */\n\nvar uid = 0;\n\nfunction initMixin (Vue) {\n  Vue.prototype._init = function (options) {\n    var vm = this;\n    // a uid\n    vm._uid = uid++;\n\n    var startTag, endTag;\n    /* istanbul ignore if */\n    if (process.env.NODE_ENV !== 'production' && config.performance && mark) {\n      startTag = \"vue-perf-init:\" + (vm._uid);\n      endTag = \"vue-perf-end:\" + (vm._uid);\n      mark(startTag);\n    }\n\n    // a flag to avoid this being observed\n    vm._isVue = true;\n    // merge options\n    if (options && options._isComponent) {\n      // optimize internal component instantiation\n      // since dynamic options merging is pretty slow, and none of the\n      // internal component options needs special treatment.\n      initInternalComponent(vm, options);\n    } else {\n      vm.$options = mergeOptions(\n        resolveConstructorOptions(vm.constructor),\n        options || {},\n        vm\n      );\n    }\n    /* istanbul ignore else */\n    if (process.env.NODE_ENV !== 'production') {\n      initProxy(vm);\n    } else {\n      vm._renderProxy = vm;\n    }\n    // expose real self\n    vm._self = vm;\n    initLifecycle(vm);\n    initEvents(vm);\n    initRender(vm);\n    callHook(vm, 'beforeCreate');\n    initInjections(vm); // resolve injections before data/props\n    initState(vm);\n    initProvide(vm); // resolve provide after data/props\n    callHook(vm, 'created');\n\n    /* istanbul ignore if */\n    if (process.env.NODE_ENV !== 'production' && config.performance && mark) {\n      vm._name = formatComponentName(vm, false);\n      mark(endTag);\n      measure(((vm._name) + \" init\"), startTag, endTag);\n    }\n\n    if (vm.$options.el) {\n      vm.$mount(vm.$options.el);\n    }\n  };\n}\n\nfunction initInternalComponent (vm, options) {\n  var opts = vm.$options = Object.create(vm.constructor.options);\n  // doing this because it's faster than dynamic enumeration.\n  opts.parent = options.parent;\n  opts.propsData = options.propsData;\n  opts._parentVnode = options._parentVnode;\n  opts._parentListeners = options._parentListeners;\n  opts._renderChildren = options._renderChildren;\n  opts._componentTag = options._componentTag;\n  opts._parentElm = options._parentElm;\n  opts._refElm = options._refElm;\n  if (options.render) {\n    opts.render = options.render;\n    opts.staticRenderFns = options.staticRenderFns;\n  }\n}\n\nfunction resolveConstructorOptions (Ctor) {\n  var options = Ctor.options;\n  if (Ctor.super) {\n    var superOptions = resolveConstructorOptions(Ctor.super);\n    var cachedSuperOptions = Ctor.superOptions;\n    if (superOptions !== cachedSuperOptions) {\n      // super option changed,\n      // need to resolve new options.\n      Ctor.superOptions = superOptions;\n      // check if there are any late-modified/attached options (#4976)\n      var modifiedOptions = resolveModifiedOptions(Ctor);\n      // update base extend options\n      if (modifiedOptions) {\n        extend(Ctor.extendOptions, modifiedOptions);\n      }\n      options = Ctor.options = mergeOptions(superOptions, Ctor.extendOptions);\n      if (options.name) {\n        options.components[options.name] = Ctor;\n      }\n    }\n  }\n  return options\n}\n\nfunction resolveModifiedOptions (Ctor) {\n  var modified;\n  var latest = Ctor.options;\n  var extended = Ctor.extendOptions;\n  var sealed = Ctor.sealedOptions;\n  for (var key in latest) {\n    if (latest[key] !== sealed[key]) {\n      if (!modified) { modified = {}; }\n      modified[key] = dedupe(latest[key], extended[key], sealed[key]);\n    }\n  }\n  return modified\n}\n\nfunction dedupe (latest, extended, sealed) {\n  // compare latest and sealed to ensure lifecycle hooks won't be duplicated\n  // between merges\n  if (Array.isArray(latest)) {\n    var res = [];\n    sealed = Array.isArray(sealed) ? sealed : [sealed];\n    extended = Array.isArray(extended) ? extended : [extended];\n    for (var i = 0; i < latest.length; i++) {\n      // push original options and not sealed options to exclude duplicated options\n      if (extended.indexOf(latest[i]) >= 0 || sealed.indexOf(latest[i]) < 0) {\n        res.push(latest[i]);\n      }\n    }\n    return res\n  } else {\n    return latest\n  }\n}\n\nfunction Vue$2 (options) {\n  if (process.env.NODE_ENV !== 'production' &&\n    !(this instanceof Vue$2)\n  ) {\n    warn('Vue is a constructor and should be called with the `new` keyword');\n  }\n  this._init(options);\n}\n\ninitMixin(Vue$2);\nstateMixin(Vue$2);\neventsMixin(Vue$2);\nlifecycleMixin(Vue$2);\nrenderMixin(Vue$2);\n\n/*  */\n\nfunction initUse (Vue) {\n  Vue.use = function (plugin) {\n    var installedPlugins = (this._installedPlugins || (this._installedPlugins = []));\n    if (installedPlugins.indexOf(plugin) > -1) {\n      return this\n    }\n\n    // additional parameters\n    var args = toArray(arguments, 1);\n    args.unshift(this);\n    if (typeof plugin.install === 'function') {\n      plugin.install.apply(plugin, args);\n    } else if (typeof plugin === 'function') {\n      plugin.apply(null, args);\n    }\n    installedPlugins.push(plugin);\n    return this\n  };\n}\n\n/*  */\n\nfunction initMixin$1 (Vue) {\n  Vue.mixin = function (mixin) {\n    this.options = mergeOptions(this.options, mixin);\n    return this\n  };\n}\n\n/*  */\n\nfunction initExtend (Vue) {\n  /**\n   * Each instance constructor, including Vue, has a unique\n   * cid. This enables us to create wrapped \"child\n   * constructors\" for prototypal inheritance and cache them.\n   */\n  Vue.cid = 0;\n  var cid = 1;\n\n  /**\n   * Class inheritance\n   */\n  Vue.extend = function (extendOptions) {\n    extendOptions = extendOptions || {};\n    var Super = this;\n    var SuperId = Super.cid;\n    var cachedCtors = extendOptions._Ctor || (extendOptions._Ctor = {});\n    if (cachedCtors[SuperId]) {\n      return cachedCtors[SuperId]\n    }\n\n    var name = extendOptions.name || Super.options.name;\n    if (process.env.NODE_ENV !== 'production') {\n      if (!/^[a-zA-Z][\\w-]*$/.test(name)) {\n        warn(\n          'Invalid component name: \"' + name + '\". Component names ' +\n          'can only contain alphanumeric characters and the hyphen, ' +\n          'and must start with a letter.'\n        );\n      }\n    }\n\n    var Sub = function VueComponent (options) {\n      this._init(options);\n    };\n    Sub.prototype = Object.create(Super.prototype);\n    Sub.prototype.constructor = Sub;\n    Sub.cid = cid++;\n    Sub.options = mergeOptions(\n      Super.options,\n      extendOptions\n    );\n    Sub['super'] = Super;\n\n    // For props and computed properties, we define the proxy getters on\n    // the Vue instances at extension time, on the extended prototype. This\n    // avoids Object.defineProperty calls for each instance created.\n    if (Sub.options.props) {\n      initProps$1(Sub);\n    }\n    if (Sub.options.computed) {\n      initComputed$1(Sub);\n    }\n\n    // allow further extension/mixin/plugin usage\n    Sub.extend = Super.extend;\n    Sub.mixin = Super.mixin;\n    Sub.use = Super.use;\n\n    // create asset registers, so extended classes\n    // can have their private assets too.\n    ASSET_TYPES.forEach(function (type) {\n      Sub[type] = Super[type];\n    });\n    // enable recursive self-lookup\n    if (name) {\n      Sub.options.components[name] = Sub;\n    }\n\n    // keep a reference to the super options at extension time.\n    // later at instantiation we can check if Super's options have\n    // been updated.\n    Sub.superOptions = Super.options;\n    Sub.extendOptions = extendOptions;\n    Sub.sealedOptions = extend({}, Sub.options);\n\n    // cache constructor\n    cachedCtors[SuperId] = Sub;\n    return Sub\n  };\n}\n\nfunction initProps$1 (Comp) {\n  var props = Comp.options.props;\n  for (var key in props) {\n    proxy(Comp.prototype, \"_props\", key);\n  }\n}\n\nfunction initComputed$1 (Comp) {\n  var computed = Comp.options.computed;\n  for (var key in computed) {\n    defineComputed(Comp.prototype, key, computed[key]);\n  }\n}\n\n/*  */\n\nfunction initAssetRegisters (Vue) {\n  /**\n   * Create asset registration methods.\n   */\n  ASSET_TYPES.forEach(function (type) {\n    Vue[type] = function (\n      id,\n      definition\n    ) {\n      if (!definition) {\n        return this.options[type + 's'][id]\n      } else {\n        /* istanbul ignore if */\n        if (process.env.NODE_ENV !== 'production') {\n          if (type === 'component' && config.isReservedTag(id)) {\n            warn(\n              'Do not use built-in or reserved HTML elements as component ' +\n              'id: ' + id\n            );\n          }\n        }\n        if (type === 'component' && isPlainObject(definition)) {\n          definition.name = definition.name || id;\n          definition = this.options._base.extend(definition);\n        }\n        if (type === 'directive' && typeof definition === 'function') {\n          definition = { bind: definition, update: definition };\n        }\n        this.options[type + 's'][id] = definition;\n        return definition\n      }\n    };\n  });\n}\n\n/*  */\n\nvar patternTypes = [String, RegExp, Array];\n\nfunction getComponentName (opts) {\n  return opts && (opts.Ctor.options.name || opts.tag)\n}\n\nfunction matches (pattern, name) {\n  if (Array.isArray(pattern)) {\n    return pattern.indexOf(name) > -1\n  } else if (typeof pattern === 'string') {\n    return pattern.split(',').indexOf(name) > -1\n  } else if (isRegExp(pattern)) {\n    return pattern.test(name)\n  }\n  /* istanbul ignore next */\n  return false\n}\n\nfunction pruneCache (cache, current, filter) {\n  for (var key in cache) {\n    var cachedNode = cache[key];\n    if (cachedNode) {\n      var name = getComponentName(cachedNode.componentOptions);\n      if (name && !filter(name)) {\n        if (cachedNode !== current) {\n          pruneCacheEntry(cachedNode);\n        }\n        cache[key] = null;\n      }\n    }\n  }\n}\n\nfunction pruneCacheEntry (vnode) {\n  if (vnode) {\n    vnode.componentInstance.$destroy();\n  }\n}\n\nvar KeepAlive = {\n  name: 'keep-alive',\n  abstract: true,\n\n  props: {\n    include: patternTypes,\n    exclude: patternTypes\n  },\n\n  created: function created () {\n    this.cache = Object.create(null);\n  },\n\n  destroyed: function destroyed () {\n    var this$1 = this;\n\n    for (var key in this$1.cache) {\n      pruneCacheEntry(this$1.cache[key]);\n    }\n  },\n\n  watch: {\n    include: function include (val) {\n      pruneCache(this.cache, this._vnode, function (name) { return matches(val, name); });\n    },\n    exclude: function exclude (val) {\n      pruneCache(this.cache, this._vnode, function (name) { return !matches(val, name); });\n    }\n  },\n\n  render: function render () {\n    var vnode = getFirstComponentChild(this.$slots.default);\n    var componentOptions = vnode && vnode.componentOptions;\n    if (componentOptions) {\n      // check pattern\n      var name = getComponentName(componentOptions);\n      if (name && (\n        (this.include && !matches(this.include, name)) ||\n        (this.exclude && matches(this.exclude, name))\n      )) {\n        return vnode\n      }\n      var key = vnode.key == null\n        // same constructor may get registered as different local components\n        // so cid alone is not enough (#3269)\n        ? componentOptions.Ctor.cid + (componentOptions.tag ? (\"::\" + (componentOptions.tag)) : '')\n        : vnode.key;\n      if (this.cache[key]) {\n        vnode.componentInstance = this.cache[key].componentInstance;\n      } else {\n        this.cache[key] = vnode;\n      }\n      vnode.data.keepAlive = true;\n    }\n    return vnode\n  }\n};\n\nvar builtInComponents = {\n  KeepAlive: KeepAlive\n};\n\n/*  */\n\nfunction initGlobalAPI (Vue) {\n  // config\n  var configDef = {};\n  configDef.get = function () { return config; };\n  if (process.env.NODE_ENV !== 'production') {\n    configDef.set = function () {\n      warn(\n        'Do not replace the Vue.config object, set individual fields instead.'\n      );\n    };\n  }\n  Object.defineProperty(Vue, 'config', configDef);\n\n  // exposed util methods.\n  // NOTE: these are not considered part of the public API - avoid relying on\n  // them unless you are aware of the risk.\n  Vue.util = {\n    warn: warn,\n    extend: extend,\n    mergeOptions: mergeOptions,\n    defineReactive: defineReactive$$1\n  };\n\n  Vue.set = set;\n  Vue.delete = del;\n  Vue.nextTick = nextTick;\n\n  Vue.options = Object.create(null);\n  ASSET_TYPES.forEach(function (type) {\n    Vue.options[type + 's'] = Object.create(null);\n  });\n\n  // this is used to identify the \"base\" constructor to extend all plain-object\n  // components with in Weex's multi-instance scenarios.\n  Vue.options._base = Vue;\n\n  extend(Vue.options.components, builtInComponents);\n\n  initUse(Vue);\n  initMixin$1(Vue);\n  initExtend(Vue);\n  initAssetRegisters(Vue);\n}\n\ninitGlobalAPI(Vue$2);\n\nObject.defineProperty(Vue$2.prototype, '$isServer', {\n  get: isServerRendering\n});\n\nObject.defineProperty(Vue$2.prototype, '$ssrContext', {\n  get: function get () {\n    /* istanbul ignore next */\n    return this.$vnode && this.$vnode.ssrContext\n  }\n});\n\nVue$2.version = '2.4.1';\n\n/* globals renderer */\n// renderer is injected by weex factory wrapper\n\nvar namespaceMap = {};\n\nfunction createElement$1 (tagName) {\n  return new renderer.Element(tagName)\n}\n\nfunction createElementNS (namespace, tagName) {\n  return new renderer.Element(namespace + ':' + tagName)\n}\n\nfunction createTextNode (text) {\n  return new renderer.TextNode(text)\n}\n\nfunction createComment (text) {\n  return new renderer.Comment(text)\n}\n\nfunction insertBefore (node, target, before) {\n  if (target.nodeType === 3) {\n    if (node.type === 'text') {\n      node.setAttr('value', target.text);\n      target.parentNode = node;\n    } else {\n      var text = createElement$1('text');\n      text.setAttr('value', target.text);\n      node.insertBefore(text, before);\n    }\n    return\n  }\n  node.insertBefore(target, before);\n}\n\nfunction removeChild (node, child) {\n  if (child.nodeType === 3) {\n    node.setAttr('value', '');\n    return\n  }\n  node.removeChild(child);\n}\n\nfunction appendChild (node, child) {\n  if (child.nodeType === 3) {\n    if (node.type === 'text') {\n      node.setAttr('value', child.text);\n      child.parentNode = node;\n    } else {\n      var text = createElement$1('text');\n      text.setAttr('value', child.text);\n      node.appendChild(text);\n    }\n    return\n  }\n\n  node.appendChild(child);\n}\n\nfunction parentNode (node) {\n  return node.parentNode\n}\n\nfunction nextSibling (node) {\n  return node.nextSibling\n}\n\nfunction tagName (node) {\n  return node.type\n}\n\nfunction setTextContent (node, text) {\n  node.parentNode.setAttr('value', text);\n}\n\nfunction setAttribute (node, key, val) {\n  node.setAttr(key, val);\n}\n\n\nvar nodeOps = Object.freeze({\n\tnamespaceMap: namespaceMap,\n\tcreateElement: createElement$1,\n\tcreateElementNS: createElementNS,\n\tcreateTextNode: createTextNode,\n\tcreateComment: createComment,\n\tinsertBefore: insertBefore,\n\tremoveChild: removeChild,\n\tappendChild: appendChild,\n\tparentNode: parentNode,\n\tnextSibling: nextSibling,\n\ttagName: tagName,\n\tsetTextContent: setTextContent,\n\tsetAttribute: setAttribute\n});\n\n/*  */\n\nvar ref = {\n  create: function create (_, vnode) {\n    registerRef(vnode);\n  },\n  update: function update (oldVnode, vnode) {\n    if (oldVnode.data.ref !== vnode.data.ref) {\n      registerRef(oldVnode, true);\n      registerRef(vnode);\n    }\n  },\n  destroy: function destroy (vnode) {\n    registerRef(vnode, true);\n  }\n};\n\nfunction registerRef (vnode, isRemoval) {\n  var key = vnode.data.ref;\n  if (!key) { return }\n\n  var vm = vnode.context;\n  var ref = vnode.componentInstance || vnode.elm;\n  var refs = vm.$refs;\n  if (isRemoval) {\n    if (Array.isArray(refs[key])) {\n      remove(refs[key], ref);\n    } else if (refs[key] === ref) {\n      refs[key] = undefined;\n    }\n  } else {\n    if (vnode.data.refInFor) {\n      if (!Array.isArray(refs[key])) {\n        refs[key] = [ref];\n      } else if (refs[key].indexOf(ref) < 0) {\n        // $flow-disable-line\n        refs[key].push(ref);\n      }\n    } else {\n      refs[key] = ref;\n    }\n  }\n}\n\n/**\n * Virtual DOM patching algorithm based on Snabbdom by\n * Simon Friis Vindum (@paldepind)\n * Licensed under the MIT License\n * https://github.com/paldepind/snabbdom/blob/master/LICENSE\n *\n * modified by Evan You (@yyx990803)\n *\n\n/*\n * Not type-checking this because this file is perf-critical and the cost\n * of making flow understand it is not worth it.\n */\n\nvar emptyNode = new VNode('', {}, []);\n\nvar hooks = ['create', 'activate', 'update', 'remove', 'destroy'];\n\nfunction sameVnode (a, b) {\n  return (\n    a.key === b.key && (\n      (\n        a.tag === b.tag &&\n        a.isComment === b.isComment &&\n        isDef(a.data) === isDef(b.data) &&\n        sameInputType(a, b)\n      ) || (\n        isTrue(a.isAsyncPlaceholder) &&\n        a.asyncFactory === b.asyncFactory &&\n        isUndef(b.asyncFactory.error)\n      )\n    )\n  )\n}\n\n// Some browsers do not support dynamically changing type for <input>\n// so they need to be treated as different nodes\nfunction sameInputType (a, b) {\n  if (a.tag !== 'input') { return true }\n  var i;\n  var typeA = isDef(i = a.data) && isDef(i = i.attrs) && i.type;\n  var typeB = isDef(i = b.data) && isDef(i = i.attrs) && i.type;\n  return typeA === typeB\n}\n\nfunction createKeyToOldIdx (children, beginIdx, endIdx) {\n  var i, key;\n  var map = {};\n  for (i = beginIdx; i <= endIdx; ++i) {\n    key = children[i].key;\n    if (isDef(key)) { map[key] = i; }\n  }\n  return map\n}\n\nfunction createPatchFunction (backend) {\n  var i, j;\n  var cbs = {};\n\n  var modules = backend.modules;\n  var nodeOps = backend.nodeOps;\n\n  for (i = 0; i < hooks.length; ++i) {\n    cbs[hooks[i]] = [];\n    for (j = 0; j < modules.length; ++j) {\n      if (isDef(modules[j][hooks[i]])) {\n        cbs[hooks[i]].push(modules[j][hooks[i]]);\n      }\n    }\n  }\n\n  function emptyNodeAt (elm) {\n    return new VNode(nodeOps.tagName(elm).toLowerCase(), {}, [], undefined, elm)\n  }\n\n  function createRmCb (childElm, listeners) {\n    function remove$$1 () {\n      if (--remove$$1.listeners === 0) {\n        removeNode(childElm);\n      }\n    }\n    remove$$1.listeners = listeners;\n    return remove$$1\n  }\n\n  function removeNode (el) {\n    var parent = nodeOps.parentNode(el);\n    // element may have already been removed due to v-html / v-text\n    if (isDef(parent)) {\n      nodeOps.removeChild(parent, el);\n    }\n  }\n\n  var inPre = 0;\n  function createElm (vnode, insertedVnodeQueue, parentElm, refElm, nested) {\n    vnode.isRootInsert = !nested; // for transition enter check\n    if (createComponent(vnode, insertedVnodeQueue, parentElm, refElm)) {\n      return\n    }\n\n    var data = vnode.data;\n    var children = vnode.children;\n    var tag = vnode.tag;\n    if (isDef(tag)) {\n      if (process.env.NODE_ENV !== 'production') {\n        if (data && data.pre) {\n          inPre++;\n        }\n        if (\n          !inPre &&\n          !vnode.ns &&\n          !(config.ignoredElements.length && config.ignoredElements.indexOf(tag) > -1) &&\n          config.isUnknownElement(tag)\n        ) {\n          warn(\n            'Unknown custom element: <' + tag + '> - did you ' +\n            'register the component correctly? For recursive components, ' +\n            'make sure to provide the \"name\" option.',\n            vnode.context\n          );\n        }\n      }\n      vnode.elm = vnode.ns\n        ? nodeOps.createElementNS(vnode.ns, tag)\n        : nodeOps.createElement(tag, vnode);\n      setScope(vnode);\n\n      /* istanbul ignore if */\n      {\n        // in Weex, the default insertion order is parent-first.\n        // List items can be optimized to use children-first insertion\n        // with append=\"tree\".\n        var appendAsTree = isDef(data) && isTrue(data.appendAsTree);\n        if (!appendAsTree) {\n          if (isDef(data)) {\n            invokeCreateHooks(vnode, insertedVnodeQueue);\n          }\n          insert(parentElm, vnode.elm, refElm);\n        }\n        createChildren(vnode, children, insertedVnodeQueue);\n        if (appendAsTree) {\n          if (isDef(data)) {\n            invokeCreateHooks(vnode, insertedVnodeQueue);\n          }\n          insert(parentElm, vnode.elm, refElm);\n        }\n      }\n\n      if (process.env.NODE_ENV !== 'production' && data && data.pre) {\n        inPre--;\n      }\n    } else if (isTrue(vnode.isComment)) {\n      vnode.elm = nodeOps.createComment(vnode.text);\n      insert(parentElm, vnode.elm, refElm);\n    } else {\n      vnode.elm = nodeOps.createTextNode(vnode.text);\n      insert(parentElm, vnode.elm, refElm);\n    }\n  }\n\n  function createComponent (vnode, insertedVnodeQueue, parentElm, refElm) {\n    var i = vnode.data;\n    if (isDef(i)) {\n      var isReactivated = isDef(vnode.componentInstance) && i.keepAlive;\n      if (isDef(i = i.hook) && isDef(i = i.init)) {\n        i(vnode, false /* hydrating */, parentElm, refElm);\n      }\n      // after calling the init hook, if the vnode is a child component\n      // it should've created a child instance and mounted it. the child\n      // component also has set the placeholder vnode's elm.\n      // in that case we can just return the element and be done.\n      if (isDef(vnode.componentInstance)) {\n        initComponent(vnode, insertedVnodeQueue);\n        if (isTrue(isReactivated)) {\n          reactivateComponent(vnode, insertedVnodeQueue, parentElm, refElm);\n        }\n        return true\n      }\n    }\n  }\n\n  function initComponent (vnode, insertedVnodeQueue) {\n    if (isDef(vnode.data.pendingInsert)) {\n      insertedVnodeQueue.push.apply(insertedVnodeQueue, vnode.data.pendingInsert);\n      vnode.data.pendingInsert = null;\n    }\n    vnode.elm = vnode.componentInstance.$el;\n    if (isPatchable(vnode)) {\n      invokeCreateHooks(vnode, insertedVnodeQueue);\n      setScope(vnode);\n    } else {\n      // empty component root.\n      // skip all element-related modules except for ref (#3455)\n      registerRef(vnode);\n      // make sure to invoke the insert hook\n      insertedVnodeQueue.push(vnode);\n    }\n  }\n\n  function reactivateComponent (vnode, insertedVnodeQueue, parentElm, refElm) {\n    var i;\n    // hack for #4339: a reactivated component with inner transition\n    // does not trigger because the inner node's created hooks are not called\n    // again. It's not ideal to involve module-specific logic in here but\n    // there doesn't seem to be a better way to do it.\n    var innerNode = vnode;\n    while (innerNode.componentInstance) {\n      innerNode = innerNode.componentInstance._vnode;\n      if (isDef(i = innerNode.data) && isDef(i = i.transition)) {\n        for (i = 0; i < cbs.activate.length; ++i) {\n          cbs.activate[i](emptyNode, innerNode);\n        }\n        insertedVnodeQueue.push(innerNode);\n        break\n      }\n    }\n    // unlike a newly created component,\n    // a reactivated keep-alive component doesn't insert itself\n    insert(parentElm, vnode.elm, refElm);\n  }\n\n  function insert (parent, elm, ref$$1) {\n    if (isDef(parent)) {\n      if (isDef(ref$$1)) {\n        if (ref$$1.parentNode === parent) {\n          nodeOps.insertBefore(parent, elm, ref$$1);\n        }\n      } else {\n        nodeOps.appendChild(parent, elm);\n      }\n    }\n  }\n\n  function createChildren (vnode, children, insertedVnodeQueue) {\n    if (Array.isArray(children)) {\n      for (var i = 0; i < children.length; ++i) {\n        createElm(children[i], insertedVnodeQueue, vnode.elm, null, true);\n      }\n    } else if (isPrimitive(vnode.text)) {\n      nodeOps.appendChild(vnode.elm, nodeOps.createTextNode(vnode.text));\n    }\n  }\n\n  function isPatchable (vnode) {\n    while (vnode.componentInstance) {\n      vnode = vnode.componentInstance._vnode;\n    }\n    return isDef(vnode.tag)\n  }\n\n  function invokeCreateHooks (vnode, insertedVnodeQueue) {\n    for (var i$1 = 0; i$1 < cbs.create.length; ++i$1) {\n      cbs.create[i$1](emptyNode, vnode);\n    }\n    i = vnode.data.hook; // Reuse variable\n    if (isDef(i)) {\n      if (isDef(i.create)) { i.create(emptyNode, vnode); }\n      if (isDef(i.insert)) { insertedVnodeQueue.push(vnode); }\n    }\n  }\n\n  // set scope id attribute for scoped CSS.\n  // this is implemented as a special case to avoid the overhead\n  // of going through the normal attribute patching process.\n  function setScope (vnode) {\n    var i;\n    var ancestor = vnode;\n    while (ancestor) {\n      if (isDef(i = ancestor.context) && isDef(i = i.$options._scopeId)) {\n        nodeOps.setAttribute(vnode.elm, i, '');\n      }\n      ancestor = ancestor.parent;\n    }\n    // for slot content they should also get the scopeId from the host instance.\n    if (isDef(i = activeInstance) &&\n      i !== vnode.context &&\n      isDef(i = i.$options._scopeId)\n    ) {\n      nodeOps.setAttribute(vnode.elm, i, '');\n    }\n  }\n\n  function addVnodes (parentElm, refElm, vnodes, startIdx, endIdx, insertedVnodeQueue) {\n    for (; startIdx <= endIdx; ++startIdx) {\n      createElm(vnodes[startIdx], insertedVnodeQueue, parentElm, refElm);\n    }\n  }\n\n  function invokeDestroyHook (vnode) {\n    var i, j;\n    var data = vnode.data;\n    if (isDef(data)) {\n      if (isDef(i = data.hook) && isDef(i = i.destroy)) { i(vnode); }\n      for (i = 0; i < cbs.destroy.length; ++i) { cbs.destroy[i](vnode); }\n    }\n    if (isDef(i = vnode.children)) {\n      for (j = 0; j < vnode.children.length; ++j) {\n        invokeDestroyHook(vnode.children[j]);\n      }\n    }\n  }\n\n  function removeVnodes (parentElm, vnodes, startIdx, endIdx) {\n    for (; startIdx <= endIdx; ++startIdx) {\n      var ch = vnodes[startIdx];\n      if (isDef(ch)) {\n        if (isDef(ch.tag)) {\n          removeAndInvokeRemoveHook(ch);\n          invokeDestroyHook(ch);\n        } else { // Text node\n          removeNode(ch.elm);\n        }\n      }\n    }\n  }\n\n  function removeAndInvokeRemoveHook (vnode, rm) {\n    if (isDef(rm) || isDef(vnode.data)) {\n      var i;\n      var listeners = cbs.remove.length + 1;\n      if (isDef(rm)) {\n        // we have a recursively passed down rm callback\n        // increase the listeners count\n        rm.listeners += listeners;\n      } else {\n        // directly removing\n        rm = createRmCb(vnode.elm, listeners);\n      }\n      // recursively invoke hooks on child component root node\n      if (isDef(i = vnode.componentInstance) && isDef(i = i._vnode) && isDef(i.data)) {\n        removeAndInvokeRemoveHook(i, rm);\n      }\n      for (i = 0; i < cbs.remove.length; ++i) {\n        cbs.remove[i](vnode, rm);\n      }\n      if (isDef(i = vnode.data.hook) && isDef(i = i.remove)) {\n        i(vnode, rm);\n      } else {\n        rm();\n      }\n    } else {\n      removeNode(vnode.elm);\n    }\n  }\n\n  function updateChildren (parentElm, oldCh, newCh, insertedVnodeQueue, removeOnly) {\n    var oldStartIdx = 0;\n    var newStartIdx = 0;\n    var oldEndIdx = oldCh.length - 1;\n    var oldStartVnode = oldCh[0];\n    var oldEndVnode = oldCh[oldEndIdx];\n    var newEndIdx = newCh.length - 1;\n    var newStartVnode = newCh[0];\n    var newEndVnode = newCh[newEndIdx];\n    var oldKeyToIdx, idxInOld, elmToMove, refElm;\n\n    // removeOnly is a special flag used only by <transition-group>\n    // to ensure removed elements stay in correct relative positions\n    // during leaving transitions\n    var canMove = !removeOnly;\n\n    while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {\n      if (isUndef(oldStartVnode)) {\n        oldStartVnode = oldCh[++oldStartIdx]; // Vnode has been moved left\n      } else if (isUndef(oldEndVnode)) {\n        oldEndVnode = oldCh[--oldEndIdx];\n      } else if (sameVnode(oldStartVnode, newStartVnode)) {\n        patchVnode(oldStartVnode, newStartVnode, insertedVnodeQueue);\n        oldStartVnode = oldCh[++oldStartIdx];\n        newStartVnode = newCh[++newStartIdx];\n      } else if (sameVnode(oldEndVnode, newEndVnode)) {\n        patchVnode(oldEndVnode, newEndVnode, insertedVnodeQueue);\n        oldEndVnode = oldCh[--oldEndIdx];\n        newEndVnode = newCh[--newEndIdx];\n      } else if (sameVnode(oldStartVnode, newEndVnode)) { // Vnode moved right\n        patchVnode(oldStartVnode, newEndVnode, insertedVnodeQueue);\n        canMove && nodeOps.insertBefore(parentElm, oldStartVnode.elm, nodeOps.nextSibling(oldEndVnode.elm));\n        oldStartVnode = oldCh[++oldStartIdx];\n        newEndVnode = newCh[--newEndIdx];\n      } else if (sameVnode(oldEndVnode, newStartVnode)) { // Vnode moved left\n        patchVnode(oldEndVnode, newStartVnode, insertedVnodeQueue);\n        canMove && nodeOps.insertBefore(parentElm, oldEndVnode.elm, oldStartVnode.elm);\n        oldEndVnode = oldCh[--oldEndIdx];\n        newStartVnode = newCh[++newStartIdx];\n      } else {\n        if (isUndef(oldKeyToIdx)) { oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx); }\n        idxInOld = isDef(newStartVnode.key) ? oldKeyToIdx[newStartVnode.key] : null;\n        if (isUndef(idxInOld)) { // New element\n          createElm(newStartVnode, insertedVnodeQueue, parentElm, oldStartVnode.elm);\n          newStartVnode = newCh[++newStartIdx];\n        } else {\n          elmToMove = oldCh[idxInOld];\n          /* istanbul ignore if */\n          if (process.env.NODE_ENV !== 'production' && !elmToMove) {\n            warn(\n              'It seems there are duplicate keys that is causing an update error. ' +\n              'Make sure each v-for item has a unique key.'\n            );\n          }\n          if (sameVnode(elmToMove, newStartVnode)) {\n            patchVnode(elmToMove, newStartVnode, insertedVnodeQueue);\n            oldCh[idxInOld] = undefined;\n            canMove && nodeOps.insertBefore(parentElm, elmToMove.elm, oldStartVnode.elm);\n            newStartVnode = newCh[++newStartIdx];\n          } else {\n            // same key but different element. treat as new element\n            createElm(newStartVnode, insertedVnodeQueue, parentElm, oldStartVnode.elm);\n            newStartVnode = newCh[++newStartIdx];\n          }\n        }\n      }\n    }\n    if (oldStartIdx > oldEndIdx) {\n      refElm = isUndef(newCh[newEndIdx + 1]) ? null : newCh[newEndIdx + 1].elm;\n      addVnodes(parentElm, refElm, newCh, newStartIdx, newEndIdx, insertedVnodeQueue);\n    } else if (newStartIdx > newEndIdx) {\n      removeVnodes(parentElm, oldCh, oldStartIdx, oldEndIdx);\n    }\n  }\n\n  function patchVnode (oldVnode, vnode, insertedVnodeQueue, removeOnly) {\n    if (oldVnode === vnode) {\n      return\n    }\n\n    var elm = vnode.elm = oldVnode.elm;\n\n    if (isTrue(oldVnode.isAsyncPlaceholder)) {\n      if (isDef(vnode.asyncFactory.resolved)) {\n        hydrate(oldVnode.elm, vnode, insertedVnodeQueue);\n      } else {\n        vnode.isAsyncPlaceholder = true;\n      }\n      return\n    }\n\n    // reuse element for static trees.\n    // note we only do this if the vnode is cloned -\n    // if the new node is not cloned it means the render functions have been\n    // reset by the hot-reload-api and we need to do a proper re-render.\n    if (isTrue(vnode.isStatic) &&\n      isTrue(oldVnode.isStatic) &&\n      vnode.key === oldVnode.key &&\n      (isTrue(vnode.isCloned) || isTrue(vnode.isOnce))\n    ) {\n      vnode.componentInstance = oldVnode.componentInstance;\n      return\n    }\n\n    var i;\n    var data = vnode.data;\n    if (isDef(data) && isDef(i = data.hook) && isDef(i = i.prepatch)) {\n      i(oldVnode, vnode);\n    }\n\n    var oldCh = oldVnode.children;\n    var ch = vnode.children;\n    if (isDef(data) && isPatchable(vnode)) {\n      for (i = 0; i < cbs.update.length; ++i) { cbs.update[i](oldVnode, vnode); }\n      if (isDef(i = data.hook) && isDef(i = i.update)) { i(oldVnode, vnode); }\n    }\n    if (isUndef(vnode.text)) {\n      if (isDef(oldCh) && isDef(ch)) {\n        if (oldCh !== ch) { updateChildren(elm, oldCh, ch, insertedVnodeQueue, removeOnly); }\n      } else if (isDef(ch)) {\n        if (isDef(oldVnode.text)) { nodeOps.setTextContent(elm, ''); }\n        addVnodes(elm, null, ch, 0, ch.length - 1, insertedVnodeQueue);\n      } else if (isDef(oldCh)) {\n        removeVnodes(elm, oldCh, 0, oldCh.length - 1);\n      } else if (isDef(oldVnode.text)) {\n        nodeOps.setTextContent(elm, '');\n      }\n    } else if (oldVnode.text !== vnode.text) {\n      nodeOps.setTextContent(elm, vnode.text);\n    }\n    if (isDef(data)) {\n      if (isDef(i = data.hook) && isDef(i = i.postpatch)) { i(oldVnode, vnode); }\n    }\n  }\n\n  function invokeInsertHook (vnode, queue, initial) {\n    // delay insert hooks for component root nodes, invoke them after the\n    // element is really inserted\n    if (isTrue(initial) && isDef(vnode.parent)) {\n      vnode.parent.data.pendingInsert = queue;\n    } else {\n      for (var i = 0; i < queue.length; ++i) {\n        queue[i].data.hook.insert(queue[i]);\n      }\n    }\n  }\n\n  var bailed = false;\n  // list of modules that can skip create hook during hydration because they\n  // are already rendered on the client or has no need for initialization\n  var isRenderedModule = makeMap('attrs,style,class,staticClass,staticStyle,key');\n\n  // Note: this is a browser-only function so we can assume elms are DOM nodes.\n  function hydrate (elm, vnode, insertedVnodeQueue) {\n    if (isTrue(vnode.isComment) && isDef(vnode.asyncFactory)) {\n      vnode.elm = elm;\n      vnode.isAsyncPlaceholder = true;\n      return true\n    }\n    if (process.env.NODE_ENV !== 'production') {\n      if (!assertNodeMatch(elm, vnode)) {\n        return false\n      }\n    }\n    vnode.elm = elm;\n    var tag = vnode.tag;\n    var data = vnode.data;\n    var children = vnode.children;\n    if (isDef(data)) {\n      if (isDef(i = data.hook) && isDef(i = i.init)) { i(vnode, true /* hydrating */); }\n      if (isDef(i = vnode.componentInstance)) {\n        // child component. it should have hydrated its own tree.\n        initComponent(vnode, insertedVnodeQueue);\n        return true\n      }\n    }\n    if (isDef(tag)) {\n      if (isDef(children)) {\n        // empty element, allow client to pick up and populate children\n        if (!elm.hasChildNodes()) {\n          createChildren(vnode, children, insertedVnodeQueue);\n        } else {\n          var childrenMatch = true;\n          var childNode = elm.firstChild;\n          for (var i$1 = 0; i$1 < children.length; i$1++) {\n            if (!childNode || !hydrate(childNode, children[i$1], insertedVnodeQueue)) {\n              childrenMatch = false;\n              break\n            }\n            childNode = childNode.nextSibling;\n          }\n          // if childNode is not null, it means the actual childNodes list is\n          // longer than the virtual children list.\n          if (!childrenMatch || childNode) {\n            if (process.env.NODE_ENV !== 'production' &&\n              typeof console !== 'undefined' &&\n              !bailed\n            ) {\n              bailed = true;\n              console.warn('Parent: ', elm);\n              console.warn('Mismatching childNodes vs. VNodes: ', elm.childNodes, children);\n            }\n            return false\n          }\n        }\n      }\n      if (isDef(data)) {\n        for (var key in data) {\n          if (!isRenderedModule(key)) {\n            invokeCreateHooks(vnode, insertedVnodeQueue);\n            break\n          }\n        }\n      }\n    } else if (elm.data !== vnode.text) {\n      elm.data = vnode.text;\n    }\n    return true\n  }\n\n  function assertNodeMatch (node, vnode) {\n    if (isDef(vnode.tag)) {\n      return (\n        vnode.tag.indexOf('vue-component') === 0 ||\n        vnode.tag.toLowerCase() === (node.tagName && node.tagName.toLowerCase())\n      )\n    } else {\n      return node.nodeType === (vnode.isComment ? 8 : 3)\n    }\n  }\n\n  return function patch (oldVnode, vnode, hydrating, removeOnly, parentElm, refElm) {\n    if (isUndef(vnode)) {\n      if (isDef(oldVnode)) { invokeDestroyHook(oldVnode); }\n      return\n    }\n\n    var isInitialPatch = false;\n    var insertedVnodeQueue = [];\n\n    if (isUndef(oldVnode)) {\n      // empty mount (likely as component), create new root element\n      isInitialPatch = true;\n      createElm(vnode, insertedVnodeQueue, parentElm, refElm);\n    } else {\n      var isRealElement = isDef(oldVnode.nodeType);\n      if (!isRealElement && sameVnode(oldVnode, vnode)) {\n        // patch existing root node\n        patchVnode(oldVnode, vnode, insertedVnodeQueue, removeOnly);\n      } else {\n        if (isRealElement) {\n          // mounting to a real element\n          // check if this is server-rendered content and if we can perform\n          // a successful hydration.\n          if (oldVnode.nodeType === 1 && oldVnode.hasAttribute(SSR_ATTR)) {\n            oldVnode.removeAttribute(SSR_ATTR);\n            hydrating = true;\n          }\n          if (isTrue(hydrating)) {\n            if (hydrate(oldVnode, vnode, insertedVnodeQueue)) {\n              invokeInsertHook(vnode, insertedVnodeQueue, true);\n              return oldVnode\n            } else if (process.env.NODE_ENV !== 'production') {\n              warn(\n                'The client-side rendered virtual DOM tree is not matching ' +\n                'server-rendered content. This is likely caused by incorrect ' +\n                'HTML markup, for example nesting block-level elements inside ' +\n                '<p>, or missing <tbody>. Bailing hydration and performing ' +\n                'full client-side render.'\n              );\n            }\n          }\n          // either not server-rendered, or hydration failed.\n          // create an empty node and replace it\n          oldVnode = emptyNodeAt(oldVnode);\n        }\n        // replacing existing element\n        var oldElm = oldVnode.elm;\n        var parentElm$1 = nodeOps.parentNode(oldElm);\n        createElm(\n          vnode,\n          insertedVnodeQueue,\n          // extremely rare edge case: do not insert if old element is in a\n          // leaving transition. Only happens when combining transition +\n          // keep-alive + HOCs. (#4590)\n          oldElm._leaveCb ? null : parentElm$1,\n          nodeOps.nextSibling(oldElm)\n        );\n\n        if (isDef(vnode.parent)) {\n          // component root element replaced.\n          // update parent placeholder node element, recursively\n          var ancestor = vnode.parent;\n          while (ancestor) {\n            ancestor.elm = vnode.elm;\n            ancestor = ancestor.parent;\n          }\n          if (isPatchable(vnode)) {\n            for (var i = 0; i < cbs.create.length; ++i) {\n              cbs.create[i](emptyNode, vnode.parent);\n            }\n          }\n        }\n\n        if (isDef(parentElm$1)) {\n          removeVnodes(parentElm$1, [oldVnode], 0, 0);\n        } else if (isDef(oldVnode.tag)) {\n          invokeDestroyHook(oldVnode);\n        }\n      }\n    }\n\n    invokeInsertHook(vnode, insertedVnodeQueue, isInitialPatch);\n    return vnode.elm\n  }\n}\n\n/*  */\n\nvar directives = {\n  create: updateDirectives,\n  update: updateDirectives,\n  destroy: function unbindDirectives (vnode) {\n    updateDirectives(vnode, emptyNode);\n  }\n};\n\nfunction updateDirectives (oldVnode, vnode) {\n  if (oldVnode.data.directives || vnode.data.directives) {\n    _update(oldVnode, vnode);\n  }\n}\n\nfunction _update (oldVnode, vnode) {\n  var isCreate = oldVnode === emptyNode;\n  var isDestroy = vnode === emptyNode;\n  var oldDirs = normalizeDirectives$1(oldVnode.data.directives, oldVnode.context);\n  var newDirs = normalizeDirectives$1(vnode.data.directives, vnode.context);\n\n  var dirsWithInsert = [];\n  var dirsWithPostpatch = [];\n\n  var key, oldDir, dir;\n  for (key in newDirs) {\n    oldDir = oldDirs[key];\n    dir = newDirs[key];\n    if (!oldDir) {\n      // new directive, bind\n      callHook$1(dir, 'bind', vnode, oldVnode);\n      if (dir.def && dir.def.inserted) {\n        dirsWithInsert.push(dir);\n      }\n    } else {\n      // existing directive, update\n      dir.oldValue = oldDir.value;\n      callHook$1(dir, 'update', vnode, oldVnode);\n      if (dir.def && dir.def.componentUpdated) {\n        dirsWithPostpatch.push(dir);\n      }\n    }\n  }\n\n  if (dirsWithInsert.length) {\n    var callInsert = function () {\n      for (var i = 0; i < dirsWithInsert.length; i++) {\n        callHook$1(dirsWithInsert[i], 'inserted', vnode, oldVnode);\n      }\n    };\n    if (isCreate) {\n      mergeVNodeHook(vnode.data.hook || (vnode.data.hook = {}), 'insert', callInsert);\n    } else {\n      callInsert();\n    }\n  }\n\n  if (dirsWithPostpatch.length) {\n    mergeVNodeHook(vnode.data.hook || (vnode.data.hook = {}), 'postpatch', function () {\n      for (var i = 0; i < dirsWithPostpatch.length; i++) {\n        callHook$1(dirsWithPostpatch[i], 'componentUpdated', vnode, oldVnode);\n      }\n    });\n  }\n\n  if (!isCreate) {\n    for (key in oldDirs) {\n      if (!newDirs[key]) {\n        // no longer present, unbind\n        callHook$1(oldDirs[key], 'unbind', oldVnode, oldVnode, isDestroy);\n      }\n    }\n  }\n}\n\nvar emptyModifiers = Object.create(null);\n\nfunction normalizeDirectives$1 (\n  dirs,\n  vm\n) {\n  var res = Object.create(null);\n  if (!dirs) {\n    return res\n  }\n  var i, dir;\n  for (i = 0; i < dirs.length; i++) {\n    dir = dirs[i];\n    if (!dir.modifiers) {\n      dir.modifiers = emptyModifiers;\n    }\n    res[getRawDirName(dir)] = dir;\n    dir.def = resolveAsset(vm.$options, 'directives', dir.name, true);\n  }\n  return res\n}\n\nfunction getRawDirName (dir) {\n  return dir.rawName || ((dir.name) + \".\" + (Object.keys(dir.modifiers || {}).join('.')))\n}\n\nfunction callHook$1 (dir, hook, vnode, oldVnode, isDestroy) {\n  var fn = dir.def && dir.def[hook];\n  if (fn) {\n    try {\n      fn(vnode.elm, dir, vnode, oldVnode, isDestroy);\n    } catch (e) {\n      handleError(e, vnode.context, (\"directive \" + (dir.name) + \" \" + hook + \" hook\"));\n    }\n  }\n}\n\nvar baseModules = [\n  ref,\n  directives\n];\n\n/*  */\n\nfunction updateAttrs (oldVnode, vnode) {\n  if (!oldVnode.data.attrs && !vnode.data.attrs) {\n    return\n  }\n  var key, cur, old;\n  var elm = vnode.elm;\n  var oldAttrs = oldVnode.data.attrs || {};\n  var attrs = vnode.data.attrs || {};\n  // clone observed objects, as the user probably wants to mutate it\n  if (attrs.__ob__) {\n    attrs = vnode.data.attrs = extend({}, attrs);\n  }\n\n  for (key in attrs) {\n    cur = attrs[key];\n    old = oldAttrs[key];\n    if (old !== cur) {\n      elm.setAttr(key, cur);\n    }\n  }\n  for (key in oldAttrs) {\n    if (attrs[key] == null) {\n      elm.setAttr(key);\n    }\n  }\n}\n\nvar attrs = {\n  create: updateAttrs,\n  update: updateAttrs\n};\n\n/*  */\n\nfunction updateClass (oldVnode, vnode) {\n  var el = vnode.elm;\n  var ctx = vnode.context;\n\n  var data = vnode.data;\n  var oldData = oldVnode.data;\n  if (!data.staticClass &&\n    !data.class &&\n    (!oldData || (!oldData.staticClass && !oldData.class))\n  ) {\n    return\n  }\n\n  var oldClassList = [];\n  // unlike web, weex vnode staticClass is an Array\n  var oldStaticClass = oldData.staticClass;\n  if (oldStaticClass) {\n    oldClassList.push.apply(oldClassList, oldStaticClass);\n  }\n  if (oldData.class) {\n    oldClassList.push.apply(oldClassList, oldData.class);\n  }\n\n  var classList = [];\n  // unlike web, weex vnode staticClass is an Array\n  var staticClass = data.staticClass;\n  if (staticClass) {\n    classList.push.apply(classList, staticClass);\n  }\n  if (data.class) {\n    classList.push.apply(classList, data.class);\n  }\n\n  var style = getStyle(oldClassList, classList, ctx);\n  for (var key in style) {\n    el.setStyle(key, style[key]);\n  }\n}\n\nfunction getStyle (oldClassList, classList, ctx) {\n  // style is a weex-only injected object\n  // compiled from <style> tags in weex files\n  var stylesheet = ctx.$options.style || {};\n  var result = {};\n  classList.forEach(function (name) {\n    var style = stylesheet[name];\n    extend(result, style);\n  });\n  oldClassList.forEach(function (name) {\n    var style = stylesheet[name];\n    for (var key in style) {\n      if (!result.hasOwnProperty(key)) {\n        result[key] = '';\n      }\n    }\n  });\n  return result\n}\n\nvar klass = {\n  create: updateClass,\n  update: updateClass\n};\n\n/*  */\n\nvar target$1;\n\nfunction add$1 (\n  event,\n  handler,\n  once,\n  capture\n) {\n  if (capture) {\n    console.log('Weex do not support event in bubble phase.');\n    return\n  }\n  if (once) {\n    var oldHandler = handler;\n    var _target = target$1; // save current target element in closure\n    handler = function (ev) {\n      var res = arguments.length === 1\n        ? oldHandler(ev)\n        : oldHandler.apply(null, arguments);\n      if (res !== null) {\n        remove$2(event, null, null, _target);\n      }\n    };\n  }\n  target$1.addEvent(event, handler);\n}\n\nfunction remove$2 (\n  event,\n  handler,\n  capture,\n  _target\n) {\n  (_target || target$1).removeEvent(event);\n}\n\nfunction updateDOMListeners (oldVnode, vnode) {\n  var isComponentRoot = !!vnode.componentOptions;\n  var oldOn = isComponentRoot ? oldVnode.data.nativeOn : oldVnode.data.on;\n  var on = isComponentRoot ? vnode.data.nativeOn : vnode.data.on;\n  if (!oldOn && !on) {\n    return\n  }\n  on = on || {};\n  oldOn = oldOn || {};\n  target$1 = vnode.elm;\n  updateListeners(on, oldOn, add$1, remove$2, vnode.context);\n}\n\nvar events = {\n  create: updateDOMListeners,\n  update: updateDOMListeners\n};\n\n/*  */\n\nvar normalize = cached(camelize);\n\nfunction createStyle (oldVnode, vnode) {\n  if (!vnode.data.staticStyle) {\n    updateStyle(oldVnode, vnode);\n    return\n  }\n  var elm = vnode.elm;\n  var staticStyle = vnode.data.staticStyle;\n  for (var name in staticStyle) {\n    if (staticStyle[name]) {\n      elm.setStyle(normalize(name), staticStyle[name]);\n    }\n  }\n  updateStyle(oldVnode, vnode);\n}\n\nfunction updateStyle (oldVnode, vnode) {\n  if (!oldVnode.data.style && !vnode.data.style) {\n    return\n  }\n  var cur, name;\n  var elm = vnode.elm;\n  var oldStyle = oldVnode.data.style || {};\n  var style = vnode.data.style || {};\n\n  var needClone = style.__ob__;\n\n  // handle array syntax\n  if (Array.isArray(style)) {\n    style = vnode.data.style = toObject$1(style);\n  }\n\n  // clone the style for future updates,\n  // in case the user mutates the style object in-place.\n  if (needClone) {\n    style = vnode.data.style = extend({}, style);\n  }\n\n  for (name in oldStyle) {\n    if (!style[name]) {\n      elm.setStyle(normalize(name), '');\n    }\n  }\n  for (name in style) {\n    cur = style[name];\n    elm.setStyle(normalize(name), cur);\n  }\n}\n\nfunction toObject$1 (arr) {\n  var res = {};\n  for (var i = 0; i < arr.length; i++) {\n    if (arr[i]) {\n      extend(res, arr[i]);\n    }\n  }\n  return res\n}\n\nvar style = {\n  create: createStyle,\n  update: updateStyle\n};\n\n/*  */\n\n/**\n * Add class with compatibility for SVG since classList is not supported on\n * SVG elements in IE\n */\n\n\n/**\n * Remove class with compatibility for SVG since classList is not supported on\n * SVG elements in IE\n */\n\n/*  */\n\nfunction resolveTransition (def$$1) {\n  if (!def$$1) {\n    return\n  }\n  /* istanbul ignore else */\n  if (typeof def$$1 === 'object') {\n    var res = {};\n    if (def$$1.css !== false) {\n      extend(res, autoCssTransition(def$$1.name || 'v'));\n    }\n    extend(res, def$$1);\n    return res\n  } else if (typeof def$$1 === 'string') {\n    return autoCssTransition(def$$1)\n  }\n}\n\nvar autoCssTransition = cached(function (name) {\n  return {\n    enterClass: (name + \"-enter\"),\n    enterToClass: (name + \"-enter-to\"),\n    enterActiveClass: (name + \"-enter-active\"),\n    leaveClass: (name + \"-leave\"),\n    leaveToClass: (name + \"-leave-to\"),\n    leaveActiveClass: (name + \"-leave-active\")\n  }\n});\n\n\n// Transition property/event sniffing\n\n\n\n\n// binding to window is necessary to make hot reload work in IE in strict mode\nvar raf = inBrowser && window.requestAnimationFrame\n  ? window.requestAnimationFrame.bind(window)\n  : setTimeout;\n\nvar transition = {\n  create: enter,\n  activate: enter,\n  remove: leave\n};\n\nfunction enter (_, vnode) {\n  var el = vnode.elm;\n\n  // call leave callback now\n  if (el._leaveCb) {\n    el._leaveCb.cancelled = true;\n    el._leaveCb();\n  }\n\n  var data = resolveTransition(vnode.data.transition);\n  if (!data) {\n    return\n  }\n\n  /* istanbul ignore if */\n  if (el._enterCb) {\n    return\n  }\n\n  var enterClass = data.enterClass;\n  var enterToClass = data.enterToClass;\n  var enterActiveClass = data.enterActiveClass;\n  var appearClass = data.appearClass;\n  var appearToClass = data.appearToClass;\n  var appearActiveClass = data.appearActiveClass;\n  var beforeEnter = data.beforeEnter;\n  var enter = data.enter;\n  var afterEnter = data.afterEnter;\n  var enterCancelled = data.enterCancelled;\n  var beforeAppear = data.beforeAppear;\n  var appear = data.appear;\n  var afterAppear = data.afterAppear;\n  var appearCancelled = data.appearCancelled;\n\n  var context = activeInstance;\n  var transitionNode = activeInstance.$vnode;\n  while (transitionNode && transitionNode.parent) {\n    transitionNode = transitionNode.parent;\n    context = transitionNode.context;\n  }\n\n  var isAppear = !context._isMounted || !vnode.isRootInsert;\n\n  if (isAppear && !appear && appear !== '') {\n    return\n  }\n\n  var startClass = isAppear ? appearClass : enterClass;\n  var toClass = isAppear ? appearToClass : enterToClass;\n  var activeClass = isAppear ? appearActiveClass : enterActiveClass;\n  var beforeEnterHook = isAppear ? (beforeAppear || beforeEnter) : beforeEnter;\n  var enterHook = isAppear ? (typeof appear === 'function' ? appear : enter) : enter;\n  var afterEnterHook = isAppear ? (afterAppear || afterEnter) : afterEnter;\n  var enterCancelledHook = isAppear ? (appearCancelled || enterCancelled) : enterCancelled;\n\n  var userWantsControl =\n    enterHook &&\n    // enterHook may be a bound method which exposes\n    // the length of original fn as _length\n    (enterHook._length || enterHook.length) > 1;\n\n  var stylesheet = vnode.context.$options.style || {};\n  var startState = stylesheet[startClass];\n  var transitionProperties = (stylesheet['@TRANSITION'] && stylesheet['@TRANSITION'][activeClass]) || {};\n  var endState = getEnterTargetState(el, stylesheet, startClass, toClass, activeClass, vnode.context);\n  var needAnimation = Object.keys(endState).length > 0;\n\n  var cb = el._enterCb = once(function () {\n    if (cb.cancelled) {\n      enterCancelledHook && enterCancelledHook(el);\n    } else {\n      afterEnterHook && afterEnterHook(el);\n    }\n    el._enterCb = null;\n  });\n\n  // We need to wait until the native element has been inserted, but currently\n  // there's no API to do that. So we have to wait \"one frame\" - not entirely\n  // sure if this is guaranteed to be enough (e.g. on slow devices?)\n  setTimeout(function () {\n    var parent = el.parentNode;\n    var pendingNode = parent && parent._pending && parent._pending[vnode.key];\n    if (pendingNode &&\n      pendingNode.context === vnode.context &&\n      pendingNode.tag === vnode.tag &&\n      pendingNode.elm._leaveCb\n    ) {\n      pendingNode.elm._leaveCb();\n    }\n    enterHook && enterHook(el, cb);\n\n    if (needAnimation) {\n      var animation = vnode.context.$requireWeexModule('animation');\n      animation.transition(el.ref, {\n        styles: endState,\n        duration: transitionProperties.duration || 0,\n        delay: transitionProperties.delay || 0,\n        timingFunction: transitionProperties.timingFunction || 'linear'\n      }, userWantsControl ? noop : cb);\n    } else if (!userWantsControl) {\n      cb();\n    }\n  }, 16);\n\n  // start enter transition\n  beforeEnterHook && beforeEnterHook(el);\n\n  if (startState) {\n    for (var key in startState) {\n      el.setStyle(key, startState[key]);\n    }\n  }\n\n  if (!needAnimation && !userWantsControl) {\n    cb();\n  }\n}\n\nfunction leave (vnode, rm) {\n  var el = vnode.elm;\n\n  // call enter callback now\n  if (el._enterCb) {\n    el._enterCb.cancelled = true;\n    el._enterCb();\n  }\n\n  var data = resolveTransition(vnode.data.transition);\n  if (!data) {\n    return rm()\n  }\n\n  if (el._leaveCb) {\n    return\n  }\n\n  var leaveClass = data.leaveClass;\n  var leaveToClass = data.leaveToClass;\n  var leaveActiveClass = data.leaveActiveClass;\n  var beforeLeave = data.beforeLeave;\n  var leave = data.leave;\n  var afterLeave = data.afterLeave;\n  var leaveCancelled = data.leaveCancelled;\n  var delayLeave = data.delayLeave;\n\n  var userWantsControl =\n    leave &&\n    // leave hook may be a bound method which exposes\n    // the length of original fn as _length\n    (leave._length || leave.length) > 1;\n\n  var stylesheet = vnode.context.$options.style || {};\n  var startState = stylesheet[leaveClass];\n  var endState = stylesheet[leaveToClass] || stylesheet[leaveActiveClass];\n  var transitionProperties = (stylesheet['@TRANSITION'] && stylesheet['@TRANSITION'][leaveActiveClass]) || {};\n\n  var cb = el._leaveCb = once(function () {\n    if (el.parentNode && el.parentNode._pending) {\n      el.parentNode._pending[vnode.key] = null;\n    }\n    if (cb.cancelled) {\n      leaveCancelled && leaveCancelled(el);\n    } else {\n      rm();\n      afterLeave && afterLeave(el);\n    }\n    el._leaveCb = null;\n  });\n\n  if (delayLeave) {\n    delayLeave(performLeave);\n  } else {\n    performLeave();\n  }\n\n  function performLeave () {\n    var animation = vnode.context.$requireWeexModule('animation');\n    // the delayed leave may have already been cancelled\n    if (cb.cancelled) {\n      return\n    }\n    // record leaving element\n    if (!vnode.data.show) {\n      (el.parentNode._pending || (el.parentNode._pending = {}))[vnode.key] = vnode;\n    }\n    beforeLeave && beforeLeave(el);\n\n    if (startState) {\n      animation.transition(el.ref, {\n        styles: startState\n      }, next);\n    } else {\n      next();\n    }\n\n    function next () {\n      animation.transition(el.ref, {\n        styles: endState,\n        duration: transitionProperties.duration || 0,\n        delay: transitionProperties.delay || 0,\n        timingFunction: transitionProperties.timingFunction || 'linear'\n      }, userWantsControl ? noop : cb);\n    }\n\n    leave && leave(el, cb);\n    if (!endState && !userWantsControl) {\n      cb();\n    }\n  }\n}\n\n// determine the target animation style for an entering transition.\nfunction getEnterTargetState (el, stylesheet, startClass, endClass, activeClass, vm) {\n  var targetState = {};\n  var startState = stylesheet[startClass];\n  var endState = stylesheet[endClass];\n  var activeState = stylesheet[activeClass];\n  // 1. fallback to element's default styling\n  if (startState) {\n    for (var key in startState) {\n      targetState[key] = el.style[key];\n      if (\n        process.env.NODE_ENV !== 'production' &&\n        targetState[key] == null &&\n        (!activeState || activeState[key] == null) &&\n        (!endState || endState[key] == null)\n      ) {\n        warn(\n          \"transition property \\\"\" + key + \"\\\" is declared in enter starting class (.\" + startClass + \"), \" +\n          \"but not declared anywhere in enter ending class (.\" + endClass + \"), \" +\n          \"enter active cass (.\" + activeClass + \") or the element's default styling. \" +\n          \"Note in Weex, CSS properties need explicit values to be transitionable.\"\n        );\n      }\n    }\n  }\n  // 2. if state is mixed in active state, extract them while excluding\n  //    transition properties\n  if (activeState) {\n    for (var key$1 in activeState) {\n      if (key$1.indexOf('transition') !== 0) {\n        targetState[key$1] = activeState[key$1];\n      }\n    }\n  }\n  // 3. explicit endState has highest priority\n  if (endState) {\n    extend(targetState, endState);\n  }\n  return targetState\n}\n\nvar platformModules = [\n  attrs,\n  klass,\n  events,\n  style,\n  transition\n];\n\n/*  */\n\n// the directive module should be applied last, after all\n// built-in modules have been applied.\nvar modules = platformModules.concat(baseModules);\n\nvar patch = createPatchFunction({\n  nodeOps: nodeOps,\n  modules: modules,\n  LONG_LIST_THRESHOLD: 10\n});\n\nvar platformDirectives = {\n};\n\n/*  */\n\n// Provides transition support for a single element/component.\n// supports transition mode (out-in / in-out)\n\nvar transitionProps = {\n  name: String,\n  appear: Boolean,\n  css: Boolean,\n  mode: String,\n  type: String,\n  enterClass: String,\n  leaveClass: String,\n  enterToClass: String,\n  leaveToClass: String,\n  enterActiveClass: String,\n  leaveActiveClass: String,\n  appearClass: String,\n  appearActiveClass: String,\n  appearToClass: String,\n  duration: [Number, String, Object]\n};\n\n// in case the child is also an abstract component, e.g. <keep-alive>\n// we want to recursively retrieve the real component to be rendered\nfunction getRealChild (vnode) {\n  var compOptions = vnode && vnode.componentOptions;\n  if (compOptions && compOptions.Ctor.options.abstract) {\n    return getRealChild(getFirstComponentChild(compOptions.children))\n  } else {\n    return vnode\n  }\n}\n\nfunction extractTransitionData (comp) {\n  var data = {};\n  var options = comp.$options;\n  // props\n  for (var key in options.propsData) {\n    data[key] = comp[key];\n  }\n  // events.\n  // extract listeners and pass them directly to the transition methods\n  var listeners = options._parentListeners;\n  for (var key$1 in listeners) {\n    data[camelize(key$1)] = listeners[key$1];\n  }\n  return data\n}\n\nfunction placeholder (h, rawChild) {\n  if (/\\d-keep-alive$/.test(rawChild.tag)) {\n    return h('keep-alive', {\n      props: rawChild.componentOptions.propsData\n    })\n  }\n}\n\nfunction hasParentTransition (vnode) {\n  while ((vnode = vnode.parent)) {\n    if (vnode.data.transition) {\n      return true\n    }\n  }\n}\n\nfunction isSameChild (child, oldChild) {\n  return oldChild.key === child.key && oldChild.tag === child.tag\n}\n\nfunction isAsyncPlaceholder (node) {\n  return node.isComment && node.asyncFactory\n}\n\nvar Transition$1 = {\n  name: 'transition',\n  props: transitionProps,\n  abstract: true,\n\n  render: function render (h) {\n    var this$1 = this;\n\n    var children = this.$options._renderChildren;\n    if (!children) {\n      return\n    }\n\n    // filter out text nodes (possible whitespaces)\n    children = children.filter(function (c) { return c.tag || isAsyncPlaceholder(c); });\n    /* istanbul ignore if */\n    if (!children.length) {\n      return\n    }\n\n    // warn multiple elements\n    if (process.env.NODE_ENV !== 'production' && children.length > 1) {\n      warn(\n        '<transition> can only be used on a single element. Use ' +\n        '<transition-group> for lists.',\n        this.$parent\n      );\n    }\n\n    var mode = this.mode;\n\n    // warn invalid mode\n    if (process.env.NODE_ENV !== 'production' &&\n      mode && mode !== 'in-out' && mode !== 'out-in'\n    ) {\n      warn(\n        'invalid <transition> mode: ' + mode,\n        this.$parent\n      );\n    }\n\n    var rawChild = children[0];\n\n    // if this is a component root node and the component's\n    // parent container node also has transition, skip.\n    if (hasParentTransition(this.$vnode)) {\n      return rawChild\n    }\n\n    // apply transition data to child\n    // use getRealChild() to ignore abstract components e.g. keep-alive\n    var child = getRealChild(rawChild);\n    /* istanbul ignore if */\n    if (!child) {\n      return rawChild\n    }\n\n    if (this._leaving) {\n      return placeholder(h, rawChild)\n    }\n\n    // ensure a key that is unique to the vnode type and to this transition\n    // component instance. This key will be used to remove pending leaving nodes\n    // during entering.\n    var id = \"__transition-\" + (this._uid) + \"-\";\n    child.key = child.key == null\n      ? child.isComment\n        ? id + 'comment'\n        : id + child.tag\n      : isPrimitive(child.key)\n        ? (String(child.key).indexOf(id) === 0 ? child.key : id + child.key)\n        : child.key;\n\n    var data = (child.data || (child.data = {})).transition = extractTransitionData(this);\n    var oldRawChild = this._vnode;\n    var oldChild = getRealChild(oldRawChild);\n\n    // mark v-show\n    // so that the transition module can hand over the control to the directive\n    if (child.data.directives && child.data.directives.some(function (d) { return d.name === 'show'; })) {\n      child.data.show = true;\n    }\n\n    if (\n      oldChild &&\n      oldChild.data &&\n      !isSameChild(child, oldChild) &&\n      !isAsyncPlaceholder(oldChild)\n    ) {\n      // replace old child transition data with fresh one\n      // important for dynamic transitions!\n      var oldData = oldChild && (oldChild.data.transition = extend({}, data));\n      // handle transition mode\n      if (mode === 'out-in') {\n        // return placeholder node and queue update when leave finishes\n        this._leaving = true;\n        mergeVNodeHook(oldData, 'afterLeave', function () {\n          this$1._leaving = false;\n          this$1.$forceUpdate();\n        });\n        return placeholder(h, rawChild)\n      } else if (mode === 'in-out') {\n        if (isAsyncPlaceholder(child)) {\n          return oldRawChild\n        }\n        var delayedLeave;\n        var performLeave = function () { delayedLeave(); };\n        mergeVNodeHook(data, 'afterEnter', performLeave);\n        mergeVNodeHook(data, 'enterCancelled', performLeave);\n        mergeVNodeHook(oldData, 'delayLeave', function (leave) { delayedLeave = leave; });\n      }\n    }\n\n    return rawChild\n  }\n};\n\n// reuse same transition component logic from web\n\nvar props = extend({\n  tag: String,\n  moveClass: String\n}, transitionProps);\n\ndelete props.mode;\n\nvar TransitionGroup = {\n  props: props,\n\n  created: function created () {\n    var dom = this.$requireWeexModule('dom');\n    this.getPosition = function (el) { return new Promise(function (resolve, reject) {\n      dom.getComponentRect(el.ref, function (res) {\n        if (!res.result) {\n          reject(new Error((\"failed to get rect for element: \" + (el.tag))));\n        } else {\n          resolve(res.size);\n        }\n      });\n    }); };\n\n    var animation = this.$requireWeexModule('animation');\n    this.animate = function (el, options) { return new Promise(function (resolve) {\n      animation.transition(el.ref, options, resolve);\n    }); };\n  },\n\n  render: function render (h) {\n    var tag = this.tag || this.$vnode.data.tag || 'span';\n    var map = Object.create(null);\n    var prevChildren = this.prevChildren = this.children;\n    var rawChildren = this.$slots.default || [];\n    var children = this.children = [];\n    var transitionData = extractTransitionData(this);\n\n    for (var i = 0; i < rawChildren.length; i++) {\n      var c = rawChildren[i];\n      if (c.tag) {\n        if (c.key != null && String(c.key).indexOf('__vlist') !== 0) {\n          children.push(c);\n          map[c.key] = c\n          ;(c.data || (c.data = {})).transition = transitionData;\n        } else if (process.env.NODE_ENV !== 'production') {\n          var opts = c.componentOptions;\n          var name = opts\n            ? (opts.Ctor.options.name || opts.tag)\n            : c.tag;\n          warn((\"<transition-group> children must be keyed: <\" + name + \">\"));\n        }\n      }\n    }\n\n    if (prevChildren) {\n      var kept = [];\n      var removed = [];\n      prevChildren.forEach(function (c) {\n        c.data.transition = transitionData;\n\n        // TODO: record before patch positions\n\n        if (map[c.key]) {\n          kept.push(c);\n        } else {\n          removed.push(c);\n        }\n      });\n      this.kept = h(tag, null, kept);\n      this.removed = removed;\n    }\n\n    return h(tag, null, children)\n  },\n\n  beforeUpdate: function beforeUpdate () {\n    // force removing pass\n    this.__patch__(\n      this._vnode,\n      this.kept,\n      false, // hydrating\n      true // removeOnly (!important, avoids unnecessary moves)\n    );\n    this._vnode = this.kept;\n  },\n\n  updated: function updated () {\n    var children = this.prevChildren;\n    var moveClass = this.moveClass || ((this.name || 'v') + '-move');\n    var moveData = children.length && this.getMoveData(children[0].context, moveClass);\n    if (!moveData) {\n      return\n    }\n\n    // TODO: finish implementing move animations once\n    // we have access to sync getComponentRect()\n\n    // children.forEach(callPendingCbs)\n\n    // Promise.all(children.map(c => {\n    //   const oldPos = c.data.pos\n    //   const newPos = c.data.newPos\n    //   const dx = oldPos.left - newPos.left\n    //   const dy = oldPos.top - newPos.top\n    //   if (dx || dy) {\n    //     c.data.moved = true\n    //     return this.animate(c.elm, {\n    //       styles: {\n    //         transform: `translate(${dx}px,${dy}px)`\n    //       }\n    //     })\n    //   }\n    // })).then(() => {\n    //   children.forEach(c => {\n    //     if (c.data.moved) {\n    //       this.animate(c.elm, {\n    //         styles: {\n    //           transform: ''\n    //         },\n    //         duration: moveData.duration || 0,\n    //         delay: moveData.delay || 0,\n    //         timingFunction: moveData.timingFunction || 'linear'\n    //       })\n    //     }\n    //   })\n    // })\n  },\n\n  methods: {\n    getMoveData: function getMoveData (context, moveClass) {\n      var stylesheet = context.$options.style || {};\n      return stylesheet['@TRANSITION'] && stylesheet['@TRANSITION'][moveClass]\n    }\n  }\n};\n\n// function callPendingCbs (c) {\n//   /* istanbul ignore if */\n//   if (c.elm._moveCb) {\n//     c.elm._moveCb()\n//   }\n//   /* istanbul ignore if */\n//   if (c.elm._enterCb) {\n//     c.elm._enterCb()\n//   }\n// }\n\nvar platformComponents = {\n  Transition: Transition$1,\n  TransitionGroup: TransitionGroup\n};\n\n/* globals renderer */\n\nvar isReservedTag = makeMap(\n  'template,script,style,element,content,slot,link,meta,svg,view,' +\n  'a,div,img,image,text,span,richtext,input,switch,textarea,spinner,select,' +\n  'slider,slider-neighbor,indicator,trisition,trisition-group,canvas,' +\n  'list,cell,header,loading,loading-indicator,refresh,scrollable,scroller,' +\n  'video,web,embed,tabbar,tabheader,datepicker,timepicker,marquee,countdown',\n  true\n);\n\n// Elements that you can, intentionally, leave open (and which close themselves)\n// more flexable than web\nvar canBeLeftOpenTag = makeMap(\n  'web,spinner,switch,video,textarea,canvas,' +\n  'indicator,marquee,countdown',\n  true\n);\n\nvar isUnaryTag = makeMap(\n  'embed,img,image,input,link,meta',\n  true\n);\n\nfunction mustUseProp () { /* console.log('mustUseProp') */ }\n\nfunction isUnknownElement () { /* console.log('isUnknownElement') */ }\n\nfunction query (el, document) {\n  // renderer is injected by weex factory wrapper\n  var placeholder = new renderer.Comment('root');\n  placeholder.hasAttribute = placeholder.removeAttribute = function () {}; // hack for patch\n  document.documentElement.appendChild(placeholder);\n  return placeholder\n}\n\n/*  */\n\n// install platform specific utils\nVue$2.config.mustUseProp = mustUseProp;\nVue$2.config.isReservedTag = isReservedTag;\nVue$2.config.isUnknownElement = isUnknownElement;\n\n// install platform runtime directives and components\nVue$2.options.directives = platformDirectives;\nVue$2.options.components = platformComponents;\n\n// install platform patch function\nVue$2.prototype.__patch__ = patch;\n\n// wrap mount\nVue$2.prototype.$mount = function (\n  el,\n  hydrating\n) {\n  return mountComponent(\n    this,\n    el && query(el, this.$document),\n    hydrating\n  )\n};\n\n// this entry is built and wrapped with a factory function\n// used to generate a fresh copy of Vue for every Weex instance.\n\nexports.Vue = Vue$2;\n\n}\n"
  },
  {
    "path": "packages/weex-vue-framework/index.js",
    "content": "'use strict';\n\nObject.defineProperty(exports, '__esModule', { value: true });\n\nvar latestNodeId = 1;\n\nfunction TextNode (text) {\n  this.instanceId = '';\n  this.nodeId = latestNodeId++;\n  this.parentNode = null;\n  this.nodeType = 3;\n  this.text = text;\n}\n\n// this will be preserved during build\nvar VueFactory = require('./factory');\n\nvar instances = {};\nvar modules = {};\nvar components = {};\n\nvar renderer = {\n  TextNode: TextNode,\n  instances: instances,\n  modules: modules,\n  components: components\n};\n\n/**\n * Prepare framework config, basically about the virtual-DOM and JS bridge.\n * @param {object} cfg\n */\nfunction init (cfg) {\n  renderer.Document = cfg.Document;\n  renderer.Element = cfg.Element;\n  renderer.Comment = cfg.Comment;\n  renderer.compileBundle = cfg.compileBundle;\n}\n\n/**\n * Reset framework config and clear all registrations.\n */\nfunction reset () {\n  clear(instances);\n  clear(modules);\n  clear(components);\n  delete renderer.Document;\n  delete renderer.Element;\n  delete renderer.Comment;\n  delete renderer.compileBundle;\n}\n\n/**\n * Delete all keys of an object.\n * @param {object} obj\n */\nfunction clear (obj) {\n  for (var key in obj) {\n    delete obj[key];\n  }\n}\n\n/**\n * Create an instance with id, code, config and external data.\n * @param {string} instanceId\n * @param {string} appCode\n * @param {object} config\n * @param {object} data\n * @param {object} env { info, config, services }\n */\nfunction createInstance (\n  instanceId,\n  appCode,\n  config,\n  data,\n  env\n) {\n  if ( appCode === void 0 ) appCode = '';\n  if ( config === void 0 ) config = {};\n  if ( env === void 0 ) env = {};\n\n  // Virtual-DOM object.\n  var document = new renderer.Document(instanceId, config.bundleUrl);\n\n  var instance = instances[instanceId] = {\n    instanceId: instanceId, config: config, data: data,\n    document: document\n  };\n\n  // Prepare native module getter and HTML5 Timer APIs.\n  var moduleGetter = genModuleGetter(instanceId);\n  var timerAPIs = getInstanceTimer(instanceId, moduleGetter);\n\n  // Prepare `weex` instance variable.\n  var weexInstanceVar = {\n    config: config,\n    document: document,\n    supports: supports,\n    requireModule: moduleGetter\n  };\n  Object.freeze(weexInstanceVar);\n\n  // Each instance has a independent `Vue` module instance\n  var Vue = instance.Vue = createVueModuleInstance(instanceId, moduleGetter);\n\n  // The function which create a closure the JS Bundle will run in.\n  // It will declare some instance variables like `Vue`, HTML5 Timer APIs etc.\n  var instanceVars = Object.assign({\n    Vue: Vue,\n    weex: weexInstanceVar,\n    // deprecated\n    __weex_require_module__: weexInstanceVar.requireModule // eslint-disable-line\n  }, timerAPIs, env.services);\n\n  if (!callFunctionNative(instanceVars, appCode)) {\n    // If failed to compile functionBody on native side,\n    // fallback to 'callFunction()'.\n    callFunction(instanceVars, appCode);\n  }\n\n  // Send `createFinish` signal to native.\n  instance.document.taskCenter.send('dom', { action: 'createFinish' }, []);\n}\n\n/**\n * Destroy an instance with id. It will make sure all memory of\n * this instance released and no more leaks.\n * @param {string} instanceId\n */\nfunction destroyInstance (instanceId) {\n  var instance = instances[instanceId];\n  if (instance && instance.app instanceof instance.Vue) {\n    instance.document.destroy();\n    instance.app.$destroy();\n  }\n  delete instances[instanceId];\n}\n\n/**\n * Refresh an instance with id and new top-level component data.\n * It will use `Vue.set` on all keys of the new data. So it's better\n * define all possible meaningful keys when instance created.\n * @param {string} instanceId\n * @param {object} data\n */\nfunction refreshInstance (instanceId, data) {\n  var instance = instances[instanceId];\n  if (!instance || !(instance.app instanceof instance.Vue)) {\n    return new Error((\"refreshInstance: instance \" + instanceId + \" not found!\"))\n  }\n  for (var key in data) {\n    instance.Vue.set(instance.app, key, data[key]);\n  }\n  // Finally `refreshFinish` signal needed.\n  instance.document.taskCenter.send('dom', { action: 'refreshFinish' }, []);\n}\n\n/**\n * Get the JSON object of the root element.\n * @param {string} instanceId\n */\nfunction getRoot (instanceId) {\n  var instance = instances[instanceId];\n  if (!instance || !(instance.app instanceof instance.Vue)) {\n    return new Error((\"getRoot: instance \" + instanceId + \" not found!\"))\n  }\n  return instance.app.$el.toJSON()\n}\n\nvar jsHandlers = {\n  fireEvent: function (id) {\n    var args = [], len = arguments.length - 1;\n    while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ];\n\n    return fireEvent.apply(void 0, [ instances[id] ].concat( args ))\n  },\n  callback: function (id) {\n    var args = [], len = arguments.length - 1;\n    while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ];\n\n    return callback.apply(void 0, [ instances[id] ].concat( args ))\n  }\n};\n\nfunction fireEvent (instance, nodeId, type, e, domChanges) {\n  var el = instance.document.getRef(nodeId);\n  if (el) {\n    return instance.document.fireEvent(el, type, e, domChanges)\n  }\n  return new Error((\"invalid element reference \\\"\" + nodeId + \"\\\"\"))\n}\n\nfunction callback (instance, callbackId, data, ifKeepAlive) {\n  var result = instance.document.taskCenter.callback(callbackId, data, ifKeepAlive);\n  instance.document.taskCenter.send('dom', { action: 'updateFinish' }, []);\n  return result\n}\n\n/**\n * Accept calls from native (event or callback).\n *\n * @param  {string} id\n * @param  {array} tasks list with `method` and `args`\n */\nfunction receiveTasks (id, tasks) {\n  var instance = instances[id];\n  if (instance && Array.isArray(tasks)) {\n    var results = [];\n    tasks.forEach(function (task) {\n      var handler = jsHandlers[task.method];\n      var args = [].concat( task.args );\n      /* istanbul ignore else */\n      if (typeof handler === 'function') {\n        args.unshift(id);\n        results.push(handler.apply(void 0, args));\n      }\n    });\n    return results\n  }\n  return new Error((\"invalid instance id \\\"\" + id + \"\\\" or tasks\"))\n}\n\n/**\n * Register native modules information.\n * @param {object} newModules\n */\nfunction registerModules (newModules) {\n  var loop = function ( name ) {\n    if (!modules[name]) {\n      modules[name] = {};\n    }\n    newModules[name].forEach(function (method) {\n      if (typeof method === 'string') {\n        modules[name][method] = true;\n      } else {\n        modules[name][method.name] = method.args;\n      }\n    });\n  };\n\n  for (var name in newModules) loop( name );\n}\n\n/**\n * Check whether the module or the method has been registered.\n * @param {String} module name\n * @param {String} method name (optional)\n */\nfunction isRegisteredModule (name, method) {\n  if (typeof method === 'string') {\n    return !!(modules[name] && modules[name][method])\n  }\n  return !!modules[name]\n}\n\n/**\n * Register native components information.\n * @param {array} newComponents\n */\nfunction registerComponents (newComponents) {\n  if (Array.isArray(newComponents)) {\n    newComponents.forEach(function (component) {\n      if (!component) {\n        return\n      }\n      if (typeof component === 'string') {\n        components[component] = true;\n      } else if (typeof component === 'object' && typeof component.type === 'string') {\n        components[component.type] = component;\n      }\n    });\n  }\n}\n\n/**\n * Check whether the component has been registered.\n * @param {String} component name\n */\nfunction isRegisteredComponent (name) {\n  return !!components[name]\n}\n\n/**\n * Detects whether Weex supports specific features.\n * @param {String} condition\n */\nfunction supports (condition) {\n  if (typeof condition !== 'string') { return null }\n\n  var res = condition.match(/^@(\\w+)\\/(\\w+)(\\.(\\w+))?$/i);\n  if (res) {\n    var type = res[1];\n    var name = res[2];\n    var method = res[4];\n    switch (type) {\n      case 'module': return isRegisteredModule(name, method)\n      case 'component': return isRegisteredComponent(name)\n    }\n  }\n\n  return null\n}\n\n/**\n * Create a fresh instance of Vue for each Weex instance.\n */\nfunction createVueModuleInstance (instanceId, moduleGetter) {\n  var exports = {};\n  VueFactory(exports, renderer);\n  var Vue = exports.Vue;\n\n  var instance = instances[instanceId];\n\n  // patch reserved tag detection to account for dynamically registered\n  // components\n  var isReservedTag = Vue.config.isReservedTag || (function () { return false; });\n  Vue.config.isReservedTag = function (name) {\n    return components[name] || isReservedTag(name)\n  };\n\n  // expose weex-specific info\n  Vue.prototype.$instanceId = instanceId;\n  Vue.prototype.$document = instance.document;\n\n  // expose weex native module getter on subVue prototype so that\n  // vdom runtime modules can access native modules via vnode.context\n  Vue.prototype.$requireWeexModule = moduleGetter;\n\n  // Hack `Vue` behavior to handle instance information and data\n  // before root component created.\n  Vue.mixin({\n    beforeCreate: function beforeCreate () {\n      var options = this.$options;\n      // root component (vm)\n      if (options.el) {\n        // set external data of instance\n        var dataOption = options.data;\n        var internalData = (typeof dataOption === 'function' ? dataOption() : dataOption) || {};\n        options.data = Object.assign(internalData, instance.data);\n        // record instance by id\n        instance.app = this;\n      }\n    }\n  });\n\n  /**\n   * @deprecated Just instance variable `weex.config`\n   * Get instance config.\n   * @return {object}\n   */\n  Vue.prototype.$getConfig = function () {\n    if (instance.app instanceof Vue) {\n      return instance.config\n    }\n  };\n\n  return Vue\n}\n\n/**\n * Generate native module getter. Each native module has several\n * methods to call. And all the behaviors is instance-related. So\n * this getter will return a set of methods which additionally\n * send current instance id to native when called.\n * @param  {string}  instanceId\n * @return {function}\n */\nfunction genModuleGetter (instanceId) {\n  var instance = instances[instanceId];\n  return function (name) {\n    var nativeModule = modules[name] || [];\n    var output = {};\n    var loop = function ( methodName ) {\n      Object.defineProperty(output, methodName, {\n        enumerable: true,\n        configurable: true,\n        get: function proxyGetter () {\n          return function () {\n            var args = [], len = arguments.length;\n            while ( len-- ) args[ len ] = arguments[ len ];\n\n            return instance.document.taskCenter.send('module', { module: name, method: methodName }, args)\n          }\n        },\n        set: function proxySetter (val) {\n          if (typeof val === 'function') {\n            return instance.document.taskCenter.send('module', { module: name, method: methodName }, [val])\n          }\n        }\n      });\n    };\n\n    for (var methodName in nativeModule) loop( methodName );\n    return output\n  }\n}\n\n/**\n * Generate HTML5 Timer APIs. An important point is that the callback\n * will be converted into callback id when sent to native. So the\n * framework can make sure no side effect of the callback happened after\n * an instance destroyed.\n * @param  {[type]} instanceId   [description]\n * @param  {[type]} moduleGetter [description]\n * @return {[type]}              [description]\n */\nfunction getInstanceTimer (instanceId, moduleGetter) {\n  var instance = instances[instanceId];\n  var timer = moduleGetter('timer');\n  var timerAPIs = {\n    setTimeout: function () {\n      var args = [], len = arguments.length;\n      while ( len-- ) args[ len ] = arguments[ len ];\n\n      var handler = function () {\n        args[0].apply(args, args.slice(2));\n      };\n\n      timer.setTimeout(handler, args[1]);\n      return instance.document.taskCenter.callbackManager.lastCallbackId.toString()\n    },\n    setInterval: function () {\n      var args = [], len = arguments.length;\n      while ( len-- ) args[ len ] = arguments[ len ];\n\n      var handler = function () {\n        args[0].apply(args, args.slice(2));\n      };\n\n      timer.setInterval(handler, args[1]);\n      return instance.document.taskCenter.callbackManager.lastCallbackId.toString()\n    },\n    clearTimeout: function (n) {\n      timer.clearTimeout(n);\n    },\n    clearInterval: function (n) {\n      timer.clearInterval(n);\n    }\n  };\n  return timerAPIs\n}\n\n/**\n * Call a new function body with some global objects.\n * @param  {object} globalObjects\n * @param  {string} code\n * @return {any}\n */\nfunction callFunction (globalObjects, body) {\n  var globalKeys = [];\n  var globalValues = [];\n  for (var key in globalObjects) {\n    globalKeys.push(key);\n    globalValues.push(globalObjects[key]);\n  }\n  globalKeys.push(body);\n\n  var result = new (Function.prototype.bind.apply( Function, [ null ].concat( globalKeys) ));\n  return result.apply(void 0, globalValues)\n}\n\n/**\n * Call a new function generated on the V8 native side.\n *\n * This function helps speed up bundle compiling. Normally, the V8\n * engine needs to download, parse, and compile a bundle on every\n * visit. If 'compileBundle()' is available on native side,\n * the downloding, parsing, and compiling steps would be skipped.\n * @param  {object} globalObjects\n * @param  {string} body\n * @return {boolean}\n */\nfunction callFunctionNative (globalObjects, body) {\n  if (typeof renderer.compileBundle !== 'function') {\n    return false\n  }\n\n  var fn = void 0;\n  var isNativeCompileOk = false;\n  var script = '(function (';\n  var globalKeys = [];\n  var globalValues = [];\n  for (var key in globalObjects) {\n    globalKeys.push(key);\n    globalValues.push(globalObjects[key]);\n  }\n  for (var i = 0; i < globalKeys.length - 1; ++i) {\n    script += globalKeys[i];\n    script += ',';\n  }\n  script += globalKeys[globalKeys.length - 1];\n  script += ') {';\n  script += body;\n  script += '} )';\n\n  try {\n    var weex = globalObjects.weex || {};\n    var config = weex.config || {};\n    fn = renderer.compileBundle(script,\n      config.bundleUrl,\n      config.bundleDigest,\n      config.codeCachePath);\n    if (fn && typeof fn === 'function') {\n      fn.apply(void 0, globalValues);\n      isNativeCompileOk = true;\n    }\n  } catch (e) {\n    console.error(e);\n  }\n\n  return isNativeCompileOk\n}\n\nexports.init = init;\nexports.reset = reset;\nexports.createInstance = createInstance;\nexports.destroyInstance = destroyInstance;\nexports.refreshInstance = refreshInstance;\nexports.getRoot = getRoot;\nexports.receiveTasks = receiveTasks;\nexports.registerModules = registerModules;\nexports.isRegisteredModule = isRegisteredModule;\nexports.registerComponents = registerComponents;\nexports.isRegisteredComponent = isRegisteredComponent;\nexports.supports = supports;\n"
  },
  {
    "path": "packages/weex-vue-framework/package.json",
    "content": "{\n  \"name\": \"weex-vue-framework\",\n  \"version\": \"2.1.9-weex.1\",\n  \"description\": \"Vue 2.0 Framework for Weex\",\n  \"main\": \"index.js\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/vuejs/vue.git\"\n  },\n  \"keywords\": [\n    \"vue\",\n    \"compiler\"\n  ],\n  \"author\": \"Evan You\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/vuejs/vue/issues\"\n  },\n  \"homepage\": \"https://github.com/vuejs/vue/tree/dev/packages/weex-vue-framework#readme\"\n}\n"
  },
  {
    "path": "src/compiler/codegen/events.js",
    "content": "/* @flow */\n\nconst fnExpRE = /^\\s*([\\w$_]+|\\([^)]*?\\))\\s*=>|^function\\s*\\(/\nconst simplePathRE = /^\\s*[A-Za-z_$][\\w$]*(?:\\.[A-Za-z_$][\\w$]*|\\['.*?']|\\[\".*?\"]|\\[\\d+]|\\[[A-Za-z_$][\\w$]*])*\\s*$/\n\n// keyCode aliases\nconst keyCodes: { [key: string]: number | Array<number> } = {\n  esc: 27,\n  tab: 9,\n  enter: 13,\n  space: 32,\n  up: 38,\n  left: 37,\n  right: 39,\n  down: 40,\n  'delete': [8, 46]\n}\n\n// #4868: modifiers that prevent the execution of the listener\n// need to explicitly return null so that we can determine whether to remove\n// the listener for .once\nconst genGuard = condition => `if(${condition})return null;`\n\nconst modifierCode: { [key: string]: string } = {\n  stop: '$event.stopPropagation();',\n  prevent: '$event.preventDefault();',\n  self: genGuard(`$event.target !== $event.currentTarget`),\n  ctrl: genGuard(`!$event.ctrlKey`),\n  shift: genGuard(`!$event.shiftKey`),\n  alt: genGuard(`!$event.altKey`),\n  meta: genGuard(`!$event.metaKey`),\n  left: genGuard(`'button' in $event && $event.button !== 0`),\n  middle: genGuard(`'button' in $event && $event.button !== 1`),\n  right: genGuard(`'button' in $event && $event.button !== 2`)\n}\n\nexport function genHandlers (\n  events: ASTElementHandlers,\n  isNative: boolean,\n  warn: Function\n): string {\n  let res = isNative ? 'nativeOn:{' : 'on:{'\n  for (const name in events) {\n    const handler = events[name]\n    // #5330: warn click.right, since right clicks do not actually fire click events.\n    if (process.env.NODE_ENV !== 'production' &&\n      name === 'click' &&\n      handler && handler.modifiers && handler.modifiers.right\n    ) {\n      warn(\n        `Use \"contextmenu\" instead of \"click.right\" since right clicks ` +\n        `do not actually fire \"click\" events.`\n      )\n    }\n    res += `\"${name}\":${genHandler(name, handler)},`\n  }\n  return res.slice(0, -1) + '}'\n}\n\nfunction genHandler (\n  name: string,\n  handler: ASTElementHandler | Array<ASTElementHandler>\n): string {\n  if (!handler) {\n    return 'function(){}'\n  }\n\n  if (Array.isArray(handler)) {\n    return `[${handler.map(handler => genHandler(name, handler)).join(',')}]`\n  }\n\n  const isMethodPath = simplePathRE.test(handler.value)\n  const isFunctionExpression = fnExpRE.test(handler.value)\n\n  if (!handler.modifiers) {\n    return isMethodPath || isFunctionExpression\n      ? handler.value\n      : `function($event){${handler.value}}` // inline statement\n  } else {\n    let code = ''\n    let genModifierCode = ''\n    const keys = []\n    for (const key in handler.modifiers) {\n      if (modifierCode[key]) {\n        genModifierCode += modifierCode[key]\n        // left/right\n        if (keyCodes[key]) {\n          keys.push(key)\n        }\n      } else {\n        keys.push(key)\n      }\n    }\n    if (keys.length) {\n      code += genKeyFilter(keys)\n    }\n    // Make sure modifiers like prevent and stop get executed after key filtering\n    if (genModifierCode) {\n      code += genModifierCode\n    }\n    const handlerCode = isMethodPath\n      ? handler.value + '($event)'\n      : isFunctionExpression\n        ? `(${handler.value})($event)`\n        : handler.value\n    return `function($event){${code}${handlerCode}}`\n  }\n}\n\nfunction genKeyFilter (keys: Array<string>): string {\n  return `if(!('button' in $event)&&${keys.map(genFilterCode).join('&&')})return null;`\n}\n\nfunction genFilterCode (key: string): string {\n  const keyVal = parseInt(key, 10)\n  if (keyVal) {\n    return `$event.keyCode!==${keyVal}`\n  }\n  const alias = keyCodes[key]\n  return `_k($event.keyCode,${JSON.stringify(key)}${alias ? ',' + JSON.stringify(alias) : ''})`\n}\n"
  },
  {
    "path": "src/compiler/codegen/index.js",
    "content": "/* @flow */\n\nimport { genHandlers } from './events'\nimport baseDirectives from '../directives/index'\nimport { camelize, no, extend } from 'shared/util'\nimport { baseWarn, pluckModuleFunction } from '../helpers'\n\ntype TransformFunction = (el: ASTElement, code: string) => string;\ntype DataGenFunction = (el: ASTElement) => string;\ntype DirectiveFunction = (el: ASTElement, dir: ASTDirective, warn: Function) => boolean;\n\nexport class CodegenState {\n  options: CompilerOptions;\n  warn: Function;\n  transforms: Array<TransformFunction>;\n  dataGenFns: Array<DataGenFunction>;\n  directives: { [key: string]: DirectiveFunction };\n  maybeComponent: (el: ASTElement) => boolean;\n  onceId: number;\n  staticRenderFns: Array<string>;\n\n  constructor (options: CompilerOptions) {\n    this.options = options\n    this.warn = options.warn || baseWarn\n    this.transforms = pluckModuleFunction(options.modules, 'transformCode')\n    this.dataGenFns = pluckModuleFunction(options.modules, 'genData')\n    this.directives = extend(extend({}, baseDirectives), options.directives)\n    const isReservedTag = options.isReservedTag || no\n    this.maybeComponent = (el: ASTElement) => !isReservedTag(el.tag)\n    this.onceId = 0\n    this.staticRenderFns = []\n  }\n}\n\nexport type CodegenResult = {\n  render: string,\n  staticRenderFns: Array<string>\n};\n\nexport function generate (\n  ast: ASTElement | void,\n  options: CompilerOptions\n): CodegenResult {\n  const state = new CodegenState(options)\n  const code = ast ? genElement(ast, state) : '_c(\"div\")'\n  return {\n    render: `with(this){return ${code}}`,\n    staticRenderFns: state.staticRenderFns\n  }\n}\n\nexport function genElement (el: ASTElement, state: CodegenState): string {\n  if (el.staticRoot && !el.staticProcessed) {\n    return genStatic(el, state)\n  } else if (el.once && !el.onceProcessed) {\n    return genOnce(el, state)\n  } else if (el.for && !el.forProcessed) {\n    return genFor(el, state)\n  } else if (el.if && !el.ifProcessed) {\n    return genIf(el, state)\n  } else if (el.tag === 'template' && !el.slotTarget) {\n    return genChildren(el, state) || 'void 0'\n  } else if (el.tag === 'slot') {\n    return genSlot(el, state)\n  } else {\n    // component or element\n    let code\n    if (el.component) {\n      code = genComponent(el.component, el, state)\n    } else {\n      const data = el.plain ? undefined : genData(el, state)\n\n      const children = el.inlineTemplate ? null : genChildren(el, state, true)\n      code = `_c('${el.tag}'${\n        data ? `,${data}` : '' // data\n      }${\n        children ? `,${children}` : '' // children\n      })`\n    }\n    // module transforms\n    for (let i = 0; i < state.transforms.length; i++) {\n      code = state.transforms[i](el, code)\n    }\n    return code\n  }\n}\n\n// hoist static sub-trees out\nfunction genStatic (el: ASTElement, state: CodegenState): string {\n  el.staticProcessed = true\n  state.staticRenderFns.push(`with(this){return ${genElement(el, state)}}`)\n  return `_m(${state.staticRenderFns.length - 1}${el.staticInFor ? ',true' : ''})`\n}\n\n// v-once\nfunction genOnce (el: ASTElement, state: CodegenState): string {\n  el.onceProcessed = true\n  if (el.if && !el.ifProcessed) {\n    return genIf(el, state)\n  } else if (el.staticInFor) {\n    let key = ''\n    let parent = el.parent\n    while (parent) {\n      if (parent.for) {\n        key = parent.key\n        break\n      }\n      parent = parent.parent\n    }\n    if (!key) {\n      process.env.NODE_ENV !== 'production' && state.warn(\n        `v-once can only be used inside v-for that is keyed. `\n      )\n      return genElement(el, state)\n    }\n    return `_o(${genElement(el, state)},${state.onceId++}${key ? `,${key}` : ``})`\n  } else {\n    return genStatic(el, state)\n  }\n}\n\nexport function genIf (\n  el: any,\n  state: CodegenState,\n  altGen?: Function,\n  altEmpty?: string\n): string {\n  el.ifProcessed = true // avoid recursion\n  return genIfConditions(el.ifConditions.slice(), state, altGen, altEmpty)\n}\n\nfunction genIfConditions (\n  conditions: ASTIfConditions,\n  state: CodegenState,\n  altGen?: Function,\n  altEmpty?: string\n): string {\n  if (!conditions.length) {\n    return altEmpty || '_e()'\n  }\n\n  const condition = conditions.shift()\n  if (condition.exp) {\n    return `(${condition.exp})?${\n      genTernaryExp(condition.block)\n    }:${\n      genIfConditions(conditions, state, altGen, altEmpty)\n    }`\n  } else {\n    return `${genTernaryExp(condition.block)}`\n  }\n\n  // v-if with v-once should generate code like (a)?_m(0):_m(1)\n  function genTernaryExp (el) {\n    return altGen\n      ? altGen(el, state)\n      : el.once\n        ? genOnce(el, state)\n        : genElement(el, state)\n  }\n}\n\nexport function genFor (\n  el: any,\n  state: CodegenState,\n  altGen?: Function,\n  altHelper?: string\n): string {\n  const exp = el.for\n  const alias = el.alias\n  const iterator1 = el.iterator1 ? `,${el.iterator1}` : ''\n  const iterator2 = el.iterator2 ? `,${el.iterator2}` : ''\n\n  if (process.env.NODE_ENV !== 'production' &&\n    state.maybeComponent(el) &&\n    el.tag !== 'slot' &&\n    el.tag !== 'template' &&\n    !el.key\n  ) {\n    state.warn(\n      `<${el.tag} v-for=\"${alias} in ${exp}\">: component lists rendered with ` +\n      `v-for should have explicit keys. ` +\n      `See https://vuejs.org/guide/list.html#key for more info.`,\n      true /* tip */\n    )\n  }\n\n  el.forProcessed = true // avoid recursion\n  return `${altHelper || '_l'}((${exp}),` +\n    `function(${alias}${iterator1}${iterator2}){` +\n      `return ${(altGen || genElement)(el, state)}` +\n    '})'\n}\n\nexport function genData (el: ASTElement, state: CodegenState): string {\n  let data = '{'\n\n  // directives first.\n  // directives may mutate the el's other properties before they are generated.\n  const dirs = genDirectives(el, state)\n  if (dirs) data += dirs + ','\n\n  // key\n  if (el.key) {\n    data += `key:${el.key},`\n  }\n  // ref\n  if (el.ref) {\n    data += `ref:${el.ref},`\n  }\n  if (el.refInFor) {\n    data += `refInFor:true,`\n  }\n  // pre\n  if (el.pre) {\n    data += `pre:true,`\n  }\n  // record original tag name for components using \"is\" attribute\n  if (el.component) {\n    data += `tag:\"${el.tag}\",`\n  }\n  // module data generation functions\n  for (let i = 0; i < state.dataGenFns.length; i++) {\n    data += state.dataGenFns[i](el)\n  }\n  // attributes\n  if (el.attrs) {\n    data += `attrs:{${genProps(el.attrs)}},`\n  }\n  // DOM props\n  if (el.props) {\n    data += `domProps:{${genProps(el.props)}},`\n  }\n  // event handlers\n  if (el.events) {\n    data += `${genHandlers(el.events, false, state.warn)},`\n  }\n  if (el.nativeEvents) {\n    data += `${genHandlers(el.nativeEvents, true, state.warn)},`\n  }\n  // slot target\n  if (el.slotTarget) {\n    data += `slot:${el.slotTarget},`\n  }\n  // scoped slots\n  if (el.scopedSlots) {\n    data += `${genScopedSlots(el.scopedSlots, state)},`\n  }\n  // component v-model\n  if (el.model) {\n    data += `model:{value:${\n      el.model.value\n    },callback:${\n      el.model.callback\n    },expression:${\n      el.model.expression\n    }},`\n  }\n  // inline-template\n  if (el.inlineTemplate) {\n    const inlineTemplate = genInlineTemplate(el, state)\n    if (inlineTemplate) {\n      data += `${inlineTemplate},`\n    }\n  }\n  data = data.replace(/,$/, '') + '}'\n  // v-bind data wrap\n  if (el.wrapData) {\n    data = el.wrapData(data)\n  }\n  // v-on data wrap\n  if (el.wrapListeners) {\n    data = el.wrapListeners(data)\n  }\n  return data\n}\n\nfunction genDirectives (el: ASTElement, state: CodegenState): string | void {\n  const dirs = el.directives\n  if (!dirs) return\n  let res = 'directives:['\n  let hasRuntime = false\n  let i, l, dir, needRuntime\n  for (i = 0, l = dirs.length; i < l; i++) {\n    dir = dirs[i]\n    needRuntime = true\n    const gen: DirectiveFunction = state.directives[dir.name]\n    if (gen) {\n      // compile-time directive that manipulates AST.\n      // returns true if it also needs a runtime counterpart.\n      needRuntime = !!gen(el, dir, state.warn)\n    }\n    if (needRuntime) {\n      hasRuntime = true\n      res += `{name:\"${dir.name}\",rawName:\"${dir.rawName}\"${\n        dir.value ? `,value:(${dir.value}),expression:${JSON.stringify(dir.value)}` : ''\n      }${\n        dir.arg ? `,arg:\"${dir.arg}\"` : ''\n      }${\n        dir.modifiers ? `,modifiers:${JSON.stringify(dir.modifiers)}` : ''\n      }},`\n    }\n  }\n  if (hasRuntime) {\n    return res.slice(0, -1) + ']'\n  }\n}\n\nfunction genInlineTemplate (el: ASTElement, state: CodegenState): ?string {\n  const ast = el.children[0]\n  if (process.env.NODE_ENV !== 'production' && (\n    el.children.length > 1 || ast.type !== 1\n  )) {\n    state.warn('Inline-template components must have exactly one child element.')\n  }\n  if (ast.type === 1) {\n    const inlineRenderFns = generate(ast, state.options)\n    return `inlineTemplate:{render:function(){${\n      inlineRenderFns.render\n    }},staticRenderFns:[${\n      inlineRenderFns.staticRenderFns.map(code => `function(){${code}}`).join(',')\n    }]}`\n  }\n}\n\nfunction genScopedSlots (\n  slots: { [key: string]: ASTElement },\n  state: CodegenState\n): string {\n  return `scopedSlots:_u([${\n    Object.keys(slots).map(key => {\n      return genScopedSlot(key, slots[key], state)\n    }).join(',')\n  }])`\n}\n\nfunction genScopedSlot (\n  key: string,\n  el: ASTElement,\n  state: CodegenState\n): string {\n  if (el.for && !el.forProcessed) {\n    return genForScopedSlot(key, el, state)\n  }\n  return `{key:${key},fn:function(${String(el.attrsMap.scope)}){` +\n    `return ${el.tag === 'template'\n      ? genChildren(el, state) || 'void 0'\n      : genElement(el, state)\n  }}}`\n}\n\nfunction genForScopedSlot (\n  key: string,\n  el: any,\n  state: CodegenState\n): string {\n  const exp = el.for\n  const alias = el.alias\n  const iterator1 = el.iterator1 ? `,${el.iterator1}` : ''\n  const iterator2 = el.iterator2 ? `,${el.iterator2}` : ''\n  el.forProcessed = true // avoid recursion\n  return `_l((${exp}),` +\n    `function(${alias}${iterator1}${iterator2}){` +\n      `return ${genScopedSlot(key, el, state)}` +\n    '})'\n}\n\nexport function genChildren (\n  el: ASTElement,\n  state: CodegenState,\n  checkSkip?: boolean,\n  altGenElement?: Function,\n  altGenNode?: Function\n): string | void {\n  const children = el.children\n  if (children.length) {\n    const el: any = children[0]\n    // optimize single v-for\n    if (children.length === 1 &&\n      el.for &&\n      el.tag !== 'template' &&\n      el.tag !== 'slot'\n    ) {\n      return (altGenElement || genElement)(el, state)\n    }\n    const normalizationType = checkSkip\n      ? getNormalizationType(children, state.maybeComponent)\n      : 0\n    const gen = altGenNode || genNode\n    return `[${children.map(c => gen(c, state)).join(',')}]${\n      normalizationType ? `,${normalizationType}` : ''\n    }`\n  }\n}\n\n// determine the normalization needed for the children array.\n// 0: no normalization needed\n// 1: simple normalization needed (possible 1-level deep nested array)\n// 2: full normalization needed\nfunction getNormalizationType (\n  children: Array<ASTNode>,\n  maybeComponent: (el: ASTElement) => boolean\n): number {\n  let res = 0\n  for (let i = 0; i < children.length; i++) {\n    const el: ASTNode = children[i]\n    if (el.type !== 1) {\n      continue\n    }\n    if (needsNormalization(el) ||\n        (el.ifConditions && el.ifConditions.some(c => needsNormalization(c.block)))) {\n      res = 2\n      break\n    }\n    if (maybeComponent(el) ||\n        (el.ifConditions && el.ifConditions.some(c => maybeComponent(c.block)))) {\n      res = 1\n    }\n  }\n  return res\n}\n\nfunction needsNormalization (el: ASTElement): boolean {\n  return el.for !== undefined || el.tag === 'template' || el.tag === 'slot'\n}\n\nfunction genNode (node: ASTNode, state: CodegenState): string {\n  if (node.type === 1) {\n    return genElement(node, state)\n  } if (node.type === 3 && node.isComment) {\n    return genComment(node)\n  } else {\n    return genText(node)\n  }\n}\n\nexport function genText (text: ASTText | ASTExpression): string {\n  return `_v(${text.type === 2\n    ? text.expression // no need for () because already wrapped in _s()\n    : transformSpecialNewlines(JSON.stringify(text.text))\n  })`\n}\n\nexport function genComment (comment: ASTText): string {\n  return `_e('${comment.text}')`\n}\n\nfunction genSlot (el: ASTElement, state: CodegenState): string {\n  const slotName = el.slotName || '\"default\"'\n  const children = genChildren(el, state)\n  let res = `_t(${slotName}${children ? `,${children}` : ''}`\n  const attrs = el.attrs && `{${el.attrs.map(a => `${camelize(a.name)}:${a.value}`).join(',')}}`\n  const bind = el.attrsMap['v-bind']\n  if ((attrs || bind) && !children) {\n    res += `,null`\n  }\n  if (attrs) {\n    res += `,${attrs}`\n  }\n  if (bind) {\n    res += `${attrs ? '' : ',null'},${bind}`\n  }\n  return res + ')'\n}\n\n// componentName is el.component, take it as argument to shun flow's pessimistic refinement\nfunction genComponent (\n  componentName: string,\n  el: ASTElement,\n  state: CodegenState\n): string {\n  const children = el.inlineTemplate ? null : genChildren(el, state, true)\n  return `_c(${componentName},${genData(el, state)}${\n    children ? `,${children}` : ''\n  })`\n}\n\nfunction genProps (props: Array<{ name: string, value: string }>): string {\n  let res = ''\n  for (let i = 0; i < props.length; i++) {\n    const prop = props[i]\n    res += `\"${prop.name}\":${transformSpecialNewlines(prop.value)},`\n  }\n  return res.slice(0, -1)\n}\n\n// #3895, #4268\nfunction transformSpecialNewlines (text: string): string {\n  return text\n    .replace(/\\u2028/g, '\\\\u2028')\n    .replace(/\\u2029/g, '\\\\u2029')\n}\n"
  },
  {
    "path": "src/compiler/create-compiler.js",
    "content": "/* @flow */\n\nimport { extend } from 'shared/util'\nimport { detectErrors } from './error-detector'\nimport { createCompileToFunctionFn } from './to-function'\n\nexport function createCompilerCreator (baseCompile: Function): Function {\n  return function createCompiler (baseOptions: CompilerOptions) {\n    function compile (\n      template: string,\n      options?: CompilerOptions\n    ): CompiledResult {\n      const finalOptions = Object.create(baseOptions)\n      const errors = []\n      const tips = []\n      finalOptions.warn = (msg, tip) => {\n        (tip ? tips : errors).push(msg)\n      }\n\n      if (options) {\n        // merge custom modules\n        if (options.modules) {\n          finalOptions.modules =\n            (baseOptions.modules || []).concat(options.modules)\n        }\n        // merge custom directives\n        if (options.directives) {\n          finalOptions.directives = extend(\n            Object.create(baseOptions.directives),\n            options.directives\n          )\n        }\n        // copy other options\n        for (const key in options) {\n          if (key !== 'modules' && key !== 'directives') {\n            finalOptions[key] = options[key]\n          }\n        }\n      }\n\n      const compiled = baseCompile(template, finalOptions)\n      if (process.env.NODE_ENV !== 'production') {\n        errors.push.apply(errors, detectErrors(compiled.ast))\n      }\n      compiled.errors = errors\n      compiled.tips = tips\n      return compiled\n    }\n\n    return {\n      compile,\n      compileToFunctions: createCompileToFunctionFn(compile)\n    }\n  }\n}\n"
  },
  {
    "path": "src/compiler/directives/bind.js",
    "content": "/* @flow */\n\nexport default function bind (el: ASTElement, dir: ASTDirective) {\n  el.wrapData = (code: string) => {\n    return `_b(${code},'${el.tag}',${dir.value},${\n      dir.modifiers && dir.modifiers.prop ? 'true' : 'false'\n    }${\n      dir.modifiers && dir.modifiers.sync ? ',true' : ''\n    })`\n  }\n}\n"
  },
  {
    "path": "src/compiler/directives/index.js",
    "content": "/* @flow */\n\nimport on from './on'\nimport bind from './bind'\nimport { noop } from 'shared/util'\n\nexport default {\n  on,\n  bind,\n  cloak: noop\n}\n"
  },
  {
    "path": "src/compiler/directives/model.js",
    "content": "/* @flow */\n\n/**\n * Cross-platform code generation for component v-model\n */\nexport function genComponentModel (\n  el: ASTElement,\n  value: string,\n  modifiers: ?ASTModifiers\n): ?boolean {\n  const { number, trim } = modifiers || {}\n\n  const baseValueExpression = '$$v'\n  let valueExpression = baseValueExpression\n  if (trim) {\n    valueExpression =\n      `(typeof ${baseValueExpression} === 'string'` +\n        `? ${baseValueExpression}.trim()` +\n        `: ${baseValueExpression})`\n  }\n  if (number) {\n    valueExpression = `_n(${valueExpression})`\n  }\n  const assignment = genAssignmentCode(value, valueExpression)\n\n  el.model = {\n    value: `(${value})`,\n    expression: `\"${value}\"`,\n    callback: `function (${baseValueExpression}) {${assignment}}`\n  }\n}\n\n/**\n * Cross-platform codegen helper for generating v-model value assignment code.\n */\nexport function genAssignmentCode (\n  value: string,\n  assignment: string\n): string {\n  const modelRs = parseModel(value)\n  if (modelRs.idx === null) {\n    return `${value}=${assignment}`\n  } else {\n    return `$set(${modelRs.exp}, ${modelRs.idx}, ${assignment})`\n  }\n}\n\n/**\n * parse directive model to do the array update transform. a[idx] = val => $$a.splice($$idx, 1, val)\n *\n * for loop possible cases:\n *\n * - test\n * - test[idx]\n * - test[test1[idx]]\n * - test[\"a\"][idx]\n * - xxx.test[a[a].test1[idx]]\n * - test.xxx.a[\"asa\"][test1[idx]]\n *\n */\n\nlet len, str, chr, index, expressionPos, expressionEndPos\n\nexport function parseModel (val: string): Object {\n  str = val\n  len = str.length\n  index = expressionPos = expressionEndPos = 0\n\n  if (val.indexOf('[') < 0 || val.lastIndexOf(']') < len - 1) {\n    return {\n      exp: val,\n      idx: null\n    }\n  }\n\n  while (!eof()) {\n    chr = next()\n    /* istanbul ignore if */\n    if (isStringStart(chr)) {\n      parseString(chr)\n    } else if (chr === 0x5B) {\n      parseBracket(chr)\n    }\n  }\n\n  return {\n    exp: val.substring(0, expressionPos),\n    idx: val.substring(expressionPos + 1, expressionEndPos)\n  }\n}\n\nfunction next (): number {\n  return str.charCodeAt(++index)\n}\n\nfunction eof (): boolean {\n  return index >= len\n}\n\nfunction isStringStart (chr: number): boolean {\n  return chr === 0x22 || chr === 0x27\n}\n\nfunction parseBracket (chr: number): void {\n  let inBracket = 1\n  expressionPos = index\n  while (!eof()) {\n    chr = next()\n    if (isStringStart(chr)) {\n      parseString(chr)\n      continue\n    }\n    if (chr === 0x5B) inBracket++\n    if (chr === 0x5D) inBracket--\n    if (inBracket === 0) {\n      expressionEndPos = index\n      break\n    }\n  }\n}\n\nfunction parseString (chr: number): void {\n  const stringQuote = chr\n  while (!eof()) {\n    chr = next()\n    if (chr === stringQuote) {\n      break\n    }\n  }\n}\n"
  },
  {
    "path": "src/compiler/directives/on.js",
    "content": "/* @flow */\n\nimport { warn } from 'core/util/index'\n\nexport default function on (el: ASTElement, dir: ASTDirective) {\n  if (process.env.NODE_ENV !== 'production' && dir.modifiers) {\n    warn(`v-on without argument does not support modifiers.`)\n  }\n  el.wrapListeners = (code: string) => `_g(${code},${dir.value})`\n}\n"
  },
  {
    "path": "src/compiler/error-detector.js",
    "content": "/* @flow */\n\nimport { dirRE, onRE } from './parser/index'\n\n// these keywords should not appear inside expressions, but operators like\n// typeof, instanceof and in are allowed\nconst prohibitedKeywordRE = new RegExp('\\\\b' + (\n  'do,if,for,let,new,try,var,case,else,with,await,break,catch,class,const,' +\n  'super,throw,while,yield,delete,export,import,return,switch,default,' +\n  'extends,finally,continue,debugger,function,arguments'\n).split(',').join('\\\\b|\\\\b') + '\\\\b')\n\n// these unary operators should not be used as property/method names\nconst unaryOperatorsRE = new RegExp('\\\\b' + (\n  'delete,typeof,void'\n).split(',').join('\\\\s*\\\\([^\\\\)]*\\\\)|\\\\b') + '\\\\s*\\\\([^\\\\)]*\\\\)')\n\n// check valid identifier for v-for\nconst identRE = /[A-Za-z_$][\\w$]*/\n\n// strip strings in expressions\nconst stripStringRE = /'(?:[^'\\\\]|\\\\.)*'|\"(?:[^\"\\\\]|\\\\.)*\"|`(?:[^`\\\\]|\\\\.)*\\$\\{|\\}(?:[^`\\\\]|\\\\.)*`|`(?:[^`\\\\]|\\\\.)*`/g\n\n// detect problematic expressions in a template\nexport function detectErrors (ast: ?ASTNode): Array<string> {\n  const errors: Array<string> = []\n  if (ast) {\n    checkNode(ast, errors)\n  }\n  return errors\n}\n\nfunction checkNode (node: ASTNode, errors: Array<string>) {\n  if (node.type === 1) {\n    for (const name in node.attrsMap) {\n      if (dirRE.test(name)) {\n        const value = node.attrsMap[name]\n        if (value) {\n          if (name === 'v-for') {\n            checkFor(node, `v-for=\"${value}\"`, errors)\n          } else if (onRE.test(name)) {\n            checkEvent(value, `${name}=\"${value}\"`, errors)\n          } else {\n            checkExpression(value, `${name}=\"${value}\"`, errors)\n          }\n        }\n      }\n    }\n    if (node.children) {\n      for (let i = 0; i < node.children.length; i++) {\n        checkNode(node.children[i], errors)\n      }\n    }\n  } else if (node.type === 2) {\n    checkExpression(node.expression, node.text, errors)\n  }\n}\n\nfunction checkEvent (exp: string, text: string, errors: Array<string>) {\n  const stipped = exp.replace(stripStringRE, '')\n  const keywordMatch: any = stipped.match(unaryOperatorsRE)\n  if (keywordMatch && stipped.charAt(keywordMatch.index - 1) !== '$') {\n    errors.push(\n      `avoid using JavaScript unary operator as property name: ` +\n      `\"${keywordMatch[0]}\" in expression ${text.trim()}`\n    )\n  }\n  checkExpression(exp, text, errors)\n}\n\nfunction checkFor (node: ASTElement, text: string, errors: Array<string>) {\n  checkExpression(node.for || '', text, errors)\n  checkIdentifier(node.alias, 'v-for alias', text, errors)\n  checkIdentifier(node.iterator1, 'v-for iterator', text, errors)\n  checkIdentifier(node.iterator2, 'v-for iterator', text, errors)\n}\n\nfunction checkIdentifier (ident: ?string, type: string, text: string, errors: Array<string>) {\n  if (typeof ident === 'string' && !identRE.test(ident)) {\n    errors.push(`invalid ${type} \"${ident}\" in expression: ${text.trim()}`)\n  }\n}\n\nfunction checkExpression (exp: string, text: string, errors: Array<string>) {\n  try {\n    new Function(`return ${exp}`)\n  } catch (e) {\n    const keywordMatch = exp.replace(stripStringRE, '').match(prohibitedKeywordRE)\n    if (keywordMatch) {\n      errors.push(\n        `avoid using JavaScript keyword as property name: ` +\n        `\"${keywordMatch[0]}\" in expression ${text.trim()}`\n      )\n    } else {\n      errors.push(`invalid expression: ${text.trim()}`)\n    }\n  }\n}\n"
  },
  {
    "path": "src/compiler/helpers.js",
    "content": "/* @flow */\n\nimport { parseFilters } from './parser/filter-parser'\n\nexport function baseWarn (msg: string) {\n  console.error(`[Vue compiler]: ${msg}`)\n}\n\nexport function pluckModuleFunction<F: Function> (\n  modules: ?Array<Object>,\n  key: string\n): Array<F> {\n  return modules\n    ? modules.map(m => m[key]).filter(_ => _)\n    : []\n}\n\nexport function addProp (el: ASTElement, name: string, value: string) {\n  (el.props || (el.props = [])).push({ name, value })\n}\n\nexport function addAttr (el: ASTElement, name: string, value: string) {\n  (el.attrs || (el.attrs = [])).push({ name, value })\n}\n\nexport function addDirective (\n  el: ASTElement,\n  name: string,\n  rawName: string,\n  value: string,\n  arg: ?string,\n  modifiers: ?ASTModifiers\n) {\n  (el.directives || (el.directives = [])).push({ name, rawName, value, arg, modifiers })\n}\n\nexport function addHandler (\n  el: ASTElement,\n  name: string,\n  value: string,\n  modifiers: ?ASTModifiers,\n  important?: boolean,\n  warn?: Function\n) {\n  // warn prevent and passive modifier\n  /* istanbul ignore if */\n  if (\n    process.env.NODE_ENV !== 'production' && warn &&\n    modifiers && modifiers.prevent && modifiers.passive\n  ) {\n    warn(\n      'passive and prevent can\\'t be used together. ' +\n      'Passive handler can\\'t prevent default event.'\n    )\n  }\n  // check capture modifier\n  if (modifiers && modifiers.capture) {\n    delete modifiers.capture\n    name = '!' + name // mark the event as captured\n  }\n  if (modifiers && modifiers.once) {\n    delete modifiers.once\n    name = '~' + name // mark the event as once\n  }\n  /* istanbul ignore if */\n  if (modifiers && modifiers.passive) {\n    delete modifiers.passive\n    name = '&' + name // mark the event as passive\n  }\n  let events\n  if (modifiers && modifiers.native) {\n    delete modifiers.native\n    events = el.nativeEvents || (el.nativeEvents = {})\n  } else {\n    events = el.events || (el.events = {})\n  }\n  const newHandler = { value, modifiers }\n  const handlers = events[name]\n  /* istanbul ignore if */\n  if (Array.isArray(handlers)) {\n    important ? handlers.unshift(newHandler) : handlers.push(newHandler)\n  } else if (handlers) {\n    events[name] = important ? [newHandler, handlers] : [handlers, newHandler]\n  } else {\n    events[name] = newHandler\n  }\n}\n\nexport function getBindingAttr (\n  el: ASTElement,\n  name: string,\n  getStatic?: boolean\n): ?string {\n  const dynamicValue =\n    getAndRemoveAttr(el, ':' + name) ||\n    getAndRemoveAttr(el, 'v-bind:' + name)\n  if (dynamicValue != null) {\n    return parseFilters(dynamicValue)\n  } else if (getStatic !== false) {\n    const staticValue = getAndRemoveAttr(el, name)\n    if (staticValue != null) {\n      return JSON.stringify(staticValue)\n    }\n  }\n}\n\nexport function getAndRemoveAttr (el: ASTElement, name: string): ?string {\n  let val\n  if ((val = el.attrsMap[name]) != null) {\n    const list = el.attrsList\n    for (let i = 0, l = list.length; i < l; i++) {\n      if (list[i].name === name) {\n        list.splice(i, 1)\n        break\n      }\n    }\n  }\n  return val\n}\n"
  },
  {
    "path": "src/compiler/index.js",
    "content": "/* @flow */\n\nimport { parse } from './parser/index'\nimport { optimize } from './optimizer'\nimport { generate } from './codegen/index'\nimport { createCompilerCreator } from './create-compiler'\n\n// `createCompilerCreator` allows creating compilers that use alternative\n// parser/optimizer/codegen, e.g the SSR optimizing compiler.\n// Here we just export a default compiler using the default parts.\nexport const createCompiler = createCompilerCreator(function baseCompile (\n  template: string,\n  options: CompilerOptions\n): CompiledResult {\n  const ast = parse(template.trim(), options)\n  optimize(ast, options)\n  const code = generate(ast, options)\n  return {\n    ast,\n    render: code.render,\n    staticRenderFns: code.staticRenderFns\n  }\n})\n"
  },
  {
    "path": "src/compiler/optimizer.js",
    "content": "/* @flow */\n\nimport { makeMap, isBuiltInTag, cached, no } from 'shared/util'\n\nlet isStaticKey\nlet isPlatformReservedTag\n\nconst genStaticKeysCached = cached(genStaticKeys)\n\n/**\n * Goal of the optimizer: walk the generated template AST tree\n * and detect sub-trees that are purely static, i.e. parts of\n * the DOM that never needs to change.\n *\n * Once we detect these sub-trees, we can:\n *\n * 1. Hoist them into constants, so that we no longer need to\n *    create fresh nodes for them on each re-render;\n * 2. Completely skip them in the patching process.\n */\nexport function optimize (root: ?ASTElement, options: CompilerOptions) {\n  if (!root) return\n  isStaticKey = genStaticKeysCached(options.staticKeys || '')\n  isPlatformReservedTag = options.isReservedTag || no\n  // first pass: mark all non-static nodes.\n  markStatic(root)\n  // second pass: mark static roots.\n  markStaticRoots(root, false)\n}\n\nfunction genStaticKeys (keys: string): Function {\n  return makeMap(\n    'type,tag,attrsList,attrsMap,plain,parent,children,attrs' +\n    (keys ? ',' + keys : '')\n  )\n}\n\nfunction markStatic (node: ASTNode) {\n  node.static = isStatic(node)\n  if (node.type === 1) {\n    // do not make component slot content static. this avoids\n    // 1. components not able to mutate slot nodes\n    // 2. static slot content fails for hot-reloading\n    if (\n      !isPlatformReservedTag(node.tag) &&\n      node.tag !== 'slot' &&\n      node.attrsMap['inline-template'] == null\n    ) {\n      return\n    }\n    for (let i = 0, l = node.children.length; i < l; i++) {\n      const child = node.children[i]\n      markStatic(child)\n      if (!child.static) {\n        node.static = false\n      }\n    }\n    if (node.ifConditions) {\n      for (let i = 1, l = node.ifConditions.length; i < l; i++) {\n        const block = node.ifConditions[i].block\n        markStatic(block)\n        if (!block.static) {\n          node.static = false\n        }\n      }\n    }\n  }\n}\n\nfunction markStaticRoots (node: ASTNode, isInFor: boolean) {\n  if (node.type === 1) {\n    if (node.static || node.once) {\n      node.staticInFor = isInFor\n    }\n    // For a node to qualify as a static root, it should have children that\n    // are not just static text. Otherwise the cost of hoisting out will\n    // outweigh the benefits and it's better off to just always render it fresh.\n    if (node.static && node.children.length && !(\n      node.children.length === 1 &&\n      node.children[0].type === 3\n    )) {\n      node.staticRoot = true\n      return\n    } else {\n      node.staticRoot = false\n    }\n    if (node.children) {\n      for (let i = 0, l = node.children.length; i < l; i++) {\n        markStaticRoots(node.children[i], isInFor || !!node.for)\n      }\n    }\n    if (node.ifConditions) {\n      for (let i = 1, l = node.ifConditions.length; i < l; i++) {\n        markStaticRoots(node.ifConditions[i].block, isInFor)\n      }\n    }\n  }\n}\n\nfunction isStatic (node: ASTNode): boolean {\n  if (node.type === 2) { // expression\n    return false\n  }\n  if (node.type === 3) { // text\n    return true\n  }\n  return !!(node.pre || (\n    !node.hasBindings && // no dynamic bindings\n    !node.if && !node.for && // not v-if or v-for or v-else\n    !isBuiltInTag(node.tag) && // not a built-in\n    isPlatformReservedTag(node.tag) && // not a component\n    !isDirectChildOfTemplateFor(node) &&\n    Object.keys(node).every(isStaticKey)\n  ))\n}\n\nfunction isDirectChildOfTemplateFor (node: ASTElement): boolean {\n  while (node.parent) {\n    node = node.parent\n    if (node.tag !== 'template') {\n      return false\n    }\n    if (node.for) {\n      return true\n    }\n  }\n  return false\n}\n"
  },
  {
    "path": "src/compiler/parser/entity-decoder.js",
    "content": "/* @flow */\n\nlet decoder\n\nexport default {\n  decode (html: string): string {\n    decoder = decoder || document.createElement('div')\n    decoder.innerHTML = html\n    return decoder.textContent\n  }\n}\n"
  },
  {
    "path": "src/compiler/parser/filter-parser.js",
    "content": "/* @flow */\n\nconst validDivisionCharRE = /[\\w).+\\-_$\\]]/\n\nexport function parseFilters (exp: string): string {\n  let inSingle = false\n  let inDouble = false\n  let inTemplateString = false\n  let inRegex = false\n  let curly = 0\n  let square = 0\n  let paren = 0\n  let lastFilterIndex = 0\n  let c, prev, i, expression, filters\n\n  for (i = 0; i < exp.length; i++) {\n    prev = c\n    c = exp.charCodeAt(i)\n    if (inSingle) {\n      if (c === 0x27 && prev !== 0x5C) inSingle = false\n    } else if (inDouble) {\n      if (c === 0x22 && prev !== 0x5C) inDouble = false\n    } else if (inTemplateString) {\n      if (c === 0x60 && prev !== 0x5C) inTemplateString = false\n    } else if (inRegex) {\n      if (c === 0x2f && prev !== 0x5C) inRegex = false\n    } else if (\n      c === 0x7C && // pipe\n      exp.charCodeAt(i + 1) !== 0x7C &&\n      exp.charCodeAt(i - 1) !== 0x7C &&\n      !curly && !square && !paren\n    ) {\n      if (expression === undefined) {\n        // first filter, end of expression\n        lastFilterIndex = i + 1\n        expression = exp.slice(0, i).trim()\n      } else {\n        pushFilter()\n      }\n    } else {\n      switch (c) {\n        case 0x22: inDouble = true; break         // \"\n        case 0x27: inSingle = true; break         // '\n        case 0x60: inTemplateString = true; break // `\n        case 0x28: paren++; break                 // (\n        case 0x29: paren--; break                 // )\n        case 0x5B: square++; break                // [\n        case 0x5D: square--; break                // ]\n        case 0x7B: curly++; break                 // {\n        case 0x7D: curly--; break                 // }\n      }\n      if (c === 0x2f) { // /\n        let j = i - 1\n        let p\n        // find first non-whitespace prev char\n        for (; j >= 0; j--) {\n          p = exp.charAt(j)\n          if (p !== ' ') break\n        }\n        if (!p || !validDivisionCharRE.test(p)) {\n          inRegex = true\n        }\n      }\n    }\n  }\n\n  if (expression === undefined) {\n    expression = exp.slice(0, i).trim()\n  } else if (lastFilterIndex !== 0) {\n    pushFilter()\n  }\n\n  function pushFilter () {\n    (filters || (filters = [])).push(exp.slice(lastFilterIndex, i).trim())\n    lastFilterIndex = i + 1\n  }\n\n  if (filters) {\n    for (i = 0; i < filters.length; i++) {\n      expression = wrapFilter(expression, filters[i])\n    }\n  }\n\n  return expression\n}\n\nfunction wrapFilter (exp: string, filter: string): string {\n  const i = filter.indexOf('(')\n  if (i < 0) {\n    // _f: resolveFilter\n    return `_f(\"${filter}\")(${exp})`\n  } else {\n    const name = filter.slice(0, i)\n    const args = filter.slice(i + 1)\n    return `_f(\"${name}\")(${exp},${args}`\n  }\n}\n"
  },
  {
    "path": "src/compiler/parser/html-parser.js",
    "content": "/**\n * Not type-checking this file because it's mostly vendor code.\n */\n\n/*!\n * HTML Parser By John Resig (ejohn.org)\n * Modified by Juriy \"kangax\" Zaytsev\n * Original code by Erik Arvidsson, Mozilla Public License\n * http://erik.eae.net/simplehtmlparser/simplehtmlparser.js\n */\n\nimport { makeMap, no } from 'shared/util'\nimport { isNonPhrasingTag } from 'web/compiler/util'\n\n// Regular Expressions for parsing tags and attributes\nconst singleAttrIdentifier = /([^\\s\"'<>/=]+)/\nconst singleAttrAssign = /(?:=)/\nconst singleAttrValues = [\n  // attr value double quotes\n  /\"([^\"]*)\"+/.source,\n  // attr value, single quotes\n  /'([^']*)'+/.source,\n  // attr value, no quotes\n  /([^\\s\"'=<>`]+)/.source\n]\nconst attribute = new RegExp(\n  '^\\\\s*' + singleAttrIdentifier.source +\n  '(?:\\\\s*(' + singleAttrAssign.source + ')' +\n  '\\\\s*(?:' + singleAttrValues.join('|') + '))?'\n)\n\n// could use https://www.w3.org/TR/1999/REC-xml-names-19990114/#NT-QName\n// but for Vue templates we can enforce a simple charset\nconst ncname = '[a-zA-Z_][\\\\w\\\\-\\\\.]*'\nconst qnameCapture = '((?:' + ncname + '\\\\:)?' + ncname + ')'\nconst startTagOpen = new RegExp('^<' + qnameCapture)\nconst startTagClose = /^\\s*(\\/?)>/\nconst endTag = new RegExp('^<\\\\/' + qnameCapture + '[^>]*>')\nconst doctype = /^<!DOCTYPE [^>]+>/i\nconst comment = /^<!--/\nconst conditionalComment = /^<!\\[/\n\nlet IS_REGEX_CAPTURING_BROKEN = false\n'x'.replace(/x(.)?/g, function (m, g) {\n  IS_REGEX_CAPTURING_BROKEN = g === ''\n})\n\n// Special Elements (can contain anything)\nexport const isPlainTextElement = makeMap('script,style,textarea', true)\nconst reCache = {}\n\nconst decodingMap = {\n  '&lt;': '<',\n  '&gt;': '>',\n  '&quot;': '\"',\n  '&amp;': '&',\n  '&#10;': '\\n'\n}\nconst encodedAttr = /&(?:lt|gt|quot|amp);/g\nconst encodedAttrWithNewLines = /&(?:lt|gt|quot|amp|#10);/g\n\n// #5992\nconst isIgnoreNewlineTag = makeMap('pre,textarea', true)\nconst shouldIgnoreFirstNewline = (tag, html) => tag && isIgnoreNewlineTag(tag) && html[0] === '\\n'\n\nfunction decodeAttr (value, shouldDecodeNewlines) {\n  const re = shouldDecodeNewlines ? encodedAttrWithNewLines : encodedAttr\n  return value.replace(re, match => decodingMap[match])\n}\n\nexport function parseHTML (html, options) {\n  const stack = []\n  const expectHTML = options.expectHTML\n  const isUnaryTag = options.isUnaryTag || no\n  const canBeLeftOpenTag = options.canBeLeftOpenTag || no\n  let index = 0\n  let last, lastTag\n  while (html) {\n    last = html\n    // Make sure we're not in a plaintext content element like script/style\n    if (!lastTag || !isPlainTextElement(lastTag)) {\n      if (shouldIgnoreFirstNewline(lastTag, html)) {\n        advance(1)\n      }\n      let textEnd = html.indexOf('<')\n      if (textEnd === 0) {\n        // Comment:\n        if (comment.test(html)) {\n          const commentEnd = html.indexOf('-->')\n\n          if (commentEnd >= 0) {\n            if (options.shouldKeepComment) {\n              options.comment(html.substring(4, commentEnd))\n            }\n            advance(commentEnd + 3)\n            continue\n          }\n        }\n\n        // http://en.wikipedia.org/wiki/Conditional_comment#Downlevel-revealed_conditional_comment\n        if (conditionalComment.test(html)) {\n          const conditionalEnd = html.indexOf(']>')\n\n          if (conditionalEnd >= 0) {\n            advance(conditionalEnd + 2)\n            continue\n          }\n        }\n\n        // Doctype:\n        const doctypeMatch = html.match(doctype)\n        if (doctypeMatch) {\n          advance(doctypeMatch[0].length)\n          continue\n        }\n\n        // End tag:\n        const endTagMatch = html.match(endTag)\n        if (endTagMatch) {\n          const curIndex = index\n          advance(endTagMatch[0].length)\n          parseEndTag(endTagMatch[1], curIndex, index)\n          continue\n        }\n\n        // Start tag:\n        const startTagMatch = parseStartTag()\n        if (startTagMatch) {\n          handleStartTag(startTagMatch)\n          continue\n        }\n      }\n\n      let text, rest, next\n      if (textEnd >= 0) {\n        rest = html.slice(textEnd)\n        while (\n          !endTag.test(rest) &&\n          !startTagOpen.test(rest) &&\n          !comment.test(rest) &&\n          !conditionalComment.test(rest)\n        ) {\n          // < in plain text, be forgiving and treat it as text\n          next = rest.indexOf('<', 1)\n          if (next < 0) break\n          textEnd += next\n          rest = html.slice(textEnd)\n        }\n        text = html.substring(0, textEnd)\n        advance(textEnd)\n      }\n\n      if (textEnd < 0) {\n        text = html\n        html = ''\n      }\n\n      if (options.chars && text) {\n        options.chars(text)\n      }\n    } else {\n      let endTagLength = 0\n      const stackedTag = lastTag.toLowerCase()\n      const reStackedTag = reCache[stackedTag] || (reCache[stackedTag] = new RegExp('([\\\\s\\\\S]*?)(</' + stackedTag + '[^>]*>)', 'i'))\n      const rest = html.replace(reStackedTag, function (all, text, endTag) {\n        endTagLength = endTag.length\n        if (!isPlainTextElement(stackedTag) && stackedTag !== 'noscript') {\n          text = text\n            .replace(/<!--([\\s\\S]*?)-->/g, '$1')\n            .replace(/<!\\[CDATA\\[([\\s\\S]*?)]]>/g, '$1')\n        }\n        if (shouldIgnoreFirstNewline(stackedTag, text)) {\n          text = text.slice(1)\n        }\n        if (options.chars) {\n          options.chars(text)\n        }\n        return ''\n      })\n      index += html.length - rest.length\n      html = rest\n      parseEndTag(stackedTag, index - endTagLength, index)\n    }\n\n    if (html === last) {\n      options.chars && options.chars(html)\n      if (process.env.NODE_ENV !== 'production' && !stack.length && options.warn) {\n        options.warn(`Mal-formatted tag at end of template: \"${html}\"`)\n      }\n      break\n    }\n  }\n\n  // Clean up any remaining tags\n  parseEndTag()\n\n  function advance (n) {\n    index += n\n    html = html.substring(n)\n  }\n\n  function parseStartTag () {\n    const start = html.match(startTagOpen)\n    if (start) {\n      const match = {\n        tagName: start[1],\n        attrs: [],\n        start: index\n      }\n      advance(start[0].length)\n      let end, attr\n      while (!(end = html.match(startTagClose)) && (attr = html.match(attribute))) {\n        advance(attr[0].length)\n        match.attrs.push(attr)\n      }\n      if (end) {\n        match.unarySlash = end[1]\n        advance(end[0].length)\n        match.end = index\n        return match\n      }\n    }\n  }\n\n  function handleStartTag (match) {\n    const tagName = match.tagName\n    const unarySlash = match.unarySlash\n\n    if (expectHTML) {\n      if (lastTag === 'p' && isNonPhrasingTag(tagName)) {\n        parseEndTag(lastTag)\n      }\n      if (canBeLeftOpenTag(tagName) && lastTag === tagName) {\n        parseEndTag(tagName)\n      }\n    }\n\n    const unary = isUnaryTag(tagName) || !!unarySlash\n\n    const l = match.attrs.length\n    const attrs = new Array(l)\n    for (let i = 0; i < l; i++) {\n      const args = match.attrs[i]\n      // hackish work around FF bug https://bugzilla.mozilla.org/show_bug.cgi?id=369778\n      if (IS_REGEX_CAPTURING_BROKEN && args[0].indexOf('\"\"') === -1) {\n        if (args[3] === '') { delete args[3] }\n        if (args[4] === '') { delete args[4] }\n        if (args[5] === '') { delete args[5] }\n      }\n      const value = args[3] || args[4] || args[5] || ''\n      attrs[i] = {\n        name: args[1],\n        value: decodeAttr(\n          value,\n          options.shouldDecodeNewlines\n        )\n      }\n    }\n\n    if (!unary) {\n      stack.push({ tag: tagName, lowerCasedTag: tagName.toLowerCase(), attrs: attrs })\n      lastTag = tagName\n    }\n\n    if (options.start) {\n      options.start(tagName, attrs, unary, match.start, match.end)\n    }\n  }\n\n  function parseEndTag (tagName, start, end) {\n    let pos, lowerCasedTagName\n    if (start == null) start = index\n    if (end == null) end = index\n\n    if (tagName) {\n      lowerCasedTagName = tagName.toLowerCase()\n    }\n\n    // Find the closest opened tag of the same type\n    if (tagName) {\n      for (pos = stack.length - 1; pos >= 0; pos--) {\n        if (stack[pos].lowerCasedTag === lowerCasedTagName) {\n          break\n        }\n      }\n    } else {\n      // If no tag name is provided, clean shop\n      pos = 0\n    }\n\n    if (pos >= 0) {\n      // Close all the open elements, up the stack\n      for (let i = stack.length - 1; i >= pos; i--) {\n        if (process.env.NODE_ENV !== 'production' &&\n          (i > pos || !tagName) &&\n          options.warn\n        ) {\n          options.warn(\n            `tag <${stack[i].tag}> has no matching end tag.`\n          )\n        }\n        if (options.end) {\n          options.end(stack[i].tag, start, end)\n        }\n      }\n\n      // Remove the open elements from the stack\n      stack.length = pos\n      lastTag = pos && stack[pos - 1].tag\n    } else if (lowerCasedTagName === 'br') {\n      if (options.start) {\n        options.start(tagName, [], true, start, end)\n      }\n    } else if (lowerCasedTagName === 'p') {\n      if (options.start) {\n        options.start(tagName, [], false, start, end)\n      }\n      if (options.end) {\n        options.end(tagName, start, end)\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "src/compiler/parser/index.js",
    "content": "/* @flow */\n\nimport he from 'he'\nimport { parseHTML } from './html-parser'\nimport { parseText } from './text-parser'\nimport { parseFilters } from './filter-parser'\nimport { cached, no, camelize } from 'shared/util'\nimport { genAssignmentCode } from '../directives/model'\nimport { isIE, isEdge, isServerRendering } from 'core/util/env'\n\nimport {\n  addProp,\n  addAttr,\n  baseWarn,\n  addHandler,\n  addDirective,\n  getBindingAttr,\n  getAndRemoveAttr,\n  pluckModuleFunction\n} from '../helpers'\n\nexport const onRE = /^@|^v-on:/\nexport const dirRE = /^v-|^@|^:/\nexport const forAliasRE = /(.*?)\\s+(?:in|of)\\s+(.*)/\nexport const forIteratorRE = /\\((\\{[^}]*\\}|[^,]*),([^,]*)(?:,([^,]*))?\\)/\n\nconst argRE = /:(.*)$/\nconst bindRE = /^:|^v-bind:/\nconst modifierRE = /\\.[^.]+/g\n\nconst decodeHTMLCached = cached(he.decode)\n\n// configurable state\nexport let warn\nlet delimiters\nlet transforms\nlet preTransforms\nlet postTransforms\nlet platformIsPreTag\nlet platformMustUseProp\nlet platformGetTagNamespace\n\n/**\n * Convert HTML string to AST.\n */\nexport function parse (\n  template: string,\n  options: CompilerOptions\n): ASTElement | void {\n  warn = options.warn || baseWarn\n\n  platformIsPreTag = options.isPreTag || no\n  platformMustUseProp = options.mustUseProp || no\n  platformGetTagNamespace = options.getTagNamespace || no\n\n  transforms = pluckModuleFunction(options.modules, 'transformNode')\n  preTransforms = pluckModuleFunction(options.modules, 'preTransformNode')\n  postTransforms = pluckModuleFunction(options.modules, 'postTransformNode')\n\n  delimiters = options.delimiters\n\n  const stack = []\n  const preserveWhitespace = options.preserveWhitespace !== false\n  let root\n  let currentParent\n  let inVPre = false\n  let inPre = false\n  let warned = false\n\n  function warnOnce (msg) {\n    if (!warned) {\n      warned = true\n      warn(msg)\n    }\n  }\n\n  function endPre (element) {\n    // check pre state\n    if (element.pre) {\n      inVPre = false\n    }\n    if (platformIsPreTag(element.tag)) {\n      inPre = false\n    }\n  }\n\n  parseHTML(template, {\n    warn,\n    expectHTML: options.expectHTML,\n    isUnaryTag: options.isUnaryTag,\n    canBeLeftOpenTag: options.canBeLeftOpenTag,\n    shouldDecodeNewlines: options.shouldDecodeNewlines,\n    shouldKeepComment: options.comments,\n    start (tag, attrs, unary) {\n      // check namespace.\n      // inherit parent ns if there is one\n      const ns = (currentParent && currentParent.ns) || platformGetTagNamespace(tag)\n\n      // handle IE svg bug\n      /* istanbul ignore if */\n      if (isIE && ns === 'svg') {\n        attrs = guardIESVGBug(attrs)\n      }\n\n      const element: ASTElement = {\n        type: 1,\n        tag,\n        attrsList: attrs,\n        attrsMap: makeAttrsMap(attrs),\n        parent: currentParent,\n        children: []\n      }\n      if (ns) {\n        element.ns = ns\n      }\n\n      if (isForbiddenTag(element) && !isServerRendering()) {\n        element.forbidden = true\n        process.env.NODE_ENV !== 'production' && warn(\n          'Templates should only be responsible for mapping the state to the ' +\n          'UI. Avoid placing tags with side-effects in your templates, such as ' +\n          `<${tag}>` + ', as they will not be parsed.'\n        )\n      }\n\n      // apply pre-transforms\n      for (let i = 0; i < preTransforms.length; i++) {\n        preTransforms[i](element, options)\n      }\n\n      if (!inVPre) {\n        processPre(element)\n        if (element.pre) {\n          inVPre = true\n        }\n      }\n      if (platformIsPreTag(element.tag)) {\n        inPre = true\n      }\n      if (inVPre) {\n        processRawAttrs(element)\n      } else {\n        processFor(element)\n        processIf(element)\n        processOnce(element)\n        processKey(element)\n\n        // determine whether this is a plain element after\n        // removing structural attributes\n        element.plain = !element.key && !attrs.length\n\n        processRef(element)\n        processSlot(element)\n        processComponent(element)\n        for (let i = 0; i < transforms.length; i++) {\n          transforms[i](element, options)\n        }\n        processAttrs(element)\n      }\n\n      function checkRootConstraints (el) {\n        if (process.env.NODE_ENV !== 'production') {\n          if (el.tag === 'slot' || el.tag === 'template') {\n            warnOnce(\n              `Cannot use <${el.tag}> as component root element because it may ` +\n              'contain multiple nodes.'\n            )\n          }\n          if (el.attrsMap.hasOwnProperty('v-for')) {\n            warnOnce(\n              'Cannot use v-for on stateful component root element because ' +\n              'it renders multiple elements.'\n            )\n          }\n        }\n      }\n\n      // tree management\n      if (!root) {\n        root = element\n        checkRootConstraints(root)\n      } else if (!stack.length) {\n        // allow root elements with v-if, v-else-if and v-else\n        if (root.if && (element.elseif || element.else)) {\n          checkRootConstraints(element)\n          addIfCondition(root, {\n            exp: element.elseif,\n            block: element\n          })\n        } else if (process.env.NODE_ENV !== 'production') {\n          warnOnce(\n            `Component template should contain exactly one root element. ` +\n            `If you are using v-if on multiple elements, ` +\n            `use v-else-if to chain them instead.`\n          )\n        }\n      }\n      if (currentParent && !element.forbidden) {\n        if (element.elseif || element.else) {\n          processIfConditions(element, currentParent)\n        } else if (element.slotScope) { // scoped slot\n          currentParent.plain = false\n          const name = element.slotTarget || '\"default\"'\n          ;(currentParent.scopedSlots || (currentParent.scopedSlots = {}))[name] = element\n        } else {\n          currentParent.children.push(element)\n          element.parent = currentParent\n        }\n      }\n      if (!unary) {\n        currentParent = element\n        stack.push(element)\n      } else {\n        endPre(element)\n      }\n      // apply post-transforms\n      for (let i = 0; i < postTransforms.length; i++) {\n        postTransforms[i](element, options)\n      }\n    },\n\n    end () {\n      // remove trailing whitespace\n      const element = stack[stack.length - 1]\n      const lastNode = element.children[element.children.length - 1]\n      if (lastNode && lastNode.type === 3 && lastNode.text === ' ' && !inPre) {\n        element.children.pop()\n      }\n      // pop stack\n      stack.length -= 1\n      currentParent = stack[stack.length - 1]\n      endPre(element)\n    },\n\n    chars (text: string) {\n      if (!currentParent) {\n        if (process.env.NODE_ENV !== 'production') {\n          if (text === template) {\n            warnOnce(\n              'Component template requires a root element, rather than just text.'\n            )\n          } else if ((text = text.trim())) {\n            warnOnce(\n              `text \"${text}\" outside root element will be ignored.`\n            )\n          }\n        }\n        return\n      }\n      // IE textarea placeholder bug\n      /* istanbul ignore if */\n      if (isIE &&\n        currentParent.tag === 'textarea' &&\n        currentParent.attrsMap.placeholder === text\n      ) {\n        return\n      }\n      const children = currentParent.children\n      text = inPre || text.trim()\n        ? isTextTag(currentParent) ? text : decodeHTMLCached(text)\n        // only preserve whitespace if its not right after a starting tag\n        : preserveWhitespace && children.length ? ' ' : ''\n      if (text) {\n        let expression\n        if (!inVPre && text !== ' ' && (expression = parseText(text, delimiters))) {\n          children.push({\n            type: 2,\n            expression,\n            text\n          })\n        } else if (text !== ' ' || !children.length || children[children.length - 1].text !== ' ') {\n          children.push({\n            type: 3,\n            text\n          })\n        }\n      }\n    },\n    comment (text: string) {\n      currentParent.children.push({\n        type: 3,\n        text,\n        isComment: true\n      })\n    }\n  })\n  return root\n}\n\nfunction processPre (el) {\n  if (getAndRemoveAttr(el, 'v-pre') != null) {\n    el.pre = true\n  }\n}\n\nfunction processRawAttrs (el) {\n  const l = el.attrsList.length\n  if (l) {\n    const attrs = el.attrs = new Array(l)\n    for (let i = 0; i < l; i++) {\n      attrs[i] = {\n        name: el.attrsList[i].name,\n        value: JSON.stringify(el.attrsList[i].value)\n      }\n    }\n  } else if (!el.pre) {\n    // non root node in pre blocks with no attributes\n    el.plain = true\n  }\n}\n\nfunction processKey (el) {\n  const exp = getBindingAttr(el, 'key')\n  if (exp) {\n    if (process.env.NODE_ENV !== 'production' && el.tag === 'template') {\n      warn(`<template> cannot be keyed. Place the key on real elements instead.`)\n    }\n    el.key = exp\n  }\n}\n\nfunction processRef (el) {\n  const ref = getBindingAttr(el, 'ref')\n  if (ref) {\n    el.ref = ref\n    el.refInFor = checkInFor(el)\n  }\n}\n\nfunction processFor (el) {\n  let exp\n  if ((exp = getAndRemoveAttr(el, 'v-for'))) {\n    const inMatch = exp.match(forAliasRE)\n    if (!inMatch) {\n      process.env.NODE_ENV !== 'production' && warn(\n        `Invalid v-for expression: ${exp}`\n      )\n      return\n    }\n    el.for = inMatch[2].trim()\n    const alias = inMatch[1].trim()\n    const iteratorMatch = alias.match(forIteratorRE)\n    if (iteratorMatch) {\n      el.alias = iteratorMatch[1].trim()\n      el.iterator1 = iteratorMatch[2].trim()\n      if (iteratorMatch[3]) {\n        el.iterator2 = iteratorMatch[3].trim()\n      }\n    } else {\n      el.alias = alias\n    }\n  }\n}\n\nfunction processIf (el) {\n  const exp = getAndRemoveAttr(el, 'v-if')\n  if (exp) {\n    el.if = exp\n    addIfCondition(el, {\n      exp: exp,\n      block: el\n    })\n  } else {\n    if (getAndRemoveAttr(el, 'v-else') != null) {\n      el.else = true\n    }\n    const elseif = getAndRemoveAttr(el, 'v-else-if')\n    if (elseif) {\n      el.elseif = elseif\n    }\n  }\n}\n\nfunction processIfConditions (el, parent) {\n  const prev = findPrevElement(parent.children)\n  if (prev && prev.if) {\n    addIfCondition(prev, {\n      exp: el.elseif,\n      block: el\n    })\n  } else if (process.env.NODE_ENV !== 'production') {\n    warn(\n      `v-${el.elseif ? ('else-if=\"' + el.elseif + '\"') : 'else'} ` +\n      `used on element <${el.tag}> without corresponding v-if.`\n    )\n  }\n}\n\nfunction findPrevElement (children: Array<any>): ASTElement | void {\n  let i = children.length\n  while (i--) {\n    if (children[i].type === 1) {\n      return children[i]\n    } else {\n      if (process.env.NODE_ENV !== 'production' && children[i].text !== ' ') {\n        warn(\n          `text \"${children[i].text.trim()}\" between v-if and v-else(-if) ` +\n          `will be ignored.`\n        )\n      }\n      children.pop()\n    }\n  }\n}\n\nfunction addIfCondition (el, condition) {\n  if (!el.ifConditions) {\n    el.ifConditions = []\n  }\n  el.ifConditions.push(condition)\n}\n\nfunction processOnce (el) {\n  const once = getAndRemoveAttr(el, 'v-once')\n  if (once != null) {\n    el.once = true\n  }\n}\n\nfunction processSlot (el) {\n  if (el.tag === 'slot') {\n    el.slotName = getBindingAttr(el, 'name')\n    if (process.env.NODE_ENV !== 'production' && el.key) {\n      warn(\n        `\\`key\\` does not work on <slot> because slots are abstract outlets ` +\n        `and can possibly expand into multiple elements. ` +\n        `Use the key on a wrapping element instead.`\n      )\n    }\n  } else {\n    const slotTarget = getBindingAttr(el, 'slot')\n    if (slotTarget) {\n      el.slotTarget = slotTarget === '\"\"' ? '\"default\"' : slotTarget\n    }\n    if (el.tag === 'template') {\n      el.slotScope = getAndRemoveAttr(el, 'scope')\n    }\n  }\n}\n\nfunction processComponent (el) {\n  let binding\n  if ((binding = getBindingAttr(el, 'is'))) {\n    el.component = binding\n  }\n  if (getAndRemoveAttr(el, 'inline-template') != null) {\n    el.inlineTemplate = true\n  }\n}\n\nfunction processAttrs (el) {\n  const list = el.attrsList\n  let i, l, name, rawName, value, modifiers, isProp\n  for (i = 0, l = list.length; i < l; i++) {\n    name = rawName = list[i].name\n    value = list[i].value\n    if (dirRE.test(name)) {\n      // mark element as dynamic\n      el.hasBindings = true\n      // modifiers\n      modifiers = parseModifiers(name)\n      if (modifiers) {\n        name = name.replace(modifierRE, '')\n      }\n      if (bindRE.test(name)) { // v-bind\n        name = name.replace(bindRE, '')\n        value = parseFilters(value)\n        isProp = false\n        if (modifiers) {\n          if (modifiers.prop) {\n            isProp = true\n            name = camelize(name)\n            if (name === 'innerHtml') name = 'innerHTML'\n          }\n          if (modifiers.camel) {\n            name = camelize(name)\n          }\n          if (modifiers.sync) {\n            addHandler(\n              el,\n              `update:${camelize(name)}`,\n              genAssignmentCode(value, `$event`)\n            )\n          }\n        }\n        if (!el.component && (\n          isProp || platformMustUseProp(el.tag, el.attrsMap.type, name)\n        )) {\n          addProp(el, name, value)\n        } else {\n          addAttr(el, name, value)\n        }\n      } else if (onRE.test(name)) { // v-on\n        name = name.replace(onRE, '')\n        addHandler(el, name, value, modifiers, false, warn)\n      } else { // normal directives\n        name = name.replace(dirRE, '')\n        // parse arg\n        const argMatch = name.match(argRE)\n        const arg = argMatch && argMatch[1]\n        if (arg) {\n          name = name.slice(0, -(arg.length + 1))\n        }\n        addDirective(el, name, rawName, value, arg, modifiers)\n        if (process.env.NODE_ENV !== 'production' && name === 'model') {\n          checkForAliasModel(el, value)\n        }\n      }\n    } else {\n      // literal attribute\n      if (process.env.NODE_ENV !== 'production') {\n        const expression = parseText(value, delimiters)\n        if (expression) {\n          warn(\n            `${name}=\"${value}\": ` +\n            'Interpolation inside attributes has been removed. ' +\n            'Use v-bind or the colon shorthand instead. For example, ' +\n            'instead of <div id=\"{{ val }}\">, use <div :id=\"val\">.'\n          )\n        }\n      }\n      addAttr(el, name, JSON.stringify(value))\n    }\n  }\n}\n\nfunction checkInFor (el: ASTElement): boolean {\n  let parent = el\n  while (parent) {\n    if (parent.for !== undefined) {\n      return true\n    }\n    parent = parent.parent\n  }\n  return false\n}\n\nfunction parseModifiers (name: string): Object | void {\n  const match = name.match(modifierRE)\n  if (match) {\n    const ret = {}\n    match.forEach(m => { ret[m.slice(1)] = true })\n    return ret\n  }\n}\n\nfunction makeAttrsMap (attrs: Array<Object>): Object {\n  const map = {}\n  for (let i = 0, l = attrs.length; i < l; i++) {\n    if (\n      process.env.NODE_ENV !== 'production' &&\n      map[attrs[i].name] && !isIE && !isEdge\n    ) {\n      warn('duplicate attribute: ' + attrs[i].name)\n    }\n    map[attrs[i].name] = attrs[i].value\n  }\n  return map\n}\n\n// for script (e.g. type=\"x/template\") or style, do not decode content\nfunction isTextTag (el): boolean {\n  return el.tag === 'script' || el.tag === 'style'\n}\n\nfunction isForbiddenTag (el): boolean {\n  return (\n    el.tag === 'style' ||\n    (el.tag === 'script' && (\n      !el.attrsMap.type ||\n      el.attrsMap.type === 'text/javascript'\n    ))\n  )\n}\n\nconst ieNSBug = /^xmlns:NS\\d+/\nconst ieNSPrefix = /^NS\\d+:/\n\n/* istanbul ignore next */\nfunction guardIESVGBug (attrs) {\n  const res = []\n  for (let i = 0; i < attrs.length; i++) {\n    const attr = attrs[i]\n    if (!ieNSBug.test(attr.name)) {\n      attr.name = attr.name.replace(ieNSPrefix, '')\n      res.push(attr)\n    }\n  }\n  return res\n}\n\nfunction checkForAliasModel (el, value) {\n  let _el = el\n  while (_el) {\n    if (_el.for && _el.alias === value) {\n      warn(\n        `<${el.tag} v-model=\"${value}\">: ` +\n        `You are binding v-model directly to a v-for iteration alias. ` +\n        `This will not be able to modify the v-for source array because ` +\n        `writing to the alias is like modifying a function local variable. ` +\n        `Consider using an array of objects and use v-model on an object property instead.`\n      )\n    }\n    _el = _el.parent\n  }\n}\n"
  },
  {
    "path": "src/compiler/parser/text-parser.js",
    "content": "/* @flow */\n\nimport { cached } from 'shared/util'\nimport { parseFilters } from './filter-parser'\n\nconst defaultTagRE = /\\{\\{((?:.|\\n)+?)\\}\\}/g\nconst regexEscapeRE = /[-.*+?^${}()|[\\]\\/\\\\]/g\n\nconst buildRegex = cached(delimiters => {\n  const open = delimiters[0].replace(regexEscapeRE, '\\\\$&')\n  const close = delimiters[1].replace(regexEscapeRE, '\\\\$&')\n  return new RegExp(open + '((?:.|\\\\n)+?)' + close, 'g')\n})\n\nexport function parseText (\n  text: string,\n  delimiters?: [string, string]\n): string | void {\n  const tagRE = delimiters ? buildRegex(delimiters) : defaultTagRE\n  if (!tagRE.test(text)) {\n    return\n  }\n  const tokens = []\n  let lastIndex = tagRE.lastIndex = 0\n  let match, index\n  while ((match = tagRE.exec(text))) {\n    index = match.index\n    // push text token\n    if (index > lastIndex) {\n      tokens.push(JSON.stringify(text.slice(lastIndex, index)))\n    }\n    // tag token\n    const exp = parseFilters(match[1].trim())\n    tokens.push(`_s(${exp})`)\n    lastIndex = index + match[0].length\n  }\n  if (lastIndex < text.length) {\n    tokens.push(JSON.stringify(text.slice(lastIndex)))\n  }\n  return tokens.join('+')\n}\n"
  },
  {
    "path": "src/compiler/to-function.js",
    "content": "/* @flow */\n\nimport { noop } from 'shared/util'\nimport { warn, tip } from 'core/util/debug'\n\ntype CompiledFunctionResult = {\n  render: Function;\n  staticRenderFns: Array<Function>;\n};\n\nfunction createFunction (code, errors) {\n  try {\n    return new Function(code)\n  } catch (err) {\n    errors.push({ err, code })\n    return noop\n  }\n}\n\nexport function createCompileToFunctionFn (compile: Function): Function {\n  const cache: {\n    [key: string]: CompiledFunctionResult;\n  } = Object.create(null)\n\n  return function compileToFunctions (\n    template: string,\n    options?: CompilerOptions,\n    vm?: Component\n  ): CompiledFunctionResult {\n    options = options || {}\n\n    /* istanbul ignore if */\n    if (process.env.NODE_ENV !== 'production') {\n      // detect possible CSP restriction\n      try {\n        new Function('return 1')\n      } catch (e) {\n        if (e.toString().match(/unsafe-eval|CSP/)) {\n          warn(\n            'It seems you are using the standalone build of Vue.js in an ' +\n            'environment with Content Security Policy that prohibits unsafe-eval. ' +\n            'The template compiler cannot work in this environment. Consider ' +\n            'relaxing the policy to allow unsafe-eval or pre-compiling your ' +\n            'templates into render functions.'\n          )\n        }\n      }\n    }\n\n    // check cache\n    const key = options.delimiters\n      ? String(options.delimiters) + template\n      : template\n    if (cache[key]) {\n      return cache[key]\n    }\n\n    // compile\n    const compiled = compile(template, options)\n\n    // check compilation errors/tips\n    if (process.env.NODE_ENV !== 'production') {\n      if (compiled.errors && compiled.errors.length) {\n        warn(\n          `Error compiling template:\\n\\n${template}\\n\\n` +\n          compiled.errors.map(e => `- ${e}`).join('\\n') + '\\n',\n          vm\n        )\n      }\n      if (compiled.tips && compiled.tips.length) {\n        compiled.tips.forEach(msg => tip(msg, vm))\n      }\n    }\n\n    // turn code into functions\n    const res = {}\n    const fnGenErrors = []\n    res.render = createFunction(compiled.render, fnGenErrors)\n    res.staticRenderFns = compiled.staticRenderFns.map(code => {\n      return createFunction(code, fnGenErrors)\n    })\n\n    // check function generation errors.\n    // this should only happen if there is a bug in the compiler itself.\n    // mostly for codegen development use\n    /* istanbul ignore if */\n    if (process.env.NODE_ENV !== 'production') {\n      if ((!compiled.errors || !compiled.errors.length) && fnGenErrors.length) {\n        warn(\n          `Failed to generate render function:\\n\\n` +\n          fnGenErrors.map(({ err, code }) => `${err.toString()} in\\n\\n${code}\\n`).join('\\n'),\n          vm\n        )\n      }\n    }\n\n    return (cache[key] = res)\n  }\n}\n"
  },
  {
    "path": "src/core/components/index.js",
    "content": "import KeepAlive from './keep-alive'\n\nexport default {\n  KeepAlive\n}\n"
  },
  {
    "path": "src/core/components/keep-alive.js",
    "content": "/* @flow */\n\nimport { isRegExp } from 'shared/util'\nimport { getFirstComponentChild } from 'core/vdom/helpers/index'\n\ntype VNodeCache = { [key: string]: ?VNode };\n\nconst patternTypes: Array<Function> = [String, RegExp, Array]\n\nfunction getComponentName (opts: ?VNodeComponentOptions): ?string {\n  return opts && (opts.Ctor.options.name || opts.tag)\n}\n\nfunction matches (pattern: string | RegExp | Array<string>, name: string): boolean {\n  if (Array.isArray(pattern)) {\n    return pattern.indexOf(name) > -1\n  } else if (typeof pattern === 'string') {\n    return pattern.split(',').indexOf(name) > -1\n  } else if (isRegExp(pattern)) {\n    return pattern.test(name)\n  }\n  /* istanbul ignore next */\n  return false\n}\n\nfunction pruneCache (cache: VNodeCache, current: VNode, filter: Function) {\n  for (const key in cache) {\n    const cachedNode: ?VNode = cache[key]\n    if (cachedNode) {\n      const name: ?string = getComponentName(cachedNode.componentOptions)\n      if (name && !filter(name)) {\n        if (cachedNode !== current) {\n          pruneCacheEntry(cachedNode)\n        }\n        cache[key] = null\n      }\n    }\n  }\n}\n\nfunction pruneCacheEntry (vnode: ?VNode) {\n  if (vnode) {\n    vnode.componentInstance.$destroy()\n  }\n}\n\nexport default {\n  name: 'keep-alive',\n  abstract: true,\n\n  props: {\n    include: patternTypes,\n    exclude: patternTypes\n  },\n\n  created () {\n    this.cache = Object.create(null)\n  },\n\n  destroyed () {\n    for (const key in this.cache) {\n      pruneCacheEntry(this.cache[key])\n    }\n  },\n\n  watch: {\n    include (val: string | RegExp | Array<string>) {\n      pruneCache(this.cache, this._vnode, name => matches(val, name))\n    },\n    exclude (val: string | RegExp | Array<string>) {\n      pruneCache(this.cache, this._vnode, name => !matches(val, name))\n    }\n  },\n\n  render () {\n    const vnode: VNode = getFirstComponentChild(this.$slots.default)\n    const componentOptions: ?VNodeComponentOptions = vnode && vnode.componentOptions\n    if (componentOptions) {\n      // check pattern\n      const name: ?string = getComponentName(componentOptions)\n      if (name && (\n        (this.include && !matches(this.include, name)) ||\n        (this.exclude && matches(this.exclude, name))\n      )) {\n        return vnode\n      }\n      const key: ?string = vnode.key == null\n        // same constructor may get registered as different local components\n        // so cid alone is not enough (#3269)\n        ? componentOptions.Ctor.cid + (componentOptions.tag ? `::${componentOptions.tag}` : '')\n        : vnode.key\n      if (this.cache[key]) {\n        vnode.componentInstance = this.cache[key].componentInstance\n      } else {\n        this.cache[key] = vnode\n      }\n      vnode.data.keepAlive = true\n    }\n    return vnode\n  }\n}\n"
  },
  {
    "path": "src/core/config.js",
    "content": "/* @flow */\n\nimport {\n  no,\n  noop,\n  identity\n} from 'shared/util'\n\nimport { LIFECYCLE_HOOKS } from 'shared/constants'\n\nexport type Config = {\n  // user\n  optionMergeStrategies: { [key: string]: Function };\n  silent: boolean;\n  productionTip: boolean;\n  performance: boolean;\n  devtools: boolean;\n  errorHandler: ?(err: Error, vm: Component, info: string) => void;\n  warnHandler: ?(msg: string, vm: Component, trace: string) => void;\n  ignoredElements: Array<string>;\n  keyCodes: { [key: string]: number | Array<number> };\n\n  // platform\n  isReservedTag: (x?: string) => boolean;\n  isReservedAttr: (x?: string) => boolean;\n  parsePlatformTagName: (x: string) => string;\n  isUnknownElement: (x?: string) => boolean;\n  getTagNamespace: (x?: string) => string | void;\n  mustUseProp: (tag: string, type: ?string, name: string) => boolean;\n\n  // legacy\n  _lifecycleHooks: Array<string>;\n};\n\nexport default ({\n  /**\n   * Option merge strategies (used in core/util/options)\n   */\n  optionMergeStrategies: Object.create(null),\n\n  /**\n   * Whether to suppress warnings.\n   */\n  silent: false,\n\n  /**\n   * Show production mode tip message on boot?\n   */\n  productionTip: process.env.NODE_ENV !== 'production',\n\n  /**\n   * Whether to enable devtools\n   */\n  devtools: process.env.NODE_ENV !== 'production',\n\n  /**\n   * Whether to record perf\n   */\n  performance: false,\n\n  /**\n   * Error handler for watcher errors\n   */\n  errorHandler: null,\n\n  /**\n   * Warn handler for watcher warns\n   */\n  warnHandler: null,\n\n  /**\n   * Ignore certain custom elements\n   */\n  ignoredElements: [],\n\n  /**\n   * Custom user key aliases for v-on\n   */\n  keyCodes: Object.create(null),\n\n  /**\n   * Check if a tag is reserved so that it cannot be registered as a\n   * component. This is platform-dependent and may be overwritten.\n   */\n  isReservedTag: no,\n\n  /**\n   * Check if an attribute is reserved so that it cannot be used as a component\n   * prop. This is platform-dependent and may be overwritten.\n   */\n  isReservedAttr: no,\n\n  /**\n   * Check if a tag is an unknown element.\n   * Platform-dependent.\n   */\n  isUnknownElement: no,\n\n  /**\n   * Get the namespace of an element\n   */\n  getTagNamespace: noop,\n\n  /**\n   * Parse the real tag name for the specific platform.\n   */\n  parsePlatformTagName: identity,\n\n  /**\n   * Check if an attribute must be bound using property, e.g. value\n   * Platform-dependent.\n   */\n  mustUseProp: no,\n\n  /**\n   * Exposed for legacy reasons\n   */\n  _lifecycleHooks: LIFECYCLE_HOOKS\n}: Config)\n"
  },
  {
    "path": "src/core/global-api/assets.js",
    "content": "/* @flow */\n\nimport config from '../config'\nimport { ASSET_TYPES } from 'shared/constants'\nimport { warn, isPlainObject } from '../util/index'\n\nexport function initAssetRegisters (Vue: GlobalAPI) {\n  /**\n   * Create asset registration methods.\n   */\n  ASSET_TYPES.forEach(type => {\n    Vue[type] = function (\n      id: string,\n      definition: Function | Object\n    ): Function | Object | void {\n      if (!definition) {\n        return this.options[type + 's'][id]\n      } else {\n        /* istanbul ignore if */\n        if (process.env.NODE_ENV !== 'production') {\n          if (type === 'component' && config.isReservedTag(id)) {\n            warn(\n              'Do not use built-in or reserved HTML elements as component ' +\n              'id: ' + id\n            )\n          }\n        }\n        if (type === 'component' && isPlainObject(definition)) {\n          definition.name = definition.name || id\n          definition = this.options._base.extend(definition)\n        }\n        if (type === 'directive' && typeof definition === 'function') {\n          definition = { bind: definition, update: definition }\n        }\n        this.options[type + 's'][id] = definition\n        return definition\n      }\n    }\n  })\n}\n"
  },
  {
    "path": "src/core/global-api/extend.js",
    "content": "/* @flow */\n\nimport { ASSET_TYPES } from 'shared/constants'\nimport { warn, extend, mergeOptions } from '../util/index'\nimport { defineComputed, proxy } from '../instance/state'\n\nexport function initExtend (Vue: GlobalAPI) {\n  /**\n   * Each instance constructor, including Vue, has a unique\n   * cid. This enables us to create wrapped \"child\n   * constructors\" for prototypal inheritance and cache them.\n   */\n  Vue.cid = 0\n  let cid = 1\n\n  /**\n   * Class inheritance\n   */\n  Vue.extend = function (extendOptions: Object): Function {\n    extendOptions = extendOptions || {}\n    const Super = this\n    const SuperId = Super.cid\n    const cachedCtors = extendOptions._Ctor || (extendOptions._Ctor = {})\n    if (cachedCtors[SuperId]) {\n      return cachedCtors[SuperId]\n    }\n\n    const name = extendOptions.name || Super.options.name\n    if (process.env.NODE_ENV !== 'production') {\n      if (!/^[a-zA-Z][\\w-]*$/.test(name)) {\n        warn(\n          'Invalid component name: \"' + name + '\". Component names ' +\n          'can only contain alphanumeric characters and the hyphen, ' +\n          'and must start with a letter.'\n        )\n      }\n    }\n\n    const Sub = function VueComponent (options) {\n      this._init(options)\n    }\n    Sub.prototype = Object.create(Super.prototype)\n    Sub.prototype.constructor = Sub\n    Sub.cid = cid++\n    Sub.options = mergeOptions(\n      Super.options,\n      extendOptions\n    )\n    Sub['super'] = Super\n\n    // For props and computed properties, we define the proxy getters on\n    // the Vue instances at extension time, on the extended prototype. This\n    // avoids Object.defineProperty calls for each instance created.\n    if (Sub.options.props) {\n      initProps(Sub)\n    }\n    if (Sub.options.computed) {\n      initComputed(Sub)\n    }\n\n    // allow further extension/mixin/plugin usage\n    Sub.extend = Super.extend\n    Sub.mixin = Super.mixin\n    Sub.use = Super.use\n\n    // create asset registers, so extended classes\n    // can have their private assets too.\n    ASSET_TYPES.forEach(function (type) {\n      Sub[type] = Super[type]\n    })\n    // enable recursive self-lookup\n    if (name) {\n      Sub.options.components[name] = Sub\n    }\n\n    // keep a reference to the super options at extension time.\n    // later at instantiation we can check if Super's options have\n    // been updated.\n    Sub.superOptions = Super.options\n    Sub.extendOptions = extendOptions\n    Sub.sealedOptions = extend({}, Sub.options)\n\n    // cache constructor\n    cachedCtors[SuperId] = Sub\n    return Sub\n  }\n}\n\nfunction initProps (Comp) {\n  const props = Comp.options.props\n  for (const key in props) {\n    proxy(Comp.prototype, `_props`, key)\n  }\n}\n\nfunction initComputed (Comp) {\n  const computed = Comp.options.computed\n  for (const key in computed) {\n    defineComputed(Comp.prototype, key, computed[key])\n  }\n}\n"
  },
  {
    "path": "src/core/global-api/index.js",
    "content": "/* @flow */\n\nimport config from '../config'\nimport { initUse } from './use'\nimport { initMixin } from './mixin'\nimport { initExtend } from './extend'\nimport { initAssetRegisters } from './assets'\nimport { set, del } from '../observer/index'\nimport { ASSET_TYPES } from 'shared/constants'\nimport builtInComponents from '../components/index'\n\nimport {\n  warn,\n  extend,\n  nextTick,\n  mergeOptions,\n  defineReactive\n} from '../util/index'\n\nexport function initGlobalAPI (Vue: GlobalAPI) {\n  // config\n  const configDef = {}\n  configDef.get = () => config\n  if (process.env.NODE_ENV !== 'production') {\n    configDef.set = () => {\n      warn(\n        'Do not replace the Vue.config object, set individual fields instead.'\n      )\n    }\n  }\n  Object.defineProperty(Vue, 'config', configDef)\n\n  // exposed util methods.\n  // NOTE: these are not considered part of the public API - avoid relying on\n  // them unless you are aware of the risk.\n  Vue.util = {\n    warn,\n    extend,\n    mergeOptions,\n    defineReactive\n  }\n\n  Vue.set = set\n  Vue.delete = del\n  Vue.nextTick = nextTick\n\n  Vue.options = Object.create(null)\n  ASSET_TYPES.forEach(type => {\n    Vue.options[type + 's'] = Object.create(null)\n  })\n\n  // this is used to identify the \"base\" constructor to extend all plain-object\n  // components with in Weex's multi-instance scenarios.\n  Vue.options._base = Vue\n\n  extend(Vue.options.components, builtInComponents)\n\n  initUse(Vue)\n  initMixin(Vue)\n  initExtend(Vue)\n  initAssetRegisters(Vue)\n}\n"
  },
  {
    "path": "src/core/global-api/mixin.js",
    "content": "/* @flow */\n\nimport { mergeOptions } from '../util/index'\n\nexport function initMixin (Vue: GlobalAPI) {\n  Vue.mixin = function (mixin: Object) {\n    this.options = mergeOptions(this.options, mixin)\n    return this\n  }\n}\n"
  },
  {
    "path": "src/core/global-api/use.js",
    "content": "/* @flow */\n\nimport { toArray } from '../util/index'\n\nexport function initUse (Vue: GlobalAPI) {\n  Vue.use = function (plugin: Function | Object) {\n    const installedPlugins = (this._installedPlugins || (this._installedPlugins = []))\n    if (installedPlugins.indexOf(plugin) > -1) {\n      return this\n    }\n\n    // additional parameters\n    const args = toArray(arguments, 1)\n    args.unshift(this)\n    if (typeof plugin.install === 'function') {\n      plugin.install.apply(plugin, args)\n    } else if (typeof plugin === 'function') {\n      plugin.apply(null, args)\n    }\n    installedPlugins.push(plugin)\n    return this\n  }\n}\n"
  },
  {
    "path": "src/core/index.js",
    "content": "import Vue from './instance/index'\nimport { initGlobalAPI } from './global-api/index'\nimport { isServerRendering } from 'core/util/env'\n\ninitGlobalAPI(Vue)\n\nObject.defineProperty(Vue.prototype, '$isServer', {\n  get: isServerRendering\n})\n\nObject.defineProperty(Vue.prototype, '$ssrContext', {\n  get () {\n    /* istanbul ignore next */\n    return this.$vnode && this.$vnode.ssrContext\n  }\n})\n\nVue.version = '__VERSION__'\nVue.mpvueVersion = '__MPVUE_VERSION__'\n\nexport default Vue\n"
  },
  {
    "path": "src/core/instance/events.js",
    "content": "/* @flow */\n\nimport {\n  tip,\n  toArray,\n  hyphenate,\n  handleError,\n  formatComponentName\n} from '../util/index'\nimport { updateListeners } from '../vdom/helpers/index'\n\nexport function initEvents (vm: Component) {\n  vm._events = Object.create(null)\n  vm._hasHookEvent = false\n  // init parent attached events\n  const listeners = vm.$options._parentListeners\n  if (listeners) {\n    updateComponentListeners(vm, listeners)\n  }\n}\n\nlet target: Component\n\nfunction add (event, fn, once) {\n  if (once) {\n    target.$once(event, fn)\n  } else {\n    target.$on(event, fn)\n  }\n}\n\nfunction remove (event, fn) {\n  target.$off(event, fn)\n}\n\nexport function updateComponentListeners (\n  vm: Component,\n  listeners: Object,\n  oldListeners: ?Object\n) {\n  target = vm\n  updateListeners(listeners, oldListeners || {}, add, remove, vm)\n}\n\nexport function eventsMixin (Vue: Class<Component>) {\n  const hookRE = /^hook:/\n  Vue.prototype.$on = function (event: string | Array<string>, fn: Function): Component {\n    const vm: Component = this\n    if (Array.isArray(event)) {\n      for (let i = 0, l = event.length; i < l; i++) {\n        this.$on(event[i], fn)\n      }\n    } else {\n      (vm._events[event] || (vm._events[event] = [])).push(fn)\n      // optimize hook:event cost by using a boolean flag marked at registration\n      // instead of a hash lookup\n      if (hookRE.test(event)) {\n        vm._hasHookEvent = true\n      }\n    }\n    return vm\n  }\n\n  Vue.prototype.$once = function (event: string, fn: Function): Component {\n    const vm: Component = this\n    function on () {\n      vm.$off(event, on)\n      fn.apply(vm, arguments)\n    }\n    on.fn = fn\n    vm.$on(event, on)\n    return vm\n  }\n\n  Vue.prototype.$off = function (event?: string | Array<string>, fn?: Function): Component {\n    const vm: Component = this\n    // all\n    if (!arguments.length) {\n      vm._events = Object.create(null)\n      return vm\n    }\n    // array of events\n    if (Array.isArray(event)) {\n      for (let i = 0, l = event.length; i < l; i++) {\n        this.$off(event[i], fn)\n      }\n      return vm\n    }\n    // specific event\n    const cbs = vm._events[event]\n    if (!cbs) {\n      return vm\n    }\n    if (arguments.length === 1) {\n      vm._events[event] = null\n      return vm\n    }\n    // specific handler\n    let cb\n    let i = cbs.length\n    while (i--) {\n      cb = cbs[i]\n      if (cb === fn || cb.fn === fn) {\n        cbs.splice(i, 1)\n        break\n      }\n    }\n    return vm\n  }\n\n  Vue.prototype.$emit = function (event: string): Component {\n    const vm: Component = this\n    if (process.env.NODE_ENV !== 'production') {\n      const lowerCaseEvent = event.toLowerCase()\n      if (lowerCaseEvent !== event && vm._events[lowerCaseEvent]) {\n        tip(\n          `Event \"${lowerCaseEvent}\" is emitted in component ` +\n          `${formatComponentName(vm)} but the handler is registered for \"${event}\". ` +\n          `Note that HTML attributes are case-insensitive and you cannot use ` +\n          `v-on to listen to camelCase events when using in-DOM templates. ` +\n          `You should probably use \"${hyphenate(event)}\" instead of \"${event}\".`\n        )\n      }\n    }\n    let cbs = vm._events[event]\n    if (cbs) {\n      cbs = cbs.length > 1 ? toArray(cbs) : cbs\n      const args = toArray(arguments, 1)\n      for (let i = 0, l = cbs.length; i < l; i++) {\n        try {\n          cbs[i].apply(vm, args)\n        } catch (e) {\n          handleError(e, vm, `event handler for \"${event}\"`)\n        }\n      }\n    }\n    return vm\n  }\n}\n"
  },
  {
    "path": "src/core/instance/index.js",
    "content": "import { initMixin } from './init'\nimport { stateMixin } from './state'\nimport { renderMixin } from './render'\nimport { eventsMixin } from './events'\nimport { lifecycleMixin } from './lifecycle'\nimport { warn } from '../util/index'\n\nfunction Vue (options) {\n  if (process.env.NODE_ENV !== 'production' &&\n    !(this instanceof Vue)\n  ) {\n    warn('Vue is a constructor and should be called with the `new` keyword')\n  }\n  this._init(options)\n}\n\ninitMixin(Vue)\nstateMixin(Vue)\neventsMixin(Vue)\nlifecycleMixin(Vue)\nrenderMixin(Vue)\n\nexport default Vue\n"
  },
  {
    "path": "src/core/instance/init.js",
    "content": "/* @flow */\n\nimport config from '../config'\nimport { initProxy } from './proxy'\nimport { initState } from './state'\nimport { initRender } from './render'\nimport { initEvents } from './events'\nimport { mark, measure } from '../util/perf'\nimport { initLifecycle, callHook } from './lifecycle'\nimport { initProvide, initInjections } from './inject'\nimport { extend, mergeOptions, formatComponentName } from '../util/index'\n\nlet uid = 0\n\nexport function initMixin (Vue: Class<Component>) {\n  Vue.prototype._init = function (options?: Object) {\n    const vm: Component = this\n    // a uid\n    vm._uid = uid++\n\n    let startTag, endTag\n    /* istanbul ignore if */\n    if (process.env.NODE_ENV !== 'production' && config.performance && mark) {\n      startTag = `vue-perf-init:${vm._uid}`\n      endTag = `vue-perf-end:${vm._uid}`\n      mark(startTag)\n    }\n\n    // a flag to avoid this being observed\n    vm._isVue = true\n    // merge options\n    if (options && options._isComponent) {\n      // optimize internal component instantiation\n      // since dynamic options merging is pretty slow, and none of the\n      // internal component options needs special treatment.\n      initInternalComponent(vm, options)\n    } else {\n      vm.$options = mergeOptions(\n        resolveConstructorOptions(vm.constructor),\n        options || {},\n        vm\n      )\n    }\n    /* istanbul ignore else */\n    if (process.env.NODE_ENV !== 'production') {\n      initProxy(vm)\n    } else {\n      vm._renderProxy = vm\n    }\n    // expose real self\n    vm._self = vm\n    initLifecycle(vm)\n    initEvents(vm)\n    initRender(vm)\n    callHook(vm, 'beforeCreate')\n    initInjections(vm) // resolve injections before data/props\n    initState(vm)\n    initProvide(vm) // resolve provide after data/props\n    callHook(vm, 'created')\n\n    /* istanbul ignore if */\n    if (process.env.NODE_ENV !== 'production' && config.performance && mark) {\n      vm._name = formatComponentName(vm, false)\n      mark(endTag)\n      measure(`${vm._name} init`, startTag, endTag)\n    }\n\n    if (vm.$options.el) {\n      vm.$mount(vm.$options.el)\n    }\n  }\n}\n\nfunction initInternalComponent (vm: Component, options: InternalComponentOptions) {\n  const opts = vm.$options = Object.create(vm.constructor.options)\n  // doing this because it's faster than dynamic enumeration.\n  opts.parent = options.parent\n  opts.propsData = options.propsData\n  opts._parentVnode = options._parentVnode\n  opts._parentListeners = options._parentListeners\n  opts._renderChildren = options._renderChildren\n  opts._componentTag = options._componentTag\n  opts._parentElm = options._parentElm\n  opts._refElm = options._refElm\n  if (options.render) {\n    opts.render = options.render\n    opts.staticRenderFns = options.staticRenderFns\n  }\n}\n\nexport function resolveConstructorOptions (Ctor: Class<Component>) {\n  let options = Ctor.options\n  if (Ctor.super) {\n    const superOptions = resolveConstructorOptions(Ctor.super)\n    const cachedSuperOptions = Ctor.superOptions\n    if (superOptions !== cachedSuperOptions) {\n      // super option changed,\n      // need to resolve new options.\n      Ctor.superOptions = superOptions\n      // check if there are any late-modified/attached options (#4976)\n      const modifiedOptions = resolveModifiedOptions(Ctor)\n      // update base extend options\n      if (modifiedOptions) {\n        extend(Ctor.extendOptions, modifiedOptions)\n      }\n      options = Ctor.options = mergeOptions(superOptions, Ctor.extendOptions)\n      if (options.name) {\n        options.components[options.name] = Ctor\n      }\n    }\n  }\n  return options\n}\n\nfunction resolveModifiedOptions (Ctor: Class<Component>): ?Object {\n  let modified\n  const latest = Ctor.options\n  const extended = Ctor.extendOptions\n  const sealed = Ctor.sealedOptions\n  for (const key in latest) {\n    if (latest[key] !== sealed[key]) {\n      if (!modified) modified = {}\n      modified[key] = dedupe(latest[key], extended[key], sealed[key])\n    }\n  }\n  return modified\n}\n\nfunction dedupe (latest, extended, sealed) {\n  // compare latest and sealed to ensure lifecycle hooks won't be duplicated\n  // between merges\n  if (Array.isArray(latest)) {\n    const res = []\n    sealed = Array.isArray(sealed) ? sealed : [sealed]\n    extended = Array.isArray(extended) ? extended : [extended]\n    for (let i = 0; i < latest.length; i++) {\n      // push original options and not sealed options to exclude duplicated options\n      if (extended.indexOf(latest[i]) >= 0 || sealed.indexOf(latest[i]) < 0) {\n        res.push(latest[i])\n      }\n    }\n    return res\n  } else {\n    return latest\n  }\n}\n"
  },
  {
    "path": "src/core/instance/inject.js",
    "content": "/* @flow */\n\nimport { warn } from '../util/index'\nimport { hasOwn } from 'shared/util'\nimport { hasSymbol } from 'core/util/env'\nimport { defineReactive, observerState } from '../observer/index'\n\nexport function initProvide (vm: Component) {\n  const provide = vm.$options.provide\n  if (provide) {\n    vm._provided = typeof provide === 'function'\n      ? provide.call(vm)\n      : provide\n  }\n}\n\nexport function initInjections (vm: Component) {\n  const result = resolveInject(vm.$options.inject, vm)\n  if (result) {\n    observerState.shouldConvert = false\n    Object.keys(result).forEach(key => {\n      /* istanbul ignore else */\n      if (process.env.NODE_ENV !== 'production') {\n        defineReactive(vm, key, result[key], () => {\n          warn(\n            `Avoid mutating an injected value directly since the changes will be ` +\n            `overwritten whenever the provided component re-renders. ` +\n            `injection being mutated: \"${key}\"`,\n            vm\n          )\n        })\n      } else {\n        defineReactive(vm, key, result[key])\n      }\n    })\n    observerState.shouldConvert = true\n  }\n}\n\nexport function resolveInject (inject: any, vm: Component): ?Object {\n  if (inject) {\n    // inject is :any because flow is not smart enough to figure out cached\n    const result = Object.create(null)\n    const keys = hasSymbol\n        ? Reflect.ownKeys(inject)\n        : Object.keys(inject)\n\n    for (let i = 0; i < keys.length; i++) {\n      const key = keys[i]\n      const provideKey = inject[key]\n      let source = vm\n      while (source) {\n        if (source._provided && provideKey in source._provided) {\n          result[key] = source._provided[provideKey]\n          break\n        }\n        source = source.$parent\n      }\n      if (process.env.NODE_ENV !== 'production' && !hasOwn(result, key)) {\n        warn(`Injection \"${key}\" not found`, vm)\n      }\n    }\n    return result\n  }\n}\n"
  },
  {
    "path": "src/core/instance/lifecycle.js",
    "content": "/* @flow */\n\nimport config from '../config'\nimport Watcher from '../observer/watcher'\nimport { mark, measure } from '../util/perf'\nimport { createEmptyVNode } from '../vdom/vnode'\nimport { observerState } from '../observer/index'\nimport { updateComponentListeners } from './events'\nimport { resolveSlots } from './render-helpers/resolve-slots'\n\nimport {\n  warn,\n  noop,\n  remove,\n  handleError,\n  emptyObject,\n  validateProp\n} from '../util/index'\n\nexport let activeInstance: any = null\nexport let isUpdatingChildComponent: boolean = false\n\nexport function initLifecycle (vm: Component) {\n  const options = vm.$options\n\n  // locate first non-abstract parent\n  let parent = options.parent\n  if (parent && !options.abstract) {\n    while (parent.$options.abstract && parent.$parent) {\n      parent = parent.$parent\n    }\n    parent.$children.push(vm)\n  }\n\n  vm.$parent = parent\n  vm.$root = parent ? parent.$root : vm\n\n  vm.$children = []\n  vm.$refs = {}\n\n  vm._watcher = null\n  vm._inactive = null\n  vm._directInactive = false\n  vm._isMounted = false\n  vm._isDestroyed = false\n  vm._isBeingDestroyed = false\n}\n\nexport function lifecycleMixin (Vue: Class<Component>) {\n  Vue.prototype._update = function (vnode: VNode, hydrating?: boolean) {\n    const vm: Component = this\n    if (vm._isMounted) {\n      callHook(vm, 'beforeUpdate')\n    }\n    const prevEl = vm.$el\n    const prevVnode = vm._vnode\n    const prevActiveInstance = activeInstance\n    activeInstance = vm\n    vm._vnode = vnode\n    // Vue.prototype.__patch__ is injected in entry points\n    // based on the rendering backend used.\n    if (!prevVnode) {\n      // initial render\n      vm.$el = vm.__patch__(\n        vm.$el, vnode, hydrating, false /* removeOnly */,\n        vm.$options._parentElm,\n        vm.$options._refElm\n      )\n      // no need for the ref nodes after initial patch\n      // this prevents keeping a detached DOM tree in memory (#5851)\n      vm.$options._parentElm = vm.$options._refElm = null\n    } else {\n      // updates\n      vm.$el = vm.__patch__(prevVnode, vnode)\n    }\n    activeInstance = prevActiveInstance\n    // update __vue__ reference\n    if (prevEl) {\n      prevEl.__vue__ = null\n    }\n    if (vm.$el) {\n      vm.$el.__vue__ = vm\n    }\n    // if parent is an HOC, update its $el as well\n    if (vm.$vnode && vm.$parent && vm.$vnode === vm.$parent._vnode) {\n      vm.$parent.$el = vm.$el\n    }\n    // updated hook is called by the scheduler to ensure that children are\n    // updated in a parent's updated hook.\n  }\n\n  Vue.prototype.$forceUpdate = function () {\n    const vm: Component = this\n    if (vm._watcher) {\n      vm._watcher.update()\n    }\n  }\n\n  Vue.prototype.$destroy = function () {\n    const vm: Component = this\n    if (vm._isBeingDestroyed) {\n      return\n    }\n    callHook(vm, 'beforeDestroy')\n    vm._isBeingDestroyed = true\n    // remove self from parent\n    const parent = vm.$parent\n    if (parent && !parent._isBeingDestroyed && !vm.$options.abstract) {\n      remove(parent.$children, vm)\n    }\n    // teardown watchers\n    if (vm._watcher) {\n      vm._watcher.teardown()\n    }\n    let i = vm._watchers.length\n    while (i--) {\n      vm._watchers[i].teardown()\n    }\n    // remove reference from data ob\n    // frozen object may not have observer.\n    if (vm._data.__ob__) {\n      vm._data.__ob__.vmCount--\n    }\n    // call the last hook...\n    vm._isDestroyed = true\n    // invoke destroy hooks on current rendered tree\n    vm.__patch__(vm._vnode, null)\n    // fire destroyed hook\n    callHook(vm, 'destroyed')\n    // turn off all instance listeners.\n    vm.$off()\n    // remove __vue__ reference\n    if (vm.$el) {\n      vm.$el.__vue__ = null\n    }\n  }\n}\n\nexport function mountComponent (\n  vm: Component,\n  el: ?Element,\n  hydrating?: boolean\n): Component {\n  vm.$el = el\n  if (!vm.$options.render) {\n    vm.$options.render = createEmptyVNode\n    if (process.env.NODE_ENV !== 'production') {\n      /* istanbul ignore if */\n      if ((vm.$options.template && vm.$options.template.charAt(0) !== '#') ||\n        vm.$options.el || el) {\n        warn(\n          'You are using the runtime-only build of Vue where the template ' +\n          'compiler is not available. Either pre-compile the templates into ' +\n          'render functions, or use the compiler-included build.',\n          vm\n        )\n      } else {\n        warn(\n          'Failed to mount component: template or render function not defined.',\n          vm\n        )\n      }\n    }\n  }\n  callHook(vm, 'beforeMount')\n\n  let updateComponent\n  /* istanbul ignore if */\n  if (process.env.NODE_ENV !== 'production' && config.performance && mark) {\n    updateComponent = () => {\n      const name = vm._name\n      const id = vm._uid\n      const startTag = `vue-perf-start:${id}`\n      const endTag = `vue-perf-end:${id}`\n\n      mark(startTag)\n      const vnode = vm._render()\n      mark(endTag)\n      measure(`${name} render`, startTag, endTag)\n\n      mark(startTag)\n      vm._update(vnode, hydrating)\n      mark(endTag)\n      measure(`${name} patch`, startTag, endTag)\n    }\n  } else {\n    updateComponent = () => {\n      vm._update(vm._render(), hydrating)\n    }\n  }\n\n  vm._watcher = new Watcher(vm, updateComponent, noop)\n  hydrating = false\n\n  // manually mounted instance, call mounted on self\n  // mounted is called for render-created child components in its inserted hook\n  if (vm.$vnode == null) {\n    vm._isMounted = true\n    callHook(vm, 'mounted')\n  }\n  return vm\n}\n\nexport function updateChildComponent (\n  vm: Component,\n  propsData: ?Object,\n  listeners: ?Object,\n  parentVnode: VNode,\n  renderChildren: ?Array<VNode>\n) {\n  if (process.env.NODE_ENV !== 'production') {\n    isUpdatingChildComponent = true\n  }\n\n  // determine whether component has slot children\n  // we need to do this before overwriting $options._renderChildren\n  const hasChildren = !!(\n    renderChildren ||               // has new static slots\n    vm.$options._renderChildren ||  // has old static slots\n    parentVnode.data.scopedSlots || // has new scoped slots\n    vm.$scopedSlots !== emptyObject // has old scoped slots\n  )\n\n  vm.$options._parentVnode = parentVnode\n  vm.$vnode = parentVnode // update vm's placeholder node without re-render\n\n  if (vm._vnode) { // update child tree's parent\n    vm._vnode.parent = parentVnode\n  }\n  vm.$options._renderChildren = renderChildren\n\n  // update $attrs and $listensers hash\n  // these are also reactive so they may trigger child update if the child\n  // used them during render\n  vm.$attrs = parentVnode.data && parentVnode.data.attrs\n  vm.$listeners = listeners\n\n  // update props\n  if (propsData && vm.$options.props) {\n    observerState.shouldConvert = false\n    const props = vm._props\n    const propKeys = vm.$options._propKeys || []\n    for (let i = 0; i < propKeys.length; i++) {\n      const key = propKeys[i]\n      props[key] = validateProp(key, vm.$options.props, propsData, vm)\n    }\n    observerState.shouldConvert = true\n    // keep a copy of raw propsData\n    vm.$options.propsData = propsData\n  }\n\n  // update listeners\n  if (listeners) {\n    const oldListeners = vm.$options._parentListeners\n    vm.$options._parentListeners = listeners\n    updateComponentListeners(vm, listeners, oldListeners)\n  }\n  // resolve slots + force update if has children\n  if (hasChildren) {\n    vm.$slots = resolveSlots(renderChildren, parentVnode.context)\n    vm.$forceUpdate()\n  }\n\n  if (process.env.NODE_ENV !== 'production') {\n    isUpdatingChildComponent = false\n  }\n}\n\nfunction isInInactiveTree (vm) {\n  while (vm && (vm = vm.$parent)) {\n    if (vm._inactive) return true\n  }\n  return false\n}\n\nexport function activateChildComponent (vm: Component, direct?: boolean) {\n  if (direct) {\n    vm._directInactive = false\n    if (isInInactiveTree(vm)) {\n      return\n    }\n  } else if (vm._directInactive) {\n    return\n  }\n  if (vm._inactive || vm._inactive === null) {\n    vm._inactive = false\n    for (let i = 0; i < vm.$children.length; i++) {\n      activateChildComponent(vm.$children[i])\n    }\n    callHook(vm, 'activated')\n  }\n}\n\nexport function deactivateChildComponent (vm: Component, direct?: boolean) {\n  if (direct) {\n    vm._directInactive = true\n    if (isInInactiveTree(vm)) {\n      return\n    }\n  }\n  if (!vm._inactive) {\n    vm._inactive = true\n    for (let i = 0; i < vm.$children.length; i++) {\n      deactivateChildComponent(vm.$children[i])\n    }\n    callHook(vm, 'deactivated')\n  }\n}\n\nexport function callHook (vm: Component, hook: string) {\n  const handlers = vm.$options[hook]\n  if (handlers) {\n    for (let i = 0, j = handlers.length; i < j; i++) {\n      try {\n        handlers[i].call(vm)\n      } catch (e) {\n        handleError(e, vm, `${hook} hook`)\n      }\n    }\n  }\n  if (vm._hasHookEvent) {\n    vm.$emit('hook:' + hook)\n  }\n}\n"
  },
  {
    "path": "src/core/instance/proxy.js",
    "content": "/* not type checking this file because flow doesn't play well with Proxy */\n\nimport config from 'core/config'\nimport { warn, makeMap } from '../util/index'\n\nlet initProxy\n\nif (process.env.NODE_ENV !== 'production') {\n  const allowedGlobals = makeMap(\n    'Infinity,undefined,NaN,isFinite,isNaN,' +\n    'parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,' +\n    'Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,' +\n    'require' // for Webpack/Browserify\n  )\n\n  const warnNonPresent = (target, key) => {\n    warn(\n      `Property or method \"${key}\" is not defined on the instance but ` +\n      `referenced during render. Make sure to declare reactive data ` +\n      `properties in the data option.`,\n      target\n    )\n  }\n\n  const hasProxy =\n    typeof Proxy !== 'undefined' &&\n    Proxy.toString().match(/native code/)\n\n  if (hasProxy) {\n    const isBuiltInModifier = makeMap('stop,prevent,self,ctrl,shift,alt,meta')\n    config.keyCodes = new Proxy(config.keyCodes, {\n      set (target, key, value) {\n        if (isBuiltInModifier(key)) {\n          warn(`Avoid overwriting built-in modifier in config.keyCodes: .${key}`)\n          return false\n        } else {\n          target[key] = value\n          return true\n        }\n      }\n    })\n  }\n\n  const hasHandler = {\n    has (target, key) {\n      const has = key in target\n      const isAllowed = allowedGlobals(key) || key.charAt(0) === '_'\n      if (!has && !isAllowed) {\n        warnNonPresent(target, key)\n      }\n      return has || !isAllowed\n    }\n  }\n\n  const getHandler = {\n    get (target, key) {\n      if (typeof key === 'string' && !(key in target)) {\n        warnNonPresent(target, key)\n      }\n      return target[key]\n    }\n  }\n\n  initProxy = function initProxy (vm) {\n    if (hasProxy) {\n      // determine which proxy handler to use\n      const options = vm.$options\n      const handlers = options.render && options.render._withStripped\n        ? getHandler\n        : hasHandler\n      vm._renderProxy = new Proxy(vm, handlers)\n    } else {\n      vm._renderProxy = vm\n    }\n  }\n}\n\nexport { initProxy }\n"
  },
  {
    "path": "src/core/instance/render-helpers/bind-object-listeners.js",
    "content": "/* @flow */\n\nimport { warn, extend, isPlainObject } from 'core/util/index'\n\nexport function bindObjectListeners (data: any, value: any): VNodeData {\n  if (value) {\n    if (!isPlainObject(value)) {\n      process.env.NODE_ENV !== 'production' && warn(\n        'v-on without argument expects an Object value',\n        this\n      )\n    } else {\n      const on = data.on = data.on ? extend({}, data.on) : {}\n      for (const key in value) {\n        const existing = on[key]\n        const ours = value[key]\n        on[key] = existing ? [].concat(ours, existing) : ours\n      }\n    }\n  }\n  return data\n}\n"
  },
  {
    "path": "src/core/instance/render-helpers/bind-object-props.js",
    "content": "/* @flow */\n\nimport config from 'core/config'\n\nimport {\n  warn,\n  isObject,\n  toObject,\n  isReservedAttribute\n} from 'core/util/index'\n\n/**\n * Runtime helper for merging v-bind=\"object\" into a VNode's data.\n */\nexport function bindObjectProps (\n  data: any,\n  tag: string,\n  value: any,\n  asProp: boolean,\n  isSync?: boolean\n): VNodeData {\n  if (value) {\n    if (!isObject(value)) {\n      process.env.NODE_ENV !== 'production' && warn(\n        'v-bind without argument expects an Object or Array value',\n        this\n      )\n    } else {\n      if (Array.isArray(value)) {\n        value = toObject(value)\n      }\n      let hash\n      for (const key in value) {\n        if (\n          key === 'class' ||\n          key === 'style' ||\n          isReservedAttribute(key)\n        ) {\n          hash = data\n        } else {\n          const type = data.attrs && data.attrs.type\n          hash = asProp || config.mustUseProp(tag, type, key)\n            ? data.domProps || (data.domProps = {})\n            : data.attrs || (data.attrs = {})\n        }\n        if (!(key in hash)) {\n          hash[key] = value[key]\n\n          if (isSync) {\n            const on = data.on || (data.on = {})\n            on[`update:${key}`] = function ($event) {\n              value[key] = $event\n            }\n          }\n        }\n      }\n    }\n  }\n  return data\n}\n"
  },
  {
    "path": "src/core/instance/render-helpers/check-keycodes.js",
    "content": "/* @flow */\n\nimport config from 'core/config'\n\n/**\n * Runtime helper for checking keyCodes from config.\n */\nexport function checkKeyCodes (\n  eventKeyCode: number,\n  key: string,\n  builtInAlias: number | Array<number> | void\n): boolean {\n  const keyCodes = config.keyCodes[key] || builtInAlias\n  if (Array.isArray(keyCodes)) {\n    return keyCodes.indexOf(eventKeyCode) === -1\n  } else {\n    return keyCodes !== eventKeyCode\n  }\n}\n"
  },
  {
    "path": "src/core/instance/render-helpers/render-list.js",
    "content": "/* @flow */\n\nimport { isObject, isDef } from 'core/util/index'\n\n/**\n * Runtime helper for rendering v-for lists.\n */\nexport function renderList (\n  val: any,\n  render: (\n    val: any,\n    keyOrIndex: string | number,\n    index?: number\n  ) => VNode\n): ?Array<VNode> {\n  let ret: ?Array<VNode>, i, l, keys, key\n  if (Array.isArray(val) || typeof val === 'string') {\n    ret = new Array(val.length)\n    for (i = 0, l = val.length; i < l; i++) {\n      ret[i] = render(val[i], i)\n    }\n  } else if (typeof val === 'number') {\n    ret = new Array(val)\n    for (i = 0; i < val; i++) {\n      ret[i] = render(i + 1, i)\n    }\n  } else if (isObject(val)) {\n    keys = Object.keys(val)\n    ret = new Array(keys.length)\n    for (i = 0, l = keys.length; i < l; i++) {\n      key = keys[i]\n      ret[i] = render(val[key], key, i)\n    }\n  }\n  if (isDef(ret)) {\n    (ret: any)._isVList = true\n  }\n  return ret\n}\n"
  },
  {
    "path": "src/core/instance/render-helpers/render-slot.js",
    "content": "/* @flow */\n\nimport { extend, warn } from 'core/util/index'\n\n/**\n * Runtime helper for rendering <slot>\n */\nexport function renderSlot (\n  name: string,\n  fallback: ?Array<VNode>,\n  props: ?Object,\n  bindObject: ?Object\n): ?Array<VNode> {\n  const scopedSlotFn = this.$scopedSlots[name]\n  if (scopedSlotFn) { // scoped slot\n    props = props || {}\n    if (bindObject) {\n      props = extend(extend({}, bindObject), props)\n    }\n    return scopedSlotFn(props) || fallback\n  } else {\n    const slotNodes = this.$slots[name]\n    // warn duplicate slot usage\n    if (slotNodes && process.env.NODE_ENV !== 'production') {\n      slotNodes._rendered && warn(\n        `Duplicate presence of slot \"${name}\" found in the same render tree ` +\n        `- this will likely cause render errors.`,\n        this\n      )\n      slotNodes._rendered = true\n    }\n    return slotNodes || fallback\n  }\n}\n"
  },
  {
    "path": "src/core/instance/render-helpers/render-static.js",
    "content": "/* @flow */\n\nimport { cloneVNode, cloneVNodes } from 'core/vdom/vnode'\n\n/**\n * Runtime helper for rendering static trees.\n */\nexport function renderStatic (\n  index: number,\n  isInFor?: boolean\n): VNode | Array<VNode> {\n  let tree = this._staticTrees[index]\n  // if has already-rendered static tree and not inside v-for,\n  // we can reuse the same tree by doing a shallow clone.\n  if (tree && !isInFor) {\n    return Array.isArray(tree)\n      ? cloneVNodes(tree)\n      : cloneVNode(tree)\n  }\n  // otherwise, render a fresh tree.\n  tree = this._staticTrees[index] =\n    this.$options.staticRenderFns[index].call(this._renderProxy)\n  markStatic(tree, `__static__${index}`, false)\n  return tree\n}\n\n/**\n * Runtime helper for v-once.\n * Effectively it means marking the node as static with a unique key.\n */\nexport function markOnce (\n  tree: VNode | Array<VNode>,\n  index: number,\n  key: string\n) {\n  markStatic(tree, `__once__${index}${key ? `_${key}` : ``}`, true)\n  return tree\n}\n\nfunction markStatic (\n  tree: VNode | Array<VNode>,\n  key: string,\n  isOnce: boolean\n) {\n  if (Array.isArray(tree)) {\n    for (let i = 0; i < tree.length; i++) {\n      if (tree[i] && typeof tree[i] !== 'string') {\n        markStaticNode(tree[i], `${key}_${i}`, isOnce)\n      }\n    }\n  } else {\n    markStaticNode(tree, key, isOnce)\n  }\n}\n\nfunction markStaticNode (node, key, isOnce) {\n  node.isStatic = true\n  node.key = key\n  node.isOnce = isOnce\n}\n"
  },
  {
    "path": "src/core/instance/render-helpers/resolve-filter.js",
    "content": "/* @flow */\n\nimport { identity, resolveAsset } from 'core/util/index'\n\n/**\n * Runtime helper for resolving filters\n */\nexport function resolveFilter (id: string): Function {\n  return resolveAsset(this.$options, 'filters', id, true) || identity\n}\n"
  },
  {
    "path": "src/core/instance/render-helpers/resolve-slots.js",
    "content": "/* @flow */\n\n/**\n * Runtime helper for resolving raw children VNodes into a slot object.\n */\nexport function resolveSlots (\n  children: ?Array<VNode>,\n  context: ?Component\n): { [key: string]: Array<VNode> } {\n  const slots = {}\n  if (!children) {\n    return slots\n  }\n  const defaultSlot = []\n  for (let i = 0, l = children.length; i < l; i++) {\n    const child = children[i]\n    // named slots should only be respected if the vnode was rendered in the\n    // same context.\n    if ((child.context === context || child.functionalContext === context) &&\n      child.data && child.data.slot != null\n    ) {\n      const name = child.data.slot\n      const slot = (slots[name] || (slots[name] = []))\n      if (child.tag === 'template') {\n        slot.push.apply(slot, child.children)\n      } else {\n        slot.push(child)\n      }\n    } else {\n      defaultSlot.push(child)\n    }\n  }\n  // ignore whitespace\n  if (!defaultSlot.every(isWhitespace)) {\n    slots.default = defaultSlot\n  }\n  return slots\n}\n\nfunction isWhitespace (node: VNode): boolean {\n  return node.isComment || node.text === ' '\n}\n\nexport function resolveScopedSlots (\n  fns: ScopedSlotsData, // see flow/vnode\n  res?: Object\n): { [key: string]: Function } {\n  res = res || {}\n  for (let i = 0; i < fns.length; i++) {\n    if (Array.isArray(fns[i])) {\n      resolveScopedSlots(fns[i], res)\n    } else {\n      res[fns[i].key] = fns[i].fn\n    }\n  }\n  return res\n}\n"
  },
  {
    "path": "src/core/instance/render.js",
    "content": "/* @flow */\n\nimport {\n  warn,\n  nextTick,\n  toNumber,\n  toString,\n  looseEqual,\n  emptyObject,\n  handleError,\n  looseIndexOf,\n  defineReactive\n} from '../util/index'\n\nimport VNode, {\n  cloneVNodes,\n  createTextVNode,\n  createEmptyVNode\n} from '../vdom/vnode'\n\nimport { isUpdatingChildComponent } from './lifecycle'\n\nimport { createElement } from '../vdom/create-element'\nimport { renderList } from './render-helpers/render-list'\nimport { renderSlot } from './render-helpers/render-slot'\nimport { resolveFilter } from './render-helpers/resolve-filter'\nimport { checkKeyCodes } from './render-helpers/check-keycodes'\nimport { bindObjectProps } from './render-helpers/bind-object-props'\nimport { renderStatic, markOnce } from './render-helpers/render-static'\nimport { bindObjectListeners } from './render-helpers/bind-object-listeners'\nimport { resolveSlots, resolveScopedSlots } from './render-helpers/resolve-slots'\n\nexport function initRender (vm: Component) {\n  vm._vnode = null // the root of the child tree\n  vm._staticTrees = null\n  const parentVnode = vm.$vnode = vm.$options._parentVnode // the placeholder node in parent tree\n  const renderContext = parentVnode && parentVnode.context\n  vm.$slots = resolveSlots(vm.$options._renderChildren, renderContext)\n  vm.$scopedSlots = emptyObject\n  // bind the createElement fn to this instance\n  // so that we get proper render context inside it.\n  // args order: tag, data, children, normalizationType, alwaysNormalize\n  // internal version is used by render functions compiled from templates\n  vm._c = (a, b, c, d) => createElement(vm, a, b, c, d, false)\n  // normalization is always applied for the public version, used in\n  // user-written render functions.\n  vm.$createElement = (a, b, c, d) => createElement(vm, a, b, c, d, true)\n\n  // $attrs & $listeners are exposed for easier HOC creation.\n  // they need to be reactive so that HOCs using them are always updated\n  const parentData = parentVnode && parentVnode.data\n  /* istanbul ignore else */\n  if (process.env.NODE_ENV !== 'production') {\n    defineReactive(vm, '$attrs', parentData && parentData.attrs, () => {\n      !isUpdatingChildComponent && warn(`$attrs is readonly.`, vm)\n    }, true)\n    defineReactive(vm, '$listeners', parentData && parentData.on, () => {\n      !isUpdatingChildComponent && warn(`$listeners is readonly.`, vm)\n    }, true)\n  } else {\n    defineReactive(vm, '$attrs', parentData && parentData.attrs, null, true)\n    defineReactive(vm, '$listeners', parentData && parentData.on, null, true)\n  }\n}\n\nexport function renderMixin (Vue: Class<Component>) {\n  Vue.prototype.$nextTick = function (fn: Function) {\n    return nextTick(fn, this)\n  }\n\n  Vue.prototype._render = function (): VNode {\n    const vm: Component = this\n    const {\n      render,\n      staticRenderFns,\n      _parentVnode\n    } = vm.$options\n\n    if (vm._isMounted) {\n      // clone slot nodes on re-renders\n      for (const key in vm.$slots) {\n        vm.$slots[key] = cloneVNodes(vm.$slots[key])\n      }\n    }\n\n    vm.$scopedSlots = (_parentVnode && _parentVnode.data.scopedSlots) || emptyObject\n\n    if (staticRenderFns && !vm._staticTrees) {\n      vm._staticTrees = []\n    }\n    // set parent vnode. this allows render functions to have access\n    // to the data on the placeholder node.\n    vm.$vnode = _parentVnode\n    // render self\n    let vnode\n    try {\n      vnode = render.call(vm._renderProxy, vm.$createElement)\n    } catch (e) {\n      handleError(e, vm, `render function`)\n      // return error render result,\n      // or previous vnode to prevent render error causing blank component\n      /* istanbul ignore else */\n      if (process.env.NODE_ENV !== 'production') {\n        vnode = vm.$options.renderError\n          ? vm.$options.renderError.call(vm._renderProxy, vm.$createElement, e)\n          : vm._vnode\n      } else {\n        vnode = vm._vnode\n      }\n    }\n    // return empty vnode in case the render function errored out\n    if (!(vnode instanceof VNode)) {\n      if (process.env.NODE_ENV !== 'production' && Array.isArray(vnode)) {\n        warn(\n          'Multiple root nodes returned from render function. Render function ' +\n          'should return a single root node.',\n          vm\n        )\n      }\n      vnode = createEmptyVNode()\n    }\n    // set parent\n    vnode.parent = _parentVnode\n    return vnode\n  }\n\n  // internal render helpers.\n  // these are exposed on the instance prototype to reduce generated render\n  // code size.\n  Vue.prototype._o = markOnce\n  Vue.prototype._n = toNumber\n  Vue.prototype._s = toString\n  Vue.prototype._l = renderList\n  Vue.prototype._t = renderSlot\n  Vue.prototype._q = looseEqual\n  Vue.prototype._i = looseIndexOf\n  Vue.prototype._m = renderStatic\n  Vue.prototype._f = resolveFilter\n  Vue.prototype._k = checkKeyCodes\n  Vue.prototype._b = bindObjectProps\n  Vue.prototype._v = createTextVNode\n  Vue.prototype._e = createEmptyVNode\n  Vue.prototype._u = resolveScopedSlots\n  Vue.prototype._g = bindObjectListeners\n}\n"
  },
  {
    "path": "src/core/instance/state.js",
    "content": "/* @flow */\n\nimport config from '../config'\nimport Dep from '../observer/dep'\nimport Watcher from '../observer/watcher'\nimport { isUpdatingChildComponent } from './lifecycle'\n\nimport {\n  set,\n  del,\n  observe,\n  observerState,\n  defineReactive\n} from '../observer/index'\n\nimport {\n  warn,\n  bind,\n  noop,\n  hasOwn,\n  isReserved,\n  handleError,\n  nativeWatch,\n  validateProp,\n  isPlainObject,\n  isReservedAttribute\n} from '../util/index'\n\nconst sharedPropertyDefinition = {\n  enumerable: true,\n  configurable: true,\n  get: noop,\n  set: noop\n}\n\nexport function proxy (target: Object, sourceKey: string, key: string) {\n  sharedPropertyDefinition.get = function proxyGetter () {\n    return this[sourceKey][key]\n  }\n  sharedPropertyDefinition.set = function proxySetter (val) {\n    this[sourceKey][key] = val\n  }\n  Object.defineProperty(target, key, sharedPropertyDefinition)\n}\n\nexport function initState (vm: Component) {\n  vm._watchers = []\n  const opts = vm.$options\n  if (opts.props) initProps(vm, opts.props)\n  if (opts.methods) initMethods(vm, opts.methods)\n  if (opts.data) {\n    initData(vm)\n  } else {\n    observe(vm._data = {}, true /* asRootData */)\n  }\n  if (opts.computed) initComputed(vm, opts.computed)\n  if (opts.watch && opts.watch !== nativeWatch) {\n    initWatch(vm, opts.watch)\n  }\n}\n\nfunction checkOptionType (vm: Component, name: string) {\n  const option = vm.$options[name]\n  if (!isPlainObject(option)) {\n    warn(\n      `component option \"${name}\" should be an object.`,\n      vm\n    )\n  }\n}\n\nfunction initProps (vm: Component, propsOptions: Object) {\n  const propsData = vm.$options.propsData || {}\n  const props = vm._props = {}\n  // cache prop keys so that future props updates can iterate using Array\n  // instead of dynamic object key enumeration.\n  const keys = vm.$options._propKeys = []\n  const isRoot = !vm.$parent\n  // root instance props should be converted\n  observerState.shouldConvert = isRoot\n  for (const key in propsOptions) {\n    keys.push(key)\n    const value = validateProp(key, propsOptions, propsData, vm)\n    /* istanbul ignore else */\n    if (process.env.NODE_ENV !== 'production') {\n      if (isReservedAttribute(key) || config.isReservedAttr(key)) {\n        warn(\n          `\"${key}\" is a reserved attribute and cannot be used as component prop.`,\n          vm\n        )\n      }\n      defineReactive(props, key, value, () => {\n        if (vm.$parent && !isUpdatingChildComponent) {\n          warn(\n            `Avoid mutating a prop directly since the value will be ` +\n            `overwritten whenever the parent component re-renders. ` +\n            `Instead, use a data or computed property based on the prop's ` +\n            `value. Prop being mutated: \"${key}\"`,\n            vm\n          )\n        }\n      })\n    } else {\n      defineReactive(props, key, value)\n    }\n    // static props are already proxied on the component's prototype\n    // during Vue.extend(). We only need to proxy props defined at\n    // instantiation here.\n    if (!(key in vm)) {\n      proxy(vm, `_props`, key)\n    }\n  }\n  observerState.shouldConvert = true\n}\n\nfunction initData (vm: Component) {\n  let data = vm.$options.data\n  data = vm._data = typeof data === 'function'\n    ? getData(data, vm)\n    : data || {}\n  if (!isPlainObject(data)) {\n    data = {}\n    process.env.NODE_ENV !== 'production' && warn(\n      'data functions should return an object:\\n' +\n      'https://vuejs.org/v2/guide/components.html#data-Must-Be-a-Function',\n      vm\n    )\n  }\n  // proxy data on instance\n  const keys = Object.keys(data)\n  const props = vm.$options.props\n  const methods = vm.$options.methods\n  let i = keys.length\n  while (i--) {\n    const key = keys[i]\n    if (process.env.NODE_ENV !== 'production') {\n      if (methods && hasOwn(methods, key)) {\n        warn(\n          `method \"${key}\" has already been defined as a data property.`,\n          vm\n        )\n      }\n    }\n    if (props && hasOwn(props, key)) {\n      process.env.NODE_ENV !== 'production' && warn(\n        `The data property \"${key}\" is already declared as a prop. ` +\n        `Use prop default value instead.`,\n        vm\n      )\n    } else if (!isReserved(key)) {\n      proxy(vm, `_data`, key)\n    }\n  }\n  // observe data\n  observe(data, true /* asRootData */)\n}\n\nfunction getData (data: Function, vm: Component): any {\n  try {\n    return data.call(vm)\n  } catch (e) {\n    handleError(e, vm, `data()`)\n    return {}\n  }\n}\n\nconst computedWatcherOptions = { lazy: true }\n\nfunction initComputed (vm: Component, computed: Object) {\n  process.env.NODE_ENV !== 'production' && checkOptionType(vm, 'computed')\n  const watchers = vm._computedWatchers = Object.create(null)\n\n  for (const key in computed) {\n    const userDef = computed[key]\n    let getter = typeof userDef === 'function' ? userDef : userDef.get\n    if (process.env.NODE_ENV !== 'production') {\n      if (getter === undefined) {\n        warn(\n          `No getter function has been defined for computed property \"${key}\".`,\n          vm\n        )\n        getter = noop\n      }\n    }\n    // create internal watcher for the computed property.\n    watchers[key] = new Watcher(vm, getter, noop, computedWatcherOptions)\n\n    // component-defined computed properties are already defined on the\n    // component prototype. We only need to define computed properties defined\n    // at instantiation here.\n    if (!(key in vm)) {\n      defineComputed(vm, key, userDef)\n    } else if (process.env.NODE_ENV !== 'production') {\n      if (key in vm.$data) {\n        warn(`The computed property \"${key}\" is already defined in data.`, vm)\n      } else if (vm.$options.props && key in vm.$options.props) {\n        warn(`The computed property \"${key}\" is already defined as a prop.`, vm)\n      }\n    }\n  }\n}\n\nexport function defineComputed (target: any, key: string, userDef: Object | Function) {\n  if (typeof userDef === 'function') {\n    sharedPropertyDefinition.get = createComputedGetter(key)\n    sharedPropertyDefinition.set = noop\n  } else {\n    sharedPropertyDefinition.get = userDef.get\n      ? userDef.cache !== false\n        ? createComputedGetter(key)\n        : userDef.get\n      : noop\n    sharedPropertyDefinition.set = userDef.set\n      ? userDef.set\n      : noop\n  }\n  Object.defineProperty(target, key, sharedPropertyDefinition)\n}\n\nfunction createComputedGetter (key) {\n  return function computedGetter () {\n    const watcher = this._computedWatchers && this._computedWatchers[key]\n    if (watcher) {\n      if (watcher.dirty) {\n        watcher.evaluate()\n      }\n      if (Dep.target) {\n        watcher.depend()\n      }\n      return watcher.value\n    }\n  }\n}\n\nfunction initMethods (vm: Component, methods: Object) {\n  process.env.NODE_ENV !== 'production' && checkOptionType(vm, 'methods')\n  const props = vm.$options.props\n  for (const key in methods) {\n    vm[key] = methods[key] == null ? noop : bind(methods[key], vm)\n    if (process.env.NODE_ENV !== 'production') {\n      if (methods[key] == null) {\n        warn(\n          `method \"${key}\" has an undefined value in the component definition. ` +\n          `Did you reference the function correctly?`,\n          vm\n        )\n      }\n      if (props && hasOwn(props, key)) {\n        warn(\n          `method \"${key}\" has already been defined as a prop.`,\n          vm\n        )\n      }\n    }\n  }\n}\n\nfunction initWatch (vm: Component, watch: Object) {\n  process.env.NODE_ENV !== 'production' && checkOptionType(vm, 'watch')\n  for (const key in watch) {\n    const handler = watch[key]\n    if (Array.isArray(handler)) {\n      for (let i = 0; i < handler.length; i++) {\n        createWatcher(vm, key, handler[i])\n      }\n    } else {\n      createWatcher(vm, key, handler)\n    }\n  }\n}\n\nfunction createWatcher (\n  vm: Component,\n  keyOrFn: string | Function,\n  handler: any,\n  options?: Object\n) {\n  if (isPlainObject(handler)) {\n    options = handler\n    handler = handler.handler\n  }\n  if (typeof handler === 'string') {\n    handler = vm[handler]\n  }\n  return vm.$watch(keyOrFn, handler, options)\n}\n\nexport function stateMixin (Vue: Class<Component>) {\n  // flow somehow has problems with directly declared definition object\n  // when using Object.defineProperty, so we have to procedurally build up\n  // the object here.\n  const dataDef = {}\n  dataDef.get = function () { return this._data }\n  const propsDef = {}\n  propsDef.get = function () { return this._props }\n  if (process.env.NODE_ENV !== 'production') {\n    dataDef.set = function (newData: Object) {\n      warn(\n        'Avoid replacing instance root $data. ' +\n        'Use nested data properties instead.',\n        this\n      )\n    }\n    propsDef.set = function () {\n      warn(`$props is readonly.`, this)\n    }\n  }\n  Object.defineProperty(Vue.prototype, '$data', dataDef)\n  Object.defineProperty(Vue.prototype, '$props', propsDef)\n\n  Vue.prototype.$set = set\n  Vue.prototype.$delete = del\n\n  Vue.prototype.$watch = function (\n    expOrFn: string | Function,\n    cb: any,\n    options?: Object\n  ): Function {\n    const vm: Component = this\n    if (isPlainObject(cb)) {\n      return createWatcher(vm, expOrFn, cb, options)\n    }\n    options = options || {}\n    options.user = true\n    const watcher = new Watcher(vm, expOrFn, cb, options)\n    if (options.immediate) {\n      cb.call(vm, watcher.value)\n    }\n    return function unwatchFn () {\n      watcher.teardown()\n    }\n  }\n}\n"
  },
  {
    "path": "src/core/observer/array.js",
    "content": "/*\n * not type checking this file because flow doesn't play well with\n * dynamically accessing methods on Array prototype\n */\n\nimport { def } from '../util/index'\n\nconst arrayProto = Array.prototype\nexport const arrayMethods = Object.create(arrayProto)\n\n/**\n * Intercept mutating methods and emit events\n */\n;[\n  'push',\n  'pop',\n  'shift',\n  'unshift',\n  'splice',\n  'sort',\n  'reverse'\n]\n.forEach(function (method) {\n  // cache original method\n  const original = arrayProto[method]\n  def(arrayMethods, method, function mutator (...args) {\n    const result = original.apply(this, args)\n    const ob = this.__ob__\n    let inserted\n    switch (method) {\n      case 'push':\n      case 'unshift':\n        inserted = args\n        break\n      case 'splice':\n        inserted = args.slice(2)\n        break\n    }\n    if (inserted) ob.observeArray(inserted)\n    // notify change\n    ob.dep.notify()\n    return result\n  })\n})\n"
  },
  {
    "path": "src/core/observer/dep.js",
    "content": "/* @flow */\n\nimport type Watcher from './watcher'\nimport { remove } from '../util/index'\n\nlet uid = 0\n\n/**\n * A dep is an observable that can have multiple\n * directives subscribing to it.\n */\nexport default class Dep {\n  static target: ?Watcher;\n  id: number;\n  subs: Array<Watcher>;\n\n  constructor () {\n    this.id = uid++\n    this.subs = []\n  }\n\n  addSub (sub: Watcher) {\n    this.subs.push(sub)\n  }\n\n  removeSub (sub: Watcher) {\n    remove(this.subs, sub)\n  }\n\n  depend () {\n    if (Dep.target) {\n      Dep.target.addDep(this)\n    }\n  }\n\n  notify () {\n    // stabilize the subscriber list first\n    const subs = this.subs.slice()\n    for (let i = 0, l = subs.length; i < l; i++) {\n      subs[i].update()\n    }\n  }\n}\n\n// the current target watcher being evaluated.\n// this is globally unique because there could be only one\n// watcher being evaluated at any time.\nDep.target = null\nconst targetStack = []\n\nexport function pushTarget (_target: Watcher) {\n  if (Dep.target) targetStack.push(Dep.target)\n  Dep.target = _target\n}\n\nexport function popTarget () {\n  Dep.target = targetStack.pop()\n}\n"
  },
  {
    "path": "src/core/observer/index.js",
    "content": "/* @flow */\n\nimport Dep from './dep'\nimport { arrayMethods } from './array'\nimport {\n  def,\n  warn,\n  hasOwn,\n  hasProto,\n  isObject,\n  isPlainObject,\n  isValidArrayIndex,\n  isServerRendering\n} from '../util/index'\n\nconst arrayKeys = Object.getOwnPropertyNames(arrayMethods)\n\n/**\n * By default, when a reactive property is set, the new value is\n * also converted to become reactive. However when passing down props,\n * we don't want to force conversion because the value may be a nested value\n * under a frozen data structure. Converting it would defeat the optimization.\n */\nexport const observerState = {\n  shouldConvert: true\n}\n\n/**\n * Observer class that are attached to each observed\n * object. Once attached, the observer converts target\n * object's property keys into getter/setters that\n * collect dependencies and dispatches updates.\n */\nexport class Observer {\n  value: any;\n  dep: Dep;\n  vmCount: number; // number of vms that has this object as root $data\n\n  constructor (value: any, key: any) {\n    this.value = value\n    this.dep = new Dep()\n    this.vmCount = 0\n    if (key) {\n      this.key = key\n    }\n    def(value, '__ob__', this)\n    if (Array.isArray(value)) {\n      const augment = hasProto\n        ? protoAugment\n        : copyAugment\n      augment(value, arrayMethods, arrayKeys)\n      // 微信小程序中使用插件，数组对象上会直接挂载`push、pop、sort`等方法\n      // 导致mpvue对隐式原型的覆盖无效，无法感知用户对数组的操作\n      if (hasProto) {\n        const ownMethods = hasOwnArrayMethods(value, arrayKeys)\n        ownMethods.length && copyAugment(value, arrayMethods, ownMethods)\n      }\n      this.observeArray(value)\n    } else {\n      this.walk(value)\n    }\n  }\n\n  /**\n   * Walk through each property and convert them into\n   * getter/setters. This method should only be called when\n   * value type is Object.\n   */\n  walk (obj: Object) {\n    const keys = Object.keys(obj)\n    for (let i = 0; i < keys.length; i++) {\n      defineReactive(obj, keys[i], obj[keys[i]])\n    }\n  }\n\n  /**\n   * Observe a list of Array items.\n   */\n  observeArray (items: Array<any>) {\n    for (let i = 0, l = items.length; i < l; i++) {\n      observe(items[i])\n    }\n  }\n}\n\n/**\n * 判断当前数组上是否被挂载了数组方法\n */\nfunction hasOwnArrayMethods (value: Object, keys: Array<string>) {\n  const ownMethods = []\n  /* eslint-disable no-proto */\n  keys.forEach(key => {\n    if (value[key] !== value.__proto__[key]) {\n      ownMethods.push(key)\n    }\n  })\n  /* eslint-enable no-proto */\n  return ownMethods\n}\n\n// helpers\n\n/**\n * Augment an target Object or Array by intercepting\n * the prototype chain using __proto__\n */\nfunction protoAugment (target, src: Object, keys: any) {\n  /* eslint-disable no-proto */\n  target.__proto__ = src\n  /* eslint-enable no-proto */\n}\n\n/**\n * Augment an target Object or Array by defining\n * hidden properties.\n */\n/* istanbul ignore next */\nfunction copyAugment (target: Object, src: Object, keys: Array<string>) {\n  for (let i = 0, l = keys.length; i < l; i++) {\n    const key = keys[i]\n    def(target, key, src[key])\n  }\n}\n\n/**\n * Attempt to create an observer instance for a value,\n * returns the new observer if successfully observed,\n * or the existing observer if the value already has one.\n */\nexport function observe (value: any, asRootData: ?boolean, key: any): Observer | void {\n  if (!isObject(value)) {\n    return\n  }\n  let ob: Observer | void\n  if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) {\n    ob = value.__ob__\n  } else if (\n    observerState.shouldConvert &&\n    !isServerRendering() &&\n    (Array.isArray(value) || isPlainObject(value)) &&\n    Object.isExtensible(value) &&\n    !value._isVue\n  ) {\n    ob = new Observer(value, key)\n  }\n  if (asRootData && ob) {\n    ob.vmCount++\n  }\n  return ob\n}\n\n/**\n * Define a reactive property on an Object.\n */\nexport function defineReactive (\n  obj: Object,\n  key: string,\n  val: any,\n  customSetter?: ?Function,\n  shallow?: boolean\n) {\n  const dep = new Dep()\n\n  const property = Object.getOwnPropertyDescriptor(obj, key)\n  if (property && property.configurable === false) {\n    return\n  }\n\n  // cater for pre-defined getter/setters\n  const getter = property && property.get\n  const setter = property && property.set\n\n  let childOb = !shallow && observe(val, undefined, key)\n  Object.defineProperty(obj, key, {\n    enumerable: true,\n    configurable: true,\n    get: function reactiveGetter () {\n      const value = getter ? getter.call(obj) : val\n      if (Dep.target) {\n        dep.depend()\n        if (childOb) {\n          childOb.dep.depend()\n        }\n        if (Array.isArray(value)) {\n          dependArray(value)\n        }\n      }\n      return value\n    },\n    set: function reactiveSetter (newVal) {\n      const value = getter ? getter.call(obj) : val\n      /* eslint-disable no-self-compare */\n      if (newVal === value || (newVal !== newVal && value !== value)) {\n        return\n      }\n\n      /* eslint-enable no-self-compare */\n      if (process.env.NODE_ENV !== 'production' && customSetter) {\n        customSetter()\n      }\n      if (setter) {\n        setter.call(obj, newVal)\n      } else {\n        val = newVal\n      }\n      childOb = !shallow && observe(newVal, undefined, key)\n      dep.notify()\n\n      if (!obj.__keyPath) {\n        def(obj, '__keyPath', {}, false)\n      }\n      obj.__keyPath[key] = true\n      if (newVal instanceof Object && !(newVal instanceof Array)) {\n        // 标记是否是通过this.Obj = {} 赋值印发的改动，解决少更新问题#1305\n        def(newVal, '__newReference', true, false)\n      }\n    }\n  })\n}\n\n/**\n * Set a property on an object. Adds the new property and\n * triggers change notification if the property doesn't\n * already exist.\n */\nexport function set (target: Array<any> | Object, key: any, val: any): any {\n  if (Array.isArray(target) && isValidArrayIndex(key)) {\n    target.length = Math.max(target.length, key)\n    target.splice(key, 1, val)\n    return val\n  }\n  if (hasOwn(target, key)) {\n    target[key] = val\n    return val\n  }\n  const ob = (target: any).__ob__\n  if (target._isVue || (ob && ob.vmCount)) {\n    process.env.NODE_ENV !== 'production' && warn(\n      'Avoid adding reactive properties to a Vue instance or its root $data ' +\n      'at runtime - declare it upfront in the data option.'\n    )\n    return val\n  }\n  if (!ob) {\n    target[key] = val\n    return val\n  }\n  defineReactive(ob.value, key, val)\n  // Vue.set 添加对象属性，渲染时候把 val 传给小程序渲染\n  if (!target.__keyPath) {\n    def(target, '__keyPath', {}, false)\n  }\n  target.__keyPath[key] = true\n  ob.dep.notify()\n  return val\n}\n\n/**\n * Delete a property and trigger change if necessary.\n */\nexport function del (target: Array<any> | Object, key: any) {\n  if (Array.isArray(target) && isValidArrayIndex(key)) {\n    target.splice(key, 1)\n    return\n  }\n  const ob = (target: any).__ob__\n  if (target._isVue || (ob && ob.vmCount)) {\n    process.env.NODE_ENV !== 'production' && warn(\n      'Avoid deleting properties on a Vue instance or its root $data ' +\n      '- just set it to null.'\n    )\n    return\n  }\n  if (!hasOwn(target, key)) {\n    return\n  }\n  delete target[key]\n  if (!ob) {\n    return\n  }\n  if (!target.__keyPath) {\n    def(target, '__keyPath', {}, false)\n  }\n  // Vue.del 删除对象属性，渲染时候把这个属性设置为 undefined\n  target.__keyPath[key] = 'del'\n  ob.dep.notify()\n}\n\n/**\n * Collect dependencies on array elements when the array is touched, since\n * we cannot intercept array element access like property getters.\n */\nfunction dependArray (value: Array<any>) {\n  for (let e, i = 0, l = value.length; i < l; i++) {\n    e = value[i]\n    e && e.__ob__ && e.__ob__.dep.depend()\n    if (Array.isArray(e)) {\n      dependArray(e)\n    }\n  }\n}\n"
  },
  {
    "path": "src/core/observer/scheduler.js",
    "content": "/* @flow */\n\nimport type Watcher from './watcher'\nimport config from '../config'\nimport { callHook, activateChildComponent } from '../instance/lifecycle'\n\nimport {\n  warn,\n  nextTick,\n  devtools\n} from '../util/index'\n\nexport const MAX_UPDATE_COUNT = 100\n\nconst queue: Array<Watcher> = []\nconst activatedChildren: Array<Component> = []\nlet has: { [key: number]: ?true } = {}\nlet circular: { [key: number]: number } = {}\nlet waiting = false\nlet flushing = false\nlet index = 0\n\n/**\n * Reset the scheduler's state.\n */\nfunction resetSchedulerState () {\n  index = queue.length = activatedChildren.length = 0\n  has = {}\n  if (process.env.NODE_ENV !== 'production') {\n    circular = {}\n  }\n  waiting = flushing = false\n}\n\n/**\n * Flush both queues and run the watchers.\n */\nfunction flushSchedulerQueue () {\n  flushing = true\n  let watcher, id\n\n  // Sort queue before flush.\n  // This ensures that:\n  // 1. Components are updated from parent to child. (because parent is always\n  //    created before the child)\n  // 2. A component's user watchers are run before its render watcher (because\n  //    user watchers are created before the render watcher)\n  // 3. If a component is destroyed during a parent component's watcher run,\n  //    its watchers can be skipped.\n  queue.sort((a, b) => a.id - b.id)\n\n  // do not cache length because more watchers might be pushed\n  // as we run existing watchers\n  for (index = 0; index < queue.length; index++) {\n    watcher = queue[index]\n    id = watcher.id\n    has[id] = null\n    watcher.run()\n    // in dev build, check and stop circular updates.\n    if (process.env.NODE_ENV !== 'production' && has[id] != null) {\n      circular[id] = (circular[id] || 0) + 1\n      if (circular[id] > MAX_UPDATE_COUNT) {\n        warn(\n          'You may have an infinite update loop ' + (\n            watcher.user\n              ? `in watcher with expression \"${watcher.expression}\"`\n              : `in a component render function.`\n          ),\n          watcher.vm\n        )\n        break\n      }\n    }\n  }\n\n  // keep copies of post queues before resetting state\n  const activatedQueue = activatedChildren.slice()\n  const updatedQueue = queue.slice()\n\n  resetSchedulerState()\n\n  // call component updated and activated hooks\n  callActivatedHooks(activatedQueue)\n  callUpdatedHooks(updatedQueue)\n\n  // devtool hook\n  /* istanbul ignore if */\n  if (devtools && config.devtools) {\n    devtools.emit('flush')\n  }\n}\n\nfunction callUpdatedHooks (queue) {\n  let i = queue.length\n  while (i--) {\n    const watcher = queue[i]\n    const vm = watcher.vm\n    if (vm._watcher === watcher && vm._isMounted) {\n      callHook(vm, 'updated')\n    }\n  }\n}\n\n/**\n * Queue a kept-alive component that was activated during patch.\n * The queue will be processed after the entire tree has been patched.\n */\nexport function queueActivatedComponent (vm: Component) {\n  // setting _inactive to false here so that a render function can\n  // rely on checking whether it's in an inactive tree (e.g. router-view)\n  vm._inactive = false\n  activatedChildren.push(vm)\n}\n\nfunction callActivatedHooks (queue) {\n  for (let i = 0; i < queue.length; i++) {\n    queue[i]._inactive = true\n    activateChildComponent(queue[i], true /* true */)\n  }\n}\n\n/**\n * Push a watcher into the watcher queue.\n * Jobs with duplicate IDs will be skipped unless it's\n * pushed when the queue is being flushed.\n */\nexport function queueWatcher (watcher: Watcher) {\n  const id = watcher.id\n  if (has[id] == null) {\n    has[id] = true\n    if (!flushing) {\n      queue.push(watcher)\n    } else {\n      // if already flushing, splice the watcher based on its id\n      // if already past its id, it will be run next immediately.\n      let i = queue.length - 1\n      while (i > index && queue[i].id > watcher.id) {\n        i--\n      }\n      queue.splice(i + 1, 0, watcher)\n    }\n    // queue the flush\n    if (!waiting) {\n      waiting = true\n      nextTick(flushSchedulerQueue)\n    }\n  }\n}\n"
  },
  {
    "path": "src/core/observer/watcher.js",
    "content": "/* @flow */\n\nimport { queueWatcher } from './scheduler'\nimport Dep, { pushTarget, popTarget } from './dep'\n\nimport {\n  warn,\n  remove,\n  isObject,\n  parsePath,\n  _Set as Set,\n  handleError\n} from '../util/index'\n\nimport type { ISet } from '../util/index'\n\nlet uid = 0\n\n/**\n * A watcher parses an expression, collects dependencies,\n * and fires callback when the expression value changes.\n * This is used for both the $watch() api and directives.\n */\nexport default class Watcher {\n  vm: Component;\n  expression: string;\n  cb: Function;\n  id: number;\n  deep: boolean;\n  user: boolean;\n  lazy: boolean;\n  sync: boolean;\n  dirty: boolean;\n  active: boolean;\n  deps: Array<Dep>;\n  newDeps: Array<Dep>;\n  depIds: ISet;\n  newDepIds: ISet;\n  getter: Function;\n  value: any;\n\n  constructor (\n    vm: Component,\n    expOrFn: string | Function,\n    cb: Function,\n    options?: Object\n  ) {\n    this.vm = vm\n    vm._watchers.push(this)\n    // options\n    if (options) {\n      this.deep = !!options.deep\n      this.user = !!options.user\n      this.lazy = !!options.lazy\n      this.sync = !!options.sync\n    } else {\n      this.deep = this.user = this.lazy = this.sync = false\n    }\n    this.cb = cb\n    this.id = ++uid // uid for batching\n    this.active = true\n    this.dirty = this.lazy // for lazy watchers\n    this.deps = []\n    this.newDeps = []\n    this.depIds = new Set()\n    this.newDepIds = new Set()\n    this.expression = process.env.NODE_ENV !== 'production'\n      ? expOrFn.toString()\n      : ''\n    // parse expression for getter\n    if (typeof expOrFn === 'function') {\n      this.getter = expOrFn\n    } else {\n      this.getter = parsePath(expOrFn)\n      if (!this.getter) {\n        this.getter = function () {}\n        process.env.NODE_ENV !== 'production' && warn(\n          `Failed watching path: \"${expOrFn}\" ` +\n          'Watcher only accepts simple dot-delimited paths. ' +\n          'For full control, use a function instead.',\n          vm\n        )\n      }\n    }\n    this.value = this.lazy\n      ? undefined\n      : this.get()\n  }\n\n  /**\n   * Evaluate the getter, and re-collect dependencies.\n   */\n  get () {\n    pushTarget(this)\n    let value\n    const vm = this.vm\n    try {\n      value = this.getter.call(vm, vm)\n    } catch (e) {\n      if (this.user) {\n        handleError(e, vm, `getter for watcher \"${this.expression}\"`)\n      } else {\n        throw e\n      }\n    } finally {\n      // \"touch\" every property so they are all tracked as\n      // dependencies for deep watching\n      if (this.deep) {\n        traverse(value)\n      }\n      popTarget()\n      this.cleanupDeps()\n    }\n    return value\n  }\n\n  /**\n   * Add a dependency to this directive.\n   */\n  addDep (dep: Dep) {\n    const id = dep.id\n    if (!this.newDepIds.has(id)) {\n      this.newDepIds.add(id)\n      this.newDeps.push(dep)\n      if (!this.depIds.has(id)) {\n        dep.addSub(this)\n      }\n    }\n  }\n\n  /**\n   * Clean up for dependency collection.\n   */\n  cleanupDeps () {\n    let i = this.deps.length\n    while (i--) {\n      const dep = this.deps[i]\n      if (!this.newDepIds.has(dep.id)) {\n        dep.removeSub(this)\n      }\n    }\n    let tmp = this.depIds\n    this.depIds = this.newDepIds\n    this.newDepIds = tmp\n    this.newDepIds.clear()\n    tmp = this.deps\n    this.deps = this.newDeps\n    this.newDeps = tmp\n    this.newDeps.length = 0\n  }\n\n  /**\n   * Subscriber interface.\n   * Will be called when a dependency changes.\n   */\n  update () {\n    /* istanbul ignore else */\n    if (this.lazy) {\n      this.dirty = true\n    } else if (this.sync) {\n      this.run()\n    } else {\n      queueWatcher(this)\n    }\n  }\n\n  /**\n   * Scheduler job interface.\n   * Will be called by the scheduler.\n   */\n  run () {\n    if (this.active) {\n      const value = this.get()\n      if (\n        value !== this.value ||\n        // Deep watchers and watchers on Object/Arrays should fire even\n        // when the value is the same, because the value may\n        // have mutated.\n        isObject(value) ||\n        this.deep\n      ) {\n        // set new value\n        const oldValue = this.value\n        this.value = value\n        if (this.user) {\n          try {\n            this.cb.call(this.vm, value, oldValue)\n          } catch (e) {\n            handleError(e, this.vm, `callback for watcher \"${this.expression}\"`)\n          }\n        } else {\n          this.cb.call(this.vm, value, oldValue)\n        }\n      }\n    }\n  }\n\n  /**\n   * Evaluate the value of the watcher.\n   * This only gets called for lazy watchers.\n   */\n  evaluate () {\n    this.value = this.get()\n    this.dirty = false\n  }\n\n  /**\n   * Depend on all deps collected by this watcher.\n   */\n  depend () {\n    let i = this.deps.length\n    while (i--) {\n      this.deps[i].depend()\n    }\n  }\n\n  /**\n   * Remove self from all dependencies' subscriber list.\n   */\n  teardown () {\n    if (this.active) {\n      // remove self from vm's watcher list\n      // this is a somewhat expensive operation so we skip it\n      // if the vm is being destroyed.\n      if (!this.vm._isBeingDestroyed) {\n        remove(this.vm._watchers, this)\n      }\n      let i = this.deps.length\n      while (i--) {\n        this.deps[i].removeSub(this)\n      }\n      this.active = false\n    }\n  }\n}\n\n/**\n * Recursively traverse an object to evoke all converted\n * getters, so that every nested property inside the object\n * is collected as a \"deep\" dependency.\n */\nconst seenObjects = new Set()\nfunction traverse (val: any) {\n  seenObjects.clear()\n  _traverse(val, seenObjects)\n}\n\nfunction _traverse (val: any, seen: ISet) {\n  let i, keys\n  const isA = Array.isArray(val)\n  if ((!isA && !isObject(val)) || !Object.isExtensible(val)) {\n    return\n  }\n  if (val.__ob__) {\n    const depId = val.__ob__.dep.id\n    if (seen.has(depId)) {\n      return\n    }\n    seen.add(depId)\n  }\n  if (isA) {\n    i = val.length\n    while (i--) _traverse(val[i], seen)\n  } else {\n    keys = Object.keys(val)\n    i = keys.length\n    while (i--) _traverse(val[keys[i]], seen)\n  }\n}\n"
  },
  {
    "path": "src/core/util/debug.js",
    "content": "/* @flow */\n\nimport config from '../config'\nimport { noop } from 'shared/util'\n\nexport let warn = noop\nexport let tip = noop\nexport let formatComponentName: Function = (null: any) // work around flow check\n\nif (process.env.NODE_ENV !== 'production') {\n  const hasConsole = typeof console !== 'undefined'\n  const classifyRE = /(?:^|[-_])(\\w)/g\n  const classify = str => str\n    .replace(classifyRE, c => c.toUpperCase())\n    .replace(/[-_]/g, '')\n\n  warn = (msg, vm) => {\n    const trace = vm ? generateComponentTrace(vm) : ''\n\n    if (config.warnHandler) {\n      config.warnHandler.call(null, msg, vm, trace)\n    } else if (hasConsole && (!config.silent)) {\n      console.error(`[Vue warn]: ${msg}${trace}`)\n    }\n  }\n\n  tip = (msg, vm) => {\n    if (hasConsole && (!config.silent)) {\n      console.warn(`[Vue tip]: ${msg}` + (\n        vm ? generateComponentTrace(vm) : ''\n      ))\n    }\n  }\n\n  formatComponentName = (vm, includeFile) => {\n    if (vm.$root === vm) {\n      return '<Root>'\n    }\n    let name = typeof vm === 'string'\n      ? vm\n      : typeof vm === 'function' && vm.options\n        ? vm.options.name\n        : vm._isVue\n          ? vm.$options.name || vm.$options._componentTag\n          : vm.name\n\n    const file = vm._isVue && vm.$options.__file\n    if (!name && file) {\n      const match = file.match(/([^/\\\\]+)\\.vue$/)\n      name = match && match[1]\n    }\n\n    return (\n      (name ? `<${classify(name)}>` : `<Anonymous>`) +\n      (file && includeFile !== false ? ` at ${file}` : '')\n    )\n  }\n\n  const repeat = (str, n) => {\n    let res = ''\n    while (n) {\n      if (n % 2 === 1) res += str\n      if (n > 1) str += str\n      n >>= 1\n    }\n    return res\n  }\n\n  const generateComponentTrace = vm => {\n    if (vm._isVue && vm.$parent) {\n      const tree = []\n      let currentRecursiveSequence = 0\n      while (vm) {\n        if (tree.length > 0) {\n          const last = tree[tree.length - 1]\n          if (last.constructor === vm.constructor) {\n            currentRecursiveSequence++\n            vm = vm.$parent\n            continue\n          } else if (currentRecursiveSequence > 0) {\n            tree[tree.length - 1] = [last, currentRecursiveSequence]\n            currentRecursiveSequence = 0\n          }\n        }\n        tree.push(vm)\n        vm = vm.$parent\n      }\n      return '\\n\\nfound in\\n\\n' + tree\n        .map((vm, i) => `${\n          i === 0 ? '---> ' : repeat(' ', 5 + i * 2)\n        }${\n          Array.isArray(vm)\n            ? `${formatComponentName(vm[0])}... (${vm[1]} recursive calls)`\n            : formatComponentName(vm)\n        }`)\n        .join('\\n')\n    } else {\n      return `\\n\\n(found in ${formatComponentName(vm)})`\n    }\n  }\n}\n"
  },
  {
    "path": "src/core/util/env.js",
    "content": "/* @flow */\n\nimport { noop } from 'shared/util'\nimport { handleError } from './error'\n\n// can we use __proto__?\nexport const hasProto = '__proto__' in {}\n\n// Browser environment sniffing\nexport const inBrowser = typeof window !== 'undefined'\nexport const UA = inBrowser && window.navigator.userAgent.toLowerCase()\nexport const isIE = UA && /msie|trident/.test(UA)\nexport const isIE9 = UA && UA.indexOf('msie 9.0') > 0\nexport const isEdge = UA && UA.indexOf('edge/') > 0\nexport const isAndroid = UA && UA.indexOf('android') > 0\nexport const isIOS = UA && /iphone|ipad|ipod|ios/.test(UA)\nexport const isChrome = UA && /chrome\\/\\d+/.test(UA) && !isEdge\n\n// Firefix has a \"watch\" function on Object.prototype...\nexport const nativeWatch = ({}).watch\n\nexport let supportsPassive = false\nif (inBrowser) {\n  try {\n    const opts = {}\n    Object.defineProperty(opts, 'passive', ({\n      get () {\n        /* istanbul ignore next */\n        supportsPassive = true\n      }\n    }: Object)) // https://github.com/facebook/flow/issues/285\n    window.addEventListener('test-passive', null, opts)\n  } catch (e) {}\n}\n\n// this needs to be lazy-evaled because vue may be required before\n// vue-server-renderer can set VUE_ENV\nlet _isServer\nexport const isServerRendering = () => {\n  if (_isServer === undefined) {\n    /* istanbul ignore if */\n    if (!inBrowser && typeof global !== 'undefined') {\n      // detect presence of vue-server-renderer and avoid\n      // Webpack shimming the process\n      _isServer = global['process'].env.VUE_ENV === 'server'\n    } else {\n      _isServer = false\n    }\n  }\n  return _isServer\n}\n\n// detect devtools\nexport const devtools = inBrowser && window.__VUE_DEVTOOLS_GLOBAL_HOOK__\n\n/* istanbul ignore next */\nexport function isNative (Ctor: any): boolean {\n  return typeof Ctor === 'function' && /native code/.test(Ctor.toString())\n}\n\nexport const hasSymbol =\n  typeof Symbol !== 'undefined' && isNative(Symbol) &&\n  typeof Reflect !== 'undefined' && isNative(Reflect.ownKeys)\n\n/**\n * Defer a task to execute it asynchronously.\n */\nexport const nextTick = (function () {\n  const callbacks = []\n  let pending = false\n  let timerFunc\n\n  function nextTickHandler () {\n    pending = false\n    const copies = callbacks.slice(0)\n    callbacks.length = 0\n    for (let i = 0; i < copies.length; i++) {\n      copies[i]()\n    }\n  }\n\n  // the nextTick behavior leverages the microtask queue, which can be accessed\n  // via either native Promise.then or MutationObserver.\n  // MutationObserver has wider support, however it is seriously bugged in\n  // UIWebView in iOS >= 9.3.3 when triggered in touch event handlers. It\n  // completely stops working after triggering a few times... so, if native\n  // Promise is available, we will use it:\n  /* istanbul ignore if */\n  if (typeof Promise !== 'undefined' && isNative(Promise)) {\n    var p = Promise.resolve()\n    var logError = err => { console.error(err) }\n    timerFunc = () => {\n      p.then(nextTickHandler).catch(logError)\n      // in problematic UIWebViews, Promise.then doesn't completely break, but\n      // it can get stuck in a weird state where callbacks are pushed into the\n      // microtask queue but the queue isn't being flushed, until the browser\n      // needs to do some other work, e.g. handle a timer. Therefore we can\n      // \"force\" the microtask queue to be flushed by adding an empty timer.\n      if (isIOS) setTimeout(noop)\n    }\n  // } else if (typeof MutationObserver !== 'undefined' && (\n  //   isNative(MutationObserver) ||\n  //   // PhantomJS and iOS 7.x\n  //   MutationObserver.toString() === '[object MutationObserverConstructor]'\n  // )) {\n  //   // use MutationObserver where native Promise is not available,\n  //   // e.g. PhantomJS IE11, iOS7, Android 4.4\n  //   var counter = 1\n  //   var observer = new MutationObserver(nextTickHandler)\n  //   var textNode = document.createTextNode(String(counter))\n  //   observer.observe(textNode, {\n  //     characterData: true\n  //   })\n  //   timerFunc = () => {\n  //     counter = (counter + 1) % 2\n  //     textNode.data = String(counter)\n  //   }\n  } else {\n    // fallback to setTimeout\n    /* istanbul ignore next */\n    timerFunc = () => {\n      setTimeout(nextTickHandler, 0)\n    }\n  }\n\n  return function queueNextTick (cb?: Function, ctx?: Object) {\n    let _resolve\n    callbacks.push(() => {\n      if (cb) {\n        try {\n          cb.call(ctx)\n        } catch (e) {\n          handleError(e, ctx, 'nextTick')\n        }\n      } else if (_resolve) {\n        _resolve(ctx)\n      }\n    })\n    if (!pending) {\n      pending = true\n      timerFunc()\n    }\n    if (!cb && typeof Promise !== 'undefined') {\n      return new Promise((resolve, reject) => {\n        _resolve = resolve\n      })\n    }\n  }\n})()\n\nlet _Set\n/* istanbul ignore if */\nif (typeof Set !== 'undefined' && isNative(Set)) {\n  // use native Set when available.\n  _Set = Set\n} else {\n  // a non-standard Set polyfill that only works with primitive keys.\n  _Set = class Set implements ISet {\n    set: Object;\n    constructor () {\n      this.set = Object.create(null)\n    }\n    has (key: string | number) {\n      return this.set[key] === true\n    }\n    add (key: string | number) {\n      this.set[key] = true\n    }\n    clear () {\n      this.set = Object.create(null)\n    }\n  }\n}\n\ninterface ISet {\n  has(key: string | number): boolean;\n  add(key: string | number): mixed;\n  clear(): void;\n}\n\nexport { _Set }\nexport type { ISet }\n"
  },
  {
    "path": "src/core/util/error.js",
    "content": "/* @flow */\n\nimport config from '../config'\nimport { warn } from './debug'\nimport { inBrowser } from './env'\n\nexport function handleError (err: Error, vm: any, info: string) {\n  if (config.errorHandler) {\n    config.errorHandler.call(null, err, vm, info)\n  } else {\n    if (process.env.NODE_ENV !== 'production') {\n      warn(`Error in ${info}: \"${err.toString()}\"`, vm)\n    }\n    /* istanbul ignore else */\n    if (inBrowser && typeof console !== 'undefined') {\n      console.error(err)\n    } else {\n      throw err\n    }\n  }\n}\n"
  },
  {
    "path": "src/core/util/index.js",
    "content": "/* @flow */\n\nexport * from 'shared/util'\nexport * from './lang'\nexport * from './env'\nexport * from './options'\nexport * from './debug'\nexport * from './props'\nexport * from './error'\nexport { defineReactive } from '../observer/index'\n"
  },
  {
    "path": "src/core/util/lang.js",
    "content": "/* @flow */\n\nexport const emptyObject = Object.freeze({})\n\n/**\n * Check if a string starts with $ or _\n */\nexport function isReserved (str: string): boolean {\n  const c = (str + '').charCodeAt(0)\n  return c === 0x24 || c === 0x5F\n}\n\n/**\n * Define a property.\n */\nexport function def (obj: Object, key: string, val: any, enumerable?: boolean) {\n  Object.defineProperty(obj, key, {\n    value: val,\n    enumerable: !!enumerable,\n    writable: true,\n    configurable: true\n  })\n}\n\n/**\n * Parse simple path.\n */\nconst bailRE = /[^\\w.$]/\nexport function parsePath (path: string): any {\n  if (bailRE.test(path)) {\n    return\n  }\n  const segments = path.split('.')\n  return function (obj) {\n    for (let i = 0; i < segments.length; i++) {\n      if (!obj) return\n      obj = obj[segments[i]]\n    }\n    return obj\n  }\n}\n"
  },
  {
    "path": "src/core/util/options.js",
    "content": "/* @flow */\n\nimport config from '../config'\nimport { warn } from './debug'\nimport { nativeWatch } from './env'\nimport { set } from '../observer/index'\n\nimport {\n  ASSET_TYPES,\n  LIFECYCLE_HOOKS\n} from 'shared/constants'\n\nimport {\n  extend,\n  hasOwn,\n  camelize,\n  capitalize,\n  isBuiltInTag,\n  isPlainObject\n} from 'shared/util'\n\n/**\n * Option overwriting strategies are functions that handle\n * how to merge a parent option value and a child option\n * value into the final value.\n */\nconst strats = config.optionMergeStrategies\n\n/**\n * Options with restrictions\n */\nif (process.env.NODE_ENV !== 'production') {\n  strats.el = strats.propsData = function (parent, child, vm, key) {\n    if (!vm) {\n      warn(\n        `option \"${key}\" can only be used during instance ` +\n        'creation with the `new` keyword.'\n      )\n    }\n    return defaultStrat(parent, child)\n  }\n}\n\n/**\n * Helper that recursively merges two data objects together.\n */\nfunction mergeData (to: Object, from: ?Object): Object {\n  if (!from) return to\n  let key, toVal, fromVal\n  const keys = Object.keys(from)\n  for (let i = 0; i < keys.length; i++) {\n    key = keys[i]\n    toVal = to[key]\n    fromVal = from[key]\n    if (!hasOwn(to, key)) {\n      set(to, key, fromVal)\n    } else if (isPlainObject(toVal) && isPlainObject(fromVal)) {\n      mergeData(toVal, fromVal)\n    }\n  }\n  return to\n}\n\n/**\n * Data\n */\nexport function mergeDataOrFn (\n  parentVal: any,\n  childVal: any,\n  vm?: Component\n): ?Function {\n  if (!vm) {\n    // in a Vue.extend merge, both should be functions\n    if (!childVal) {\n      return parentVal\n    }\n    if (!parentVal) {\n      return childVal\n    }\n    // when parentVal & childVal are both present,\n    // we need to return a function that returns the\n    // merged result of both functions... no need to\n    // check if parentVal is a function here because\n    // it has to be a function to pass previous merges.\n    return function mergedDataFn () {\n      return mergeData(\n        typeof childVal === 'function' ? childVal.call(this) : childVal,\n        parentVal.call(this)\n      )\n    }\n  } else if (parentVal || childVal) {\n    return function mergedInstanceDataFn () {\n      // instance merge\n      const instanceData = typeof childVal === 'function'\n        ? childVal.call(vm)\n        : childVal\n      const defaultData = typeof parentVal === 'function'\n        ? parentVal.call(vm)\n        : undefined\n      if (instanceData) {\n        return mergeData(instanceData, defaultData)\n      } else {\n        return defaultData\n      }\n    }\n  }\n}\n\nstrats.data = function (\n  parentVal: any,\n  childVal: any,\n  vm?: Component\n): ?Function {\n  if (!vm) {\n    if (childVal && typeof childVal !== 'function') {\n      process.env.NODE_ENV !== 'production' && warn(\n        'The \"data\" option should be a function ' +\n        'that returns a per-instance value in component ' +\n        'definitions.',\n        vm\n      )\n\n      return parentVal\n    }\n    return mergeDataOrFn.call(this, parentVal, childVal)\n  }\n\n  return mergeDataOrFn(parentVal, childVal, vm)\n}\n\n/**\n * Hooks and props are merged as arrays.\n */\nfunction mergeHook (\n  parentVal: ?Array<Function>,\n  childVal: ?Function | ?Array<Function>\n): ?Array<Function> {\n  return childVal\n    ? parentVal\n      ? parentVal.concat(childVal)\n      : Array.isArray(childVal)\n        ? childVal\n        : [childVal]\n    : parentVal\n}\n\nLIFECYCLE_HOOKS.forEach(hook => {\n  strats[hook] = mergeHook\n})\n\n/**\n * Assets\n *\n * When a vm is present (instance creation), we need to do\n * a three-way merge between constructor options, instance\n * options and parent options.\n */\nfunction mergeAssets (parentVal: ?Object, childVal: ?Object): Object {\n  const res = Object.create(parentVal || null)\n  return childVal\n    ? extend(res, childVal)\n    : res\n}\n\nASSET_TYPES.forEach(function (type) {\n  strats[type + 's'] = mergeAssets\n})\n\n/**\n * Watchers.\n *\n * Watchers hashes should not overwrite one\n * another, so we merge them as arrays.\n */\nstrats.watch = function (parentVal: ?Object, childVal: ?Object): ?Object {\n  // work around Firefox's Object.prototype.watch...\n  if (parentVal === nativeWatch) parentVal = undefined\n  if (childVal === nativeWatch) childVal = undefined\n  /* istanbul ignore if */\n  if (!childVal) return Object.create(parentVal || null)\n  if (!parentVal) return childVal\n  const ret = {}\n  extend(ret, parentVal)\n  for (const key in childVal) {\n    let parent = ret[key]\n    const child = childVal[key]\n    if (parent && !Array.isArray(parent)) {\n      parent = [parent]\n    }\n    ret[key] = parent\n      ? parent.concat(child)\n      : Array.isArray(child) ? child : [child]\n  }\n  return ret\n}\n\n/**\n * Other object hashes.\n */\nstrats.props =\nstrats.methods =\nstrats.inject =\nstrats.computed = function (parentVal: ?Object, childVal: ?Object): ?Object {\n  if (!childVal) return Object.create(parentVal || null)\n  if (!parentVal) return childVal\n  const ret = Object.create(null)\n  extend(ret, parentVal)\n  extend(ret, childVal)\n  return ret\n}\nstrats.provide = mergeDataOrFn\n\n/**\n * Default strategy.\n */\nconst defaultStrat = function (parentVal: any, childVal: any): any {\n  return childVal === undefined\n    ? parentVal\n    : childVal\n}\n\n/**\n * Validate component names\n */\nfunction checkComponents (options: Object) {\n  for (const key in options.components) {\n    const lower = key.toLowerCase()\n    if (isBuiltInTag(lower) || config.isReservedTag(lower)) {\n      warn(\n        'Do not use built-in or reserved HTML elements as component ' +\n        'id: ' + key\n      )\n    }\n  }\n}\n\n/**\n * Ensure all props option syntax are normalized into the\n * Object-based format.\n */\nfunction normalizeProps (options: Object) {\n  const props = options.props\n  if (!props) return\n  const res = {}\n  let i, val, name\n  if (Array.isArray(props)) {\n    i = props.length\n    while (i--) {\n      val = props[i]\n      if (typeof val === 'string') {\n        name = camelize(val)\n        res[name] = { type: null }\n      } else if (process.env.NODE_ENV !== 'production') {\n        warn('props must be strings when using array syntax.')\n      }\n    }\n  } else if (isPlainObject(props)) {\n    for (const key in props) {\n      val = props[key]\n      name = camelize(key)\n      res[name] = isPlainObject(val)\n        ? val\n        : { type: val }\n    }\n  }\n  options.props = res\n}\n\n/**\n * Normalize all injections into Object-based format\n */\nfunction normalizeInject (options: Object) {\n  const inject = options.inject\n  if (Array.isArray(inject)) {\n    const normalized = options.inject = {}\n    for (let i = 0; i < inject.length; i++) {\n      normalized[inject[i]] = inject[i]\n    }\n  }\n}\n\n/**\n * Normalize raw function directives into object format.\n */\nfunction normalizeDirectives (options: Object) {\n  const dirs = options.directives\n  if (dirs) {\n    for (const key in dirs) {\n      const def = dirs[key]\n      if (typeof def === 'function') {\n        dirs[key] = { bind: def, update: def }\n      }\n    }\n  }\n}\n\n/**\n * Merge two option objects into a new one.\n * Core utility used in both instantiation and inheritance.\n */\nexport function mergeOptions (\n  parent: Object,\n  child: Object,\n  vm?: Component\n): Object {\n  if (process.env.NODE_ENV !== 'production') {\n    checkComponents(child)\n  }\n\n  if (typeof child === 'function') {\n    child = child.options\n  }\n\n  normalizeProps(child)\n  normalizeInject(child)\n  normalizeDirectives(child)\n  const extendsFrom = child.extends\n  if (extendsFrom) {\n    parent = mergeOptions(parent, extendsFrom, vm)\n  }\n  if (child.mixins) {\n    for (let i = 0, l = child.mixins.length; i < l; i++) {\n      parent = mergeOptions(parent, child.mixins[i], vm)\n    }\n  }\n  const options = {}\n  let key\n  for (key in parent) {\n    mergeField(key)\n  }\n  for (key in child) {\n    if (!hasOwn(parent, key)) {\n      mergeField(key)\n    }\n  }\n  function mergeField (key) {\n    const strat = strats[key] || defaultStrat\n    options[key] = strat(parent[key], child[key], vm, key)\n  }\n  return options\n}\n\n/**\n * Resolve an asset.\n * This function is used because child instances need access\n * to assets defined in its ancestor chain.\n */\nexport function resolveAsset (\n  options: Object,\n  type: string,\n  id: string,\n  warnMissing?: boolean\n): any {\n  /* istanbul ignore if */\n  if (typeof id !== 'string') {\n    return\n  }\n  const assets = options[type]\n  // check local registration variations first\n  if (hasOwn(assets, id)) return assets[id]\n  const camelizedId = camelize(id)\n  if (hasOwn(assets, camelizedId)) return assets[camelizedId]\n  const PascalCaseId = capitalize(camelizedId)\n  if (hasOwn(assets, PascalCaseId)) return assets[PascalCaseId]\n  // fallback to prototype chain\n  const res = assets[id] || assets[camelizedId] || assets[PascalCaseId]\n  if (process.env.NODE_ENV !== 'production' && warnMissing && !res) {\n    warn(\n      'Failed to resolve ' + type.slice(0, -1) + ': ' + id,\n      options\n    )\n  }\n  return res\n}\n"
  },
  {
    "path": "src/core/util/perf.js",
    "content": "import { inBrowser } from './env'\n\nexport let mark\nexport let measure\n\nif (process.env.NODE_ENV !== 'production') {\n  const perf = inBrowser && window.performance\n  /* istanbul ignore if */\n  if (\n    perf &&\n    perf.mark &&\n    perf.measure &&\n    perf.clearMarks &&\n    perf.clearMeasures\n  ) {\n    mark = tag => perf.mark(tag)\n    measure = (name, startTag, endTag) => {\n      perf.measure(name, startTag, endTag)\n      perf.clearMarks(startTag)\n      perf.clearMarks(endTag)\n      perf.clearMeasures(name)\n    }\n  }\n}\n"
  },
  {
    "path": "src/core/util/props.js",
    "content": "/* @flow */\n\nimport { warn } from './debug'\nimport { observe, observerState } from '../observer/index'\nimport {\n  hasOwn,\n  isObject,\n  hyphenate,\n  capitalize,\n  isPlainObject\n} from 'shared/util'\n\ntype PropOptions = {\n  type: Function | Array<Function> | null,\n  default: any,\n  required: ?boolean,\n  validator: ?Function\n};\n\nexport function validateProp (\n  key: string,\n  propOptions: Object,\n  propsData: Object,\n  vm?: Component\n): any {\n  const prop = propOptions[key]\n  const absent = !hasOwn(propsData, key)\n  let value = propsData[key]\n  // handle boolean props\n  if (isType(Boolean, prop.type)) {\n    if (absent && !hasOwn(prop, 'default')) {\n      value = false\n    } else if (!isType(String, prop.type) && (value === '' || value === hyphenate(key))) {\n      value = true\n    }\n  }\n  // check default value\n  if (value === undefined) {\n    value = getPropDefaultValue(vm, prop, key)\n    // since the default value is a fresh copy,\n    // make sure to observe it.\n    const prevShouldConvert = observerState.shouldConvert\n    observerState.shouldConvert = true\n    observe(value)\n    observerState.shouldConvert = prevShouldConvert\n  }\n  if (process.env.NODE_ENV !== 'production') {\n    assertProp(prop, key, value, vm, absent)\n  }\n  return value\n}\n\n/**\n * Get the default value of a prop.\n */\nfunction getPropDefaultValue (vm: ?Component, prop: PropOptions, key: string): any {\n  // no default, return undefined\n  if (!hasOwn(prop, 'default')) {\n    return undefined\n  }\n  const def = prop.default\n  // warn against non-factory defaults for Object & Array\n  if (process.env.NODE_ENV !== 'production' && isObject(def)) {\n    warn(\n      'Invalid default value for prop \"' + key + '\": ' +\n      'Props with type Object/Array must use a factory function ' +\n      'to return the default value.',\n      vm\n    )\n  }\n  // the raw prop value was also undefined from previous render,\n  // return previous default value to avoid unnecessary watcher trigger\n  if (vm && vm.$options.propsData &&\n    vm.$options.propsData[key] === undefined &&\n    vm._props[key] !== undefined\n  ) {\n    return vm._props[key]\n  }\n  // call factory function for non-Function types\n  // a value is Function if its prototype is function even across different execution context\n  return typeof def === 'function' && getType(prop.type) !== 'Function'\n    ? def.call(vm)\n    : def\n}\n\n/**\n * Assert whether a prop is valid.\n */\nfunction assertProp (\n  prop: PropOptions,\n  name: string,\n  value: any,\n  vm: ?Component,\n  absent: boolean\n) {\n  if (prop.required && absent) {\n    warn(\n      'Missing required prop: \"' + name + '\"',\n      vm\n    )\n    return\n  }\n  if (value == null && !prop.required) {\n    return\n  }\n  let type = prop.type\n  let valid = !type || type === true\n  const expectedTypes = []\n  if (type) {\n    if (!Array.isArray(type)) {\n      type = [type]\n    }\n    for (let i = 0; i < type.length && !valid; i++) {\n      const assertedType = assertType(value, type[i])\n      expectedTypes.push(assertedType.expectedType || '')\n      valid = assertedType.valid\n    }\n  }\n  if (!valid) {\n    warn(\n      'Invalid prop: type check failed for prop \"' + name + '\".' +\n      ' Expected ' + expectedTypes.map(capitalize).join(', ') +\n      ', got ' + Object.prototype.toString.call(value).slice(8, -1) + '.',\n      vm\n    )\n    return\n  }\n  const validator = prop.validator\n  if (validator) {\n    if (!validator(value)) {\n      warn(\n        'Invalid prop: custom validator check failed for prop \"' + name + '\".',\n        vm\n      )\n    }\n  }\n}\n\nconst simpleCheckRE = /^(String|Number|Boolean|Function|Symbol)$/\n\nfunction assertType (value: any, type: Function): {\n  valid: boolean;\n  expectedType: string;\n} {\n  let valid\n  const expectedType = getType(type)\n  if (simpleCheckRE.test(expectedType)) {\n    valid = typeof value === expectedType.toLowerCase()\n  } else if (expectedType === 'Object') {\n    valid = isPlainObject(value)\n  } else if (expectedType === 'Array') {\n    valid = Array.isArray(value)\n  } else {\n    valid = value instanceof type\n  }\n  return {\n    valid,\n    expectedType\n  }\n}\n\n/**\n * Use function string name to check built-in types,\n * because a simple equality check will fail when running\n * across different vms / iframes.\n */\nfunction getType (fn) {\n  const match = fn && fn.toString().match(/^\\s*function (\\w+)/)\n  return match ? match[1] : ''\n}\n\nfunction isType (type, fn) {\n  if (!Array.isArray(fn)) {\n    return getType(fn) === getType(type)\n  }\n  for (let i = 0, len = fn.length; i < len; i++) {\n    if (getType(fn[i]) === getType(type)) {\n      return true\n    }\n  }\n  /* istanbul ignore next */\n  return false\n}\n"
  },
  {
    "path": "src/core/vdom/create-component.js",
    "content": "/* @flow */\n\nimport VNode from './vnode'\nimport { resolveConstructorOptions } from 'core/instance/init'\nimport { queueActivatedComponent } from 'core/observer/scheduler'\nimport { createFunctionalComponent } from './create-functional-component'\n\nimport {\n  warn,\n  isDef,\n  isUndef,\n  isTrue,\n  isObject\n} from '../util/index'\n\nimport {\n  resolveAsyncComponent,\n  createAsyncPlaceholder,\n  extractPropsFromVNodeData\n} from './helpers/index'\n\nimport {\n  callHook,\n  activeInstance,\n  updateChildComponent,\n  activateChildComponent,\n  deactivateChildComponent\n} from '../instance/lifecycle'\n\n// hooks to be invoked on component VNodes during patch\nconst componentVNodeHooks = {\n  init (\n    vnode: VNodeWithData,\n    hydrating: boolean,\n    parentElm: ?Node,\n    refElm: ?Node\n  ): ?boolean {\n    if (!vnode.componentInstance || vnode.componentInstance._isDestroyed) {\n      const child = vnode.componentInstance = createComponentInstanceForVnode(\n        vnode,\n        activeInstance,\n        parentElm,\n        refElm\n      )\n      child.$mount(hydrating ? vnode.elm : undefined, hydrating)\n    } else if (vnode.data.keepAlive) {\n      // kept-alive components, treat as a patch\n      const mountedNode: any = vnode // work around flow\n      componentVNodeHooks.prepatch(mountedNode, mountedNode)\n    }\n  },\n\n  prepatch (oldVnode: MountedComponentVNode, vnode: MountedComponentVNode) {\n    const options = vnode.componentOptions\n    const child = vnode.componentInstance = oldVnode.componentInstance\n    updateChildComponent(\n      child,\n      options.propsData, // updated props\n      options.listeners, // updated listeners\n      vnode, // new parent vnode\n      options.children // new children\n    )\n  },\n\n  insert (vnode: MountedComponentVNode) {\n    const { context, componentInstance } = vnode\n\n    if (!componentInstance._isMounted) {\n      componentInstance._isMounted = true\n      callHook(componentInstance, 'mounted')\n    }\n    if (vnode.data.keepAlive) {\n      if (context._isMounted) {\n        // vue-router#1212\n        // During updates, a kept-alive component's child components may\n        // change, so directly walking the tree here may call activated hooks\n        // on incorrect children. Instead we push them into a queue which will\n        // be processed after the whole patch process ended.\n        queueActivatedComponent(componentInstance)\n      } else {\n        activateChildComponent(componentInstance, true /* direct */)\n      }\n    }\n  },\n\n  destroy (vnode: MountedComponentVNode) {\n    const { componentInstance } = vnode\n    if (!componentInstance._isDestroyed) {\n      if (!vnode.data.keepAlive) {\n        componentInstance.$destroy()\n      } else {\n        deactivateChildComponent(componentInstance, true /* direct */)\n      }\n    }\n  }\n}\n\nconst hooksToMerge = Object.keys(componentVNodeHooks)\n\nexport function createComponent (\n  Ctor: Class<Component> | Function | Object | void,\n  data: ?VNodeData,\n  context: Component,\n  children: ?Array<VNode>,\n  tag?: string\n): VNode | void {\n  if (isUndef(Ctor)) {\n    return\n  }\n\n  const baseCtor = context.$options._base\n\n  // plain options object: turn it into a constructor\n  if (isObject(Ctor)) {\n    Ctor = baseCtor.extend(Ctor)\n  }\n\n  // if at this stage it's not a constructor or an async component factory,\n  // reject.\n  if (typeof Ctor !== 'function') {\n    if (process.env.NODE_ENV !== 'production') {\n      warn(`Invalid Component definition: ${String(Ctor)}`, context)\n    }\n    return\n  }\n\n  // async component\n  let asyncFactory\n  if (isUndef(Ctor.cid)) {\n    asyncFactory = Ctor\n    Ctor = resolveAsyncComponent(asyncFactory, baseCtor, context)\n    if (Ctor === undefined) {\n      // return a placeholder node for async component, which is rendered\n      // as a comment node but preserves all the raw information for the node.\n      // the information will be used for async server-rendering and hydration.\n      return createAsyncPlaceholder(\n        asyncFactory,\n        data,\n        context,\n        children,\n        tag\n      )\n    }\n  }\n\n  data = data || {}\n\n  // resolve constructor options in case global mixins are applied after\n  // component constructor creation\n  resolveConstructorOptions(Ctor)\n\n  // transform component v-model data into props & events\n  if (isDef(data.model)) {\n    transformModel(Ctor.options, data)\n  }\n\n  // extract props\n  const propsData = extractPropsFromVNodeData(data, Ctor, tag)\n\n  // functional component\n  if (isTrue(Ctor.options.functional)) {\n    return createFunctionalComponent(Ctor, propsData, data, context, children)\n  }\n\n  // keep listeners\n  const listeners = data.on\n\n  if (isTrue(Ctor.options.abstract)) {\n    // abstract components do not keep anything\n    // other than props & listeners & slot\n\n    // work around flow\n    const slot = data.slot\n    data = {}\n    if (slot) {\n      data.slot = slot\n    }\n  }\n\n  // merge component management hooks onto the placeholder node\n  mergeHooks(data)\n\n  // return a placeholder vnode\n  const name = Ctor.options.name || tag\n  const vnode = new VNode(\n    `vue-component-${Ctor.cid}${name ? `-${name}` : ''}`,\n    data, undefined, undefined, undefined, context,\n    { Ctor, propsData, listeners, tag, children },\n    asyncFactory\n  )\n  return vnode\n}\n\nexport function createComponentInstanceForVnode (\n  vnode: any, // we know it's MountedComponentVNode but flow doesn't\n  parent: any, // activeInstance in lifecycle state\n  parentElm?: ?Node,\n  refElm?: ?Node\n): Component {\n  const vnodeComponentOptions = vnode.componentOptions\n  const options: InternalComponentOptions = {\n    _isComponent: true,\n    parent,\n    propsData: vnodeComponentOptions.propsData,\n    _componentTag: vnodeComponentOptions.tag,\n    _parentVnode: vnode,\n    _parentListeners: vnodeComponentOptions.listeners,\n    _renderChildren: vnodeComponentOptions.children,\n    _parentElm: parentElm || null,\n    _refElm: refElm || null\n  }\n  // check inline-template render functions\n  const inlineTemplate = vnode.data.inlineTemplate\n  if (isDef(inlineTemplate)) {\n    options.render = inlineTemplate.render\n    options.staticRenderFns = inlineTemplate.staticRenderFns\n  }\n  return new vnodeComponentOptions.Ctor(options)\n}\n\nfunction mergeHooks (data: VNodeData) {\n  if (!data.hook) {\n    data.hook = {}\n  }\n  for (let i = 0; i < hooksToMerge.length; i++) {\n    const key = hooksToMerge[i]\n    const fromParent = data.hook[key]\n    const ours = componentVNodeHooks[key]\n    data.hook[key] = fromParent ? mergeHook(ours, fromParent) : ours\n  }\n}\n\nfunction mergeHook (one: Function, two: Function): Function {\n  return function (a, b, c, d) {\n    one(a, b, c, d)\n    two(a, b, c, d)\n  }\n}\n\n// transform component v-model info (value and callback) into\n// prop and event handler respectively.\nfunction transformModel (options, data: any) {\n  const prop = (options.model && options.model.prop) || 'value'\n  const event = (options.model && options.model.event) || 'input'\n  ;(data.props || (data.props = {}))[prop] = data.model.value\n  const on = data.on || (data.on = {})\n  if (isDef(on[event])) {\n    on[event] = [data.model.callback].concat(on[event])\n  } else {\n    on[event] = data.model.callback\n  }\n}\n"
  },
  {
    "path": "src/core/vdom/create-element.js",
    "content": "/* @flow */\n\nimport config from '../config'\nimport VNode, { createEmptyVNode } from './vnode'\nimport { createComponent } from './create-component'\n\nimport {\n  warn,\n  isDef,\n  isUndef,\n  isTrue,\n  isPrimitive,\n  resolveAsset\n} from '../util/index'\n\nimport {\n  normalizeChildren,\n  simpleNormalizeChildren\n} from './helpers/index'\n\nconst SIMPLE_NORMALIZE = 1\nconst ALWAYS_NORMALIZE = 2\n\n// wrapper function for providing a more flexible interface\n// without getting yelled at by flow\nexport function createElement (\n  context: Component,\n  tag: any,\n  data: any,\n  children: any,\n  normalizationType: any,\n  alwaysNormalize: boolean\n): VNode {\n  if (Array.isArray(data) || isPrimitive(data)) {\n    normalizationType = children\n    children = data\n    data = undefined\n  }\n  if (isTrue(alwaysNormalize)) {\n    normalizationType = ALWAYS_NORMALIZE\n  }\n  return _createElement(context, tag, data, children, normalizationType)\n}\n\nexport function _createElement (\n  context: Component,\n  tag?: string | Class<Component> | Function | Object,\n  data?: VNodeData,\n  children?: any,\n  normalizationType?: number\n): VNode {\n  if (isDef(data) && isDef((data: any).__ob__)) {\n    process.env.NODE_ENV !== 'production' && warn(\n      `Avoid using observed data object as vnode data: ${JSON.stringify(data)}\\n` +\n      'Always create fresh vnode data objects in each render!',\n      context\n    )\n    return createEmptyVNode()\n  }\n  // object syntax in v-bind\n  if (isDef(data) && isDef(data.is)) {\n    tag = data.is\n  }\n  if (!tag) {\n    // in case of component :is set to falsy value\n    return createEmptyVNode()\n  }\n  // warn against non-primitive key\n  if (process.env.NODE_ENV !== 'production' &&\n    isDef(data) && isDef(data.key) && !isPrimitive(data.key)\n  ) {\n    warn(\n      'Avoid using non-primitive value as key, ' +\n      'use string/number value instead.',\n      context\n    )\n  }\n  // support single function children as default scoped slot\n  if (Array.isArray(children) &&\n    typeof children[0] === 'function'\n  ) {\n    data = data || {}\n    data.scopedSlots = { default: children[0] }\n    children.length = 0\n  }\n  if (normalizationType === ALWAYS_NORMALIZE) {\n    children = normalizeChildren(children)\n  } else if (normalizationType === SIMPLE_NORMALIZE) {\n    children = simpleNormalizeChildren(children)\n  }\n  let vnode, ns\n  if (typeof tag === 'string') {\n    let Ctor\n    ns = config.getTagNamespace(tag)\n    if (config.isReservedTag(tag)) {\n      // platform built-in elements\n      vnode = new VNode(\n        config.parsePlatformTagName(tag), data, children,\n        undefined, undefined, context\n      )\n    } else if (isDef(Ctor = resolveAsset(context.$options, 'components', tag))) {\n      // component\n      vnode = createComponent(Ctor, data, context, children, tag)\n    } else {\n      // unknown or unlisted namespaced elements\n      // check at runtime because it may get assigned a namespace when its\n      // parent normalizes children\n      vnode = new VNode(\n        tag, data, children,\n        undefined, undefined, context\n      )\n    }\n  } else {\n    // direct component options / constructor\n    vnode = createComponent(tag, data, context, children)\n  }\n  if (isDef(vnode)) {\n    if (ns) applyNS(vnode, ns)\n    return vnode\n  } else {\n    return createEmptyVNode()\n  }\n}\n\nfunction applyNS (vnode, ns) {\n  vnode.ns = ns\n  if (vnode.tag === 'foreignObject') {\n    // use default namespace inside foreignObject\n    return\n  }\n  if (isDef(vnode.children)) {\n    for (let i = 0, l = vnode.children.length; i < l; i++) {\n      const child = vnode.children[i]\n      if (isDef(child.tag) && isUndef(child.ns)) {\n        applyNS(child, ns)\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "src/core/vdom/create-functional-component.js",
    "content": "/* @flow */\n\nimport VNode from './vnode'\nimport { createElement } from './create-element'\nimport { resolveInject } from '../instance/inject'\nimport { resolveSlots } from '../instance/render-helpers/resolve-slots'\n\nimport {\n  isDef,\n  camelize,\n  validateProp\n} from '../util/index'\n\nexport function createFunctionalComponent (\n  Ctor: Class<Component>,\n  propsData: ?Object,\n  data: VNodeData,\n  context: Component,\n  children: ?Array<VNode>\n): VNode | void {\n  const props = {}\n  const propOptions = Ctor.options.props\n  if (isDef(propOptions)) {\n    for (const key in propOptions) {\n      props[key] = validateProp(key, propOptions, propsData || {})\n    }\n  } else {\n    if (isDef(data.attrs)) mergeProps(props, data.attrs)\n    if (isDef(data.props)) mergeProps(props, data.props)\n  }\n  // ensure the createElement function in functional components\n  // gets a unique context - this is necessary for correct named slot check\n  const _context = Object.create(context)\n  const h = (a, b, c, d) => createElement(_context, a, b, c, d, true)\n  const vnode = Ctor.options.render.call(null, h, {\n    data,\n    props,\n    children,\n    parent: context,\n    listeners: data.on || {},\n    injections: resolveInject(Ctor.options.inject, context),\n    slots: () => resolveSlots(children, context)\n  })\n  if (vnode instanceof VNode) {\n    vnode.functionalContext = context\n    vnode.functionalOptions = Ctor.options\n    if (data.slot) {\n      (vnode.data || (vnode.data = {})).slot = data.slot\n    }\n  }\n  return vnode\n}\n\nfunction mergeProps (to, from) {\n  for (const key in from) {\n    to[camelize(key)] = from[key]\n  }\n}\n"
  },
  {
    "path": "src/core/vdom/helpers/extract-props.js",
    "content": "/* @flow */\n\nimport {\n  tip,\n  hasOwn,\n  isDef,\n  isUndef,\n  hyphenate,\n  formatComponentName\n} from 'core/util/index'\n\nexport function extractPropsFromVNodeData (\n  data: VNodeData,\n  Ctor: Class<Component>,\n  tag?: string\n): ?Object {\n  // we are only extracting raw values here.\n  // validation and default values are handled in the child\n  // component itself.\n  const propOptions = Ctor.options.props\n  if (isUndef(propOptions)) {\n    return\n  }\n  const res = {}\n  const { attrs, props } = data\n  if (isDef(attrs) || isDef(props)) {\n    for (const key in propOptions) {\n      const altKey = hyphenate(key)\n      if (process.env.NODE_ENV !== 'production') {\n        const keyInLowerCase = key.toLowerCase()\n        if (\n          key !== keyInLowerCase &&\n          attrs && hasOwn(attrs, keyInLowerCase)\n        ) {\n          tip(\n            `Prop \"${keyInLowerCase}\" is passed to component ` +\n            `${formatComponentName(tag || Ctor)}, but the declared prop name is` +\n            ` \"${key}\". ` +\n            `Note that HTML attributes are case-insensitive and camelCased ` +\n            `props need to use their kebab-case equivalents when using in-DOM ` +\n            `templates. You should probably use \"${altKey}\" instead of \"${key}\".`\n          )\n        }\n      }\n      checkProp(res, props, key, altKey, true) ||\n      checkProp(res, attrs, key, altKey, false)\n    }\n  }\n  return res\n}\n\nfunction checkProp (\n  res: Object,\n  hash: ?Object,\n  key: string,\n  altKey: string,\n  preserve: boolean\n): boolean {\n  if (isDef(hash)) {\n    if (hasOwn(hash, key)) {\n      res[key] = hash[key]\n      if (!preserve) {\n        delete hash[key]\n      }\n      return true\n    } else if (hasOwn(hash, altKey)) {\n      res[key] = hash[altKey]\n      if (!preserve) {\n        delete hash[altKey]\n      }\n      return true\n    }\n  }\n  return false\n}\n"
  },
  {
    "path": "src/core/vdom/helpers/get-first-component-child.js",
    "content": "/* @flow */\n\nimport { isDef } from 'shared/util'\n\nexport function getFirstComponentChild (children: ?Array<VNode>): ?VNode {\n  if (Array.isArray(children)) {\n    for (let i = 0; i < children.length; i++) {\n      const c = children[i]\n      if (isDef(c) && isDef(c.componentOptions)) {\n        return c\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "src/core/vdom/helpers/index.js",
    "content": "/* @flow */\n\nexport * from './merge-hook'\nexport * from './extract-props'\nexport * from './update-listeners'\nexport * from './normalize-children'\nexport * from './resolve-async-component'\nexport * from './get-first-component-child'\n"
  },
  {
    "path": "src/core/vdom/helpers/merge-hook.js",
    "content": "/* @flow */\n\nimport { createFnInvoker } from './update-listeners'\nimport { remove, isDef, isUndef, isTrue } from 'shared/util'\n\nexport function mergeVNodeHook (def: Object, hookKey: string, hook: Function) {\n  let invoker\n  const oldHook = def[hookKey]\n\n  function wrappedHook () {\n    hook.apply(this, arguments)\n    // important: remove merged hook to ensure it's called only once\n    // and prevent memory leak\n    remove(invoker.fns, wrappedHook)\n  }\n\n  if (isUndef(oldHook)) {\n    // no existing hook\n    invoker = createFnInvoker([wrappedHook])\n  } else {\n    /* istanbul ignore if */\n    if (isDef(oldHook.fns) && isTrue(oldHook.merged)) {\n      // already a merged invoker\n      invoker = oldHook\n      invoker.fns.push(wrappedHook)\n    } else {\n      // existing plain hook\n      invoker = createFnInvoker([oldHook, wrappedHook])\n    }\n  }\n\n  invoker.merged = true\n  def[hookKey] = invoker\n}\n"
  },
  {
    "path": "src/core/vdom/helpers/normalize-children.js",
    "content": "/* @flow */\n\nimport VNode, { createTextVNode } from 'core/vdom/vnode'\nimport { isFalse, isTrue, isDef, isUndef, isPrimitive } from 'shared/util'\n\n// The template compiler attempts to minimize the need for normalization by\n// statically analyzing the template at compile time.\n//\n// For plain HTML markup, normalization can be completely skipped because the\n// generated render function is guaranteed to return Array<VNode>. There are\n// two cases where extra normalization is needed:\n\n// 1. When the children contains components - because a functional component\n// may return an Array instead of a single root. In this case, just a simple\n// normalization is needed - if any child is an Array, we flatten the whole\n// thing with Array.prototype.concat. It is guaranteed to be only 1-level deep\n// because functional components already normalize their own children.\nexport function simpleNormalizeChildren (children: any) {\n  for (let i = 0; i < children.length; i++) {\n    if (Array.isArray(children[i])) {\n      return Array.prototype.concat.apply([], children)\n    }\n  }\n  return children\n}\n\n// 2. When the children contains constructs that always generated nested Arrays,\n// e.g. <template>, <slot>, v-for, or when the children is provided by user\n// with hand-written render functions / JSX. In such cases a full normalization\n// is needed to cater to all possible types of children values.\nexport function normalizeChildren (children: any): ?Array<VNode> {\n  return isPrimitive(children)\n    ? [createTextVNode(children)]\n    : Array.isArray(children)\n      ? normalizeArrayChildren(children)\n      : undefined\n}\n\nfunction isTextNode (node): boolean {\n  return isDef(node) && isDef(node.text) && isFalse(node.isComment)\n}\n\nfunction normalizeArrayChildren (children: any, nestedIndex?: string): Array<VNode> {\n  const res = []\n  let i, c, last\n  for (i = 0; i < children.length; i++) {\n    c = children[i]\n    if (isUndef(c) || typeof c === 'boolean') continue\n    last = res[res.length - 1]\n    //  nested\n    if (Array.isArray(c)) {\n      res.push.apply(res, normalizeArrayChildren(c, `${nestedIndex || ''}_${i}`))\n    } else if (isPrimitive(c)) {\n      if (isTextNode(last)) {\n        // merge adjacent text nodes\n        // this is necessary for SSR hydration because text nodes are\n        // essentially merged when rendered to HTML strings\n        (last: any).text += String(c)\n      } else if (c !== '') {\n        // convert primitive to vnode\n        res.push(createTextVNode(c))\n      }\n    } else {\n      if (isTextNode(c) && isTextNode(last)) {\n        // merge adjacent text nodes\n        res[res.length - 1] = createTextVNode(last.text + c.text)\n      } else {\n        // default key for nested array children (likely generated by v-for)\n        if (isTrue(children._isVList) &&\n          isDef(c.tag) &&\n          isUndef(c.key) &&\n          isDef(nestedIndex)) {\n          c.key = `__vlist${nestedIndex}_${i}__`\n        }\n        res.push(c)\n      }\n    }\n  }\n  return res\n}\n"
  },
  {
    "path": "src/core/vdom/helpers/resolve-async-component.js",
    "content": "/* @flow */\n\nimport {\n  warn,\n  once,\n  isDef,\n  isUndef,\n  isTrue,\n  isObject\n} from 'core/util/index'\n\nimport { createEmptyVNode } from 'core/vdom/vnode'\n\nfunction ensureCtor (comp, base) {\n  if (comp.__esModule && comp.default) {\n    comp = comp.default\n  }\n  return isObject(comp)\n    ? base.extend(comp)\n    : comp\n}\n\nexport function createAsyncPlaceholder (\n  factory: Function,\n  data: ?VNodeData,\n  context: Component,\n  children: ?Array<VNode>,\n  tag: ?string\n): VNode {\n  const node = createEmptyVNode()\n  node.asyncFactory = factory\n  node.asyncMeta = { data, context, children, tag }\n  return node\n}\n\nexport function resolveAsyncComponent (\n  factory: Function,\n  baseCtor: Class<Component>,\n  context: Component\n): Class<Component> | void {\n  if (isTrue(factory.error) && isDef(factory.errorComp)) {\n    return factory.errorComp\n  }\n\n  if (isDef(factory.resolved)) {\n    return factory.resolved\n  }\n\n  if (isTrue(factory.loading) && isDef(factory.loadingComp)) {\n    return factory.loadingComp\n  }\n\n  if (isDef(factory.contexts)) {\n    // already pending\n    factory.contexts.push(context)\n  } else {\n    const contexts = factory.contexts = [context]\n    let sync = true\n\n    const forceRender = () => {\n      for (let i = 0, l = contexts.length; i < l; i++) {\n        contexts[i].$forceUpdate()\n      }\n    }\n\n    const resolve = once((res: Object | Class<Component>) => {\n      // cache resolved\n      factory.resolved = ensureCtor(res, baseCtor)\n      // invoke callbacks only if this is not a synchronous resolve\n      // (async resolves are shimmed as synchronous during SSR)\n      if (!sync) {\n        forceRender()\n      }\n    })\n\n    const reject = once(reason => {\n      process.env.NODE_ENV !== 'production' && warn(\n        `Failed to resolve async component: ${String(factory)}` +\n        (reason ? `\\nReason: ${reason}` : '')\n      )\n      if (isDef(factory.errorComp)) {\n        factory.error = true\n        forceRender()\n      }\n    })\n\n    const res = factory(resolve, reject)\n\n    if (isObject(res)) {\n      if (typeof res.then === 'function') {\n        // () => Promise\n        if (isUndef(factory.resolved)) {\n          res.then(resolve, reject)\n        }\n      } else if (isDef(res.component) && typeof res.component.then === 'function') {\n        res.component.then(resolve, reject)\n\n        if (isDef(res.error)) {\n          factory.errorComp = ensureCtor(res.error, baseCtor)\n        }\n\n        if (isDef(res.loading)) {\n          factory.loadingComp = ensureCtor(res.loading, baseCtor)\n          if (res.delay === 0) {\n            factory.loading = true\n          } else {\n            setTimeout(() => {\n              if (isUndef(factory.resolved) && isUndef(factory.error)) {\n                factory.loading = true\n                forceRender()\n              }\n            }, res.delay || 200)\n          }\n        }\n\n        if (isDef(res.timeout)) {\n          setTimeout(() => {\n            if (isUndef(factory.resolved)) {\n              reject(\n                process.env.NODE_ENV !== 'production'\n                  ? `timeout (${res.timeout}ms)`\n                  : null\n              )\n            }\n          }, res.timeout)\n        }\n      }\n    }\n\n    sync = false\n    // return in case resolved synchronously\n    return factory.loading\n      ? factory.loadingComp\n      : factory.resolved\n  }\n}\n"
  },
  {
    "path": "src/core/vdom/helpers/update-listeners.js",
    "content": "/* @flow */\n\nimport { warn } from 'core/util/index'\nimport { cached, isUndef } from 'shared/util'\n\nconst normalizeEvent = cached((name: string): {\n  name: string,\n  once: boolean,\n  capture: boolean,\n  passive: boolean\n} => {\n  const passive = name.charAt(0) === '&'\n  name = passive ? name.slice(1) : name\n  const once = name.charAt(0) === '~' // Prefixed last, checked first\n  name = once ? name.slice(1) : name\n  const capture = name.charAt(0) === '!'\n  name = capture ? name.slice(1) : name\n  return {\n    name,\n    once,\n    capture,\n    passive\n  }\n})\n\nexport function createFnInvoker (fns: Function | Array<Function>): Function {\n  function invoker () {\n    const fns = invoker.fns\n    if (Array.isArray(fns)) {\n      const cloned = fns.slice()\n      for (let i = 0; i < cloned.length; i++) {\n        cloned[i].apply(null, arguments)\n      }\n    } else {\n      // return handler return value for single handlers\n      return fns.apply(null, arguments)\n    }\n  }\n  invoker.fns = fns\n  return invoker\n}\n\nexport function updateListeners (\n  on: Object,\n  oldOn: Object,\n  add: Function,\n  remove: Function,\n  vm: Component\n) {\n  let name, cur, old, event\n  for (name in on) {\n    cur = on[name]\n    old = oldOn[name]\n    event = normalizeEvent(name)\n    if (isUndef(cur)) {\n      process.env.NODE_ENV !== 'production' && warn(\n        `Invalid handler for event \"${event.name}\": got ` + String(cur),\n        vm\n      )\n    } else if (isUndef(old)) {\n      if (isUndef(cur.fns)) {\n        cur = on[name] = createFnInvoker(cur)\n      }\n      add(event.name, cur, event.once, event.capture, event.passive)\n    } else if (cur !== old) {\n      old.fns = cur\n      on[name] = old\n    }\n  }\n  for (name in oldOn) {\n    if (isUndef(on[name])) {\n      event = normalizeEvent(name)\n      remove(event.name, oldOn[name], event.capture)\n    }\n  }\n}\n"
  },
  {
    "path": "src/core/vdom/modules/directives.js",
    "content": "/* @flow */\n\nimport { emptyNode } from 'core/vdom/patch'\nimport { resolveAsset, handleError } from 'core/util/index'\nimport { mergeVNodeHook } from 'core/vdom/helpers/index'\n\nexport default {\n  create: updateDirectives,\n  update: updateDirectives,\n  destroy: function unbindDirectives (vnode: VNodeWithData) {\n    updateDirectives(vnode, emptyNode)\n  }\n}\n\nfunction updateDirectives (oldVnode: VNodeWithData, vnode: VNodeWithData) {\n  if (oldVnode.data.directives || vnode.data.directives) {\n    _update(oldVnode, vnode)\n  }\n}\n\nfunction _update (oldVnode, vnode) {\n  const isCreate = oldVnode === emptyNode\n  const isDestroy = vnode === emptyNode\n  const oldDirs = normalizeDirectives(oldVnode.data.directives, oldVnode.context)\n  const newDirs = normalizeDirectives(vnode.data.directives, vnode.context)\n\n  const dirsWithInsert = []\n  const dirsWithPostpatch = []\n\n  let key, oldDir, dir\n  for (key in newDirs) {\n    oldDir = oldDirs[key]\n    dir = newDirs[key]\n    if (!oldDir) {\n      // new directive, bind\n      callHook(dir, 'bind', vnode, oldVnode)\n      if (dir.def && dir.def.inserted) {\n        dirsWithInsert.push(dir)\n      }\n    } else {\n      // existing directive, update\n      dir.oldValue = oldDir.value\n      callHook(dir, 'update', vnode, oldVnode)\n      if (dir.def && dir.def.componentUpdated) {\n        dirsWithPostpatch.push(dir)\n      }\n    }\n  }\n\n  if (dirsWithInsert.length) {\n    const callInsert = () => {\n      for (let i = 0; i < dirsWithInsert.length; i++) {\n        callHook(dirsWithInsert[i], 'inserted', vnode, oldVnode)\n      }\n    }\n    if (isCreate) {\n      mergeVNodeHook(vnode.data.hook || (vnode.data.hook = {}), 'insert', callInsert)\n    } else {\n      callInsert()\n    }\n  }\n\n  if (dirsWithPostpatch.length) {\n    mergeVNodeHook(vnode.data.hook || (vnode.data.hook = {}), 'postpatch', () => {\n      for (let i = 0; i < dirsWithPostpatch.length; i++) {\n        callHook(dirsWithPostpatch[i], 'componentUpdated', vnode, oldVnode)\n      }\n    })\n  }\n\n  if (!isCreate) {\n    for (key in oldDirs) {\n      if (!newDirs[key]) {\n        // no longer present, unbind\n        callHook(oldDirs[key], 'unbind', oldVnode, oldVnode, isDestroy)\n      }\n    }\n  }\n}\n\nconst emptyModifiers = Object.create(null)\n\nfunction normalizeDirectives (\n  dirs: ?Array<VNodeDirective>,\n  vm: Component\n): { [key: string]: VNodeDirective } {\n  const res = Object.create(null)\n  if (!dirs) {\n    return res\n  }\n  let i, dir\n  for (i = 0; i < dirs.length; i++) {\n    dir = dirs[i]\n    if (!dir.modifiers) {\n      dir.modifiers = emptyModifiers\n    }\n    res[getRawDirName(dir)] = dir\n    dir.def = resolveAsset(vm.$options, 'directives', dir.name, true)\n  }\n  return res\n}\n\nfunction getRawDirName (dir: VNodeDirective): string {\n  return dir.rawName || `${dir.name}.${Object.keys(dir.modifiers || {}).join('.')}`\n}\n\nfunction callHook (dir, hook, vnode, oldVnode, isDestroy) {\n  const fn = dir.def && dir.def[hook]\n  if (fn) {\n    try {\n      fn(vnode.elm, dir, vnode, oldVnode, isDestroy)\n    } catch (e) {\n      handleError(e, vnode.context, `directive ${dir.name} ${hook} hook`)\n    }\n  }\n}\n"
  },
  {
    "path": "src/core/vdom/modules/index.js",
    "content": "import directives from './directives'\nimport ref from './ref'\n\nexport default [\n  ref,\n  directives\n]\n"
  },
  {
    "path": "src/core/vdom/modules/ref.js",
    "content": "/* @flow */\n\nimport { remove } from 'shared/util'\n\nexport default {\n  create (_: any, vnode: VNodeWithData) {\n    registerRef(vnode)\n  },\n  update (oldVnode: VNodeWithData, vnode: VNodeWithData) {\n    if (oldVnode.data.ref !== vnode.data.ref) {\n      registerRef(oldVnode, true)\n      registerRef(vnode)\n    }\n  },\n  destroy (vnode: VNodeWithData) {\n    registerRef(vnode, true)\n  }\n}\n\nexport function registerRef (vnode: VNodeWithData, isRemoval: ?boolean) {\n  const key = vnode.data.ref\n  if (!key) return\n\n  const vm = vnode.context\n  const ref = vnode.componentInstance || vnode.elm\n  const refs = vm.$refs\n  if (isRemoval) {\n    if (Array.isArray(refs[key])) {\n      remove(refs[key], ref)\n    } else if (refs[key] === ref) {\n      refs[key] = undefined\n    }\n  } else {\n    if (vnode.data.refInFor) {\n      if (!Array.isArray(refs[key])) {\n        refs[key] = [ref]\n      } else if (refs[key].indexOf(ref) < 0) {\n        // $flow-disable-line\n        refs[key].push(ref)\n      }\n    } else {\n      refs[key] = ref\n    }\n  }\n}\n"
  },
  {
    "path": "src/core/vdom/patch.js",
    "content": "/**\n * Virtual DOM patching algorithm based on Snabbdom by\n * Simon Friis Vindum (@paldepind)\n * Licensed under the MIT License\n * https://github.com/paldepind/snabbdom/blob/master/LICENSE\n *\n * modified by Evan You (@yyx990803)\n *\n\n/*\n * Not type-checking this because this file is perf-critical and the cost\n * of making flow understand it is not worth it.\n */\n\nimport VNode from './vnode'\nimport config from '../config'\nimport { SSR_ATTR } from 'shared/constants'\nimport { registerRef } from './modules/ref'\nimport { activeInstance } from '../instance/lifecycle'\n\nimport {\n  warn,\n  isDef,\n  isUndef,\n  isTrue,\n  makeMap,\n  isPrimitive\n} from '../util/index'\n\nexport const emptyNode = new VNode('', {}, [])\n\nconst hooks = ['create', 'activate', 'update', 'remove', 'destroy']\n\nfunction sameVnode (a, b) {\n  return (\n    a.key === b.key && (\n      (\n        a.tag === b.tag &&\n        a.isComment === b.isComment &&\n        isDef(a.data) === isDef(b.data) &&\n        sameInputType(a, b)\n      ) || (\n        isTrue(a.isAsyncPlaceholder) &&\n        a.asyncFactory === b.asyncFactory &&\n        isUndef(b.asyncFactory.error)\n      )\n    )\n  )\n}\n\n// Some browsers do not support dynamically changing type for <input>\n// so they need to be treated as different nodes\nfunction sameInputType (a, b) {\n  if (a.tag !== 'input') return true\n  let i\n  const typeA = isDef(i = a.data) && isDef(i = i.attrs) && i.type\n  const typeB = isDef(i = b.data) && isDef(i = i.attrs) && i.type\n  return typeA === typeB\n}\n\nfunction createKeyToOldIdx (children, beginIdx, endIdx) {\n  let i, key\n  const map = {}\n  for (i = beginIdx; i <= endIdx; ++i) {\n    key = children[i].key\n    if (isDef(key)) map[key] = i\n  }\n  return map\n}\n\nexport function createPatchFunction (backend) {\n  let i, j\n  const cbs = {}\n\n  const { modules, nodeOps } = backend\n\n  for (i = 0; i < hooks.length; ++i) {\n    cbs[hooks[i]] = []\n    for (j = 0; j < modules.length; ++j) {\n      if (isDef(modules[j][hooks[i]])) {\n        cbs[hooks[i]].push(modules[j][hooks[i]])\n      }\n    }\n  }\n\n  function emptyNodeAt (elm) {\n    return new VNode(nodeOps.tagName(elm).toLowerCase(), {}, [], undefined, elm)\n  }\n\n  function createRmCb (childElm, listeners) {\n    function remove () {\n      if (--remove.listeners === 0) {\n        removeNode(childElm)\n      }\n    }\n    remove.listeners = listeners\n    return remove\n  }\n\n  function removeNode (el) {\n    const parent = nodeOps.parentNode(el)\n    // element may have already been removed due to v-html / v-text\n    if (isDef(parent)) {\n      nodeOps.removeChild(parent, el)\n    }\n  }\n\n  let inPre = 0\n  function createElm (vnode, insertedVnodeQueue, parentElm, refElm, nested) {\n    vnode.isRootInsert = !nested // for transition enter check\n    if (createComponent(vnode, insertedVnodeQueue, parentElm, refElm)) {\n      return\n    }\n\n    const data = vnode.data\n    const children = vnode.children\n    const tag = vnode.tag\n    if (isDef(tag)) {\n      if (process.env.NODE_ENV !== 'production') {\n        if (data && data.pre) {\n          inPre++\n        }\n        if (\n          !inPre &&\n          !vnode.ns &&\n          !(config.ignoredElements.length && config.ignoredElements.indexOf(tag) > -1) &&\n          config.isUnknownElement(tag)\n        ) {\n          warn(\n            'Unknown custom element: <' + tag + '> - did you ' +\n            'register the component correctly? For recursive components, ' +\n            'make sure to provide the \"name\" option.',\n            vnode.context\n          )\n        }\n      }\n      vnode.elm = vnode.ns\n        ? nodeOps.createElementNS(vnode.ns, tag)\n        : nodeOps.createElement(tag, vnode)\n      setScope(vnode)\n\n      /* istanbul ignore if */\n      if (__WEEX__) {\n        // in Weex, the default insertion order is parent-first.\n        // List items can be optimized to use children-first insertion\n        // with append=\"tree\".\n        const appendAsTree = isDef(data) && isTrue(data.appendAsTree)\n        if (!appendAsTree) {\n          if (isDef(data)) {\n            invokeCreateHooks(vnode, insertedVnodeQueue)\n          }\n          insert(parentElm, vnode.elm, refElm)\n        }\n        createChildren(vnode, children, insertedVnodeQueue)\n        if (appendAsTree) {\n          if (isDef(data)) {\n            invokeCreateHooks(vnode, insertedVnodeQueue)\n          }\n          insert(parentElm, vnode.elm, refElm)\n        }\n      } else {\n        createChildren(vnode, children, insertedVnodeQueue)\n        if (isDef(data)) {\n          invokeCreateHooks(vnode, insertedVnodeQueue)\n        }\n        insert(parentElm, vnode.elm, refElm)\n      }\n\n      if (process.env.NODE_ENV !== 'production' && data && data.pre) {\n        inPre--\n      }\n    } else if (isTrue(vnode.isComment)) {\n      vnode.elm = nodeOps.createComment(vnode.text)\n      insert(parentElm, vnode.elm, refElm)\n    } else {\n      vnode.elm = nodeOps.createTextNode(vnode.text)\n      insert(parentElm, vnode.elm, refElm)\n    }\n  }\n\n  function createComponent (vnode, insertedVnodeQueue, parentElm, refElm) {\n    let i = vnode.data\n    if (isDef(i)) {\n      const isReactivated = isDef(vnode.componentInstance) && i.keepAlive\n      if (isDef(i = i.hook) && isDef(i = i.init)) {\n        i(vnode, false /* hydrating */, parentElm, refElm)\n      }\n      // after calling the init hook, if the vnode is a child component\n      // it should've created a child instance and mounted it. the child\n      // component also has set the placeholder vnode's elm.\n      // in that case we can just return the element and be done.\n      if (isDef(vnode.componentInstance)) {\n        initComponent(vnode, insertedVnodeQueue)\n        if (isTrue(isReactivated)) {\n          reactivateComponent(vnode, insertedVnodeQueue, parentElm, refElm)\n        }\n        return true\n      }\n    }\n  }\n\n  function initComponent (vnode, insertedVnodeQueue) {\n    if (isDef(vnode.data.pendingInsert)) {\n      insertedVnodeQueue.push.apply(insertedVnodeQueue, vnode.data.pendingInsert)\n      vnode.data.pendingInsert = null\n    }\n    vnode.elm = vnode.componentInstance.$el\n    if (isPatchable(vnode)) {\n      invokeCreateHooks(vnode, insertedVnodeQueue)\n      setScope(vnode)\n    } else {\n      // empty component root.\n      // skip all element-related modules except for ref (#3455)\n      registerRef(vnode)\n      // make sure to invoke the insert hook\n      insertedVnodeQueue.push(vnode)\n    }\n  }\n\n  function reactivateComponent (vnode, insertedVnodeQueue, parentElm, refElm) {\n    let i\n    // hack for #4339: a reactivated component with inner transition\n    // does not trigger because the inner node's created hooks are not called\n    // again. It's not ideal to involve module-specific logic in here but\n    // there doesn't seem to be a better way to do it.\n    let innerNode = vnode\n    while (innerNode.componentInstance) {\n      innerNode = innerNode.componentInstance._vnode\n      if (isDef(i = innerNode.data) && isDef(i = i.transition)) {\n        for (i = 0; i < cbs.activate.length; ++i) {\n          cbs.activate[i](emptyNode, innerNode)\n        }\n        insertedVnodeQueue.push(innerNode)\n        break\n      }\n    }\n    // unlike a newly created component,\n    // a reactivated keep-alive component doesn't insert itself\n    insert(parentElm, vnode.elm, refElm)\n  }\n\n  function insert (parent, elm, ref) {\n    if (isDef(parent)) {\n      if (isDef(ref)) {\n        if (ref.parentNode === parent) {\n          nodeOps.insertBefore(parent, elm, ref)\n        }\n      } else {\n        nodeOps.appendChild(parent, elm)\n      }\n    }\n  }\n\n  function createChildren (vnode, children, insertedVnodeQueue) {\n    if (Array.isArray(children)) {\n      for (let i = 0; i < children.length; ++i) {\n        createElm(children[i], insertedVnodeQueue, vnode.elm, null, true)\n      }\n    } else if (isPrimitive(vnode.text)) {\n      nodeOps.appendChild(vnode.elm, nodeOps.createTextNode(vnode.text))\n    }\n  }\n\n  function isPatchable (vnode) {\n    while (vnode.componentInstance) {\n      vnode = vnode.componentInstance._vnode\n    }\n    return isDef(vnode.tag)\n  }\n\n  function invokeCreateHooks (vnode, insertedVnodeQueue) {\n    for (let i = 0; i < cbs.create.length; ++i) {\n      cbs.create[i](emptyNode, vnode)\n    }\n    i = vnode.data.hook // Reuse variable\n    if (isDef(i)) {\n      if (isDef(i.create)) i.create(emptyNode, vnode)\n      if (isDef(i.insert)) insertedVnodeQueue.push(vnode)\n    }\n  }\n\n  // set scope id attribute for scoped CSS.\n  // this is implemented as a special case to avoid the overhead\n  // of going through the normal attribute patching process.\n  function setScope (vnode) {\n    let i\n    let ancestor = vnode\n    while (ancestor) {\n      if (isDef(i = ancestor.context) && isDef(i = i.$options._scopeId)) {\n        nodeOps.setAttribute(vnode.elm, i, '')\n      }\n      ancestor = ancestor.parent\n    }\n    // for slot content they should also get the scopeId from the host instance.\n    if (isDef(i = activeInstance) &&\n      i !== vnode.context &&\n      isDef(i = i.$options._scopeId)\n    ) {\n      nodeOps.setAttribute(vnode.elm, i, '')\n    }\n  }\n\n  function addVnodes (parentElm, refElm, vnodes, startIdx, endIdx, insertedVnodeQueue) {\n    for (; startIdx <= endIdx; ++startIdx) {\n      createElm(vnodes[startIdx], insertedVnodeQueue, parentElm, refElm)\n    }\n  }\n\n  function invokeDestroyHook (vnode) {\n    let i, j\n    const data = vnode.data\n    if (isDef(data)) {\n      if (isDef(i = data.hook) && isDef(i = i.destroy)) i(vnode)\n      for (i = 0; i < cbs.destroy.length; ++i) cbs.destroy[i](vnode)\n    }\n    if (isDef(i = vnode.children)) {\n      for (j = 0; j < vnode.children.length; ++j) {\n        invokeDestroyHook(vnode.children[j])\n      }\n    }\n  }\n\n  function removeVnodes (parentElm, vnodes, startIdx, endIdx) {\n    for (; startIdx <= endIdx; ++startIdx) {\n      const ch = vnodes[startIdx]\n      if (isDef(ch)) {\n        if (isDef(ch.tag)) {\n          removeAndInvokeRemoveHook(ch)\n          invokeDestroyHook(ch)\n        } else { // Text node\n          removeNode(ch.elm)\n        }\n      }\n    }\n  }\n\n  function removeAndInvokeRemoveHook (vnode, rm) {\n    if (isDef(rm) || isDef(vnode.data)) {\n      let i\n      const listeners = cbs.remove.length + 1\n      if (isDef(rm)) {\n        // we have a recursively passed down rm callback\n        // increase the listeners count\n        rm.listeners += listeners\n      } else {\n        // directly removing\n        rm = createRmCb(vnode.elm, listeners)\n      }\n      // recursively invoke hooks on child component root node\n      if (isDef(i = vnode.componentInstance) && isDef(i = i._vnode) && isDef(i.data)) {\n        removeAndInvokeRemoveHook(i, rm)\n      }\n      for (i = 0; i < cbs.remove.length; ++i) {\n        cbs.remove[i](vnode, rm)\n      }\n      if (isDef(i = vnode.data.hook) && isDef(i = i.remove)) {\n        i(vnode, rm)\n      } else {\n        rm()\n      }\n    } else {\n      removeNode(vnode.elm)\n    }\n  }\n\n  function updateChildren (parentElm, oldCh, newCh, insertedVnodeQueue, removeOnly) {\n    let oldStartIdx = 0\n    let newStartIdx = 0\n    let oldEndIdx = oldCh.length - 1\n    let oldStartVnode = oldCh[0]\n    let oldEndVnode = oldCh[oldEndIdx]\n    let newEndIdx = newCh.length - 1\n    let newStartVnode = newCh[0]\n    let newEndVnode = newCh[newEndIdx]\n    let oldKeyToIdx, idxInOld, elmToMove, refElm\n\n    // removeOnly is a special flag used only by <transition-group>\n    // to ensure removed elements stay in correct relative positions\n    // during leaving transitions\n    const canMove = !removeOnly\n\n    while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {\n      if (isUndef(oldStartVnode)) {\n        oldStartVnode = oldCh[++oldStartIdx] // Vnode has been moved left\n      } else if (isUndef(oldEndVnode)) {\n        oldEndVnode = oldCh[--oldEndIdx]\n      } else if (sameVnode(oldStartVnode, newStartVnode)) {\n        patchVnode(oldStartVnode, newStartVnode, insertedVnodeQueue)\n        oldStartVnode = oldCh[++oldStartIdx]\n        newStartVnode = newCh[++newStartIdx]\n      } else if (sameVnode(oldEndVnode, newEndVnode)) {\n        patchVnode(oldEndVnode, newEndVnode, insertedVnodeQueue)\n        oldEndVnode = oldCh[--oldEndIdx]\n        newEndVnode = newCh[--newEndIdx]\n      } else if (sameVnode(oldStartVnode, newEndVnode)) { // Vnode moved right\n        patchVnode(oldStartVnode, newEndVnode, insertedVnodeQueue)\n        canMove && nodeOps.insertBefore(parentElm, oldStartVnode.elm, nodeOps.nextSibling(oldEndVnode.elm))\n        oldStartVnode = oldCh[++oldStartIdx]\n        newEndVnode = newCh[--newEndIdx]\n      } else if (sameVnode(oldEndVnode, newStartVnode)) { // Vnode moved left\n        patchVnode(oldEndVnode, newStartVnode, insertedVnodeQueue)\n        canMove && nodeOps.insertBefore(parentElm, oldEndVnode.elm, oldStartVnode.elm)\n        oldEndVnode = oldCh[--oldEndIdx]\n        newStartVnode = newCh[++newStartIdx]\n      } else {\n        if (isUndef(oldKeyToIdx)) oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx)\n        idxInOld = isDef(newStartVnode.key) ? oldKeyToIdx[newStartVnode.key] : null\n        if (isUndef(idxInOld)) { // New element\n          createElm(newStartVnode, insertedVnodeQueue, parentElm, oldStartVnode.elm)\n          newStartVnode = newCh[++newStartIdx]\n        } else {\n          elmToMove = oldCh[idxInOld]\n          /* istanbul ignore if */\n          if (process.env.NODE_ENV !== 'production' && !elmToMove) {\n            warn(\n              'It seems there are duplicate keys that is causing an update error. ' +\n              'Make sure each v-for item has a unique key.'\n            )\n          }\n          if (sameVnode(elmToMove, newStartVnode)) {\n            patchVnode(elmToMove, newStartVnode, insertedVnodeQueue)\n            oldCh[idxInOld] = undefined\n            canMove && nodeOps.insertBefore(parentElm, elmToMove.elm, oldStartVnode.elm)\n            newStartVnode = newCh[++newStartIdx]\n          } else {\n            // same key but different element. treat as new element\n            createElm(newStartVnode, insertedVnodeQueue, parentElm, oldStartVnode.elm)\n            newStartVnode = newCh[++newStartIdx]\n          }\n        }\n      }\n    }\n    if (oldStartIdx > oldEndIdx) {\n      refElm = isUndef(newCh[newEndIdx + 1]) ? null : newCh[newEndIdx + 1].elm\n      addVnodes(parentElm, refElm, newCh, newStartIdx, newEndIdx, insertedVnodeQueue)\n    } else if (newStartIdx > newEndIdx) {\n      removeVnodes(parentElm, oldCh, oldStartIdx, oldEndIdx)\n    }\n  }\n\n  function patchVnode (oldVnode, vnode, insertedVnodeQueue, removeOnly) {\n    if (oldVnode === vnode) {\n      return\n    }\n\n    const elm = vnode.elm = oldVnode.elm\n\n    if (isTrue(oldVnode.isAsyncPlaceholder)) {\n      if (isDef(vnode.asyncFactory.resolved)) {\n        hydrate(oldVnode.elm, vnode, insertedVnodeQueue)\n      } else {\n        vnode.isAsyncPlaceholder = true\n      }\n      return\n    }\n\n    // reuse element for static trees.\n    // note we only do this if the vnode is cloned -\n    // if the new node is not cloned it means the render functions have been\n    // reset by the hot-reload-api and we need to do a proper re-render.\n    if (isTrue(vnode.isStatic) &&\n      isTrue(oldVnode.isStatic) &&\n      vnode.key === oldVnode.key &&\n      (isTrue(vnode.isCloned) || isTrue(vnode.isOnce))\n    ) {\n      vnode.componentInstance = oldVnode.componentInstance\n      return\n    }\n\n    let i\n    const data = vnode.data\n    if (isDef(data) && isDef(i = data.hook) && isDef(i = i.prepatch)) {\n      i(oldVnode, vnode)\n    }\n\n    const oldCh = oldVnode.children\n    const ch = vnode.children\n    if (isDef(data) && isPatchable(vnode)) {\n      for (i = 0; i < cbs.update.length; ++i) cbs.update[i](oldVnode, vnode)\n      if (isDef(i = data.hook) && isDef(i = i.update)) i(oldVnode, vnode)\n    }\n    if (isUndef(vnode.text)) {\n      if (isDef(oldCh) && isDef(ch)) {\n        if (oldCh !== ch) updateChildren(elm, oldCh, ch, insertedVnodeQueue, removeOnly)\n      } else if (isDef(ch)) {\n        if (isDef(oldVnode.text)) nodeOps.setTextContent(elm, '')\n        addVnodes(elm, null, ch, 0, ch.length - 1, insertedVnodeQueue)\n      } else if (isDef(oldCh)) {\n        removeVnodes(elm, oldCh, 0, oldCh.length - 1)\n      } else if (isDef(oldVnode.text)) {\n        nodeOps.setTextContent(elm, '')\n      }\n    } else if (oldVnode.text !== vnode.text) {\n      nodeOps.setTextContent(elm, vnode.text)\n    }\n    if (isDef(data)) {\n      if (isDef(i = data.hook) && isDef(i = i.postpatch)) i(oldVnode, vnode)\n    }\n  }\n\n  function invokeInsertHook (vnode, queue, initial) {\n    // delay insert hooks for component root nodes, invoke them after the\n    // element is really inserted\n    if (isTrue(initial) && isDef(vnode.parent)) {\n      vnode.parent.data.pendingInsert = queue\n    } else {\n      for (let i = 0; i < queue.length; ++i) {\n        queue[i].data.hook.insert(queue[i])\n      }\n    }\n  }\n\n  let bailed = false\n  // list of modules that can skip create hook during hydration because they\n  // are already rendered on the client or has no need for initialization\n  const isRenderedModule = makeMap('attrs,style,class,staticClass,staticStyle,key')\n\n  // Note: this is a browser-only function so we can assume elms are DOM nodes.\n  function hydrate (elm, vnode, insertedVnodeQueue) {\n    if (isTrue(vnode.isComment) && isDef(vnode.asyncFactory)) {\n      vnode.elm = elm\n      vnode.isAsyncPlaceholder = true\n      return true\n    }\n    if (process.env.NODE_ENV !== 'production') {\n      if (!assertNodeMatch(elm, vnode)) {\n        return false\n      }\n    }\n    vnode.elm = elm\n    const { tag, data, children } = vnode\n    if (isDef(data)) {\n      if (isDef(i = data.hook) && isDef(i = i.init)) i(vnode, true /* hydrating */)\n      if (isDef(i = vnode.componentInstance)) {\n        // child component. it should have hydrated its own tree.\n        initComponent(vnode, insertedVnodeQueue)\n        return true\n      }\n    }\n    if (isDef(tag)) {\n      if (isDef(children)) {\n        // empty element, allow client to pick up and populate children\n        if (!elm.hasChildNodes()) {\n          createChildren(vnode, children, insertedVnodeQueue)\n        } else {\n          let childrenMatch = true\n          let childNode = elm.firstChild\n          for (let i = 0; i < children.length; i++) {\n            if (!childNode || !hydrate(childNode, children[i], insertedVnodeQueue)) {\n              childrenMatch = false\n              break\n            }\n            childNode = childNode.nextSibling\n          }\n          // if childNode is not null, it means the actual childNodes list is\n          // longer than the virtual children list.\n          if (!childrenMatch || childNode) {\n            if (process.env.NODE_ENV !== 'production' &&\n              typeof console !== 'undefined' &&\n              !bailed\n            ) {\n              bailed = true\n              console.warn('Parent: ', elm)\n              console.warn('Mismatching childNodes vs. VNodes: ', elm.childNodes, children)\n            }\n            return false\n          }\n        }\n      }\n      if (isDef(data)) {\n        for (const key in data) {\n          if (!isRenderedModule(key)) {\n            invokeCreateHooks(vnode, insertedVnodeQueue)\n            break\n          }\n        }\n      }\n    } else if (elm.data !== vnode.text) {\n      elm.data = vnode.text\n    }\n    return true\n  }\n\n  function assertNodeMatch (node, vnode) {\n    if (isDef(vnode.tag)) {\n      return (\n        vnode.tag.indexOf('vue-component') === 0 ||\n        vnode.tag.toLowerCase() === (node.tagName && node.tagName.toLowerCase())\n      )\n    } else {\n      return node.nodeType === (vnode.isComment ? 8 : 3)\n    }\n  }\n\n  return function patch (oldVnode, vnode, hydrating, removeOnly, parentElm, refElm) {\n    if (isUndef(vnode)) {\n      if (isDef(oldVnode)) invokeDestroyHook(oldVnode)\n      return\n    }\n\n    let isInitialPatch = false\n    const insertedVnodeQueue = []\n\n    if (isUndef(oldVnode)) {\n      // empty mount (likely as component), create new root element\n      isInitialPatch = true\n      createElm(vnode, insertedVnodeQueue, parentElm, refElm)\n    } else {\n      const isRealElement = isDef(oldVnode.nodeType)\n      if (!isRealElement && sameVnode(oldVnode, vnode)) {\n        // patch existing root node\n        patchVnode(oldVnode, vnode, insertedVnodeQueue, removeOnly)\n      } else {\n        if (isRealElement) {\n          // mounting to a real element\n          // check if this is server-rendered content and if we can perform\n          // a successful hydration.\n          if (oldVnode.nodeType === 1 && oldVnode.hasAttribute(SSR_ATTR)) {\n            oldVnode.removeAttribute(SSR_ATTR)\n            hydrating = true\n          }\n          if (isTrue(hydrating)) {\n            if (hydrate(oldVnode, vnode, insertedVnodeQueue)) {\n              invokeInsertHook(vnode, insertedVnodeQueue, true)\n              return oldVnode\n            } else if (process.env.NODE_ENV !== 'production') {\n              warn(\n                'The client-side rendered virtual DOM tree is not matching ' +\n                'server-rendered content. This is likely caused by incorrect ' +\n                'HTML markup, for example nesting block-level elements inside ' +\n                '<p>, or missing <tbody>. Bailing hydration and performing ' +\n                'full client-side render.'\n              )\n            }\n          }\n          // either not server-rendered, or hydration failed.\n          // create an empty node and replace it\n          oldVnode = emptyNodeAt(oldVnode)\n        }\n        // replacing existing element\n        const oldElm = oldVnode.elm\n        const parentElm = nodeOps.parentNode(oldElm)\n        createElm(\n          vnode,\n          insertedVnodeQueue,\n          // extremely rare edge case: do not insert if old element is in a\n          // leaving transition. Only happens when combining transition +\n          // keep-alive + HOCs. (#4590)\n          oldElm._leaveCb ? null : parentElm,\n          nodeOps.nextSibling(oldElm)\n        )\n\n        if (isDef(vnode.parent)) {\n          // component root element replaced.\n          // update parent placeholder node element, recursively\n          let ancestor = vnode.parent\n          while (ancestor) {\n            ancestor.elm = vnode.elm\n            ancestor = ancestor.parent\n          }\n          if (isPatchable(vnode)) {\n            for (let i = 0; i < cbs.create.length; ++i) {\n              cbs.create[i](emptyNode, vnode.parent)\n            }\n          }\n        }\n\n        if (isDef(parentElm)) {\n          removeVnodes(parentElm, [oldVnode], 0, 0)\n        } else if (isDef(oldVnode.tag)) {\n          invokeDestroyHook(oldVnode)\n        }\n      }\n    }\n\n    invokeInsertHook(vnode, insertedVnodeQueue, isInitialPatch)\n    return vnode.elm\n  }\n}\n"
  },
  {
    "path": "src/core/vdom/vnode.js",
    "content": "/* @flow */\n\nexport default class VNode {\n  tag: string | void;\n  data: VNodeData | void;\n  children: ?Array<VNode>;\n  text: string | void;\n  elm: Node | void;\n  ns: string | void;\n  context: Component | void; // rendered in this component's scope\n  functionalContext: Component | void; // only for functional component root nodes\n  key: string | number | void;\n  componentOptions: VNodeComponentOptions | void;\n  componentInstance: Component | void; // component instance\n  parent: VNode | void; // component placeholder node\n  raw: boolean; // contains raw HTML? (server only)\n  isStatic: boolean; // hoisted static node\n  isRootInsert: boolean; // necessary for enter transition check\n  isComment: boolean; // empty comment placeholder?\n  isCloned: boolean; // is a cloned node?\n  isOnce: boolean; // is a v-once node?\n  asyncFactory: Function | void; // async component factory function\n  asyncMeta: Object | void;\n  isAsyncPlaceholder: boolean;\n  ssrContext: Object | void;\n\n  constructor (\n    tag?: string,\n    data?: VNodeData,\n    children?: ?Array<VNode>,\n    text?: string,\n    elm?: Node,\n    context?: Component,\n    componentOptions?: VNodeComponentOptions,\n    asyncFactory?: Function\n  ) {\n    this.tag = tag\n    this.data = data\n    this.children = children\n    this.text = text\n    this.elm = elm\n    this.ns = undefined\n    this.context = context\n    this.functionalContext = undefined\n    this.key = data && data.key\n    this.componentOptions = componentOptions\n    this.componentInstance = undefined\n    this.parent = undefined\n    this.raw = false\n    this.isStatic = false\n    this.isRootInsert = true\n    this.isComment = false\n    this.isCloned = false\n    this.isOnce = false\n    this.asyncFactory = asyncFactory\n    this.asyncMeta = undefined\n    this.isAsyncPlaceholder = false\n  }\n\n  // DEPRECATED: alias for componentInstance for backwards compat.\n  /* istanbul ignore next */\n  get child (): Component | void {\n    return this.componentInstance\n  }\n}\n\nexport const createEmptyVNode = (text: string = '') => {\n  const node = new VNode()\n  node.text = text\n  node.isComment = true\n  return node\n}\n\nexport function createTextVNode (val: string | number) {\n  return new VNode(undefined, undefined, undefined, String(val))\n}\n\n// optimized shallow clone\n// used for static nodes and slot nodes because they may be reused across\n// multiple renders, cloning them avoids errors when DOM manipulations rely\n// on their elm reference.\nexport function cloneVNode (vnode: VNode): VNode {\n  const cloned = new VNode(\n    vnode.tag,\n    vnode.data,\n    vnode.children,\n    vnode.text,\n    vnode.elm,\n    vnode.context,\n    vnode.componentOptions,\n    vnode.asyncFactory\n  )\n  cloned.ns = vnode.ns\n  cloned.isStatic = vnode.isStatic\n  cloned.key = vnode.key\n  cloned.isComment = vnode.isComment\n  cloned.isCloned = true\n  return cloned\n}\n\nexport function cloneVNodes (vnodes: Array<VNode>): Array<VNode> {\n  const len = vnodes.length\n  const res = new Array(len)\n  for (let i = 0; i < len; i++) {\n    res[i] = cloneVNode(vnodes[i])\n  }\n  return res\n}\n"
  },
  {
    "path": "src/platforms/mp/compiler/common/babel-plugins.js",
    "content": "// babel-plugin-transform-object-to-ternary-operator.js\n\nimport * as t from 'babel-types'\nimport generate from 'babel-generator'\nimport template from 'babel-template'\nimport { hyphenate } from 'shared/util'\n\nfunction getStrByNode (node, onlyStr = false) {\n  if (onlyStr) {\n    return node.value || node.name || ''\n  }\n  return node.type === 'StringLiteral' ? node : t.stringLiteral(node.name || '')\n}\n\n// 把 { key: value } 转换成 [ value ? 'key' : '' ]\nconst objectVisitor = {\n  ObjectExpression (path) {\n    const elements = path.node.properties.map(propertyItem => {\n      return t.conditionalExpression(propertyItem.value, getStrByNode(propertyItem.key), t.stringLiteral(''))\n    })\n    path.replaceWith(t.arrayExpression(elements))\n  }\n}\n\nexport function transformObjectToTernaryOperator (babel) {\n  return { visitor: objectVisitor }\n}\n\n// 把 { key: value } 转换成 'key:' + value + ';'\nconst objectToStringVisitor = {\n  ObjectExpression (path) {\n    const expression = path.node.properties.map(propertyItem => {\n      const keyStr = getStrByNode(propertyItem.key, true)\n      const key = keyStr ? hyphenate(keyStr) : keyStr\n      const { code: val } = generate(t.ExpressionStatement(propertyItem.value))\n      return `'${key}:' + (${val.slice(0, -1)}) + ';'`\n    }).join('+')\n\n    const p = template(expression)({})\n    path.replaceWith(p.expression)\n  }\n}\n\nexport function transformObjectToString (babel) {\n  return { visitor: objectToStringVisitor }\n}\n"
  },
  {
    "path": "src/platforms/mp/compiler/common/config.js",
    "content": "export default {\n  virtualTag: ['slot', 'template', 'block']\n}\n"
  },
  {
    "path": "src/platforms/mp/compiler/common/convert/index.js",
    "content": "import tag from './tag'\nimport tagConfig from '../config'\nimport { hyphenate } from 'shared/util'\n\nfunction convertAst (node, options = {}, util, conventRule) {\n  const { children, ifConditions, staticClass = '', mpcomid } = node\n  let { tag: tagName } = node\n  const { log, deps, slots, slotTemplates } = util\n  let mpmlAst = Object.assign({}, node)\n  const { moduleId, components } = options\n  mpmlAst.tag = tagName = tagName ? hyphenate(tagName) : tagName\n  // 引入 import, isSlot 是使用 slot 的编译地方，意即 <slot></slot> 的地方\n  const isSlot = tagName === 'slot'\n  if (isSlot) {\n    deps.slots = 'slots'\n    // 把当前 slot 节点包裹 template\n    const defSlot = Object.assign({}, mpmlAst)\n    defSlot.tag = 'template'\n    const templateName = `${defSlot.attrsMap.name || 'default'}`\n    defSlot.attrsMap.name = templateName\n    mpmlAst.children = []\n    defSlot.parent = node.parent.parent\n    slotTemplates[templateName] = defSlot\n  }\n\n  const currentIsComponent = conventRule.component.isComponent(tagName, components)\n  if (currentIsComponent) {\n    deps[tagName] = tagName\n  }\n\n  if (moduleId && !currentIsComponent && tagConfig.virtualTag.indexOf(tagName) < 0) {\n    mpmlAst.staticClass = staticClass ? `${moduleId} ${staticClass}`.replace(/\\\"/g, '') : moduleId\n  } else {\n    mpmlAst.staticClass = staticClass.replace(/\\\"/g, '')\n  }\n\n  // 组件内部的node节点全部是 slot\n  mpmlAst.slots = {}\n  if (currentIsComponent && children && children.length) {\n    // 只检查组件下的子节点（不检查孙子节点）是不是具名 slot，不然就是 default slot\n    children\n      .reduce((res, n) => {\n        const { slot } = n.attrsMap || {}\n        // 不是具名的，全部放在第一个数组元素中\n        const arr = slot ? res : res[0]\n        arr.push(n)\n        return res\n      }, [[]])\n      .forEach(n => {\n        const isDefault = Array.isArray(n)\n        const slotName = isDefault ? 'default' : n.attrsMap.slot\n        const slotId = `${moduleId}-${slotName}-${mpcomid.replace(/\\'/g, '')}`\n        if (!isDefault) {\n          delete n.attrsMap.slot\n        }\n        const node = { tag: 'slot', attrsMap: {}, children: isDefault ? n : [n] }\n        node.tag = 'template'\n        node.attrsMap.name = slotId\n        // 缓存，会集中生成一个 slots 文件\n        slots[slotId] = { node: convertAst(node, options, util, conventRule), name: slotName, slotId }\n        mpmlAst.slots[slotName] = slotId\n      })\n    // 清理当前组件下的节点信息，因为 slot 都被转移了\n    children.length = 0\n    mpmlAst.children.length = 0\n  }\n\n  mpmlAst.attrsMap = conventRule.attrs.format(mpmlAst.attrsMap)\n  mpmlAst = tag(mpmlAst, options, conventRule.component, conventRule.attrs)\n  mpmlAst = conventRule.convertFor(mpmlAst, options)\n  mpmlAst = conventRule.attrs.convertAttr(mpmlAst, log)\n  if (children && !isSlot) {\n    mpmlAst.children = children.map((k) => convertAst(k, options, util, conventRule))\n  }\n\n  if (ifConditions) {\n    const length = ifConditions.length\n    for (let i = 1; i < length; i++) {\n      mpmlAst.ifConditions[i].block = convertAst(ifConditions[i].block, options, util, conventRule)\n    }\n  }\n\n  return mpmlAst\n}\n\nexport default function getAstCommon (compiled, options = {}, log, conventRule) {\n  const { ast } = compiled\n  const deps = {\n    // slots: 'slots'\n  }\n  const slots = {\n    // slotId: nodeAst\n  }\n  const slotTemplates = {\n  }\n\n  const wxast = convertAst(ast, options, { log, deps, slots, slotTemplates }, conventRule)\n  const children = Object.keys(slotTemplates).map(k => convertAst(slotTemplates[k], options, { log, deps, slots, slotTemplates }, conventRule))\n  wxast.children = children.concat(wxast.children)\n  return {\n    wxast,\n    deps,\n    slots\n  }\n}\n"
  },
  {
    "path": "src/platforms/mp/compiler/common/convert/tag.js",
    "content": "// import component from './component'\nimport tagMap from '../../common/tagMap'\nimport _ from 'lodash'\n\nexport default function (ast, options, component, attrs) {\n  const { tag, elseif, else: elseText, for: forText, staticClass = '', attrsMap = {}} = ast\n  const { components } = options\n  const { 'v-if': ifText, href, 'v-bind:href': bindHref, name } = attrsMap\n\n  if (!tag) {\n    return ast\n  }\n  const isComponent = component.isComponent(tag, components)\n  if (tag !== 'template' && tag !== 'block' && tag !== 'slot' && !isComponent) {\n    ast.staticClass = staticClass ? `_${tag} ${staticClass}` : `_${tag}`\n  }\n  ast.tag = tagMap[tag] || tag\n\n  const isSlot = tag === 'slot'\n\n  if ((ifText || elseif || elseText || forText) && tag === 'template') {\n    ast.tag = 'block'\n  } else if (isComponent || isSlot) {\n    const originSlotName = name || 'default'\n    const slotName = isSlot ? `$slot${originSlotName} || '${originSlotName}'` : undefined\n\n    // 用完必须删除，不然会被编译成 <template name=\"xxx\"> 在小程序中就会表示这是一个模版申明而不是使用，小程序中不能同时申明和使用模版\n    delete ast.attrsMap.name\n    ast = component.convertComponent(ast, components, slotName)\n    ast.tag = 'template'\n    if (isSlot) {\n      const originParent = ast.parent\n      const _copyAstOne = _.cloneDeep(ast)\n      const _copyAstTwo = _.cloneDeep(ast)\n      const baseObject = {\n        type: ast.type,\n        tag: 'block'\n      }\n      const childOne = attrs.convertAttr(Object.assign({\n        if: `$slot${originSlotName}`,\n        attrsMap: {\n          'v-if': `$slot${originSlotName}`\n        }\n      }, baseObject))\n      const childTwo = attrs.convertAttr(Object.assign({\n        else: `'${originSlotName}'`,\n        attrsMap: {\n          'v-else': ''\n        }\n      }, baseObject))\n      _copyAstOne.attrsMap['is'] = '{{' + `$slot${originSlotName}` + '}}'\n      _copyAstTwo.attrsMap['is'] = '{{' + `'${originSlotName}'` + '}}'\n      _copyAstOne.parent = childOne\n      _copyAstTwo.parent = childTwo\n      childOne.children = [_copyAstOne]\n      childTwo.children = [_copyAstTwo]\n      const parentObject = {\n        type: ast.type,\n        tag: 'block',\n        parent: originParent\n      }\n      childOne.parent = parentObject\n      childTwo.parent = parentObject\n      parentObject.children = [\n        childOne,\n        childTwo\n      ]\n      ast = parentObject\n    }\n  } else if (tag === 'a' && !(href || bindHref)) {\n    ast.tag = 'view'\n  } else if (ast.events && ast.events.scroll) {\n    ast.tag = 'scroll-view'\n  } else if (tag === 'input') {\n    const type = attrsMap.type\n    if (type && ['button', 'checkbox', 'radio'].indexOf(type) > -1) {\n      delete ast.attrsMap.type\n      ast.tag = type\n    }\n    if (type === 'button') {\n      ast.children.push({\n        text: attrsMap.value || '',\n        type: 3\n      })\n      delete ast.attrsMap.value\n    }\n  }\n  return ast\n}\n"
  },
  {
    "path": "src/platforms/mp/compiler/common/generate.js",
    "content": "import utils from './utils'\n\nconst autoEndTags = [\n  'progress',\n  'checkbox',\n  'switch',\n  'input',\n  'radio',\n  'slider',\n  'textarea'\n]\n\nfunction convertAttr (key, val) {\n  return (val === '' || typeof val === 'undefined') ? key : `${key}=\"${val}\"`\n}\n\nfunction generateCode (nodeAst, options = {}) {\n  const { tag, attrsMap = {}, children = [], text, ifConditions = [] } = nodeAst\n  if (!tag) {\n    return text\n  }\n  // v-if 指令\n  const ifConditionsArr = []\n  if (ifConditions) {\n    const length = ifConditions.length\n    for (let i = 1; i < length; i++) {\n      ifConditionsArr.push(generateCode(ifConditions[i].block, options))\n    }\n  }\n  const childrenContent = children.map(childAst => generateCode(childAst, options)).join('')\n  let attrs = Object.keys(attrsMap).map(key => convertAttr(key, attrsMap[key])).join(' ')\n  attrs = attrs ? ` ${attrs}` : ''\n\n  if (autoEndTags.indexOf(tag) > -1 && !childrenContent) {\n    return `<${tag}${attrs} />${ifConditionsArr.join('')}`\n  }\n  return `<${tag}${attrs}>${childrenContent}</${tag}>${ifConditionsArr.join('')}`\n\n  // if (autoEndTags.indexOf(tag) > -1 && !children.length) {\n  //   return `<${tag}${attrs ? ' ' + attrs : ''} />${ifConditionsArr.join('')}`\n  // }\n  // return `<${tag}${attrs ? ' ' + attrs : ''}>${childrenContent}</${tag}>${ifConditionsArr.join('')}`\n}\n\n\nexport default function compileToMPMLCommon (compiled, options = {}, getAst) {\n  // TODO, compiled is undefined\n  const { components = {}} = options\n  const log = utils.log(compiled)\n\n  const { wxast, deps = {}, slots = {}} = getAst(compiled, options, log)\n  let code = generateCode(wxast, options)\n\n  // 引用子模版\n  const importCode = Object.keys(deps).map(k => components[k] ? `<import src=\"${components[k].src}\" />` : '').join('')\n  code = `${importCode}<template name=\"${options.name}\">${code}</template>`\n\n  // 生成 slots code\n  Object.keys(slots).forEach(k => {\n    const slot = slots[k]\n    slot.code = generateCode(slot.node, options)\n  })\n\n  // TODO: 后期优化掉这种暴力全部 import，虽然对性能没啥大影响\n  return { code, compiled, slots, importCode }\n}\n\n"
  },
  {
    "path": "src/platforms/mp/compiler/common/tagMap.js",
    "content": "export default {\n  'br': 'view',\n  'hr': 'view',\n\n  'p': 'view',\n  'h1': 'view',\n  'h2': 'view',\n  'h3': 'view',\n  'h4': 'view',\n  'h5': 'view',\n  'h6': 'view',\n  'abbr': 'view',\n  'address': 'view',\n  'b': 'view',\n  'bdi': 'view',\n  'bdo': 'view',\n  'blockquote': 'view',\n  'cite': 'view',\n  'code': 'view',\n  'del': 'view',\n  'ins': 'view',\n  'dfn': 'view',\n  'em': 'view',\n  'strong': 'view',\n  'samp': 'view',\n  'kbd': 'view',\n  'var': 'view',\n  'i': 'view',\n  'mark': 'view',\n  'pre': 'view',\n  'q': 'view',\n  'ruby': 'view',\n  'rp': 'view',\n  'rt': 'view',\n  's': 'view',\n  'small': 'view',\n  'sub': 'view',\n  'sup': 'view',\n  'time': 'view',\n  'u': 'view',\n  'wbr': 'view',\n\n  // 表单元素\n  'form': 'form',\n  'input': 'input',\n  'textarea': 'textarea',\n  'button': 'button',\n  'select': 'picker',\n  'option': 'view',\n  'optgroup': 'view',\n  'label': 'label',\n  'fieldset': 'view',\n  'datalist': 'picker',\n  'legend': 'view',\n  'output': 'view',\n\n  // 框架\n  'iframe': 'view',\n  // 图像\n  'img': 'image',\n  'canvas': 'canvas',\n  'figure': 'view',\n  'figcaption': 'view',\n\n  // 音视频\n  'audio': 'audio',\n  'source': 'audio',\n  'video': 'video',\n  'track': 'video',\n  // 链接\n  'a': 'navigator',\n  'nav': 'view',\n  'link': 'navigator',\n  // 列表\n  'ul': 'view',\n  'ol': 'view',\n  'li': 'view',\n  'dl': 'view',\n  'dt': 'view',\n  'dd': 'view',\n  'menu': 'view',\n  'command': 'view',\n\n  // 表格table\n  'table': 'view',\n  'caption': 'view',\n  'th': 'view',\n  'td': 'view',\n  'tr': 'view',\n  'thead': 'view',\n  'tbody': 'view',\n  'tfoot': 'view',\n  'col': 'view',\n  'colgroup': 'view',\n\n  // 样式\n  'div': 'view',\n  'main': 'view',\n  'span': 'label',\n  'header': 'view',\n  'footer': 'view',\n  'section': 'view',\n  'article': 'view',\n  'aside': 'view',\n  'details': 'view',\n  'dialog': 'view',\n  'summary': 'view',\n\n  'progress': 'progress',\n  'meter': 'progress',\n  'head': 'view',\n  'meta': 'view',\n  'base': 'text',\n  'area': 'navigator',\n\n  'script': 'view',\n  'noscript': 'view',\n  'embed': 'view',\n  'object': 'view',\n  'param': 'view',\n\n  // https://mp.weixin.qq.com/debug/wxadoc/dev/component/\n  // [...document.querySelectorAll('.markdown-section tbody td:first-child')].map(v => v.textContent).join(',\\n')\n  'view': 'view',\n  'scroll-view': 'scroll-view',\n  'swiper': 'swiper',\n  'icon': 'icon',\n  'text': 'text',\n  'checkbox': 'checkbox',\n  'radio': 'radio',\n  'picker': 'picker',\n  'picker-view': 'picker-view',\n  'slider': 'slider',\n  'switch': 'switch',\n  'navigator': 'navigator',\n  'image': 'image',\n  'map': 'map',\n  'contact-button': 'contact-button',\n  'block': 'block'\n}\n"
  },
  {
    "path": "src/platforms/mp/compiler/common/utils.js",
    "content": "export default {\n  toLowerCase (str) {\n    return str.replace(/([A-Z])/g, '-$1').toLowerCase().trim()\n  },\n\n  getChar (index) {\n    return String.fromCharCode(0x61 + index)\n  },\n\n  log (compiled) {\n    compiled.mpErrors = []\n    compiled.mpTips = []\n\n    return (str, type) => {\n      if (type === 'waring') {\n        compiled.mpTips.push(str)\n      } else {\n        compiled.mpErrors.push(str)\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "src/platforms/mp/compiler/create-compiler.js",
    "content": "/* @flow */\n\nimport { parse } from 'compiler/parser/index'\nimport { optimize } from 'compiler/optimizer'\nimport { generate } from 'compiler/codegen/index'\nimport { createCompilerCreator } from 'compiler/create-compiler'\n\n// for mp\nimport { markComponent } from './mark-component'\n\n// `createCompilerCreator` allows creating compilers that use alternative\n// parser/optimizer/codegen, e.g the SSR optimizing compiler.\n// Here we just export a default compiler using the default parts.\nexport const createCompiler = createCompilerCreator(function baseCompile (\n  template: string,\n  options: CompilerOptions\n): CompiledResult {\n  const originAst = parse(template.trim(), options)\n  const ast = markComponent(originAst, options)\n  optimize(ast, options)\n  const code = generate(ast, options)\n  return {\n    ast,\n    render: code.render,\n    staticRenderFns: code.staticRenderFns\n  }\n})\n"
  },
  {
    "path": "src/platforms/mp/compiler/directives/html.js",
    "content": "/* @flow */\n\nimport { addProp } from 'compiler/helpers'\n\nexport default function html (el: ASTElement, dir: ASTDirective) {\n  if (dir.value) {\n    addProp(el, 'innerHTML', `_s(${dir.value})`)\n  }\n}\n"
  },
  {
    "path": "src/platforms/mp/compiler/directives/index.js",
    "content": "import model from './model'\nimport text from './text'\nimport html from './html'\n\nexport default {\n  model,\n  text,\n  html\n}\n"
  },
  {
    "path": "src/platforms/mp/compiler/directives/model.js",
    "content": "/* @flow */\n\nimport config from 'core/config'\nimport { addHandler, addProp, getBindingAttr } from 'compiler/helpers'\nimport { genComponentModel, genAssignmentCode } from 'compiler/directives/model'\n\nlet warn\n\n// in some cases, the event used has to be determined at runtime\n// so we used some reserved tokens during compile.\nexport const RANGE_TOKEN = '__r'\nexport const CHECKBOX_RADIO_TOKEN = '__c'\n\nexport default function model (\n  el: ASTElement,\n  dir: ASTDirective,\n  _warn: Function\n): ?boolean {\n  warn = _warn\n  const value = dir.value\n  const modifiers = dir.modifiers\n  const tag = el.tag\n  const type = el.attrsMap.type\n\n  if (process.env.NODE_ENV !== 'production') {\n    const dynamicType = el.attrsMap['v-bind:type'] || el.attrsMap[':type']\n    if (tag === 'input' && dynamicType) {\n      warn(\n        `<input :type=\"${dynamicType}\" v-model=\"${value}\">:\\n` +\n        `v-model does not support dynamic input types. Use v-if branches instead.`\n      )\n    }\n    // inputs with type=\"file\" are read only and setting the input's\n    // value will throw an error.\n    if (tag === 'input' && type === 'file') {\n      warn(\n        `<${el.tag} v-model=\"${value}\" type=\"file\">:\\n` +\n        `File inputs are read only. Use a v-on:change listener instead.`\n      )\n    }\n  }\n\n  if (el.component) {\n    genComponentModel(el, value, modifiers)\n    // component v-model doesn't need extra runtime\n    return false\n  } else if (tag === 'select') {\n    genSelect(el, value, modifiers)\n  } else if (tag === 'input' && type === 'checkbox') {\n    genCheckboxModel(el, value, modifiers)\n  } else if (tag === 'input' && type === 'radio') {\n    genRadioModel(el, value, modifiers)\n  } else if (tag === 'input' || tag === 'textarea') {\n    genDefaultModel(el, value, modifiers)\n  } else if (!config.isReservedTag(tag)) {\n    genComponentModel(el, value, modifiers)\n    // component v-model doesn't need extra runtime\n    return false\n  } else if (process.env.NODE_ENV !== 'production') {\n    warn(\n      `<${el.tag} v-model=\"${value}\">: ` +\n      `v-model is not supported on this element type. ` +\n      'If you are working with contenteditable, it\\'s recommended to ' +\n      'wrap a library dedicated for that purpose inside a custom component.'\n    )\n  }\n\n  // ensure runtime directive metadata\n  return true\n}\n\nfunction genCheckboxModel (\n  el: ASTElement,\n  value: string,\n  modifiers: ?ASTModifiers\n) {\n  const number = modifiers && modifiers.number\n  const valueBinding = getBindingAttr(el, 'value') || 'null'\n  const trueValueBinding = getBindingAttr(el, 'true-value') || 'true'\n  const falseValueBinding = getBindingAttr(el, 'false-value') || 'false'\n  addProp(el, 'checked',\n    `Array.isArray(${value})` +\n      `?_i(${value},${valueBinding})>-1` + (\n        trueValueBinding === 'true'\n          ? `:(${value})`\n          : `:_q(${value},${trueValueBinding})`\n      )\n  )\n  addHandler(el, CHECKBOX_RADIO_TOKEN,\n    `var $$a=${value},` +\n        '$$el=$event.target,' +\n        `$$c=$$el.checked?(${trueValueBinding}):(${falseValueBinding});` +\n    'if(Array.isArray($$a)){' +\n      `var $$v=${number ? '_n(' + valueBinding + ')' : valueBinding},` +\n          '$$i=_i($$a,$$v);' +\n      `if($$c){$$i<0&&(${value}=$$a.concat($$v))}` +\n      `else{$$i>-1&&(${value}=$$a.slice(0,$$i).concat($$a.slice($$i+1)))}` +\n    `}else{${genAssignmentCode(value, '$$c')}}`,\n    null, true\n  )\n}\n\nfunction genRadioModel (\n    el: ASTElement,\n    value: string,\n    modifiers: ?ASTModifiers\n) {\n  const number = modifiers && modifiers.number\n  let valueBinding = getBindingAttr(el, 'value') || 'null'\n  valueBinding = number ? `_n(${valueBinding})` : valueBinding\n  addProp(el, 'checked', `_q(${value},${valueBinding})`)\n  addHandler(el, CHECKBOX_RADIO_TOKEN, genAssignmentCode(value, valueBinding), null, true)\n}\n\nfunction genSelect (\n    el: ASTElement,\n    value: string,\n    modifiers: ?ASTModifiers\n) {\n  const number = modifiers && modifiers.number\n  const selectedVal = `Array.prototype.filter` +\n    `.call($event.target.options,function(o){return o.selected})` +\n    `.map(function(o){var val = \"_value\" in o ? o._value : o.value;` +\n    `return ${number ? '_n(val)' : 'val'}})`\n\n  const assignment = '$event.target.multiple ? $$selectedVal : $$selectedVal[0]'\n  let code = `var $$selectedVal = ${selectedVal};`\n  code = `${code} ${genAssignmentCode(value, assignment)}`\n  addHandler(el, 'change', code, null, true)\n}\n\nfunction genDefaultModel (\n  el: ASTElement,\n  value: string,\n  modifiers: ?ASTModifiers\n): ?boolean {\n  const type = el.attrsMap.type\n  const { lazy, number, trim } = modifiers || {}\n  const needCompositionGuard = !lazy && type !== 'range'\n  const event = lazy\n    ? 'change'\n    : type === 'range'\n      ? RANGE_TOKEN\n      : 'input'\n\n  let valueExpression = '$event.target.value'\n  if (trim) {\n    valueExpression = `$event.target.value.trim()`\n  }\n  if (number) {\n    valueExpression = `_n(${valueExpression})`\n  }\n\n  let code = genAssignmentCode(value, valueExpression)\n  if (needCompositionGuard) {\n    code = `if($event.target.composing)return;${code}`\n  }\n\n  addProp(el, 'value', `(${value})`)\n  addHandler(el, event, code, null, true)\n  if (trim || number) {\n    addHandler(el, 'blur', '$forceUpdate()')\n  }\n}\n"
  },
  {
    "path": "src/platforms/mp/compiler/directives/text.js",
    "content": "/* @flow */\n\nimport { addProp } from 'compiler/helpers'\n\nexport default function text (el: ASTElement, dir: ASTDirective) {\n  if (dir.value) {\n    addProp(el, 'textContent', `_s(${dir.value})`)\n  }\n}\n"
  },
  {
    "path": "src/platforms/mp/compiler/index.js",
    "content": "import { baseOptions } from './options'\nimport { createCompiler } from './create-compiler'\n\nimport codeGenWx from './wx/index'\nimport codeGenSwan from './swan/index'\nimport codeGenTt from './tt/index'\nimport codeGenMy from './my/index'\n\nfunction compileToMPML (compiled, options, fileExt) {\n  let code\n  switch (fileExt.platform) {\n    case 'swan':\n      code = codeGenSwan(compiled, options)\n      break\n    case 'wx':\n      code = codeGenWx(compiled, options)\n      break\n    case 'tt':\n      code = codeGenTt(compiled, options)\n      break\n    case 'my':\n      code = codeGenMy(compiled, options)\n      break\n    default:\n      code = codeGenWx(compiled, options)\n  }\n  return code\n}\n\nconst { compile, compileToFunctions } = createCompiler(baseOptions)\nexport {\n  compile,\n  compileToFunctions,\n  compileToMPML\n}\n"
  },
  {
    "path": "src/platforms/mp/compiler/mark-component.js",
    "content": "import convertTagMap from './common/tagMap'\n\nfunction maybeTag (tagName) {\n  return convertTagMap[tagName]\n}\n\nfunction getWxEleId (index, arr) {\n  if (!arr || !arr.length) {\n    return `'${index}'`\n  }\n\n  const str = arr.join(`+'-'+`)\n  return `'${index}_'+${str}`\n}\n\n// 检查不允许在 v-for 的时候出现2个及其以上相同 iterator1\nfunction checkRepeatIterator (arr, options) {\n  const len = arr.length\n  if (len > 1 && len !== new Set(arr).size) {\n    options.warn(`同一组件内嵌套的 v-for 不能连续使用相同的索引，目前为: ${arr}`, false)\n  }\n}\n\nfunction fixDefaultIterator (path) {\n  const { for: forText, iterator1 } = path\n  if (forText && !iterator1) {\n    path.iterator1 = 'index'\n  }\n}\n\nfunction addAttr (path, key, value, inVdom) {\n  path[key] = value\n  path.plain = false\n  // path.attrsMap[key] = value\n  if (!inVdom) {\n    path.attrsMap[`data-${key}`] = `{{${value}}}`\n  }\n\n  // if (!path.attrsList) {\n  //   path.attrsList = []\n  // }\n  // path.attrsList.push({ name: `':${key}'`, value })\n\n  if (!path.attrs) {\n    path.attrs = []\n  }\n  path.attrs.push({ name: key, value })\n}\n\nfunction mark (path, options, deps, iteratorArr = []) {\n  fixDefaultIterator(path)\n\n  const { tag, children, iterator1, events, directives, ifConditions } = path\n\n  const currentArr = Object.assign([], iteratorArr)\n\n  if (iterator1) {\n    currentArr.push(iterator1)\n  }\n\n  checkRepeatIterator(currentArr, options)\n\n  // 递归子节点\n  if (children && children.length) {\n    children.forEach((v, i) => {\n      // const counterIterator = children.slice(0, i).filter(v => v.for).map(v => v.for + '.length').join(`+'-'+`)\n      mark(v, options, deps, currentArr)\n    })\n  }\n\n  // fix: v-else events\n  if (ifConditions && ifConditions.length > 1) {\n    ifConditions.slice(1).forEach((v, i) => {\n      mark(v.block, options, deps, currentArr)\n    })\n  }\n\n  // for mpvue-template-compiler\n  // events || v-model\n  const hasModel = directives && directives.find(v => v.name === 'model')\n  const needEventsID = events || hasModel\n\n  if (needEventsID) {\n    let level = 0\n    let _path = Object.assign({}, path)\n    while (_path && _path.parent) {\n      level++\n      _path = _path.parent\n    }\n    const eventId = getWxEleId(level + '_' + deps.eventIndex, currentArr)\n    // const eventId = getWxEleId(eIndex, currentArr)\n    addAttr(path, 'eventid', eventId)\n    path.attrsMap['data-comkey'] = '{{$k}}'\n    deps.eventIndex += 1\n    // eIndex += 1\n  }\n\n  // 子组件\n  if (!tag || maybeTag(tag)) {\n    return\n  }\n\n  // eg. '1-'+i+'-'+j\n  const value = getWxEleId(deps.comIndex, currentArr)\n  addAttr(path, 'mpcomid', value, true)\n  path['mpcomid'] = value\n  deps.comIndex += 1\n}\n\n// 全局的事件触发器 ID\n// let eIndex = 0\nexport function markComponent (ast, options) {\n  const deps = { comIndex: 0, eventIndex: 0 }\n  mark(ast, options, deps)\n\n  return ast\n}\n"
  },
  {
    "path": "src/platforms/mp/compiler/modules/class.js",
    "content": "/* @flow */\n\nimport { parseText } from 'compiler/parser/text-parser'\nimport {\n  getAndRemoveAttr,\n  getBindingAttr,\n  baseWarn\n} from 'compiler/helpers'\n\nfunction transformNode (el: ASTElement, options: CompilerOptions) {\n  const warn = options.warn || baseWarn\n  const staticClass = getAndRemoveAttr(el, 'class')\n  if (process.env.NODE_ENV !== 'production' && staticClass) {\n    const expression = parseText(staticClass, options.delimiters)\n    if (expression) {\n      warn(\n        `class=\"${staticClass}\": ` +\n        'Interpolation inside attributes has been removed. ' +\n        'Use v-bind or the colon shorthand instead. For example, ' +\n        'instead of <div class=\"{{ val }}\">, use <div :class=\"val\">.'\n      )\n    }\n  }\n  if (staticClass) {\n    el.staticClass = JSON.stringify(staticClass)\n  }\n  const classBinding = getBindingAttr(el, 'class', false /* getStatic */)\n  if (classBinding) {\n    el.classBinding = classBinding\n  }\n}\n\nfunction genData (el: ASTElement): string {\n  let data = ''\n  if (el.staticClass) {\n    data += `staticClass:${el.staticClass},`\n  }\n  if (el.classBinding) {\n    data += `class:${el.classBinding},`\n  }\n  return data\n}\n\nexport default {\n  staticKeys: ['staticClass'],\n  transformNode,\n  genData\n}\n"
  },
  {
    "path": "src/platforms/mp/compiler/modules/index.js",
    "content": "import klass from './class'\nimport style from './style'\n\nexport default [\n  klass,\n  style\n]\n"
  },
  {
    "path": "src/platforms/mp/compiler/modules/style.js",
    "content": "/* @flow */\n\nimport { parseText } from 'compiler/parser/text-parser'\nimport { parseStyleText } from 'web/util/style'\nimport {\n  getAndRemoveAttr,\n  getBindingAttr,\n  baseWarn\n} from 'compiler/helpers'\n\nfunction transformNode (el: ASTElement, options: CompilerOptions) {\n  const warn = options.warn || baseWarn\n  const staticStyle = getAndRemoveAttr(el, 'style')\n  if (staticStyle) {\n    /* istanbul ignore if */\n    if (process.env.NODE_ENV !== 'production') {\n      const expression = parseText(staticStyle, options.delimiters)\n      if (expression) {\n        warn(\n          `style=\"${staticStyle}\": ` +\n          'Interpolation inside attributes has been removed. ' +\n          'Use v-bind or the colon shorthand instead. For example, ' +\n          'instead of <div style=\"{{ val }}\">, use <div :style=\"val\">.'\n        )\n      }\n    }\n    el.staticStyle = JSON.stringify(parseStyleText(staticStyle))\n  }\n\n  const styleBinding = getBindingAttr(el, 'style', false /* getStatic */)\n  if (styleBinding) {\n    el.styleBinding = styleBinding\n  }\n}\n\nfunction genData (el: ASTElement): string {\n  let data = ''\n  if (el.staticStyle) {\n    data += `staticStyle:${el.staticStyle},`\n  }\n  if (el.styleBinding) {\n    data += `style:(${el.styleBinding}),`\n  }\n  return data\n}\n\nexport default {\n  staticKeys: ['staticStyle'],\n  transformNode,\n  genData\n}\n"
  },
  {
    "path": "src/platforms/mp/compiler/my/config/astMap.js",
    "content": "export default {\n  'if': 'a:if',\n  'iterator1': 'a:for-index',\n  'key': 'a:key',\n  'alias': 'a:for-item',\n  'v-for': 'a:for'\n}\n"
  },
  {
    "path": "src/platforms/mp/compiler/my/config/directiveMap.js",
    "content": "// type：\n// 0, 默认值, 拼接 ${name}={{ ${content} }}\n// 1, 拼接 ${name}\n// 2, 拼接 ${map[key]}={{ '${content}' }}\n// 3, 拼接 {{ ${content} }}\n// 4, 拼接为空字符串\n// 5, 不需要在wxml上表现出来，可直接清除\n\nconst noSupport = {\n  type: 4,\n  check: (k, v, errors) => {\n    errors(`不支持此指令: ${k}=\"${v}\"`)\n    return false\n  }\n}\n\nexport default {\n  'v-if': {\n    name: 'a:if',\n    type: 0\n  },\n  'v-else-if': {\n    name: 'a:elif',\n    type: 0\n  },\n  'v-else': {\n    name: 'a:else',\n    type: 1\n  },\n  'v-text': {\n    name: '',\n    type: 1\n  },\n  'v-html': {\n    name: '',\n    type: 1\n  },\n  'v-on': {\n    name: '',\n    map: {\n      click: 'tap',\n      touchstart: 'touchStart',\n      touchmove: 'touchMove',\n      touchcancel: 'touchCancel',\n      touchend: 'touchEnd',\n      tap: 'tap',\n      longtap: 'longTap',\n      input: 'input',\n      change: 'change',\n      submit: 'submit',\n      blur: 'blur',\n      focus: 'focus',\n      reset: 'reset',\n      confirm: 'confirm',\n      columnchange: 'columnChange',\n      linechange: 'lineChange',\n      error: 'error',\n      scrolltoupper: 'scrollToUpper',\n      scrolltolower: 'scrollToLower',\n      scroll: 'scroll',\n      load: 'load'\n    },\n    type: 2\n  },\n  'v-bind': {\n    name: '',\n    map: {\n      'href': 'url'\n    },\n    type: 3\n  },\n  'href': {\n    name: 'url',\n    type: 2\n  },\n  'v-pre': noSupport,\n  'v-cloak': noSupport,\n  'v-once': {\n    name: '',\n    type: 5\n  }\n}\n"
  },
  {
    "path": "src/platforms/mp/compiler/my/convert/attrs.js",
    "content": "import directiveMap from '../config/directiveMap'\nimport tagConfig from '../../common/config'\n\nimport babel from 'babel-core'\nimport prettier from 'prettier'\n\nimport { transformObjectToTernaryOperator, transformObjectToString } from '../../common/babel-plugins'\nfunction transformDynamicClass (staticClass = '', clsBinding) {\n  const result = babel.transform(`!${clsBinding}`, { plugins: [transformObjectToTernaryOperator] })\n  // 先实现功能，再优化代码\n  // https://github.com/babel/babel/issues/7138\n  const cls = prettier.format(result.code, { semi: false, singleQuote: true }).slice(1).slice(0, -1).replace(/\\n|\\r/g, '')\n  return `${staticClass} {{${cls}}}`\n}\n\nfunction transformDynamicStyle (staticStyle = '', styleBinding) {\n  const result = babel.transform(`!${styleBinding}`, { plugins: [transformObjectToString] })\n  const cls = prettier.format(result.code, { semi: false, singleQuote: true }).slice(1).slice(0, -1).replace(/\\n|\\r/g, '')\n  return `${staticStyle} {{${cls}}}`\n}\n\nexport default {\n  format (attrs = {}) {\n    const obj = {}\n\n    Object.keys(attrs).map((key) => {\n      const val = attrs[key]\n      obj[key.replace('@', 'v-on:').replace(/^:/, 'v-bind:')] = val\n    })\n    return obj\n  },\n\n  convertAttr (ast, log) {\n    const { attrsMap = {}, tag, staticClass } = ast\n    let attrs = {}\n    const wxClass = this.classObj(attrsMap['v-bind:class'], staticClass)\n    wxClass.length ? attrsMap['class'] = wxClass : ''\n    const wxStyle = this.styleObj(attrsMap['v-bind:style'], attrsMap['style'])\n    wxStyle.length ? attrsMap['style'] = wxStyle : ''\n\n    Object.keys(attrsMap).map(key => {\n      const val = attrsMap[key]\n      if (key === 'v-bind:class' || key === 'v-bind:style') {\n        return\n      }\n      if (key === 'v-text') {\n        ast.children.unshift({\n          text: `{{${val}}}`,\n          type: 3\n        })\n      } else if (key === 'v-html') {\n        ast.tag = 'rich-text'\n        attrs['nodes'] = `{{${val}}}`\n      } else if (key === 'v-show') {\n        attrs['hidden'] = `{{!(${val})}}`\n      } else if (/^v\\-on\\:/i.test(key)) {\n        attrs = this.event(key, val, attrs, tag, log)\n      } else if (/^v\\-bind\\:/i.test(key)) {\n        attrs = this.bind(key, val, attrs, tag, attrsMap['a:key'])\n      } else if (/^v\\-model/.test(key)) {\n        attrs = this.model(key, val, attrs, tag, log)\n      } else if (directiveMap[key]) {\n        const { name = '', type, map = {}, check } = directiveMap[key] || {}\n        if (!(check && !check(key, val, log)) && !(!name || typeof type !== 'number')) {\n          // 见 ./directiveMap.js 注释\n          if (type === 0) {\n            attrs[name] = `{{${val}}}`\n          }\n\n          if (type === 1) {\n            attrs[name] = undefined\n          }\n\n          if (type === 2) {\n            attrs[name] = val\n          }\n\n          if (type === 3) {\n            attrs[map[name] || name] = `{{${val}}}`\n            return\n          }\n        }\n      } else if (/^v\\-/.test(key)) {\n        log(`不支持此属性-> ${key}=\"${val}\"`, 'waring')\n      } else {\n        if ((tagConfig.virtualTag.indexOf(tag) > -1) && (key === 'class' || key === 'style' || key === 'data-mpcomid')) {\n          if (key !== 'data-mpcomid') {\n            log(`template 不支持此属性-> ${key}=\"${val}\"`, 'waring')\n          }\n        } else {\n          attrs[key] = val\n        }\n      }\n    })\n    ast.attrsMap = attrs\n    return ast\n  },\n\n  event (key, val, attrs, tag, log) {\n    // 小程序能力所致，bind 和 catch 事件同时绑定时候，只会触发 bind ,catch 不会被触发。\n    // .stop 的使用会阻止冒泡，但是同时绑定了一个非冒泡事件，会导致该元素上的 catchEventName 失效！\n    // .prevent 可以直接干掉，因为小程序里没有什么默认事件，比如submit并不会跳转页面\n    // .capture 不能做，因为小程序没有捕获类型的事件\n    // .self 没有可以判断的标识\n    // .once 也不能做，因为小程序没有 removeEventListener, 虽然可以直接在 handleProxy 中处理，但非常的不优雅，违背了原意，暂不考虑\n    const name = key.replace(/^v\\-on\\:/i, '').replace(/\\.prevent/i, '')\n    const [eventName, ...eventNameMap] = name.split('.')\n    const { 'v-on': eventMap, check } = directiveMap\n\n    if (check) {\n      check(key, val)\n    }\n    let wxmlEventName = ''\n    if (eventName === 'change' && (tag === 'input' || tag === 'textarea')) {\n      wxmlEventName = 'blur'\n    } else {\n      wxmlEventName = eventMap.map[eventName]\n    }\n\n    let eventType = 'on'\n    const isStop = eventNameMap.includes('stop')\n    if (eventNameMap.includes('capture')) {\n      log('支付宝小程序不支持事件捕获')\n    } else if (isStop) {\n      eventType = 'catch'\n    }\n    const camelCaseEvent = (wxmlEventName || eventName).replace(/^\\S/, (letter) => letter.toUpperCase())\n    wxmlEventName = eventType + camelCaseEvent\n    attrs[wxmlEventName] = 'handleProxy'\n\n    return attrs\n  },\n\n  bind (key, val, attrs, tag, isIf) {\n    const name = key.replace(/^v\\-bind\\:/i, '')\n\n    if (isIf && name === 'key') {\n      attrs['a:key'] = val\n    }\n\n    if (tag === 'template') {\n      return attrs\n    }\n\n    if (name === 'href') {\n      attrs['url'] = `{{${val}}}`\n    } else {\n      attrs[name] = `{{${val}}}`\n    }\n\n    return attrs\n  },\n\n  classObj (clsBinding = '', staticCls) {\n    if (!clsBinding && !staticCls) {\n      return ''\n    }\n    if (!clsBinding && staticCls) {\n      return staticCls\n    }\n\n    return transformDynamicClass(staticCls, clsBinding)\n  },\n\n  styleObj (styleBinding = '', staticStyle) {\n    if (!styleBinding && !staticStyle) {\n      return ''\n    }\n    if (!styleBinding && staticStyle) {\n      return staticStyle\n    }\n\n    return transformDynamicStyle(staticStyle, styleBinding)\n  },\n\n  model (key, val, attrs, tag) {\n    const isFormInput = tag === 'input' || tag === 'textarea'\n    attrs['value'] = `{{${val}}}`\n    if (key === 'v-model.lazy') {\n      if (isFormInput) {\n        attrs['onBlur'] = 'handleProxy'\n      } else {\n        attrs['onChange'] = 'handleProxy'\n      }\n    } else {\n      if (isFormInput) {\n        attrs['onInput'] = 'handleProxy'\n      } else {\n        attrs['onChange'] = 'handleProxy'\n      }\n    }\n    return attrs\n  }\n}\n"
  },
  {
    "path": "src/platforms/mp/compiler/my/convert/component.js",
    "content": "function getSlotsName (obj) {\n  if (!obj) {\n    return ''\n  }\n  // wxml模板中 data=\"{{ a:{a1:'string2'}, b:'string'}}\" 键a不能放在最后，会出错\n  return tmplateSlotsObj(obj)\n    .concat(\n      Object.keys(obj).map(function (k) {\n        return '$slot' + k + \":'\" + obj[k] + \"'\"\n      })\n    )\n    .join(',')\n}\n\nfunction tmplateSlotsObj (obj) {\n  if (!obj) {\n    return []\n  }\n  // wxml模板中 data=\"{{ a:{a1:'string2'}, b:'string'}}\" 键a1不能写成 'a1' 带引号的形式，会出错\n  const $for = Object.keys(obj)\n    .map(function (k) {\n      return `${k}:'${obj[k]}'`\n    })\n    .join(',')\n  return $for ? [`$for:{${$for}}`] : []\n}\n\nexport default {\n  isComponent (tagName, components = {}) {\n    return !!components[tagName]\n  },\n  convertComponent (ast, components, slotName) {\n    const { attrsMap, tag, mpcomid, slots } = ast\n    if (slotName) {\n      attrsMap['data'] = \"{{...$root[$p], ...$root[$k], $root}}\"\n      // bindedName is available when rendering slot in v-for\n      const bindedName = attrsMap['v-bind:name']\n      if (bindedName) {\n        attrsMap['is'] = \"{{$for[\" + bindedName + \"]}}\"\n      } else {\n        attrsMap['is'] = \"{{\" + slotName + \"}}\"\n      }\n    } else {\n      const slotsName = getSlotsName(slots)\n      const restSlotsName = slotsName ? `, ${slotsName}` : ''\n      attrsMap['data'] = `{{...$root[$kk+${mpcomid}], $root${restSlotsName}}}`\n      attrsMap['is'] = components[tag].name\n    }\n    return ast\n  }\n}\n"
  },
  {
    "path": "src/platforms/mp/compiler/my/convert/for.js",
    "content": "import astMap from '../config/astMap'\n\nexport default function (ast) {\n  const { iterator1, for: forText, key, alias, attrsMap } = ast\n\n  if (forText) {\n    attrsMap[astMap['v-for']] = `{{${forText}}}`\n    if (iterator1) {\n      attrsMap[astMap['iterator1']] = iterator1\n    }\n    if (key) {\n      attrsMap[astMap['key']] = key\n    }\n    if (alias) {\n      attrsMap[astMap['alias']] = alias\n    }\n\n    delete attrsMap['v-for']\n  }\n\n  return ast\n}\n"
  },
  {
    "path": "src/platforms/mp/compiler/my/convert/index.js",
    "content": "import attrs from './attrs'\nimport component from './component'\nimport convertFor from './for'\nimport getAstCommon from '../../common/convert/index'\n\nexport default function mpmlAst (compiled, options = {}, log) {\n  const conventRule = { attrs, component, convertFor }\n  return getAstCommon(compiled, options, log, conventRule)\n}\n"
  },
  {
    "path": "src/platforms/mp/compiler/my/index.js",
    "content": "import getMpmlAst from './convert/index'\nimport compileToMPMLCommon from '../common/generate'\n\nexport default function compileToMPML (compiled, options = {}) {\n  return compileToMPMLCommon(compiled, options, getMpmlAst)\n}\n\n"
  },
  {
    "path": "src/platforms/mp/compiler/options.js",
    "content": "/* @flow */\n\nimport {\n  isPreTag,\n  mustUseProp,\n  isReservedTag,\n  getTagNamespace\n} from '../util/index'\n\nimport modules from './modules/index'\nimport directives from './directives/index'\nimport { genStaticKeys } from 'shared/util'\nimport { isUnaryTag, canBeLeftOpenTag } from './util'\n\nexport const baseOptions: CompilerOptions = {\n  expectHTML: true,\n  modules,\n  directives,\n  isPreTag,\n  isUnaryTag,\n  mustUseProp,\n  canBeLeftOpenTag,\n  isReservedTag,\n  getTagNamespace,\n  staticKeys: genStaticKeys(modules)\n}\n"
  },
  {
    "path": "src/platforms/mp/compiler/swan/config/astMap.js",
    "content": "export default {\n  'if': 's-if',\n  'v-for': 's-for',\n  'alias': 's-for-item',\n  'iterator1': 's-for-index',\n  'key': 's-key'\n}\n"
  },
  {
    "path": "src/platforms/mp/compiler/swan/config/directiveMap.js",
    "content": "// type：\n// 0, 默认值, 拼接 ${name}={{ ${content} }}\n// 1, 拼接 ${name}\n// 2, 拼接 ${map[key]}={{ '${content}' }}\n// 3, 拼接 {{ ${content} }}\n// 4, 拼接为空字符串\n// 5, 不需要在wxml上表现出来，可直接清除\n\nconst noSupport = {\n  type: 4,\n  check (k, v, errors) {\n    errors(`不支持此指令: ${k}=\"${v}\"`)\n    return false\n  }\n}\nexport default {\n  'v-if': {\n    name: 's-if',\n    type: 2\n  },\n  'v-else-if': {\n    name: 's-elif',\n    type: 2\n  },\n  'v-else': {\n    name: 's-else',\n    type: 1\n  },\n  'v-text': {\n    name: '',\n    type: 1\n  },\n  'v-html': {\n    name: '',\n    type: 1\n  },\n  'v-on': {\n    name: '',\n    map: {\n      click: 'tap',\n      touchstart: 'touchstart',\n      touchmove: 'touchmove',\n      touchcancel: 'touchcancel',\n      touchend: 'touchend',\n      tap: 'tap',\n      longtap: 'longtap',\n      input: 'input',\n      change: 'change',\n      submit: 'submit',\n      blur: 'blur',\n      focus: 'focus',\n      reset: 'reset',\n      confirm: 'confirm',\n      columnchange: 'columnchange',\n      linechange: 'linechange',\n      error: 'error',\n      scrolltoupper: 'scrolltoupper',\n      scrolltolower: 'scrolltolower',\n      scroll: 'scroll',\n      load: 'load'\n    },\n    type: 2\n  },\n  'v-bind': {\n    name: '',\n    map: {\n      'href': 'url'\n    },\n    type: 3\n  },\n  'href': {\n    name: 'url',\n    type: 2\n  },\n  'v-pre': noSupport,\n  'v-cloak': noSupport,\n  'v-once': {\n    name: '',\n    type: 5\n  }\n}\n"
  },
  {
    "path": "src/platforms/mp/compiler/swan/convert/attrs.js",
    "content": "import directiveMap from '../config/directiveMap'\nimport tagConfig from '../../common/config'\n\nimport babel from 'babel-core'\nimport prettier from 'prettier'\n\nimport { transformObjectToTernaryOperator, transformObjectToString } from '../../common/babel-plugins'\nfunction transformDynamicClass (staticClass = '', clsBinding) {\n  const result = babel.transform(`!${clsBinding}`, { plugins: [transformObjectToTernaryOperator] })\n  // 先实现功能，再优化代码\n  // https://github.com/babel/babel/issues/7138\n  const cls = prettier.format(result.code, { semi: false, singleQuote: true }).slice(1).slice(0, -1).replace(/\\n|\\r/g, '')\n  return `${staticClass} {{${cls}}}`\n}\n\nfunction transformDynamicStyle (staticStyle = '', styleBinding) {\n  const result = babel.transform(`!${styleBinding}`, { plugins: [transformObjectToString] })\n  const cls = prettier.format(result.code, { semi: false, singleQuote: true }).slice(1).slice(0, -1).replace(/\\n|\\r/g, '')\n  return `${staticStyle} {{${cls}}}`\n}\n\nexport default {\n  format (attrs = {}) {\n    const obj = {}\n\n    Object.keys(attrs).map((key) => {\n      const val = attrs[key]\n      obj[key.replace('@', 'v-on:').replace(/^:/, 'v-bind:')] = val\n    })\n\n    return obj\n  },\n\n  convertAttr (ast, log) {\n    const { attrsMap = {}, tag, staticClass } = ast\n    let attrs = {}\n    const wxClass = this.classObj(attrsMap['v-bind:class'], staticClass)\n    wxClass.length ? attrsMap['class'] = wxClass : ''\n    const wxStyle = this.styleObj(attrsMap['v-bind:style'], attrsMap['style'])\n    wxStyle.length ? attrsMap['style'] = wxStyle : ''\n\n    Object.keys(attrsMap).map(key => {\n      const val = attrsMap[key]\n      if (key === 'v-bind:class' || key === 'v-bind:style') {\n        return\n      }\n      if (key === 'v-text') {\n        ast.children.unshift({\n          text: `{{${val}}}`,\n          type: 3\n        })\n      } else if (key === 'v-html') {\n        ast.tag = 'rich-text'\n        attrs['nodes'] = `{{${val}}}`\n      } else if (key === 'v-show') {\n        attrs['hidden'] = `{{!(${val})}}`\n      } else if (/^v\\-on\\:/i.test(key)) {\n        attrs = this.event(key, val, attrs, tag)\n      } else if (/^v\\-bind\\:/i.test(key)) {\n        attrs = this.bind(key, val, attrs, tag, attrsMap['wx:key'])\n      } else if (/^v\\-model/.test(key)) {\n        attrs = this.model(key, val, attrs, tag, log)\n      } else if (directiveMap[key]) {\n        const { name = '', type, map = {}, check } = directiveMap[key] || {}\n        if (!(check && !check(key, val, log)) && !(!name || typeof type !== 'number')) {\n          // 见 ./directiveMap.js 注释\n          if (type === 0) {\n            attrs[name] = `{{${val}}}`\n          }\n\n          if (type === 1) {\n            attrs[name] = undefined\n          }\n\n          if (type === 2) {\n            attrs[name] = val\n          }\n\n          if (type === 3) {\n            attrs[map[name] || name] = `{{${val}}}`\n            return\n          }\n        }\n      } else if (/^v\\-/.test(key)) {\n        log(`不支持此属性-> ${key}=\"${val}\"`, 'waring')\n      } else {\n        if ((tagConfig.virtualTag.indexOf(tag) > -1) && (key === 'class' || key === 'style' || key === 'data-mpcomid')) {\n          if (key !== 'data-mpcomid') {\n            log(`template 不支持此属性-> ${key}=\"${val}\"`, 'waring')\n          }\n        } else {\n          attrs[key] = val\n        }\n      }\n    })\n    ast.attrsMap = attrs\n    return ast\n  },\n\n  event (key, val, attrs, tag) {\n    // 小程序能力所致，bind 和 catch 事件同时绑定时候，只会触发 bind ,catch 不会被触发。\n    // .stop 的使用会阻止冒泡，但是同时绑定了一个非冒泡事件，会导致该元素上的 catchEventName 失效！\n    // .prevent 可以直接干掉，因为小程序里没有什么默认事件，比如submit并不会跳转页面\n    // .capture 不能做，因为小程序没有捕获类型的事件\n    // .self 没有可以判断的标识\n    // .once 也不能做，因为小程序没有 removeEventListener, 虽然可以直接在 handleProxy 中处理，但非常的不优雅，违背了原意，暂不考虑\n    const name = key.replace(/^v\\-on\\:/i, '').replace(/\\.prevent/i, '')\n    const [eventName, ...eventNameMap] = name.split('.')\n    const { 'v-on': eventMap, check } = directiveMap\n\n    if (check) {\n      check(key, val)\n    }\n    let wxmlEventName = ''\n    if (eventName === 'change' && (tag === 'input' || tag === 'textarea')) {\n      wxmlEventName = 'blur'\n    } else {\n      wxmlEventName = eventMap.map[eventName]\n    }\n\n    let eventType = 'bind'\n    const isStop = eventNameMap.includes('stop')\n    if (eventNameMap.includes('capture')) {\n      eventType = isStop ? 'capture-catch:' : 'capture-bind:'\n    } else if (isStop) {\n      eventType = 'catch'\n    }\n\n    wxmlEventName = eventType + (wxmlEventName || eventName)\n    attrs[wxmlEventName] = 'handleProxy'\n\n    return attrs\n  },\n\n  bind (key, val, attrs, tag, isIf) {\n    const name = key.replace(/^v\\-bind\\:/i, '')\n\n    if (isIf && name === 'key') {\n      attrs['wx:key'] = val\n    }\n\n    if (tag === 'template') {\n      return attrs\n    }\n\n    if (name === 'href') {\n      attrs['url'] = `{{${val}}}`\n    } else {\n      attrs[name] = `{{${val}}}`\n    }\n\n    if (tag === 'scroll-view') {\n      if (name === 'scroll-top' || name === 'scroll-left' || name === 'scroll-into-view') {\n        attrs[name] = `{=${val}=}`\n      }\n    }\n\n    if (tag === 'input' || tag === 'textarea' || tag === 'slider') {\n      if (name === 'value') {\n        attrs[name] = `{=${val}=}`\n      }\n    }\n\n    if (tag === 'movable-view' && (name === 'x' || name === 'y')) {\n      attrs[name] = `{=${val}=}`\n    }\n\n    return attrs\n  },\n\n  classObj (clsBinding = '', staticCls) {\n    if (!clsBinding && !staticCls) {\n      return ''\n    }\n    if (!clsBinding && staticCls) {\n      return staticCls\n    }\n\n    return transformDynamicClass(staticCls, clsBinding)\n  },\n\n  styleObj (styleBinding = '', staticStyle) {\n    if (!styleBinding && !staticStyle) {\n      return ''\n    }\n    if (!styleBinding && staticStyle) {\n      return staticStyle\n    }\n\n    return transformDynamicStyle(staticStyle, styleBinding)\n  },\n\n  model (key, val, attrs, tag) {\n    const isFormInput = tag === 'input' || tag === 'textarea'\n    attrs['value'] = `{{${val}}}`\n    if (key === 'v-model.lazy') {\n      if (isFormInput) {\n        attrs['bindblur'] = 'handleProxy'\n      } else {\n        attrs['bindchange'] = 'handleProxy'\n      }\n    } else {\n      if (isFormInput) {\n        attrs['bindinput'] = 'handleProxy'\n      } else {\n        attrs['bindchange'] = 'handleProxy'\n      }\n    }\n\n    return attrs\n  }\n}\n"
  },
  {
    "path": "src/platforms/mp/compiler/swan/convert/component.js",
    "content": "function getSlotsName (obj) {\n  if (!obj) {\n    return ''\n  }\n  // wxml模板中 data=\"{{ a:{a1:'string2'}, b:'string'}}\" 键a不能放在最后，会出错\n  return tmplateSlotsObj(obj)\n    .concat(\n      Object.keys(obj).map(k => `$slot${k}:'${obj[k]}'`)\n    )\n    .join(',')\n}\n\nfunction tmplateSlotsObj (obj) {\n  if (!obj) {\n    return []\n  }\n  // wxml模板中 data=\"{{ a:{a1:'string2'}, b:'string'}}\" 键a1不能写成 'a1' 带引号的形式，会出错\n  const $for = Object.keys(obj)\n    .map(k => `${k}:'${obj[k]}'`)\n    .join(',')\n  return $for ? [`$for:{${$for}}`] : []\n}\n\nexport default {\n  isComponent (tagName, components = {}) {\n    return !!components[tagName]\n  },\n  convertComponent (ast, components, slotName) {\n    const { attrsMap, tag, mpcomid, slots } = ast\n    if (slotName) {\n      attrsMap['data'] = '{{{...$root[$p], ...$root[$k], $root}}}'\n      // bindedName is available when rendering slot in v-for\n      const bindedName = attrsMap['v-bind:name']\n      if (bindedName) {\n        attrsMap['is'] = '{{$for[' + bindedName + ']}}'\n      } else {\n        attrsMap['is'] = '{{' + slotName + '}}'\n      }\n    } else {\n      const slotsName = getSlotsName(slots)\n      const restSlotsName = slotsName ? `, ${slotsName}` : ''\n      attrsMap['data'] = `{{{...$root[$kk+${mpcomid}], $root${restSlotsName}}}}`\n      attrsMap['is'] = components[tag].name\n    }\n    return ast\n  }\n}\n"
  },
  {
    "path": "src/platforms/mp/compiler/swan/convert/for.js",
    "content": "import astMap from '../config/astMap'\n\nexport default function (ast) {\n  const { iterator1, for: forText, key, alias, attrsMap } = ast\n\n  // 缩写：<view s-for=\"p,index in persons\">\n  // 全写：<view s-for=\"persons\" s-for-index=\"index\" s-for-item=\"p\">\n\n  if (forText) {\n    attrsMap[astMap['v-for']] = `${alias},${iterator1} in ${forText}`\n    // attrsMap[astMap['v-for']] = forText\n    // if (iterator1) {\n    //   attrsMap[astMap['iterator1']] = iterator1\n    // }\n    // if (alias) {\n    //   attrsMap[astMap['alias']] = alias\n    // }\n    // if (key) {\n    //   attrsMap[astMap['key']] = key\n    // }\n    delete attrsMap['v-for']\n  }\n\n\n  return ast\n}\n"
  },
  {
    "path": "src/platforms/mp/compiler/swan/convert/index.js",
    "content": "import attrs from './attrs'\nimport component from './component'\nimport convertFor from './for'\nimport getAstCommon from '../../common/convert/index'\n\nexport default function mpmlAst (compiled, options = {}, log) {\n  const conventRule = { attrs, component, convertFor }\n  return getAstCommon(compiled, options, log, conventRule)\n}\n"
  },
  {
    "path": "src/platforms/mp/compiler/swan/index.js",
    "content": "import getMpmlAst from './convert/index'\nimport compileToMPMLCommon from '../common/generate'\n\nexport default function compileToMPML (compiled, options = {}) {\n  return compileToMPMLCommon(compiled, options, getMpmlAst)\n}\n"
  },
  {
    "path": "src/platforms/mp/compiler/tt/config/astMap.js",
    "content": "export default {\n  'if': 'tt:if',\n  'iterator1': 'tt:for-index',\n  'key': 'tt:key',\n  'alias': 'tt:for-item',\n  'v-for': 'tt:for'\n}\n"
  },
  {
    "path": "src/platforms/mp/compiler/tt/config/directiveMap.js",
    "content": "// type：\n// 0, 默认值, 拼接 ${name}={{ ${content} }}\n// 1, 拼接 ${name}\n// 2, 拼接 ${map[key]}={{ '${content}' }}\n// 3, 拼接 {{ ${content} }}\n// 4, 拼接为空字符串\n// 5, 不需要在wxml上表现出来，可直接清除\n\nconst noSupport = {\n  type: 4,\n  check (k, v, errors) {\n    errors(`不支持此指令: ${k}=\"${v}\"`)\n    return false\n  }\n}\nexport default {\n  'v-if': {\n    name: 'tt:if',\n    type: 0\n  },\n  'v-else-if': {\n    name: 'tt:elif',\n    type: 0\n  },\n  'v-else': {\n    name: 'tt:else',\n    type: 1\n  },\n  'v-text': {\n    name: '',\n    type: 1\n  },\n  'v-html': {\n    name: '',\n    type: 1\n  },\n  'v-on': {\n    name: '',\n    map: {\n      click: 'tap',\n      touchstart: 'touchstart',\n      touchmove: 'touchmove',\n      touchcancel: 'touchcancel',\n      touchend: 'touchend',\n      tap: 'tap',\n      longtap: 'longtap',\n      input: 'input',\n      change: 'change',\n      submit: 'submit',\n      blur: 'blur',\n      focus: 'focus',\n      reset: 'reset',\n      confirm: 'confirm',\n      columnchange: 'columnchange',\n      linechange: 'linechange',\n      error: 'error',\n      scrolltoupper: 'scrolltoupper',\n      scrolltolower: 'scrolltolower',\n      scroll: 'scroll',\n      load: 'load'\n    },\n    type: 2\n  },\n  'v-bind': {\n    name: '',\n    map: {\n      'href': 'url'\n    },\n    type: 3\n  },\n  'href': {\n    name: 'url',\n    type: 2\n  },\n  'v-pre': noSupport,\n  'v-cloak': noSupport,\n  'v-once': {\n    name: '',\n    type: 5\n  }\n}\n"
  },
  {
    "path": "src/platforms/mp/compiler/tt/convert/attrs.js",
    "content": "import directiveMap from '../config/directiveMap'\nimport tagConfig from '../../common/config'\n\nimport babel from 'babel-core'\nimport prettier from 'prettier'\n\nimport { transformObjectToTernaryOperator, transformObjectToString } from '../../common/babel-plugins'\nfunction transformDynamicClass (staticClass = '', clsBinding) {\n  const result = babel.transform(`!${clsBinding}`, { plugins: [transformObjectToTernaryOperator] })\n  // 先实现功能，再优化代码\n  // https://github.com/babel/babel/issues/7138\n  const cls = prettier.format(result.code, { semi: false, singleQuote: true }).slice(1).slice(0, -1).replace(/\\n|\\r/g, '')\n  return `${staticClass} {{${cls}}}`\n}\n\nfunction transformDynamicStyle (staticStyle = '', styleBinding) {\n  const result = babel.transform(`!${styleBinding}`, { plugins: [transformObjectToString] })\n  const cls = prettier.format(result.code, { semi: false, singleQuote: true }).slice(1).slice(0, -1).replace(/\\n|\\r/g, '')\n  return `${staticStyle} {{${cls}}}`\n}\n\nexport default {\n  format (attrs = {}) {\n    const obj = {}\n\n    Object.keys(attrs).map((key) => {\n      const val = attrs[key]\n      obj[key.replace('@', 'v-on:').replace(/^:/, 'v-bind:')] = val\n    })\n\n    return obj\n  },\n\n  convertAttr (ast, log) {\n    const { attrsMap = {}, tag, staticClass } = ast\n    let attrs = {}\n    const wxClass = this.classObj(attrsMap['v-bind:class'], staticClass)\n    wxClass.length ? attrsMap['class'] = wxClass : ''\n    const wxStyle = this.styleObj(attrsMap['v-bind:style'], attrsMap['style'])\n    wxStyle.length ? attrsMap['style'] = wxStyle : ''\n\n    Object.keys(attrsMap).map(key => {\n      const val = attrsMap[key]\n      if (key === 'v-bind:class' || key === 'v-bind:style') {\n        return\n      }\n      if (key === 'v-text') {\n        ast.children.unshift({\n          text: `{{${val}}}`,\n          type: 3\n        })\n      } else if (key === 'v-html') {\n        ast.tag = 'rich-text'\n        attrs['nodes'] = `{{${val}}}`\n      } else if (key === 'v-show') {\n        attrs['hidden'] = `{{!(${val})}}`\n      } else if (/^v\\-on\\:/i.test(key)) {\n        attrs = this.event(key, val, attrs, tag)\n      } else if (/^v\\-bind\\:/i.test(key)) {\n        attrs = this.bind(key, val, attrs, tag, attrsMap['tt:key'])\n      } else if (/^v\\-model/.test(key)) {\n        attrs = this.model(key, val, attrs, tag, log)\n      } else if (directiveMap[key]) {\n        const { name = '', type, map = {}, check } = directiveMap[key] || {}\n        if (!(check && !check(key, val, log)) && !(!name || typeof type !== 'number')) {\n          // 见 ./directiveMap.js 注释\n          if (type === 0) {\n            attrs[name] = `{{${val}}}`\n          }\n\n          if (type === 1) {\n            attrs[name] = undefined\n          }\n\n          if (type === 2) {\n            attrs[name] = val\n          }\n\n          if (type === 3) {\n            attrs[map[name] || name] = `{{${val}}}`\n            return\n          }\n        }\n      } else if (/^v\\-/.test(key)) {\n        log(`不支持此属性-> ${key}=\"${val}\"`, 'waring')\n      } else {\n        if ((tagConfig.virtualTag.indexOf(tag) > -1) && (key === 'class' || key === 'style' || key === 'data-mpcomid')) {\n          if (key !== 'data-mpcomid') {\n            log(`template 不支持此属性-> ${key}=\"${val}\"`, 'waring')\n          }\n        } else {\n          attrs[key] = val\n        }\n      }\n    })\n    ast.attrsMap = attrs\n    return ast\n  },\n\n  event (key, val, attrs, tag) {\n    // 小程序能力所致，bind 和 catch 事件同时绑定时候，只会触发 bind ,catch 不会被触发。\n    // .stop 的使用会阻止冒泡，但是同时绑定了一个非冒泡事件，会导致该元素上的 catchEventName 失效！\n    // .prevent 可以直接干掉，因为小程序里没有什么默认事件，比如submit并不会跳转页面\n    // .capture 不能做，因为小程序没有捕获类型的事件\n    // .self 没有可以判断的标识\n    // .once 也不能做，因为小程序没有 removeEventListener, 虽然可以直接在 handleProxy 中处理，但非常的不优雅，违背了原意，暂不考虑\n    const name = key.replace(/^v\\-on\\:/i, '').replace(/\\.prevent/i, '')\n    const [eventName, ...eventNameMap] = name.split('.')\n    const { 'v-on': eventMap, check } = directiveMap\n\n    if (check) {\n      check(key, val)\n    }\n    let wxmlEventName = ''\n    if (eventName === 'change' && (tag === 'input' || tag === 'textarea')) {\n      wxmlEventName = 'blur'\n    } else {\n      wxmlEventName = eventMap.map[eventName]\n    }\n\n    let eventType = 'bind'\n    const isStop = eventNameMap.includes('stop')\n    if (eventNameMap.includes('capture')) {\n      eventType = isStop ? 'capture-catch:' : 'capture-bind:'\n    } else if (isStop) {\n      eventType = 'catch'\n    }\n\n    wxmlEventName = eventType + (wxmlEventName || eventName)\n    attrs[wxmlEventName] = 'handleProxy'\n\n    return attrs\n  },\n\n  bind (key, val, attrs, tag, isIf) {\n    const name = key.replace(/^v\\-bind\\:/i, '')\n\n    if (isIf && name === 'key') {\n      attrs['tt:key'] = val\n    }\n\n    if (tag === 'template') {\n      return attrs\n    }\n\n    if (name === 'href') {\n      attrs['url'] = `{{${val}}}`\n    } else {\n      attrs[name] = `{{${val}}}`\n    }\n\n    return attrs\n  },\n\n  classObj (clsBinding = '', staticCls) {\n    if (!clsBinding && !staticCls) {\n      return ''\n    }\n    if (!clsBinding && staticCls) {\n      return staticCls\n    }\n\n    return transformDynamicClass(staticCls, clsBinding)\n  },\n\n  styleObj (styleBinding = '', staticStyle) {\n    if (!styleBinding && !staticStyle) {\n      return ''\n    }\n    if (!styleBinding && staticStyle) {\n      return staticStyle\n    }\n\n    return transformDynamicStyle(staticStyle, styleBinding)\n  },\n\n  model (key, val, attrs, tag) {\n    const isFormInput = tag === 'input' || tag === 'textarea'\n    attrs['value'] = `{{${val}}}`\n    if (key === 'v-model.lazy') {\n      if (isFormInput) {\n        attrs['bindblur'] = 'handleProxy'\n      } else {\n        attrs['bindchange'] = 'handleProxy'\n      }\n    } else {\n      if (isFormInput) {\n        attrs['bindinput'] = 'handleProxy'\n      } else {\n        attrs['bindchange'] = 'handleProxy'\n      }\n    }\n\n    return attrs\n  }\n}\n"
  },
  {
    "path": "src/platforms/mp/compiler/tt/convert/component.js",
    "content": "function getSlotsName (obj) {\n  if (!obj) {\n    return ''\n  }\n  // wxml模板中 data=\"{{ a:{a1:'string2'}, b:'string'}}\" 键a不能放在最后，会出错\n  return tmplateSlotsObj(obj)\n    .concat(\n      Object.keys(obj).map(function(k) {\n        return '$slot' + k + \":'\" + obj[k] + \"'\"\n      })\n    )\n    .join(',')\n}\n\nfunction tmplateSlotsObj(obj) {\n  if (!obj) {\n    return []\n  }\n  // wxml模板中 data=\"{{ a:{a1:'string2'}, b:'string'}}\" 键a1不能写成 'a1' 带引号的形式，会出错\n  const $for = Object.keys(obj)\n    .map(function(k) {\n      return `${k}:'${obj[k]}'`\n    })\n    .join(',')\n  return $for ? [`$for:{${$for}}`] : []\n}\n\nexport default {\n  isComponent (tagName, components = {}) {\n    return !!components[tagName]\n  },\n  convertComponent (ast, components, slotName) {\n    const { attrsMap, tag, mpcomid, slots } = ast\n    if (slotName) {\n      attrsMap['data'] = \"{{...$root[$p], ...$root[$k], $root}}\"\n      // bindedName is available when rendering slot in v-for\n      const bindedName = attrsMap['v-bind:name']\n      if(bindedName) {\n        attrsMap['is'] = \"{{$for[\" + bindedName + \"]}}\"\n      } else {\n        attrsMap['is'] = \"{{\" + slotName + \"}}\"\n      }\n    } else {\n      const slotsName = getSlotsName(slots)\n      const restSlotsName = slotsName ? `, ${slotsName}` : ''\n      attrsMap['data'] = `{{...$root[$kk+${mpcomid}], $root${restSlotsName}}}`\n      attrsMap['is'] = components[tag].name\n    }\n    return ast\n  }\n}\n"
  },
  {
    "path": "src/platforms/mp/compiler/tt/convert/for.js",
    "content": "import astMap from '../config/astMap'\n\nexport default function (ast) {\n  const { iterator1, for: forText, key, alias, attrsMap } = ast\n  if (forText) {\n    attrsMap[astMap['v-for']] = `{{${forText}}}`\n    if (iterator1) {\n      attrsMap[astMap['iterator1']] = iterator1\n    }\n    if (key) {\n      attrsMap[astMap['key']] = key\n    }\n    if (alias) {\n      attrsMap[astMap['alias']] = alias\n    }\n\n    delete attrsMap['v-for']\n  }\n\n  return ast\n}\n"
  },
  {
    "path": "src/platforms/mp/compiler/tt/convert/index.js",
    "content": "import attrs from './attrs'\nimport component from './component'\nimport convertFor from './for'\nimport getAstCommon from '../../common/convert/index'\n\nexport default function mpmlAst (compiled, options = {}, log) {\n  const conventRule = { attrs, component, convertFor }\n  return getAstCommon(compiled, options, log, conventRule)\n}\n"
  },
  {
    "path": "src/platforms/mp/compiler/tt/index.js",
    "content": "import getMpmlAst from './convert/index'\nimport compileToMPMLCommon from '../common/generate'\n\nexport default function compileToMPML (compiled, options = {}) {\n  return compileToMPMLCommon(compiled, options, getMpmlAst)\n}\n"
  },
  {
    "path": "src/platforms/mp/compiler/util.js",
    "content": "/* @flow */\n\nimport { makeMap } from 'shared/util'\n\nexport const isUnaryTag = makeMap(\n  'area,base,br,col,embed,frame,hr,img,input,isindex,keygen,' +\n  'link,meta,param,source,track,wbr'\n)\n\n// Elements that you can, intentionally, leave open\n// (and which close themselves)\nexport const canBeLeftOpenTag = makeMap(\n  'colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr,source'\n)\n\n// HTML5 tags https://html.spec.whatwg.org/multipage/indices.html#elements-3\n// Phrasing Content https://html.spec.whatwg.org/multipage/dom.html#phrasing-content\nexport const isNonPhrasingTag = makeMap(\n  'address,article,aside,base,blockquote,body,caption,col,colgroup,dd,' +\n  'details,dialog,div,dl,dt,fieldset,figcaption,figure,footer,form,' +\n  'h1,h2,h3,h4,h5,h6,head,header,hgroup,hr,html,legend,li,menuitem,meta,' +\n  'optgroup,option,param,rp,rt,source,style,summary,tbody,td,tfoot,th,thead,' +\n  'title,tr,track'\n)\n"
  },
  {
    "path": "src/platforms/mp/compiler/wx/config/astMap.js",
    "content": "export default {\n  'if': 'wx:if',\n  'iterator1': 'wx:for-index',\n  'key': 'wx:key',\n  'alias': 'wx:for-item',\n  'v-for': 'wx:for'\n}\n"
  },
  {
    "path": "src/platforms/mp/compiler/wx/config/directiveMap.js",
    "content": "// type：\n// 0, 默认值, 拼接 ${name}={{ ${content} }}\n// 1, 拼接 ${name}\n// 2, 拼接 ${map[key]}={{ '${content}' }}\n// 3, 拼接 {{ ${content} }}\n// 4, 拼接为空字符串\n// 5, 不需要在wxml上表现出来，可直接清除\n\nconst noSupport = {\n  type: 4,\n  check (k, v, errors) {\n    errors(`不支持此指令: ${k}=\"${v}\"`)\n    return false\n  }\n}\nexport default {\n  'v-if': {\n    name: 'wx:if',\n    type: 0\n  },\n  'v-else-if': {\n    name: 'wx:elif',\n    type: 0\n  },\n  'v-else': {\n    name: 'wx:else',\n    type: 1\n  },\n  'v-text': {\n    name: '',\n    type: 1\n  },\n  'v-html': {\n    name: '',\n    type: 1\n  },\n  'v-on': {\n    name: '',\n    map: {\n      click: 'tap',\n      touchstart: 'touchstart',\n      touchmove: 'touchmove',\n      touchcancel: 'touchcancel',\n      touchend: 'touchend',\n      tap: 'tap',\n      longtap: 'longtap',\n      input: 'input',\n      change: 'change',\n      submit: 'submit',\n      blur: 'blur',\n      focus: 'focus',\n      reset: 'reset',\n      confirm: 'confirm',\n      columnchange: 'columnchange',\n      linechange: 'linechange',\n      error: 'error',\n      scrolltoupper: 'scrolltoupper',\n      scrolltolower: 'scrolltolower',\n      scroll: 'scroll',\n      load: 'load'\n    },\n    type: 2\n  },\n  'v-bind': {\n    name: '',\n    map: {\n      'href': 'url'\n    },\n    type: 3\n  },\n  'href': {\n    name: 'url',\n    type: 2\n  },\n  'v-pre': noSupport,\n  'v-cloak': noSupport,\n  'v-once': {\n    name: '',\n    type: 5\n  }\n}\n"
  },
  {
    "path": "src/platforms/mp/compiler/wx/convert/attrs.js",
    "content": "import directiveMap from '../config/directiveMap'\nimport tagConfig from '../../common/config'\n\nimport babel from 'babel-core'\nimport prettier from 'prettier'\n\nimport { transformObjectToTernaryOperator, transformObjectToString } from '../../common/babel-plugins'\nfunction transformDynamicClass (staticClass = '', clsBinding) {\n  const result = babel.transform(`!${clsBinding}`, { plugins: [transformObjectToTernaryOperator] })\n  // 先实现功能，再优化代码\n  // https://github.com/babel/babel/issues/7138\n  const cls = prettier.format(result.code, { semi: false, singleQuote: true }).slice(1).slice(0, -1).replace(/\\n|\\r/g, '')\n  return `${staticClass} {{${cls}}}`\n}\n\nfunction transformDynamicStyle (staticStyle = '', styleBinding) {\n  const result = babel.transform(`!${styleBinding}`, { plugins: [transformObjectToString] })\n  const cls = prettier.format(result.code, { semi: false, singleQuote: true }).slice(1).slice(0, -1).replace(/\\n|\\r/g, '')\n  return `${staticStyle} {{${cls}}}`\n}\n\nexport default {\n  format (attrs = {}) {\n    const obj = {}\n\n    Object.keys(attrs).map((key) => {\n      const val = attrs[key]\n      obj[key.replace('@', 'v-on:').replace(/^:/, 'v-bind:')] = val\n    })\n\n    return obj\n  },\n\n  convertAttr (ast, log) {\n    const { attrsMap = {}, tag, staticClass } = ast\n    let attrs = {}\n    const wxClass = this.classObj(attrsMap['v-bind:class'], staticClass)\n    wxClass.length ? attrsMap['class'] = wxClass : ''\n    const wxStyle = this.styleObj(attrsMap['v-bind:style'], attrsMap['style'])\n    wxStyle.length ? attrsMap['style'] = wxStyle : ''\n\n    Object.keys(attrsMap).map(key => {\n      const val = attrsMap[key]\n      if (key === 'v-bind:class' || key === 'v-bind:style') {\n        return\n      }\n      if (key === 'v-text') {\n        ast.children.unshift({\n          text: `{{${val}}}`,\n          type: 3\n        })\n      } else if (key === 'v-html') {\n        ast.tag = 'rich-text'\n        attrs['nodes'] = `{{${val}}}`\n      } else if (key === 'v-show') {\n        attrs['hidden'] = `{{!(${val})}}`\n      } else if (/^v\\-on\\:/i.test(key)) {\n        attrs = this.event(key, val, attrs, tag)\n      } else if (/^v\\-bind\\:/i.test(key)) {\n        attrs = this.bind(key, val, attrs, tag, attrsMap['wx:key'])\n      } else if (/^v\\-model/.test(key)) {\n        attrs = this.model(key, val, attrs, tag, log)\n      } else if (directiveMap[key]) {\n        const { name = '', type, map = {}, check } = directiveMap[key] || {}\n        if (!(check && !check(key, val, log)) && !(!name || typeof type !== 'number')) {\n          // 见 ./directiveMap.js 注释\n          if (type === 0) {\n            attrs[name] = `{{${val}}}`\n          }\n\n          if (type === 1) {\n            attrs[name] = undefined\n          }\n\n          if (type === 2) {\n            attrs[name] = val\n          }\n\n          if (type === 3) {\n            attrs[map[name] || name] = `{{${val}}}`\n            return\n          }\n        }\n      } else if (/^v\\-/.test(key)) {\n        log(`不支持此属性-> ${key}=\"${val}\"`, 'waring')\n      } else {\n        if ((tagConfig.virtualTag.indexOf(tag) > -1) && (key === 'class' || key === 'style' || key === 'data-mpcomid')) {\n          if (key !== 'data-mpcomid') {\n            log(`template 不支持此属性-> ${key}=\"${val}\"`, 'waring')\n          }\n        } else {\n          attrs[key] = val\n        }\n      }\n    })\n    ast.attrsMap = attrs\n    return ast\n  },\n\n  event (key, val, attrs, tag) {\n    // 小程序能力所致，bind 和 catch 事件同时绑定时候，只会触发 bind ,catch 不会被触发。\n    // .stop 的使用会阻止冒泡，但是同时绑定了一个非冒泡事件，会导致该元素上的 catchEventName 失效！\n    // .prevent 可以直接干掉，因为小程序里没有什么默认事件，比如submit并不会跳转页面\n    // .capture 不能做，因为小程序没有捕获类型的事件\n    // .self 没有可以判断的标识\n    // .once 也不能做，因为小程序没有 removeEventListener, 虽然可以直接在 handleProxy 中处理，但非常的不优雅，违背了原意，暂不考虑\n    const name = key.replace(/^v\\-on\\:/i, '').replace(/\\.prevent/i, '')\n    const [eventName, ...eventNameMap] = name.split('.')\n    const { 'v-on': eventMap, check } = directiveMap\n\n    if (check) {\n      check(key, val)\n    }\n    let wxmlEventName = ''\n    if (eventName === 'change' && (tag === 'input' || tag === 'textarea')) {\n      wxmlEventName = 'blur'\n    } else {\n      wxmlEventName = eventMap.map[eventName]\n    }\n\n    let eventType = 'bind'\n    const isStop = eventNameMap.includes('stop')\n    if (eventNameMap.includes('capture')) {\n      eventType = isStop ? 'capture-catch:' : 'capture-bind:'\n    } else if (isStop) {\n      eventType = 'catch'\n    }\n\n    wxmlEventName = eventType + (wxmlEventName || eventName)\n    attrs[wxmlEventName] = 'handleProxy'\n\n    return attrs\n  },\n\n  bind (key, val, attrs, tag, isIf) {\n    const name = key.replace(/^v\\-bind\\:/i, '')\n\n    if (isIf && name === 'key') {\n      attrs['wx:key'] = val\n    }\n\n    if (tag === 'template') {\n      return attrs\n    }\n\n    if (name === 'href') {\n      attrs['url'] = `{{${val}}}`\n    } else {\n      attrs[name] = `{{${val}}}`\n    }\n\n    return attrs\n  },\n\n  classObj (clsBinding = '', staticCls) {\n    if (!clsBinding && !staticCls) {\n      return ''\n    }\n    if (!clsBinding && staticCls) {\n      return staticCls\n    }\n\n    return transformDynamicClass(staticCls, clsBinding)\n  },\n\n  styleObj (styleBinding = '', staticStyle) {\n    if (!styleBinding && !staticStyle) {\n      return ''\n    }\n    if (!styleBinding && staticStyle) {\n      return staticStyle\n    }\n\n    return transformDynamicStyle(staticStyle, styleBinding)\n  },\n\n  model (key, val, attrs, tag) {\n    const isFormInput = tag === 'input' || tag === 'textarea'\n    attrs['value'] = `{{${val}}}`\n    if (key === 'v-model.lazy') {\n      if (isFormInput) {\n        attrs['bindblur'] = 'handleProxy'\n      } else {\n        attrs['bindchange'] = 'handleProxy'\n      }\n    } else {\n      if (isFormInput) {\n        attrs['bindinput'] = 'handleProxy'\n      } else {\n        attrs['bindchange'] = 'handleProxy'\n      }\n    }\n\n    return attrs\n  }\n}\n"
  },
  {
    "path": "src/platforms/mp/compiler/wx/convert/component.js",
    "content": "function getSlotsName (obj) {\n  if (!obj) {\n    return ''\n  }\n  // wxml模板中 data=\"{{ a:{a1:'string2'}, b:'string'}}\" 键a不能放在最后，会出错\n  return tmplateSlotsObj(obj)\n    .concat(\n      Object.keys(obj).map(function(k) {\n        return '$slot' + k + \":'\" + obj[k] + \"'\"\n      })\n    )\n    .join(',')\n}\n\nfunction tmplateSlotsObj(obj) {\n  if (!obj) {\n    return []\n  }\n  // wxml模板中 data=\"{{ a:{a1:'string2'}, b:'string'}}\" 键a1不能写成 'a1' 带引号的形式，会出错\n  const $for = Object.keys(obj)\n    .map(function(k) {\n      return `${k}:'${obj[k]}'`\n    })\n    .join(',')\n  return $for ? [`$for:{${$for}}`] : []\n}\n\nexport default {\n  isComponent (tagName, components = {}) {\n    return !!components[tagName]\n  },\n  convertComponent (ast, components, slotName) {\n    const { attrsMap, tag, mpcomid, slots } = ast\n    if (slotName) {\n      attrsMap['data'] = \"{{...$root[$p], ...$root[$k], $root}}\"\n      // bindedName is available when rendering slot in v-for\n      const bindedName = attrsMap['v-bind:name']\n      if(bindedName) {\n        attrsMap['is'] = \"{{$for[\" + bindedName + \"]}}\"\n      } else {\n        attrsMap['is'] = \"{{\" + slotName + \"}}\"\n      }\n    } else {\n      const slotsName = getSlotsName(slots)\n      const restSlotsName = slotsName ? `, ${slotsName}` : ''\n      attrsMap['data'] = `{{...$root[$kk+${mpcomid}], $root${restSlotsName}}}`\n      attrsMap['is'] = components[tag].name\n    }\n    return ast\n  }\n}\n"
  },
  {
    "path": "src/platforms/mp/compiler/wx/convert/for.js",
    "content": "import astMap from '../config/astMap'\n\nexport default function (ast) {\n  const { iterator1, for: forText, key, alias, attrsMap } = ast\n\n  if (forText) {\n    attrsMap[astMap['v-for']] = `{{${forText}}}`\n    if (iterator1) {\n      attrsMap[astMap['iterator1']] = iterator1\n    }\n    if (key) {\n      attrsMap[astMap['key']] = key\n    }\n    if (alias) {\n      attrsMap[astMap['alias']] = alias\n    }\n\n    delete attrsMap['v-for']\n  }\n\n  return ast\n}\n"
  },
  {
    "path": "src/platforms/mp/compiler/wx/convert/index.js",
    "content": "import attrs from './attrs'\nimport component from './component'\nimport convertFor from './for'\nimport getAstCommon from '../../common/convert/index'\n\nexport default function mpmlAst (compiled, options = {}, log) {\n  const conventRule = { attrs, component, convertFor }\n  return getAstCommon(compiled, options, log, conventRule)\n}\n"
  },
  {
    "path": "src/platforms/mp/compiler/wx/index.js",
    "content": "import getMpmlAst from './convert/index'\nimport compileToMPMLCommon from '../common/generate'\n\nexport default function compileToMPML (compiled, options = {}) {\n  return compileToMPMLCommon(compiled, options, getMpmlAst)\n}\n"
  },
  {
    "path": "src/platforms/mp/entry-compiler.js",
    "content": "/* @flow */\n\nexport { parseComponent } from 'sfc/parser'\nexport { compile, compileToFunctions, compileToMPML } from './compiler/index'\n"
  },
  {
    "path": "src/platforms/mp/entry-runtime.js",
    "content": "/* @flow */\n\nimport Vue from './runtime/index'\nimport { createMP } from './runtime/lifecycle'\n\nexport default {\n  Vue,\n  createMP\n}\n"
  },
  {
    "path": "src/platforms/mp/join-code-in-build.js",
    "content": "// used by `/build/config.js`\n\nexports.mpBanner = `// fix env\ntry {\n  if (!global) global = {};\n  global.process = global.process || {};\n  global.process.env = global.process.env || {};\n  global.App = global.App || App;\n  global.Page = global.Page || Page;\n  global.Component = global.Component || Component;\n  global.getApp = global.getApp || getApp;\n\n  if (typeof wx !== 'undefined') {\n    global.mpvue = wx;\n    global.mpvuePlatform = 'wx';\n  } else if (typeof swan !== 'undefined') {\n    global.mpvue = swan;\n    global.mpvuePlatform = 'swan';\n  }else if (typeof tt !== 'undefined') {\n    global.mpvue = tt;\n    global.mpvuePlatform = 'tt';\n  }else if (typeof my !== 'undefined') {\n    global.mpvue = my;\n    global.mpvuePlatform = 'my';\n  }\n} catch (e) {}\n`\n\n// hack fix mp LIFECYCLE_HOOKS, used by `/build/config.js`\nexports.mpLifecycleHooks = `'onLaunch',\n  'onLoad',\n  'onShow',\n  'onReady',\n  'onHide',\n  'onUnload',\n  'onPullDownRefresh',\n  'onReachBottom',\n  'onShareAppMessage',\n  'onPageScroll',\n  'onTabItemTap',\n  'attached',\n  'ready',\n  'moved',\n  'detached'`\n"
  },
  {
    "path": "src/platforms/mp/runtime/diff-data.js",
    "content": "import Vue from 'core/index'\nimport { diffLog } from './runtime-trace'\nimport { def } from 'core/util/index'\n\nconst KEY_SEP = '_'\n\nfunction getDeepData (keyList, viewData) {\n  if (keyList.length > 1) {\n    const _key = keyList.splice(0, 1)\n    const _viewData = viewData[_key]\n    if (_viewData) {\n      return getDeepData(keyList, _viewData)\n    } else {\n      return null\n    }\n  } else {\n    if (viewData[keyList[0]]) {\n      return viewData[keyList[0]]\n    } else {\n      return null\n    }\n  }\n}\n\nfunction deepDiff (oldData, newData, data, key) {\n  if (oldData === newData) {\n    return\n  }\n  // 新旧数据如果存在值为null则添加到需要更新的表中\n  if (oldData === null || newData === null) {\n    data[key] = newData\n    return\n  }\n  if (Object.prototype.toString.call(oldData) !== Object.prototype.toString.call(newData)) {\n    data[key] = newData\n    return\n  }\n  // 如果新旧数据均为数组，则进行diff\n  if (Array.isArray(newData) && Array.isArray(oldData)) {\n    if (newData.length === oldData.length) {\n      for (let i = 0, len = newData.length; i < len; i++) {\n        // 递归处理，处理数据中包含数据或者包含对象的情况\n        deepDiff(oldData[i], newData[i], data, key + '[' + i + ']')\n      }\n    } else {\n      // 数组长度不一样直接setData\n      data[key] = newData\n    }\n    return\n  }\n  // 如果新旧数据均为对象，进行diff\n  if (typeof oldData === 'object' && typeof newData === 'object') {\n    var newKeys = Object.keys(newData)\n    var oldKeys = Object.keys(oldData)\n    var uniqueKeys = new Set([...newKeys, ...oldKeys])\n    uniqueKeys.forEach(itemKey => {\n      if (oldData[itemKey] &&\n        newData[itemKey] &&\n        typeof newData[itemKey] === 'object' &&\n        Object.prototype.toString.call(oldData) === Object.prototype.toString.call(newData)\n      ) {\n        deepDiff(oldData[itemKey], newData[itemKey], data, key + '.' + itemKey)\n        return\n      }\n      if (oldData[itemKey] !== newData[itemKey]) {\n        data[key + '.' + itemKey] = newData[itemKey]\n      }\n    })\n    return\n  }\n  if (oldData !== newData) {\n    data[key] = newData\n  }\n}\n\nfunction compareAndSetDeepData (key, newData, vm, data) {\n  // 比较引用类型数据\n  try {\n    const keyList = key.split('.')\n    // page.__viewData__老版小程序不存在，使用mpvue里绑的data比对\n    const oldData = getDeepData(keyList, vm.$root.$mp.page.data)\n    if (!oldData) {\n      data[key] = newData\n      return\n    }\n    deepDiff(oldData, newData, data, key)\n  } catch (e) {\n    console.log(e, key, newData, vm)\n  }\n}\n\nfunction cleanKeyPath (vm) {\n  if (vm.__mpKeyPath) {\n    Object.keys(vm.__mpKeyPath).forEach((_key) => {\n      delete vm.__mpKeyPath[_key]['__keyPath']\n    })\n  }\n}\n\nfunction minifyDeepData (rootKey, originKey, vmData, data, _mpValueSet, vm) {\n  try {\n    if (vmData instanceof Array) {\n       // 数组\n      compareAndSetDeepData(rootKey + '.' + originKey, vmData, vm, data)\n    } else {\n      // Object\n      let __keyPathOnThis = {} // 存储这层对象的keyPath\n      if (vmData.__keyPath && !vmData.__newReference) {\n        // 有更新列表 ，按照更新列表更新\n        __keyPathOnThis = vmData.__keyPath\n        Object.keys(vmData).forEach((_key) => {\n          if (vmData[_key] instanceof Object) {\n            // 引用类型 递归\n            if (_key === '__keyPath') {\n              return\n            }\n            minifyDeepData(rootKey + '.' + originKey, _key, vmData[_key], data, null, vm)\n          } else {\n            // 更新列表中的 加入data\n            if (__keyPathOnThis[_key] === true) {\n              if (originKey) {\n                data[rootKey + '.' + originKey + '.' + _key] = vmData[_key]\n              } else {\n                data[rootKey + '.' + _key] = vmData[_key]\n              }\n            }\n          }\n        })\n         // 根节点可能有父子引用同一个引用类型数据，依赖树都遍历完后清理\n        vm['__mpKeyPath'] = vm['__mpKeyPath'] || {}\n        vm['__mpKeyPath'][vmData.__ob__.dep.id] = vmData\n      } else {\n        // 没有更新列表\n        compareAndSetDeepData(rootKey + '.' + originKey, vmData, vm, data)\n      }\n      // 标记是否是通过this.Obj = {} 赋值印发的改动，解决少更新问题#1305\n      def(vmData, '__newReference', false, false)\n    }\n  } catch (e) {\n    console.log(e, rootKey, originKey, vmData, data)\n  }\n}\n\nfunction getRootKey (vm, rootKey) {\n  if (!vm.$parent.$attrs) {\n    rootKey = '$root.0' + KEY_SEP + rootKey\n    return rootKey\n  } else {\n    rootKey = vm.$parent.$attrs.mpcomid + KEY_SEP + rootKey\n    return getRootKey(vm.$parent, rootKey)\n  }\n}\n\nexport function diffData (vm, data) {\n  const vmData = vm._data || {}\n  const vmProps = vm._props || {}\n  let rootKey = ''\n  if (!vm.$attrs) {\n    rootKey = '$root.0'\n  } else {\n    rootKey = getRootKey(vm, vm.$attrs.mpcomid)\n  }\n  Vue.nextTick(() => {\n    cleanKeyPath(vm)\n  })\n  // console.log(rootKey)\n\n  // 值类型变量不考虑优化，还是直接更新\n  const __keyPathOnThis = vmData.__keyPath || vm.__keyPath || {}\n  delete vm.__keyPath\n  delete vmData.__keyPath\n  delete vmProps.__keyPath\n  if (vm._mpValueSet === 'done') {\n    // 第二次赋值才进行缩减操作\n    Object.keys(vmData).forEach((vmDataItemKey) => {\n      if (vmData[vmDataItemKey] instanceof Object) {\n        // 引用类型\n        minifyDeepData(rootKey, vmDataItemKey, vmData[vmDataItemKey], data, vm._mpValueSet, vm)\n      } else if (vmData[vmDataItemKey] !== undefined) {\n        // _data上的值属性只有要更新的时候才赋值\n        if (__keyPathOnThis[vmDataItemKey] === true) {\n          data[rootKey + '.' + vmDataItemKey] = vmData[vmDataItemKey]\n        }\n      }\n    })\n\n    Object.keys(vmProps).forEach((vmPropsItemKey) => {\n      if (vmProps[vmPropsItemKey] instanceof Object) {\n        // 引用类型\n        minifyDeepData(rootKey, vmPropsItemKey, vmProps[vmPropsItemKey], data, vm._mpValueSet, vm)\n      } else if (vmProps[vmPropsItemKey] !== undefined) {\n        data[rootKey + '.' + vmPropsItemKey] = vmProps[vmPropsItemKey]\n      }\n      // _props上的值属性只有要更新的时候才赋值\n    })\n\n    // 检查完data和props,最后补上_mpProps & _computedWatchers\n    const vmMpProps = vm._mpProps || {}\n    const vmComputedWatchers = vm._computedWatchers || {}\n    Object.keys(vmMpProps).forEach((mpItemKey) => {\n      data[rootKey + '.' + mpItemKey] = vm[mpItemKey]\n    })\n    Object.keys(vmComputedWatchers).forEach((computedItemKey) => {\n      data[rootKey + '.' + computedItemKey] = vm[computedItemKey]\n    })\n    // 更新的时候要删除$root.0:{},否则会覆盖原正确数据\n    delete data[rootKey]\n  }\n  if (vm._mpValueSet === undefined) {\n    // 第一次设置数据成功后，标记位置true,再更新到这个节点如果没有keyPath数组认为不需要更新\n    vm._mpValueSet = 'done'\n  }\n  if (Vue.config._mpTrace) {\n    // console.log('更新VM节点', vm)\n    // console.log('实际传到Page.setData数据', data)\n    diffLog(data)\n  }\n}\n"
  },
  {
    "path": "src/platforms/mp/runtime/events.js",
    "content": "import { getComKey, eventTypeMap } from '../util/index'\nimport { noop } from 'shared/util'\n\n// 虚拟dom的compid与真实dom的comkey匹配，多层嵌套的先补齐虚拟dom的compid直到完全匹配为止\nfunction isVmKeyMatchedCompkey (k, comkey) {\n  if (!k || !comkey) {\n    return false\n  }\n  // 完全匹配 comkey = '1_0_1', k = '1_0_1'\n  // 部分匹配 comkey = '1_0_10_1', k = '1_0_10'\n  // k + KEY_SEP防止k = '1_0_1'误匹配comkey = '1_0_10_1'\n  return comkey === k || comkey.indexOf(k + KEY_SEP) === 0\n}\n\nfunction getVM (vm, comkeys = []) {\n  const keys = comkeys.slice(1)\n  if (!keys.length) return vm\n\n  // bugfix #1375: 虚拟dom的compid和真实dom的comkey在组件嵌套时匹配出错，comid会丢失前缀，需要从父节点补充\n  let comkey = keys.join(KEY_SEP)\n  let comidPrefix = ''\n  return keys.reduce((res, key) => {\n    const len = res.$children.length\n    for (let i = 0; i < len; i++) {\n      const v = res.$children[i]\n      let k = getComKey(v)\n      if (comidPrefix) {\n        k = comidPrefix + KEY_SEP + k\n      }\n      // 找到匹配的父节点\n      if (isVmKeyMatchedCompkey(k, comkey)) {\n        comidPrefix = k\n        res = v\n        return res\n      }\n    }\n    return res\n  }, vm)\n}\n\nfunction getHandle (vnode, eventid, eventTypes = []) {\n  let res = []\n  if (!vnode || !vnode.tag) {\n    return res\n  }\n\n  const { data = {}, children = [], componentInstance } = vnode || {}\n  if (componentInstance) {\n    // 增加 slot 情况的处理\n    // Object.values 会多增加几行编译后的代码\n    Object.keys(componentInstance.$slots).forEach(slotKey => {\n      const slot = componentInstance.$slots[slotKey]\n      const slots = Array.isArray(slot) ? slot : [slot]\n      slots.forEach(node => {\n        res = res.concat(getHandle(node, eventid, eventTypes))\n      })\n    })\n  } else {\n    // 避免遍历超出当前组件的 vm\n    children.forEach(node => {\n      res = res.concat(getHandle(node, eventid, eventTypes))\n    })\n  }\n\n  const { attrs, on } = data\n  if (attrs && on && attrs['eventid'] === eventid) {\n    eventTypes.forEach(et => {\n      const h = on[et]\n      if (typeof h === 'function') {\n        res.push(h)\n      } else if (Array.isArray(h)) {\n        res = res.concat(h)\n      }\n    })\n    return res\n  }\n\n  return res\n}\n\nfunction getWebEventByMP (e) {\n  const { type, timeStamp, touches, detail = {}, target = {}, currentTarget = {} } = e\n  const { x, y } = detail\n  const event = {\n    mp: e,\n    type,\n    timeStamp,\n    x,\n    y,\n    target: Object.assign({}, target, detail),\n    currentTarget,\n    stopPropagation: noop,\n    preventDefault: noop\n  }\n\n  if (touches && touches.length) {\n    Object.assign(event, touches[0])\n    event.touches = touches\n  }\n  return event\n}\n\nconst KEY_SEP = '_'\nexport function handleProxyWithVue (e) {\n  const rootVueVM = this.$root\n  const { type, target = {}, currentTarget } = e\n  const { dataset = {} } = currentTarget || target\n  const { comkey = '', eventid } = dataset\n  const vm = getVM(rootVueVM, comkey.split(KEY_SEP))\n\n  if (!vm) {\n    return\n  }\n\n  const webEventTypes = eventTypeMap[type] || [type]\n  const handles = getHandle(vm._vnode, eventid, webEventTypes)\n\n  // TODO, enevt 还需要处理更多\n  // https://developer.mozilla.org/zh-CN/docs/Web/API/Event\n  if (handles.length) {\n    const event = getWebEventByMP(e)\n    if (handles.length === 1) {\n      const result = handles[0](event)\n      return result\n    }\n    handles.forEach(h => h(event))\n  }\n}\n"
  },
  {
    "path": "src/platforms/mp/runtime/index.js",
    "content": "import Vue from 'core/index'\n\n// for platforms\n// import config from 'core/config'\nimport { mountComponent } from 'core/instance/lifecycle'\n\nimport {\n  mustUseProp,\n  isReservedTag,\n  isReservedAttr,\n  getTagNamespace,\n  isUnknownElement\n} from 'mp/util/index'\nimport { patch } from './patch'\n\n// install platform specific utils\nVue.config.mustUseProp = mustUseProp\nVue.config.isReservedTag = isReservedTag\nVue.config.isReservedAttr = isReservedAttr\nVue.config.getTagNamespace = getTagNamespace\nVue.config.isUnknownElement = isUnknownElement\n\n// install platform patch function\nVue.prototype.__patch__ = patch\n\n// public mount method\nVue.prototype.$mount = function (el, hydrating) {\n  // el = el && inBrowser ? query(el) : undefined\n  // return mountComponent(this, el, hydrating)\n\n  // 初始化小程序生命周期相关\n  const options = this.$options\n\n  if (options && (options.render || options.mpType)) {\n    const { mpType = 'page' } = options\n    return this._initMP(mpType, () => {\n      return mountComponent(this, undefined, undefined)\n    })\n  } else {\n    return mountComponent(this, undefined, undefined)\n  }\n}\n\n// for mp\nimport { initMP } from './lifecycle'\nVue.prototype._initMP = initMP\n\nimport { updateDataToMP, initDataToMP } from './render'\nVue.prototype.$updateDataToMP = updateDataToMP\nVue.prototype._initDataToMP = initDataToMP\n\nimport { handleProxyWithVue } from './events'\nVue.prototype.$handleProxyWithVue = handleProxyWithVue\n\nexport default Vue\n"
  },
  {
    "path": "src/platforms/mp/runtime/lifecycle.js",
    "content": "import { handleError } from 'core/util/index'\nimport { observe } from 'core/observer/index'\nimport { proxy } from 'core/instance/state'\nimport { mountComponent } from 'core/instance/lifecycle'\n\nfunction _next (rootVueVM) {\n  return mountComponent(rootVueVM, undefined, undefined)\n}\n\nimport {\n  camelize,\n  isPlainObject\n} from 'shared/util'\nimport { warn } from 'core/util/debug'\n\nexport function callHook (vm, hook, params) {\n  let handlers = vm.$options[hook]\n  if (hook === 'onError' && handlers) {\n    handlers = [handlers]\n  } else if (hook === 'onPageNotFound' && handlers) {\n    handlers = [handlers]\n  }\n\n  let ret\n  if (handlers) {\n    for (let i = 0, j = handlers.length; i < j; i++) {\n      try {\n        ret = handlers[i].call(vm, params)\n      } catch (e) {\n        handleError(e, vm, `${hook} hook`)\n      }\n    }\n  }\n  if (vm._hasHookEvent) {\n    vm.$emit('hook:' + hook)\n  }\n\n  // for child\n  if (vm.$children.length) {\n    vm.$children.forEach(v => callHook(v, hook, params))\n  }\n\n  return ret\n}\n\n// mpType 小程序实例的类型，可能的值是 'app', 'page'\n// rootVueVM 是 vue 的根组件实例，子组件中访问 this.$root 可得\nfunction getGlobalData (app, rootVueVM) {\n  const mp = rootVueVM.$mp\n  if (app && app.globalData) {\n    mp.appOptions = app.globalData.appOptions\n  }\n}\n\n// 格式化 properties 属性，并给每个属性加上 observer 方法\n\n// properties 的 一些类型 https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/component.html\n// properties: {\n//   paramA: Number,\n//   myProperty: { // 属性名\n//     type: String, // 类型（必填），目前接受的类型包括：String, Number, Boolean, Object, Array, null（表示任意类型）\n//     value: '', // 属性初始值（可选），如果未指定则会根据类型选择一个\n//     observer: function(newVal, oldVal, changedPath) {\n//        // 属性被改变时执行的函数（可选），也可以写成在methods段中定义的方法名字符串, 如：'_propertyChange'\n//        // 通常 newVal 就是新设置的数据， oldVal 是旧数据\n//     }\n//   },\n// }\n\n// props 的一些类型 https://cn.vuejs.org/v2/guide/components-props.html#ad\n// props: {\n//   // 基础的类型检查 (`null` 匹配任何类型)\n//   propA: Number,\n//   // 多个可能的类型\n//   propB: [String, Number],\n//   // 必填的字符串\n//   propC: {\n//     type: String,\n//     required: true\n//   },\n//   // 带有默认值的数字\n//   propD: {\n//     type: Number,\n//     default: 100\n//   },\n//   // 带有默认值的对象\n//   propE: {\n//     type: Object,\n//     // 对象或数组且一定会从一个工厂函数返回默认值\n//     default: function () {\n//       return { message: 'hello' }\n//     }\n//   },\n//   // 自定义验证函数\n//   propF: {\n//     validator: function (value) {\n//       // 这个值必须匹配下列字符串中的一个\n//       return ['success', 'warning', 'danger'].indexOf(value) !== -1\n//     }\n//   }\n// }\n\n// core/util/options\nfunction normalizeProps (props, res, vm) {\n  if (!props) return\n  let i, val, name\n  if (Array.isArray(props)) {\n    i = props.length\n    while (i--) {\n      val = props[i]\n      if (typeof val === 'string') {\n        name = camelize(val)\n        res[name] = { type: null }\n      } else if (process.env.NODE_ENV !== 'production') {\n        warn('props must be strings when using array syntax.')\n      }\n    }\n  } else if (isPlainObject(props)) {\n    for (const key in props) {\n      val = props[key]\n      name = camelize(key)\n      res[name] = isPlainObject(val)\n        ? val\n        : { type: val }\n    }\n  }\n\n  // fix vueProps to properties\n  for (const key in res) {\n    if (res.hasOwnProperty(key)) {\n      const item = res[key]\n      if (item.default) {\n        item.value = item.default\n      }\n      const oldObserver = item.observer\n      item.observer = function (newVal, oldVal) {\n        vm[name] = newVal\n        // 先修改值再触发原始的 observer，跟 watch 行为保持一致\n        if (typeof oldObserver === 'function') {\n          oldObserver.call(vm, newVal, oldVal)\n        }\n      }\n    }\n  }\n\n  return res\n}\n\nfunction normalizeProperties (vm) {\n  const properties = vm.$options.properties\n  const vueProps = vm.$options.props\n  const res = {}\n\n  normalizeProps(properties, res, vm)\n  normalizeProps(vueProps, res, vm)\n\n  return res\n}\n\n/**\n * 把 properties 中的属性 proxy 到 vm 上\n */\nfunction initMpProps (vm) {\n  const mpProps = vm._mpProps = {}\n  const keys = Object.keys(vm.$options.properties || {})\n  keys.forEach(key => {\n    if (!(key in vm)) {\n      proxy(vm, '_mpProps', key)\n      mpProps[key] = undefined // for observe\n    }\n  })\n  observe(mpProps, true)\n}\n\nexport function initMP (mpType, next) {\n  const rootVueVM = this.$root\n  if (!rootVueVM.$mp) {\n    rootVueVM.$mp = {}\n  }\n\n  const mp = rootVueVM.$mp\n\n  // Please do not register multiple Pages\n  // if (mp.registered) {\n  if (mp.status) {\n    if (mpType === 'app') {\n      callHook(this, 'onLaunch', mp.appOptions)\n    } else {\n      callHook(this, 'onLoad', mp.query)\n      callHook(this, 'onReady')\n    }\n    return next()\n  }\n  // mp.registered = true\n\n  mp.mpType = mpType\n  mp.status = 'register'\n}\n\nexport function createMP ({ mpType, init }) {\n  if (!mpType) mpType = 'page'\n  if (mpType === 'app') {\n    global.App({\n      // 页面的初始数据\n      globalData: {\n        appOptions: {}\n      },\n\n      handleProxy (e) {\n        return this.rootVueVM.$handleProxyWithVue(e)\n      },\n\n      // Do something initial when launch.\n      onLaunch (options = {}) {\n        if (!this.rootVueVM) {\n          this.rootVueVM = init()\n          this.rootVueVM.$mp = {}\n        }\n        const mp = this.rootVueVM.$mp\n        mp.mpType = 'app'\n        mp.app = this\n        mp.status = 'launch'\n        this.globalData.appOptions = mp.appOptions = options\n        this.rootVueVM.$mount()\n      },\n\n      // Do something when app show.\n      onShow (options = {}) {\n        // 百度小程序onLaunch与onShow存在bug\n        // 如果this.rootVueVM不存在则初始化\n        if (!this.rootVueVM) {\n          this.rootVueVM = init()\n          this.rootVueVM.$mp = {}\n        }\n        const mp = this.rootVueVM.$mp\n        mp.status = 'show'\n        this.globalData.appOptions = mp.appOptions = options\n        callHook(this.rootVueVM, 'onShow', options)\n      },\n\n      // Do something when app hide.\n      onHide () {\n        const mp = this.rootVueVM.$mp\n        mp.status = 'hide'\n        callHook(this.rootVueVM, 'onHide')\n      },\n\n      onError (err) {\n        callHook(this.rootVueVM, 'onError', err)\n      },\n\n      onPageNotFound (err) {\n        callHook(this.rootVueVM, 'onPageNotFound', err)\n      }\n    })\n  }\n  if (mpType === 'page') {\n    const app = global.getApp()\n    global.Page({\n      // 页面的初始数据\n      data: {\n        $root: {}\n      },\n\n      handleProxy (e) {\n        return this.rootVueVM.$handleProxyWithVue(e)\n      },\n\n      // mp lifecycle for vue\n      // 生命周期函数--监听页面加载\n      onLoad (query) {\n        this.rootVueVM = init()\n        const mp = this.rootVueVM.$mp = {}\n        mp.mpType = 'page'\n        mp.page = this\n        mp.query = query\n        mp.status = 'load'\n        getGlobalData(app, this.rootVueVM)\n        this.rootVueVM.$mount()\n      },\n\n      // 生命周期函数--监听页面显示\n      onShow () {\n        const mp = this.rootVueVM.$mp\n        mp.page = this\n        mp.status = 'show'\n        callHook(this.rootVueVM, 'onShow')\n        // 只有页面需要 setData\n        this.rootVueVM.$nextTick(() => {\n          this.rootVueVM._initDataToMP()\n        })\n      },\n\n      // 生命周期函数--监听页面初次渲染完成\n      onReady () {\n        const mp = this.rootVueVM.$mp\n        mp.status = 'ready'\n        return _next(this.rootVueVM)\n      },\n\n      // 生命周期函数--监听页面隐藏\n      onHide () {\n        const mp = this.rootVueVM.$mp\n        mp.status = 'hide'\n        callHook(this.rootVueVM, 'onHide')\n        mp.page = null\n      },\n\n      // 生命周期函数--监听页面卸载\n      onUnload () {\n        const mp = this.rootVueVM.$mp\n        mp.status = 'unload'\n        callHook(this.rootVueVM, 'onUnload')\n        mp.page = null\n      },\n\n      // 页面相关事件处理函数--监听用户下拉动作\n      onPullDownRefresh () {\n        callHook(this.rootVueVM, 'onPullDownRefresh')\n      },\n\n      // 页面上拉触底事件的处理函数\n      onReachBottom () {\n        callHook(this.rootVueVM, 'onReachBottom')\n      },\n\n      // 用户点击右上角分享\n      onShareAppMessage (options) {\n        if (this.rootVueVM.$options.onShareAppMessage) {\n          callHook(this.rootVueVM, 'onShareAppMessage', options)\n        }\n      },\n\n      // Do something when page scroll\n      onPageScroll (options) {\n        callHook(this.rootVueVM, 'onPageScroll', options)\n      },\n\n      // 当前是 tab 页时，点击 tab 时触发\n      onTabItemTap (options) {\n        callHook(this.rootVueVM, 'onTabItemTap', options)\n      }\n    })\n  }\n  if (mpType === 'component') {\n    global.Component({\n      // 小程序原生的组件属性\n      properties: {},\n      // 页面的初始数据\n      data: {\n        $root: {}\n      },\n      methods: {\n        handleProxy (e) {\n          return this.rootVueVM.$handleProxyWithVue(e)\n        }\n      },\n      // mp lifecycle for vue\n      // 组件生命周期函数，在组件实例进入页面节点树时执行，注意此时不能调用 setData\n      created () {\n        this.rootVueVM = init()\n        initMpProps(this.rootVueVM)\n        this.properties = normalizeProperties(this.rootVueVM)\n        const mp = this.rootVueVM.$mp = {}\n        mp.mpType = 'component'\n        mp.status = 'created'\n        mp.page = this\n        this.rootVueVM.$mount()\n        callHook(this.rootVueVM, 'created')\n      },\n      // 组件生命周期函数，在组件实例进入页面节点树时执行\n      attached () {\n        const mp = this.rootVueVM.$mp\n        mp.status = 'attached'\n        callHook(this.rootVueVM, 'attached')\n      },\n      // 组件生命周期函数，在组件布局完成后执行，此时可以获取节点信息（使用 SelectorQuery ）\n      ready () {\n        const mp = this.rootVueVM.$mp\n        mp.status = 'ready'\n        callHook(this.rootVueVM, 'ready')\n        _next(this.rootVueVM)\n\n        // 只有页面需要 setData\n        this.rootVueVM.$nextTick(() => {\n          this.rootVueVM._initDataToMP()\n        })\n      },\n      // 组件生命周期函数，在组件实例被移动到节点树另一个位置时执行\n      moved () {\n        callHook(this.rootVueVM, 'moved')\n      },\n      // 组件生命周期函数，在组件实例被从页面节点树移除时执行\n      detached () {\n        const mp = this.rootVueVM.$mp\n        mp.status = 'detached'\n        callHook(this.rootVueVM, 'detached')\n      }\n    })\n  }\n}\n"
  },
  {
    "path": "src/platforms/mp/runtime/node-ops.js",
    "content": "/* @flow */\n\n// import { namespaceMap } from 'mp/util/index'\n\nconst obj = {}\n\nexport function createElement (tagName: string, vnode: VNode) {\n  return obj\n}\n\nexport function createElementNS (namespace: string, tagName: string) {\n  return obj\n}\n\nexport function createTextNode (text: string) {\n  return obj\n}\n\nexport function createComment (text: string) {\n  return obj\n}\n\nexport function insertBefore (parentNode: Node, newNode: Node, referenceNode: Node) {}\n\nexport function removeChild (node: Node, child: Node) {}\n\nexport function appendChild (node: Node, child: Node) {}\n\nexport function parentNode (node: Node) {\n  return obj\n}\n\nexport function nextSibling (node: Node) {\n  return obj\n}\n\nexport function tagName (node: Element): string {\n  return 'div'\n}\n\nexport function setTextContent (node: Node, text: string) {\n  return obj\n}\n\nexport function setAttribute (node: Element, key: string, val: string) {\n  return obj\n}\n"
  },
  {
    "path": "src/platforms/mp/runtime/patch.js",
    "content": "/* @flow */\n\nimport * as nodeOps from './node-ops'\nimport { createPatchFunction } from 'core/vdom/patch'\n// import baseModules from 'core/vdom/modules/index'\nimport ref from 'core/vdom/modules/ref'\n// const platformModules = []\n// import platformModules from 'web/runtime/modules/index'\n\n// the directive module should be applied last, after all\n// built-in modules have been applied.\n// const modules = platformModules.concat(baseModules)\nconst modules = [ref]\n\nexport const corePatch: Function = createPatchFunction({ nodeOps, modules })\n\nexport function patch () {\n  corePatch.apply(this, arguments)\n  this.$updateDataToMP()\n}\n"
  },
  {
    "path": "src/platforms/mp/runtime/render.js",
    "content": "// 节流方法，性能优化\nimport { getComKey, cloneDeep } from '../util/index'\nimport { diffData } from './diff-data'\n\n// 全局的命名约定，为了节省编译的包大小一律采取形象的缩写，说明如下。\n// $c === $child\n// $k === $comKey\n\n// 新型的被拍平的数据结构\n// {\n//   $root: {\n//     '1-1'{\n//       // ... data\n//     },\n//     '1.2-1': {\n//       // ... data1\n//     },\n//     '1.2-2': {\n//       // ... data2\n//     }\n//   }\n// }\n\nconst KEY_SEP = '_'\n\nfunction getVmData (vm) {\n  // 确保当前 vm 所有数据被同步\n  const dataKeys = [].concat(\n    Object.keys(vm._data || {}),\n    Object.keys(vm._props || {}),\n    Object.keys(vm._mpProps || {}),\n    Object.keys(vm._computedWatchers || {})\n  )\n  return dataKeys.reduce((res, key) => {\n    res[key] = cloneDeep(vm[key])\n    return res\n  }, {})\n}\n\nfunction getParentComKey (vm, res = []) {\n  const { $parent } = vm || {}\n  if (!$parent) return res\n  res.unshift(getComKey($parent))\n  if ($parent.$parent) {\n    return getParentComKey($parent, res)\n  }\n  return res\n}\n\nfunction formatVmData (vm) {\n  const $p = getParentComKey(vm).join(KEY_SEP)\n  const $k = $p + ($p ? KEY_SEP : '') + getComKey(vm)\n\n  // getVmData 这儿获取当前组件内的所有数据，包含 props、computed 的数据\n  // 改动 vue.runtime 所获的的核心能力\n  const data = Object.assign(getVmData(vm), { $k, $kk: `${$k}${KEY_SEP}`, $p })\n  const key = '$root.' + $k\n  const res = { [key]: data }\n  return res\n}\n\nfunction collectVmData (vm, res = {}) {\n  const { $children: vms } = vm\n  if (vms && vms.length) {\n    vms.forEach(v => collectVmData(v, res))\n  }\n  return Object.assign(res, formatVmData(vm))\n}\n\n/**\n * 频率控制 返回函数连续调用时，func 执行频率限定为 次 / wait\n * 自动合并 data\n *\n * @param  {function}   func      传入函数\n * @param  {number}     wait      表示时间窗口的间隔\n * @param  {object}     options   如果想忽略开始边界上的调用，传入{leading: false}。\n *                                如果想忽略结尾边界上的调用，传入{trailing: false}\n * @return {function}             返回客户调用函数\n */\nfunction throttle (func, wait, options) {\n  let context, args, result\n  let timeout = null\n  // 上次执行时间点\n  let previous = 0\n  if (!options) options = {}\n  // 延迟执行函数\n  function later () {\n    // 若设定了开始边界不执行选项，上次执行时间始终为0\n    previous = options.leading === false ? 0 : Date.now()\n    timeout = null\n    result = func.apply(context, args)\n    if (!timeout) context = args = null\n  }\n  return function (handle, data) {\n    const now = Date.now()\n    // 首次执行时，如果设定了开始边界不执行选项，将上次执行时间设定为当前时间。\n    if (!previous && options.leading === false) previous = now\n    // 延迟执行时间间隔\n    const remaining = wait - (now - previous)\n    context = this\n    args = args ? [handle, Object.assign(args[1], data)] : [handle, data]\n    // 延迟时间间隔remaining小于等于0，表示上次执行至此所间隔时间已经超过一个时间窗口\n    // remaining大于时间窗口wait，表示客户端系统时间被调整过\n    if (remaining <= 0 || remaining > wait) {\n      clearTimeout(timeout)\n      timeout = null\n      previous = now\n      result = func.apply(context, args)\n      if (!timeout) context = args = null\n    // 如果延迟执行不存在，且没有设定结尾边界不执行选项\n    } else if (!timeout && options.trailing !== false) {\n      timeout = setTimeout(later, remaining)\n    }\n    return result\n  }\n}\n\n// 优化频繁的 setData: https://mp.weixin.qq.com/debug/wxadoc/dev/framework/performance/tips.html\nconst throttleSetData = throttle((handle, data) => {\n  if (!Object.keys(data).length) {\n    return\n  }\n  handle(data)\n}, 50)\n\nfunction getPage (vm) {\n  const rootVueVM = vm.$root\n  const { mpType = '', page } = rootVueVM.$mp || {}\n\n  // 优化后台态页面进行 setData: https://mp.weixin.qq.com/debug/wxadoc/dev/framework/performance/tips.html\n  if (mpType === 'app' || !page || typeof page.setData !== 'function') {\n    return\n  }\n  return page\n}\n\n// 优化js变量动态变化时候引起全量更新\n// 优化每次 setData 都传递大量新数据\nexport function updateDataToMP () {\n  const page = getPage(this)\n  if (!page) {\n    return\n  }\n\n  const data = {}\n  diffData(this, data)\n  throttleSetData(page.setData.bind(page), data)\n}\n\nexport function initDataToMP () {\n  const page = getPage(this)\n  if (!page) {\n    return\n  }\n\n  const data = collectVmData(this.$root)\n  page.setData(data)\n}\n"
  },
  {
    "path": "src/platforms/mp/runtime/runtime-trace.js",
    "content": "import Vue from 'core/index'\nvar updateDataTotal = 0 // 总共更新的数据量\nexport function diffLog (updateData) {\n  updateData = JSON.stringify(updateData)\n  if (!Vue._mpvueTraceTimer) {\n    Vue._mpvueTraceTimer = setTimeout(function () {\n      clearTimeout(Vue._mpvueTraceTimer)\n      updateDataTotal = (updateDataTotal / 1024).toFixed(1)\n      console.log('这次操作引发500ms内数据更新量:' + updateDataTotal + 'kb')\n      Vue._mpvueTraceTimer = 0\n      updateDataTotal = 0\n    }, 500)\n  } else if (Vue._mpvueTraceTimer) {\n    updateData = updateData.replace(/[^\\u0000-\\u00ff]/g, 'aa') // 中文占2字节，中文替换成两个字母计算占用空间\n    updateDataTotal += updateData.length\n  }\n}\n"
  },
  {
    "path": "src/platforms/mp/util/index.js",
    "content": "/* globals renderer */\n\nimport { makeMap } from 'shared/util'\n\nexport const isPreTag = (tag) => tag === 'pre'\n\nexport const isReservedTag = makeMap(\n  'template,script,style,element,content,slot,link,meta,svg,view,' +\n  'a,div,img,image,text,span,richtext,input,switch,textarea,spinner,select,' +\n  'slider,slider-neighbor,indicator,trisition,trisition-group,canvas,' +\n  'list,cell,header,loading,loading-indicator,refresh,scrollable,scroller,' +\n  'video,web,embed,tabbar,tabheader,datepicker,timepicker,marquee,countdown',\n  true\n)\n\n// these are reserved for web because they are directly compiled away\n// during template compilation\nexport const isReservedAttr = makeMap('style,class')\n\n// Elements that you can, intentionally, leave open (and which close themselves)\n// more flexable than web\nexport const canBeLeftOpenTag = makeMap(\n  'web,spinner,switch,video,textarea,canvas,' +\n  'indicator,marquee,countdown',\n  true\n)\n\nexport const isUnaryTag = makeMap(\n  'embed,img,image,input,link,meta',\n  true\n)\n\nexport function mustUseProp () { /* console.log('mustUseProp') */ }\nexport function getTagNamespace () { /* console.log('getTagNamespace') */ }\nexport function isUnknownElement () { /* console.log('isUnknownElement') */ }\n\nexport function query (el, document) {\n  // renderer is injected by weex factory wrapper\n  const placeholder = new renderer.Comment('root')\n  placeholder.hasAttribute = placeholder.removeAttribute = function () {} // hack for patch\n  document.documentElement.appendChild(placeholder)\n  return placeholder\n}\n\nexport function getComKey (vm) {\n  return vm && vm.$attrs ? vm.$attrs['mpcomid'] : '0'\n}\n\n// 用于小程序的 event type 到 web 的 event\nexport const eventTypeMap = {\n  tap: ['tap', 'click'],\n  touchstart: ['touchstart'],\n  touchmove: ['touchmove'],\n  touchcancel: ['touchcancel'],\n  touchend: ['touchend'],\n  longtap: ['longtap'],\n  input: ['input'],\n  blur: ['change', 'blur'],\n  submit: ['submit'],\n  focus: ['focus'],\n  scrolltoupper: ['scrolltoupper'],\n  scrolltolower: ['scrolltolower'],\n  scroll: ['scroll']\n}\n\n// vm上的数据深拷贝，小程序里不支持eval函数，暂不支持函数拷贝\nfunction isObject (obj) {\n  return (typeof obj === 'object') && obj !== null\n}\n\nexport function cloneDeep (data, hash = new WeakMap()) {\n  if (!isObject(data) || !data || !data.constructor) {\n    return data\n  }\n  let copyData\n  const Constructor = data.constructor\n  // 实际情况中，正则表达式会被以{}存储，Date对象会以时间字符串形式存储\n  // 函数则变为null\n  switch (Constructor) {\n    case RegExp:\n      copyData = new Constructor(data)\n      break\n    case Date:\n      copyData = new Constructor(data.getTime())\n      break\n    default:\n      // 循环引用问题解决\n      if (hash.has(data)) {\n        return hash.get(data)\n      }\n      copyData = new Constructor()\n      if (Constructor === Map) {\n        data.forEach((value, key) => {\n          copyData.set(key, isObject(value) ? cloneDeep(value) : value)\n        })\n      }\n      if (Constructor === Set) {\n        data.forEach(value => {\n          copyData.add(isObject(value) ? cloneDeep(value) : value)\n        })\n      }\n      hash.set(data, copyData)\n  }\n  const symbols = Object.getOwnPropertySymbols(data)\n  if (symbols && symbols.length) {\n    symbols.forEach(symkey => {\n      copyData[symkey] = isObject(data[symkey]) ? cloneDeep(data[symkey], hash) : data[symkey]\n    })\n  }\n  for (var key in data) {\n    copyData[key] = isObject(data[key]) ? cloneDeep(data[key], hash) : data[key]\n  }\n  return copyData\n}\n"
  },
  {
    "path": "src/platforms/web/compiler/directives/html.js",
    "content": "/* @flow */\n\nimport { addProp } from 'compiler/helpers'\n\nexport default function html (el: ASTElement, dir: ASTDirective) {\n  if (dir.value) {\n    addProp(el, 'innerHTML', `_s(${dir.value})`)\n  }\n}\n"
  },
  {
    "path": "src/platforms/web/compiler/directives/index.js",
    "content": "import model from './model'\nimport text from './text'\nimport html from './html'\n\nexport default {\n  model,\n  text,\n  html\n}\n"
  },
  {
    "path": "src/platforms/web/compiler/directives/model.js",
    "content": "/* @flow */\n\nimport config from 'core/config'\nimport { addHandler, addProp, getBindingAttr } from 'compiler/helpers'\nimport { genComponentModel, genAssignmentCode } from 'compiler/directives/model'\n\nlet warn\n\n// in some cases, the event used has to be determined at runtime\n// so we used some reserved tokens during compile.\nexport const RANGE_TOKEN = '__r'\nexport const CHECKBOX_RADIO_TOKEN = '__c'\n\nexport default function model (\n  el: ASTElement,\n  dir: ASTDirective,\n  _warn: Function\n): ?boolean {\n  warn = _warn\n  const value = dir.value\n  const modifiers = dir.modifiers\n  const tag = el.tag\n  const type = el.attrsMap.type\n\n  if (process.env.NODE_ENV !== 'production') {\n    const dynamicType = el.attrsMap['v-bind:type'] || el.attrsMap[':type']\n    if (tag === 'input' && dynamicType) {\n      warn(\n        `<input :type=\"${dynamicType}\" v-model=\"${value}\">:\\n` +\n        `v-model does not support dynamic input types. Use v-if branches instead.`\n      )\n    }\n    // inputs with type=\"file\" are read only and setting the input's\n    // value will throw an error.\n    if (tag === 'input' && type === 'file') {\n      warn(\n        `<${el.tag} v-model=\"${value}\" type=\"file\">:\\n` +\n        `File inputs are read only. Use a v-on:change listener instead.`\n      )\n    }\n  }\n\n  if (el.component) {\n    genComponentModel(el, value, modifiers)\n    // component v-model doesn't need extra runtime\n    return false\n  } else if (tag === 'select') {\n    genSelect(el, value, modifiers)\n  } else if (tag === 'input' && type === 'checkbox') {\n    genCheckboxModel(el, value, modifiers)\n  } else if (tag === 'input' && type === 'radio') {\n    genRadioModel(el, value, modifiers)\n  } else if (tag === 'input' || tag === 'textarea') {\n    genDefaultModel(el, value, modifiers)\n  } else if (!config.isReservedTag(tag)) {\n    genComponentModel(el, value, modifiers)\n    // component v-model doesn't need extra runtime\n    return false\n  } else if (process.env.NODE_ENV !== 'production') {\n    warn(\n      `<${el.tag} v-model=\"${value}\">: ` +\n      `v-model is not supported on this element type. ` +\n      'If you are working with contenteditable, it\\'s recommended to ' +\n      'wrap a library dedicated for that purpose inside a custom component.'\n    )\n  }\n\n  // ensure runtime directive metadata\n  return true\n}\n\nfunction genCheckboxModel (\n  el: ASTElement,\n  value: string,\n  modifiers: ?ASTModifiers\n) {\n  const number = modifiers && modifiers.number\n  const valueBinding = getBindingAttr(el, 'value') || 'null'\n  const trueValueBinding = getBindingAttr(el, 'true-value') || 'true'\n  const falseValueBinding = getBindingAttr(el, 'false-value') || 'false'\n  addProp(el, 'checked',\n    `Array.isArray(${value})` +\n      `?_i(${value},${valueBinding})>-1` + (\n        trueValueBinding === 'true'\n          ? `:(${value})`\n          : `:_q(${value},${trueValueBinding})`\n      )\n  )\n  addHandler(el, CHECKBOX_RADIO_TOKEN,\n    `var $$a=${value},` +\n        '$$el=$event.target,' +\n        `$$c=$$el.checked?(${trueValueBinding}):(${falseValueBinding});` +\n    'if(Array.isArray($$a)){' +\n      `var $$v=${number ? '_n(' + valueBinding + ')' : valueBinding},` +\n          '$$i=_i($$a,$$v);' +\n      `if($$c){$$i<0&&(${value}=$$a.concat($$v))}` +\n      `else{$$i>-1&&(${value}=$$a.slice(0,$$i).concat($$a.slice($$i+1)))}` +\n    `}else{${genAssignmentCode(value, '$$c')}}`,\n    null, true\n  )\n}\n\nfunction genRadioModel (\n    el: ASTElement,\n    value: string,\n    modifiers: ?ASTModifiers\n) {\n  const number = modifiers && modifiers.number\n  let valueBinding = getBindingAttr(el, 'value') || 'null'\n  valueBinding = number ? `_n(${valueBinding})` : valueBinding\n  addProp(el, 'checked', `_q(${value},${valueBinding})`)\n  addHandler(el, CHECKBOX_RADIO_TOKEN, genAssignmentCode(value, valueBinding), null, true)\n}\n\nfunction genSelect (\n    el: ASTElement,\n    value: string,\n    modifiers: ?ASTModifiers\n) {\n  const number = modifiers && modifiers.number\n  const selectedVal = `Array.prototype.filter` +\n    `.call($event.target.options,function(o){return o.selected})` +\n    `.map(function(o){var val = \"_value\" in o ? o._value : o.value;` +\n    `return ${number ? '_n(val)' : 'val'}})`\n\n  const assignment = '$event.target.multiple ? $$selectedVal : $$selectedVal[0]'\n  let code = `var $$selectedVal = ${selectedVal};`\n  code = `${code} ${genAssignmentCode(value, assignment)}`\n  addHandler(el, 'change', code, null, true)\n}\n\nfunction genDefaultModel (\n  el: ASTElement,\n  value: string,\n  modifiers: ?ASTModifiers\n): ?boolean {\n  const type = el.attrsMap.type\n  const { lazy, number, trim } = modifiers || {}\n  const needCompositionGuard = !lazy && type !== 'range'\n  const event = lazy\n    ? 'change'\n    : type === 'range'\n      ? RANGE_TOKEN\n      : 'input'\n\n  let valueExpression = '$event.target.value'\n  if (trim) {\n    valueExpression = `$event.target.value.trim()`\n  }\n  if (number) {\n    valueExpression = `_n(${valueExpression})`\n  }\n\n  let code = genAssignmentCode(value, valueExpression)\n  if (needCompositionGuard) {\n    code = `if($event.target.composing)return;${code}`\n  }\n\n  addProp(el, 'value', `(${value})`)\n  addHandler(el, event, code, null, true)\n  if (trim || number) {\n    addHandler(el, 'blur', '$forceUpdate()')\n  }\n}\n"
  },
  {
    "path": "src/platforms/web/compiler/directives/text.js",
    "content": "/* @flow */\n\nimport { addProp } from 'compiler/helpers'\n\nexport default function text (el: ASTElement, dir: ASTDirective) {\n  if (dir.value) {\n    addProp(el, 'textContent', `_s(${dir.value})`)\n  }\n}\n"
  },
  {
    "path": "src/platforms/web/compiler/index.js",
    "content": "/* @flow */\n\nimport { baseOptions } from './options'\nimport { createCompiler } from 'compiler/index'\n\nconst { compile, compileToFunctions } = createCompiler(baseOptions)\n\nexport { compile, compileToFunctions }\n"
  },
  {
    "path": "src/platforms/web/compiler/modules/class.js",
    "content": "/* @flow */\n\nimport { parseText } from 'compiler/parser/text-parser'\nimport {\n  getAndRemoveAttr,\n  getBindingAttr,\n  baseWarn\n} from 'compiler/helpers'\n\nfunction transformNode (el: ASTElement, options: CompilerOptions) {\n  const warn = options.warn || baseWarn\n  const staticClass = getAndRemoveAttr(el, 'class')\n  if (process.env.NODE_ENV !== 'production' && staticClass) {\n    const expression = parseText(staticClass, options.delimiters)\n    if (expression) {\n      warn(\n        `class=\"${staticClass}\": ` +\n        'Interpolation inside attributes has been removed. ' +\n        'Use v-bind or the colon shorthand instead. For example, ' +\n        'instead of <div class=\"{{ val }}\">, use <div :class=\"val\">.'\n      )\n    }\n  }\n  if (staticClass) {\n    el.staticClass = JSON.stringify(staticClass)\n  }\n  const classBinding = getBindingAttr(el, 'class', false /* getStatic */)\n  if (classBinding) {\n    el.classBinding = classBinding\n  }\n}\n\nfunction genData (el: ASTElement): string {\n  let data = ''\n  if (el.staticClass) {\n    data += `staticClass:${el.staticClass},`\n  }\n  if (el.classBinding) {\n    data += `class:${el.classBinding},`\n  }\n  return data\n}\n\nexport default {\n  staticKeys: ['staticClass'],\n  transformNode,\n  genData\n}\n"
  },
  {
    "path": "src/platforms/web/compiler/modules/index.js",
    "content": "import klass from './class'\nimport style from './style'\n\nexport default [\n  klass,\n  style\n]\n"
  },
  {
    "path": "src/platforms/web/compiler/modules/style.js",
    "content": "/* @flow */\n\nimport { parseText } from 'compiler/parser/text-parser'\nimport { parseStyleText } from 'web/util/style'\nimport {\n  getAndRemoveAttr,\n  getBindingAttr,\n  baseWarn\n} from 'compiler/helpers'\n\nfunction transformNode (el: ASTElement, options: CompilerOptions) {\n  const warn = options.warn || baseWarn\n  const staticStyle = getAndRemoveAttr(el, 'style')\n  if (staticStyle) {\n    /* istanbul ignore if */\n    if (process.env.NODE_ENV !== 'production') {\n      const expression = parseText(staticStyle, options.delimiters)\n      if (expression) {\n        warn(\n          `style=\"${staticStyle}\": ` +\n          'Interpolation inside attributes has been removed. ' +\n          'Use v-bind or the colon shorthand instead. For example, ' +\n          'instead of <div style=\"{{ val }}\">, use <div :style=\"val\">.'\n        )\n      }\n    }\n    el.staticStyle = JSON.stringify(parseStyleText(staticStyle))\n  }\n\n  const styleBinding = getBindingAttr(el, 'style', false /* getStatic */)\n  if (styleBinding) {\n    el.styleBinding = styleBinding\n  }\n}\n\nfunction genData (el: ASTElement): string {\n  let data = ''\n  if (el.staticStyle) {\n    data += `staticStyle:${el.staticStyle},`\n  }\n  if (el.styleBinding) {\n    data += `style:(${el.styleBinding}),`\n  }\n  return data\n}\n\nexport default {\n  staticKeys: ['staticStyle'],\n  transformNode,\n  genData\n}\n"
  },
  {
    "path": "src/platforms/web/compiler/options.js",
    "content": "/* @flow */\n\nimport {\n  isPreTag,\n  mustUseProp,\n  isReservedTag,\n  getTagNamespace\n} from '../util/index'\n\nimport modules from './modules/index'\nimport directives from './directives/index'\nimport { genStaticKeys } from 'shared/util'\nimport { isUnaryTag, canBeLeftOpenTag } from './util'\n\nexport const baseOptions: CompilerOptions = {\n  expectHTML: true,\n  modules,\n  directives,\n  isPreTag,\n  isUnaryTag,\n  mustUseProp,\n  canBeLeftOpenTag,\n  isReservedTag,\n  getTagNamespace,\n  staticKeys: genStaticKeys(modules)\n}\n"
  },
  {
    "path": "src/platforms/web/compiler/util.js",
    "content": "/* @flow */\n\nimport { makeMap } from 'shared/util'\n\nexport const isUnaryTag = makeMap(\n  'area,base,br,col,embed,frame,hr,img,input,isindex,keygen,' +\n  'link,meta,param,source,track,wbr'\n)\n\n// Elements that you can, intentionally, leave open\n// (and which close themselves)\nexport const canBeLeftOpenTag = makeMap(\n  'colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr,source'\n)\n\n// HTML5 tags https://html.spec.whatwg.org/multipage/indices.html#elements-3\n// Phrasing Content https://html.spec.whatwg.org/multipage/dom.html#phrasing-content\nexport const isNonPhrasingTag = makeMap(\n  'address,article,aside,base,blockquote,body,caption,col,colgroup,dd,' +\n  'details,dialog,div,dl,dt,fieldset,figcaption,figure,footer,form,' +\n  'h1,h2,h3,h4,h5,h6,head,header,hgroup,hr,html,legend,li,menuitem,meta,' +\n  'optgroup,option,param,rp,rt,source,style,summary,tbody,td,tfoot,th,thead,' +\n  'title,tr,track'\n)\n"
  },
  {
    "path": "src/platforms/web/entry-compiler.js",
    "content": "/* @flow */\n\nexport { parseComponent } from 'sfc/parser'\nexport { compile, compileToFunctions } from './compiler/index'\nexport { ssrCompile, ssrCompileToFunctions } from './server/compiler'\n"
  },
  {
    "path": "src/platforms/web/entry-runtime-with-compiler.js",
    "content": "/* @flow */\n\nimport config from 'core/config'\nimport { warn, cached } from 'core/util/index'\nimport { mark, measure } from 'core/util/perf'\n\nimport Vue from './runtime/index'\nimport { query } from './util/index'\nimport { shouldDecodeNewlines } from './util/compat'\nimport { compileToFunctions } from './compiler/index'\n\nconst idToTemplate = cached(id => {\n  const el = query(id)\n  return el && el.innerHTML\n})\n\nconst mount = Vue.prototype.$mount\nVue.prototype.$mount = function (\n  el?: string | Element,\n  hydrating?: boolean\n): Component {\n  el = el && query(el)\n\n  /* istanbul ignore if */\n  if (el === document.body || el === document.documentElement) {\n    process.env.NODE_ENV !== 'production' && warn(\n      `Do not mount Vue to <html> or <body> - mount to normal elements instead.`\n    )\n    return this\n  }\n\n  const options = this.$options\n  // resolve template/el and convert to render function\n  if (!options.render) {\n    let template = options.template\n    if (template) {\n      if (typeof template === 'string') {\n        if (template.charAt(0) === '#') {\n          template = idToTemplate(template)\n          /* istanbul ignore if */\n          if (process.env.NODE_ENV !== 'production' && !template) {\n            warn(\n              `Template element not found or is empty: ${options.template}`,\n              this\n            )\n          }\n        }\n      } else if (template.nodeType) {\n        template = template.innerHTML\n      } else {\n        if (process.env.NODE_ENV !== 'production') {\n          warn('invalid template option:' + template, this)\n        }\n        return this\n      }\n    } else if (el) {\n      template = getOuterHTML(el)\n    }\n    if (template) {\n      /* istanbul ignore if */\n      if (process.env.NODE_ENV !== 'production' && config.performance && mark) {\n        mark('compile')\n      }\n\n      const { render, staticRenderFns } = compileToFunctions(template, {\n        shouldDecodeNewlines,\n        delimiters: options.delimiters,\n        comments: options.comments\n      }, this)\n      options.render = render\n      options.staticRenderFns = staticRenderFns\n\n      /* istanbul ignore if */\n      if (process.env.NODE_ENV !== 'production' && config.performance && mark) {\n        mark('compile end')\n        measure(`${this._name} compile`, 'compile', 'compile end')\n      }\n    }\n  }\n  return mount.call(this, el, hydrating)\n}\n\n/**\n * Get outerHTML of elements, taking care\n * of SVG elements in IE as well.\n */\nfunction getOuterHTML (el: Element): string {\n  if (el.outerHTML) {\n    return el.outerHTML\n  } else {\n    const container = document.createElement('div')\n    container.appendChild(el.cloneNode(true))\n    return container.innerHTML\n  }\n}\n\nVue.compile = compileToFunctions\n\nexport default Vue\n"
  },
  {
    "path": "src/platforms/web/entry-runtime.js",
    "content": "/* @flow */\n\nimport Vue from './runtime/index'\n\nexport default Vue\n"
  },
  {
    "path": "src/platforms/web/entry-server-basic-renderer.js",
    "content": "/* @flow */\n\nimport modules from './server/modules/index'\nimport directives from './server/directives/index'\nimport { isUnaryTag, canBeLeftOpenTag } from './compiler/util'\nimport { createBasicRenderer } from 'server/create-basic-renderer'\n\nexport default createBasicRenderer({\n  modules,\n  directives,\n  isUnaryTag,\n  canBeLeftOpenTag\n})\n"
  },
  {
    "path": "src/platforms/web/entry-server-renderer.js",
    "content": "/* @flow */\n\nprocess.env.VUE_ENV = 'server'\n\nimport modules from './server/modules/index'\nimport baseDirectives from './server/directives/index'\nimport { isUnaryTag, canBeLeftOpenTag } from './compiler/util'\n\nimport { createRenderer as _createRenderer } from 'server/create-renderer'\nimport { createBundleRendererCreator } from 'server/bundle-renderer/create-bundle-renderer'\n\nexport function createRenderer (options?: Object = {}): {\n  renderToString: Function,\n  renderToStream: Function\n} {\n  return _createRenderer(Object.assign({}, options, {\n    isUnaryTag,\n    canBeLeftOpenTag,\n    modules,\n    // user can provide server-side implementations for custom directives\n    // when creating the renderer.\n    directives: Object.assign(baseDirectives, options.directives)\n  }))\n}\n\nexport const createBundleRenderer = createBundleRendererCreator(createRenderer)\n"
  },
  {
    "path": "src/platforms/web/runtime/class-util.js",
    "content": "/* @flow */\n\n/**\n * Add class with compatibility for SVG since classList is not supported on\n * SVG elements in IE\n */\nexport function addClass (el: HTMLElement, cls: ?string) {\n  /* istanbul ignore if */\n  if (!cls || !(cls = cls.trim())) {\n    return\n  }\n\n  /* istanbul ignore else */\n  if (el.classList) {\n    if (cls.indexOf(' ') > -1) {\n      cls.split(/\\s+/).forEach(c => el.classList.add(c))\n    } else {\n      el.classList.add(cls)\n    }\n  } else {\n    const cur = ` ${el.getAttribute('class') || ''} `\n    if (cur.indexOf(' ' + cls + ' ') < 0) {\n      el.setAttribute('class', (cur + cls).trim())\n    }\n  }\n}\n\n/**\n * Remove class with compatibility for SVG since classList is not supported on\n * SVG elements in IE\n */\nexport function removeClass (el: HTMLElement, cls: ?string) {\n  /* istanbul ignore if */\n  if (!cls || !(cls = cls.trim())) {\n    return\n  }\n\n  /* istanbul ignore else */\n  if (el.classList) {\n    if (cls.indexOf(' ') > -1) {\n      cls.split(/\\s+/).forEach(c => el.classList.remove(c))\n    } else {\n      el.classList.remove(cls)\n    }\n    if (!el.classList.length) {\n      el.removeAttribute('class')\n    }\n  } else {\n    let cur = ` ${el.getAttribute('class') || ''} `\n    const tar = ' ' + cls + ' '\n    while (cur.indexOf(tar) >= 0) {\n      cur = cur.replace(tar, ' ')\n    }\n    cur = cur.trim()\n    if (cur) {\n      el.setAttribute('class', cur)\n    } else {\n      el.removeAttribute('class')\n    }\n  }\n}\n"
  },
  {
    "path": "src/platforms/web/runtime/components/index.js",
    "content": "import Transition from './transition'\nimport TransitionGroup from './transition-group'\n\nexport default {\n  Transition,\n  TransitionGroup\n}\n"
  },
  {
    "path": "src/platforms/web/runtime/components/transition-group.js",
    "content": "/* @flow */\n\n// Provides transition support for list items.\n// supports move transitions using the FLIP technique.\n\n// Because the vdom's children update algorithm is \"unstable\" - i.e.\n// it doesn't guarantee the relative positioning of removed elements,\n// we force transition-group to update its children into two passes:\n// in the first pass, we remove all nodes that need to be removed,\n// triggering their leaving transition; in the second pass, we insert/move\n// into the final desired state. This way in the second pass removed\n// nodes will remain where they should be.\n\nimport { warn, extend } from 'core/util/index'\nimport { addClass, removeClass } from '../class-util'\nimport { transitionProps, extractTransitionData } from './transition'\n\nimport {\n  hasTransition,\n  getTransitionInfo,\n  transitionEndEvent,\n  addTransitionClass,\n  removeTransitionClass\n} from '../transition-util'\n\nconst props = extend({\n  tag: String,\n  moveClass: String\n}, transitionProps)\n\ndelete props.mode\n\nexport default {\n  props,\n\n  render (h: Function) {\n    const tag: string = this.tag || this.$vnode.data.tag || 'span'\n    const map: Object = Object.create(null)\n    const prevChildren: Array<VNode> = this.prevChildren = this.children\n    const rawChildren: Array<VNode> = this.$slots.default || []\n    const children: Array<VNode> = this.children = []\n    const transitionData: Object = extractTransitionData(this)\n\n    for (let i = 0; i < rawChildren.length; i++) {\n      const c: VNode = rawChildren[i]\n      if (c.tag) {\n        if (c.key != null && String(c.key).indexOf('__vlist') !== 0) {\n          children.push(c)\n          map[c.key] = c\n          ;(c.data || (c.data = {})).transition = transitionData\n        } else if (process.env.NODE_ENV !== 'production') {\n          const opts: ?VNodeComponentOptions = c.componentOptions\n          const name: string = opts ? (opts.Ctor.options.name || opts.tag || '') : c.tag\n          warn(`<transition-group> children must be keyed: <${name}>`)\n        }\n      }\n    }\n\n    if (prevChildren) {\n      const kept: Array<VNode> = []\n      const removed: Array<VNode> = []\n      for (let i = 0; i < prevChildren.length; i++) {\n        const c: VNode = prevChildren[i]\n        c.data.transition = transitionData\n        c.data.pos = c.elm.getBoundingClientRect()\n        if (map[c.key]) {\n          kept.push(c)\n        } else {\n          removed.push(c)\n        }\n      }\n      this.kept = h(tag, null, kept)\n      this.removed = removed\n    }\n\n    return h(tag, null, children)\n  },\n\n  beforeUpdate () {\n    // force removing pass\n    this.__patch__(\n      this._vnode,\n      this.kept,\n      false, // hydrating\n      true // removeOnly (!important, avoids unnecessary moves)\n    )\n    this._vnode = this.kept\n  },\n\n  updated () {\n    const children: Array<VNode> = this.prevChildren\n    const moveClass: string = this.moveClass || ((this.name || 'v') + '-move')\n    if (!children.length || !this.hasMove(children[0].elm, moveClass)) {\n      return\n    }\n\n    // we divide the work into three loops to avoid mixing DOM reads and writes\n    // in each iteration - which helps prevent layout thrashing.\n    children.forEach(callPendingCbs)\n    children.forEach(recordPosition)\n    children.forEach(applyTranslation)\n\n    // force reflow to put everything in position\n    const body: any = document.body\n    const f: number = body.offsetHeight // eslint-disable-line\n\n    children.forEach((c: VNode) => {\n      if (c.data.moved) {\n        var el: any = c.elm\n        var s: any = el.style\n        addTransitionClass(el, moveClass)\n        s.transform = s.WebkitTransform = s.transitionDuration = ''\n        el.addEventListener(transitionEndEvent, el._moveCb = function cb (e) {\n          if (!e || /transform$/.test(e.propertyName)) {\n            el.removeEventListener(transitionEndEvent, cb)\n            el._moveCb = null\n            removeTransitionClass(el, moveClass)\n          }\n        })\n      }\n    })\n  },\n\n  methods: {\n    hasMove (el: any, moveClass: string): boolean {\n      /* istanbul ignore if */\n      if (!hasTransition) {\n        return false\n      }\n      /* istanbul ignore if */\n      if (this._hasMove) {\n        return this._hasMove\n      }\n      // Detect whether an element with the move class applied has\n      // CSS transitions. Since the element may be inside an entering\n      // transition at this very moment, we make a clone of it and remove\n      // all other transition classes applied to ensure only the move class\n      // is applied.\n      const clone: HTMLElement = el.cloneNode()\n      if (el._transitionClasses) {\n        el._transitionClasses.forEach((cls: string) => { removeClass(clone, cls) })\n      }\n      addClass(clone, moveClass)\n      clone.style.display = 'none'\n      this.$el.appendChild(clone)\n      const info: Object = getTransitionInfo(clone)\n      this.$el.removeChild(clone)\n      return (this._hasMove = info.hasTransform)\n    }\n  }\n}\n\nfunction callPendingCbs (c: VNode) {\n  /* istanbul ignore if */\n  if (c.elm._moveCb) {\n    c.elm._moveCb()\n  }\n  /* istanbul ignore if */\n  if (c.elm._enterCb) {\n    c.elm._enterCb()\n  }\n}\n\nfunction recordPosition (c: VNode) {\n  c.data.newPos = c.elm.getBoundingClientRect()\n}\n\nfunction applyTranslation (c: VNode) {\n  const oldPos = c.data.pos\n  const newPos = c.data.newPos\n  const dx = oldPos.left - newPos.left\n  const dy = oldPos.top - newPos.top\n  if (dx || dy) {\n    c.data.moved = true\n    const s = c.elm.style\n    s.transform = s.WebkitTransform = `translate(${dx}px,${dy}px)`\n    s.transitionDuration = '0s'\n  }\n}\n"
  },
  {
    "path": "src/platforms/web/runtime/components/transition.js",
    "content": "/* @flow */\n\n// Provides transition support for a single element/component.\n// supports transition mode (out-in / in-out)\n\nimport { warn } from 'core/util/index'\nimport { camelize, extend, isPrimitive } from 'shared/util'\nimport { mergeVNodeHook, getFirstComponentChild } from 'core/vdom/helpers/index'\n\nexport const transitionProps = {\n  name: String,\n  appear: Boolean,\n  css: Boolean,\n  mode: String,\n  type: String,\n  enterClass: String,\n  leaveClass: String,\n  enterToClass: String,\n  leaveToClass: String,\n  enterActiveClass: String,\n  leaveActiveClass: String,\n  appearClass: String,\n  appearActiveClass: String,\n  appearToClass: String,\n  duration: [Number, String, Object]\n}\n\n// in case the child is also an abstract component, e.g. <keep-alive>\n// we want to recursively retrieve the real component to be rendered\nfunction getRealChild (vnode: ?VNode): ?VNode {\n  const compOptions: ?VNodeComponentOptions = vnode && vnode.componentOptions\n  if (compOptions && compOptions.Ctor.options.abstract) {\n    return getRealChild(getFirstComponentChild(compOptions.children))\n  } else {\n    return vnode\n  }\n}\n\nexport function extractTransitionData (comp: Component): Object {\n  const data = {}\n  const options: ComponentOptions = comp.$options\n  // props\n  for (const key in options.propsData) {\n    data[key] = comp[key]\n  }\n  // events.\n  // extract listeners and pass them directly to the transition methods\n  const listeners: ?Object = options._parentListeners\n  for (const key in listeners) {\n    data[camelize(key)] = listeners[key]\n  }\n  return data\n}\n\nfunction placeholder (h: Function, rawChild: VNode): ?VNode {\n  if (/\\d-keep-alive$/.test(rawChild.tag)) {\n    return h('keep-alive', {\n      props: rawChild.componentOptions.propsData\n    })\n  }\n}\n\nfunction hasParentTransition (vnode: VNode): ?boolean {\n  while ((vnode = vnode.parent)) {\n    if (vnode.data.transition) {\n      return true\n    }\n  }\n}\n\nfunction isSameChild (child: VNode, oldChild: VNode): boolean {\n  return oldChild.key === child.key && oldChild.tag === child.tag\n}\n\nfunction isAsyncPlaceholder (node: VNode): boolean {\n  return node.isComment && node.asyncFactory\n}\n\nexport default {\n  name: 'transition',\n  props: transitionProps,\n  abstract: true,\n\n  render (h: Function) {\n    let children: ?Array<VNode> = this.$options._renderChildren\n    if (!children) {\n      return\n    }\n\n    // filter out text nodes (possible whitespaces)\n    children = children.filter((c: VNode) => c.tag || isAsyncPlaceholder(c))\n    /* istanbul ignore if */\n    if (!children.length) {\n      return\n    }\n\n    // warn multiple elements\n    if (process.env.NODE_ENV !== 'production' && children.length > 1) {\n      warn(\n        '<transition> can only be used on a single element. Use ' +\n        '<transition-group> for lists.',\n        this.$parent\n      )\n    }\n\n    const mode: string = this.mode\n\n    // warn invalid mode\n    if (process.env.NODE_ENV !== 'production' &&\n      mode && mode !== 'in-out' && mode !== 'out-in'\n    ) {\n      warn(\n        'invalid <transition> mode: ' + mode,\n        this.$parent\n      )\n    }\n\n    const rawChild: VNode = children[0]\n\n    // if this is a component root node and the component's\n    // parent container node also has transition, skip.\n    if (hasParentTransition(this.$vnode)) {\n      return rawChild\n    }\n\n    // apply transition data to child\n    // use getRealChild() to ignore abstract components e.g. keep-alive\n    const child: ?VNode = getRealChild(rawChild)\n    /* istanbul ignore if */\n    if (!child) {\n      return rawChild\n    }\n\n    if (this._leaving) {\n      return placeholder(h, rawChild)\n    }\n\n    // ensure a key that is unique to the vnode type and to this transition\n    // component instance. This key will be used to remove pending leaving nodes\n    // during entering.\n    const id: string = `__transition-${this._uid}-`\n    child.key = child.key == null\n      ? child.isComment\n        ? id + 'comment'\n        : id + child.tag\n      : isPrimitive(child.key)\n        ? (String(child.key).indexOf(id) === 0 ? child.key : id + child.key)\n        : child.key\n\n    const data: Object = (child.data || (child.data = {})).transition = extractTransitionData(this)\n    const oldRawChild: VNode = this._vnode\n    const oldChild: VNode = getRealChild(oldRawChild)\n\n    // mark v-show\n    // so that the transition module can hand over the control to the directive\n    if (child.data.directives && child.data.directives.some(d => d.name === 'show')) {\n      child.data.show = true\n    }\n\n    if (\n      oldChild &&\n      oldChild.data &&\n      !isSameChild(child, oldChild) &&\n      !isAsyncPlaceholder(oldChild)\n    ) {\n      // replace old child transition data with fresh one\n      // important for dynamic transitions!\n      const oldData: Object = oldChild && (oldChild.data.transition = extend({}, data))\n      // handle transition mode\n      if (mode === 'out-in') {\n        // return placeholder node and queue update when leave finishes\n        this._leaving = true\n        mergeVNodeHook(oldData, 'afterLeave', () => {\n          this._leaving = false\n          this.$forceUpdate()\n        })\n        return placeholder(h, rawChild)\n      } else if (mode === 'in-out') {\n        if (isAsyncPlaceholder(child)) {\n          return oldRawChild\n        }\n        let delayedLeave\n        const performLeave = () => { delayedLeave() }\n        mergeVNodeHook(data, 'afterEnter', performLeave)\n        mergeVNodeHook(data, 'enterCancelled', performLeave)\n        mergeVNodeHook(oldData, 'delayLeave', leave => { delayedLeave = leave })\n      }\n    }\n\n    return rawChild\n  }\n}\n"
  },
  {
    "path": "src/platforms/web/runtime/directives/index.js",
    "content": "import model from './model'\nimport show from './show'\n\nexport default {\n  model,\n  show\n}\n"
  },
  {
    "path": "src/platforms/web/runtime/directives/model.js",
    "content": "/**\n * Not type checking this file because flow doesn't like attaching\n * properties to Elements.\n */\n\nimport { looseEqual, looseIndexOf, makeMap } from 'shared/util'\nimport { warn, isAndroid, isIE9, isIE, isEdge } from 'core/util/index'\n\nconst isTextInputType = makeMap('text,number,password,search,email,tel,url')\n\n/* istanbul ignore if */\nif (isIE9) {\n  // http://www.matts411.com/post/internet-explorer-9-oninput/\n  document.addEventListener('selectionchange', () => {\n    const el = document.activeElement\n    if (el && el.vmodel) {\n      trigger(el, 'input')\n    }\n  })\n}\n\nexport default {\n  inserted (el, binding, vnode) {\n    if (vnode.tag === 'select') {\n      const cb = () => {\n        setSelected(el, binding, vnode.context)\n      }\n      cb()\n      /* istanbul ignore if */\n      if (isIE || isEdge) {\n        setTimeout(cb, 0)\n      }\n    } else if (vnode.tag === 'textarea' || isTextInputType(el.type)) {\n      el._vModifiers = binding.modifiers\n      if (!binding.modifiers.lazy) {\n        // Safari < 10.2 & UIWebView doesn't fire compositionend when\n        // switching focus before confirming composition choice\n        // this also fixes the issue where some browsers e.g. iOS Chrome\n        // fires \"change\" instead of \"input\" on autocomplete.\n        el.addEventListener('change', onCompositionEnd)\n        if (!isAndroid) {\n          el.addEventListener('compositionstart', onCompositionStart)\n          el.addEventListener('compositionend', onCompositionEnd)\n        }\n        /* istanbul ignore if */\n        if (isIE9) {\n          el.vmodel = true\n        }\n      }\n    }\n  },\n  componentUpdated (el, binding, vnode) {\n    if (vnode.tag === 'select') {\n      setSelected(el, binding, vnode.context)\n      // in case the options rendered by v-for have changed,\n      // it's possible that the value is out-of-sync with the rendered options.\n      // detect such cases and filter out values that no longer has a matching\n      // option in the DOM.\n      const needReset = el.multiple\n        ? binding.value.some(v => hasNoMatchingOption(v, el.options))\n        : binding.value !== binding.oldValue && hasNoMatchingOption(binding.value, el.options)\n      if (needReset) {\n        trigger(el, 'change')\n      }\n    }\n  }\n}\n\nfunction setSelected (el, binding, vm) {\n  const value = binding.value\n  const isMultiple = el.multiple\n  if (isMultiple && !Array.isArray(value)) {\n    process.env.NODE_ENV !== 'production' && warn(\n      `<select multiple v-model=\"${binding.expression}\"> ` +\n      `expects an Array value for its binding, but got ${\n        Object.prototype.toString.call(value).slice(8, -1)\n      }`,\n      vm\n    )\n    return\n  }\n  let selected, option\n  for (let i = 0, l = el.options.length; i < l; i++) {\n    option = el.options[i]\n    if (isMultiple) {\n      selected = looseIndexOf(value, getValue(option)) > -1\n      if (option.selected !== selected) {\n        option.selected = selected\n      }\n    } else {\n      if (looseEqual(getValue(option), value)) {\n        if (el.selectedIndex !== i) {\n          el.selectedIndex = i\n        }\n        return\n      }\n    }\n  }\n  if (!isMultiple) {\n    el.selectedIndex = -1\n  }\n}\n\nfunction hasNoMatchingOption (value, options) {\n  for (let i = 0, l = options.length; i < l; i++) {\n    if (looseEqual(getValue(options[i]), value)) {\n      return false\n    }\n  }\n  return true\n}\n\nfunction getValue (option) {\n  return '_value' in option\n    ? option._value\n    : option.value\n}\n\nfunction onCompositionStart (e) {\n  e.target.composing = true\n}\n\nfunction onCompositionEnd (e) {\n  // prevent triggering an input event for no reason\n  if (!e.target.composing) return\n  e.target.composing = false\n  trigger(e.target, 'input')\n}\n\nfunction trigger (el, type) {\n  const e = document.createEvent('HTMLEvents')\n  e.initEvent(type, true, true)\n  el.dispatchEvent(e)\n}\n"
  },
  {
    "path": "src/platforms/web/runtime/directives/show.js",
    "content": "/* @flow */\n\nimport { isIE9 } from 'core/util/env'\nimport { enter, leave } from '../modules/transition'\n\n// recursively search for possible transition defined inside the component root\nfunction locateNode (vnode: VNode): VNodeWithData {\n  return vnode.componentInstance && (!vnode.data || !vnode.data.transition)\n    ? locateNode(vnode.componentInstance._vnode)\n    : vnode\n}\n\nexport default {\n  bind (el: any, { value }: VNodeDirective, vnode: VNodeWithData) {\n    vnode = locateNode(vnode)\n    const transition = vnode.data && vnode.data.transition\n    const originalDisplay = el.__vOriginalDisplay =\n      el.style.display === 'none' ? '' : el.style.display\n    if (value && transition && !isIE9) {\n      vnode.data.show = true\n      enter(vnode, () => {\n        el.style.display = originalDisplay\n      })\n    } else {\n      el.style.display = value ? originalDisplay : 'none'\n    }\n  },\n\n  update (el: any, { value, oldValue }: VNodeDirective, vnode: VNodeWithData) {\n    /* istanbul ignore if */\n    if (value === oldValue) return\n    vnode = locateNode(vnode)\n    const transition = vnode.data && vnode.data.transition\n    if (transition && !isIE9) {\n      vnode.data.show = true\n      if (value) {\n        enter(vnode, () => {\n          el.style.display = el.__vOriginalDisplay\n        })\n      } else {\n        leave(vnode, () => {\n          el.style.display = 'none'\n        })\n      }\n    } else {\n      el.style.display = value ? el.__vOriginalDisplay : 'none'\n    }\n  },\n\n  unbind (\n    el: any,\n    binding: VNodeDirective,\n    vnode: VNodeWithData,\n    oldVnode: VNodeWithData,\n    isDestroy: boolean\n  ) {\n    if (!isDestroy) {\n      el.style.display = el.__vOriginalDisplay\n    }\n  }\n}\n"
  },
  {
    "path": "src/platforms/web/runtime/index.js",
    "content": "/* @flow */\n\nimport Vue from 'core/index'\nimport config from 'core/config'\nimport { extend, noop } from 'shared/util'\nimport { mountComponent } from 'core/instance/lifecycle'\nimport { devtools, inBrowser, isChrome } from 'core/util/index'\n\nimport {\n  query,\n  mustUseProp,\n  isReservedTag,\n  isReservedAttr,\n  getTagNamespace,\n  isUnknownElement\n} from 'web/util/index'\n\nimport { patch } from './patch'\nimport platformDirectives from './directives/index'\nimport platformComponents from './components/index'\n\n// install platform specific utils\nVue.config.mustUseProp = mustUseProp\nVue.config.isReservedTag = isReservedTag\nVue.config.isReservedAttr = isReservedAttr\nVue.config.getTagNamespace = getTagNamespace\nVue.config.isUnknownElement = isUnknownElement\n\n// install platform runtime directives & components\nextend(Vue.options.directives, platformDirectives)\nextend(Vue.options.components, platformComponents)\n\n// install platform patch function\nVue.prototype.__patch__ = inBrowser ? patch : noop\n\n// public mount method\nVue.prototype.$mount = function (\n  el?: string | Element,\n  hydrating?: boolean\n): Component {\n  el = el && inBrowser ? query(el) : undefined\n  return mountComponent(this, el, hydrating)\n}\n\n// devtools global hook\n/* istanbul ignore next */\nsetTimeout(() => {\n  if (config.devtools) {\n    if (devtools) {\n      devtools.emit('init', Vue)\n    } else if (process.env.NODE_ENV !== 'production' && isChrome) {\n      console[console.info ? 'info' : 'log'](\n        'Download the Vue Devtools extension for a better development experience:\\n' +\n        'https://github.com/vuejs/vue-devtools'\n      )\n    }\n  }\n  if (process.env.NODE_ENV !== 'production' &&\n    config.productionTip !== false &&\n    inBrowser && typeof console !== 'undefined'\n  ) {\n    console[console.info ? 'info' : 'log'](\n      `You are running Vue in development mode.\\n` +\n      `Make sure to turn on production mode when deploying for production.\\n` +\n      `See more tips at https://vuejs.org/guide/deployment.html`\n    )\n  }\n}, 0)\n\nexport default Vue\n"
  },
  {
    "path": "src/platforms/web/runtime/modules/attrs.js",
    "content": "/* @flow */\n\nimport { isIE9 } from 'core/util/env'\n\nimport {\n  extend,\n  isDef,\n  isUndef\n} from 'shared/util'\n\nimport {\n  isXlink,\n  xlinkNS,\n  getXlinkProp,\n  isBooleanAttr,\n  isEnumeratedAttr,\n  isFalsyAttrValue\n} from 'web/util/index'\n\nfunction updateAttrs (oldVnode: VNodeWithData, vnode: VNodeWithData) {\n  const opts = vnode.componentOptions\n  if (isDef(opts) && opts.Ctor.options.inheritAttrs === false) {\n    return\n  }\n  if (isUndef(oldVnode.data.attrs) && isUndef(vnode.data.attrs)) {\n    return\n  }\n  let key, cur, old\n  const elm = vnode.elm\n  const oldAttrs = oldVnode.data.attrs || {}\n  let attrs: any = vnode.data.attrs || {}\n  // clone observed objects, as the user probably wants to mutate it\n  if (isDef(attrs.__ob__)) {\n    attrs = vnode.data.attrs = extend({}, attrs)\n  }\n\n  for (key in attrs) {\n    cur = attrs[key]\n    old = oldAttrs[key]\n    if (old !== cur) {\n      setAttr(elm, key, cur)\n    }\n  }\n  // #4391: in IE9, setting type can reset value for input[type=radio]\n  /* istanbul ignore if */\n  if (isIE9 && attrs.value !== oldAttrs.value) {\n    setAttr(elm, 'value', attrs.value)\n  }\n  for (key in oldAttrs) {\n    if (isUndef(attrs[key])) {\n      if (isXlink(key)) {\n        elm.removeAttributeNS(xlinkNS, getXlinkProp(key))\n      } else if (!isEnumeratedAttr(key)) {\n        elm.removeAttribute(key)\n      }\n    }\n  }\n}\n\nfunction setAttr (el: Element, key: string, value: any) {\n  if (isBooleanAttr(key)) {\n    // set attribute for blank value\n    // e.g. <option disabled>Select one</option>\n    if (isFalsyAttrValue(value)) {\n      el.removeAttribute(key)\n    } else {\n      el.setAttribute(key, key)\n    }\n  } else if (isEnumeratedAttr(key)) {\n    el.setAttribute(key, isFalsyAttrValue(value) || value === 'false' ? 'false' : 'true')\n  } else if (isXlink(key)) {\n    if (isFalsyAttrValue(value)) {\n      el.removeAttributeNS(xlinkNS, getXlinkProp(key))\n    } else {\n      el.setAttributeNS(xlinkNS, key, value)\n    }\n  } else {\n    if (isFalsyAttrValue(value)) {\n      el.removeAttribute(key)\n    } else {\n      el.setAttribute(key, value)\n    }\n  }\n}\n\nexport default {\n  create: updateAttrs,\n  update: updateAttrs\n}\n"
  },
  {
    "path": "src/platforms/web/runtime/modules/class.js",
    "content": "/* @flow */\n\nimport {\n  isDef,\n  isUndef\n} from 'shared/util'\n\nimport {\n  concat,\n  stringifyClass,\n  genClassForVnode\n} from 'web/util/index'\n\nfunction updateClass (oldVnode: any, vnode: any) {\n  const el = vnode.elm\n  const data: VNodeData = vnode.data\n  const oldData: VNodeData = oldVnode.data\n  if (\n    isUndef(data.staticClass) &&\n    isUndef(data.class) && (\n      isUndef(oldData) || (\n        isUndef(oldData.staticClass) &&\n        isUndef(oldData.class)\n      )\n    )\n  ) {\n    return\n  }\n\n  let cls = genClassForVnode(vnode)\n\n  // handle transition classes\n  const transitionClass = el._transitionClasses\n  if (isDef(transitionClass)) {\n    cls = concat(cls, stringifyClass(transitionClass))\n  }\n\n  // set the class\n  if (cls !== el._prevClass) {\n    el.setAttribute('class', cls)\n    el._prevClass = cls\n  }\n}\n\nexport default {\n  create: updateClass,\n  update: updateClass\n}\n"
  },
  {
    "path": "src/platforms/web/runtime/modules/dom-props.js",
    "content": "/* @flow */\n\nimport { isDef, isUndef, extend, toNumber } from 'shared/util'\n\nfunction updateDOMProps (oldVnode: VNodeWithData, vnode: VNodeWithData) {\n  if (isUndef(oldVnode.data.domProps) && isUndef(vnode.data.domProps)) {\n    return\n  }\n  let key, cur\n  const elm: any = vnode.elm\n  const oldProps = oldVnode.data.domProps || {}\n  let props = vnode.data.domProps || {}\n  // clone observed objects, as the user probably wants to mutate it\n  if (isDef(props.__ob__)) {\n    props = vnode.data.domProps = extend({}, props)\n  }\n\n  for (key in oldProps) {\n    if (isUndef(props[key])) {\n      elm[key] = ''\n    }\n  }\n  for (key in props) {\n    cur = props[key]\n    // ignore children if the node has textContent or innerHTML,\n    // as these will throw away existing DOM nodes and cause removal errors\n    // on subsequent patches (#3360)\n    if (key === 'textContent' || key === 'innerHTML') {\n      if (vnode.children) vnode.children.length = 0\n      if (cur === oldProps[key]) continue\n    }\n\n    if (key === 'value') {\n      // store value as _value as well since\n      // non-string values will be stringified\n      elm._value = cur\n      // avoid resetting cursor position when value is the same\n      const strCur = isUndef(cur) ? '' : String(cur)\n      if (shouldUpdateValue(elm, vnode, strCur)) {\n        elm.value = strCur\n      }\n    } else {\n      elm[key] = cur\n    }\n  }\n}\n\n// check platforms/web/util/attrs.js acceptValue\ntype acceptValueElm = HTMLInputElement | HTMLSelectElement | HTMLOptionElement;\n\nfunction shouldUpdateValue (\n  elm: acceptValueElm,\n  vnode: VNodeWithData,\n  checkVal: string\n): boolean {\n  return (!elm.composing && (\n    vnode.tag === 'option' ||\n    isDirty(elm, checkVal) ||\n    isInputChanged(elm, checkVal)\n  ))\n}\n\nfunction isDirty (elm: acceptValueElm, checkVal: string): boolean {\n  // return true when textbox (.number and .trim) loses focus and its value is\n  // not equal to the updated value\n  return document.activeElement !== elm && elm.value !== checkVal\n}\n\nfunction isInputChanged (elm: any, newVal: string): boolean {\n  const value = elm.value\n  const modifiers = elm._vModifiers // injected by v-model runtime\n  if (isDef(modifiers) && modifiers.number) {\n    return toNumber(value) !== toNumber(newVal)\n  }\n  if (isDef(modifiers) && modifiers.trim) {\n    return value.trim() !== newVal.trim()\n  }\n  return value !== newVal\n}\n\nexport default {\n  create: updateDOMProps,\n  update: updateDOMProps\n}\n"
  },
  {
    "path": "src/platforms/web/runtime/modules/events.js",
    "content": "/* @flow */\n\nimport { isDef, isUndef } from 'shared/util'\nimport { updateListeners } from 'core/vdom/helpers/index'\nimport { isChrome, isIE, supportsPassive } from 'core/util/env'\nimport { RANGE_TOKEN, CHECKBOX_RADIO_TOKEN } from 'web/compiler/directives/model'\n\n// normalize v-model event tokens that can only be determined at runtime.\n// it's important to place the event as the first in the array because\n// the whole point is ensuring the v-model callback gets called before\n// user-attached handlers.\nfunction normalizeEvents (on) {\n  let event\n  /* istanbul ignore if */\n  if (isDef(on[RANGE_TOKEN])) {\n    // IE input[type=range] only supports `change` event\n    event = isIE ? 'change' : 'input'\n    on[event] = [].concat(on[RANGE_TOKEN], on[event] || [])\n    delete on[RANGE_TOKEN]\n  }\n  if (isDef(on[CHECKBOX_RADIO_TOKEN])) {\n    // Chrome fires microtasks in between click/change, leads to #4521\n    event = isChrome ? 'click' : 'change'\n    on[event] = [].concat(on[CHECKBOX_RADIO_TOKEN], on[event] || [])\n    delete on[CHECKBOX_RADIO_TOKEN]\n  }\n}\n\nlet target: HTMLElement\n\nfunction add (\n  event: string,\n  handler: Function,\n  once: boolean,\n  capture: boolean,\n  passive: boolean\n) {\n  if (once) {\n    const oldHandler = handler\n    const _target = target // save current target element in closure\n    handler = function (ev) {\n      const res = arguments.length === 1\n        ? oldHandler(ev)\n        : oldHandler.apply(null, arguments)\n      if (res !== null) {\n        remove(event, handler, capture, _target)\n      }\n    }\n  }\n  target.addEventListener(\n    event,\n    handler,\n    supportsPassive\n      ? { capture, passive }\n      : capture\n  )\n}\n\nfunction remove (\n  event: string,\n  handler: Function,\n  capture: boolean,\n  _target?: HTMLElement\n) {\n  (_target || target).removeEventListener(event, handler, capture)\n}\n\nfunction updateDOMListeners (oldVnode: VNodeWithData, vnode: VNodeWithData) {\n  const isComponentRoot = isDef(vnode.componentOptions)\n  let oldOn = isComponentRoot ? oldVnode.data.nativeOn : oldVnode.data.on\n  let on = isComponentRoot ? vnode.data.nativeOn : vnode.data.on\n  if (isUndef(oldOn) && isUndef(on)) {\n    return\n  }\n  on = on || {}\n  oldOn = oldOn || {}\n  target = vnode.elm\n  normalizeEvents(on)\n  updateListeners(on, oldOn, add, remove, vnode.context)\n}\n\nexport default {\n  create: updateDOMListeners,\n  update: updateDOMListeners\n}\n"
  },
  {
    "path": "src/platforms/web/runtime/modules/index.js",
    "content": "import attrs from './attrs'\nimport klass from './class'\nimport events from './events'\nimport domProps from './dom-props'\nimport style from './style'\nimport transition from './transition'\n\nexport default [\n  attrs,\n  klass,\n  events,\n  domProps,\n  style,\n  transition\n]\n"
  },
  {
    "path": "src/platforms/web/runtime/modules/style.js",
    "content": "/* @flow */\n\nimport { getStyle, normalizeStyleBinding } from 'web/util/style'\nimport { cached, camelize, extend, isDef, isUndef } from 'shared/util'\n\nconst cssVarRE = /^--/\nconst importantRE = /\\s*!important$/\nconst setProp = (el, name, val) => {\n  /* istanbul ignore if */\n  if (cssVarRE.test(name)) {\n    el.style.setProperty(name, val)\n  } else if (importantRE.test(val)) {\n    el.style.setProperty(name, val.replace(importantRE, ''), 'important')\n  } else {\n    const normalizedName = normalize(name)\n    if (Array.isArray(val)) {\n      // Support values array created by autoprefixer, e.g.\n      // {display: [\"-webkit-box\", \"-ms-flexbox\", \"flex\"]}\n      // Set them one by one, and the browser will only set those it can recognize\n      for (let i = 0, len = val.length; i < len; i++) {\n        el.style[normalizedName] = val[i]\n      }\n    } else {\n      el.style[normalizedName] = val\n    }\n  }\n}\n\nconst vendorNames = ['Webkit', 'Moz', 'ms']\n\nlet emptyStyle\nconst normalize = cached(function (prop) {\n  emptyStyle = emptyStyle || document.createElement('div').style\n  prop = camelize(prop)\n  if (prop !== 'filter' && (prop in emptyStyle)) {\n    return prop\n  }\n  const capName = prop.charAt(0).toUpperCase() + prop.slice(1)\n  for (let i = 0; i < vendorNames.length; i++) {\n    const name = vendorNames[i] + capName\n    if (name in emptyStyle) {\n      return name\n    }\n  }\n})\n\nfunction updateStyle (oldVnode: VNodeWithData, vnode: VNodeWithData) {\n  const data = vnode.data\n  const oldData = oldVnode.data\n\n  if (isUndef(data.staticStyle) && isUndef(data.style) &&\n    isUndef(oldData.staticStyle) && isUndef(oldData.style)\n  ) {\n    return\n  }\n\n  let cur, name\n  const el: any = vnode.elm\n  const oldStaticStyle: any = oldData.staticStyle\n  const oldStyleBinding: any = oldData.normalizedStyle || oldData.style || {}\n\n  // if static style exists, stylebinding already merged into it when doing normalizeStyleData\n  const oldStyle = oldStaticStyle || oldStyleBinding\n\n  const style = normalizeStyleBinding(vnode.data.style) || {}\n\n  // store normalized style under a different key for next diff\n  // make sure to clone it if it's reactive, since the user likley wants\n  // to mutate it.\n  vnode.data.normalizedStyle = isDef(style.__ob__)\n    ? extend({}, style)\n    : style\n\n  const newStyle = getStyle(vnode, true)\n\n  for (name in oldStyle) {\n    if (isUndef(newStyle[name])) {\n      setProp(el, name, '')\n    }\n  }\n  for (name in newStyle) {\n    cur = newStyle[name]\n    if (cur !== oldStyle[name]) {\n      // ie9 setting to null has no effect, must use empty string\n      setProp(el, name, cur == null ? '' : cur)\n    }\n  }\n}\n\nexport default {\n  create: updateStyle,\n  update: updateStyle\n}\n"
  },
  {
    "path": "src/platforms/web/runtime/modules/transition.js",
    "content": "/* @flow */\n\nimport { inBrowser, isIE9, warn } from 'core/util/index'\nimport { mergeVNodeHook } from 'core/vdom/helpers/index'\nimport { activeInstance } from 'core/instance/lifecycle'\n\nimport {\n  once,\n  isDef,\n  isUndef,\n  isObject,\n  toNumber\n} from 'shared/util'\n\nimport {\n  nextFrame,\n  resolveTransition,\n  whenTransitionEnds,\n  addTransitionClass,\n  removeTransitionClass\n} from '../transition-util'\n\nexport function enter (vnode: VNodeWithData, toggleDisplay: ?() => void) {\n  const el: any = vnode.elm\n\n  // call leave callback now\n  if (isDef(el._leaveCb)) {\n    el._leaveCb.cancelled = true\n    el._leaveCb()\n  }\n\n  const data = resolveTransition(vnode.data.transition)\n  if (isUndef(data)) {\n    return\n  }\n\n  /* istanbul ignore if */\n  if (isDef(el._enterCb) || el.nodeType !== 1) {\n    return\n  }\n\n  const {\n    css,\n    type,\n    enterClass,\n    enterToClass,\n    enterActiveClass,\n    appearClass,\n    appearToClass,\n    appearActiveClass,\n    beforeEnter,\n    enter,\n    afterEnter,\n    enterCancelled,\n    beforeAppear,\n    appear,\n    afterAppear,\n    appearCancelled,\n    duration\n  } = data\n\n  // activeInstance will always be the <transition> component managing this\n  // transition. One edge case to check is when the <transition> is placed\n  // as the root node of a child component. In that case we need to check\n  // <transition>'s parent for appear check.\n  let context = activeInstance\n  let transitionNode = activeInstance.$vnode\n  while (transitionNode && transitionNode.parent) {\n    transitionNode = transitionNode.parent\n    context = transitionNode.context\n  }\n\n  const isAppear = !context._isMounted || !vnode.isRootInsert\n\n  if (isAppear && !appear && appear !== '') {\n    return\n  }\n\n  const startClass = isAppear && appearClass\n    ? appearClass\n    : enterClass\n  const activeClass = isAppear && appearActiveClass\n    ? appearActiveClass\n    : enterActiveClass\n  const toClass = isAppear && appearToClass\n    ? appearToClass\n    : enterToClass\n\n  const beforeEnterHook = isAppear\n    ? (beforeAppear || beforeEnter)\n    : beforeEnter\n  const enterHook = isAppear\n    ? (typeof appear === 'function' ? appear : enter)\n    : enter\n  const afterEnterHook = isAppear\n    ? (afterAppear || afterEnter)\n    : afterEnter\n  const enterCancelledHook = isAppear\n    ? (appearCancelled || enterCancelled)\n    : enterCancelled\n\n  const explicitEnterDuration: any = toNumber(\n    isObject(duration)\n      ? duration.enter\n      : duration\n  )\n\n  if (process.env.NODE_ENV !== 'production' && explicitEnterDuration != null) {\n    checkDuration(explicitEnterDuration, 'enter', vnode)\n  }\n\n  const expectsCSS = css !== false && !isIE9\n  const userWantsControl = getHookArgumentsLength(enterHook)\n\n  const cb = el._enterCb = once(() => {\n    if (expectsCSS) {\n      removeTransitionClass(el, toClass)\n      removeTransitionClass(el, activeClass)\n    }\n    if (cb.cancelled) {\n      if (expectsCSS) {\n        removeTransitionClass(el, startClass)\n      }\n      enterCancelledHook && enterCancelledHook(el)\n    } else {\n      afterEnterHook && afterEnterHook(el)\n    }\n    el._enterCb = null\n  })\n\n  if (!vnode.data.show) {\n    // remove pending leave element on enter by injecting an insert hook\n    mergeVNodeHook(vnode.data.hook || (vnode.data.hook = {}), 'insert', () => {\n      const parent = el.parentNode\n      const pendingNode = parent && parent._pending && parent._pending[vnode.key]\n      if (pendingNode &&\n        pendingNode.tag === vnode.tag &&\n        pendingNode.elm._leaveCb\n      ) {\n        pendingNode.elm._leaveCb()\n      }\n      enterHook && enterHook(el, cb)\n    })\n  }\n\n  // start enter transition\n  beforeEnterHook && beforeEnterHook(el)\n  if (expectsCSS) {\n    addTransitionClass(el, startClass)\n    addTransitionClass(el, activeClass)\n    nextFrame(() => {\n      addTransitionClass(el, toClass)\n      removeTransitionClass(el, startClass)\n      if (!cb.cancelled && !userWantsControl) {\n        if (isValidDuration(explicitEnterDuration)) {\n          setTimeout(cb, explicitEnterDuration)\n        } else {\n          whenTransitionEnds(el, type, cb)\n        }\n      }\n    })\n  }\n\n  if (vnode.data.show) {\n    toggleDisplay && toggleDisplay()\n    enterHook && enterHook(el, cb)\n  }\n\n  if (!expectsCSS && !userWantsControl) {\n    cb()\n  }\n}\n\nexport function leave (vnode: VNodeWithData, rm: Function) {\n  const el: any = vnode.elm\n\n  // call enter callback now\n  if (isDef(el._enterCb)) {\n    el._enterCb.cancelled = true\n    el._enterCb()\n  }\n\n  const data = resolveTransition(vnode.data.transition)\n  if (isUndef(data)) {\n    return rm()\n  }\n\n  /* istanbul ignore if */\n  if (isDef(el._leaveCb) || el.nodeType !== 1) {\n    return\n  }\n\n  const {\n    css,\n    type,\n    leaveClass,\n    leaveToClass,\n    leaveActiveClass,\n    beforeLeave,\n    leave,\n    afterLeave,\n    leaveCancelled,\n    delayLeave,\n    duration\n  } = data\n\n  const expectsCSS = css !== false && !isIE9\n  const userWantsControl = getHookArgumentsLength(leave)\n\n  const explicitLeaveDuration: any = toNumber(\n    isObject(duration)\n      ? duration.leave\n      : duration\n  )\n\n  if (process.env.NODE_ENV !== 'production' && isDef(explicitLeaveDuration)) {\n    checkDuration(explicitLeaveDuration, 'leave', vnode)\n  }\n\n  const cb = el._leaveCb = once(() => {\n    if (el.parentNode && el.parentNode._pending) {\n      el.parentNode._pending[vnode.key] = null\n    }\n    if (expectsCSS) {\n      removeTransitionClass(el, leaveToClass)\n      removeTransitionClass(el, leaveActiveClass)\n    }\n    if (cb.cancelled) {\n      if (expectsCSS) {\n        removeTransitionClass(el, leaveClass)\n      }\n      leaveCancelled && leaveCancelled(el)\n    } else {\n      rm()\n      afterLeave && afterLeave(el)\n    }\n    el._leaveCb = null\n  })\n\n  if (delayLeave) {\n    delayLeave(performLeave)\n  } else {\n    performLeave()\n  }\n\n  function performLeave () {\n    // the delayed leave may have already been cancelled\n    if (cb.cancelled) {\n      return\n    }\n    // record leaving element\n    if (!vnode.data.show) {\n      (el.parentNode._pending || (el.parentNode._pending = {}))[(vnode.key: any)] = vnode\n    }\n    beforeLeave && beforeLeave(el)\n    if (expectsCSS) {\n      addTransitionClass(el, leaveClass)\n      addTransitionClass(el, leaveActiveClass)\n      nextFrame(() => {\n        addTransitionClass(el, leaveToClass)\n        removeTransitionClass(el, leaveClass)\n        if (!cb.cancelled && !userWantsControl) {\n          if (isValidDuration(explicitLeaveDuration)) {\n            setTimeout(cb, explicitLeaveDuration)\n          } else {\n            whenTransitionEnds(el, type, cb)\n          }\n        }\n      })\n    }\n    leave && leave(el, cb)\n    if (!expectsCSS && !userWantsControl) {\n      cb()\n    }\n  }\n}\n\n// only used in dev mode\nfunction checkDuration (val, name, vnode) {\n  if (typeof val !== 'number') {\n    warn(\n      `<transition> explicit ${name} duration is not a valid number - ` +\n      `got ${JSON.stringify(val)}.`,\n      vnode.context\n    )\n  } else if (isNaN(val)) {\n    warn(\n      `<transition> explicit ${name} duration is NaN - ` +\n      'the duration expression might be incorrect.',\n      vnode.context\n    )\n  }\n}\n\nfunction isValidDuration (val) {\n  return typeof val === 'number' && !isNaN(val)\n}\n\n/**\n * Normalize a transition hook's argument length. The hook may be:\n * - a merged hook (invoker) with the original in .fns\n * - a wrapped component method (check ._length)\n * - a plain function (.length)\n */\nfunction getHookArgumentsLength (fn: Function): boolean {\n  if (isUndef(fn)) {\n    return false\n  }\n  const invokerFns = fn.fns\n  if (isDef(invokerFns)) {\n    // invoker\n    return getHookArgumentsLength(\n      Array.isArray(invokerFns)\n        ? invokerFns[0]\n        : invokerFns\n    )\n  } else {\n    return (fn._length || fn.length) > 1\n  }\n}\n\nfunction _enter (_: any, vnode: VNodeWithData) {\n  if (vnode.data.show !== true) {\n    enter(vnode)\n  }\n}\n\nexport default inBrowser ? {\n  create: _enter,\n  activate: _enter,\n  remove (vnode: VNode, rm: Function) {\n    /* istanbul ignore else */\n    if (vnode.data.show !== true) {\n      leave(vnode, rm)\n    } else {\n      rm()\n    }\n  }\n} : {}\n"
  },
  {
    "path": "src/platforms/web/runtime/node-ops.js",
    "content": "/* @flow */\n\nimport { namespaceMap } from 'web/util/index'\n\nexport function createElement (tagName: string, vnode: VNode): Element {\n  const elm = document.createElement(tagName)\n  if (tagName !== 'select') {\n    return elm\n  }\n  // false or null will remove the attribute but undefined will not\n  if (vnode.data && vnode.data.attrs && vnode.data.attrs.multiple !== undefined) {\n    elm.setAttribute('multiple', 'multiple')\n  }\n  return elm\n}\n\nexport function createElementNS (namespace: string, tagName: string): Element {\n  return document.createElementNS(namespaceMap[namespace], tagName)\n}\n\nexport function createTextNode (text: string): Text {\n  return document.createTextNode(text)\n}\n\nexport function createComment (text: string): Comment {\n  return document.createComment(text)\n}\n\nexport function insertBefore (parentNode: Node, newNode: Node, referenceNode: Node) {\n  parentNode.insertBefore(newNode, referenceNode)\n}\n\nexport function removeChild (node: Node, child: Node) {\n  node.removeChild(child)\n}\n\nexport function appendChild (node: Node, child: Node) {\n  node.appendChild(child)\n}\n\nexport function parentNode (node: Node): ?Node {\n  return node.parentNode\n}\n\nexport function nextSibling (node: Node): ?Node {\n  return node.nextSibling\n}\n\nexport function tagName (node: Element): string {\n  return node.tagName\n}\n\nexport function setTextContent (node: Node, text: string) {\n  node.textContent = text\n}\n\nexport function setAttribute (node: Element, key: string, val: string) {\n  node.setAttribute(key, val)\n}\n"
  },
  {
    "path": "src/platforms/web/runtime/patch.js",
    "content": "/* @flow */\n\nimport * as nodeOps from 'web/runtime/node-ops'\nimport { createPatchFunction } from 'core/vdom/patch'\nimport baseModules from 'core/vdom/modules/index'\nimport platformModules from 'web/runtime/modules/index'\n\n// the directive module should be applied last, after all\n// built-in modules have been applied.\nconst modules = platformModules.concat(baseModules)\n\nexport const patch: Function = createPatchFunction({ nodeOps, modules })\n"
  },
  {
    "path": "src/platforms/web/runtime/transition-util.js",
    "content": "/* @flow */\n\nimport { inBrowser, isIE9 } from 'core/util/index'\nimport { addClass, removeClass } from './class-util'\nimport { remove, extend, cached } from 'shared/util'\n\nexport function resolveTransition (def?: string | Object): ?Object {\n  if (!def) {\n    return\n  }\n  /* istanbul ignore else */\n  if (typeof def === 'object') {\n    const res = {}\n    if (def.css !== false) {\n      extend(res, autoCssTransition(def.name || 'v'))\n    }\n    extend(res, def)\n    return res\n  } else if (typeof def === 'string') {\n    return autoCssTransition(def)\n  }\n}\n\nconst autoCssTransition: (name: string) => Object = cached(name => {\n  return {\n    enterClass: `${name}-enter`,\n    enterToClass: `${name}-enter-to`,\n    enterActiveClass: `${name}-enter-active`,\n    leaveClass: `${name}-leave`,\n    leaveToClass: `${name}-leave-to`,\n    leaveActiveClass: `${name}-leave-active`\n  }\n})\n\nexport const hasTransition = inBrowser && !isIE9\nconst TRANSITION = 'transition'\nconst ANIMATION = 'animation'\n\n// Transition property/event sniffing\nexport let transitionProp = 'transition'\nexport let transitionEndEvent = 'transitionend'\nexport let animationProp = 'animation'\nexport let animationEndEvent = 'animationend'\nif (hasTransition) {\n  /* istanbul ignore if */\n  if (window.ontransitionend === undefined &&\n    window.onwebkittransitionend !== undefined\n  ) {\n    transitionProp = 'WebkitTransition'\n    transitionEndEvent = 'webkitTransitionEnd'\n  }\n  if (window.onanimationend === undefined &&\n    window.onwebkitanimationend !== undefined\n  ) {\n    animationProp = 'WebkitAnimation'\n    animationEndEvent = 'webkitAnimationEnd'\n  }\n}\n\n// binding to window is necessary to make hot reload work in IE in strict mode\nconst raf = inBrowser && window.requestAnimationFrame\n  ? window.requestAnimationFrame.bind(window)\n  : setTimeout\n\nexport function nextFrame (fn: Function) {\n  raf(() => {\n    raf(fn)\n  })\n}\n\nexport function addTransitionClass (el: any, cls: string) {\n  const transitionClasses = el._transitionClasses || (el._transitionClasses = [])\n  if (transitionClasses.indexOf(cls) < 0) {\n    transitionClasses.push(cls)\n    addClass(el, cls)\n  }\n}\n\nexport function removeTransitionClass (el: any, cls: string) {\n  if (el._transitionClasses) {\n    remove(el._transitionClasses, cls)\n  }\n  removeClass(el, cls)\n}\n\nexport function whenTransitionEnds (\n  el: Element,\n  expectedType: ?string,\n  cb: Function\n) {\n  const { type, timeout, propCount } = getTransitionInfo(el, expectedType)\n  if (!type) return cb()\n  const event: string = type === TRANSITION ? transitionEndEvent : animationEndEvent\n  let ended = 0\n  const end = () => {\n    el.removeEventListener(event, onEnd)\n    cb()\n  }\n  const onEnd = e => {\n    if (e.target === el) {\n      if (++ended >= propCount) {\n        end()\n      }\n    }\n  }\n  setTimeout(() => {\n    if (ended < propCount) {\n      end()\n    }\n  }, timeout + 1)\n  el.addEventListener(event, onEnd)\n}\n\nconst transformRE = /\\b(transform|all)(,|$)/\n\nexport function getTransitionInfo (el: Element, expectedType?: ?string): {\n  type: ?string;\n  propCount: number;\n  timeout: number;\n  hasTransform: boolean;\n} {\n  const styles: any = window.getComputedStyle(el)\n  const transitionDelays: Array<string> = styles[transitionProp + 'Delay'].split(', ')\n  const transitionDurations: Array<string> = styles[transitionProp + 'Duration'].split(', ')\n  const transitionTimeout: number = getTimeout(transitionDelays, transitionDurations)\n  const animationDelays: Array<string> = styles[animationProp + 'Delay'].split(', ')\n  const animationDurations: Array<string> = styles[animationProp + 'Duration'].split(', ')\n  const animationTimeout: number = getTimeout(animationDelays, animationDurations)\n\n  let type: ?string\n  let timeout = 0\n  let propCount = 0\n  /* istanbul ignore if */\n  if (expectedType === TRANSITION) {\n    if (transitionTimeout > 0) {\n      type = TRANSITION\n      timeout = transitionTimeout\n      propCount = transitionDurations.length\n    }\n  } else if (expectedType === ANIMATION) {\n    if (animationTimeout > 0) {\n      type = ANIMATION\n      timeout = animationTimeout\n      propCount = animationDurations.length\n    }\n  } else {\n    timeout = Math.max(transitionTimeout, animationTimeout)\n    type = timeout > 0\n      ? transitionTimeout > animationTimeout\n        ? TRANSITION\n        : ANIMATION\n      : null\n    propCount = type\n      ? type === TRANSITION\n        ? transitionDurations.length\n        : animationDurations.length\n      : 0\n  }\n  const hasTransform: boolean =\n    type === TRANSITION &&\n    transformRE.test(styles[transitionProp + 'Property'])\n  return {\n    type,\n    timeout,\n    propCount,\n    hasTransform\n  }\n}\n\nfunction getTimeout (delays: Array<string>, durations: Array<string>): number {\n  /* istanbul ignore next */\n  while (delays.length < durations.length) {\n    delays = delays.concat(delays)\n  }\n\n  return Math.max.apply(null, durations.map((d, i) => {\n    return toMs(d) + toMs(delays[i])\n  }))\n}\n\nfunction toMs (s: string): number {\n  return Number(s.slice(0, -1)) * 1000\n}\n"
  },
  {
    "path": "src/platforms/web/server/compiler.js",
    "content": "/* @flow */\n\nimport { baseOptions } from '../compiler/options'\nimport { createCompiler } from 'server/optimizing-compiler/index'\n\nconst { compile, compileToFunctions } = createCompiler(baseOptions)\n\nexport {\n  compile as ssrCompile,\n  compileToFunctions as ssrCompileToFunctions\n}\n"
  },
  {
    "path": "src/platforms/web/server/directives/index.js",
    "content": "import show from './show'\n\nexport default {\n  show\n}\n"
  },
  {
    "path": "src/platforms/web/server/directives/show.js",
    "content": "/* @flow */\n\nexport default function show (node: VNodeWithData, dir: VNodeDirective) {\n  if (!dir.value) {\n    const style: any = node.data.style || (node.data.style = {})\n    style.display = 'none'\n  }\n}\n"
  },
  {
    "path": "src/platforms/web/server/modules/attrs.js",
    "content": "/* @flow */\n\nimport { cachedEscape } from '../util'\n\nimport {\n  isDef,\n  isUndef\n} from 'shared/util'\n\nimport {\n  isBooleanAttr,\n  isEnumeratedAttr,\n  isFalsyAttrValue\n} from 'web/util/attrs'\n\nexport default function renderAttrs (node: VNodeWithData): string {\n  let attrs = node.data.attrs\n  let res = ''\n\n  const opts = node.parent && node.parent.componentOptions\n  if (isUndef(opts) || opts.Ctor.options.inheritAttrs !== false) {\n    let parent = node.parent\n    while (isDef(parent)) {\n      if (isDef(parent.data) && isDef(parent.data.attrs)) {\n        attrs = Object.assign({}, attrs, parent.data.attrs)\n      }\n      parent = parent.parent\n    }\n  }\n\n  if (isUndef(attrs)) {\n    return res\n  }\n\n  for (const key in attrs) {\n    if (key === 'style') {\n      // leave it to the style module\n      continue\n    }\n    res += renderAttr(key, attrs[key])\n  }\n  return res\n}\n\nexport function renderAttr (key: string, value: string): string {\n  if (isBooleanAttr(key)) {\n    if (!isFalsyAttrValue(value)) {\n      return ` ${key}=\"${key}\"`\n    }\n  } else if (isEnumeratedAttr(key)) {\n    return ` ${key}=\"${isFalsyAttrValue(value) || value === 'false' ? 'false' : 'true'}\"`\n  } else if (!isFalsyAttrValue(value)) {\n    return ` ${key}=\"${typeof value === 'string' ? cachedEscape(value) : value}\"`\n  }\n  return ''\n}\n"
  },
  {
    "path": "src/platforms/web/server/modules/class.js",
    "content": "/* @flow */\n\nimport { cachedEscape } from '../util'\nimport { genClassForVnode } from 'web/util/index'\n\nexport default function renderClass (node: VNodeWithData): ?string {\n  const classList = genClassForVnode(node)\n  if (classList !== '') {\n    return ` class=\"${cachedEscape(classList)}\"`\n  }\n}\n"
  },
  {
    "path": "src/platforms/web/server/modules/dom-props.js",
    "content": "/* @flow */\n\nimport VNode from 'core/vdom/vnode'\nimport { renderAttr } from './attrs'\nimport { isDef, isUndef } from 'shared/util'\nimport { propsToAttrMap, isRenderableAttr } from '../util'\n\nexport default function renderDOMProps (node: VNodeWithData): string {\n  let props = node.data.domProps\n  let res = ''\n\n  let parent = node.parent\n  while (isDef(parent)) {\n    if (parent.data && parent.data.domProps) {\n      props = Object.assign({}, props, parent.data.domProps)\n    }\n    parent = parent.parent\n  }\n\n  if (isUndef(props)) {\n    return res\n  }\n\n  const attrs = node.data.attrs\n  for (const key in props) {\n    if (key === 'innerHTML') {\n      setText(node, props[key], true)\n    } else if (key === 'textContent') {\n      setText(node, props[key], false)\n    } else {\n      const attr = propsToAttrMap[key] || key.toLowerCase()\n      if (isRenderableAttr(attr) &&\n        // avoid rendering double-bound props/attrs twice\n        !(isDef(attrs) && isDef(attrs[attr]))\n      ) {\n        res += renderAttr(attr, props[key])\n      }\n    }\n  }\n  return res\n}\n\nfunction setText (node, text, raw) {\n  const child = new VNode(undefined, undefined, undefined, text)\n  child.raw = raw\n  node.children = [child]\n}\n"
  },
  {
    "path": "src/platforms/web/server/modules/index.js",
    "content": "import attrs from './attrs'\nimport domProps from './dom-props'\nimport klass from './class'\nimport style from './style'\n\nexport default [\n  attrs,\n  domProps,\n  klass,\n  style\n]\n"
  },
  {
    "path": "src/platforms/web/server/modules/style.js",
    "content": "/* @flow */\n\nimport { cachedEscape } from '../util'\nimport { hyphenate } from 'shared/util'\nimport { getStyle } from 'web/util/style'\n\nexport function genStyle (style: Object): string {\n  let styleText = ''\n  for (const key in style) {\n    const value = style[key]\n    const hyphenatedKey = hyphenate(key)\n    if (Array.isArray(value)) {\n      for (let i = 0, len = value.length; i < len; i++) {\n        styleText += `${hyphenatedKey}:${value[i]};`\n      }\n    } else {\n      styleText += `${hyphenatedKey}:${value};`\n    }\n  }\n  return styleText\n}\n\nexport default function renderStyle (vnode: VNodeWithData): ?string {\n  const styleText = genStyle(getStyle(vnode, false))\n  if (styleText !== '') {\n    return ` style=${JSON.stringify(cachedEscape(styleText))}`\n  }\n}\n"
  },
  {
    "path": "src/platforms/web/server/util.js",
    "content": "/* @flow */\n\nimport { makeMap, cached } from 'shared/util'\n\nconst isAttr = makeMap(\n  'accept,accept-charset,accesskey,action,align,alt,async,autocomplete,' +\n  'autofocus,autoplay,autosave,bgcolor,border,buffered,challenge,charset,' +\n  'checked,cite,class,code,codebase,color,cols,colspan,content,http-equiv,' +\n  'name,contenteditable,contextmenu,controls,coords,data,datetime,default,' +\n  'defer,dir,dirname,disabled,download,draggable,dropzone,enctype,method,for,' +\n  'form,formaction,headers,height,hidden,high,href,hreflang,http-equiv,' +\n  'icon,id,ismap,itemprop,keytype,kind,label,lang,language,list,loop,low,' +\n  'manifest,max,maxlength,media,method,GET,POST,min,multiple,email,file,' +\n  'muted,name,novalidate,open,optimum,pattern,ping,placeholder,poster,' +\n  'preload,radiogroup,readonly,rel,required,reversed,rows,rowspan,sandbox,' +\n  'scope,scoped,seamless,selected,shape,size,type,text,password,sizes,span,' +\n  'spellcheck,src,srcdoc,srclang,srcset,start,step,style,summary,tabindex,' +\n  'target,title,type,usemap,value,width,wrap'\n)\n\n/* istanbul ignore next */\nconst isRenderableAttr = (name: string): boolean => {\n  return (\n    isAttr(name) ||\n    name.indexOf('data-') === 0 ||\n    name.indexOf('aria-') === 0\n  )\n}\nexport { isRenderableAttr }\n\nexport const propsToAttrMap = {\n  acceptCharset: 'accept-charset',\n  className: 'class',\n  htmlFor: 'for',\n  httpEquiv: 'http-equiv'\n}\n\nconst ESC = {\n  '<': '&lt;',\n  '>': '&gt;',\n  '\"': '&quot;',\n  '&': '&amp;'\n}\n\nexport function escape (s: string) {\n  return s.replace(/[<>\"&]/g, escapeChar)\n}\n\nexport const cachedEscape = cached(escape)\n\nfunction escapeChar (a) {\n  return ESC[a] || a\n}\n"
  },
  {
    "path": "src/platforms/web/util/attrs.js",
    "content": "/* @flow */\n\nimport { makeMap } from 'shared/util'\n\n// these are reserved for web because they are directly compiled away\n// during template compilation\nexport const isReservedAttr = makeMap('style,class')\n\n// attributes that should be using props for binding\nconst acceptValue = makeMap('input,textarea,option,select')\nexport const mustUseProp = (tag: string, type: ?string, attr: string): boolean => {\n  return (\n    (attr === 'value' && acceptValue(tag)) && type !== 'button' ||\n    (attr === 'selected' && tag === 'option') ||\n    (attr === 'checked' && tag === 'input') ||\n    (attr === 'muted' && tag === 'video')\n  )\n}\n\nexport const isEnumeratedAttr = makeMap('contenteditable,draggable,spellcheck')\n\nexport const isBooleanAttr = makeMap(\n  'allowfullscreen,async,autofocus,autoplay,checked,compact,controls,declare,' +\n  'default,defaultchecked,defaultmuted,defaultselected,defer,disabled,' +\n  'enabled,formnovalidate,hidden,indeterminate,inert,ismap,itemscope,loop,multiple,' +\n  'muted,nohref,noresize,noshade,novalidate,nowrap,open,pauseonexit,readonly,' +\n  'required,reversed,scoped,seamless,selected,sortable,translate,' +\n  'truespeed,typemustmatch,visible'\n)\n\nexport const xlinkNS = 'http://www.w3.org/1999/xlink'\n\nexport const isXlink = (name: string): boolean => {\n  return name.charAt(5) === ':' && name.slice(0, 5) === 'xlink'\n}\n\nexport const getXlinkProp = (name: string): string => {\n  return isXlink(name) ? name.slice(6, name.length) : ''\n}\n\nexport const isFalsyAttrValue = (val: any): boolean => {\n  return val == null || val === false\n}\n"
  },
  {
    "path": "src/platforms/web/util/class.js",
    "content": "/* @flow */\n\nimport { isDef, isObject } from 'shared/util'\n\nexport function genClassForVnode (vnode: VNode): string {\n  let data = vnode.data\n  let parentNode = vnode\n  let childNode = vnode\n  while (isDef(childNode.componentInstance)) {\n    childNode = childNode.componentInstance._vnode\n    if (childNode.data) {\n      data = mergeClassData(childNode.data, data)\n    }\n  }\n  while (isDef(parentNode = parentNode.parent)) {\n    if (parentNode.data) {\n      data = mergeClassData(data, parentNode.data)\n    }\n  }\n  return renderClass(data.staticClass, data.class)\n}\n\nfunction mergeClassData (child: VNodeData, parent: VNodeData): {\n  staticClass: string,\n  class: any\n} {\n  return {\n    staticClass: concat(child.staticClass, parent.staticClass),\n    class: isDef(child.class)\n      ? [child.class, parent.class]\n      : parent.class\n  }\n}\n\nexport function renderClass (\n  staticClass: ?string,\n  dynamicClass: any\n): string {\n  if (isDef(staticClass) || isDef(dynamicClass)) {\n    return concat(staticClass, stringifyClass(dynamicClass))\n  }\n  /* istanbul ignore next */\n  return ''\n}\n\nexport function concat (a: ?string, b: ?string): string {\n  return a ? b ? (a + ' ' + b) : a : (b || '')\n}\n\nexport function stringifyClass (value: any): string {\n  if (Array.isArray(value)) {\n    return stringifyArray(value)\n  }\n  if (isObject(value)) {\n    return stringifyObject(value)\n  }\n  if (typeof value === 'string') {\n    return value\n  }\n  /* istanbul ignore next */\n  return ''\n}\n\nfunction stringifyArray (value: Array<any>): string {\n  let res = ''\n  let stringified\n  for (let i = 0, l = value.length; i < l; i++) {\n    if (isDef(stringified = stringifyClass(value[i])) && stringified !== '') {\n      if (res) res += ' '\n      res += stringified\n    }\n  }\n  return res\n}\n\nfunction stringifyObject (value: Object): string {\n  let res = ''\n  for (const key in value) {\n    if (value[key]) {\n      if (res) res += ' '\n      res += key\n    }\n  }\n  return res\n}\n"
  },
  {
    "path": "src/platforms/web/util/compat.js",
    "content": "/* @flow */\n\nimport { inBrowser } from 'core/util/index'\n\n// check whether current browser encodes a char inside attribute values\nfunction shouldDecode (content: string, encoded: string): boolean {\n  const div = document.createElement('div')\n  div.innerHTML = `<div a=\"${content}\"/>`\n  return div.innerHTML.indexOf(encoded) > 0\n}\n\n// #3663\n// IE encodes newlines inside attribute values while other browsers don't\nexport const shouldDecodeNewlines = inBrowser ? shouldDecode('\\n', '&#10;') : false\n"
  },
  {
    "path": "src/platforms/web/util/element.js",
    "content": "/* @flow */\n\nimport { inBrowser } from 'core/util/env'\nimport { makeMap } from 'shared/util'\n\nexport const namespaceMap = {\n  svg: 'http://www.w3.org/2000/svg',\n  math: 'http://www.w3.org/1998/Math/MathML'\n}\n\nexport const isHTMLTag = makeMap(\n  'html,body,base,head,link,meta,style,title,' +\n  'address,article,aside,footer,header,h1,h2,h3,h4,h5,h6,hgroup,nav,section,' +\n  'div,dd,dl,dt,figcaption,figure,picture,hr,img,li,main,ol,p,pre,ul,' +\n  'a,b,abbr,bdi,bdo,br,cite,code,data,dfn,em,i,kbd,mark,q,rp,rt,rtc,ruby,' +\n  's,samp,small,span,strong,sub,sup,time,u,var,wbr,area,audio,map,track,video,' +\n  'embed,object,param,source,canvas,script,noscript,del,ins,' +\n  'caption,col,colgroup,table,thead,tbody,td,th,tr,' +\n  'button,datalist,fieldset,form,input,label,legend,meter,optgroup,option,' +\n  'output,progress,select,textarea,' +\n  'details,dialog,menu,menuitem,summary,' +\n  'content,element,shadow,template,blockquote,iframe,tfoot'\n)\n\n// this map is intentionally selective, only covering SVG elements that may\n// contain child elements.\nexport const isSVG = makeMap(\n  'svg,animate,circle,clippath,cursor,defs,desc,ellipse,filter,font-face,' +\n  'foreignObject,g,glyph,image,line,marker,mask,missing-glyph,path,pattern,' +\n  'polygon,polyline,rect,switch,symbol,text,textpath,tspan,use,view',\n  true\n)\n\nexport const isPreTag = (tag: ?string): boolean => tag === 'pre'\n\nexport const isReservedTag = (tag: string): ?boolean => {\n  return isHTMLTag(tag) || isSVG(tag)\n}\n\nexport function getTagNamespace (tag: string): ?string {\n  if (isSVG(tag)) {\n    return 'svg'\n  }\n  // basic support for MathML\n  // note it doesn't support other MathML elements being component roots\n  if (tag === 'math') {\n    return 'math'\n  }\n}\n\nconst unknownElementCache = Object.create(null)\nexport function isUnknownElement (tag: string): boolean {\n  /* istanbul ignore if */\n  if (!inBrowser) {\n    return true\n  }\n  if (isReservedTag(tag)) {\n    return false\n  }\n  tag = tag.toLowerCase()\n  /* istanbul ignore if */\n  if (unknownElementCache[tag] != null) {\n    return unknownElementCache[tag]\n  }\n  const el = document.createElement(tag)\n  if (tag.indexOf('-') > -1) {\n    // http://stackoverflow.com/a/28210364/1070244\n    return (unknownElementCache[tag] = (\n      el.constructor === window.HTMLUnknownElement ||\n      el.constructor === window.HTMLElement\n    ))\n  } else {\n    return (unknownElementCache[tag] = /HTMLUnknownElement/.test(el.toString()))\n  }\n}\n"
  },
  {
    "path": "src/platforms/web/util/index.js",
    "content": "/* @flow */\n\nimport { warn } from 'core/util/index'\n\nexport * from './attrs'\nexport * from './class'\nexport * from './element'\n\n/**\n * Query an element selector if it's not an element already.\n */\nexport function query (el: string | Element): Element {\n  if (typeof el === 'string') {\n    const selected = document.querySelector(el)\n    if (!selected) {\n      process.env.NODE_ENV !== 'production' && warn(\n        'Cannot find element: ' + el\n      )\n      return document.createElement('div')\n    }\n    return selected\n  } else {\n    return el\n  }\n}\n"
  },
  {
    "path": "src/platforms/web/util/style.js",
    "content": "/* @flow */\n\nimport { cached, extend, toObject } from 'shared/util'\n\nexport const parseStyleText = cached(function (cssText) {\n  const res = {}\n  const listDelimiter = /;(?![^(]*\\))/g\n  const propertyDelimiter = /:(.+)/\n  cssText.split(listDelimiter).forEach(function (item) {\n    if (item) {\n      var tmp = item.split(propertyDelimiter)\n      tmp.length > 1 && (res[tmp[0].trim()] = tmp[1].trim())\n    }\n  })\n  return res\n})\n\n// merge static and dynamic style data on the same vnode\nfunction normalizeStyleData (data: VNodeData): ?Object {\n  const style = normalizeStyleBinding(data.style)\n  // static style is pre-processed into an object during compilation\n  // and is always a fresh object, so it's safe to merge into it\n  return data.staticStyle\n    ? extend(data.staticStyle, style)\n    : style\n}\n\n// normalize possible array / string values into Object\nexport function normalizeStyleBinding (bindingStyle: any): ?Object {\n  if (Array.isArray(bindingStyle)) {\n    return toObject(bindingStyle)\n  }\n  if (typeof bindingStyle === 'string') {\n    return parseStyleText(bindingStyle)\n  }\n  return bindingStyle\n}\n\n/**\n * parent component style should be after child's\n * so that parent component's style could override it\n */\nexport function getStyle (vnode: VNode, checkChild: boolean): Object {\n  const res = {}\n  let styleData\n\n  if (checkChild) {\n    let childNode = vnode\n    while (childNode.componentInstance) {\n      childNode = childNode.componentInstance._vnode\n      if (childNode.data && (styleData = normalizeStyleData(childNode.data))) {\n        extend(res, styleData)\n      }\n    }\n  }\n\n  if ((styleData = normalizeStyleData(vnode.data))) {\n    extend(res, styleData)\n  }\n\n  let parentNode = vnode\n  while ((parentNode = parentNode.parent)) {\n    if (parentNode.data && (styleData = normalizeStyleData(parentNode.data))) {\n      extend(res, styleData)\n    }\n  }\n  return res\n}\n\n"
  },
  {
    "path": "src/platforms/weex/compiler/directives/index.js",
    "content": "import model from './model'\n\nexport default {\n  model\n}\n"
  },
  {
    "path": "src/platforms/weex/compiler/directives/model.js",
    "content": "/* @flow */\n\nimport { addHandler, addAttr } from 'compiler/helpers'\nimport { genComponentModel, genAssignmentCode } from 'compiler/directives/model'\n\nexport default function model (\n  el: ASTElement,\n  dir: ASTDirective,\n  _warn: Function\n): ?boolean {\n  if (el.tag === 'input' || el.tag === 'textarea') {\n    genDefaultModel(el, dir.value, dir.modifiers)\n  } else {\n    genComponentModel(el, dir.value, dir.modifiers)\n  }\n}\n\nfunction genDefaultModel (\n  el: ASTElement,\n  value: string,\n  modifiers: ?ASTModifiers\n): ?boolean {\n  const { lazy, trim, number } = modifiers || {}\n  const event = lazy ? 'change' : 'input'\n\n  let valueExpression = `$event.target.attr.value${trim ? '.trim()' : ''}`\n  if (number) {\n    valueExpression = `_n(${valueExpression})`\n  }\n\n  const code = genAssignmentCode(value, valueExpression)\n  addAttr(el, 'value', `(${value})`)\n  addHandler(el, event, code, null, true)\n}\n"
  },
  {
    "path": "src/platforms/weex/compiler/index.js",
    "content": "/* @flow */\n\nimport { genStaticKeys } from 'shared/util'\nimport { createCompiler } from 'compiler/index'\n\nimport modules from './modules/index'\nimport directives from './directives/index'\n\nimport {\n  isUnaryTag,\n  mustUseProp,\n  isReservedTag,\n  canBeLeftOpenTag,\n  getTagNamespace\n} from '../util/index'\n\nexport const baseOptions: CompilerOptions = {\n  modules,\n  directives,\n  isUnaryTag,\n  mustUseProp,\n  canBeLeftOpenTag,\n  isReservedTag,\n  getTagNamespace,\n  preserveWhitespace: false,\n  staticKeys: genStaticKeys(modules)\n}\n\nconst { compile, compileToFunctions } = createCompiler(baseOptions)\nexport { compile, compileToFunctions }\n"
  },
  {
    "path": "src/platforms/weex/compiler/modules/append.js",
    "content": "/* @flow */\n\nfunction preTransformNode (el: ASTElement, options: CompilerOptions) {\n  if (el.tag === 'cell' && !el.attrsList.some(item => item.name === 'append')) {\n    el.attrsMap.append = 'tree'\n    el.attrsList.push({ name: 'append', value: 'tree' })\n  }\n  if (el.attrsMap.append === 'tree') {\n    el.appendAsTree = true\n  }\n}\n\nfunction genData (el: ASTElement): string {\n  return el.appendAsTree ? `appendAsTree:true,` : ''\n}\n\nexport default {\n  staticKeys: ['appendAsTree'],\n  preTransformNode,\n  genData\n}\n"
  },
  {
    "path": "src/platforms/weex/compiler/modules/class.js",
    "content": "/* @flow */\n\nimport { parseText } from 'compiler/parser/text-parser'\nimport {\n  getAndRemoveAttr,\n  getBindingAttr,\n  baseWarn\n} from 'compiler/helpers'\n\ntype StaticClassResult = {\n  dynamic: boolean,\n  classResult: string\n};\n\nfunction transformNode (el: ASTElement, options: CompilerOptions) {\n  const warn = options.warn || baseWarn\n  const staticClass = getAndRemoveAttr(el, 'class')\n  const { dynamic, classResult } = parseStaticClass(staticClass, options)\n  if (process.env.NODE_ENV !== 'production' && dynamic && staticClass) {\n    warn(\n      `class=\"${staticClass}\": ` +\n      'Interpolation inside attributes has been deprecated. ' +\n      'Use v-bind or the colon shorthand instead.'\n    )\n  }\n  if (!dynamic && classResult) {\n    el.staticClass = classResult\n  }\n  const classBinding = getBindingAttr(el, 'class', false /* getStatic */)\n  if (classBinding) {\n    el.classBinding = classBinding\n  } else if (dynamic) {\n    el.classBinding = classResult\n  }\n}\n\nfunction genData (el: ASTElement): string {\n  let data = ''\n  if (el.staticClass) {\n    data += `staticClass:${el.staticClass},`\n  }\n  if (el.classBinding) {\n    data += `class:${el.classBinding},`\n  }\n  return data\n}\n\nfunction parseStaticClass (staticClass: ?string, options: CompilerOptions): StaticClassResult {\n  // \"a b c\" -> [\"a\", \"b\", \"c\"] => staticClass: [\"a\", \"b\", \"c\"]\n  // \"a {{x}} c\" -> [\"a\", x, \"c\"] => classBinding: '[\"a\", x, \"c\"]'\n  let dynamic = false\n  let classResult = ''\n  if (staticClass) {\n    const classList = staticClass.trim().split(' ').map(name => {\n      const result = parseText(name, options.delimiters)\n      if (result) {\n        dynamic = true\n        return result\n      }\n      return JSON.stringify(name)\n    })\n    if (classList.length) {\n      classResult = '[' + classList.join(',') + ']'\n    }\n  }\n  return { dynamic, classResult }\n}\n\nexport default {\n  staticKeys: ['staticClass'],\n  transformNode,\n  genData\n}\n"
  },
  {
    "path": "src/platforms/weex/compiler/modules/index.js",
    "content": "import klass from './class'\nimport style from './style'\nimport props from './props'\nimport append from './append'\n\nexport default [\n  klass,\n  style,\n  props,\n  append\n]\n"
  },
  {
    "path": "src/platforms/weex/compiler/modules/props.js",
    "content": "/* @flow */\n\nimport { cached, camelize } from 'shared/util'\n\nconst normalize = cached(camelize)\n\nfunction normalizeKeyName (str: string): string {\n  if (str.match(/^v\\-/)) {\n    return str.replace(/(v-[a-z\\-]+\\:)([a-z\\-]+)$/i, ($, directive, prop) => {\n      return directive + normalize(prop)\n    })\n  }\n  return normalize(str)\n}\n\nfunction transformNode (el: ASTElement, options: CompilerOptions) {\n  if (Array.isArray(el.attrsList)) {\n    el.attrsList.forEach(attr => {\n      if (attr.name && attr.name.match(/\\-/)) {\n        const realName = normalizeKeyName(attr.name)\n        if (el.attrsMap) {\n          el.attrsMap[realName] = el.attrsMap[attr.name]\n          delete el.attrsMap[attr.name]\n        }\n        attr.name = realName\n      }\n    })\n  }\n}\nexport default {\n  transformNode\n}\n"
  },
  {
    "path": "src/platforms/weex/compiler/modules/style.js",
    "content": "/* @flow */\n\nimport { cached, camelize } from 'shared/util'\nimport { parseText } from 'compiler/parser/text-parser'\nimport {\n  getAndRemoveAttr,\n  getBindingAttr,\n  baseWarn\n} from 'compiler/helpers'\n\ntype StaticStyleResult = {\n  dynamic: boolean,\n  styleResult: string\n};\n\nconst normalize = cached(camelize)\n\nfunction transformNode (el: ASTElement, options: CompilerOptions) {\n  const warn = options.warn || baseWarn\n  const staticStyle = getAndRemoveAttr(el, 'style')\n  const { dynamic, styleResult } = parseStaticStyle(staticStyle, options)\n  if (process.env.NODE_ENV !== 'production' && dynamic) {\n    warn(\n      `style=\"${String(staticStyle)}\": ` +\n      'Interpolation inside attributes has been deprecated. ' +\n      'Use v-bind or the colon shorthand instead.'\n    )\n  }\n  if (!dynamic && styleResult) {\n    el.staticStyle = styleResult\n  }\n  const styleBinding = getBindingAttr(el, 'style', false /* getStatic */)\n  if (styleBinding) {\n    el.styleBinding = styleBinding\n  } else if (dynamic) {\n    el.styleBinding = styleResult\n  }\n}\n\nfunction genData (el: ASTElement): string {\n  let data = ''\n  if (el.staticStyle) {\n    data += `staticStyle:${el.staticStyle},`\n  }\n  if (el.styleBinding) {\n    data += `style:${el.styleBinding},`\n  }\n  return data\n}\n\nfunction parseStaticStyle (staticStyle: ?string, options: CompilerOptions): StaticStyleResult {\n  // \"width: 200px; height: 200px;\" -> {width: 200, height: 200}\n  // \"width: 200px; height: {{y}}\" -> {width: 200, height: y}\n  let dynamic = false\n  let styleResult = ''\n  if (staticStyle) {\n    const styleList = staticStyle.trim().split(';').map(style => {\n      const result = style.trim().split(':')\n      if (result.length !== 2) {\n        return\n      }\n      const key = normalize(result[0].trim())\n      const value = result[1].trim()\n      const dynamicValue = parseText(value, options.delimiters)\n      if (dynamicValue) {\n        dynamic = true\n        return key + ':' + dynamicValue\n      }\n      return key + ':' + JSON.stringify(value)\n    }).filter(result => result)\n    if (styleList.length) {\n      styleResult = '{' + styleList.join(',') + '}'\n    }\n  }\n  return { dynamic, styleResult }\n}\n\nexport default {\n  staticKeys: ['staticStyle'],\n  transformNode,\n  genData\n}\n"
  },
  {
    "path": "src/platforms/weex/entry-compiler.js",
    "content": "export { compile } from 'weex/compiler/index'\n"
  },
  {
    "path": "src/platforms/weex/entry-framework.js",
    "content": "import TextNode from 'weex/runtime/text-node'\n\n// this will be preserved during build\nconst VueFactory = require('./factory')\n\nconst instances = {}\nconst modules = {}\nconst components = {}\n\nconst renderer = {\n  TextNode,\n  instances,\n  modules,\n  components\n}\n\n/**\n * Prepare framework config, basically about the virtual-DOM and JS bridge.\n * @param {object} cfg\n */\nexport function init (cfg) {\n  renderer.Document = cfg.Document\n  renderer.Element = cfg.Element\n  renderer.Comment = cfg.Comment\n  renderer.compileBundle = cfg.compileBundle\n}\n\n/**\n * Reset framework config and clear all registrations.\n */\nexport function reset () {\n  clear(instances)\n  clear(modules)\n  clear(components)\n  delete renderer.Document\n  delete renderer.Element\n  delete renderer.Comment\n  delete renderer.compileBundle\n}\n\n/**\n * Delete all keys of an object.\n * @param {object} obj\n */\nfunction clear (obj) {\n  for (const key in obj) {\n    delete obj[key]\n  }\n}\n\n/**\n * Create an instance with id, code, config and external data.\n * @param {string} instanceId\n * @param {string} appCode\n * @param {object} config\n * @param {object} data\n * @param {object} env { info, config, services }\n */\nexport function createInstance (\n  instanceId,\n  appCode = '',\n  config = {},\n  data,\n  env = {}\n) {\n  // Virtual-DOM object.\n  const document = new renderer.Document(instanceId, config.bundleUrl)\n\n  const instance = instances[instanceId] = {\n    instanceId, config, data,\n    document\n  }\n\n  // Prepare native module getter and HTML5 Timer APIs.\n  const moduleGetter = genModuleGetter(instanceId)\n  const timerAPIs = getInstanceTimer(instanceId, moduleGetter)\n\n  // Prepare `weex` instance variable.\n  const weexInstanceVar = {\n    config,\n    document,\n    supports,\n    requireModule: moduleGetter\n  }\n  Object.freeze(weexInstanceVar)\n\n  // Each instance has a independent `Vue` module instance\n  const Vue = instance.Vue = createVueModuleInstance(instanceId, moduleGetter)\n\n  // The function which create a closure the JS Bundle will run in.\n  // It will declare some instance variables like `Vue`, HTML5 Timer APIs etc.\n  const instanceVars = Object.assign({\n    Vue,\n    weex: weexInstanceVar,\n    // deprecated\n    __weex_require_module__: weexInstanceVar.requireModule // eslint-disable-line\n  }, timerAPIs, env.services)\n\n  if (!callFunctionNative(instanceVars, appCode)) {\n    // If failed to compile functionBody on native side,\n    // fallback to 'callFunction()'.\n    callFunction(instanceVars, appCode)\n  }\n\n  // Send `createFinish` signal to native.\n  instance.document.taskCenter.send('dom', { action: 'createFinish' }, [])\n}\n\n/**\n * Destroy an instance with id. It will make sure all memory of\n * this instance released and no more leaks.\n * @param {string} instanceId\n */\nexport function destroyInstance (instanceId) {\n  const instance = instances[instanceId]\n  if (instance && instance.app instanceof instance.Vue) {\n    instance.document.destroy()\n    instance.app.$destroy()\n  }\n  delete instances[instanceId]\n}\n\n/**\n * Refresh an instance with id and new top-level component data.\n * It will use `Vue.set` on all keys of the new data. So it's better\n * define all possible meaningful keys when instance created.\n * @param {string} instanceId\n * @param {object} data\n */\nexport function refreshInstance (instanceId, data) {\n  const instance = instances[instanceId]\n  if (!instance || !(instance.app instanceof instance.Vue)) {\n    return new Error(`refreshInstance: instance ${instanceId} not found!`)\n  }\n  for (const key in data) {\n    instance.Vue.set(instance.app, key, data[key])\n  }\n  // Finally `refreshFinish` signal needed.\n  instance.document.taskCenter.send('dom', { action: 'refreshFinish' }, [])\n}\n\n/**\n * Get the JSON object of the root element.\n * @param {string} instanceId\n */\nexport function getRoot (instanceId) {\n  const instance = instances[instanceId]\n  if (!instance || !(instance.app instanceof instance.Vue)) {\n    return new Error(`getRoot: instance ${instanceId} not found!`)\n  }\n  return instance.app.$el.toJSON()\n}\n\nconst jsHandlers = {\n  fireEvent: (id, ...args) => {\n    return fireEvent(instances[id], ...args)\n  },\n  callback: (id, ...args) => {\n    return callback(instances[id], ...args)\n  }\n}\n\nfunction fireEvent (instance, nodeId, type, e, domChanges) {\n  const el = instance.document.getRef(nodeId)\n  if (el) {\n    return instance.document.fireEvent(el, type, e, domChanges)\n  }\n  return new Error(`invalid element reference \"${nodeId}\"`)\n}\n\nfunction callback (instance, callbackId, data, ifKeepAlive) {\n  const result = instance.document.taskCenter.callback(callbackId, data, ifKeepAlive)\n  instance.document.taskCenter.send('dom', { action: 'updateFinish' }, [])\n  return result\n}\n\n/**\n * Accept calls from native (event or callback).\n *\n * @param  {string} id\n * @param  {array} tasks list with `method` and `args`\n */\nexport function receiveTasks (id, tasks) {\n  const instance = instances[id]\n  if (instance && Array.isArray(tasks)) {\n    const results = []\n    tasks.forEach((task) => {\n      const handler = jsHandlers[task.method]\n      const args = [...task.args]\n      /* istanbul ignore else */\n      if (typeof handler === 'function') {\n        args.unshift(id)\n        results.push(handler(...args))\n      }\n    })\n    return results\n  }\n  return new Error(`invalid instance id \"${id}\" or tasks`)\n}\n\n/**\n * Register native modules information.\n * @param {object} newModules\n */\nexport function registerModules (newModules) {\n  for (const name in newModules) {\n    if (!modules[name]) {\n      modules[name] = {}\n    }\n    newModules[name].forEach(method => {\n      if (typeof method === 'string') {\n        modules[name][method] = true\n      } else {\n        modules[name][method.name] = method.args\n      }\n    })\n  }\n}\n\n/**\n * Check whether the module or the method has been registered.\n * @param {String} module name\n * @param {String} method name (optional)\n */\nexport function isRegisteredModule (name, method) {\n  if (typeof method === 'string') {\n    return !!(modules[name] && modules[name][method])\n  }\n  return !!modules[name]\n}\n\n/**\n * Register native components information.\n * @param {array} newComponents\n */\nexport function registerComponents (newComponents) {\n  if (Array.isArray(newComponents)) {\n    newComponents.forEach(component => {\n      if (!component) {\n        return\n      }\n      if (typeof component === 'string') {\n        components[component] = true\n      } else if (typeof component === 'object' && typeof component.type === 'string') {\n        components[component.type] = component\n      }\n    })\n  }\n}\n\n/**\n * Check whether the component has been registered.\n * @param {String} component name\n */\nexport function isRegisteredComponent (name) {\n  return !!components[name]\n}\n\n/**\n * Detects whether Weex supports specific features.\n * @param {String} condition\n */\nexport function supports (condition) {\n  if (typeof condition !== 'string') return null\n\n  const res = condition.match(/^@(\\w+)\\/(\\w+)(\\.(\\w+))?$/i)\n  if (res) {\n    const type = res[1]\n    const name = res[2]\n    const method = res[4]\n    switch (type) {\n      case 'module': return isRegisteredModule(name, method)\n      case 'component': return isRegisteredComponent(name)\n    }\n  }\n\n  return null\n}\n\n/**\n * Create a fresh instance of Vue for each Weex instance.\n */\nfunction createVueModuleInstance (instanceId, moduleGetter) {\n  const exports = {}\n  VueFactory(exports, renderer)\n  const Vue = exports.Vue\n\n  const instance = instances[instanceId]\n\n  // patch reserved tag detection to account for dynamically registered\n  // components\n  const isReservedTag = Vue.config.isReservedTag || (() => false)\n  Vue.config.isReservedTag = name => {\n    return components[name] || isReservedTag(name)\n  }\n\n  // expose weex-specific info\n  Vue.prototype.$instanceId = instanceId\n  Vue.prototype.$document = instance.document\n\n  // expose weex native module getter on subVue prototype so that\n  // vdom runtime modules can access native modules via vnode.context\n  Vue.prototype.$requireWeexModule = moduleGetter\n\n  // Hack `Vue` behavior to handle instance information and data\n  // before root component created.\n  Vue.mixin({\n    beforeCreate () {\n      const options = this.$options\n      // root component (vm)\n      if (options.el) {\n        // set external data of instance\n        const dataOption = options.data\n        const internalData = (typeof dataOption === 'function' ? dataOption() : dataOption) || {}\n        options.data = Object.assign(internalData, instance.data)\n        // record instance by id\n        instance.app = this\n      }\n    }\n  })\n\n  /**\n   * @deprecated Just instance variable `weex.config`\n   * Get instance config.\n   * @return {object}\n   */\n  Vue.prototype.$getConfig = function () {\n    if (instance.app instanceof Vue) {\n      return instance.config\n    }\n  }\n\n  return Vue\n}\n\n/**\n * Generate native module getter. Each native module has several\n * methods to call. And all the behaviors is instance-related. So\n * this getter will return a set of methods which additionally\n * send current instance id to native when called.\n * @param  {string}  instanceId\n * @return {function}\n */\nfunction genModuleGetter (instanceId) {\n  const instance = instances[instanceId]\n  return function (name) {\n    const nativeModule = modules[name] || []\n    const output = {}\n    for (const methodName in nativeModule) {\n      Object.defineProperty(output, methodName, {\n        enumerable: true,\n        configurable: true,\n        get: function proxyGetter () {\n          return (...args) => {\n            return instance.document.taskCenter.send('module', { module: name, method: methodName }, args)\n          }\n        },\n        set: function proxySetter (val) {\n          if (typeof val === 'function') {\n            return instance.document.taskCenter.send('module', { module: name, method: methodName }, [val])\n          }\n        }\n      })\n    }\n    return output\n  }\n}\n\n/**\n * Generate HTML5 Timer APIs. An important point is that the callback\n * will be converted into callback id when sent to native. So the\n * framework can make sure no side effect of the callback happened after\n * an instance destroyed.\n * @param  {[type]} instanceId   [description]\n * @param  {[type]} moduleGetter [description]\n * @return {[type]}              [description]\n */\nfunction getInstanceTimer (instanceId, moduleGetter) {\n  const instance = instances[instanceId]\n  const timer = moduleGetter('timer')\n  const timerAPIs = {\n    setTimeout: (...args) => {\n      const handler = function () {\n        args[0](...args.slice(2))\n      }\n\n      timer.setTimeout(handler, args[1])\n      return instance.document.taskCenter.callbackManager.lastCallbackId.toString()\n    },\n    setInterval: (...args) => {\n      const handler = function () {\n        args[0](...args.slice(2))\n      }\n\n      timer.setInterval(handler, args[1])\n      return instance.document.taskCenter.callbackManager.lastCallbackId.toString()\n    },\n    clearTimeout: (n) => {\n      timer.clearTimeout(n)\n    },\n    clearInterval: (n) => {\n      timer.clearInterval(n)\n    }\n  }\n  return timerAPIs\n}\n\n/**\n * Call a new function body with some global objects.\n * @param  {object} globalObjects\n * @param  {string} code\n * @return {any}\n */\nfunction callFunction (globalObjects, body) {\n  const globalKeys = []\n  const globalValues = []\n  for (const key in globalObjects) {\n    globalKeys.push(key)\n    globalValues.push(globalObjects[key])\n  }\n  globalKeys.push(body)\n\n  const result = new Function(...globalKeys)\n  return result(...globalValues)\n}\n\n/**\n * Call a new function generated on the V8 native side.\n *\n * This function helps speed up bundle compiling. Normally, the V8\n * engine needs to download, parse, and compile a bundle on every\n * visit. If 'compileBundle()' is available on native side,\n * the downloding, parsing, and compiling steps would be skipped.\n * @param  {object} globalObjects\n * @param  {string} body\n * @return {boolean}\n */\nfunction callFunctionNative (globalObjects, body) {\n  if (typeof renderer.compileBundle !== 'function') {\n    return false\n  }\n\n  let fn = void 0\n  let isNativeCompileOk = false\n  let script = '(function ('\n  const globalKeys = []\n  const globalValues = []\n  for (const key in globalObjects) {\n    globalKeys.push(key)\n    globalValues.push(globalObjects[key])\n  }\n  for (let i = 0; i < globalKeys.length - 1; ++i) {\n    script += globalKeys[i]\n    script += ','\n  }\n  script += globalKeys[globalKeys.length - 1]\n  script += ') {'\n  script += body\n  script += '} )'\n\n  try {\n    const weex = globalObjects.weex || {}\n    const config = weex.config || {}\n    fn = renderer.compileBundle(script,\n      config.bundleUrl,\n      config.bundleDigest,\n      config.codeCachePath)\n    if (fn && typeof fn === 'function') {\n      fn(...globalValues)\n      isNativeCompileOk = true\n    }\n  } catch (e) {\n    console.error(e)\n  }\n\n  return isNativeCompileOk\n}\n"
  },
  {
    "path": "src/platforms/weex/entry-runtime-factory.js",
    "content": "// this entry is built and wrapped with a factory function\n// used to generate a fresh copy of Vue for every Weex instance.\n\nimport Vue from './runtime/index'\n\nexports.Vue = Vue\n"
  },
  {
    "path": "src/platforms/weex/runtime/components/index.js",
    "content": "import Transition from './transition'\nimport TransitionGroup from './transition-group'\n\nexport default {\n  Transition,\n  TransitionGroup\n}\n"
  },
  {
    "path": "src/platforms/weex/runtime/components/transition-group.js",
    "content": "import { warn, extend } from 'core/util/index'\nimport { transitionProps, extractTransitionData } from './transition'\n\nconst props = extend({\n  tag: String,\n  moveClass: String\n}, transitionProps)\n\ndelete props.mode\n\nexport default {\n  props,\n\n  created () {\n    const dom = this.$requireWeexModule('dom')\n    this.getPosition = el => new Promise((resolve, reject) => {\n      dom.getComponentRect(el.ref, res => {\n        if (!res.result) {\n          reject(new Error(`failed to get rect for element: ${el.tag}`))\n        } else {\n          resolve(res.size)\n        }\n      })\n    })\n\n    const animation = this.$requireWeexModule('animation')\n    this.animate = (el, options) => new Promise(resolve => {\n      animation.transition(el.ref, options, resolve)\n    })\n  },\n\n  render (h) {\n    const tag = this.tag || this.$vnode.data.tag || 'span'\n    const map = Object.create(null)\n    const prevChildren = this.prevChildren = this.children\n    const rawChildren = this.$slots.default || []\n    const children = this.children = []\n    const transitionData = extractTransitionData(this)\n\n    for (let i = 0; i < rawChildren.length; i++) {\n      const c = rawChildren[i]\n      if (c.tag) {\n        if (c.key != null && String(c.key).indexOf('__vlist') !== 0) {\n          children.push(c)\n          map[c.key] = c\n          ;(c.data || (c.data = {})).transition = transitionData\n        } else if (process.env.NODE_ENV !== 'production') {\n          const opts = c.componentOptions\n          const name = opts\n            ? (opts.Ctor.options.name || opts.tag)\n            : c.tag\n          warn(`<transition-group> children must be keyed: <${name}>`)\n        }\n      }\n    }\n\n    if (prevChildren) {\n      const kept = []\n      const removed = []\n      prevChildren.forEach(c => {\n        c.data.transition = transitionData\n\n        // TODO: record before patch positions\n\n        if (map[c.key]) {\n          kept.push(c)\n        } else {\n          removed.push(c)\n        }\n      })\n      this.kept = h(tag, null, kept)\n      this.removed = removed\n    }\n\n    return h(tag, null, children)\n  },\n\n  beforeUpdate () {\n    // force removing pass\n    this.__patch__(\n      this._vnode,\n      this.kept,\n      false, // hydrating\n      true // removeOnly (!important, avoids unnecessary moves)\n    )\n    this._vnode = this.kept\n  },\n\n  updated () {\n    const children = this.prevChildren\n    const moveClass = this.moveClass || ((this.name || 'v') + '-move')\n    const moveData = children.length && this.getMoveData(children[0].context, moveClass)\n    if (!moveData) {\n      return\n    }\n\n    // TODO: finish implementing move animations once\n    // we have access to sync getComponentRect()\n\n    // children.forEach(callPendingCbs)\n\n    // Promise.all(children.map(c => {\n    //   const oldPos = c.data.pos\n    //   const newPos = c.data.newPos\n    //   const dx = oldPos.left - newPos.left\n    //   const dy = oldPos.top - newPos.top\n    //   if (dx || dy) {\n    //     c.data.moved = true\n    //     return this.animate(c.elm, {\n    //       styles: {\n    //         transform: `translate(${dx}px,${dy}px)`\n    //       }\n    //     })\n    //   }\n    // })).then(() => {\n    //   children.forEach(c => {\n    //     if (c.data.moved) {\n    //       this.animate(c.elm, {\n    //         styles: {\n    //           transform: ''\n    //         },\n    //         duration: moveData.duration || 0,\n    //         delay: moveData.delay || 0,\n    //         timingFunction: moveData.timingFunction || 'linear'\n    //       })\n    //     }\n    //   })\n    // })\n  },\n\n  methods: {\n    getMoveData (context, moveClass) {\n      const stylesheet = context.$options.style || {}\n      return stylesheet['@TRANSITION'] && stylesheet['@TRANSITION'][moveClass]\n    }\n  }\n}\n\n// function callPendingCbs (c) {\n//   /* istanbul ignore if */\n//   if (c.elm._moveCb) {\n//     c.elm._moveCb()\n//   }\n//   /* istanbul ignore if */\n//   if (c.elm._enterCb) {\n//     c.elm._enterCb()\n//   }\n// }\n"
  },
  {
    "path": "src/platforms/weex/runtime/components/transition.js",
    "content": "// reuse same transition component logic from web\nexport {\n  transitionProps,\n  extractTransitionData\n} from 'web/runtime/components/transition'\n\nimport Transition from 'web/runtime/components/transition'\n\nexport default Transition\n"
  },
  {
    "path": "src/platforms/weex/runtime/directives/index.js",
    "content": "export default {\n}\n"
  },
  {
    "path": "src/platforms/weex/runtime/index.js",
    "content": "/* @flow */\n\nimport Vue from 'core/index'\nimport { patch } from 'weex/runtime/patch'\nimport { mountComponent } from 'core/instance/lifecycle'\nimport platformDirectives from 'weex/runtime/directives/index'\nimport platformComponents from 'weex/runtime/components/index'\n\nimport {\n  query,\n  mustUseProp,\n  isReservedTag,\n  isUnknownElement\n} from 'weex/util/index'\n\n// install platform specific utils\nVue.config.mustUseProp = mustUseProp\nVue.config.isReservedTag = isReservedTag\nVue.config.isUnknownElement = isUnknownElement\n\n// install platform runtime directives and components\nVue.options.directives = platformDirectives\nVue.options.components = platformComponents\n\n// install platform patch function\nVue.prototype.__patch__ = patch\n\n// wrap mount\nVue.prototype.$mount = function (\n  el?: any,\n  hydrating?: boolean\n): Component {\n  return mountComponent(\n    this,\n    el && query(el, this.$document),\n    hydrating\n  )\n}\n\nexport default Vue\n"
  },
  {
    "path": "src/platforms/weex/runtime/modules/attrs.js",
    "content": "/* @flow */\n\nimport { extend } from 'shared/util'\n\nfunction updateAttrs (oldVnode: VNodeWithData, vnode: VNodeWithData) {\n  if (!oldVnode.data.attrs && !vnode.data.attrs) {\n    return\n  }\n  let key, cur, old\n  const elm = vnode.elm\n  const oldAttrs = oldVnode.data.attrs || {}\n  let attrs = vnode.data.attrs || {}\n  // clone observed objects, as the user probably wants to mutate it\n  if (attrs.__ob__) {\n    attrs = vnode.data.attrs = extend({}, attrs)\n  }\n\n  for (key in attrs) {\n    cur = attrs[key]\n    old = oldAttrs[key]\n    if (old !== cur) {\n      elm.setAttr(key, cur)\n    }\n  }\n  for (key in oldAttrs) {\n    if (attrs[key] == null) {\n      elm.setAttr(key)\n    }\n  }\n}\n\nexport default {\n  create: updateAttrs,\n  update: updateAttrs\n}\n"
  },
  {
    "path": "src/platforms/weex/runtime/modules/class.js",
    "content": "/* @flow */\n\nimport { extend } from 'shared/util'\n\nfunction updateClass (oldVnode: VNodeWithData, vnode: VNodeWithData) {\n  const el = vnode.elm\n  const ctx = vnode.context\n\n  const data: VNodeData = vnode.data\n  const oldData: VNodeData = oldVnode.data\n  if (!data.staticClass &&\n    !data.class &&\n    (!oldData || (!oldData.staticClass && !oldData.class))\n  ) {\n    return\n  }\n\n  const oldClassList = []\n  // unlike web, weex vnode staticClass is an Array\n  const oldStaticClass: any = oldData.staticClass\n  if (oldStaticClass) {\n    oldClassList.push.apply(oldClassList, oldStaticClass)\n  }\n  if (oldData.class) {\n    oldClassList.push.apply(oldClassList, oldData.class)\n  }\n\n  const classList = []\n  // unlike web, weex vnode staticClass is an Array\n  const staticClass: any = data.staticClass\n  if (staticClass) {\n    classList.push.apply(classList, staticClass)\n  }\n  if (data.class) {\n    classList.push.apply(classList, data.class)\n  }\n\n  const style = getStyle(oldClassList, classList, ctx)\n  for (const key in style) {\n    el.setStyle(key, style[key])\n  }\n}\n\nfunction getStyle (oldClassList: Array<string>, classList: Array<string>, ctx: Component): Object {\n  // style is a weex-only injected object\n  // compiled from <style> tags in weex files\n  const stylesheet: any = ctx.$options.style || {}\n  const result = {}\n  classList.forEach(name => {\n    const style = stylesheet[name]\n    extend(result, style)\n  })\n  oldClassList.forEach(name => {\n    const style = stylesheet[name]\n    for (const key in style) {\n      if (!result.hasOwnProperty(key)) {\n        result[key] = ''\n      }\n    }\n  })\n  return result\n}\n\nexport default {\n  create: updateClass,\n  update: updateClass\n}\n"
  },
  {
    "path": "src/platforms/weex/runtime/modules/events.js",
    "content": "/* @flow */\n\nimport { updateListeners } from 'core/vdom/helpers/update-listeners'\n\nlet target: any\n\nfunction add (\n  event: string,\n  handler: Function,\n  once: boolean,\n  capture: boolean\n) {\n  if (capture) {\n    console.log('Weex do not support event in bubble phase.')\n    return\n  }\n  if (once) {\n    const oldHandler = handler\n    const _target = target // save current target element in closure\n    handler = function (ev) {\n      const res = arguments.length === 1\n        ? oldHandler(ev)\n        : oldHandler.apply(null, arguments)\n      if (res !== null) {\n        remove(event, null, null, _target)\n      }\n    }\n  }\n  target.addEvent(event, handler)\n}\n\nfunction remove (\n  event: string,\n  handler: any,\n  capture: any,\n  _target?: any\n) {\n  (_target || target).removeEvent(event)\n}\n\nfunction updateDOMListeners (oldVnode: VNodeWithData, vnode: VNodeWithData) {\n  const isComponentRoot = !!vnode.componentOptions\n  let oldOn = isComponentRoot ? oldVnode.data.nativeOn : oldVnode.data.on\n  let on = isComponentRoot ? vnode.data.nativeOn : vnode.data.on\n  if (!oldOn && !on) {\n    return\n  }\n  on = on || {}\n  oldOn = oldOn || {}\n  target = vnode.elm\n  updateListeners(on, oldOn, add, remove, vnode.context)\n}\n\nexport default {\n  create: updateDOMListeners,\n  update: updateDOMListeners\n}\n"
  },
  {
    "path": "src/platforms/weex/runtime/modules/index.js",
    "content": "import attrs from './attrs'\nimport klass from './class'\nimport events from './events'\nimport style from './style'\nimport transition from './transition'\n\nexport default [\n  attrs,\n  klass,\n  events,\n  style,\n  transition\n]\n"
  },
  {
    "path": "src/platforms/weex/runtime/modules/style.js",
    "content": "/* @flow */\n\nimport { extend, cached, camelize } from 'shared/util'\n\nconst normalize = cached(camelize)\n\nfunction createStyle (oldVnode: VNodeWithData, vnode: VNodeWithData) {\n  if (!vnode.data.staticStyle) {\n    updateStyle(oldVnode, vnode)\n    return\n  }\n  const elm = vnode.elm\n  const staticStyle = vnode.data.staticStyle\n  for (const name in staticStyle) {\n    if (staticStyle[name]) {\n      elm.setStyle(normalize(name), staticStyle[name])\n    }\n  }\n  updateStyle(oldVnode, vnode)\n}\n\nfunction updateStyle (oldVnode: VNodeWithData, vnode: VNodeWithData) {\n  if (!oldVnode.data.style && !vnode.data.style) {\n    return\n  }\n  let cur, name\n  const elm = vnode.elm\n  const oldStyle: any = oldVnode.data.style || {}\n  let style: any = vnode.data.style || {}\n\n  const needClone = style.__ob__\n\n  // handle array syntax\n  if (Array.isArray(style)) {\n    style = vnode.data.style = toObject(style)\n  }\n\n  // clone the style for future updates,\n  // in case the user mutates the style object in-place.\n  if (needClone) {\n    style = vnode.data.style = extend({}, style)\n  }\n\n  for (name in oldStyle) {\n    if (!style[name]) {\n      elm.setStyle(normalize(name), '')\n    }\n  }\n  for (name in style) {\n    cur = style[name]\n    elm.setStyle(normalize(name), cur)\n  }\n}\n\nfunction toObject (arr) {\n  const res = {}\n  for (var i = 0; i < arr.length; i++) {\n    if (arr[i]) {\n      extend(res, arr[i])\n    }\n  }\n  return res\n}\n\nexport default {\n  create: createStyle,\n  update: updateStyle\n}\n"
  },
  {
    "path": "src/platforms/weex/runtime/modules/transition.js",
    "content": "import { warn } from 'core/util/debug'\nimport { extend, once, noop } from 'shared/util'\nimport { activeInstance } from 'core/instance/lifecycle'\nimport { resolveTransition } from 'web/runtime/transition-util'\n\nexport default {\n  create: enter,\n  activate: enter,\n  remove: leave\n}\n\nfunction enter (_, vnode) {\n  const el = vnode.elm\n\n  // call leave callback now\n  if (el._leaveCb) {\n    el._leaveCb.cancelled = true\n    el._leaveCb()\n  }\n\n  const data = resolveTransition(vnode.data.transition)\n  if (!data) {\n    return\n  }\n\n  /* istanbul ignore if */\n  if (el._enterCb) {\n    return\n  }\n\n  const {\n    enterClass,\n    enterToClass,\n    enterActiveClass,\n    appearClass,\n    appearToClass,\n    appearActiveClass,\n    beforeEnter,\n    enter,\n    afterEnter,\n    enterCancelled,\n    beforeAppear,\n    appear,\n    afterAppear,\n    appearCancelled\n  } = data\n\n  let context = activeInstance\n  let transitionNode = activeInstance.$vnode\n  while (transitionNode && transitionNode.parent) {\n    transitionNode = transitionNode.parent\n    context = transitionNode.context\n  }\n\n  const isAppear = !context._isMounted || !vnode.isRootInsert\n\n  if (isAppear && !appear && appear !== '') {\n    return\n  }\n\n  const startClass = isAppear ? appearClass : enterClass\n  const toClass = isAppear ? appearToClass : enterToClass\n  const activeClass = isAppear ? appearActiveClass : enterActiveClass\n  const beforeEnterHook = isAppear ? (beforeAppear || beforeEnter) : beforeEnter\n  const enterHook = isAppear ? (typeof appear === 'function' ? appear : enter) : enter\n  const afterEnterHook = isAppear ? (afterAppear || afterEnter) : afterEnter\n  const enterCancelledHook = isAppear ? (appearCancelled || enterCancelled) : enterCancelled\n\n  const userWantsControl =\n    enterHook &&\n    // enterHook may be a bound method which exposes\n    // the length of original fn as _length\n    (enterHook._length || enterHook.length) > 1\n\n  const stylesheet = vnode.context.$options.style || {}\n  const startState = stylesheet[startClass]\n  const transitionProperties = (stylesheet['@TRANSITION'] && stylesheet['@TRANSITION'][activeClass]) || {}\n  const endState = getEnterTargetState(el, stylesheet, startClass, toClass, activeClass, vnode.context)\n  const needAnimation = Object.keys(endState).length > 0\n\n  const cb = el._enterCb = once(() => {\n    if (cb.cancelled) {\n      enterCancelledHook && enterCancelledHook(el)\n    } else {\n      afterEnterHook && afterEnterHook(el)\n    }\n    el._enterCb = null\n  })\n\n  // We need to wait until the native element has been inserted, but currently\n  // there's no API to do that. So we have to wait \"one frame\" - not entirely\n  // sure if this is guaranteed to be enough (e.g. on slow devices?)\n  setTimeout(() => {\n    const parent = el.parentNode\n    const pendingNode = parent && parent._pending && parent._pending[vnode.key]\n    if (pendingNode &&\n      pendingNode.context === vnode.context &&\n      pendingNode.tag === vnode.tag &&\n      pendingNode.elm._leaveCb\n    ) {\n      pendingNode.elm._leaveCb()\n    }\n    enterHook && enterHook(el, cb)\n\n    if (needAnimation) {\n      const animation = vnode.context.$requireWeexModule('animation')\n      animation.transition(el.ref, {\n        styles: endState,\n        duration: transitionProperties.duration || 0,\n        delay: transitionProperties.delay || 0,\n        timingFunction: transitionProperties.timingFunction || 'linear'\n      }, userWantsControl ? noop : cb)\n    } else if (!userWantsControl) {\n      cb()\n    }\n  }, 16)\n\n  // start enter transition\n  beforeEnterHook && beforeEnterHook(el)\n\n  if (startState) {\n    for (const key in startState) {\n      el.setStyle(key, startState[key])\n    }\n  }\n\n  if (!needAnimation && !userWantsControl) {\n    cb()\n  }\n}\n\nfunction leave (vnode, rm) {\n  const el = vnode.elm\n\n  // call enter callback now\n  if (el._enterCb) {\n    el._enterCb.cancelled = true\n    el._enterCb()\n  }\n\n  const data = resolveTransition(vnode.data.transition)\n  if (!data) {\n    return rm()\n  }\n\n  if (el._leaveCb) {\n    return\n  }\n\n  const {\n    leaveClass,\n    leaveToClass,\n    leaveActiveClass,\n    beforeLeave,\n    leave,\n    afterLeave,\n    leaveCancelled,\n    delayLeave\n  } = data\n\n  const userWantsControl =\n    leave &&\n    // leave hook may be a bound method which exposes\n    // the length of original fn as _length\n    (leave._length || leave.length) > 1\n\n  const stylesheet = vnode.context.$options.style || {}\n  const startState = stylesheet[leaveClass]\n  const endState = stylesheet[leaveToClass] || stylesheet[leaveActiveClass]\n  const transitionProperties = (stylesheet['@TRANSITION'] && stylesheet['@TRANSITION'][leaveActiveClass]) || {}\n\n  const cb = el._leaveCb = once(() => {\n    if (el.parentNode && el.parentNode._pending) {\n      el.parentNode._pending[vnode.key] = null\n    }\n    if (cb.cancelled) {\n      leaveCancelled && leaveCancelled(el)\n    } else {\n      rm()\n      afterLeave && afterLeave(el)\n    }\n    el._leaveCb = null\n  })\n\n  if (delayLeave) {\n    delayLeave(performLeave)\n  } else {\n    performLeave()\n  }\n\n  function performLeave () {\n    const animation = vnode.context.$requireWeexModule('animation')\n    // the delayed leave may have already been cancelled\n    if (cb.cancelled) {\n      return\n    }\n    // record leaving element\n    if (!vnode.data.show) {\n      (el.parentNode._pending || (el.parentNode._pending = {}))[vnode.key] = vnode\n    }\n    beforeLeave && beforeLeave(el)\n\n    if (startState) {\n      animation.transition(el.ref, {\n        styles: startState\n      }, next)\n    } else {\n      next()\n    }\n\n    function next () {\n      animation.transition(el.ref, {\n        styles: endState,\n        duration: transitionProperties.duration || 0,\n        delay: transitionProperties.delay || 0,\n        timingFunction: transitionProperties.timingFunction || 'linear'\n      }, userWantsControl ? noop : cb)\n    }\n\n    leave && leave(el, cb)\n    if (!endState && !userWantsControl) {\n      cb()\n    }\n  }\n}\n\n// determine the target animation style for an entering transition.\nfunction getEnterTargetState (el, stylesheet, startClass, endClass, activeClass, vm) {\n  const targetState = {}\n  const startState = stylesheet[startClass]\n  const endState = stylesheet[endClass]\n  const activeState = stylesheet[activeClass]\n  // 1. fallback to element's default styling\n  if (startState) {\n    for (const key in startState) {\n      targetState[key] = el.style[key]\n      if (\n        process.env.NODE_ENV !== 'production' &&\n        targetState[key] == null &&\n        (!activeState || activeState[key] == null) &&\n        (!endState || endState[key] == null)\n      ) {\n        warn(\n          `transition property \"${key}\" is declared in enter starting class (.${startClass}), ` +\n          `but not declared anywhere in enter ending class (.${endClass}), ` +\n          `enter active cass (.${activeClass}) or the element's default styling. ` +\n          `Note in Weex, CSS properties need explicit values to be transitionable.`\n        )\n      }\n    }\n  }\n  // 2. if state is mixed in active state, extract them while excluding\n  //    transition properties\n  if (activeState) {\n    for (const key in activeState) {\n      if (key.indexOf('transition') !== 0) {\n        targetState[key] = activeState[key]\n      }\n    }\n  }\n  // 3. explicit endState has highest priority\n  if (endState) {\n    extend(targetState, endState)\n  }\n  return targetState\n}\n"
  },
  {
    "path": "src/platforms/weex/runtime/node-ops.js",
    "content": "/* globals renderer */\n// renderer is injected by weex factory wrapper\n\nexport const namespaceMap = {}\n\nexport function createElement (tagName) {\n  return new renderer.Element(tagName)\n}\n\nexport function createElementNS (namespace, tagName) {\n  return new renderer.Element(namespace + ':' + tagName)\n}\n\nexport function createTextNode (text) {\n  return new renderer.TextNode(text)\n}\n\nexport function createComment (text) {\n  return new renderer.Comment(text)\n}\n\nexport function insertBefore (node, target, before) {\n  if (target.nodeType === 3) {\n    if (node.type === 'text') {\n      node.setAttr('value', target.text)\n      target.parentNode = node\n    } else {\n      const text = createElement('text')\n      text.setAttr('value', target.text)\n      node.insertBefore(text, before)\n    }\n    return\n  }\n  node.insertBefore(target, before)\n}\n\nexport function removeChild (node, child) {\n  if (child.nodeType === 3) {\n    node.setAttr('value', '')\n    return\n  }\n  node.removeChild(child)\n}\n\nexport function appendChild (node, child) {\n  if (child.nodeType === 3) {\n    if (node.type === 'text') {\n      node.setAttr('value', child.text)\n      child.parentNode = node\n    } else {\n      const text = createElement('text')\n      text.setAttr('value', child.text)\n      node.appendChild(text)\n    }\n    return\n  }\n\n  node.appendChild(child)\n}\n\nexport function parentNode (node) {\n  return node.parentNode\n}\n\nexport function nextSibling (node) {\n  return node.nextSibling\n}\n\nexport function tagName (node) {\n  return node.type\n}\n\nexport function setTextContent (node, text) {\n  node.parentNode.setAttr('value', text)\n}\n\nexport function setAttribute (node, key, val) {\n  node.setAttr(key, val)\n}\n"
  },
  {
    "path": "src/platforms/weex/runtime/patch.js",
    "content": "/* @flow */\n\nimport * as nodeOps from 'weex/runtime/node-ops'\nimport { createPatchFunction } from 'core/vdom/patch'\nimport baseModules from 'core/vdom/modules/index'\nimport platformModules from 'weex/runtime/modules/index'\n\n// the directive module should be applied last, after all\n// built-in modules have been applied.\nconst modules = platformModules.concat(baseModules)\n\nexport const patch: Function = createPatchFunction({\n  nodeOps,\n  modules,\n  LONG_LIST_THRESHOLD: 10\n})\n"
  },
  {
    "path": "src/platforms/weex/runtime/text-node.js",
    "content": "let latestNodeId = 1\n\nexport default function TextNode (text) {\n  this.instanceId = ''\n  this.nodeId = latestNodeId++\n  this.parentNode = null\n  this.nodeType = 3\n  this.text = text\n}\n"
  },
  {
    "path": "src/platforms/weex/util/index.js",
    "content": "/* globals renderer */\n\nimport { makeMap } from 'shared/util'\n\nexport const isReservedTag = makeMap(\n  'template,script,style,element,content,slot,link,meta,svg,view,' +\n  'a,div,img,image,text,span,richtext,input,switch,textarea,spinner,select,' +\n  'slider,slider-neighbor,indicator,trisition,trisition-group,canvas,' +\n  'list,cell,header,loading,loading-indicator,refresh,scrollable,scroller,' +\n  'video,web,embed,tabbar,tabheader,datepicker,timepicker,marquee,countdown',\n  true\n)\n\n// Elements that you can, intentionally, leave open (and which close themselves)\n// more flexable than web\nexport const canBeLeftOpenTag = makeMap(\n  'web,spinner,switch,video,textarea,canvas,' +\n  'indicator,marquee,countdown',\n  true\n)\n\nexport const isUnaryTag = makeMap(\n  'embed,img,image,input,link,meta',\n  true\n)\n\nexport function mustUseProp () { /* console.log('mustUseProp') */ }\nexport function getTagNamespace () { /* console.log('getTagNamespace') */ }\nexport function isUnknownElement () { /* console.log('isUnknownElement') */ }\n\nexport function query (el, document) {\n  // renderer is injected by weex factory wrapper\n  const placeholder = new renderer.Comment('root')\n  placeholder.hasAttribute = placeholder.removeAttribute = function () {} // hack for patch\n  document.documentElement.appendChild(placeholder)\n  return placeholder\n}\n"
  },
  {
    "path": "src/server/bundle-renderer/create-bundle-renderer.js",
    "content": "/* @flow */\n\nimport { createBundleRunner } from './create-bundle-runner'\nimport type { Renderer, RenderOptions } from '../create-renderer'\nimport { createSourceMapConsumers, rewriteErrorTrace } from './source-map-support'\n\nconst fs = require('fs')\nconst path = require('path')\nconst PassThrough = require('stream').PassThrough\n\nconst INVALID_MSG =\n  'Invalid server-rendering bundle format. Should be a string ' +\n  'or a bundle Object of type:\\n\\n' +\n`{\n  entry: string;\n  files: { [filename: string]: string; };\n  maps: { [filename: string]: string; };\n}\\n`\n\n// The render bundle can either be a string (single bundled file)\n// or a bundle manifest object generated by vue-ssr-webpack-plugin.\ntype RenderBundle = {\n  basedir?: string;\n  entry: string;\n  files: { [filename: string]: string; };\n  maps: { [filename: string]: string; };\n  modules?: { [filename: string]: Array<string> };\n};\n\nexport function createBundleRendererCreator (\n  createRenderer: (options?: RenderOptions) => Renderer\n) {\n  return function createBundleRenderer (\n    bundle: string | RenderBundle,\n    rendererOptions?: RenderOptions = {}\n  ) {\n    let files, entry, maps\n    let basedir = rendererOptions.basedir\n\n    // load bundle if given filepath\n    if (\n      typeof bundle === 'string' &&\n      /\\.js(on)?$/.test(bundle) &&\n      path.isAbsolute(bundle)\n    ) {\n      if (fs.existsSync(bundle)) {\n        const isJSON = /\\.json$/.test(bundle)\n        basedir = basedir || path.dirname(bundle)\n        bundle = fs.readFileSync(bundle, 'utf-8')\n        if (isJSON) {\n          try {\n            bundle = JSON.parse(bundle)\n          } catch (e) {\n            throw new Error(`Invalid JSON bundle file: ${bundle}`)\n          }\n        }\n      } else {\n        throw new Error(`Cannot locate bundle file: ${bundle}`)\n      }\n    }\n\n    if (typeof bundle === 'object') {\n      entry = bundle.entry\n      files = bundle.files\n      basedir = basedir || bundle.basedir\n      maps = createSourceMapConsumers(bundle.maps)\n      if (typeof entry !== 'string' || typeof files !== 'object') {\n        throw new Error(INVALID_MSG)\n      }\n    } else if (typeof bundle === 'string') {\n      entry = '__vue_ssr_bundle__'\n      files = { '__vue_ssr_bundle__': bundle }\n      maps = {}\n    } else {\n      throw new Error(INVALID_MSG)\n    }\n\n    const renderer = createRenderer(rendererOptions)\n\n    const run = createBundleRunner(\n      entry,\n      files,\n      basedir,\n      rendererOptions.runInNewContext\n    )\n\n    return {\n      renderToString: (context?: Object, cb: (err: ?Error, res: ?string) => void) => {\n        if (typeof context === 'function') {\n          cb = context\n          context = {}\n        }\n        run(context).catch(err => {\n          rewriteErrorTrace(err, maps)\n          cb(err)\n        }).then(app => {\n          if (app) {\n            renderer.renderToString(app, context, (err, res) => {\n              rewriteErrorTrace(err, maps)\n              cb(err, res)\n            })\n          }\n        })\n      },\n\n      renderToStream: (context?: Object) => {\n        const res = new PassThrough()\n        run(context).catch(err => {\n          rewriteErrorTrace(err, maps)\n          // avoid emitting synchronously before user can\n          // attach error listener\n          process.nextTick(() => {\n            res.emit('error', err)\n          })\n        }).then(app => {\n          if (app) {\n            const renderStream = renderer.renderToStream(app, context)\n\n            renderStream.on('error', err => {\n              rewriteErrorTrace(err, maps)\n              res.emit('error', err)\n            })\n\n            // relay HTMLStream special events\n            if (rendererOptions && rendererOptions.template) {\n              renderStream.on('beforeStart', () => {\n                res.emit('beforeStart')\n              })\n              renderStream.on('beforeEnd', () => {\n                res.emit('beforeEnd')\n              })\n            }\n\n            renderStream.pipe(res)\n          }\n        })\n\n        return res\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "src/server/bundle-renderer/create-bundle-runner.js",
    "content": "import { isPlainObject } from 'shared/util'\n\nconst vm = require('vm')\nconst path = require('path')\nconst resolve = require('resolve')\nconst NativeModule = require('module')\n\nfunction createSandbox (context) {\n  const sandbox = {\n    Buffer,\n    console,\n    process,\n    setTimeout,\n    setInterval,\n    setImmediate,\n    clearTimeout,\n    clearInterval,\n    clearImmediate,\n    __VUE_SSR_CONTEXT__: context\n  }\n  sandbox.global = sandbox\n  return sandbox\n}\n\nfunction compileModule (files, basedir, runInNewContext) {\n  const compiledScripts = {}\n  const resolvedModules = {}\n\n  function getCompiledScript (filename) {\n    if (compiledScripts[filename]) {\n      return compiledScripts[filename]\n    }\n    const code = files[filename]\n    const wrapper = NativeModule.wrap(code)\n    const script = new vm.Script(wrapper, {\n      filename,\n      displayErrors: true\n    })\n    compiledScripts[filename] = script\n    return script\n  }\n\n  function evaluateModule (filename, sandbox, evaluatedFiles = {}) {\n    if (evaluatedFiles[filename]) {\n      return evaluatedFiles[filename]\n    }\n\n    const script = getCompiledScript(filename)\n    const compiledWrapper = runInNewContext === false\n      ? script.runInThisContext()\n      : script.runInNewContext(sandbox)\n    const m = { exports: {}}\n    const r = file => {\n      file = path.join('.', file)\n      if (files[file]) {\n        return evaluateModule(file, sandbox, evaluatedFiles)\n      } else if (basedir) {\n        return require(\n          resolvedModules[file] ||\n          (resolvedModules[file] = resolve.sync(file, { basedir }))\n        )\n      } else {\n        return require(file)\n      }\n    }\n    compiledWrapper.call(m.exports, m.exports, r, m)\n\n    const res = Object.prototype.hasOwnProperty.call(m.exports, 'default')\n      ? m.exports.default\n      : m.exports\n    evaluatedFiles[filename] = res\n    return res\n  }\n  return evaluateModule\n}\n\nfunction deepClone (val) {\n  if (isPlainObject(val)) {\n    const res = {}\n    for (const key in val) {\n      res[key] = deepClone(val[key])\n    }\n    return res\n  } else if (Array.isArray(val)) {\n    return val.slice()\n  } else {\n    return val\n  }\n}\n\nexport function createBundleRunner (entry, files, basedir, runInNewContext) {\n  const evaluate = compileModule(files, basedir, runInNewContext)\n  if (runInNewContext !== false && runInNewContext !== 'once') {\n    // new context mode: creates a fresh context and re-evaluate the bundle\n    // on each render. Ensures entire application state is fresh for each\n    // render, but incurs extra evaluation cost.\n    return (userContext = {}) => new Promise(resolve => {\n      userContext._registeredComponents = new Set()\n      const res = evaluate(entry, createSandbox(userContext))\n      resolve(typeof res === 'function' ? res(userContext) : res)\n    })\n  } else {\n    // direct mode: instead of re-evaluating the whole bundle on\n    // each render, it simply calls the exported function. This avoids the\n    // module evaluation costs but requires the source code to be structured\n    // slightly differently.\n    let runner // lazy creation so that errors can be caught by user\n    let initialContext\n    return (userContext = {}) => new Promise(resolve => {\n      if (!runner) {\n        const sandbox = runInNewContext === 'once'\n          ? createSandbox()\n          : global\n        // the initial context is only used for collecting possible non-component\n        // styles injected by vue-style-loader.\n        initialContext = sandbox.__VUE_SSR_CONTEXT__ = {}\n        runner = evaluate(entry, sandbox)\n        // On subsequent renders, __VUE_SSR_CONTEXT__ will not be available\n        // to prevent cross-request pollution.\n        delete sandbox.__VUE_SSR_CONTEXT__\n        if (typeof runner !== 'function') {\n          throw new Error(\n            'bundle export should be a function when using ' +\n            '{ runInNewContext: false }.'\n          )\n        }\n      }\n      userContext._registeredComponents = new Set()\n      // vue-style-loader styles imported outside of component lifecycle hooks\n      if (initialContext._styles) {\n        userContext._styles = deepClone(initialContext._styles)\n      }\n      resolve(runner(userContext))\n    })\n  }\n}\n"
  },
  {
    "path": "src/server/bundle-renderer/source-map-support.js",
    "content": "/* @flow */\n\nconst SourceMapConsumer = require('source-map').SourceMapConsumer\n\nconst filenameRE = /\\(([^)]+\\.js):(\\d+):(\\d+)\\)$/\n\nexport function createSourceMapConsumers (rawMaps: Object) {\n  const maps = {}\n  Object.keys(rawMaps).forEach(file => {\n    maps[file] = new SourceMapConsumer(rawMaps[file])\n  })\n  return maps\n}\n\nexport function rewriteErrorTrace (e: any, mapConsumers: {\n  [key: string]: SourceMapConsumer\n}) {\n  if (e && typeof e.stack === 'string') {\n    e.stack = e.stack.split('\\n').map(line => {\n      return rewriteTraceLine(line, mapConsumers)\n    }).join('\\n')\n  }\n}\n\nfunction rewriteTraceLine (trace: string, mapConsumers: {\n  [key: string]: SourceMapConsumer\n}) {\n  const m = trace.match(filenameRE)\n  const map = m && mapConsumers[m[1]]\n  if (m != null && map) {\n    const originalPosition = map.originalPositionFor({\n      line: Number(m[2]),\n      column: Number(m[3])\n    })\n    if (originalPosition.source != null) {\n      const { source, line, column } = originalPosition\n      const mappedPosition = `(${source.replace(/^webpack:\\/\\/\\//, '')}:${String(line)}:${String(column)})`\n      return trace.replace(filenameRE, mappedPosition)\n    } else {\n      return trace\n    }\n  } else {\n    return trace\n  }\n}\n"
  },
  {
    "path": "src/server/create-basic-renderer.js",
    "content": "/* @flow */\n\nimport { createWriteFunction } from './write'\nimport { createRenderFunction } from './render'\nimport type { RenderOptions } from './create-renderer'\n\nexport function createBasicRenderer ({\n  modules = [],\n  directives = {},\n  isUnaryTag = (() => false),\n  cache\n}: RenderOptions = {}) {\n  const render = createRenderFunction(modules, directives, isUnaryTag, cache)\n\n  return function renderToString (\n    component: Component,\n    context: any,\n    done: any\n  ): void {\n    if (typeof context === 'function') {\n      done = context\n      context = {}\n    }\n    let result = ''\n    const write = createWriteFunction(text => {\n      result += text\n      return false\n    }, done)\n    try {\n      render(component, write, context, () => {\n        done(null, result)\n      })\n    } catch (e) {\n      done(e)\n    }\n  }\n}\n"
  },
  {
    "path": "src/server/create-renderer.js",
    "content": "/* @flow */\n\nimport RenderStream from './render-stream'\nimport { createWriteFunction } from './write'\nimport { createRenderFunction } from './render'\nimport TemplateRenderer from './template-renderer/index'\nimport type { ClientManifest } from './template-renderer/index'\n\nexport type Renderer = {\n  renderToString: (component: Component, context: any, cb: any) => void;\n  renderToStream: (component: Component, context?: Object) => stream$Readable;\n};\n\ntype RenderCache = {\n  get: (key: string, cb?: Function) => string | void;\n  set: (key: string, val: string) => void;\n  has?: (key: string, cb?: Function) => boolean | void;\n};\n\nexport type RenderOptions = {\n  modules?: Array<(vnode: VNode) => ?string>;\n  directives?: Object;\n  isUnaryTag?: Function;\n  cache?: RenderCache;\n  template?: string;\n  inject?: boolean;\n  basedir?: string;\n  shouldPreload?: Function;\n  clientManifest?: ClientManifest;\n  runInNewContext?: boolean | 'once';\n};\n\nexport function createRenderer ({\n  modules = [],\n  directives = {},\n  isUnaryTag = (() => false),\n  template,\n  inject,\n  cache,\n  shouldPreload,\n  clientManifest\n}: RenderOptions = {}): Renderer {\n  const render = createRenderFunction(modules, directives, isUnaryTag, cache)\n  const templateRenderer = new TemplateRenderer({\n    template,\n    inject,\n    shouldPreload,\n    clientManifest\n  })\n\n  return {\n    renderToString (\n      component: Component,\n      context: any,\n      done: any\n    ): void {\n      if (typeof context === 'function') {\n        done = context\n        context = {}\n      }\n      if (context) {\n        templateRenderer.bindRenderFns(context)\n      }\n      let result = ''\n      const write = createWriteFunction(text => {\n        result += text\n        return false\n      }, done)\n      try {\n        render(component, write, context, () => {\n          if (template) {\n            result = templateRenderer.renderSync(result, context)\n          }\n          done(null, result)\n        })\n      } catch (e) {\n        done(e)\n      }\n    },\n\n    renderToStream (\n      component: Component,\n      context?: Object\n    ): stream$Readable {\n      if (context) {\n        templateRenderer.bindRenderFns(context)\n      }\n      const renderStream = new RenderStream((write, done) => {\n        render(component, write, context, done)\n      })\n      if (!template) {\n        return renderStream\n      } else {\n        const templateStream = templateRenderer.createStream(context)\n        renderStream.on('error', err => {\n          templateStream.emit('error', err)\n        })\n        renderStream.pipe(templateStream)\n        return templateStream\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "src/server/optimizing-compiler/codegen.js",
    "content": "/* @flow */\n\n// The SSR codegen is essentially extending the default codegen to handle\n// SSR-optimizable nodes and turn them into string render fns. In cases where\n// a node is not optimizable it simply falls back to the default codegen.\n\nimport {\n  genIf,\n  genFor,\n  genData,\n  genText,\n  genElement,\n  genChildren,\n  CodegenState\n} from 'compiler/codegen/index'\n\nimport {\n  genAttrSegments,\n  genDOMPropSegments,\n  genClassSegments,\n  genStyleSegments,\n  applyModelTransform\n} from './modules'\n\nimport { optimizability } from './optimizer'\n\nimport type { CodegenResult } from 'compiler/codegen/index'\n\nexport type StringSegment = {\n  type: number;\n  value: string;\n};\n\n// segment types\nexport const RAW = 0\nexport const INTERPOLATION = 1\nexport const EXPRESSION = 2\n\nexport function generate (\n  ast: ASTElement | void,\n  options: CompilerOptions\n): CodegenResult {\n  const state = new CodegenState(options)\n  const code = ast ? genSSRElement(ast, state) : '_c(\"div\")'\n  return {\n    render: `with(this){return ${code}}`,\n    staticRenderFns: state.staticRenderFns\n  }\n}\n\nfunction genSSRElement (el: ASTElement, state: CodegenState): string {\n  if (el.for && !el.forProcessed) {\n    return genFor(el, state, genSSRElement)\n  } else if (el.if && !el.ifProcessed) {\n    return genIf(el, state, genSSRElement)\n  } else if (el.tag === 'template' && !el.slotTarget) {\n    return el.ssrOptimizability === optimizability.FULL\n      ? genChildrenAsStringNode(el, state)\n      : genSSRChildren(el, state) || 'void 0'\n  }\n\n  switch (el.ssrOptimizability) {\n    case optimizability.FULL:\n      // stringify whole tree\n      return genStringElement(el, state)\n    case optimizability.SELF:\n      // stringify self and check children\n      return genStringElementWithChildren(el, state)\n    case optimizability.CHILDREN:\n      // generate self as VNode and stringify children\n      return genNormalElement(el, state, true)\n    case optimizability.PARTIAL:\n      // generate self as VNode and check children\n      return genNormalElement(el, state, false)\n    default:\n      // bail whole tree\n      return genElement(el, state)\n  }\n}\n\nfunction genNormalElement (el, state, stringifyChildren) {\n  const data = el.plain ? undefined : genData(el, state)\n  const children = stringifyChildren\n    ? `[${genChildrenAsStringNode(el, state)}]`\n    : genSSRChildren(el, state, true)\n  return `_c('${el.tag}'${\n    data ? `,${data}` : ''\n  }${\n    children ? `,${children}` : ''\n  })`\n}\n\nfunction genSSRChildren (el, state, checkSkip) {\n  return genChildren(el, state, checkSkip, genSSRElement, genSSRNode)\n}\n\nfunction genSSRNode (el, state) {\n  return el.type === 1\n    ? genSSRElement(el, state)\n    : genText(el)\n}\n\nfunction genChildrenAsStringNode (el, state) {\n  return el.children.length\n    ? `_ssrNode(${flattenSegments(childrenToSegments(el, state))})`\n    : ''\n}\n\nfunction genStringElement (el, state) {\n  return `_ssrNode(${elementToString(el, state)})`\n}\n\nfunction genStringElementWithChildren (el, state) {\n  const children = genSSRChildren(el, state, true)\n  return `_ssrNode(${\n    flattenSegments(elementToOpenTagSegments(el, state))\n  },\"</${el.tag}>\"${\n    children ? `,${children}` : ''\n  })`\n}\n\nfunction elementToString (el, state) {\n  return `(${flattenSegments(elementToSegments(el, state))})`\n}\n\nfunction elementToSegments (el, state): Array<StringSegment> {\n  // v-for / v-if\n  if (el.for && !el.forProcessed) {\n    el.forProcessed = true\n    return [{\n      type: EXPRESSION,\n      value: genFor(el, state, elementToString, '_ssrList')\n    }]\n  } else if (el.if && !el.ifProcessed) {\n    el.ifProcessed = true\n    return [{\n      type: EXPRESSION,\n      value: genIf(el, state, elementToString, '\"<!---->\"')\n    }]\n  } else if (el.tag === 'template') {\n    return childrenToSegments(el, state)\n  }\n\n  const openSegments = elementToOpenTagSegments(el, state)\n  const childrenSegments = childrenToSegments(el, state)\n  const { isUnaryTag } = state.options\n  const close = (isUnaryTag && isUnaryTag(el.tag))\n    ? []\n    : [{ type: RAW, value: `</${el.tag}>` }]\n  return openSegments.concat(childrenSegments, close)\n}\n\nfunction elementToOpenTagSegments (el, state): Array<StringSegment> {\n  applyModelTransform(el, state)\n  let binding\n  const segments = [{ type: RAW, value: `<${el.tag}` }]\n  // attrs\n  if (el.attrs) {\n    segments.push.apply(segments, genAttrSegments(el.attrs))\n  }\n  // domProps\n  if (el.props) {\n    segments.push.apply(segments, genDOMPropSegments(el.props, el.attrs))\n  }\n  // v-bind=\"object\"\n  if ((binding = el.attrsMap['v-bind'])) {\n    segments.push({ type: EXPRESSION, value: `_ssrAttrs(${binding})` })\n  }\n  // v-bind.prop=\"object\"\n  if ((binding = el.attrsMap['v-bind.prop'])) {\n    segments.push({ type: EXPRESSION, value: `_ssrDOMProps(${binding})` })\n  }\n  // class\n  if (el.staticClass || el.classBinding) {\n    segments.push.apply(\n      segments,\n      genClassSegments(el.staticClass, el.classBinding)\n    )\n  }\n  // style & v-show\n  if (el.staticStyle || el.styleBinding || el.attrsMap['v-show']) {\n    segments.push.apply(\n      segments,\n      genStyleSegments(\n        el.attrsMap.style,\n        el.staticStyle,\n        el.styleBinding,\n        el.attrsMap['v-show']\n      )\n    )\n  }\n  // _scopedId\n  if (state.options.scopeId) {\n    segments.push({ type: RAW, value: ` ${state.options.scopeId}` })\n  }\n  segments.push({ type: RAW, value: `>` })\n  return segments\n}\n\nfunction childrenToSegments (el, state): Array<StringSegment> {\n  let binding\n  if ((binding = el.attrsMap['v-html'])) {\n    return [{ type: EXPRESSION, value: binding }]\n  }\n  if ((binding = el.attrsMap['v-text'])) {\n    return [{ type: INTERPOLATION, value: binding }]\n  }\n  return el.children\n    ? nodesToSegments(el.children, state)\n    : []\n}\n\nfunction nodesToSegments (\n  children: Array<ASTNode>,\n  state: CodegenState\n): Array<StringSegment> {\n  const segments = []\n  for (let i = 0; i < children.length; i++) {\n    const c = children[i]\n    if (c.type === 1) {\n      segments.push.apply(segments, elementToSegments(c, state))\n    } else if (c.type === 2) {\n      segments.push({ type: INTERPOLATION, value: c.expression })\n    } else if (c.type === 3) {\n      segments.push({ type: RAW, value: c.text })\n    }\n  }\n  return segments\n}\n\nfunction flattenSegments (segments: Array<StringSegment>): string {\n  const mergedSegments = []\n  let textBuffer = ''\n\n  const pushBuffer = () => {\n    if (textBuffer) {\n      mergedSegments.push(JSON.stringify(textBuffer))\n      textBuffer = ''\n    }\n  }\n\n  for (let i = 0; i < segments.length; i++) {\n    const s = segments[i]\n    if (s.type === RAW) {\n      textBuffer += s.value\n    } else if (s.type === INTERPOLATION) {\n      pushBuffer()\n      mergedSegments.push(`_ssrEscape(${s.value})`)\n    } else if (s.type === EXPRESSION) {\n      pushBuffer()\n      mergedSegments.push(`(${s.value})`)\n    }\n  }\n  pushBuffer()\n\n  return mergedSegments.join('+')\n}\n"
  },
  {
    "path": "src/server/optimizing-compiler/index.js",
    "content": "/* @flow */\n\nimport { parse } from 'compiler/parser/index'\nimport { generate } from './codegen'\nimport { optimize } from './optimizer'\nimport { createCompilerCreator } from 'compiler/create-compiler'\n\nexport const createCompiler = createCompilerCreator(function baseCompile (\n  template: string,\n  options: CompilerOptions\n): CompiledResult {\n  const ast = parse(template.trim(), options)\n  optimize(ast, options)\n  const code = generate(ast, options)\n  return {\n    ast,\n    render: code.render,\n    staticRenderFns: code.staticRenderFns\n  }\n})\n"
  },
  {
    "path": "src/server/optimizing-compiler/modules.js",
    "content": "/* @flow */\n\nimport {\n  RAW,\n  // INTERPOLATION,\n  EXPRESSION\n} from './codegen'\n\nimport {\n  propsToAttrMap,\n  isRenderableAttr\n} from 'web/server/util'\n\nimport {\n  isBooleanAttr,\n  isEnumeratedAttr\n} from 'web/util/attrs'\n\nimport type { StringSegment } from './codegen'\nimport type { CodegenState } from 'compiler/codegen/index'\n\ntype Attr = { name: string; value: string };\n\nconst plainStringRE = /^\"(?:[^\"\\\\]|\\\\.)*\"$|^'(?:[^'\\\\]|\\\\.)*'$/\n\n// let the model AST transform translate v-model into appropriate\n// props bindings\nexport function applyModelTransform (el: ASTElement, state: CodegenState) {\n  if (el.directives) {\n    for (let i = 0; i < el.directives.length; i++) {\n      const dir = el.directives[i]\n      if (dir.name === 'model') {\n        state.directives.model(el, dir, state.warn)\n        break\n      }\n    }\n  }\n}\n\nexport function genAttrSegments (\n  attrs: Array<Attr>\n): Array<StringSegment> {\n  return attrs.map(({ name, value }) => genAttrSegment(name, value))\n}\n\nexport function genDOMPropSegments (\n  props: Array<Attr>,\n  attrs: ?Array<Attr>\n): Array<StringSegment> {\n  const segments = []\n  props.forEach(({ name, value }) => {\n    name = propsToAttrMap[name] || name.toLowerCase()\n    if (isRenderableAttr(name) &&\n      !(attrs && attrs.some(a => a.name === name))\n    ) {\n      segments.push(genAttrSegment(name, value))\n    }\n  })\n  return segments\n}\n\nfunction genAttrSegment (name: string, value: string): StringSegment {\n  if (plainStringRE.test(value)) {\n    // force double quote\n    value = value.replace(/^'|'$/g, '\"')\n    // force enumerated attr to \"true\"\n    if (isEnumeratedAttr(name) && value !== `\"false\"`) {\n      value = `\"true\"`\n    }\n    return {\n      type: RAW,\n      value: isBooleanAttr(name)\n        ? ` ${name}=\"${name}\"`\n        : value === '\"\"'\n          ? ` ${name}`\n          : ` ${name}=${value}`\n    }\n  } else {\n    return {\n      type: EXPRESSION,\n      value: `_ssrAttr(${JSON.stringify(name)},${value})`\n    }\n  }\n}\n\nexport function genClassSegments (\n  staticClass: ?string,\n  classBinding: ?string\n): Array<StringSegment> {\n  if (staticClass && !classBinding) {\n    return [{ type: RAW, value: ` class=${staticClass}` }]\n  } else {\n    return [{\n      type: EXPRESSION,\n      value: `_ssrClass(${staticClass || 'null'},${classBinding || 'null'})`\n    }]\n  }\n}\n\nexport function genStyleSegments (\n  staticStyle: ?string,\n  parsedStaticStyle: ?string,\n  styleBinding: ?string,\n  vShowExpression: ?string\n): Array<StringSegment> {\n  if (staticStyle && !styleBinding && !vShowExpression) {\n    return [{ type: RAW, value: ` style=${JSON.stringify(staticStyle)}` }]\n  } else {\n    return [{\n      type: EXPRESSION,\n      value: `_ssrStyle(${\n        parsedStaticStyle || 'null'\n      },${\n        styleBinding || 'null'\n      }, ${\n        vShowExpression\n          ? `{ display: (${vShowExpression}) ? '' : 'none' }`\n          : 'null'\n      })`\n    }]\n  }\n}\n"
  },
  {
    "path": "src/server/optimizing-compiler/optimizer.js",
    "content": "/* @flow */\n\n/**\n * In SSR, the vdom tree is generated only once and never patched, so\n * we can optimize most element / trees into plain string render functions.\n * The SSR optimizer walks the AST tree to detect optimizable elements and trees.\n *\n * The criteria for SSR optimizability is quite a bit looser than static tree\n * detection (which is designed for client re-render). In SSR we bail only for\n * components/slots/custom directives.\n */\n\nimport { no, makeMap, isBuiltInTag } from 'shared/util'\n\n// optimizability constants\nexport const optimizability = {\n  FALSE: 0,    // whole sub tree un-optimizable\n  FULL: 1,     // whole sub tree optimizable\n  SELF: 2,     // self optimizable but has some un-optimizable children\n  CHILDREN: 3, // self un-optimizable but have fully optimizable children\n  PARTIAL: 4   // self un-optimizable with some un-optimizable children\n}\n\nlet isPlatformReservedTag\n\nexport function optimize (root: ?ASTElement, options: CompilerOptions) {\n  if (!root) return\n  isPlatformReservedTag = options.isReservedTag || no\n  walk(root, true)\n}\n\nfunction walk (node: ASTNode, isRoot?: boolean) {\n  if (isUnOptimizableTree(node)) {\n    node.ssrOptimizability = optimizability.FALSE\n    return\n  }\n  // root node or nodes with custom directives should always be a VNode\n  const selfUnoptimizable = isRoot || hasCustomDirective(node)\n  const check = child => {\n    if (child.ssrOptimizability !== optimizability.FULL) {\n      node.ssrOptimizability = selfUnoptimizable\n        ? optimizability.PARTIAL\n        : optimizability.SELF\n    }\n  }\n  if (selfUnoptimizable) {\n    node.ssrOptimizability = optimizability.CHILDREN\n  }\n  if (node.type === 1) {\n    for (let i = 0, l = node.children.length; i < l; i++) {\n      const child = node.children[i]\n      walk(child)\n      check(child)\n    }\n    if (node.ifConditions) {\n      for (let i = 1, l = node.ifConditions.length; i < l; i++) {\n        const block = node.ifConditions[i].block\n        walk(block)\n        check(block)\n      }\n    }\n    if (node.ssrOptimizability == null ||\n      (!isRoot && (node.attrsMap['v-html'] || node.attrsMap['v-text']))\n    ) {\n      node.ssrOptimizability = optimizability.FULL\n    } else {\n      node.children = optimizeSiblings(node)\n    }\n  } else {\n    node.ssrOptimizability = optimizability.FULL\n  }\n}\n\nfunction optimizeSiblings (el) {\n  const children = el.children\n  const optimizedChildren = []\n\n  let currentOptimizableGroup = []\n  const pushGroup = () => {\n    if (currentOptimizableGroup.length) {\n      optimizedChildren.push({\n        type: 1,\n        parent: el,\n        tag: 'template',\n        attrsList: [],\n        attrsMap: {},\n        children: currentOptimizableGroup,\n        ssrOptimizability: optimizability.FULL\n      })\n    }\n    currentOptimizableGroup = []\n  }\n\n  for (let i = 0; i < children.length; i++) {\n    const c = children[i]\n    if (c.ssrOptimizability === optimizability.FULL) {\n      currentOptimizableGroup.push(c)\n    } else {\n      // wrap fully-optimizable adjacent siblings inside a template tag\n      // so that they can be optimized into a single ssrNode by codegen\n      pushGroup()\n      optimizedChildren.push(c)\n    }\n  }\n  pushGroup()\n  return optimizedChildren\n}\n\nfunction isUnOptimizableTree (node: ASTNode): boolean {\n  if (node.type === 2 || node.type === 3) { // text or expression\n    return false\n  }\n  return (\n    isBuiltInTag(node.tag) || // built-in (slot, component)\n    !isPlatformReservedTag(node.tag) || // custom component\n    !!node.component // \"is\" component\n  )\n}\n\nconst isBuiltInDir = makeMap('text,html,show,on,bind,model,pre,cloak,once')\n\nfunction hasCustomDirective (node: ASTNode): ?boolean {\n  return (\n    node.type === 1 &&\n    node.directives &&\n    node.directives.some(d => !isBuiltInDir(d.name))\n  )\n}\n"
  },
  {
    "path": "src/server/optimizing-compiler/runtime-helpers.js",
    "content": "/* @flow */\n\nimport { escape, cachedEscape } from 'web/server/util'\nimport { isObject, extend } from 'shared/util'\nimport { renderAttr } from 'web/server/modules/attrs'\nimport { renderClass } from 'web/util/class'\nimport { genStyle } from 'web/server/modules/style'\nimport { normalizeStyleBinding } from 'web/util/style'\n\nimport {\n  normalizeChildren,\n  simpleNormalizeChildren\n} from 'core/vdom/helpers/normalize-children'\n\nimport {\n  propsToAttrMap,\n  isRenderableAttr\n} from 'web/server/util'\n\nexport function installSSRHelpers (vm: Component) {\n  if (vm._ssrNode) return\n  let Ctor = vm.constructor\n  while (Ctor.super) {\n    Ctor = Ctor.super\n  }\n  Object.assign(Ctor.prototype, {\n    _ssrEscape: escape,\n    _ssrNode: renderStringNode,\n    _ssrList: renderStringList,\n    _ssrAttr: renderAttr,\n    _ssrAttrs: renderAttrs,\n    _ssrDOMProps: renderDOMProps,\n    _ssrClass: renderSSRClass,\n    _ssrStyle: renderSSRStyle\n  })\n}\n\nclass StringNode {\n  isString: boolean;\n  open: string;\n  close: ?string;\n  children: ?Array<any>;\n\n  constructor (\n    open: string,\n    close?: string,\n    children?: Array<any>,\n    normalizationType?: number\n  ) {\n    this.isString = true\n    this.open = open\n    this.close = close\n    if (children) {\n      this.children = normalizationType === 1\n        ? simpleNormalizeChildren(children)\n        : normalizationType === 2\n          ? normalizeChildren(children)\n          : children\n    } else {\n      this.children = void 0\n    }\n  }\n}\n\nfunction renderStringNode (\n  open: string,\n  close?: string,\n  children?: Array<any>,\n  normalizationType?: number\n): StringNode {\n  return new StringNode(open, close, children, normalizationType)\n}\n\nfunction renderStringList (\n  val: any,\n  render: (\n    val: any,\n    keyOrIndex: string | number,\n    index?: number\n  ) => string\n): string {\n  let ret = ''\n  let i, l, keys, key\n  if (Array.isArray(val) || typeof val === 'string') {\n    for (i = 0, l = val.length; i < l; i++) {\n      ret += render(val[i], i)\n    }\n  } else if (typeof val === 'number') {\n    for (i = 0; i < val; i++) {\n      ret += render(i + 1, i)\n    }\n  } else if (isObject(val)) {\n    keys = Object.keys(val)\n    for (i = 0, l = keys.length; i < l; i++) {\n      key = keys[i]\n      ret += render(val[key], key, i)\n    }\n  }\n  return ret\n}\n\nfunction renderAttrs (obj: Object): string {\n  let res = ''\n  for (const key in obj) {\n    res += renderAttr(key, obj[key])\n  }\n  return res\n}\n\nfunction renderDOMProps (obj: Object): string {\n  let res = ''\n  for (const key in obj) {\n    const attr = propsToAttrMap[key] || key.toLowerCase()\n    if (isRenderableAttr(attr)) {\n      res += renderAttr(attr, obj[key])\n    }\n  }\n  return res\n}\n\nfunction renderSSRClass (\n  staticClass: ?string,\n  dynamic: any\n): string {\n  const res = renderClass(staticClass, dynamic)\n  return res === '' ? res : ` class=\"${cachedEscape(res)}\"`\n}\n\nfunction renderSSRStyle (\n  staticStyle: ?Object,\n  dynamic: any,\n  extra: ?Object\n): string {\n  const style = {}\n  if (staticStyle) extend(style, staticStyle)\n  if (dynamic) extend(style, normalizeStyleBinding(dynamic))\n  if (extra) extend(style, extra)\n  const res = genStyle(style)\n  return res === '' ? res : ` style=${JSON.stringify(cachedEscape(res))}`\n}\n"
  },
  {
    "path": "src/server/render-context.js",
    "content": "/* @flow */\n\nimport { isUndef } from 'shared/util'\n\ntype RenderState = {\n  type: 'Element';\n  rendered: number;\n  total: number;\n  endTag: string;\n  children: Array<VNode>;\n} | {\n  type: 'Component';\n  prevActive: Component;\n} | {\n  type: 'ComponentWithCache';\n  buffer: Array<string>;\n  bufferIndex: number;\n  componentBuffer: Array<Set<Class<Component>>>;\n  key: string;\n};\n\nexport class RenderContext {\n  userContext: ?Object;\n  activeInstance: Component;\n  renderStates: Array<RenderState>;\n  write: (text: string, next: Function) => void;\n  renderNode: (node: VNode, isRoot: boolean, context: RenderContext) => void;\n  next: () => void;\n  done: () => void;\n\n  modules: Array<(node: VNode) => ?string>;\n  directives: Object;\n  isUnaryTag: (tag: string) => boolean;\n\n  cache: any;\n  get: ?(key: string, cb: Function) => void;\n  has: ?(key: string, cb: Function) => void;\n\n  constructor (options: Object) {\n    this.userContext = options.userContext\n    this.activeInstance = options.activeInstance\n    this.renderStates = []\n\n    this.write = options.write\n    this.done = options.done\n    this.renderNode = options.renderNode\n\n    this.isUnaryTag = options.isUnaryTag\n    this.modules = options.modules\n    this.directives = options.directives\n\n    const cache = options.cache\n    if (cache && (!cache.get || !cache.set)) {\n      throw new Error('renderer cache must implement at least get & set.')\n    }\n    this.cache = cache\n    this.get = cache && normalizeAsync(cache, 'get')\n    this.has = cache && normalizeAsync(cache, 'has')\n\n    this.next = this.next.bind(this)\n  }\n\n  next () {\n    const lastState = this.renderStates[this.renderStates.length - 1]\n    if (isUndef(lastState)) {\n      return this.done()\n    }\n    switch (lastState.type) {\n      case 'Element':\n        const { children, total } = lastState\n        const rendered = lastState.rendered++\n        if (rendered < total) {\n          this.renderNode(children[rendered], false, this)\n        } else {\n          this.renderStates.pop()\n          this.write(lastState.endTag, this.next)\n        }\n        break\n      case 'Component':\n        this.renderStates.pop()\n        this.activeInstance = lastState.prevActive\n        this.next()\n        break\n      case 'ComponentWithCache':\n        this.renderStates.pop()\n        const { buffer, bufferIndex, componentBuffer, key } = lastState\n        const result = {\n          html: buffer[bufferIndex],\n          components: componentBuffer[bufferIndex]\n        }\n        this.cache.set(key, result)\n        if (bufferIndex === 0) {\n          // this is a top-level cached component,\n          // exit caching mode.\n          this.write.caching = false\n        } else {\n          // parent component is also being cached,\n          // merge self into parent's result\n          buffer[bufferIndex - 1] += result.html\n          const prev = componentBuffer[bufferIndex - 1]\n          result.components.forEach(c => prev.add(c))\n        }\n        buffer.length = bufferIndex\n        componentBuffer.length = bufferIndex\n        this.next()\n        break\n    }\n  }\n}\n\nfunction normalizeAsync (cache, method) {\n  const fn = cache[method]\n  if (isUndef(fn)) {\n    return\n  } else if (fn.length > 1) {\n    return (key, cb) => fn.call(cache, key, cb)\n  } else {\n    return (key, cb) => cb(fn.call(cache, key))\n  }\n}\n"
  },
  {
    "path": "src/server/render-stream.js",
    "content": "/* @flow */\n\n/**\n * Original RenderStream implementation by Sasha Aickin (@aickin)\n * Licensed under the Apache License, Version 2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Modified by Evan You (@yyx990803)\n */\n\nconst stream = require('stream')\n\nimport { isTrue, isUndef } from 'shared/util'\nimport { createWriteFunction } from './write'\n\nexport default class RenderStream extends stream.Readable {\n  buffer: string;\n  render: (write: Function, done: Function) => void;\n  expectedSize: number;\n  write: Function;\n  next: Function;\n  end: Function;\n  done: boolean;\n\n  constructor (render: Function) {\n    super()\n    this.buffer = ''\n    this.render = render\n    this.expectedSize = 0\n\n    this.write = createWriteFunction((text, next) => {\n      const n = this.expectedSize\n      this.buffer += text\n      if (this.buffer.length >= n) {\n        this.next = next\n        this.pushBySize(n)\n        return true // we will decide when to call next\n      }\n      return false\n    }, err => {\n      this.emit('error', err)\n    })\n\n    this.end = () => {\n      // the rendering is finished; we should push out the last of the buffer.\n      this.done = true\n      this.push(this.buffer)\n    }\n  }\n\n  pushBySize (n: number) {\n    const bufferToPush = this.buffer.substring(0, n)\n    this.buffer = this.buffer.substring(n)\n    this.push(bufferToPush)\n  }\n\n  tryRender () {\n    try {\n      this.render(this.write, this.end)\n    } catch (e) {\n      this.emit('error', e)\n    }\n  }\n\n  tryNext () {\n    try {\n      this.next()\n    } catch (e) {\n      this.emit('error', e)\n    }\n  }\n\n  _read (n: number) {\n    this.expectedSize = n\n    // it's possible that the last chunk added bumped the buffer up to > 2 * n,\n    // which means we will need to go through multiple read calls to drain it\n    // down to < n.\n    if (isTrue(this.done)) {\n      this.push(null)\n      return\n    }\n    if (this.buffer.length >= n) {\n      this.pushBySize(n)\n      return\n    }\n    if (isUndef(this.next)) {\n      // start the rendering chain.\n      this.tryRender()\n    } else {\n      // continue with the rendering.\n      this.tryNext()\n    }\n  }\n}\n"
  },
  {
    "path": "src/server/render.js",
    "content": "/* @flow */\n\nimport {\n  isDef,\n  isUndef,\n  isTrue\n} from 'shared/util'\n\nimport { escape } from 'web/server/util'\nimport { SSR_ATTR } from 'shared/constants'\nimport { RenderContext } from './render-context'\nimport { ssrCompileToFunctions } from 'web/server/compiler'\nimport { installSSRHelpers } from './optimizing-compiler/runtime-helpers'\n\nimport {\n  createComponent,\n  createComponentInstanceForVnode\n} from 'core/vdom/create-component'\n\nlet warned = Object.create(null)\nconst warnOnce = msg => {\n  if (!warned[msg]) {\n    warned[msg] = true\n    console.warn(`\\n\\u001b[31m${msg}\\u001b[39m\\n`)\n  }\n}\n\nconst normalizeRender = vm => {\n  const { render, template, _scopeId } = vm.$options\n  if (isUndef(render)) {\n    if (template) {\n      Object.assign(vm.$options, ssrCompileToFunctions(template, {\n        scopeId: _scopeId\n      }))\n    } else {\n      throw new Error(\n        `render function or template not defined in component: ${\n          vm.$options.name || vm.$options._componentTag || 'anonymous'\n        }`\n      )\n    }\n  }\n}\n\nfunction renderNode (node, isRoot, context) {\n  if (node.isString) {\n    renderStringNode(node, context)\n  } else if (isDef(node.componentOptions)) {\n    renderComponent(node, isRoot, context)\n  } else if (isDef(node.tag)) {\n    renderElement(node, isRoot, context)\n  } else if (isTrue(node.isComment)) {\n    if (isDef(node.asyncFactory)) {\n      // async component\n      renderAsyncComponent(node, isRoot, context)\n    } else {\n      context.write(`<!--${node.text}-->`, context.next)\n    }\n  } else {\n    context.write(\n      node.raw ? node.text : escape(String(node.text)),\n      context.next\n    )\n  }\n}\n\nfunction registerComponentForCache (options, write) {\n  // exposed by vue-loader, need to call this if cache hit because\n  // component lifecycle hooks will not be called.\n  const register = options._ssrRegister\n  if (write.caching && isDef(register)) {\n    write.componentBuffer[write.componentBuffer.length - 1].add(register)\n  }\n  return register\n}\n\nfunction renderComponent (node, isRoot, context) {\n  const { write, next, userContext } = context\n\n  // check cache hit\n  const Ctor = node.componentOptions.Ctor\n  const getKey = Ctor.options.serverCacheKey\n  const name = Ctor.options.name\n  const cache = context.cache\n  const registerComponent = registerComponentForCache(Ctor.options, write)\n\n  if (isDef(getKey) && isDef(cache) && isDef(name)) {\n    const key = name + '::' + getKey(node.componentOptions.propsData)\n    const { has, get } = context\n    if (isDef(has)) {\n      has(key, hit => {\n        if (hit === true && isDef(get)) {\n          get(key, res => {\n            if (isDef(registerComponent)) {\n              registerComponent(userContext)\n            }\n            res.components.forEach(register => register(userContext))\n            write(res.html, next)\n          })\n        } else {\n          renderComponentWithCache(node, isRoot, key, context)\n        }\n      })\n    } else if (isDef(get)) {\n      get(key, res => {\n        if (isDef(res)) {\n          if (isDef(registerComponent)) {\n            registerComponent(userContext)\n          }\n          res.components.forEach(register => register(userContext))\n          write(res.html, next)\n        } else {\n          renderComponentWithCache(node, isRoot, key, context)\n        }\n      })\n    }\n  } else {\n    if (isDef(getKey) && isUndef(cache)) {\n      warnOnce(\n        `[vue-server-renderer] Component ${\n          Ctor.options.name || '(anonymous)'\n        } implemented serverCacheKey, ` +\n        'but no cache was provided to the renderer.'\n      )\n    }\n    if (isDef(getKey) && isUndef(name)) {\n      warnOnce(\n        `[vue-server-renderer] Components that implement \"serverCacheKey\" ` +\n        `must also define a unique \"name\" option.`\n      )\n    }\n    renderComponentInner(node, isRoot, context)\n  }\n}\n\nfunction renderComponentWithCache (node, isRoot, key, context) {\n  const write = context.write\n  write.caching = true\n  const buffer = write.cacheBuffer\n  const bufferIndex = buffer.push('') - 1\n  const componentBuffer = write.componentBuffer\n  componentBuffer.push(new Set())\n  context.renderStates.push({\n    type: 'ComponentWithCache',\n    key,\n    buffer,\n    bufferIndex,\n    componentBuffer\n  })\n  renderComponentInner(node, isRoot, context)\n}\n\nfunction renderComponentInner (node, isRoot, context) {\n  const prevActive = context.activeInstance\n  // expose userContext on vnode\n  node.ssrContext = context.userContext\n  const child = context.activeInstance = createComponentInstanceForVnode(\n    node,\n    context.activeInstance\n  )\n  normalizeRender(child)\n  const childNode = child._render()\n  childNode.parent = node\n  context.renderStates.push({\n    type: 'Component',\n    prevActive\n  })\n  renderNode(childNode, isRoot, context)\n}\n\nfunction renderAsyncComponent (node, isRoot, context) {\n  const factory = node.asyncFactory\n\n  const resolve = comp => {\n    if (comp.__esModule && comp.default) {\n      comp = comp.default\n    }\n    const { data, children, tag } = node.asyncMeta\n    const nodeContext = node.asyncMeta.context\n    const resolvedNode: any = createComponent(\n      comp,\n      data,\n      nodeContext,\n      children,\n      tag\n    )\n    if (resolvedNode) {\n      renderComponent(resolvedNode, isRoot, context)\n    } else {\n      reject()\n    }\n  }\n\n  const reject = err => {\n    console.error(`[vue-server-renderer] error when rendering async component:\\n`)\n    if (err) console.error(err.stack)\n    context.write(`<!--${node.text}-->`, context.next)\n  }\n\n  if (factory.resolved) {\n    resolve(factory.resolved)\n    return\n  }\n\n  let res\n  try {\n    res = factory(resolve, reject)\n  } catch (e) {\n    reject(e)\n  }\n  if (res) {\n    if (typeof res.then === 'function') {\n      res.then(resolve, reject).catch(reject)\n    } else {\n      // new syntax in 2.3\n      const comp = res.component\n      if (comp && typeof comp.then === 'function') {\n        comp.then(resolve, reject).catch(reject)\n      }\n    }\n  }\n}\n\nfunction renderStringNode (el, context) {\n  const { write, next } = context\n  if (isUndef(el.children) || el.children.length === 0) {\n    write(el.open + (el.close || ''), next)\n  } else {\n    const children: Array<VNode> = el.children\n    context.renderStates.push({\n      type: 'Element',\n      rendered: 0,\n      total: children.length,\n      endTag: el.close, children\n    })\n    write(el.open, next)\n  }\n}\n\nfunction renderElement (el, isRoot, context) {\n  const { write, next } = context\n\n  if (isTrue(isRoot)) {\n    if (!el.data) el.data = {}\n    if (!el.data.attrs) el.data.attrs = {}\n    el.data.attrs[SSR_ATTR] = 'true'\n  }\n\n  if (el.functionalOptions) {\n    registerComponentForCache(el.functionalOptions, write)\n  }\n\n  const startTag = renderStartingTag(el, context)\n  const endTag = `</${el.tag}>`\n  if (context.isUnaryTag(el.tag)) {\n    write(startTag, next)\n  } else if (isUndef(el.children) || el.children.length === 0) {\n    write(startTag + endTag, next)\n  } else {\n    const children: Array<VNode> = el.children\n    context.renderStates.push({\n      type: 'Element',\n      rendered: 0,\n      total: children.length,\n      endTag, children\n    })\n    write(startTag, next)\n  }\n}\n\nfunction hasAncestorData (node: VNode) {\n  const parentNode = node.parent\n  return isDef(parentNode) && (isDef(parentNode.data) || hasAncestorData(parentNode))\n}\n\nfunction getVShowDirectiveInfo (node: VNode): ?VNodeDirective {\n  let dir: VNodeDirective\n  let tmp\n\n  while (isDef(node)) {\n    if (node.data && node.data.directives) {\n      tmp = node.data.directives.find(dir => dir.name === 'show')\n      if (tmp) {\n        dir = tmp\n      }\n    }\n    node = node.parent\n  }\n  return dir\n}\n\nfunction renderStartingTag (node: VNode, context) {\n  let markup = `<${node.tag}`\n  const { directives, modules } = context\n\n  // construct synthetic data for module processing\n  // because modules like style also produce code by parent VNode data\n  if (isUndef(node.data) && hasAncestorData(node)) {\n    node.data = {}\n  }\n  if (isDef(node.data)) {\n    // check directives\n    const dirs = node.data.directives\n    if (dirs) {\n      for (let i = 0; i < dirs.length; i++) {\n        const name = dirs[i].name\n        const dirRenderer = directives[name]\n        if (dirRenderer && name !== 'show') {\n          // directives mutate the node's data\n          // which then gets rendered by modules\n          dirRenderer(node, dirs[i])\n        }\n      }\n    }\n\n    // v-show directive needs to be merged from parent to child\n    const vshowDirectiveInfo = getVShowDirectiveInfo(node)\n    if (vshowDirectiveInfo) {\n      directives.show(node, vshowDirectiveInfo)\n    }\n\n    // apply other modules\n    for (let i = 0; i < modules.length; i++) {\n      const res = modules[i](node)\n      if (res) {\n        markup += res\n      }\n    }\n  }\n  // attach scoped CSS ID\n  let scopeId\n  const activeInstance = context.activeInstance\n  if (isDef(activeInstance) &&\n    activeInstance !== node.context &&\n    isDef(scopeId = activeInstance.$options._scopeId)\n  ) {\n    markup += ` ${(scopeId: any)}`\n  }\n  while (isDef(node)) {\n    if (isDef(scopeId = node.context.$options._scopeId)) {\n      markup += ` ${scopeId}`\n    }\n    node = node.parent\n  }\n  return markup + '>'\n}\n\nexport function createRenderFunction (\n  modules: Array<(node: VNode) => ?string>,\n  directives: Object,\n  isUnaryTag: Function,\n  cache: any\n) {\n  return function render (\n    component: Component,\n    write: (text: string, next: Function) => void,\n    userContext: ?Object,\n    done: Function\n  ) {\n    warned = Object.create(null)\n    const context = new RenderContext({\n      activeInstance: component,\n      userContext,\n      write, done, renderNode,\n      isUnaryTag, modules, directives,\n      cache\n    })\n    installSSRHelpers(component)\n    normalizeRender(component)\n    renderNode(component._render(), true, context)\n  }\n}\n"
  },
  {
    "path": "src/server/template-renderer/create-async-file-mapper.js",
    "content": "/* @flow */\n\n/**\n * Creates a mapper that maps components used during a server-side render\n * to async chunk files in the client-side build, so that we can inline them\n * directly in the rendered HTML to avoid waterfall requests.\n */\n\nimport type { ClientManifest } from './index'\n\nexport type AsyncFileMapper = (files: Array<string>) => Array<string>;\n\nexport function createMapper (\n  clientManifest: ClientManifest\n): AsyncFileMapper {\n  const map = createMap(clientManifest)\n  // map server-side moduleIds to client-side files\n  return function mapper (moduleIds: Array<string>): Array<string> {\n    const res = new Set()\n    for (let i = 0; i < moduleIds.length; i++) {\n      const mapped = map.get(moduleIds[i])\n      if (mapped) {\n        for (let j = 0; j < mapped.length; j++) {\n          res.add(mapped[j])\n        }\n      }\n    }\n    return Array.from(res)\n  }\n}\n\nfunction createMap (clientManifest) {\n  const map = new Map()\n  Object.keys(clientManifest.modules).forEach(id => {\n    map.set(id, mapIdToFile(id, clientManifest))\n  })\n  return map\n}\n\nfunction mapIdToFile (id, clientManifest) {\n  const files = []\n  const fileIndices = clientManifest.modules[id]\n  if (fileIndices) {\n    fileIndices.forEach(index => {\n      const file = clientManifest.all[index]\n      // only include async files or non-js assets\n      if (clientManifest.async.indexOf(file) > -1 || !(/\\.js($|\\?)/.test(file))) {\n        files.push(file)\n      }\n    })\n  }\n  return files\n}\n"
  },
  {
    "path": "src/server/template-renderer/index.js",
    "content": "/* @flow */\n\nconst path = require('path')\nconst serialize = require('serialize-javascript')\n\nimport { isJS, isCSS } from '../util'\nimport TemplateStream from './template-stream'\nimport { parseTemplate } from './parse-template'\nimport { createMapper } from './create-async-file-mapper'\nimport type { ParsedTemplate } from './parse-template'\nimport type { AsyncFileMapper } from './create-async-file-mapper'\n\ntype TemplateRendererOptions = {\n  template: ?string;\n  inject?: boolean;\n  clientManifest?: ClientManifest;\n  shouldPreload?: (file: string, type: string) => boolean;\n};\n\nexport type ClientManifest = {\n  publicPath: string;\n  all: Array<string>;\n  initial: Array<string>;\n  async: Array<string>;\n  modules: {\n    [id: string]: Array<number>;\n  },\n  hasNoCssVersion?: {\n    [file: string]: boolean;\n  }\n};\n\ntype PreloadFile = {\n  file: string;\n  extension: string;\n  fileWithoutQuery: string;\n  asType: string;\n};\n\nexport default class TemplateRenderer {\n  options: TemplateRendererOptions;\n  inject: boolean;\n  parsedTemplate: ParsedTemplate | null;\n  publicPath: string;\n  clientManifest: ClientManifest;\n  preloadFiles: Array<string>;\n  prefetchFiles: Array<string>;\n  mapFiles: AsyncFileMapper;\n\n  constructor (options: TemplateRendererOptions) {\n    this.options = options\n    this.inject = options.inject !== false\n    // if no template option is provided, the renderer is created\n    // as a utility object for rendering assets like preload links and scripts.\n    this.parsedTemplate = options.template\n      ? parseTemplate(options.template)\n      : null\n\n    // extra functionality with client manifest\n    if (options.clientManifest) {\n      const clientManifest = this.clientManifest = options.clientManifest\n      this.publicPath = clientManifest.publicPath.replace(/\\/$/, '')\n      // preload/prefetch drectives\n      this.preloadFiles = clientManifest.initial\n      this.prefetchFiles = clientManifest.async\n      // initial async chunk mapping\n      this.mapFiles = createMapper(clientManifest)\n    }\n  }\n\n  bindRenderFns (context: Object) {\n    const renderer: any = this\n    ;['ResourceHints', 'State', 'Scripts', 'Styles'].forEach(type => {\n      context[`render${type}`] = renderer[`render${type}`].bind(renderer, context)\n    })\n    // also expose getPreloadFiles, useful for HTTP/2 push\n    context.getPreloadFiles = renderer.getPreloadFiles.bind(renderer, context)\n  }\n\n  // render synchronously given rendered app content and render context\n  renderSync (content: string, context: ?Object) {\n    const template = this.parsedTemplate\n    if (!template) {\n      throw new Error('renderSync cannot be called without a template.')\n    }\n    context = context || {}\n    if (this.inject) {\n      return (\n        template.head(context) +\n        (context.head || '') +\n        this.renderResourceHints(context) +\n        this.renderStyles(context) +\n        template.neck(context) +\n        content +\n        this.renderState(context) +\n        this.renderScripts(context) +\n        template.tail(context)\n      )\n    } else {\n      return (\n        template.head(context) +\n        template.neck(context) +\n        content +\n        template.tail(context)\n      )\n    }\n  }\n\n  renderStyles (context: Object): string {\n    const cssFiles = this.clientManifest\n      ? this.clientManifest.all.filter(isCSS)\n      : []\n    return (\n      // render links for css files\n      (cssFiles.length\n        ? cssFiles.map(file => `<link rel=\"stylesheet\" href=\"${this.publicPath}/${file}\">`).join('')\n        : '') +\n      // context.styles is a getter exposed by vue-style-loader which contains\n      // the inline component styles collected during SSR\n      (context.styles || '')\n    )\n  }\n\n  renderResourceHints (context: Object): string {\n    return this.renderPreloadLinks(context) + this.renderPrefetchLinks(context)\n  }\n\n  getPreloadFiles (context: Object): Array<PreloadFile> {\n    const usedAsyncFiles = this.getUsedAsyncFiles(context)\n    if (this.preloadFiles || usedAsyncFiles) {\n      return (this.preloadFiles || []).concat(usedAsyncFiles || []).map(file => {\n        const withoutQuery = file.replace(/\\?.*/, '')\n        const extension = path.extname(withoutQuery).slice(1)\n        return {\n          file,\n          extension,\n          fileWithoutQuery: withoutQuery,\n          asType: getPreloadType(extension)\n        }\n      })\n    } else {\n      return []\n    }\n  }\n\n  renderPreloadLinks (context: Object): string {\n    const files = this.getPreloadFiles(context)\n    if (files.length) {\n      return files.map(({ file, extension, fileWithoutQuery, asType }) => {\n        let extra = ''\n        const shouldPreload = this.options.shouldPreload\n        // by default, we only preload scripts or css\n        if (!shouldPreload && asType !== 'script' && asType !== 'style') {\n          return ''\n        }\n        // user wants to explicitly control what to preload\n        if (shouldPreload && !shouldPreload(fileWithoutQuery, asType)) {\n          return ''\n        }\n        if (asType === 'font') {\n          extra = ` type=\"font/${extension}\" crossorigin`\n        }\n        return `<link rel=\"preload\" href=\"${\n          this.publicPath}/${file\n        }\"${\n          asType !== '' ? ` as=\"${asType}\"` : ''\n        }${\n          extra\n        }>`\n      }).join('')\n    } else {\n      return ''\n    }\n  }\n\n  renderPrefetchLinks (context: Object): string {\n    if (this.prefetchFiles) {\n      const usedAsyncFiles = this.getUsedAsyncFiles(context)\n      const alreadyRendered = file => {\n        return usedAsyncFiles && usedAsyncFiles.some(f => f === file)\n      }\n      return this.prefetchFiles.map(file => {\n        if (!alreadyRendered(file)) {\n          return `<link rel=\"prefetch\" href=\"${this.publicPath}/${file}\">`\n        } else {\n          return ''\n        }\n      }).join('')\n    } else {\n      return ''\n    }\n  }\n\n  renderState (context: Object, options?: Object): string {\n    const {\n      contextKey = 'state',\n      windowKey = '__INITIAL_STATE__'\n    } = options || {}\n    return context[contextKey]\n      ? `<script>window.${windowKey}=${\n          serialize(context[contextKey], { isJSON: true })\n        }</script>`\n      : ''\n  }\n\n  renderScripts (context: Object): string {\n    if (this.clientManifest) {\n      const initial = this.clientManifest.initial\n      const async = this.getUsedAsyncFiles(context)\n      const needed = [initial[0]].concat(async || [], initial.slice(1))\n      return needed.filter(isJS).map(file => {\n        return `<script src=\"${this.publicPath}/${file}\" defer></script>`\n      }).join('')\n    } else {\n      return ''\n    }\n  }\n\n  getUsedAsyncFiles (context: Object): ?Array<string> {\n    if (!context._mappedFiles && context._registeredComponents && this.mapFiles) {\n      context._mappedFiles = this.mapFiles(Array.from(context._registeredComponents))\n    }\n    return context._mappedFiles\n  }\n\n  // create a transform stream\n  createStream (context: ?Object): TemplateStream {\n    if (!this.parsedTemplate) {\n      throw new Error('createStream cannot be called without a template.')\n    }\n    return new TemplateStream(this, this.parsedTemplate, context || {})\n  }\n}\n\nfunction getPreloadType (ext: string): string {\n  if (ext === 'js') {\n    return 'script'\n  } else if (ext === 'css') {\n    return 'style'\n  } else if (/jpe?g|png|svg|gif|webp|ico/.test(ext)) {\n    return 'image'\n  } else if (/woff2?|ttf|otf|eot/.test(ext)) {\n    return 'font'\n  } else {\n    // not exhausting all possbilities here, but above covers common cases\n    return ''\n  }\n}\n"
  },
  {
    "path": "src/server/template-renderer/parse-template.js",
    "content": "/* @flow */\n\nconst compile = require('lodash.template')\nconst compileOptions = {\n  escape: /{{([^{][\\s\\S]+?[^}])}}/g,\n  interpolate: /{{{([\\s\\S]+?)}}}/g\n}\n\nexport type ParsedTemplate = {\n  head: (data: any) => string;\n  neck: (data: any) => string;\n  tail: (data: any) => string;\n};\n\nexport function parseTemplate (\n  template: string,\n  contentPlaceholder?: string = '<!--vue-ssr-outlet-->'\n): ParsedTemplate {\n  if (typeof template === 'object') {\n    return template\n  }\n\n  let i = template.indexOf('</head>')\n  const j = template.indexOf(contentPlaceholder)\n\n  if (j < 0) {\n    throw new Error(`Content placeholder not found in template.`)\n  }\n\n  if (i < 0) {\n    i = template.indexOf('<body>')\n    if (i < 0) {\n      i = j\n    }\n  }\n\n  return {\n    head: compile(template.slice(0, i), compileOptions),\n    neck: compile(template.slice(i, j), compileOptions),\n    tail: compile(template.slice(j + contentPlaceholder.length), compileOptions)\n  }\n}\n"
  },
  {
    "path": "src/server/template-renderer/template-stream.js",
    "content": "/* @flow */\n\nconst Transform = require('stream').Transform\nimport type TemplateRenderer from './index'\nimport type { ParsedTemplate } from './parse-template'\n\nexport default class TemplateStream extends Transform {\n  started: boolean;\n  renderer: TemplateRenderer;\n  template: ParsedTemplate;\n  context: Object;\n  inject: boolean;\n\n  constructor (\n    renderer: TemplateRenderer,\n    template: ParsedTemplate,\n    context: Object\n  ) {\n    super()\n    this.started = false\n    this.renderer = renderer\n    this.template = template\n    this.context = context || {}\n    this.inject = renderer.inject\n  }\n\n  _transform (data: Buffer | string, encoding: string, done: Function) {\n    if (!this.started) {\n      this.emit('beforeStart')\n      this.start()\n    }\n    this.push(data)\n    done()\n  }\n\n  start () {\n    this.started = true\n    this.push(this.template.head(this.context))\n\n    if (this.inject) {\n      // inline server-rendered head meta information\n      if (this.context.head) {\n        this.push(this.context.head)\n      }\n\n      // inline preload/prefetch directives for initial/async chunks\n      const links = this.renderer.renderResourceHints(this.context)\n      if (links) {\n        this.push(links)\n      }\n\n      // CSS files and inline server-rendered CSS collected by vue-style-loader\n      const styles = this.renderer.renderStyles(this.context)\n      if (styles) {\n        this.push(styles)\n      }\n    }\n\n    this.push(this.template.neck(this.context))\n  }\n\n  _flush (done: Function) {\n    this.emit('beforeEnd')\n\n    if (this.inject) {\n      // inline initial store state\n      const state = this.renderer.renderState(this.context)\n      if (state) {\n        this.push(state)\n      }\n\n      // embed scripts needed\n      const scripts = this.renderer.renderScripts(this.context)\n      if (scripts) {\n        this.push(scripts)\n      }\n    }\n\n    this.push(this.template.tail(this.context))\n    done()\n  }\n}\n"
  },
  {
    "path": "src/server/util.js",
    "content": "/* @flow */\n\nexport const isJS = (file: string): boolean => /\\.js(\\?[^.]+)?$/.test(file)\n\nexport const isCSS = (file: string): boolean => /\\.css(\\?[^.]+)?$/.test(file)\n"
  },
  {
    "path": "src/server/webpack-plugin/client.js",
    "content": "const hash = require('hash-sum')\nconst uniq = require('lodash.uniq')\nimport { isJS } from './util'\n\nexport default class VueSSRClientPlugin {\n  constructor (options = {}) {\n    this.options = Object.assign({\n      filename: 'vue-ssr-client-manifest.json'\n    }, options)\n  }\n\n  apply (compiler) {\n    compiler.plugin('emit', (compilation, cb) => {\n      const stats = compilation.getStats().toJson()\n\n      const allFiles = uniq(stats.assets\n        .map(a => a.name))\n\n      const initialFiles = uniq(Object.keys(stats.entrypoints)\n        .map(name => stats.entrypoints[name].assets)\n        .reduce((assets, all) => all.concat(assets), [])\n        .filter(isJS))\n\n      const asyncFiles = allFiles\n        .filter(isJS)\n        .filter(file => initialFiles.indexOf(file) < 0)\n\n      const manifest = {\n        publicPath: stats.publicPath,\n        all: allFiles,\n        initial: initialFiles,\n        async: asyncFiles,\n        modules: { /* [identifier: string]: Array<index: number> */ }\n      }\n\n      const assetModules = stats.modules.filter(m => m.assets.length)\n      const fileToIndex = file => manifest.all.indexOf(file)\n      stats.modules.forEach(m => {\n        // ignore modules duplicated in multiple chunks\n        if (m.chunks.length === 1) {\n          const cid = m.chunks[0]\n          const chunk = stats.chunks.find(c => c.id === cid)\n          if (!chunk || !chunk.files) {\n            return\n          }\n          const files = manifest.modules[hash(m.identifier)] = chunk.files.map(fileToIndex)\n          // find all asset modules associated with the same chunk\n          assetModules.forEach(m => {\n            if (m.chunks.some(id => id === cid)) {\n              files.push.apply(files, m.assets.map(fileToIndex))\n            }\n          })\n        }\n      })\n\n      // const debug = (file, obj) => {\n      //   require('fs').writeFileSync(__dirname + '/' + file, JSON.stringify(obj, null, 2))\n      // }\n      // debug('stats.json', stats)\n      // debug('client-manifest.json', manifest)\n\n      const json = JSON.stringify(manifest, null, 2)\n      compilation.assets[this.options.filename] = {\n        source: () => json,\n        size: () => json.length\n      }\n      cb()\n    })\n  }\n}\n"
  },
  {
    "path": "src/server/webpack-plugin/server.js",
    "content": "import { validate, isJS } from './util'\n\nexport default class VueSSRServerPlugin {\n  constructor (options = {}) {\n    this.options = Object.assign({\n      filename: 'vue-ssr-server-bundle.json'\n    }, options)\n  }\n\n  apply (compiler) {\n    validate(compiler)\n\n    compiler.plugin('emit', (compilation, cb) => {\n      const stats = compilation.getStats().toJson()\n      const entryName = Object.keys(stats.entrypoints)[0]\n      const entryInfo = stats.entrypoints[entryName]\n\n      if (!entryInfo) {\n        // #5553\n        return cb()\n      }\n\n      const entryAssets = entryInfo.assets.filter(isJS)\n\n      if (entryAssets.length > 1) {\n        throw new Error(\n          `Server-side bundle should have one single entry file. ` +\n          `Avoid using CommonsChunkPlugin in the server config.`\n        )\n      }\n\n      const entry = entryAssets[0]\n      if (!entry || typeof entry !== 'string') {\n        throw new Error(\n          `Entry \"${entryName}\" not found. Did you specify the correct entry option?`\n        )\n      }\n\n      const bundle = {\n        entry,\n        files: {},\n        maps: {}\n      }\n\n      stats.assets.forEach(asset => {\n        if (asset.name.match(/\\.js$/)) {\n          bundle.files[asset.name] = compilation.assets[asset.name].source()\n        } else if (asset.name.match(/\\.js\\.map$/)) {\n          bundle.maps[asset.name.replace(/\\.map$/, '')] = JSON.parse(compilation.assets[asset.name].source())\n        }\n        // do not emit anything else for server\n        delete compilation.assets[asset.name]\n      })\n\n      const json = JSON.stringify(bundle, null, 2)\n      const filename = this.options.filename\n\n      compilation.assets[filename] = {\n        source: () => json,\n        size: () => json.length\n      }\n\n      cb()\n    })\n  }\n}\n"
  },
  {
    "path": "src/server/webpack-plugin/util.js",
    "content": "const { red, yellow } = require('chalk')\n\nconst prefix = `[vue-server-renderer-webpack-plugin]`\nconst warn = exports.warn = msg => console.error(red(`${prefix} ${msg}\\n`))\nconst tip = exports.tip = msg => console.log(yellow(`${prefix} ${msg}\\n`))\n\nexport const validate = compiler => {\n  if (compiler.options.target !== 'node') {\n    warn('webpack config `target` should be \"node\".')\n  }\n\n  if (compiler.options.output && compiler.options.output.libraryTarget !== 'commonjs2') {\n    warn('webpack config `output.libraryTarget` should be \"commonjs2\".')\n  }\n\n  if (!compiler.options.externals) {\n    tip(\n      'It is recommended to externalize dependencies in the server build for ' +\n      'better build performance.'\n    )\n  }\n}\n\nexport { isJS, isCSS } from '../util'\n"
  },
  {
    "path": "src/server/write.js",
    "content": "/* @flow */\n\nconst MAX_STACK_DEPTH = 1000\n\nexport function createWriteFunction (\n  write: (text: string, next: Function) => boolean,\n  onError: Function\n): Function {\n  let stackDepth = 0\n  const cachedWrite = (text, next) => {\n    if (text && cachedWrite.caching) {\n      cachedWrite.cacheBuffer[cachedWrite.cacheBuffer.length - 1] += text\n    }\n    const waitForNext = write(text, next)\n    if (waitForNext !== true) {\n      if (stackDepth >= MAX_STACK_DEPTH) {\n        process.nextTick(() => {\n          try { next() } catch (e) {\n            onError(e)\n          }\n        })\n      } else {\n        stackDepth++\n        next()\n        stackDepth--\n      }\n    }\n  }\n  cachedWrite.caching = false\n  cachedWrite.cacheBuffer = []\n  cachedWrite.componentBuffer = []\n  return cachedWrite\n}\n"
  },
  {
    "path": "src/sfc/parser.js",
    "content": "/* @flow */\n\nimport deindent from 'de-indent'\nimport { parseHTML } from 'compiler/parser/html-parser'\nimport { makeMap } from 'shared/util'\n\nconst splitRE = /\\r?\\n/g\nconst replaceRE = /./g\nconst isSpecialTag = makeMap('script,style,template', true)\n\ntype Attribute = {\n  name: string,\n  value: string\n};\n\n/**\n * Parse a single-file component (*.vue) file into an SFC Descriptor Object.\n */\nexport function parseComponent (\n  content: string,\n  options?: Object = {}\n ): SFCDescriptor {\n  const sfc: SFCDescriptor = {\n    template: null,\n    script: null,\n    styles: [],\n    customBlocks: []\n  }\n  let depth = 0\n  let currentBlock: ?(SFCBlock | SFCCustomBlock) = null\n\n  function start (\n    tag: string,\n    attrs: Array<Attribute>,\n    unary: boolean,\n    start: number,\n    end: number\n  ) {\n    if (depth === 0) {\n      currentBlock = {\n        type: tag,\n        content: '',\n        start: end,\n        attrs: attrs.reduce((cumulated, { name, value }) => {\n          cumulated[name] = value || true\n          return cumulated\n        }, Object.create(null))\n      }\n      if (isSpecialTag(tag)) {\n        checkAttrs(currentBlock, attrs)\n        if (tag === 'style') {\n          sfc.styles.push(currentBlock)\n        } else {\n          sfc[tag] = currentBlock\n        }\n      } else { // custom blocks\n        sfc.customBlocks.push(currentBlock)\n      }\n    }\n    if (!unary) {\n      depth++\n    }\n  }\n\n  function checkAttrs (block: SFCBlock, attrs: Array<Attribute>) {\n    for (let i = 0; i < attrs.length; i++) {\n      const attr = attrs[i]\n      if (attr.name === 'lang') {\n        block.lang = attr.value\n      }\n      if (attr.name === 'scoped') {\n        block.scoped = true\n      }\n      if (attr.name === 'module') {\n        block.module = attr.value || true\n      }\n      if (attr.name === 'src') {\n        block.src = attr.value\n      }\n    }\n  }\n\n  function end (tag: string, start: number, end: number) {\n    if (depth === 1 && currentBlock) {\n      currentBlock.end = start\n      let text = deindent(content.slice(currentBlock.start, currentBlock.end))\n      // pad content so that linters and pre-processors can output correct\n      // line numbers in errors and warnings\n      if (currentBlock.type !== 'template' && options.pad) {\n        text = padContent(currentBlock, options.pad) + text\n      }\n      currentBlock.content = text\n      currentBlock = null\n    }\n    depth--\n  }\n\n  function padContent (block: SFCBlock | SFCCustomBlock, pad: true | \"line\" | \"space\") {\n    if (pad === 'space') {\n      return content.slice(0, block.start).replace(replaceRE, ' ')\n    } else {\n      const offset = content.slice(0, block.start).split(splitRE).length\n      const padChar = block.type === 'script' && !block.lang\n        ? '//\\n'\n        : '\\n'\n      return Array(offset).join(padChar)\n    }\n  }\n\n  parseHTML(content, {\n    start,\n    end\n  })\n\n  return sfc\n}\n"
  },
  {
    "path": "src/shared/constants.js",
    "content": "export const SSR_ATTR = 'data-server-rendered'\n\nexport const ASSET_TYPES = [\n  'component',\n  'directive',\n  'filter'\n]\n\nexport const LIFECYCLE_HOOKS = [\n  'beforeCreate',\n  'created',\n  'beforeMount',\n  'mounted',\n  'beforeUpdate',\n  'updated',\n  'beforeDestroy',\n  'destroyed',\n  'activated',\n  'deactivated'\n]\n"
  },
  {
    "path": "src/shared/util.js",
    "content": "/* @flow */\n\n// these helpers produces better vm code in JS engines due to their\n// explicitness and function inlining\nexport function isUndef (v: any): boolean %checks {\n  return v === undefined || v === null\n}\n\nexport function isDef (v: any): boolean %checks {\n  return v !== undefined && v !== null\n}\n\nexport function isTrue (v: any): boolean %checks {\n  return v === true\n}\n\nexport function isFalse (v: any): boolean %checks {\n  return v === false\n}\n\n/**\n * Check if value is primitive\n */\nexport function isPrimitive (value: any): boolean %checks {\n  return typeof value === 'string' || typeof value === 'number'\n}\n\n/**\n * Quick object check - this is primarily used to tell\n * Objects from primitive values when we know the value\n * is a JSON-compliant type.\n */\nexport function isObject (obj: mixed): boolean %checks {\n  return obj !== null && typeof obj === 'object'\n}\n\nconst _toString = Object.prototype.toString\n\n/**\n * Strict object type check. Only returns true\n * for plain JavaScript objects.\n */\nexport function isPlainObject (obj: any): boolean {\n  return _toString.call(obj) === '[object Object]'\n}\n\nexport function isRegExp (v: any): boolean {\n  return _toString.call(v) === '[object RegExp]'\n}\n\n/**\n * Check if val is a valid array index.\n */\nexport function isValidArrayIndex (val: any): boolean {\n  const n = parseFloat(val)\n  return n >= 0 && Math.floor(n) === n && isFinite(val)\n}\n\n/**\n * Convert a value to a string that is actually rendered.\n */\nexport function toString (val: any): string {\n  return val == null\n    ? ''\n    : typeof val === 'object'\n      ? JSON.stringify(val, null, 2)\n      : String(val)\n}\n\n/**\n * Convert a input value to a number for persistence.\n * If the conversion fails, return original string.\n */\nexport function toNumber (val: string): number | string {\n  const n = parseFloat(val)\n  return isNaN(n) ? val : n\n}\n\n/**\n * Make a map and return a function for checking if a key\n * is in that map.\n */\nexport function makeMap (\n  str: string,\n  expectsLowerCase?: boolean\n): (key: string) => true | void {\n  const map = Object.create(null)\n  const list: Array<string> = str.split(',')\n  for (let i = 0; i < list.length; i++) {\n    map[list[i]] = true\n  }\n  return expectsLowerCase\n    ? val => map[val.toLowerCase()]\n    : val => map[val]\n}\n\n/**\n * Check if a tag is a built-in tag.\n */\nexport const isBuiltInTag = makeMap('slot,component', true)\n\n/**\n * Check if a attribute is a reserved attribute.\n */\nexport const isReservedAttribute = makeMap('key,ref,slot,is')\n\n/**\n * Remove an item from an array\n */\nexport function remove (arr: Array<any>, item: any): Array<any> | void {\n  if (arr.length) {\n    const index = arr.indexOf(item)\n    if (index > -1) {\n      return arr.splice(index, 1)\n    }\n  }\n}\n\n/**\n * Check whether the object has the property.\n */\nconst hasOwnProperty = Object.prototype.hasOwnProperty\nexport function hasOwn (obj: Object | Array<*>, key: string): boolean {\n  return hasOwnProperty.call(obj, key)\n}\n\n/**\n * Create a cached version of a pure function.\n */\nexport function cached<F: Function> (fn: F): F {\n  const cache = Object.create(null)\n  return (function cachedFn (str: string) {\n    const hit = cache[str]\n    return hit || (cache[str] = fn(str))\n  }: any)\n}\n\n/**\n * Camelize a hyphen-delimited string.\n */\nconst camelizeRE = /-(\\w)/g\nexport const camelize = cached((str: string): string => {\n  return str.replace(camelizeRE, (_, c) => c ? c.toUpperCase() : '')\n})\n\n/**\n * Capitalize a string.\n */\nexport const capitalize = cached((str: string): string => {\n  return str.charAt(0).toUpperCase() + str.slice(1)\n})\n\n/**\n * Hyphenate a camelCase string.\n */\nconst hyphenateRE = /([^-])([A-Z])/g\nexport const hyphenate = cached((str: string): string => {\n  return str\n    .replace(hyphenateRE, '$1-$2')\n    .replace(hyphenateRE, '$1-$2')\n    .toLowerCase()\n})\n\n/**\n * Simple bind, faster than native\n */\nexport function bind (fn: Function, ctx: Object): Function {\n  function boundFn (a) {\n    const l: number = arguments.length\n    return l\n      ? l > 1\n        ? fn.apply(ctx, arguments)\n        : fn.call(ctx, a)\n      : fn.call(ctx)\n  }\n  // record original fn length\n  boundFn._length = fn.length\n  return boundFn\n}\n\n/**\n * Convert an Array-like object to a real Array.\n */\nexport function toArray (list: any, start?: number): Array<any> {\n  start = start || 0\n  let i = list.length - start\n  const ret: Array<any> = new Array(i)\n  while (i--) {\n    ret[i] = list[i + start]\n  }\n  return ret\n}\n\n/**\n * Mix properties into target object.\n */\nexport function extend (to: Object, _from: ?Object): Object {\n  for (const key in _from) {\n    to[key] = _from[key]\n  }\n  return to\n}\n\n/**\n * Merge an Array of Objects into a single Object.\n */\nexport function toObject (arr: Array<any>): Object {\n  const res = {}\n  for (let i = 0; i < arr.length; i++) {\n    if (arr[i]) {\n      extend(res, arr[i])\n    }\n  }\n  return res\n}\n\n/**\n * Perform no operation.\n * Stubbing args to make Flow happy without leaving useless transpiled code\n * with ...rest (https://flow.org/blog/2017/05/07/Strict-Function-Call-Arity/)\n */\nexport function noop (a?: any, b?: any, c?: any) {}\n\n/**\n * Always return false.\n */\nexport const no = (a?: any, b?: any, c?: any) => false\n\n/**\n * Return same value\n */\nexport const identity = (_: any) => _\n\n/**\n * Generate a static keys string from compiler modules.\n */\nexport function genStaticKeys (modules: Array<ModuleOptions>): string {\n  return modules.reduce((keys, m) => {\n    return keys.concat(m.staticKeys || [])\n  }, []).join(',')\n}\n\n/**\n * Check if two values are loosely equal - that is,\n * if they are plain objects, do they have the same shape?\n */\nexport function looseEqual (a: mixed, b: mixed): boolean {\n  const isObjectA = isObject(a)\n  const isObjectB = isObject(b)\n  if (isObjectA && isObjectB) {\n    try {\n      return JSON.stringify(a) === JSON.stringify(b)\n    } catch (e) {\n      // possible circular reference\n      return a === b\n    }\n  } else if (!isObjectA && !isObjectB) {\n    return String(a) === String(b)\n  } else {\n    return false\n  }\n}\n\nexport function looseIndexOf (arr: Array<mixed>, val: mixed): number {\n  for (let i = 0; i < arr.length; i++) {\n    if (looseEqual(arr[i], val)) return i\n  }\n  return -1\n}\n\n/**\n * Ensure a function is called only once.\n */\nexport function once (fn: Function): Function {\n  let called = false\n  return function () {\n    if (!called) {\n      called = true\n      fn.apply(this, arguments)\n    }\n  }\n}\n"
  },
  {
    "path": "test/e2e/.eslintrc",
    "content": "{\n  \"rules\": {\n    \"indent\": 0\n  }\n}\n"
  },
  {
    "path": "test/e2e/nightwatch.config.js",
    "content": "// http://nightwatchjs.org/guide#settings-file\nmodule.exports = {\n  'src_folders': ['test/e2e/specs'],\n  'output_folder': 'test/e2e/reports',\n  'custom_commands_path': ['node_modules/nightwatch-helpers/commands'],\n  'custom_assertions_path': ['node_modules/nightwatch-helpers/assertions'],\n\n  'selenium': {\n    'start_process': true,\n    'server_path': require('selenium-server').path,\n    'host': '127.0.0.1',\n    'port': 4444,\n    'cli_args': {\n      'webdriver.chrome.driver': require('chromedriver').path\n      // , 'webdriver.gecko.driver': require('geckodriver').path\n    }\n  },\n\n  'test_settings': {\n    'default': {\n      'selenium_port': 4444,\n      'selenium_host': 'localhost',\n      'silent': true,\n      'screenshots': {\n        'enabled': true,\n        'on_failure': true,\n        'on_error': false,\n        'path': 'test/e2e/screenshots'\n      }\n    },\n\n    'chrome': {\n      'desiredCapabilities': {\n        'browserName': 'chrome',\n        'javascriptEnabled': true,\n        'acceptSslCerts': true\n      }\n    },\n\n    'firefox': {\n      'desiredCapabilities': {\n        'browserName': 'firefox',\n        'javascriptEnabled': true,\n        'acceptSslCerts': true,\n        'marionette': true\n      }\n    },\n\n    'phantomjs': {\n      'desiredCapabilities': {\n        'browserName': 'phantomjs',\n        'javascriptEnabled': true,\n        'acceptSslCerts': true\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "test/e2e/runner.js",
    "content": "var path = require('path')\nvar spawn = require('cross-spawn')\nvar httpServer = require('http-server')\nvar server = httpServer.createServer({\n  root: path.resolve(__dirname, '../../')\n})\n\nserver.listen(8080)\n\nvar args = process.argv.slice(2)\nif (args.indexOf('--config') === -1) {\n  args = args.concat(['--config', 'test/e2e/nightwatch.config.js'])\n}\nif (args.indexOf('--env') === -1) {\n  args = args.concat(['--env', 'chrome,phantomjs'])\n}\nvar i = args.indexOf('--test')\nif (i > -1) {\n  args[i + 1] = 'test/e2e/specs/' + args[i + 1] + '.js'\n}\n\nvar runner = spawn('./node_modules/.bin/nightwatch', args, {\n  stdio: 'inherit'\n})\n\nrunner.on('exit', function (code) {\n  server.close()\n  process.exit(code)\n})\n\nrunner.on('error', function (err) {\n  server.close()\n  throw err\n})\n"
  },
  {
    "path": "test/e2e/specs/commits.js",
    "content": "module.exports = {\n  'commits': function (browser) {\n    browser\n    .url('http://localhost:8080/examples/commits/')\n      .waitForElementVisible('li', 5000)\n      .assert.count('input', 2)\n      .assert.count('label', 2)\n      .assert.containsText('label[for=\"master\"]', 'master')\n      .assert.containsText('label[for=\"dev\"]', 'dev')\n      .assert.checked('#master')\n      .assert.checked('#dev', false)\n      .assert.containsText('p', 'vuejs/vue@master')\n      .assert.count('li', 3)\n      .assert.count('li .commit', 3)\n      .assert.count('li .message', 3)\n      .click('#dev')\n      .assert.containsText('p', 'vuejs/vue@dev')\n      .assert.count('li', 3)\n      .assert.count('li .commit', 3)\n      .assert.count('li .message', 3)\n      .end()\n  }\n}\n"
  },
  {
    "path": "test/e2e/specs/grid.js",
    "content": "module.exports = {\n  'grid': function (browser) {\n    var columns = ['name', 'power']\n\n    browser\n    .url('http://localhost:8080/examples/grid/')\n      .waitForElementVisible('table', 1000)\n      .assert.count('th', 2)\n      .assert.count('th.active', 0)\n      .assert.containsText('th:nth-child(1)', 'Name')\n      .assert.containsText('th:nth-child(2)', 'Power')\n      assertTable([\n        { name: 'Chuck Norris', power: Infinity },\n        { name: 'Bruce Lee', power: 9000 },\n        { name: 'Jackie Chan', power: 7000 },\n        { name: 'Jet Li', power: 8000 }\n      ])\n\n    browser\n      .click('th:nth-child(1)')\n      .assert.count('th.active:nth-child(1)', 1)\n      .assert.count('th.active:nth-child(2)', 0)\n      .assert.count('th:nth-child(1) .arrow.dsc', 1)\n      .assert.count('th:nth-child(2) .arrow.dsc', 0)\n      assertTable([\n        { name: 'Jet Li', power: 8000 },\n        { name: 'Jackie Chan', power: 7000 },\n        { name: 'Chuck Norris', power: Infinity },\n        { name: 'Bruce Lee', power: 9000 }\n      ])\n\n    browser\n      .click('th:nth-child(2)')\n      .assert.count('th.active:nth-child(1)', 0)\n      .assert.count('th.active:nth-child(2)', 1)\n      .assert.count('th:nth-child(1) .arrow.dsc', 1)\n      .assert.count('th:nth-child(2) .arrow.dsc', 1)\n      assertTable([\n        { name: 'Chuck Norris', power: Infinity },\n        { name: 'Bruce Lee', power: 9000 },\n        { name: 'Jet Li', power: 8000 },\n        { name: 'Jackie Chan', power: 7000 }\n      ])\n\n    browser\n      .click('th:nth-child(2)')\n      .assert.count('th.active:nth-child(1)', 0)\n      .assert.count('th.active:nth-child(2)', 1)\n      .assert.count('th:nth-child(1) .arrow.dsc', 1)\n      .assert.count('th:nth-child(2) .arrow.asc', 1)\n      assertTable([\n        { name: 'Jackie Chan', power: 7000 },\n        { name: 'Jet Li', power: 8000 },\n        { name: 'Bruce Lee', power: 9000 },\n        { name: 'Chuck Norris', power: Infinity }\n      ])\n\n    browser\n      .click('th:nth-child(1)')\n      .assert.count('th.active:nth-child(1)', 1)\n      .assert.count('th.active:nth-child(2)', 0)\n      .assert.count('th:nth-child(1) .arrow.asc', 1)\n      .assert.count('th:nth-child(2) .arrow.asc', 1)\n      assertTable([\n        { name: 'Bruce Lee', power: 9000 },\n        { name: 'Chuck Norris', power: Infinity },\n        { name: 'Jackie Chan', power: 7000 },\n        { name: 'Jet Li', power: 8000 }\n      ])\n\n    browser\n      .setValue('input[name=\"query\"]', 'j')\n      assertTable([\n        { name: 'Jackie Chan', power: 7000 },\n        { name: 'Jet Li', power: 8000 }\n      ])\n\n    browser\n      .clearValue('input[name=\"query\"]')\n      .setValue('input[name=\"query\"]', 'infinity')\n      assertTable([\n        { name: 'Chuck Norris', power: Infinity }\n      ])\n\n    browser\n      .clearValue('input[name=\"query\"]')\n      .assert.count('p', 0)\n      .setValue('input[name=\"query\"]', 'stringthatdoesnotexistanywhere')\n      .assert.count('p', 1)\n\n    browser.end()\n\n    function assertTable (data) {\n      browser.assert.count('td', data.length * columns.length)\n      for (var i = 0; i < data.length; i++) {\n        for (var j = 0; j < columns.length; j++) {\n          browser.assert.containsText(\n            'tr:nth-child(' + (i + 1) + ') td:nth-child(' + (j + 1) + ')',\n            data[i][columns[j]]\n          )\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "test/e2e/specs/markdown.js",
    "content": "module.exports = {\n  'markdown': function (browser) {\n    browser\n    .url('http://localhost:8080/examples/markdown/')\n      .waitForElementVisible('#editor', 1000)\n      .assert.value('textarea', '# hello')\n      .assert.hasHTML('#editor div', '<h1 id=\"hello\">hello</h1>')\n      .setValue('textarea', '\\n## foo\\n\\n- bar\\n- baz')\n      // assert the output is not updated yet because of debounce\n      .assert.hasHTML('#editor div', '<h1 id=\"hello\">hello</h1>')\n      .waitFor(500)\n      .assert.hasHTML('#editor div',\n        '<h1 id=\"hello\">hello</h1>\\n' +\n        '<h2 id=\"foo\">foo</h2>\\n' +\n        '<ul>\\n<li>bar</li>\\n<li>baz</li>\\n</ul>'\n      )\n      .end()\n  }\n}\n"
  },
  {
    "path": "test/e2e/specs/modal.js",
    "content": "module.exports = {\n  'modal': function (browser) {\n    browser\n    .url('http://localhost:8080/examples/modal/')\n      .waitForElementVisible('#app', 1000)\n      .assert.elementNotPresent('.modal-mask')\n      .click('#show-modal')\n      .assert.elementPresent('.modal-mask')\n      .assert.elementPresent('.modal-wrapper')\n      .assert.elementPresent('.modal-container')\n      .waitFor(50)\n      .assert.cssClassPresent('.modal-mask', 'modal-enter-active')\n      .waitFor(300)\n      .assert.cssClassNotPresent('.modal-mask', 'modal-enter-active')\n      .assert.containsText('.modal-header h3', 'custom header')\n      .assert.containsText('.modal-body', 'default body')\n      .assert.containsText('.modal-footer', 'default footer')\n      .click('.modal-default-button')\n      // should have transition\n      .assert.elementPresent('.modal-mask')\n      .waitFor(50)\n      .assert.cssClassPresent('.modal-mask', 'modal-leave-active')\n      .waitFor(300)\n      .assert.elementNotPresent('.modal-mask')\n      .end()\n  }\n}\n"
  },
  {
    "path": "test/e2e/specs/select2.js",
    "content": "/* globals vm */\nmodule.exports = {\n  'select2': function (browser) {\n    browser\n    .url('http://localhost:8080/examples/select2/')\n      .waitForElementVisible('.select2', 1000)\n      .assert.elementPresent('select')\n      .assert.containsText('p', 'Selected: 0')\n      .assert.containsText('span.select2', 'Select one')\n\n      .click('.select2-selection__rendered')\n      .assert.count('.select2-results__option', 3)\n      .assert.containsText('.select2-results__option:nth-child(1)', 'Select one')\n      .assert.containsText('.select2-results__option:nth-child(2)', 'Hello')\n      .assert.containsText('.select2-results__option:nth-child(3)', 'World')\n      .assert.attributePresent('.select2-results__option:nth-child(1)', 'aria-disabled')\n\n      .click('.select2-results__option:nth-child(2)')\n      .assert.count('.select2-results__option', 0)\n      .assert.containsText('p', 'Selected: 1')\n      .assert.containsText('span.select2', 'Hello')\n\n      // test dynamic options\n      .execute(function () {\n        vm.options.push({ id: 3, text: 'Vue' })\n      })\n      .click('.select2-selection__rendered')\n      .assert.count('.select2-results__option', 4)\n      .assert.containsText('.select2-results__option:nth-child(1)', 'Select one')\n      .assert.containsText('.select2-results__option:nth-child(2)', 'Hello')\n      .assert.containsText('.select2-results__option:nth-child(3)', 'World')\n      .assert.containsText('.select2-results__option:nth-child(4)', 'Vue')\n\n      .click('.select2-results__option:nth-child(4)')\n      .assert.count('.select2-results__option', 0)\n      .assert.containsText('p', 'Selected: 3')\n      .assert.containsText('span.select2', 'Vue')\n\n      .execute(function () {\n        vm.selected = 2\n      })\n      .assert.containsText('p', 'Selected: 2')\n      .assert.containsText('span.select2', 'World')\n      .end()\n  }\n}\n"
  },
  {
    "path": "test/e2e/specs/svg.js",
    "content": "/* globals stats, valueToPoint */\nmodule.exports = {\n  'svg': function (browser) {\n    browser\n    .url('http://localhost:8080/examples/svg/')\n      .waitForElementVisible('svg', 1000)\n      .assert.count('g', 1)\n      .assert.count('polygon', 1)\n      .assert.count('circle', 1)\n      .assert.count('text', 6)\n      .assert.count('label', 6)\n      .assert.count('button', 7)\n      .assert.count('input[type=\"range\"]', 6)\n      .assert.evaluate(function () {\n        var points = stats.map(function (stat, i) {\n        var point = valueToPoint(stat.value, i, 6)\n          return point.x + ',' + point.y\n        }).join(' ')\n        return document.querySelector('polygon').attributes[0].value === points\n      })\n      .click('button.remove')\n      .assert.count('text', 5)\n      .assert.count('label', 5)\n      .assert.count('button', 6)\n      .assert.count('input[type=\"range\"]', 5)\n      .assert.evaluate(function () {\n        var points = stats.map(function (stat, i) {\n        var point = valueToPoint(stat.value, i, 5)\n          return point.x + ',' + point.y\n        }).join(' ')\n        return document.querySelector('polygon').attributes[0].value === points\n      })\n      .setValue('input[name=\"newlabel\"]', 'foo')\n      .click('#add > button')\n      .assert.count('text', 6)\n      .assert.count('label', 6)\n      .assert.count('button', 7)\n      .assert.count('input[type=\"range\"]', 6)\n      .assert.evaluate(function () {\n        var points = stats.map(function (stat, i) {\n        var point = valueToPoint(stat.value, i, 6)\n          return point.x + ',' + point.y\n        }).join(' ')\n        return document.querySelector('polygon').attributes[0].value === points\n      })\n      .end()\n  }\n}\n"
  },
  {
    "path": "test/e2e/specs/todomvc.js",
    "content": "module.exports = {\n  'todomvc': function (browser) {\n    browser\n    .url('http://localhost:8080/examples/todomvc/#test')\n      .waitForElementVisible('.todoapp', 1000)\n      .assert.notVisible('.main')\n      .assert.notVisible('.footer')\n      .assert.count('.filters .selected', 1)\n      .assert.evaluate(function () {\n        return document.querySelector('.filters .selected').textContent === 'All'\n      })\n\n    createNewItem('test')\n      .assert.count('.todo', 1)\n      .assert.notVisible('.todo .edit')\n      .assert.containsText('.todo label', 'test')\n      .assert.containsText('.todo-count strong', '1')\n      .assert.checked('.todo .toggle', false)\n      .assert.visible('.main')\n      .assert.visible('.footer')\n      .assert.notVisible('.clear-completed')\n      .assert.value('.new-todo', '')\n\n    createNewItem('test2')\n      .assert.count('.todo', 2)\n      .assert.containsText('.todo:nth-child(2) label', 'test2')\n      .assert.containsText('.todo-count strong', '2')\n\n    // toggle\n    browser\n      .click('.todo .toggle')\n      .assert.count('.todo.completed', 1)\n      .assert.cssClassPresent('.todo:nth-child(1)', 'completed')\n      .assert.containsText('.todo-count strong', '1')\n      .assert.visible('.clear-completed')\n\n    createNewItem('test3')\n      .assert.count('.todo', 3)\n      .assert.containsText('.todo:nth-child(3) label', 'test3')\n      .assert.containsText('.todo-count strong', '2')\n\n    createNewItem('test4')\n    createNewItem('test5')\n      .assert.count('.todo', 5)\n      .assert.containsText('.todo-count strong', '4')\n\n    // toggle more\n    browser\n      .click('.todo:nth-child(4) .toggle')\n      .click('.todo:nth-child(5) .toggle')\n      .assert.count('.todo.completed', 3)\n      .assert.containsText('.todo-count strong', '2')\n\n    // remove\n    removeItemAt(1)\n      .assert.count('.todo', 4)\n      .assert.count('.todo.completed', 2)\n      .assert.containsText('.todo-count strong', '2')\n    removeItemAt(2)\n      .assert.count('.todo', 3)\n      .assert.count('.todo.completed', 2)\n      .assert.containsText('.todo-count strong', '1')\n\n    // remove all\n    browser\n      .click('.clear-completed')\n      .assert.count('.todo', 1)\n      .assert.containsText('.todo label', 'test2')\n      .assert.count('.todo.completed', 0)\n      .assert.containsText('.todo-count strong', '1')\n      .assert.notVisible('.clear-completed')\n\n    // prepare to test filters\n    createNewItem('test')\n    createNewItem('test')\n      .click('.todo:nth-child(2) .toggle')\n      .click('.todo:nth-child(3) .toggle')\n\n    // active filter\n    browser\n      .click('.filters li:nth-child(2) a')\n      .assert.count('.todo', 1)\n      .assert.count('.todo.completed', 0)\n      // add item with filter active\n      createNewItem('test')\n      .assert.count('.todo', 2)\n\n    // completed filter\n    browser.click('.filters li:nth-child(3) a')\n      .assert.count('.todo', 2)\n      .assert.count('.todo.completed', 2)\n\n    // filter on page load\n    browser.url('http://localhost:8080/examples/todomvc/#active')\n      .assert.count('.todo', 2)\n      .assert.count('.todo.completed', 0)\n      .assert.containsText('.todo-count strong', '2')\n\n    // completed on page load\n    browser.url('http://localhost:8080/examples/todomvc/#completed')\n      .assert.count('.todo', 2)\n      .assert.count('.todo.completed', 2)\n      .assert.containsText('.todo-count strong', '2')\n\n    // toggling with filter active\n    browser\n      .click('.todo .toggle')\n      .assert.count('.todo', 1)\n      .click('.filters li:nth-child(2) a')\n      .assert.count('.todo', 3)\n      .click('.todo .toggle')\n      .assert.count('.todo', 2)\n\n    // editing triggered by blur\n    browser\n      .click('.filters li:nth-child(1) a')\n      .dblClick('.todo:nth-child(1) label')\n      .assert.count('.todo.editing', 1)\n      .assert.focused('.todo:nth-child(1) .edit')\n      .clearValue('.todo:nth-child(1) .edit')\n      .setValue('.todo:nth-child(1) .edit', 'edited!')\n      .click('footer') // blur\n      .assert.count('.todo.editing', 0)\n      .assert.containsText('.todo:nth-child(1) label', 'edited!')\n\n    // editing triggered by enter\n    browser\n      .dblClick('.todo label')\n      .enterValue('.todo:nth-child(1) .edit', 'edited again!')\n      .assert.count('.todo.editing', 0)\n      .assert.containsText('.todo:nth-child(1) label', 'edited again!')\n\n    // cancel\n    browser\n      .dblClick('.todo label')\n      .clearValue('.todo:nth-child(1) .edit')\n      .setValue('.todo:nth-child(1) .edit', 'edited!')\n      .trigger('.todo:nth-child(1) .edit', 'keyup', 27)\n      .assert.count('.todo.editing', 0)\n      .assert.containsText('.todo:nth-child(1) label', 'edited again!')\n\n    // empty value should remove\n    browser\n      .dblClick('.todo label')\n      .enterValue('.todo:nth-child(1) .edit', ' ')\n      .assert.count('.todo', 3)\n\n    // toggle all\n    browser\n      .click('.toggle-all')\n      .assert.count('.todo.completed', 3)\n      .click('.toggle-all')\n      .assert.count('.todo:not(.completed)', 3)\n      .end()\n\n    function createNewItem (text) {\n      return browser.enterValue('.new-todo', text)\n    }\n\n    function removeItemAt (n) {\n      return browser\n        .moveToElement('.todo:nth-child(' + n + ')', 10, 10)\n        .click('.todo:nth-child(' + n + ') .destroy')\n    }\n  }\n}\n"
  },
  {
    "path": "test/e2e/specs/tree.js",
    "content": "module.exports = {\n  'tree': function (browser) {\n    browser\n    .url('http://localhost:8080/examples/tree/')\n      .waitForElementVisible('li', 1000)\n      .assert.count('.item', 12)\n      .assert.count('.add', 4)\n      .assert.count('.item > ul', 4)\n      .assert.notVisible('#demo li ul')\n      .assert.containsText('#demo li div span', '[+]')\n\n      // expand root\n      .click('.bold')\n      .assert.visible('#demo ul')\n      .assert.evaluate(function () {\n        return document.querySelector('#demo li ul').children.length === 4\n      })\n      .assert.containsText('#demo li div span', '[-]')\n      .assert.containsText('#demo > .item > ul > .item:nth-child(1)', 'hello')\n      .assert.containsText('#demo > .item > ul > .item:nth-child(2)', 'wat')\n      .assert.containsText('#demo > .item > ul > .item:nth-child(3)', 'child folder')\n      .assert.containsText('#demo > .item > ul > .item:nth-child(3)', '[+]')\n\n      // add items to root\n      .click('#demo > .item > ul > .add')\n      .assert.evaluate(function () {\n        return document.querySelector('#demo li ul').children.length === 5\n      })\n      .assert.containsText('#demo > .item > ul > .item:nth-child(1)', 'hello')\n      .assert.containsText('#demo > .item > ul > .item:nth-child(2)', 'wat')\n      .assert.containsText('#demo > .item > ul > .item:nth-child(3)', 'child folder')\n      .assert.containsText('#demo > .item > ul > .item:nth-child(3)', '[+]')\n      .assert.containsText('#demo > .item > ul > .item:nth-child(4)', 'new stuff')\n\n      // add another item\n      .click('#demo > .item > ul > .add')\n      .assert.evaluate(function () {\n        return document.querySelector('#demo li ul').children.length === 6\n      })\n      .assert.containsText('#demo > .item > ul > .item:nth-child(1)', 'hello')\n      .assert.containsText('#demo > .item > ul > .item:nth-child(2)', 'wat')\n      .assert.containsText('#demo > .item > ul > .item:nth-child(3)', 'child folder')\n      .assert.containsText('#demo > .item > ul > .item:nth-child(3)', '[+]')\n      .assert.containsText('#demo > .item > ul > .item:nth-child(4)', 'new stuff')\n      .assert.containsText('#demo > .item > ul > .item:nth-child(5)', 'new stuff')\n\n      .click('#demo ul .bold')\n      .assert.visible('#demo ul ul')\n      .assert.containsText('#demo ul > .item:nth-child(3)', '[-]')\n      .assert.evaluate(function () {\n        return document.querySelector('#demo ul ul').children.length === 5\n      })\n\n      .click('.bold')\n      .assert.notVisible('#demo ul')\n      .assert.containsText('#demo li div span', '[+]')\n      .click('.bold')\n      .assert.visible('#demo ul')\n      .assert.containsText('#demo li div span', '[-]')\n\n      .dblClick('#demo ul > .item div')\n      .assert.count('.item', 15)\n      .assert.count('.item > ul', 5)\n      .assert.containsText('#demo ul > .item:nth-child(1)', '[-]')\n      .assert.evaluate(function () {\n        var firstItem = document.querySelector('#demo ul > .item:nth-child(1)')\n        var ul = firstItem.querySelector('ul')\n        return ul.children.length === 2\n      })\n      .end()\n  }\n}\n"
  },
  {
    "path": "test/helpers/.eslintrc",
    "content": "{\n  \"env\": {\n    \"jasmine\": true\n  },\n  \"globals\": {\n    \"waitForUpdate\": true\n  }\n}\n"
  },
  {
    "path": "test/helpers/classlist.js",
    "content": "beforeEach(() => {\n  jasmine.addMatchers({\n    // since classList may not be supported in all browsers\n    toHaveClass: () => {\n      return {\n        compare: (el, cls) => {\n          const pass = el.classList\n            ? el.classList.contains(cls)\n            : el.getAttribute('class').split(/\\s+/g).indexOf(cls) > -1\n          return {\n            pass,\n            message: `Expected element${pass ? ' ' : ' not '}to have class ${cls}`\n          }\n        }\n      }\n    }\n  })\n})\n"
  },
  {
    "path": "test/helpers/test-object-option.js",
    "content": "import Vue from 'vue'\n\nexport default function testObjectOption (name) {\n  it('should warn non object value', () => {\n    const options = {}\n    options[name] = () => {}\n    new Vue(options)\n    expect(`component option \"${name}\" should be an object`).toHaveBeenWarned()\n  })\n\n  it('should not warn valid object value', () => {\n    const options = {}\n    options[name] = {}\n    new Vue(options)\n    expect(`component option \"${name}\" should be an object`).not.toHaveBeenWarned()\n  })\n}\n"
  },
  {
    "path": "test/helpers/to-equal.js",
    "content": "import { isEqual } from 'lodash'\n\nbeforeEach(() => {\n  jasmine.addMatchers({\n    // override built-in toEqual because it behaves incorrectly\n    // on Vue-observed arrays in Safari\n    toEqual: () => {\n      return {\n        compare: (a, b) => {\n          const pass = isEqual(a, b)\n          return {\n            pass,\n            message: `Expected ${a} to equal ${b}`\n          }\n        }\n      }\n    }\n  })\n})\n"
  },
  {
    "path": "test/helpers/to-have-been-warned.js",
    "content": "function noop () {}\n\nif (typeof console === 'undefined') {\n  window.console = {\n    warn: noop,\n    error: noop\n  }\n}\n\n// avoid info messages during test\nconsole.info = noop\n\nlet asserted\n\nfunction createCompareFn (spy) {\n  const hasWarned = msg => {\n    var count = spy.calls.count()\n    var args\n    while (count--) {\n      args = spy.calls.argsFor(count)\n      if (args.some(containsMsg)) {\n        return true\n      }\n    }\n\n    function containsMsg (arg) {\n      return arg.toString().indexOf(msg) > -1\n    }\n  }\n\n  return {\n    compare: msg => {\n      asserted = asserted.concat(msg)\n      var warned = Array.isArray(msg)\n        ? msg.some(hasWarned)\n        : hasWarned(msg)\n      return {\n        pass: warned,\n        message: warned\n          ? 'Expected message \"' + msg + '\" not to have been warned'\n          : 'Expected message \"' + msg + '\" to have been warned'\n      }\n    }\n  }\n}\n\n// define custom matcher for warnings\nbeforeEach(() => {\n  asserted = []\n  spyOn(console, 'warn')\n  spyOn(console, 'error')\n  jasmine.addMatchers({\n    toHaveBeenWarned: () => createCompareFn(console.error),\n    toHaveBeenTipped: () => createCompareFn(console.warn)\n  })\n})\n\nafterEach(done => {\n  const warned = msg => asserted.some(assertedMsg => msg.toString().indexOf(assertedMsg) > -1)\n  let count = console.error.calls.count()\n  let args\n  while (count--) {\n    args = console.error.calls.argsFor(count)\n    if (!warned(args[0])) {\n      done.fail(`Unexpected console.error message: ${args[0]}`)\n      return\n    }\n  }\n  done()\n})\n"
  },
  {
    "path": "test/helpers/trigger-event.js",
    "content": "window.triggerEvent = function triggerEvent (target, event, process) {\n  var e = document.createEvent('HTMLEvents')\n  e.initEvent(event, true, true)\n  if (process) process(e)\n  target.dispatchEvent(e)\n}\n"
  },
  {
    "path": "test/helpers/vdom.js",
    "content": "import VNode from 'core/vdom/vnode'\n\nwindow.createTextVNode = function (text) {\n  return new VNode(undefined, undefined, undefined, text)\n}\n"
  },
  {
    "path": "test/helpers/wait-for-update.js",
    "content": "import Vue from 'vue'\n\n// helper for async assertions.\n// Use like this:\n//\n// vm.a = 123\n// waitForUpdate(() => {\n//   expect(vm.$el.textContent).toBe('123')\n//   vm.a = 234\n// })\n// .then(() => {\n//   // more assertions...\n// })\n// .then(done)\nwindow.waitForUpdate = initialCb => {\n  let end\n  const queue = initialCb ? [initialCb] : []\n\n  function shift () {\n    const job = queue.shift()\n    if (queue.length) {\n      let hasError = false\n      try {\n        job.wait ? job(shift) : job()\n      } catch (e) {\n        hasError = true\n        const done = queue[queue.length - 1]\n        if (done && done.fail) {\n          done.fail(e)\n        }\n      }\n      if (!hasError && !job.wait) {\n        if (queue.length) {\n          Vue.nextTick(shift)\n        }\n      }\n    } else if (job && (job.fail || job === end)) {\n      job() // done\n    }\n  }\n\n  Vue.nextTick(() => {\n    if (!queue.length || (!end && !queue[queue.length - 1].fail)) {\n      throw new Error('waitForUpdate chain is missing .then(done)')\n    }\n    shift()\n  })\n\n  const chainer = {\n    then: nextCb => {\n      queue.push(nextCb)\n      return chainer\n    },\n    thenWaitFor: (wait) => {\n      if (typeof wait === 'number') {\n        wait = timeout(wait)\n      }\n      wait.wait = true\n      queue.push(wait)\n      return chainer\n    },\n    end: endFn => {\n      queue.push(endFn)\n      end = endFn\n    }\n  }\n\n  return chainer\n}\n\nfunction timeout (n) {\n  return next => setTimeout(next, n)\n}\n"
  },
  {
    "path": "test/mp/.eslintrc",
    "content": "{\n  \"parser\": \"babel-eslint\",\n  \"parserOptions\": {\n    \"sourceType\": \"module\"\n  },\n  \"env\": {\n    \"browser\": false,\n    \"node\": true,\n    \"es6\": true,\n    \"jasmine\": true\n  },\n  \"plugins\": [\n    \"jasmine\"\n  ],\n  \"rules\": {\n    \"arrow-parens\": 0,\n    \"generator-star-spacing\": 0,\n    \"jasmine/no-focused-tests\": 2\n  },\n  \"globals\": {\n    \"App\": true,\n    \"Page\": true,\n    \"wx\": true,\n    \"getApp\": true,\n    \"getPage\": true\n  }\n}"
  },
  {
    "path": "test/mp/compiler/index.spec.js",
    "content": "const { compile, compileToMPML } = require('../../../packages/mpvue-template-compiler')\n// const { strToRegExp } = require('../helpers/index')\n\nfunction assertCodegen (template, assertTemplate, options, parmas = {}) {\n  const { errors = [], mpErrors = [], slots = {}, mpTips = [] } = parmas\n  const compiled = compile(template, {})\n  const output = compileToMPML(compiled, options)\n  expect(output.compiled.mpErrors).toEqual(mpErrors)\n  expect(output.compiled.mpTips).toEqual(mpTips)\n  expect(output.compiled.errors).toEqual(errors)\n  // console.log(JSON.stringify(output.slots))\n  expect(JSON.stringify(output.slots)).toEqual(JSON.stringify(slots))\n  expect(output.code).toEqual(assertTemplate)\n  // expect(output.code.replace(/\\n/g, '')).toMatch(strToRegExp(assertTemplate))\n}\n\ndescribe('a', () => {\n  it('tag a', () => {\n    assertCodegen(\n      `<a></a>`,\n      `<template name=\"a\"><view class=\"_a\"></view></template>`,\n      { name: 'a' }\n    )\n  })\n  it('tag a href', () => {\n    assertCodegen(\n      `<a href=\"s\"></a>`,\n      `<template name=\"a\"><navigator url=\"s\" class=\"_a\"></navigator></template>`,\n      { name: 'a' }\n    )\n  })\n  it('tag a :href', () => {\n    assertCodegen(\n      `<a :href=\"s\"></a>`,\n      `<template name=\"a\"><navigator url=\"{{s}}\" class=\"_a\"></navigator></template>`,\n      { name: 'a' }\n    )\n  })\n\n  it('input type', () => {\n    assertCodegen(\n      `<input type=\"button\" value=\"Click me\"></input>`,\n      `<template name=\"a\"><button class=\"_input\">Click me</button></template>`,\n      { name: 'a' }\n    )\n    assertCodegen(\n      `<input type=\"radio\"></input>`,\n      `<template name=\"a\"><radio class=\"_input\" /></template>`,\n      { name: 'a' }\n    )\n    assertCodegen(\n      `<input type=\"checkbox\" ></input>`,\n      `<template name=\"a\"><checkbox class=\"_input\" /></template>`,\n      { name: 'a' }\n    )\n  })\n})\n\ndescribe('指令', () => {\n  it('v-if', () => {\n    assertCodegen(\n      `<div v-if=\"ss\"></div>`,\n      `<template name=\"a\"><view wx:if=\"{{ss}}\" class=\"_div\"></view></template>`,\n      { name: 'a' }\n    )\n  })\n\n  it('v-for', () => {\n    assertCodegen(\n      `<div><div v-for=\"(item, indexx) in ss\" :key=\"indexx\"></div></div>`,\n      `<template name=\"a\"><view class=\"_div\"><view wx:key=\"indexx\" key=\"{{indexx}}\" wx:for=\"{{ss}}\" wx:for-index=\"indexx\" wx:for-item=\"item\" class=\"_div\"></view></view></template>`,\n      { name: 'a' }\n    )\n    // bug mpcomid=\"'0-'+index\"\n    assertCodegen(\n      `<div><my-component v-for=\"item in items\" :key=\"item.id\"></my-component></div>`,\n      `<import src=\"/components/card\" /><template name=\"a\"><view class=\"_div hashValue\"><template wx:key=\"item.id\" data=\"{{...$root[$kk+'0-'+index], $root}}\" is=\"my-component\" wx:for=\"{{items}}\" wx:for-index=\"index\" wx:for-item=\"item\"></template></view></template>`,\n      {\n        name: 'a',\n        components: {\n          'my-component': {\n            name: 'my-component',\n            src: '/components/card'\n          }\n        },\n        moduleId: 'hashValue'\n      }\n    )\n  })\n\n  it('v-if && v-for', () => {\n    assertCodegen(\n      `<div><p v-if=\"item.length\" v-for=\"item in list\"></p></div>`,\n      `<template name=\"a\"><view class=\"_div\"><view wx:if=\"{{item.length}}\" wx:for=\"{{list}}\" wx:for-index=\"index\" wx:for-item=\"item\" class=\"_p\"></view></view></template>`,\n      { name: 'a' }\n    )\n  })\n\n  it('v-if && event', () => {\n    assertCodegen(\n      `<div v-if=\"item.length\" @click=\"clickHandle\"></div>`,\n      `<template name=\"a\"><view wx:if=\"{{item.length}}\" bindtap=\"handleProxy\" data-eventid=\"{{'0'}}\" data-comkey=\"{{$k}}\" class=\"_div\"></view></template>`,\n      { name: 'a' }\n    )\n  })\n\n  it('v-if && v-for && event', () => {\n    assertCodegen(\n      `<div><p v-if=\"item.length\" v-for=\"item in list\" @click=\"clickHandle\"></p></div>`,\n      `<template name=\"a\"><view class=\"_div\"><view wx:if=\"{{item.length}}\" bindtap=\"handleProxy\" data-eventid=\"{{'0-'+index}}\" data-comkey=\"{{$k}}\" wx:for=\"{{list}}\" wx:for-index=\"index\" wx:for-item=\"item\" class=\"_p\"></view></view></template>`,\n      { name: 'a' }\n    )\n  })\n\n  it('v-for && event', () => {\n    assertCodegen(\n      `<div><p v-for=\"item in list\" @click=\"clickHandle\"></p></div>`,\n      `<template name=\"a\"><view class=\"_div\"><view bindtap=\"handleProxy\" data-eventid=\"{{'0-'+index}}\" data-comkey=\"{{$k}}\" wx:for=\"{{list}}\" wx:for-index=\"index\" wx:for-item=\"item\" class=\"_p\"></view></view></template>`,\n      { name: 'a' }\n    )\n  })\n\n  it('v-bind', () => {\n    assertCodegen(\n      `<div :a=\"s\"></div>`,\n      `<template name=\"a\"><view a=\"{{s}}\" class=\"_div\"></view></template>`,\n      { name: 'a' }\n    )\n  })\n\n  it('v-bind', () => {\n    assertCodegen(\n      `<div v-bind:a=\"s\"></div>`,\n      `<template name=\"a\"><view a=\"{{s}}\" class=\"_div\"></view></template>`,\n      { name: 'a' }\n    )\n  })\n\n  it('v-bind', () => {\n    assertCodegen(\n      `<div v-bind:a=\"a + 1\"></div>`,\n      `<template name=\"a\"><view a=\"{{a + 1}}\" class=\"_div\"></view></template>`,\n      { name: 'a' }\n    )\n  })\n\n  it('v-bind:class', () => {\n    assertCodegen(\n      `<div v-bind:class=\"{ active: isActive }\"></div>`,\n      `<template name=\"a\"><view class=\"_div {{[isActive ? 'active' : '']}}\"></view></template>`,\n      { name: 'a' }\n    )\n    assertCodegen(\n      `<div class=\"static\"  v-bind:class=\"{ active: isActive, 'textDanger': hasError }\"></div>`,\n      `<template name=\"a\"><view class=\"_div static {{[isActive ? 'active' : '', hasError ? 'textDanger' : '']}}\"></view></template>`,\n      { name: 'a' }\n    )\n    assertCodegen(\n      `<my-component class=\"baz boo\"></my-component>`,\n      `<import src=\"/components/card\" /><template name=\"a\"><template data=\"{{...$root[$kk+'0'], $root}}\" is=\"my-component\"></template></template>`,\n      {\n        name: 'a',\n        components: {\n          'my-component': {\n            name: 'my-component',\n            src: '/components/card'\n          }\n        },\n        moduleId: 'hashValue'\n      },\n      {\n        mpTips: ['template 不支持此属性-> class=\"baz boo\"'],\n        mpErrors: []\n      }\n    )\n\n    // object\n    assertCodegen(\n      `<div><p :class=\"{ active: isActive }\">233</p></div>`,\n      `<template name=\"a\"><view class=\"_div\"><view class=\"_p {{[isActive ? 'active' : '']}}\">233</view></view></template>`,\n      { name: 'a' }\n    )\n    assertCodegen(\n      `<div><p class=\"static\" v-bind:class=\"{ active: isActive, 'text-danger': hasError }\">233</p></div>`,\n      `<template name=\"a\"><view class=\"_div\"><view class=\"_p static {{[isActive ? 'active' : '', hasError ? 'text-danger' : '']}}\">233</view></view></template>`,\n      { name: 'a' }\n    )\n    assertCodegen(\n      `<div><p class=\"static\" v-bind:class=\"computedClassStr\">233</p></div>`,\n      `<template name=\"a\"><view class=\"_div\"><view class=\"_p static {{computedClassStr}}\">233</view></view></template>`,\n      { name: 'a' }\n    )\n    // TODO, classObject 暂不支持\n    // assertCodegen(\n    //   `<div><p class=\"static\" v-bind:class=\"classObject\">233</p></div>`,\n    //   `<template name=\"a\"><view class=\"_div static {{( isActive)? 'active' : ' '}} {{( hasError )? 'text-danger' : ' '}}\"></view></template>`,\n    //   { name: 'a' }\n    // )\n    // array\n    assertCodegen(\n      `<div><p class=\"static\" :class=\"[activeClass, errorClass]\">233</p></div>`,\n      `<template name=\"a\"><view class=\"_div\"><view class=\"_p static {{[activeClass, errorClass]}}\">233</view></view></template>`,\n      { name: 'a' }\n    )\n    assertCodegen(\n      `<div><p class=\"static\" v-bind:class=\"[isActive ? activeClass : '', errorClass]\">233</p></div>`,\n      `<template name=\"a\"><view class=\"_div\"><view class=\"_p static {{[isActive ? activeClass : '', errorClass]}}\">233</view></view></template>`,\n      { name: 'a' }\n    )\n    assertCodegen(\n      `<div><p class=\"static\" v-bind:class=\"[{ active: isActive }, errorClass]\">233</p></div>`,\n      `<template name=\"a\"><view class=\"_div\"><view class=\"_p static {{[[isActive ? 'active' : ''], errorClass]}}\">233</view></view></template>`,\n      { name: 'a' }\n    )\n  })\n\n  it('v-bind:style', () => {\n    assertCodegen(\n      `<div v-bind:style=\"{ color: activeColor, fontSize: fontSize + 'px' }\">111</div>`,\n      `<template name=\"a\"><view class=\"_div\" style=\" {{('color:' + activeColor + ';' + 'font-size:' + (fontSize + 'px') + ';')}}\">111</view></template>`,\n      { name: 'a' }\n    )\n    assertCodegen(\n      `<div v-bind:style=\"{ color: a === b ? activeColor : color, fontSize: fontSize + 'px' }\">111</div>`,\n      `<template name=\"a\"><view class=\"_div\" style=\" {{(  'color:' +  (a === b ? activeColor : color) +  ';' +  'font-size:' +  (fontSize + 'px') +  ';')}}\">111</view></template>`,\n      { name: 'a' }\n    )\n    assertCodegen(\n      `<div v-bind:style=\"[{ color: activeColor, fontSize: fontSize + 'px' }]\">111</div>`,\n      `<template name=\"a\"><view class=\"_div\" style=\" {{['color:' + activeColor + ';' + 'font-size:' + (fontSize + 'px') + ';']}}\">111</view></template>`,\n      { name: 'a' }\n    )\n    assertCodegen(\n      `<div v-bind:style=\"computedStyleStr\">222</div>`,\n      `<template name=\"a\"><view class=\"_div\" style=\" {{computedStyleStr}}\">222</view></template>`,\n      { name: 'a' }\n    )\n    // TODO, 等微信支持了再支持\n    // assertCodegen(\n    //   `<div v-bind:style=\"styleObject\">222</div>`,\n    //   `<template name=\"a\"><view class=\"_div\" style=\" {{tyleObjec}}\">222</view></template>`,\n    //   { name: 'a' }\n    // )\n    // assertCodegen(\n    //   `<div v-bind:style=\"[baseStyles, overridingStyles]\">333</div>`,\n    //   `<template name=\"a\"><view class=\"_div\" style=\" {{baseStyles, overridingStyles}}\">333</view></template>`,\n    //   { name: 'a' }\n    // )\n    // assertCodegen(\n    //   `<div :style=\"{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }\">444</div>`,\n    //   `<template name=\"a\"><view class=\"_div\" style=\" {{'display:' + ['-webkit-box', '-ms-flexbox', 'flex'] + ';'}}\">444</view></template>`,\n    //   { name: 'a' }\n    // )\n    assertCodegen(\n      `<my-component style=\"color: red;\"></my-component>`,\n      `<import src=\"/components/card\" /><template name=\"a\"><template data=\"{{...$root[$kk+'0'], $root}}\" is=\"my-component\"></template></template>`,\n      {\n        name: 'a',\n        components: {\n          'my-component': {\n            name: 'my-component',\n            src: '/components/card'\n          }\n        },\n        moduleId: 'hashValue'\n      },\n      {\n        mpTips: ['template 不支持此属性-> style=\"color: red;\"'],\n        mpErrors: []\n      }\n    )\n  })\n\n  it('v-text', () => {\n    assertCodegen(\n      `<div v-text=\"s\"></div>`,\n      `<template name=\"a\"><view class=\"_div\">{{s}}</view></template>`,\n      { name: 'a' }\n    )\n  })\n\n  it('v-html', () => {\n    assertCodegen(\n      `<div v-html=\"s\"></div>`,\n      `<template name=\"a\"><rich-text nodes=\"{{s}}\" class=\"_div\"></rich-text></template>`,\n      { name: 'a' }\n    )\n  })\n\n  it('v-if', () => {\n    assertCodegen(\n      `<div v-if=\"s\"></div>`,\n      `<template name=\"a\"><view wx:if=\"{{s}}\" class=\"_div\"></view></template>`,\n      { name: 'a' }\n    )\n    assertCodegen(\n      `<div v-if=\"ok\" class=\"classa\" style=\"line-height: 100rpx\"><a></a></div>`,\n      `<template name=\"a\"><view wx:if=\"{{ok}}\" class=\"_div classa\" style=\"line-height: 100rpx\"><view class=\"_a\"></view></view></template>`,\n      { name: 'a' }\n    )\n  })\n\n  it('v-if', () => {\n    assertCodegen(\n      `<div v-else-if=\"s\"></div>`,\n      `<template name=\"a\"><view wx:elif=\"{{s}}\" class=\"_div\"></view></template>`,\n      { name: 'a' }\n    )\n  })\n\n  it('v-else', () => {\n    assertCodegen(\n      `<div v-else></div>`,\n      `<template name=\"a\"><view wx:else class=\"_div\"></view></template>`,\n      { name: 'a' }\n    )\n  })\n  it('v-show', () => {\n    assertCodegen(\n      `<div v-show=\"ddd\"></div>`,\n      `<template name=\"a\"><view hidden=\"{{!(ddd)}}\" class=\"_div\"></view></template>`,\n      { name: 'a' }\n    )\n  })\n})\n\ndescribe('事件', () => {\n  it('@click', () => {\n    assertCodegen(\n      `<a @click=\"ddd\"></a>`,\n      `<template name=\"a\"><view bindtap=\"handleProxy\" data-eventid=\"{{'0'}}\" data-comkey=\"{{$k}}\" class=\"_a\"></view></template>`,\n      { name: 'a' }\n    )\n  })\n\n  it('@click.stop', () => {\n    assertCodegen(\n      `<a @click.stop=\"ddd\"></a>`,\n      `<template name=\"a\"><view catchtap=\"handleProxy\" data-eventid=\"{{'0'}}\" data-comkey=\"{{$k}}\" class=\"_a\"></view></template>`,\n      { name: 'a' }\n    )\n  })\n\n  it('@click.stop.capture', () => {\n    assertCodegen(\n      `<a @click.stop.capture=\"ddd\"></a>`,\n      `<template name=\"a\"><view capture-catch:tap=\"handleProxy\" data-eventid=\"{{'0'}}\" data-comkey=\"{{$k}}\" class=\"_a\"></view></template>`,\n      { name: 'a' }\n    )\n  })\n\n  it('@click.capture', () => {\n    assertCodegen(\n      `<a @click.capture=\"ddd\"></a>`,\n      `<template name=\"a\"><view capture-bind:tap=\"handleProxy\" data-eventid=\"{{'0'}}\" data-comkey=\"{{$k}}\" class=\"_a\"></view></template>`,\n      { name: 'a' }\n    )\n  })\n\n  it('@load', () => {\n    assertCodegen(\n      `<a @load=\"ddd\"></a>`,\n      `<template name=\"a\"><view bindload=\"handleProxy\" data-eventid=\"{{'0'}}\" data-comkey=\"{{$k}}\" class=\"_a\"></view></template>`,\n      { name: 'a' }\n    )\n  })\n\n  it('v-on:click', () => {\n    assertCodegen(\n      `<a v-on:click=\"ddd\"></a>`,\n      `<template name=\"a\"><view bindtap=\"handleProxy\" data-eventid=\"{{'0'}}\" data-comkey=\"{{$k}}\" class=\"_a\"></view></template>`,\n      { name: 'a' }\n    )\n  })\n  it('v-on', () => {\n    assertCodegen(\n      `<button v-on:click=\"say('hi')\">Say hi</button>`,\n      `<template name=\"a\"><button bindtap=\"handleProxy\" data-eventid=\"{{'0'}}\" data-comkey=\"{{$k}}\" class=\"_button\">Say hi</button></template>`,\n      { name: 'a' }\n    )\n  })\n  it('v-once', () => {\n    assertCodegen(\n      `<button v-once>Say hi</button>`,\n      `<template name=\"a\"><button class=\"_button\">Say hi</button></template>`,\n      { name: 'a' }\n    )\n  })\n  it('bindmarkertap', () => {\n    assertCodegen(\n      `<map @markertap=\"markertap\"></map>`,\n      `<template name=\"a\"><map bindmarkertap=\"handleProxy\" data-eventid=\"{{'0'}}\" data-comkey=\"{{$k}}\" class=\"_map\"></map></template>`,\n      { name: 'a' }\n    )\n  })\n  it('v-else', () => {\n    assertCodegen(\n      `<div><div v-if=\"type === 'A'\" @click=\"logger('A')\">A</div><div v-else-if=\"type === 'B'\" @click=\"logger('B')\">B</div><div v-else-if=\"type === 'C'\" @click=\"logger('C')\">C</div><div v-else @click=\"logger('Not A/B/C')\">Not A/B/C</div></div>`,\n      `<template name=\"a\"><view class=\"_div\"><view wx:if=\"{{type === 'A'}}\" bindtap=\"handleProxy\" data-eventid=\"{{'3'}}\" data-comkey=\"{{$k}}\" class=\"_div\">A</view><view wx:elif=\"{{type === 'B'}}\" bindtap=\"handleProxy\" data-eventid=\"{{'0'}}\" data-comkey=\"{{$k}}\" class=\"_div\">B</view><view wx:elif=\"{{type === 'C'}}\" bindtap=\"handleProxy\" data-eventid=\"{{'1'}}\" data-comkey=\"{{$k}}\" class=\"_div\">C</view><view wx:else bindtap=\"handleProxy\" data-eventid=\"{{'2'}}\" data-comkey=\"{{$k}}\" class=\"_div\">Not A/B/C</view></view></template>`,\n      { name: 'a' }\n    )\n  })\n})\n\ndescribe('表单', () => {\n  it('textarea', () => {\n    assertCodegen(\n      `<textarea v-model=\"message\" placeholder=\"add multiple lines\"></textarea>`,\n      `<template name=\"a\"><textarea value=\"{{message}}\" bindinput=\"handleProxy\" placeholder=\"add multiple lines\" data-eventid=\"{{'0'}}\" data-comkey=\"{{$k}}\" class=\"_textarea\" /></template>`,\n      { name: 'a' }\n    )\n  })\n  // it('checkbox', () => {\n  //   assertCodegen(\n  //     `<input type=\"checkbox\" id=\"checkbox\" v-model=\"checked\">`,\n  //     `<template name=\"a\"><input value=\"{{message}}\" bindinput=\"handleProxy\" placeholder=\"edit me\" data-eventid=\"{{'0'}}\" data-comkey=\"{{$k}}\" class=\"_input\" /></template>`,\n  //     { name: 'a' }\n  //   )\n  // })\n  // 需要核实是否支持\n  it('select', () => {\n    assertCodegen(\n      `<select v-model=\"selected\" multiple style=\"width: 50px\"></select>`,\n      `<template name=\"a\"><picker value=\"{{selected}}\" bindchange=\"handleProxy\" multiple style=\"width: 50px\" data-eventid=\"{{'0'}}\" data-comkey=\"{{$k}}\" class=\"_select\"></picker></template>`,\n      { name: 'a' }\n    )\n  })\n  it('v-model', () => {\n    assertCodegen(\n      `<input v-model=\"message\" placeholder=\"edit me\">`,\n      `<template name=\"a\"><input value=\"{{message}}\" bindinput=\"handleProxy\" placeholder=\"edit me\" data-eventid=\"{{'0'}}\" data-comkey=\"{{$k}}\" class=\"_input\" /></template>`,\n      { name: 'a' }\n    )\n  })\n  // it('v-model.trim', () => {\n  //   assertCodegen(\n  //     `<input v-model.trim=\"msg\">`,\n  //     `<template name=\"a\"><input value=\"{{message}}\" bindinput=\"handleProxy\" placeholder=\"edit me\" data-eventid=\"{{'0'}}\" data-comkey=\"{{$k}}\" class=\"_input\" /></template>`,\n  //     { name: 'a' }\n  //   )\n  // })\n  it('v-model.lazy', () => {\n    assertCodegen(\n      `<input v-model.lazy=\"msg\" >`,\n      `<template name=\"a\"><input value=\"{{msg}}\" bindblur=\"handleProxy\" data-eventid=\"{{'0'}}\" data-comkey=\"{{$k}}\" class=\"_input\" /></template>`,\n      { name: 'a' }\n    )\n  })\n  it('v-model.number', () => {\n    assertCodegen(\n      `<input v-model.number=\"age\" type=\"number\">`,\n      `<template name=\"a\"><input value=\"{{age}}\" bindinput=\"handleProxy\" type=\"number\" data-eventid=\"{{'0'}}\" data-comkey=\"{{$k}}\" class=\"_input\" /></template>`,\n      { name: 'a' }\n    )\n  })\n  it('radio', () => {\n    assertCodegen(\n      `<radio><text>233</text></radio>`,\n      `<template name=\"a\"><radio class=\"_radio\"><text class=\"_text\">233</text></radio></template>`,\n      { name: 'a' }\n    )\n  })\n})\n\ndescribe('template', () => {\n  it('template', () => {\n    assertCodegen(\n      `<div><card v-for=\"i in 10\"></card></div>`,\n      `<import src=\"/components/card\" /><template name=\"a\"><view class=\"_div data-v-djskdksdksdjkksdks\"><template data=\"{{...$root[$kk+'0-'+index], $root}}\" is=\"card\" wx:for=\"{{10}}\" wx:for-index=\"index\" wx:for-item=\"i\"></template></view></template>`,\n      {\n        name: 'a',\n        components: {\n          card: {\n            name: 'card',\n            src: '/components/card'\n          }\n        },\n        moduleId: 'data-v-djskdksdksdjkksdks'\n      }\n    )\n  })\n\n  it('template', () => {\n    assertCodegen(\n      `<div><card :message=\"1\"></card></div>`,\n      `<import src=\"/components/card\" /><template name=\"a\"><view class=\"_div data-v-djskdksdksdjkksdks\"><template data=\"{{...$root[$kk+'0'], $root}}\" is=\"card\"></template></view></template>`,\n      {\n        name: 'a',\n        components: {\n          card: {\n            name: 'card',\n            src: '/components/card'\n          }\n        },\n        moduleId: 'data-v-djskdksdksdjkksdks'\n      }\n    )\n  })\n  it('template', () => {\n    assertCodegen(\n      `<div><card :message=\"1\"></card> <block><span>test</span></block></div>`,\n      `<import src=\"/components/card\" /><template name=\"a\"><view class=\"_div data-v-djskdksdksdjkksdks\"><template data=\"{{...$root[$kk+'0'], $root}}\" is=\"card\"></template> <block><label class=\"_span data-v-djskdksdksdjkksdks\">test</label></block></view></template>`,\n      {\n        name: 'a',\n        components: {\n          card: {\n            name: 'card',\n            src: '/components/card'\n          }\n        },\n        moduleId: 'data-v-djskdksdksdjkksdks'\n      }\n    )\n  })\n})\ndescribe('onchange', () => {\n  it('onchange', () => {\n    assertCodegen(\n      `<div class=\"baz boo\"><picker @change=\"sss\"></picker> <input @change=\"sss\"></input></div>`,\n      `<template name=\"a\"><view class=\"_div hashValue baz boo\"><picker bindchange=\"handleProxy\" data-eventid=\"{{'0'}}\" data-comkey=\"{{$k}}\" class=\"_picker hashValue\"></picker> <input bindblur=\"handleProxy\" data-eventid=\"{{'1'}}\" data-comkey=\"{{$k}}\" class=\"_input hashValue\" /></view></template>`,\n      {\n        name: 'a',\n        components: {\n          'card': {\n            name: 'card',\n            src: '/components/card'\n          }\n        },\n        moduleId: 'hashValue'\n      }\n    )\n  })\n})\ndescribe('slot', () => {\n  it('插槽', () => {\n    assertCodegen(\n      `<div><slot>test</slot></div>`,\n      `<template name=\"a\"><view class=\"_div testModuleId\"><template name=\"default\">test</template><template data=\"{{...$root[$k], $root}}\" is=\"{{$slotdefault || 'default'}}\"></template></view></template>`,\n      {\n        name: 'a',\n        moduleId: 'testModuleId'\n      }\n    )\n  })\n\n  it('使用', () => {\n    assertCodegen(\n      `<div><slot name=\"w\">test</slot></div>`,\n      `<template name=\"a\"><view class=\"_div\"><template name=\"w\">test</template><template data=\"{{...$root[$k], $root}}\" is=\"{{$slotw || 'w'}}\"></template></view></template>`,\n      {\n        name: 'a'\n      }\n    )\n  })\n\n  it('含`:name`的插槽组件', () => {\n    assertCodegen(\n      `<div><slot :name=\"tab.key\">test</slot></div>`,\n      `<template name=\"a\"><view class=\"_div\"><template name=\"default\">test</template><template data=\"{{...$root[$k], $root}}\" is=\"{{$for[tab.key]}}\"></template></view></template>`,\n      {\n        name: 'a'\n      }\n    )\n  })\n\n  it('slot name', () => {\n    assertCodegen(\n      `<card class=\"baz boo\"><a slot=\"header\">test</a></card>`,\n      `<import src=\"/components/card\" /><template name=\"a\"><template data=\"{{...$root[$kk+'0'], $root, $for:{default:'hashValue-default-0',header:'hashValue-header-0'},$slotdefault:'hashValue-default-0',$slotheader:'hashValue-header-0'}}\" is=\"card\"></template></template>`,\n      {\n        name: 'a',\n        components: {\n          'card': {\n            name: 'card',\n            src: '/components/card'\n          }\n        },\n        moduleId: 'hashValue'\n      },\n      {\n        mpTips: ['template 不支持此属性-> class=\"baz boo\"'],\n        mpErrors: [],\n        /* eslint-disable */\n        slots: {\"hashValue-default-0\":{\"node\":{\"tag\":\"template\",\"attrsMap\":{\"name\":\"hashValue-default-0\"},\"children\":[],\"staticClass\":\"\",\"slots\":{}},\"name\":\"default\",\"slotId\":\"hashValue-default-0\",\"code\":\"<template name=\\\"hashValue-default-0\\\"></template>\"},\"hashValue-header-0\":{\"node\":{\"type\":1,\"tag\":\"template\",\"attrsList\":[],\"attrsMap\":{\"name\":\"hashValue-header-0\"},\"parent\":{\"type\":1,\"tag\":\"card\",\"attrsList\":[],\"attrsMap\":{\"class\":\"baz boo\"},\"children\":[],\"plain\":false,\"staticClass\":\"\\\"baz boo\\\"\",\"mpcomid\":\"'0'\",\"attrs\":[{\"name\":\"mpcomid\",\"value\":\"'0'\"}],\"static\":false,\"staticRoot\":false},\"children\":[{\"type\":3,\"text\":\"test\",\"staticClass\":\"hashValue\",\"slots\":{},\"attrsMap\":{\"class\":\"hashValue\"}}],\"plain\":false,\"slotTarget\":\"\\\"header\\\"\",\"staticRoot\":false,\"staticClass\":\"\",\"slots\":{}},\"name\":\"header\",\"slotId\":\"hashValue-header-0\",\"code\":\"<template name=\\\"hashValue-header-0\\\">test</template>\"}}\n      }\n    )\n  })\n\n  it('slot template', () => {\n    assertCodegen(\n      `<card class=\"baz boo\"><template slot=\"header\">test</template></card>`,\n      `<import src=\"/components/card\" /><template name=\"a\"><template data=\"{{...$root[$kk+'1'], $root, $for:{default:'hashValue-default-1',header:'hashValue-header-1'},$slotdefault:'hashValue-default-1',$slotheader:'hashValue-header-1'}}\" is=\"card\"></template></template>`,\n      {\n        name: 'a',\n        components: {\n          'card': {\n            name: 'card',\n            src: '/components/card'\n          }\n        },\n        moduleId: 'hashValue'\n      },\n      {\n        mpErrors: [],\n        mpTips: ['template 不支持此属性-> class=\"baz boo\"'],\n        slots: {\"hashValue-default-1\":{\"node\":{\"tag\":\"template\",\"attrsMap\":{\"name\":\"hashValue-default-1\"},\"children\":[],\"staticClass\":\"\",\"slots\":{}},\"name\":\"default\",\"slotId\":\"hashValue-default-1\",\"code\":\"<template name=\\\"hashValue-default-1\\\"></template>\"},\"hashValue-header-1\":{\"node\":{\"type\":1,\"tag\":\"template\",\"attrsList\":[],\"attrsMap\":{\"name\":\"hashValue-header-1\"},\"parent\":{\"type\":1,\"tag\":\"card\",\"attrsList\":[],\"attrsMap\":{\"class\":\"baz boo\"},\"children\":[],\"plain\":false,\"staticClass\":\"\\\"baz boo\\\"\",\"mpcomid\":\"'1'\",\"attrs\":[{\"name\":\"mpcomid\",\"value\":\"'1'\"}],\"static\":false,\"staticRoot\":false},\"children\":[{\"type\":3,\"text\":\"test\",\"staticClass\":\"hashValue\",\"slots\":{},\"attrsMap\":{\"class\":\"hashValue\"}}],\"plain\":false,\"slotTarget\":\"\\\"header\\\"\",\"mpcomid\":\"'0'\",\"attrs\":[{\"name\":\"mpcomid\",\"value\":\"'0'\"}],\"staticRoot\":false,\"staticClass\":\"\",\"slots\":{}},\"name\":\"header\",\"slotId\":\"hashValue-header-1\",\"code\":\"<template name=\\\"hashValue-header-1\\\">test</template>\"}}\n      }\n    )\n  })\n  it('slot template', () => {\n    assertCodegen(\n      `<template class=\"baz boo\"><template slot=\"header\">test</template></template>`,\n      `<template name=\"a\"><template><template slot=\"header\">test</template></template></template>`,\n      {\n        name: 'a',\n        components: {\n          'card': {\n            name: 'card',\n            src: '/components/card'\n          }\n        },\n        moduleId: 'hashValue'\n      },\n      {\n        errors: ['Cannot use <template> as component root element because it may contain multiple nodes.'],\n        mpTips: ['template 不支持此属性-> class=\"baz boo\"'],\n        mpErrors: []\n      }\n    )\n  })\n})\n\ndescribe('web-view', () => {\n  it('web-view', () => {\n    assertCodegen(\n      `<web-view src=\"https://i.meituan.com\"> </web-view>`,\n      `<template name=\"a\"><web-view src=\"https://i.meituan.com\" class=\"_web-view\"></web-view></template>`,\n      { name: 'a' }\n    );\n  })\n})\n\ndescribe('组件', () => {\n  it('组件驼峰命名', () => {\n    assertCodegen(\n      `<div><aCard></aCard></div>`,\n      `<import src=\"card$3d556b2c\" /><template name=\"index$c044a66a\"><view class=\"_div data-v-5eca2e54\"><template data=\"{{...$root[$kk+'0'], $root}}\" is=\"card$3d556b2c\"></template></view></template>`,\n      { components:\n        { 'a-card': { src: 'card$3d556b2c', name: 'card$3d556b2c' },\n          isCompleted: true,\n          slots: { src: 'slots', name: 'slots' } },\n       pageType: 'component',\n       name: 'index$c044a66a',\n       moduleId: 'data-v-5eca2e54' }\n    );\n  })\n  it('组件驼峰命名', () => {\n    assertCodegen(\n      `<div><Card></Card></div>`,\n      `<import src=\"card$3d556b2c\" /><template name=\"index$c044a66a\"><view class=\"_div data-v-5eca2e54\"><template data=\"{{...$root[$kk+'0'], $root}}\" is=\"card$3d556b2c\"></template></view></template>`,\n      { components:\n        { 'card': { src: 'card$3d556b2c', name: 'card$3d556b2c' },\n          isCompleted: true,\n          slots: { src: 'slots', name: 'slots' } },\n       pageType: 'component',\n       name: 'index$c044a66a',\n       moduleId: 'data-v-5eca2e54' }\n    );\n  })\n})\n"
  },
  {
    "path": "test/mp/helpers/index.js",
    "content": "const matchOperatorsRe = /[|\\\\{}()[\\]^$+*?.]/g\nfunction strToRegExp (str) {\n  return new RegExp(str.replace(matchOperatorsRe, '\\\\$&'))\n}\n\n// runtime\n// fix mp env\nconst { App, Page, getApp, Component } = require('./mp.runtime')\nglobal.App = App\nglobal.Page = Page\nglobal.getApp = getApp\nglobal.Component = Component\n\nconst Vue = require('../../../packages/mpvue')\n\nfunction createInstance (options) {\n  return new Vue(options)\n}\n\nmodule.exports = {\n  strToRegExp,\n  createInstance\n}\n"
  },
  {
    "path": "test/mp/helpers/mp.runtime.js",
    "content": "// 因为没办法直接跑小程序的开发者工具做测试，所以简单的模拟一下小程序 runtime ，满足我们需要的功能即可\n\nfunction getObjByPath (obj = {}, path, op = '.') {\n  if (!obj) return obj\n  const arr = (path || '').split(op)\n\n  return arr.reduce((res, k) => {\n    if (k) {\n      if (!res[k]) res[k] = {}\n      res = res[k]\n    }\n    return res\n  }, obj)\n}\n\nlet appVM = null\n\nclass MPPage {\n  constructor (config) {\n    this.data = {}\n    Object.assign(this, config)\n\n    this._options = {\n      path: 'pages/index/index',\n      scene: 1001,\n      query: {}\n    }\n\n    this._initLifecycle()\n  }\n\n  // 此处只做简单的对象参数模拟\n  setData (obj) {\n    if (!obj || Object.prototype.toString.call(obj) !== '[object Object]') {\n      return\n    }\n    this.data = this.data || {}\n    Object.keys(obj).forEach(key => {\n      const val = obj[key]\n      Object.assign(getObjByPath(this.data, key), val)\n    })\n  }\n\n  // _ 开头的方法和属性定义等，都不是小程序暴露的方法，是模拟出的私有方法，手动触发用\n  _initLifecycle () {\n    this._callHook('onLoad', this._options.query)\n    this._callHook('onShow')\n    this._callHook('onReady')\n  }\n\n  _callHook (hook, ev) {\n    const handle = this[hook]\n    if (typeof handle === 'function') {\n      return handle.call(this, ev)\n    }\n  }\n\n  _leaveAndBack () {\n    this._callHook('onHide')\n    setTimeout(() => {\n      this._callHook('onShow')\n    }, 100)\n  }\n}\n\nclass MPApp extends MPPage {\n  // app 具有不一样的生命周期\n  _initLifecycle () {\n    this._callHook('onLaunch', this._options)\n    this._callHook('onShow', this._options)\n  }\n}\n\nclass MPComponent extends MPPage {\n  // component 与page生命周期不同\n  _initLifecycle () {\n    this._callHook('created')\n    this._callHook('attached')\n    this._callHook('ready')\n  }\n\n  _leaveAndBack () {\n    // 微信原生组件会进入后台，不会触发任何生命周期\n  }\n}\n\nfunction Page (config) {\n  return new MPPage(config)\n}\n\nfunction App (config) {\n  appVM = new MPApp(config)\n  return appVM\n}\n\nfunction getApp () {\n  return appVM\n}\n\nfunction Component (config) {\n  return new MPComponent(config)\n}\n\nmodule.exports = {\n  Page,\n  App,\n  getApp,\n  Component\n}\n"
  },
  {
    "path": "test/mp/jasmine.json",
    "content": "{\n  \"spec_dir\": \"test/mp\",\n  \"spec_files\": [\n    \"**/*[sS]pec.js\"\n  ],\n  \"helpers\": [\n    \"helpers/**/*.js\"\n  ],\n  \"stopSpecOnExpectationFailure\": false,\n  \"random\": false\n}\n"
  },
  {
    "path": "test/mp/runtime/events.spec.js",
    "content": "const { createInstance } = require('../helpers/index')\n\n// 事件触发\ndescribe('events', function () {\n  // 事件由 wxml 的 bingtap 发出\n  // 单一组件\n  it('handleProxy', function (done) {\n    const options = {\n      methods: {\n        clickHandle (str, ev) {\n          expect(str).toEqual('test click')\n          expect(ev.target.id).toEqual('testEventId')\n          done()\n        }\n      },\n      // render 由 mpvue-loader 和 mpvue-template-compiler 生成\n      // <div class=\"container\">\n      //   <p @click=\"clickHandle('test click', $event)\">233</p>\n      // </div>\n      render () {\n        var _vm = this\n        var _h = _vm.$createElement\n        var _c = _vm._self._c || _h\n        return _c('div', {\n          staticClass: 'container'\n        }, [_c('p', {\n          attrs: {\n            'eventid': '0'\n          },\n          on: {\n            'click': function ($event) {\n              _vm.clickHandle('test click', $event)\n            }\n          }\n        }, [_vm._v('233')])], 1)\n      }\n    }\n    const app = createInstance(options)\n    app.$mount()\n\n    // 模拟从 wxml 的触发\n    const ev = JSON.parse(`{\"type\":\"tap\",\"timeStamp\":4155,\"target\":{\"id\":\"testEventId\",\"offsetLeft\":83,\"offsetTop\":100,\"dataset\":{\"comkey\":\"0\",\"eventid\":\"0\"}},\"currentTarget\":{\"id\":\"testEventId\",\"offsetLeft\":83,\"offsetTop\":100,\"dataset\":{\"comkey\":\"0\",\"eventid\":\"0\"}},\"detail\":{\"x\":172,\"y\":114},\"touches\":[{\"identifier\":0,\"pageX\":172,\"pageY\":114,\"clientX\":172,\"clientY\":114}],\"changedTouches\":[{\"identifier\":0,\"pageX\":172,\"pageY\":114,\"clientX\":172,\"clientY\":114}]}`)\n    app.$mp.page._callHook('handleProxy', ev)\n  })\n\n  it('onShareAppMessage', function (done) {\n    const options = {\n      onShareAppMessage (options) {\n        expect(options.from).toEqual('button')\n        return {\n          path: '/pages/index/index'\n        }\n      },\n      // render 由 mpvue-loader 和 mpvue-template-compiler 生成\n      // <div class=\"container\">\n      //   <p @click=\"clickHandle('test click', $event)\">233</p>\n      // </div>\n      render () {\n        var _vm = this\n        var _h = _vm.$createElement\n        var _c = _vm._self._c || _h\n        return _c('div', {\n          staticClass: 'container'\n        }, [_c('p', {\n          attrs: {\n            'eventid': '0'\n          },\n          on: {\n            'click': function ($event) {\n              _vm.clickHandle('test click', $event)\n            }\n          }\n        }, [_vm._v('233')])], 1)\n      }\n    }\n    const app = createInstance(options)\n    app.$mount()\n    const ret = app.$mp.page._callHook('onShareAppMessage', {\n      from: 'button'\n    })\n    expect(ret.path).toEqual('/pages/index/index')\n    done()\n  })\n\n  // 包含子组件\n  it('handleProxy with components', function (done) {\n    const warpOptions = {\n      methods: {\n        clickHandle (str, ev) {\n          expect(str).toEqual('warp component click')\n          expect(ev.target.id).toEqual('testEventId2')\n          done()\n        }\n      },\n      // <div class=\"container\">\n      //   <p @click=\"clickHandle('warp component click', $event)\">warp component</p>\n      // </div>\n      render () {\n        var _vm = this\n        var _h = _vm.$createElement\n        var _c = _vm._self._c || _h\n        return _c('div', {\n          staticClass: 'container'\n        }, [_c('p', {\n          attrs: {\n            'eventid': '0'\n          },\n          on: {\n            'click': function ($event) {\n              _vm.clickHandle('warp component click', $event)\n            }\n          }\n        }, [_vm._v('warp component')])], 1)\n      }\n    }\n    const options = {\n      components: {\n        warp: warpOptions\n      },\n      methods: {\n        clickHandle (str, ev) {\n          expect(str).toEqual('test p click')\n          expect(ev.target.id).toEqual('testEventId1')\n          done()\n        }\n      },\n      // render 由 mpvue-loader 和 mpvue-template-compiler 生成\n      // <div class=\"container\">\n      //   <p @click=\"clickHandle('test p click', $event)\">\n      //     233\n      //     <warp></warp>\n      //   </p>\n      // </div>\n      render () {\n        var _vm = this\n        var _h = _vm.$createElement\n        var _c = _vm._self._c || _h\n        return _c('div', {\n          staticClass: 'container'\n        }, [_c('p', {\n          attrs: {\n            'eventid': '0'\n          },\n          on: {\n            'click': function ($event) {\n              _vm.clickHandle('test p click', $event)\n            }\n          }\n        }, [_vm._v('233')]), _c('warp')], 1)\n      }\n    }\n    const app = createInstance(options)\n    app.$mount()\n\n    // 模拟从 wxml 的触发\n    const ev1 = JSON.parse(`{\"type\":\"tap\",\"timeStamp\":8938,\"target\":{\"id\":\"testEventId1\",\"offsetLeft\":0,\"offsetTop\":100,\"dataset\":{\"comkey\":\"0\",\"eventid\":\"0\"}},\"currentTarget\":{\"id\":\"testEventId1\",\"offsetLeft\":0,\"offsetTop\":100,\"dataset\":{\"comkey\":\"0\",\"eventid\":\"0\"}},\"detail\":{\"x\":186,\"y\":112},\"touches\":[{\"identifier\":0,\"pageX\":186,\"pageY\":112,\"clientX\":186,\"clientY\":112}],\"changedTouches\":[{\"identifier\":0,\"pageX\":186,\"pageY\":112,\"clientX\":186,\"clientY\":112}]}`)\n    app.$mp.page._callHook('handleProxy', ev1)\n\n    const ev2 = JSON.parse(`{\"type\":\"tap\",\"timeStamp\":152060,\"target\":{\"id\":\"testEventId2\",\"offsetLeft\":116,\"offsetTop\":286,\"dataset\":{\"comkey\":\"0,0\",\"eventid\":\"0\"}},\"currentTarget\":{\"id\":\"testEventId2\",\"offsetLeft\":116,\"offsetTop\":286,\"dataset\":{\"comkey\":\"0,0\",\"eventid\":\"0\"}},\"detail\":{\"x\":215,\"y\":301},\"touches\":[{\"identifier\":0,\"pageX\":216,\"pageY\":301,\"clientX\":216,\"clientY\":301}],\"changedTouches\":[{\"identifier\":0,\"pageX\":216,\"pageY\":301,\"clientX\":216,\"clientY\":301}]}`)\n    app.$mp.page._callHook('handleProxy', ev2)\n  })\n\n  // v-model 等特殊指令\n  it('v-model', function (done) {\n    const options = {\n      data () {\n        return {\n          testInput: ''\n        }\n      },\n      // render 由 mpvue-loader 和 mpvue-template-compiler 生成\n      // <div class=\"container\">\n      //   <input v-model=\"testInput\" />\n      // </div>\n      render () {\n        var _vm = this\n        var _h = _vm.$createElement\n        var _c = _vm._self._c || _h\n        return _c('div', {\n          staticClass: 'container'\n        }, [_c('input', {\n          directives: [{\n            name: 'model',\n            rawName: 'v-model',\n            value: (_vm.testInput),\n            expression: 'testInput'\n          }],\n          attrs: {\n            eventid: '0'\n          },\n          domProps: {\n            value: (_vm.testInput)\n          },\n          on: {\n            input: function ($event) {\n              if ($event.target.composing) return\n              _vm.testInput = $event.target.value\n            }\n          }\n        })])\n      }\n    }\n    const app = createInstance(options)\n    app.$mount()\n\n    // 模拟从 wxml 的触发\n    const ev = JSON.parse(`{\"type\":\"input\",\"timestamp\":1505102982041,\"detail\":{\"value\":\"233\",\"cursor\":1},\"target\":{\"id\":\"\",\"dataset\":{\"comkey\":\"0\",\"eventid\":\"0\"},\"offsetTop\":100,\"offsetLeft\":83},\"currentTarget\":{\"id\":\"\",\"dataset\":{\"comkey\":\"0\",\"eventid\":\"0\"},\"offsetTop\":100,\"offsetLeft\":83},\"touches\":[]}`)\n    app.$mp.page._callHook('handleProxy', ev)\n\n    setTimeout(function () {\n      const val = app.$mp.page.data['$root']['0']['testInput']\n      expect(val).toEqual('233')\n      done()\n    }, 300)\n  })\n\n  // v-model 等特殊指令\n  it('v-model.lazy', function (done) {\n    const options = {\n      data () {\n        return {\n          testInput: ''\n        }\n      },\n      methods: {\n        handle (ev) {\n          expect(ev.target.value).toEqual('2222')\n        }\n      },\n      // render 由 mpvue-loader 和 mpvue-template-compiler 生成\n      // <div class=\"container\">\n      //   <input v-model.lazy=\"testInput\" />\n      // </div>\n      render () {\n        var _vm = this\n        var _h = _vm.$createElement\n        var _c = _vm._self._c || _h\n        return _c('div', {\n          staticClass: 'container'\n        }, [_c('input', {\n          directives: [{\n            name: 'model',\n            rawName: 'v-model.lazy',\n            value: (_vm.testInput),\n            expression: 'testInput',\n            modifiers: {\n              lazy: true\n            }\n          }],\n          attrs: {\n            eventid: '0'\n          },\n          domProps: {\n            value: (_vm.testInput)\n          },\n          on: {\n            change: [\n              function ($event) {\n                _vm.testInput = $event.target.value\n              },\n              _vm.handle\n            ]\n          }\n        })])\n      }\n    }\n    const app = createInstance(options)\n    app.$mount()\n\n    // 模拟从 wxml 的触发\n    const ev = JSON.parse(`{\"type\":\"blur\",\"timeStamp\":90596,\"target\":{\"id\":\"\",\"offsetLeft\":83,\"offsetTop\":100,\"dataset\":{\"comkey\":\"0\",\"eventid\":\"0\"}},\"currentTarget\":{\"id\":\"\",\"offsetLeft\":83,\"offsetTop\":100,\"dataset\":{\"comkey\":\"0\",\"eventid\":\"0\"}},\"detail\":{\"value\":\"2222\"}}`)\n    app.$mp.page._callHook('handleProxy', ev)\n\n    setTimeout(function () {\n      const val = app.$mp.page.data['$root']['0']['testInput']\n      expect(val).toEqual('2222')\n      done()\n    }, 300)\n  })\n})\n"
  },
  {
    "path": "test/mp/runtime/instance.spec.js",
    "content": "const { createInstance } = require('../helpers/index')\n\n// 通过最终的 setData 来确认数据\ndescribe('instance', function () {\n  const defOptions = {\n    data () {\n      return {\n        msg: 233\n      }\n    },\n    // render 由 mpvue-loader 和 mpvue-template-compiler 生成\n    render () {\n      var _vm = this\n      var _h = _vm.$createElement\n      var _c = _vm._self._c || _h\n      return _c('div', {\n        staticClass: 'container'\n      }, [_c('p', [_vm._v(_vm._s(_vm.msg))])], 1)\n    }\n  }\n\n  function getDefAppData () {\n    return {\n      $root: {\n        0: {\n          msg: 233,\n          $k: '0',\n          $kk: '0,',\n          $p: ''\n        }\n      }\n    }\n  }\n\n  function getDefAppDataByVfor () {\n    return {\n      $root: {\n        0: {\n          items: [111, 222, 333],\n          $k: '0',\n          $kk: '0,',\n          $p: ''\n        },\n        '0,1-0': {\n          info: 111,\n          $k: '0,1-0',\n          $kk: '0,1-0,',\n          $p: '0'\n        },\n        '0,1-1': {\n          info: 222,\n          $k: '0,1-1',\n          $kk: '0,1-1,',\n          $p: '0'\n        },\n        '0,1-2': {\n          info: 333,\n          $k: '0,1-2',\n          $kk: '0,1-2,',\n          $p: '0'\n        }\n      }\n    }\n  }\n\n  // data 默认初始化数据\n  it('data', function (done) {\n    const app = createInstance(Object.assign({}, defOptions))\n    app.$mount()\n\n    setTimeout(function () {\n      const appData = getDefAppData()\n      expect(app.$mp.page.data).toEqual(appData)\n      done()\n    }, 300)\n  })\n\n  // 响应式数据 eg. setTimeout\n  it('Reactivity data', function (done) {\n    const options = Object.assign({\n      created () {\n        setTimeout(() => {\n          this.msg = 666\n        }, 20)\n      }\n    }, defOptions)\n    const app = createInstance(options)\n    app.$mount()\n\n    setTimeout(function () {\n      const appData = getDefAppData()\n      appData['$root']['0']['msg'] = 666\n      expect(app.$mp.page.data).toEqual(appData)\n      done()\n    }, 300)\n  })\n\n  // this.$nextTick\n  it('this.$nextTick', function (done) {\n    const options = Object.assign({\n      created () {\n        this.$nextTick(() => {\n          this.msg = 777\n        }, 20)\n      }\n    }, defOptions)\n    const app = createInstance(options)\n    app.$mount()\n\n    setTimeout(function () {\n      const appData = getDefAppData()\n      appData['$root']['0']['msg'] = 777\n      expect(app.$mp.page.data).toEqual(appData)\n      done()\n    }, 300)\n  })\n\n  // computed 计算属性\n  it('computed', function (done) {\n    const options = Object.assign({\n      computed: {\n        message () {\n          return this.msg + '!!!'\n        }\n      }\n    }, defOptions)\n    const app = createInstance(options)\n    app.$mount()\n\n    setTimeout(function () {\n      const appData = getDefAppData()\n      appData['$root']['0']['message'] = '233!!!'\n      expect(app.$mp.page.data).toEqual(appData)\n      done()\n    }, 300)\n  })\n\n  // 组件\n  it('props', function (done) {\n    const cardOptions = {\n      props: ['info'],\n      // <div class=\"container\">{{info}}</div>\n      render () {\n        var _vm = this\n        var _h = _vm.$createElement\n        var _c = _vm._self._c || _h\n        return _c('div', {\n          staticClass: 'container'\n        }, [_vm._v(_vm._s(_vm.info))])\n      }\n    }\n    const options = {\n      components: {\n        card: cardOptions\n      },\n      data () {\n        return {\n          msg: 233\n        }\n      },\n      // <div class=\"container\">\n      //   <card :info=\"msg\"></card>\n      // </div>\n      render () {\n        var _vm = this\n        var _h = _vm.$createElement\n        var _c = _vm._self._c || _h\n        return _c('div', {\n          staticClass: 'container'\n        }, [_c('card', {\n          attrs: {\n            'info': _vm.msg,\n            'mpcomid': '0' // 这是 mpvue-loader 通过 mpvue-template-compiler 加上的\n          }\n        })], 1)\n      }\n    }\n    const app = createInstance(options)\n    app.$mount()\n\n    setTimeout(function () {\n      const appData = {\n        $root: {\n          0: {\n            msg: 233,\n            $k: '0',\n            $kk: '0,',\n            $p: ''\n          },\n          '0,0': {\n            info: 233,\n            $k: '0,0',\n            $kk: '0,0,',\n            $p: '0'\n          }\n        }\n      }\n      expect(app.$mp.page.data).toEqual(appData)\n      done()\n    }, 300)\n  })\n\n  // v-for 情况下的子组件作用域隔离\n  it('v-for with props', function (done) {\n    const cardOptions = {\n      props: ['info'],\n      // <div class=\"container\">{{info}}</div>\n      render () {\n        var _vm = this\n        var _h = _vm.$createElement\n        var _c = _vm._self._c || _h\n        return _c('div', {\n          staticClass: 'container'\n        }, [_vm._v(_vm._s(_vm.info))])\n      }\n    }\n    const options = {\n      components: {\n        card: cardOptions\n      },\n      data () {\n        return {\n          items: [111, 222, 333]\n        }\n      },\n      // <div class=\"container\">\n      //     <card v-for=\"item in items\" :info=\"item\"></card>\n      // </div>\n      render () {\n        var _vm = this\n        var _h = _vm.$createElement\n        var _c = _vm._self._c || _h\n        return _c('div', {\n          staticClass: 'container'\n        }, [_vm._l((_vm.items), function (item, index) {\n          return _c('card', {\n            attrs: {\n              'info': item,\n              'mpcomid': '1-' + index\n            }\n          })\n        })], 1)\n      }\n    }\n    const app = createInstance(options)\n    app.$mount()\n\n    setTimeout(function () {\n      const appData = getDefAppDataByVfor()\n      expect(app.$mp.page.data).toEqual(appData)\n      done()\n    }, 300)\n  })\n\n  it('v-for with reactivity props', function (done) {\n    const cardOptions = {\n      props: ['info'],\n      // <div class=\"container\">{{info}}</div>\n      render () {\n        var _vm = this\n        var _h = _vm.$createElement\n        var _c = _vm._self._c || _h\n        return _c('div', {\n          staticClass: 'container'\n        }, [_vm._v(_vm._s(_vm.info))])\n      }\n    }\n    const options = {\n      components: {\n        card: cardOptions\n      },\n      data () {\n        return {\n          items: [111, 222, 333]\n        }\n      },\n      created () {\n        this.items[1] = 'hello 222'\n      },\n      // <div class=\"container\">\n      //     <card v-for=\"item in items\" :info=\"item\"></card>\n      // </div>\n      render () {\n        var _vm = this\n        var _h = _vm.$createElement\n        var _c = _vm._self._c || _h\n        return _c('div', {\n          staticClass: 'container'\n        }, [_vm._l((_vm.items), function (item, index) {\n          return _c('card', {\n            attrs: {\n              'info': item,\n              'mpcomid': '1-' + index\n            }\n          })\n        })], 1)\n      }\n    }\n    const app = createInstance(options)\n    app.$mount()\n\n    setTimeout(function () {\n      const appData = getDefAppDataByVfor()\n      appData['$root']['0']['items']['1'] = 'hello 222'\n      appData['$root']['0,1-1']['info'] = 'hello 222'\n      expect(app.$mp.page.data).toEqual(appData)\n      done()\n    }, 300)\n  })\n\n  it('v-for with components data', function (done) {\n    const cardOptions = {\n      props: ['info'],\n      data () {\n        return {\n          msg: 'hello card'\n        }\n      },\n      created () {\n        if (this.info === 222) {\n          this.msg = 'hello card with 222'\n        }\n      },\n      // <div class=\"container\">{{info}}</div>\n      render () {\n        var _vm = this\n        var _h = _vm.$createElement\n        var _c = _vm._self._c || _h\n        return _c('div', {\n          staticClass: 'container'\n        }, [_vm._v(_vm._s(_vm.info))])\n      }\n    }\n    const options = {\n      components: {\n        card: cardOptions\n      },\n      data () {\n        return {\n          items: [111, 222, 333]\n        }\n      },\n      // <div class=\"container\">\n      //     <card v-for=\"item in items\" :info=\"item\"></card>\n      // </div>\n      render () {\n        var _vm = this\n        var _h = _vm.$createElement\n        var _c = _vm._self._c || _h\n        return _c('div', {\n          staticClass: 'container'\n        }, [_vm._l((_vm.items), function (item, index) {\n          return _c('card', {\n            attrs: {\n              'info': item,\n              'mpcomid': '1-' + index\n            }\n          })\n        })], 1)\n      }\n    }\n    const app = createInstance(options)\n    app.$mount()\n\n    setTimeout(function () {\n      const appData = getDefAppDataByVfor()\n      appData['$root']['0,1-0']['msg'] = 'hello card'\n      appData['$root']['0,1-1']['msg'] = 'hello card with 222'\n      appData['$root']['0,1-2']['msg'] = 'hello card'\n      expect(app.$mp.page.data).toEqual(appData)\n      done()\n    }, 300)\n  })\n})\n"
  },
  {
    "path": "test/mp/runtime/lifecycle.spec.js",
    "content": "const { createInstance } = require('../helpers/index')\n\n// 生命周期\ndescribe('init mpvue with lifecycle', function () {\n  const onLifecycle = []\n  const getOptions = {}\n\n  function getComponentOptions (key = '') {\n    return {\n      // lifycycle for vue\n      beforeCreate () {\n        onLifecycle.push(`beforeCreate${key}`)\n      },\n      created () {\n        onLifecycle.push(`created${key}`)\n      },\n      beforeMount () {\n        onLifecycle.push(`beforeMount${key}`)\n      },\n      mounted () {\n        onLifecycle.push(`mounted${key}`)\n      },\n      beforeUpdate () {\n        onLifecycle.push(`beforeUpdate${key}`)\n      },\n      updated () {\n        onLifecycle.push(`updated${key}`)\n      },\n      activated () {\n        onLifecycle.push(`activated${key}`)\n      },\n      deactivated () {\n        onLifecycle.push(`deactivated${key}`)\n      },\n      beforeDestroy () {\n        onLifecycle.push(`beforeDestroy${key}`)\n      },\n      destroyed () {\n        onLifecycle.push(`destroyed${key}`)\n      },\n      // lifycycle for wxmp\n      onLaunch (opt) {\n        getOptions.onLaunch = opt\n        onLifecycle.push(`onLaunch${key}`)\n      },\n      onLoad (opt) {\n        getOptions.onLoad = opt\n        onLifecycle.push(`onLoad${key}`)\n      },\n      onShow (opt) {\n        getOptions.onShow = opt\n        onLifecycle.push(`onShow${key}`)\n      },\n      onReady () {\n        onLifecycle.push(`onReady${key}`)\n      },\n      onHide () {\n        onLifecycle.push(`onHide${key}`)\n      },\n      onUnload () {\n        onLifecycle.push(`unload${key}`)\n      },\n      onPullDownRefresh () {\n        onLifecycle.push(`pullDownRefresh${key}`)\n      },\n      onReachBottom () {\n        onLifecycle.push(`reachBottom${key}`)\n      },\n      onShareAppMessage () {\n        onLifecycle.push(`shareAppMessage${key}`)\n      },\n      onPageScroll () {\n        onLifecycle.push(`pageScroll${key}`)\n      },\n      // custom component lifecycle\n      attached () {\n        onLifecycle.push(`attached${key}`)\n      },\n      ready () {\n        onLifecycle.push(`ready${key}`)\n      },\n      moved () {\n        onLifecycle.push(`moved${key}`)\n      },\n      detached () {\n        onLifecycle.push(`detached${key}`)\n      }\n    }\n  }\n\n  beforeEach(function () {\n    onLifecycle.length = 0\n  })\n\n  it('App', function () {\n    const options = Object.assign(getComponentOptions(), {\n      mpType: 'app'\n    })\n    const app = createInstance(options)\n    app.$mount()\n    expect(onLifecycle).toEqual(['beforeCreate', 'created', 'onLaunch', 'beforeMount', 'mounted', 'onShow'])\n    expect(!!app.$mp.app).toEqual(true)\n    const opt = {\n      path: 'pages/index/index',\n      scene: 1001,\n      query: {}\n    }\n    expect(app.$mp.appOptions).toEqual(opt)\n    expect(getOptions.onLaunch).toEqual(opt)\n    expect(getOptions.onShow).toEqual(opt)\n    expect(app.$mp.mpType).toEqual('app')\n    expect(app.$mp.status).toEqual('show')\n  })\n\n  it('Page with render', function () {\n    const options = Object.assign(getComponentOptions(), {\n      render () {\n        var _vm = this\n        var _h = _vm.$createElement\n        var _c = _vm._self._c || _h\n        return _c('div', {\n          staticClass: 'container'\n        }, [], 1)\n      }\n    })\n    const app = createInstance(options)\n    app.$mount()\n    expect(onLifecycle).toEqual(['beforeCreate', 'created', 'onLoad', 'onShow', 'onReady', 'beforeMount', 'mounted'])\n    expect(!!app.$mp.page).toEqual(true)\n    expect(app.$mp.query).toEqual({})\n    expect(getOptions.onLoad).toEqual({})\n    expect(app.$mp.appOptions).toEqual({\n      path: 'pages/index/index',\n      scene: 1001,\n      query: {}\n    })\n    expect(app.$mp.mpType).toEqual('page')\n    expect(app.$mp.status).toEqual('ready')\n  })\n\n  it('Page with components', function () {\n    const warpOptions = Object.assign(getComponentOptions('-warp'), {\n      render () {\n        var _vm = this\n        var _h = _vm.$createElement\n        var _c = _vm._self._c || _h\n        return _c('div', {\n          staticClass: 'container'\n        }, [_vm._v('warp component')], 1)\n      }\n    })\n    const options = Object.assign(getComponentOptions(), {\n      components: {\n        warp: warpOptions\n      },\n      render () {\n        var _vm = this\n        var _h = _vm.$createElement\n        var _c = _vm._self._c || _h\n        return _c('div', {\n          staticClass: 'container'\n        }, [_c('warp')], 1)\n      }\n    })\n    const app = createInstance(options)\n    app.$mount()\n\n    expect(onLifecycle).toEqual([\n      'beforeCreate',\n      'created',\n      'onLoad',\n      'onShow',\n      'onReady',\n      'beforeMount',\n      'beforeCreate-warp',\n      'created-warp',\n      'onLoad-warp',\n      'onReady-warp',\n      'beforeMount-warp',\n      'mounted-warp',\n      'mounted'\n    ])\n    expect(!!app.$mp.page).toEqual(true)\n    expect(app.$mp.query).toEqual({})\n    expect(app.$mp.mpType).toEqual('page')\n    expect(app.$mp.status).toEqual('ready')\n  })\n\n  it('Page with leaveAndBack', function (done) {\n    const options = Object.assign(getComponentOptions(), {\n      render () {\n        var _vm = this\n        var _h = _vm.$createElement\n        var _c = _vm._self._c || _h\n        return _c('div', {\n          staticClass: 'container'\n        }, [], 1)\n      }\n    })\n    const app = createInstance(options)\n    app.$mount()\n    expect(onLifecycle).toEqual(['beforeCreate', 'created', 'onLoad', 'onShow', 'onReady', 'beforeMount', 'mounted'])\n    expect(!!app.$mp.page).toEqual(true)\n    expect(app.$mp.query).toEqual({})\n    expect(app.$mp.mpType).toEqual('page')\n    expect(app.$mp.status).toEqual('ready')\n\n    app.$mp.page._leaveAndBack()\n    expect(app.$mp.status).toEqual('hide')\n    setTimeout(() => {\n      expect(onLifecycle).toEqual(['beforeCreate', 'created', 'onLoad', 'onShow', 'onReady', 'beforeMount', 'mounted', 'onHide', 'onShow'])\n      expect(app.$mp.status).toEqual('show')\n      done()\n    }, 200)\n  })\n\n  it('Page with customEvent', function () {\n    const options = Object.assign(getComponentOptions(), {\n      render () {\n        var _vm = this\n        var _h = _vm.$createElement\n        var _c = _vm._self._c || _h\n        return _c('div', {\n          staticClass: 'container'\n        }, [], 1)\n      }\n    })\n    const app = createInstance(options)\n    app.$mount()\n    expect(onLifecycle).toEqual(['beforeCreate', 'created', 'onLoad', 'onShow', 'onReady', 'beforeMount', 'mounted'])\n    expect(!!app.$mp.page).toEqual(true)\n    expect(app.$mp.query).toEqual({})\n    expect(app.$mp.mpType).toEqual('page')\n    expect(app.$mp.status).toEqual('ready')\n\n    app.$mp.page._callHook('onPullDownRefresh')\n    expect(onLifecycle).toEqual(['beforeCreate', 'created', 'onLoad', 'onShow', 'onReady', 'beforeMount', 'mounted', 'pullDownRefresh'])\n\n    app.$mp.page._callHook('onReachBottom')\n    expect(onLifecycle).toEqual(['beforeCreate', 'created', 'onLoad', 'onShow', 'onReady', 'beforeMount', 'mounted', 'pullDownRefresh', 'reachBottom'])\n\n    app.$mp.page._callHook('onShareAppMessage')\n    expect(onLifecycle).toEqual(['beforeCreate', 'created', 'onLoad', 'onShow', 'onReady', 'beforeMount', 'mounted', 'pullDownRefresh', 'reachBottom', 'shareAppMessage'])\n\n    app.$mp.page._callHook('onPageScroll')\n    expect(onLifecycle).toEqual(['beforeCreate', 'created', 'onLoad', 'onShow', 'onReady', 'beforeMount', 'mounted', 'pullDownRefresh', 'reachBottom', 'shareAppMessage', 'pageScroll'])\n\n    // onUnload\n    app.$mp.page._callHook('onUnload')\n    expect(app.$mp.status).toEqual('unload')\n    expect(onLifecycle).toEqual(['beforeCreate', 'created', 'onLoad', 'onShow', 'onReady', 'beforeMount', 'mounted', 'pullDownRefresh', 'reachBottom', 'shareAppMessage', 'pageScroll', 'unload'])\n  })\n\n  it('Component with render', function () {\n    const options = Object.assign(getComponentOptions(), {\n      mpType: 'component',\n      render () {\n        var _vm = this\n        var _h = _vm.$createElement\n        var _c = _vm._self._c || _h\n        return _c('div', {\n          staticClass: 'container'\n        }, [], 1)\n      }\n    })\n\n    const app = createInstance(options)\n    app.$mount()\n    expect(onLifecycle).toEqual(['beforeCreate', 'created', 'attached', 'ready', 'beforeMount', 'mounted'])\n    expect(!!app.$mp.page).toEqual(true)\n    expect(app.$mp.mpType).toEqual('component')\n    expect(app.$mp.status).toEqual('ready')\n  })\n\n  it('Component with component', function () {\n    const warpOptions = Object.assign(getComponentOptions('-warp'), {\n      render () {\n        var _vm = this\n        var _h = _vm.$createElement\n        var _c = _vm._self._c || _h\n        return _c('div', {\n          staticClass: 'container'\n        }, [_vm._v('warp component')], 1)\n      }\n    })\n    const options = Object.assign(getComponentOptions(), {\n      mpType: 'component',\n      components: {\n        warp: warpOptions\n      },\n      render () {\n        var _vm = this\n        var _h = _vm.$createElement\n        var _c = _vm._self._c || _h\n        return _c('div', {\n          staticClass: 'container'\n        }, [_c('warp')], 1)\n      }\n    })\n    const app = createInstance(options)\n    app.$mount()\n\n    expect(onLifecycle).toEqual([\n      'beforeCreate',\n      'created',\n      'attached',\n      'ready',\n      'beforeMount',\n      'beforeCreate-warp',\n      'created-warp',\n      'onLoad-warp',\n      'onReady-warp',\n      'beforeMount-warp',\n      'mounted-warp',\n      'mounted'\n    ])\n    expect(!!app.$mp.page).toEqual(true)\n    expect(app.$mp.mpType).toEqual('component')\n    expect(app.$mp.status).toEqual('ready')\n  })\n\n  it('Component with customEvent', function () {\n    const options = Object.assign(getComponentOptions(), {\n      mpType: 'component',\n      render () {\n        var _vm = this\n        var _h = _vm.$createElement\n        var _c = _vm._self._c || _h\n        return _c('div', {\n          staticClass: 'container'\n        }, [], 1)\n      }\n    })\n    const app = createInstance(options)\n    app.$mount()\n    expect(onLifecycle).toEqual(['beforeCreate', 'created', 'attached', 'ready', 'beforeMount', 'mounted'])\n    expect(!!app.$mp.page).toEqual(true)\n    expect(app.$mp.mpType).toEqual('component')\n    expect(app.$mp.status).toEqual('ready')\n\n    // moved\n    app.$mp.page._callHook('moved')\n    expect(onLifecycle).toEqual(['beforeCreate', 'created', 'attached', 'ready', 'beforeMount', 'mounted', 'moved'])\n\n    // detached\n    app.$mp.page._callHook('detached')\n    expect(app.$mp.status).toEqual('detached')\n    expect(onLifecycle).toEqual(['beforeCreate', 'created', 'attached', 'ready', 'beforeMount', 'mounted', 'moved', 'detached'])\n  })\n})\n"
  },
  {
    "path": "test/ssr/.eslintrc",
    "content": "{\n  \"env\": {\n    \"jasmine\": true\n  },\n  \"plugins\": [\"jasmine\"],\n  \"rules\": {\n    \"jasmine/no-focused-tests\": 2\n  }\n}\n"
  },
  {
    "path": "test/ssr/async-loader.js",
    "content": "const hash = require('hash-sum')\n\nmodule.exports = function (code) {\n  const id = hash(this.request) // simulating vue-loader module id injection\n  return code.replace('__MODULE_ID__', id)\n}\n"
  },
  {
    "path": "test/ssr/compile-with-webpack.js",
    "content": "import path from 'path'\nimport webpack from 'webpack'\nimport MemoeryFS from 'memory-fs'\n\nexport function compileWithWebpack (file, extraConfig, cb) {\n  const config = Object.assign({\n    entry: path.resolve(__dirname, 'fixtures', file),\n    module: {\n      rules: [\n        {\n          test: /\\.js$/,\n          loader: 'babel-loader'\n        },\n        {\n          test: /async-.*\\.js$/,\n          loader: require.resolve('./async-loader')\n        },\n        {\n          test: /\\.(png|woff2|css)$/,\n          loader: 'file-loader',\n          options: {\n            name: '[name].[ext]'\n          }\n        }\n      ]\n    }\n  }, extraConfig)\n\n  const compiler = webpack(config)\n  const fs = new MemoeryFS()\n  compiler.outputFileSystem = fs\n\n  compiler.run((err, stats) => {\n    expect(err).toBeFalsy()\n    expect(stats.errors).toBeFalsy()\n    cb(fs)\n  })\n}\n"
  },
  {
    "path": "test/ssr/fixtures/app.js",
    "content": "import Vue from '../../../dist/vue.runtime.common.js'\n\nexport default context => {\n  return new Promise(resolve => {\n    context.msg = 'hello'\n    resolve(new Vue({\n      render (h) {\n        return h('div', context.url)\n      }\n    }))\n  })\n}\n"
  },
  {
    "path": "test/ssr/fixtures/async-bar.js",
    "content": "module.exports = {\n  beforeCreate () {\n    this.$vnode.ssrContext._registeredComponents.add('__MODULE_ID__')\n  },\n  render (h) {\n    return h('div', 'async bar')\n  }\n}\n"
  },
  {
    "path": "test/ssr/fixtures/async-foo.js",
    "content": "// import image and font\nimport './test.css'\nimport font from './test.woff2'\nimport image from './test.png'\n\nmodule.exports = {\n  beforeCreate () {\n    this.$vnode.ssrContext._registeredComponents.add('__MODULE_ID__')\n  },\n  render (h) {\n    return h('div', `async ${font} ${image}`)\n  }\n}\n"
  },
  {
    "path": "test/ssr/fixtures/cache.js",
    "content": "import Vue from '../../../dist/vue.runtime.common.js'\n\nconst app = {\n  name: 'app',\n  props: ['id'],\n  serverCacheKey: props => props.id,\n  render (h) {\n    return h('div', '/test')\n  }\n}\n\nexport default () => {\n  return Promise.resolve(new Vue({\n    render: h => h(app, { props: { id: 1 }})\n  }))\n}\n"
  },
  {
    "path": "test/ssr/fixtures/error.js",
    "content": "throw new Error('foo')\n"
  },
  {
    "path": "test/ssr/fixtures/nested-cache.js",
    "content": "import Vue from '../../../dist/vue.runtime.common.js'\n\nfunction createRegisterFn (id) {\n  return function (context) {\n    context = context || this.$vnode.ssrContext\n    context.registered.push(id)\n  }\n}\n\nfunction addHooks (comp) {\n  const hook = createRegisterFn(comp.name)\n  return Object.assign(comp, {\n    _ssrRegister: hook,\n    beforeCreate: hook\n  })\n}\n\nconst grandchild = addHooks({\n  name: 'grandchild',\n  props: ['id'],\n  serverCacheKey: props => props.id,\n  render (h) {\n    return h('div', '/test')\n  }\n})\n\nconst child = addHooks({\n  name: 'child',\n  props: ['id'],\n  serverCacheKey: props => props.id,\n  render (h) {\n    return h(grandchild, { props: { id: this.id }})\n  }\n})\n\nconst app = addHooks({\n  name: 'app',\n  props: ['id'],\n  serverCacheKey: props => props.id,\n  render (h) {\n    return h(child, { props: { id: this.id }})\n  }\n})\n\nexport default () => {\n  return Promise.resolve(new Vue({\n    render: h => h(app, { props: { id: 1 }})\n  }))\n}\n"
  },
  {
    "path": "test/ssr/fixtures/split.js",
    "content": "import Vue from '../../../dist/vue.runtime.common.js'\n\n// async component!\nconst Foo = () => import('./async-foo')\nconst Bar = () => import('./async-bar') // eslint-disable-line\n\nexport default context => {\n  return new Promise(resolve => {\n    context.msg = 'hello'\n    const vm = new Vue({\n      render (h) {\n        return h('div', [\n          context.url,\n          h(Foo)\n        ])\n      }\n    })\n\n    // simulate router.onReady\n    Foo().then(comp => {\n      // resolve now to make the render sync\n      Foo.resolved = Vue.extend(comp)\n      resolve(vm)\n    })\n  })\n}\n"
  },
  {
    "path": "test/ssr/fixtures/test.css",
    "content": ""
  },
  {
    "path": "test/ssr/jasmine.json",
    "content": "{\n  \"spec_dir\": \"test/ssr\",\n  \"spec_files\": [\n    \"*.spec.js\"\n  ],\n  \"helpers\": [\n    \"../../node_modules/babel-register/lib/node.js\"\n  ]\n}\n"
  },
  {
    "path": "test/ssr/ssr-basic-renderer.spec.js",
    "content": "import Vue from '../../dist/vue.runtime.common.js'\nimport renderToString from '../../packages/vue-server-renderer/basic'\n\ndescribe('SSR: basicRenderer', () => {\n  it('should work', done => {\n    renderToString(new Vue({\n      template: `\n        <div>\n          <p class=\"hi\">yoyo</p>\n          <div id=\"ho\" :class=\"{ red: isRed }\"></div>\n          <span>{{ test }}</span>\n          <input :value=\"test\">\n          <img :src=\"imageUrl\">\n          <test></test>\n          <test-async></test-async>\n        </div>\n      `,\n      data: {\n        test: 'hi',\n        isRed: true,\n        imageUrl: 'https://vuejs.org/images/logo.png'\n      },\n      components: {\n        test: {\n          render () {\n            return this.$createElement('div', { class: ['a'] }, 'test')\n          }\n        },\n        testAsync (resolve) {\n          resolve({\n            render () {\n              return this.$createElement('span', { class: ['b'] }, 'testAsync')\n            }\n          })\n        }\n      }\n    }), (err, result) => {\n      expect(err).toBeNull()\n      expect(result).toContain(\n        '<div data-server-rendered=\"true\">' +\n          '<p class=\"hi\">yoyo</p> ' +\n          '<div id=\"ho\" class=\"red\"></div> ' +\n          '<span>hi</span> ' +\n          '<input value=\"hi\"> ' +\n          '<img src=\"https://vuejs.org/images/logo.png\"> ' +\n          '<div class=\"a\">test</div> ' +\n          '<span class=\"b\">testAsync</span>' +\n        '</div>'\n      )\n      done()\n    })\n  })\n\n  // #5941\n  it('should work peoperly when accessing $ssrContext in root component', done => {\n    let ssrContext\n    renderToString(new Vue({\n      template: `\n        <div></div>\n      `,\n      created () {\n        ssrContext = this.$ssrContext\n      }\n    }), (err, result) => {\n      expect(err).toBeNull()\n      expect(ssrContext).toBeUndefined()\n      done()\n    })\n  })\n})\n"
  },
  {
    "path": "test/ssr/ssr-bundle-render.spec.js",
    "content": "import LRU from 'lru-cache'\nimport { compileWithWebpack } from './compile-with-webpack'\nimport { createBundleRenderer } from '../../packages/vue-server-renderer'\nimport VueSSRServerPlugin from '../../packages/vue-server-renderer/server-plugin'\n\nexport function createRenderer (file, options, cb) {\n  if (typeof options === 'function') {\n    cb = options\n    options = undefined\n  }\n  const asBundle = !!(options && options.asBundle)\n  if (options) delete options.asBundle\n\n  compileWithWebpack(file, {\n    target: 'node',\n    devtool: asBundle ? '#source-map' : false,\n    output: {\n      path: '/',\n      filename: 'bundle.js',\n      libraryTarget: 'commonjs2'\n    },\n    externals: [require.resolve('../../dist/vue.runtime.common.js')],\n    plugins: asBundle\n      ? [new VueSSRServerPlugin()]\n      : []\n  }, fs => {\n    const bundle = asBundle\n      ? JSON.parse(fs.readFileSync('/vue-ssr-server-bundle.json', 'utf-8'))\n      : fs.readFileSync('/bundle.js', 'utf-8')\n    const renderer = createBundleRenderer(bundle, options)\n    cb(renderer)\n  })\n}\n\ndescribe('SSR: bundle renderer', () => {\n  createAssertions(true)\n  createAssertions(false)\n})\n\nfunction createAssertions (runInNewContext) {\n  it('renderToString', done => {\n    createRenderer('app.js', { runInNewContext }, renderer => {\n      const context = { url: '/test' }\n      renderer.renderToString(context, (err, res) => {\n        expect(err).toBeNull()\n        expect(res).toBe('<div data-server-rendered=\"true\">/test</div>')\n        expect(context.msg).toBe('hello')\n        done()\n      })\n    })\n  })\n\n  it('renderToStream', done => {\n    createRenderer('app.js', { runInNewContext }, renderer => {\n      const context = { url: '/test' }\n      const stream = renderer.renderToStream(context)\n      let res = ''\n      stream.on('data', chunk => {\n        res += chunk.toString()\n      })\n      stream.on('end', () => {\n        expect(res).toBe('<div data-server-rendered=\"true\">/test</div>')\n        expect(context.msg).toBe('hello')\n        done()\n      })\n    })\n  })\n\n  it('renderToString catch error', done => {\n    createRenderer('error.js', { runInNewContext }, renderer => {\n      renderer.renderToString(err => {\n        expect(err.message).toBe('foo')\n        done()\n      })\n    })\n  })\n\n  it('renderToStream catch error', done => {\n    createRenderer('error.js', { runInNewContext }, renderer => {\n      const stream = renderer.renderToStream()\n      stream.on('error', err => {\n        expect(err.message).toBe('foo')\n        done()\n      })\n    })\n  })\n\n  it('render with cache (get/set)', done => {\n    const cache = {}\n    const get = jasmine.createSpy('get')\n    const set = jasmine.createSpy('set')\n    const options = {\n      runInNewContext,\n      cache: {\n        // async\n        get: (key, cb) => {\n          setTimeout(() => {\n            get(key)\n            cb(cache[key])\n          }, 0)\n        },\n        set: (key, val) => {\n          set(key, val)\n          cache[key] = val\n        }\n      }\n    }\n    createRenderer('cache.js', options, renderer => {\n      const expected = '<div data-server-rendered=\"true\">/test</div>'\n      const key = 'app::1'\n      renderer.renderToString((err, res) => {\n        expect(err).toBeNull()\n        expect(res).toBe(expected)\n        expect(get).toHaveBeenCalledWith(key)\n        const setArgs = set.calls.argsFor(0)\n        expect(setArgs[0]).toBe(key)\n        expect(setArgs[1].html).toBe(expected)\n        expect(cache[key].html).toBe(expected)\n        renderer.renderToString((err, res) => {\n          expect(err).toBeNull()\n          expect(res).toBe(expected)\n          expect(get.calls.count()).toBe(2)\n          expect(set.calls.count()).toBe(1)\n          done()\n        })\n      })\n    })\n  })\n\n  it('render with cache (get/set/has)', done => {\n    const cache = {}\n    const has = jasmine.createSpy('has')\n    const get = jasmine.createSpy('get')\n    const set = jasmine.createSpy('set')\n    const options = {\n      runInNewContext,\n      cache: {\n        // async\n        has: (key, cb) => {\n          has(key)\n          cb(!!cache[key])\n        },\n        // sync\n        get: key => {\n          get(key)\n          return cache[key]\n        },\n        set: (key, val) => {\n          set(key, val)\n          cache[key] = val\n        }\n      }\n    }\n    createRenderer('cache.js', options, renderer => {\n      const expected = '<div data-server-rendered=\"true\">/test</div>'\n      const key = 'app::1'\n      renderer.renderToString((err, res) => {\n        expect(err).toBeNull()\n        expect(res).toBe(expected)\n        expect(has).toHaveBeenCalledWith(key)\n        expect(get).not.toHaveBeenCalled()\n        const setArgs = set.calls.argsFor(0)\n        expect(setArgs[0]).toBe(key)\n        expect(setArgs[1].html).toBe(expected)\n        expect(cache[key].html).toBe(expected)\n        renderer.renderToString((err, res) => {\n          expect(err).toBeNull()\n          expect(res).toBe(expected)\n          expect(has.calls.count()).toBe(2)\n          expect(get.calls.count()).toBe(1)\n          expect(set.calls.count()).toBe(1)\n          done()\n        })\n      })\n    })\n  })\n\n  it('render with cache (nested)', done => {\n    const cache = LRU({ maxAge: Infinity })\n    spyOn(cache, 'get').and.callThrough()\n    spyOn(cache, 'set').and.callThrough()\n    const options = {\n      cache,\n      runInNewContext\n    }\n    createRenderer('nested-cache.js', options, renderer => {\n      const expected = '<div data-server-rendered=\"true\">/test</div>'\n      const key = 'app::1'\n      const context1 = { registered: [] }\n      const context2 = { registered: [] }\n      renderer.renderToString(context1, (err, res) => {\n        expect(err).toBeNull()\n        expect(res).toBe(expected)\n        expect(cache.set.calls.count()).toBe(3) // 3 nested components cached\n        const cached = cache.get(key)\n        expect(cached.html).toBe(expected)\n        expect(cache.get.calls.count()).toBe(1)\n\n        // assert component usage registration for nested children\n        expect(context1.registered).toEqual(['app', 'child', 'grandchild'])\n\n        renderer.renderToString(context2, (err, res) => {\n          expect(err).toBeNull()\n          expect(res).toBe(expected)\n          expect(cache.set.calls.count()).toBe(3) // no new cache sets\n          expect(cache.get.calls.count()).toBe(2) // 1 get for root\n\n          expect(context2.registered).toEqual(['app', 'child', 'grandchild'])\n          done()\n        })\n      })\n    })\n  })\n\n  it('renderToString (bundle format with code split)', done => {\n    createRenderer('split.js', { runInNewContext, asBundle: true }, renderer => {\n      const context = { url: '/test' }\n      renderer.renderToString(context, (err, res) => {\n        expect(err).toBeNull()\n        expect(res).toBe('<div data-server-rendered=\"true\">/test<div>async test.woff2 test.png</div></div>')\n        done()\n      })\n    })\n  })\n\n  it('renderToStream (bundle format with code split)', done => {\n    createRenderer('split.js', { runInNewContext, asBundle: true }, renderer => {\n      const context = { url: '/test' }\n      const stream = renderer.renderToStream(context)\n      let res = ''\n      stream.on('data', chunk => {\n        res += chunk.toString()\n      })\n      stream.on('end', () => {\n        expect(res).toBe('<div data-server-rendered=\"true\">/test<div>async test.woff2 test.png</div></div>')\n        done()\n      })\n    })\n  })\n\n  it('renderToString catch error (bundle format with source map)', done => {\n    createRenderer('error.js', { runInNewContext, asBundle: true }, renderer => {\n      renderer.renderToString(err => {\n        expect(err.stack).toContain('test/ssr/fixtures/error.js:1:6')\n        expect(err.message).toBe('foo')\n        done()\n      })\n    })\n  })\n\n  it('renderToString catch error (bundle format with source map)', done => {\n    createRenderer('error.js', { runInNewContext, asBundle: true }, renderer => {\n      const stream = renderer.renderToStream()\n      stream.on('error', err => {\n        expect(err.stack).toContain('test/ssr/fixtures/error.js:1:6')\n        expect(err.message).toBe('foo')\n        done()\n      })\n    })\n  })\n}\n"
  },
  {
    "path": "test/ssr/ssr-stream.spec.js",
    "content": "import Vue from '../../dist/vue.runtime.common.js'\nimport { createRenderer } from '../../packages/vue-server-renderer'\nconst { renderToStream } = createRenderer()\n\ndescribe('SSR: renderToStream', () => {\n  it('should render to a stream', done => {\n    const stream = renderToStream(new Vue({\n      template: `\n        <div>\n          <p class=\"hi\">yoyo</p>\n          <div id=\"ho\" :class=\"[testClass, { red: isRed }]\"></div>\n          <span>{{ test }}</span>\n          <input :value=\"test\">\n          <b-comp></b-comp>\n          <c-comp></c-comp>\n        </div>\n      `,\n      data: {\n        test: 'hi',\n        isRed: true,\n        testClass: 'a'\n      },\n      components: {\n        bComp (resolve) {\n          return resolve({\n            render (h) {\n              return h('test-async-2')\n            },\n            components: {\n              testAsync2 (resolve) {\n                return resolve({\n                  created () { this.$parent.$parent.testClass = 'b' },\n                  render (h) {\n                    return h('div', { class: [this.$parent.$parent.testClass] }, 'test')\n                  }\n                })\n              }\n            }\n          })\n        },\n        cComp: {\n          render (h) {\n            return h('div', { class: [this.$parent.testClass] }, 'test')\n          }\n        }\n      }\n    }))\n    let res = ''\n    stream.on('data', chunk => {\n      res += chunk\n    })\n    stream.on('end', () => {\n      expect(res).toContain(\n        '<div data-server-rendered=\"true\">' +\n          '<p class=\"hi\">yoyo</p> ' +\n          '<div id=\"ho\" class=\"a red\"></div> ' +\n          '<span>hi</span> ' +\n          '<input value=\"hi\"> ' +\n          '<div class=\"b\">test</div> ' +\n          '<div class=\"b\">test</div>' +\n        '</div>'\n      )\n      done()\n    })\n  })\n\n  it('should catch error', done => {\n    Vue.config.silent = true\n    const stream = renderToStream(new Vue({\n      render () {\n        throw new Error('oops')\n      }\n    }))\n    stream.on('error', err => {\n      expect(err.toString()).toMatch(/oops/)\n      Vue.config.silent = false\n      done()\n    })\n    stream.on('data', _ => _)\n  })\n\n  it('should not mingle two components', done => {\n    const padding = (new Array(20000)).join('x')\n    const component1 = new Vue({\n      template: `<div>${padding}<div></div></div>`,\n      _scopeId: '_component1'\n    })\n    const component2 = new Vue({\n      template: `<div></div>`,\n      _scopeId: '_component2'\n    })\n    var stream1 = renderToStream(component1)\n    var stream2 = renderToStream(component2)\n    var res = ''\n    stream1.on('data', (text) => {\n      res += text.toString('utf-8').replace(/x/g, '')\n    })\n    stream1.on('end', () => {\n      expect(res).not.toContain('_component2')\n      done()\n    })\n    stream1.read(1)\n    stream2.read(1)\n  })\n})\n"
  },
  {
    "path": "test/ssr/ssr-string.spec.js",
    "content": "import Vue from '../../dist/vue.runtime.common.js'\nimport VM from 'vm'\nimport { createRenderer } from '../../packages/vue-server-renderer'\nconst { renderToString } = createRenderer()\n\ndescribe('SSR: renderToString', () => {\n  it('static attributes', done => {\n    renderVmWithOptions({\n      template: '<div id=\"foo\" bar=\"123\"></div>'\n    }, result => {\n      expect(result).toContain('<div id=\"foo\" bar=\"123\" data-server-rendered=\"true\"></div>')\n      done()\n    })\n  })\n\n  it('unary tags', done => {\n    renderVmWithOptions({\n      template: '<input value=\"123\">'\n    }, result => {\n      expect(result).toContain('<input value=\"123\" data-server-rendered=\"true\">')\n      done()\n    })\n  })\n\n  it('dynamic attributes', done => {\n    renderVmWithOptions({\n      template: '<div qux=\"quux\" :id=\"foo\" :bar=\"baz\"></div>',\n      data: {\n        foo: 'hi',\n        baz: 123\n      }\n    }, result => {\n      expect(result).toContain('<div qux=\"quux\" id=\"hi\" bar=\"123\" data-server-rendered=\"true\"></div>')\n      done()\n    })\n  })\n\n  it('static class', done => {\n    renderVmWithOptions({\n      template: '<div class=\"foo bar\"></div>'\n    }, result => {\n      expect(result).toContain('<div data-server-rendered=\"true\" class=\"foo bar\"></div>')\n      done()\n    })\n  })\n\n  it('dynamic class', done => {\n    renderVmWithOptions({\n      template: '<div class=\"foo bar\" :class=\"[a, { qux: hasQux, quux: hasQuux }]\"></div>',\n      data: {\n        a: 'baz',\n        hasQux: true,\n        hasQuux: false\n      }\n    }, result => {\n      expect(result).toContain('<div data-server-rendered=\"true\" class=\"foo bar baz qux\"></div>')\n      done()\n    })\n  })\n\n  it('custom component class', done => {\n    renderVmWithOptions({\n      template: '<div><cmp class=\"cmp\"></cmp></div>',\n      components: {\n        cmp: {\n          render: h => h('div', 'test')\n        }\n      }\n    }, result => {\n      expect(result).toContain('<div data-server-rendered=\"true\"><div class=\"cmp\">test</div></div>')\n      done()\n    })\n  })\n\n  it('nested component class', done => {\n    renderVmWithOptions({\n      template: '<cmp class=\"outer\" :class=\"cls\"></cmp>',\n      data: { cls: { 'success': 1 }},\n      components: {\n        cmp: {\n          render: h => h('div', [h('nested', { staticClass: 'nested', 'class': { 'error': 1 }})]),\n          components: {\n            nested: {\n              render: h => h('div', { staticClass: 'inner' }, 'test')\n            }\n          }\n        }\n      }\n    }, result => {\n      expect(result).toContain('<div data-server-rendered=\"true\" class=\"outer success\">' +\n          '<div class=\"inner nested error\">test</div>' +\n        '</div>')\n      done()\n    })\n  })\n\n  it('dynamic style', done => {\n    renderVmWithOptions({\n      template: '<div style=\"background-color:black\" :style=\"{ fontSize: fontSize + \\'px\\', color: color }\"></div>',\n      data: {\n        fontSize: 14,\n        color: 'red'\n      }\n    }, result => {\n      expect(result).toContain(\n        '<div data-server-rendered=\"true\" style=\"background-color:black;font-size:14px;color:red;\"></div>'\n      )\n      done()\n    })\n  })\n\n  it('dynamic string style', done => {\n    renderVmWithOptions({\n      template: '<div :style=\"style\"></div>',\n      data: {\n        style: 'color:red'\n      }\n    }, result => {\n      expect(result).toContain(\n        '<div data-server-rendered=\"true\" style=\"color:red;\"></div>'\n      )\n      done()\n    })\n  })\n\n  it('auto-prefixed style value as array', done => {\n    renderVmWithOptions({\n      template: '<div :style=\"style\"></div>',\n      data: {\n        style: {\n          display: ['-webkit-box', '-ms-flexbox', 'flex']\n        }\n      }\n    }, result => {\n      expect(result).toContain(\n        '<div data-server-rendered=\"true\" style=\"display:-webkit-box;display:-ms-flexbox;display:flex;\"></div>'\n      )\n      done()\n    })\n  })\n\n  it('custom component style', done => {\n    renderVmWithOptions({\n      template: '<section><comp :style=\"style\"></comp></section>',\n      data: {\n        style: 'color:red'\n      },\n      components: {\n        comp: {\n          template: '<div></div>'\n        }\n      }\n    }, result => {\n      expect(result).toContain(\n        '<section data-server-rendered=\"true\"><div style=\"color:red;\"></div></section>'\n      )\n      done()\n    })\n  })\n\n  it('nested custom component style', done => {\n    renderVmWithOptions({\n      template: '<comp style=\"color: blue\" :style=\"style\"></comp>',\n      data: {\n        style: 'color:red'\n      },\n      components: {\n        comp: {\n          template: '<nested style=\"text-align: left;\" :style=\"{fontSize:\\'520rem\\'}\"></nested>',\n          components: {\n            nested: {\n              template: '<div></div>'\n            }\n          }\n        }\n      }\n    }, result => {\n      expect(result).toContain(\n        '<div data-server-rendered=\"true\" style=\"text-align:left;font-size:520rem;color:red;\"></div>'\n      )\n      done()\n    })\n  })\n\n  it('component style not passed to child', done => {\n    renderVmWithOptions({\n      template: '<comp :style=\"style\"></comp>',\n      data: {\n        style: 'color:red'\n      },\n      components: {\n        comp: {\n          template: '<div><div></div></div>'\n        }\n      }\n    }, result => {\n      expect(result).toContain(\n        '<div data-server-rendered=\"true\" style=\"color:red;\"><div></div></div>'\n      )\n      done()\n    })\n  })\n\n  it('component style not passed to slot', done => {\n    renderVmWithOptions({\n      template: '<comp :style=\"style\"><span style=\"color:black\"></span></comp>',\n      data: {\n        style: 'color:red'\n      },\n      components: {\n        comp: {\n          template: '<div><slot></slot></div>'\n        }\n      }\n    }, result => {\n      expect(result).toContain(\n        '<div data-server-rendered=\"true\" style=\"color:red;\"><span style=\"color:black;\"></span></div>'\n      )\n      done()\n    })\n  })\n\n  it('attrs merging on components', done => {\n    const Test = {\n      render: h => h('div', {\n        attrs: { id: 'a' }\n      })\n    }\n    renderVmWithOptions({\n      render: h => h(Test, {\n        attrs: { id: 'b', name: 'c' }\n      })\n    }, res => {\n      expect(res).toContain(\n        '<div id=\"b\" data-server-rendered=\"true\" name=\"c\"></div>'\n      )\n      done()\n    })\n  })\n\n  it('domProps merging on components', done => {\n    const Test = {\n      render: h => h('div', {\n        domProps: { innerHTML: 'a' }\n      })\n    }\n    renderVmWithOptions({\n      render: h => h(Test, {\n        domProps: { innerHTML: 'b', value: 'c' }\n      })\n    }, res => {\n      expect(res).toContain(\n        '<div data-server-rendered=\"true\" value=\"c\">b</div>'\n      )\n      done()\n    })\n  })\n\n  it('v-show directive render', done => {\n    renderVmWithOptions({\n      template: '<div v-show=\"false\"><span>inner</span></div>'\n    }, res => {\n      expect(res).toContain(\n        '<div data-server-rendered=\"true\" style=\"display:none;\"><span>inner</span></div>'\n      )\n      done()\n    })\n  })\n\n  it('v-show directive not passed to child', done => {\n    renderVmWithOptions({\n      template: '<foo v-show=\"false\"></foo>',\n      components: {\n        foo: {\n          template: '<div><span>inner</span></div>'\n        }\n      }\n    }, res => {\n      expect(res).toContain(\n        '<div data-server-rendered=\"true\" style=\"display:none;\"><span>inner</span></div>'\n      )\n      done()\n    })\n  })\n\n  it('v-show directive not passed to slot', done => {\n    renderVmWithOptions({\n      template: '<foo v-show=\"false\"><span>inner</span></foo>',\n      components: {\n        foo: {\n          template: '<div><slot></slot></div>'\n        }\n      }\n    }, res => {\n      expect(res).toContain(\n        '<div data-server-rendered=\"true\" style=\"display:none;\"><span>inner</span></div>'\n      )\n      done()\n    })\n  })\n\n  it('v-show directive merging on components', done => {\n    renderVmWithOptions({\n      template: '<foo v-show=\"false\"></foo>',\n      components: {\n        foo: {\n          render: h => h('bar', {\n            directives: [{\n              name: 'show',\n              value: true\n            }]\n          }),\n          components: {\n            bar: {\n              render: h => h('div', 'inner')\n            }\n          }\n        }\n      }\n    }, res => {\n      expect(res).toContain(\n        '<div data-server-rendered=\"true\" style=\"display:none;\">inner</div>'\n      )\n      done()\n    })\n  })\n\n  it('text interpolation', done => {\n    renderVmWithOptions({\n      template: '<div>{{ foo }} side {{ bar }}</div>',\n      data: {\n        foo: 'server',\n        bar: '<span>rendering</span>'\n      }\n    }, result => {\n      expect(result).toContain('<div data-server-rendered=\"true\">server side &lt;span&gt;rendering&lt;/span&gt;</div>')\n      done()\n    })\n  })\n\n  it('v-html on root', done => {\n    renderVmWithOptions({\n      template: '<div v-html=\"text\"></div>',\n      data: {\n        text: '<span>foo</span>'\n      }\n    }, result => {\n      expect(result).toContain('<div data-server-rendered=\"true\"><span>foo</span></div>')\n      done()\n    })\n  })\n\n  it('v-text on root', done => {\n    renderVmWithOptions({\n      template: '<div v-text=\"text\"></div>',\n      data: {\n        text: '<span>foo</span>'\n      }\n    }, result => {\n      expect(result).toContain('<div data-server-rendered=\"true\">&lt;span&gt;foo&lt;/span&gt;</div>')\n      done()\n    })\n  })\n\n  it('v-html', done => {\n    renderVmWithOptions({\n      template: '<div><div v-html=\"text\"></div></div>',\n      data: {\n        text: '<span>foo</span>'\n      }\n    }, result => {\n      expect(result).toContain('<div data-server-rendered=\"true\"><div><span>foo</span></div></div>')\n      done()\n    })\n  })\n\n  it('v-text', done => {\n    renderVmWithOptions({\n      template: '<div><div v-text=\"text\"></div></div>',\n      data: {\n        text: '<span>foo</span>'\n      }\n    }, result => {\n      expect(result).toContain('<div data-server-rendered=\"true\"><div>&lt;span&gt;foo&lt;/span&gt;</div></div>')\n      done()\n    })\n  })\n\n  it('child component (hoc)', done => {\n    renderVmWithOptions({\n      template: '<child class=\"foo\" :msg=\"msg\"></child>',\n      data: {\n        msg: 'hello'\n      },\n      components: {\n        child: {\n          props: ['msg'],\n          data () {\n            return { name: 'bar' }\n          },\n          render () {\n            const h = this.$createElement\n            return h('div', { class: ['bar'] }, [`${this.msg} ${this.name}`])\n          }\n        }\n      }\n    }, result => {\n      expect(result).toContain('<div data-server-rendered=\"true\" class=\"foo bar\">hello bar</div>')\n      done()\n    })\n  })\n\n  it('has correct lifecycle during render', done => {\n    let lifecycleCount = 1\n    renderVmWithOptions({\n      template: '<div><span>{{ val }}</span><test></test></div>',\n      data: {\n        val: 'hi'\n      },\n      beforeCreate () {\n        expect(lifecycleCount++).toBe(1)\n      },\n      created () {\n        this.val = 'hello'\n        expect(this.val).toBe('hello')\n        expect(lifecycleCount++).toBe(2)\n      },\n      components: {\n        test: {\n          beforeCreate () {\n            expect(lifecycleCount++).toBe(3)\n          },\n          created () {\n            expect(lifecycleCount++).toBe(4)\n          },\n          render () {\n            expect(lifecycleCount++).toBeGreaterThan(4)\n            return this.$createElement('span', { class: ['b'] }, 'testAsync')\n          }\n        }\n      }\n    }, result => {\n      expect(result).toContain(\n        '<div data-server-rendered=\"true\">' +\n          '<span>hello</span>' +\n          '<span class=\"b\">testAsync</span>' +\n        '</div>'\n      )\n      done()\n    })\n  })\n\n  it('computed properties', done => {\n    renderVmWithOptions({\n      template: '<div>{{ b }}</div>',\n      data: {\n        a: {\n          b: 1\n        }\n      },\n      computed: {\n        b () {\n          return this.a.b + 1\n        }\n      },\n      created () {\n        this.a.b = 2\n        expect(this.b).toBe(3)\n      }\n    }, result => {\n      expect(result).toContain('<div data-server-rendered=\"true\">3</div>')\n      done()\n    })\n  })\n\n  it('renders async component', done => {\n    renderVmWithOptions({\n      template: `\n        <div>\n          <test-async></test-async>\n        </div>\n      `,\n      components: {\n        testAsync (resolve) {\n          setTimeout(() => resolve({\n            render () {\n              return this.$createElement('span', { class: ['b'] }, 'testAsync')\n            }\n          }), 1)\n        }\n      }\n    }, result => {\n      expect(result).toContain('<div data-server-rendered=\"true\"><span class=\"b\">testAsync</span></div>')\n      done()\n    })\n  })\n\n  it('renders async component (Promise, nested)', done => {\n    const Foo = () => Promise.resolve({\n      render: h => h('div', [h('span', 'foo'), h(Bar)])\n    })\n    const Bar = () => ({\n      component: Promise.resolve({\n        render: h => h('span', 'bar')\n      })\n    })\n    renderVmWithOptions({\n      render: h => h(Foo)\n    }, res => {\n      expect(res).toContain(`<div data-server-rendered=\"true\"><span>foo</span><span>bar</span></div>`)\n      done()\n    })\n  })\n\n  it('renders async component (ES module)', done => {\n    const Foo = () => Promise.resolve({\n      __esModule: true,\n      default: {\n        render: h => h('div', [h('span', 'foo'), h(Bar)])\n      }\n    })\n    const Bar = () => ({\n      component: Promise.resolve({\n        __esModule: true,\n        default: {\n          render: h => h('span', 'bar')\n        }\n      })\n    })\n    renderVmWithOptions({\n      render: h => h(Foo)\n    }, res => {\n      expect(res).toContain(`<div data-server-rendered=\"true\"><span>foo</span><span>bar</span></div>`)\n      done()\n    })\n  })\n\n  it('renders async component (hoc)', done => {\n    renderVmWithOptions({\n      template: '<test-async></test-async>',\n      components: {\n        testAsync: () => Promise.resolve({\n          render () {\n            return this.$createElement('span', { class: ['b'] }, 'testAsync')\n          }\n        })\n      }\n    }, result => {\n      expect(result).toContain('<span data-server-rendered=\"true\" class=\"b\">testAsync</span>')\n      done()\n    })\n  })\n\n  it('everything together', done => {\n    renderVmWithOptions({\n      template: `\n        <div>\n          <p class=\"hi\">yoyo</p>\n          <div id=\"ho\" :class=\"{ red: isRed }\"></div>\n          <span>{{ test }}</span>\n          <input :value=\"test\">\n          <img :src=\"imageUrl\">\n          <test></test>\n          <test-async></test-async>\n        </div>\n      `,\n      data: {\n        test: 'hi',\n        isRed: true,\n        imageUrl: 'https://vuejs.org/images/logo.png'\n      },\n      components: {\n        test: {\n          render () {\n            return this.$createElement('div', { class: ['a'] }, 'test')\n          }\n        },\n        testAsync (resolve) {\n          resolve({\n            render () {\n              return this.$createElement('span', { class: ['b'] }, 'testAsync')\n            }\n          })\n        }\n      }\n    }, result => {\n      expect(result).toContain(\n        '<div data-server-rendered=\"true\">' +\n          '<p class=\"hi\">yoyo</p> ' +\n          '<div id=\"ho\" class=\"red\"></div> ' +\n          '<span>hi</span> ' +\n          '<input value=\"hi\"> ' +\n          '<img src=\"https://vuejs.org/images/logo.png\"> ' +\n          '<div class=\"a\">test</div> ' +\n          '<span class=\"b\">testAsync</span>' +\n        '</div>'\n      )\n      done()\n    })\n  })\n\n  it('normal attr', done => {\n    renderVmWithOptions({\n      template: `\n        <div>\n          <span :test=\"'ok'\">hello</span>\n          <span :test=\"null\">hello</span>\n          <span :test=\"false\">hello</span>\n          <span :test=\"true\">hello</span>\n          <span :test=\"0\">hello</span>\n        </div>\n      `\n    }, result => {\n      expect(result).toContain(\n        '<div data-server-rendered=\"true\">' +\n          '<span test=\"ok\">hello</span> ' +\n          '<span>hello</span> ' +\n          '<span>hello</span> ' +\n          '<span test=\"true\">hello</span> ' +\n          '<span test=\"0\">hello</span>' +\n        '</div>'\n      )\n      done()\n    })\n  })\n\n  it('enumerated attr', done => {\n    renderVmWithOptions({\n      template: `\n        <div>\n          <span :draggable=\"true\">hello</span>\n          <span :draggable=\"'ok'\">hello</span>\n          <span :draggable=\"null\">hello</span>\n          <span :draggable=\"false\">hello</span>\n          <span :draggable=\"''\">hello</span>\n          <span :draggable=\"'false'\">hello</span>\n        </div>\n      `\n    }, result => {\n      expect(result).toContain(\n        '<div data-server-rendered=\"true\">' +\n          '<span draggable=\"true\">hello</span> ' +\n          '<span draggable=\"true\">hello</span> ' +\n          '<span draggable=\"false\">hello</span> ' +\n          '<span draggable=\"false\">hello</span> ' +\n          '<span draggable=\"true\">hello</span> ' +\n          '<span draggable=\"false\">hello</span>' +\n        '</div>'\n      )\n      done()\n    })\n  })\n\n  it('boolean attr', done => {\n    renderVmWithOptions({\n      template: `\n        <div>\n          <span :disabled=\"true\">hello</span>\n          <span :disabled=\"'ok'\">hello</span>\n          <span :disabled=\"null\">hello</span>\n          <span :disabled=\"''\">hello</span>\n        </div>\n      `\n    }, result => {\n      expect(result).toContain(\n        '<div data-server-rendered=\"true\">' +\n          '<span disabled=\"disabled\">hello</span> ' +\n          '<span disabled=\"disabled\">hello</span> ' +\n          '<span>hello</span> ' +\n          '<span disabled=\"disabled\">hello</span>' +\n        '</div>'\n      )\n      done()\n    })\n  })\n\n  it('v-bind object', done => {\n    renderVmWithOptions({\n      data: {\n        test: { id: 'a', class: ['a', 'b'], value: 'c' }\n      },\n      template: '<input v-bind=\"test\">'\n    }, result => {\n      expect(result).toContain('<input id=\"a\" data-server-rendered=\"true\" value=\"c\" class=\"a b\">')\n      done()\n    })\n  })\n\n  it('custom directives', done => {\n    const renderer = createRenderer({\n      directives: {\n        'class-prefixer': (node, dir) => {\n          if (node.data.class) {\n            node.data.class = `${dir.value}-${node.data.class}`\n          }\n          if (node.data.staticClass) {\n            node.data.staticClass = `${dir.value}-${node.data.staticClass}`\n          }\n        }\n      }\n    })\n    renderer.renderToString(new Vue({\n      render () {\n        const h = this.$createElement\n        return h('p', {\n          class: 'class1',\n          staticClass: 'class2',\n          directives: [{\n            name: 'class-prefixer',\n            value: 'my'\n          }]\n        }, ['hello world'])\n      }\n    }), (err, result) => {\n      expect(err).toBeNull()\n      expect(result).toContain('<p data-server-rendered=\"true\" class=\"my-class2 my-class1\">hello world</p>')\n      done()\n    })\n  })\n\n  it('_scopeId', done => {\n    renderVmWithOptions({\n      _scopeId: '_v-parent',\n      template: '<div id=\"foo\"><p><child></child></p></div>',\n      components: {\n        child: {\n          _scopeId: '_v-child',\n          render () {\n            const h = this.$createElement\n            return h('div', null, [h('span', null, ['foo'])])\n          }\n        }\n      }\n    }, result => {\n      expect(result).toContain(\n        '<div id=\"foo\" data-server-rendered=\"true\" _v-parent>' +\n          '<p _v-parent>' +\n            '<div _v-child _v-parent><span _v-child>foo</span></div>' +\n          '</p>' +\n        '</div>'\n      )\n      done()\n    })\n  })\n\n  it('_scopeId on slot content', done => {\n    renderVmWithOptions({\n      _scopeId: '_v-parent',\n      template: '<div><child><p>foo</p></child></div>',\n      components: {\n        child: {\n          _scopeId: '_v-child',\n          render () {\n            const h = this.$createElement\n            return h('div', null, this.$slots.default)\n          }\n        }\n      }\n    }, result => {\n      expect(result).toContain(\n        '<div data-server-rendered=\"true\" _v-parent>' +\n          '<div _v-child _v-parent><p _v-child _v-parent>foo</p></div>' +\n        '</div>'\n      )\n      done()\n    })\n  })\n\n  it('comment nodes', done => {\n    renderVmWithOptions({\n      template: '<div><transition><div v-if=\"false\"></div></transition></div>'\n    }, result => {\n      expect(result).toContain(`<div data-server-rendered=\"true\"><!----></div>`)\n      done()\n    })\n  })\n\n  it('should catch error', done => {\n    Vue.config.silent = true\n    renderToString(new Vue({\n      render () {\n        throw new Error('oops')\n      }\n    }), err => {\n      expect(err instanceof Error).toBe(true)\n      Vue.config.silent = false\n      done()\n    })\n  })\n\n  it('default value Foreign Function', () => {\n    const FunctionConstructor = VM.runInNewContext('Function')\n    const func = () => 123\n    const vm = new Vue({\n      props: {\n        a: {\n          type: FunctionConstructor,\n          default: func\n        }\n      },\n      propsData: {\n        a: undefined\n      }\n    })\n    expect(vm.a).toBe(func)\n  })\n\n  it('should prevent xss in attribtues', done => {\n    renderVmWithOptions({\n      data: {\n        xss: '\"><script>alert(1)</script>'\n      },\n      template: `\n        <div>\n          <a :title=\"xss\" :style=\"{ color: xss }\" :class=\"[xss]\">foo</a>\n        </div>\n      `\n    }, res => {\n      expect(res).not.toContain(`<script>alert(1)</script>`)\n      done()\n    })\n  })\n\n  it('v-if', done => {\n    renderVmWithOptions({\n      template: `\n        <div>\n          <span v-if=\"true\">foo</span>\n          <span v-if=\"false\">bar</span>\n        </div>\n      `\n    }, res => {\n      expect(res).toContain(`<div data-server-rendered=\"true\"><span>foo</span> <!----></div>`)\n      done()\n    })\n  })\n\n  it('v-for', done => {\n    renderVmWithOptions({\n      template: `\n        <div>\n          <span>foo</span>\n          <span v-for=\"i in 2\">{{ i }}</span>\n        </div>\n      `\n    }, res => {\n      expect(res).toContain(`<div data-server-rendered=\"true\"><span>foo</span> <span>1</span><span>2</span></div>`)\n      done()\n    })\n  })\n\n  it('template v-if', done => {\n    renderVmWithOptions({\n      template: `\n        <div>\n          <span>foo</span>\n          <template v-if=\"true\">\n            <span>foo</span> bar <span>baz</span>\n          </template>\n        </div>\n      `\n    }, res => {\n      expect(res).toContain(`<div data-server-rendered=\"true\"><span>foo</span> <span>foo</span> bar <span>baz</span></div>`)\n      done()\n    })\n  })\n\n  it('template v-for', done => {\n    renderVmWithOptions({\n      template: `\n        <div>\n          <span>foo</span>\n          <template v-for=\"i in 2\">\n            <span>{{ i }}</span><span>bar</span>\n          </template>\n        </div>\n      `\n    }, res => {\n      expect(res).toContain(`<div data-server-rendered=\"true\"><span>foo</span> <span>1</span><span>bar</span><span>2</span><span>bar</span></div>`)\n      done()\n    })\n  })\n\n  it('with inheritAttrs: false + $attrs', done => {\n    renderVmWithOptions({\n      template: `<foo id=\"a\"/>`,\n      components: {\n        foo: {\n          inheritAttrs: false,\n          template: `<div><div v-bind=\"$attrs\"></div></div>`\n        }\n      }\n    }, res => {\n      expect(res).toBe(`<div data-server-rendered=\"true\"><div id=\"a\"></div></div>`)\n      done()\n    })\n  })\n})\n\nfunction renderVmWithOptions (options, cb) {\n  renderToString(new Vue(options), (err, res) => {\n    expect(err).toBeNull()\n    cb(res)\n  })\n}\n"
  },
  {
    "path": "test/ssr/ssr-template.spec.js",
    "content": "import webpack from 'webpack'\nimport Vue from '../../dist/vue.runtime.common.js'\nimport { compileWithWebpack } from './compile-with-webpack'\nimport { createRenderer } from '../../packages/vue-server-renderer'\nimport VueSSRClientPlugin from '../../packages/vue-server-renderer/client-plugin'\nimport { createRenderer as createBundleRenderer } from './ssr-bundle-render.spec.js'\n\nconst defaultTemplate = `<html><head></head><body><!--vue-ssr-outlet--></body></html>`\nconst interpolateTemplate = `<html><head><title>{{ title }}</title></head><body><!--vue-ssr-outlet-->{{{ snippet }}}</body></html>`\n\nfunction generateClientManifest (file, cb) {\n  compileWithWebpack(file, {\n    output: {\n      path: '/',\n      filename: '[name].js'\n    },\n    plugins: [\n      new webpack.optimize.CommonsChunkPlugin({\n        name: 'manifest',\n        minChunks: Infinity\n      }),\n      new VueSSRClientPlugin()\n    ]\n  }, fs => {\n    cb(JSON.parse(fs.readFileSync('/vue-ssr-client-manifest.json', 'utf-8')))\n  })\n}\n\nfunction createRendererWithManifest (file, options, cb) {\n  if (typeof options === 'function') {\n    cb = options\n    options = null\n  }\n  generateClientManifest(file, clientManifest => {\n    createBundleRenderer(file, Object.assign({\n      asBundle: true,\n      template: defaultTemplate,\n      clientManifest\n    }, options), cb)\n  })\n}\n\ndescribe('SSR: template option', () => {\n  it('renderToString', done => {\n    const renderer = createRenderer({\n      template: defaultTemplate\n    })\n\n    const context = {\n      head: '<meta name=\"viewport\" content=\"width=device-width\">',\n      styles: '<style>h1 { color: red }</style>',\n      state: { a: 1 }\n    }\n\n    renderer.renderToString(new Vue({\n      template: '<div>hi</div>'\n    }), context, (err, res) => {\n      expect(err).toBeNull()\n      expect(res).toContain(\n        `<html><head>${context.head}${context.styles}</head><body>` +\n        `<div data-server-rendered=\"true\">hi</div>` +\n        `<script>window.__INITIAL_STATE__={\"a\":1}</script>` +\n        `</body></html>`\n      )\n      done()\n    })\n  })\n\n  it('renderToString with interpolation', done => {\n    const renderer = createRenderer({\n      template: interpolateTemplate\n    })\n\n    const context = {\n      title: '<script>hacks</script>',\n      snippet: '<div>foo</div>',\n      head: '<meta name=\"viewport\" content=\"width=device-width\">',\n      styles: '<style>h1 { color: red }</style>',\n      state: { a: 1 }\n    }\n\n    renderer.renderToString(new Vue({\n      template: '<div>hi</div>'\n    }), context, (err, res) => {\n      expect(err).toBeNull()\n      expect(res).toContain(\n        `<html><head>` +\n        // double mustache should be escaped\n        `<title>&lt;script&gt;hacks&lt;/script&gt;</title>` +\n        `${context.head}${context.styles}</head><body>` +\n        `<div data-server-rendered=\"true\">hi</div>` +\n        `<script>window.__INITIAL_STATE__={\"a\":1}</script>` +\n        // triple should be raw\n        `<div>foo</div>` +\n        `</body></html>`\n      )\n      done()\n    })\n  })\n\n  it('renderToStream', done => {\n    const renderer = createRenderer({\n      template: defaultTemplate\n    })\n\n    const context = {\n      head: '<meta name=\"viewport\" content=\"width=device-width\">',\n      styles: '<style>h1 { color: red }</style>',\n      state: { a: 1 }\n    }\n\n    const stream = renderer.renderToStream(new Vue({\n      template: '<div>hi</div>'\n    }), context)\n\n    let res = ''\n    stream.on('data', chunk => {\n      res += chunk\n    })\n    stream.on('end', () => {\n      expect(res).toContain(\n        `<html><head>${context.head}${context.styles}</head><body>` +\n        `<div data-server-rendered=\"true\">hi</div>` +\n        `<script>window.__INITIAL_STATE__={\"a\":1}</script>` +\n        `</body></html>`\n      )\n      done()\n    })\n  })\n\n  it('renderToStream with interpolation', done => {\n    const renderer = createRenderer({\n      template: interpolateTemplate\n    })\n\n    const context = {\n      title: '<script>hacks</script>',\n      snippet: '<div>foo</div>',\n      head: '<meta name=\"viewport\" content=\"width=device-width\">',\n      styles: '<style>h1 { color: red }</style>',\n      state: { a: 1 }\n    }\n\n    const stream = renderer.renderToStream(new Vue({\n      template: '<div>hi</div>'\n    }), context)\n\n    let res = ''\n    stream.on('data', chunk => {\n      res += chunk\n    })\n    stream.on('end', () => {\n      expect(res).toContain(\n        `<html><head>` +\n        // double mustache should be escaped\n        `<title>&lt;script&gt;hacks&lt;/script&gt;</title>` +\n        `${context.head}${context.styles}</head><body>` +\n        `<div data-server-rendered=\"true\">hi</div>` +\n        `<script>window.__INITIAL_STATE__={\"a\":1}</script>` +\n        // triple should be raw\n        `<div>foo</div>` +\n        `</body></html>`\n      )\n      done()\n    })\n  })\n\n  it('bundleRenderer + renderToString', done => {\n    createBundleRenderer('app.js', {\n      asBundle: true,\n      template: defaultTemplate\n    }, renderer => {\n      const context = {\n        head: '<meta name=\"viewport\" content=\"width=device-width\">',\n        styles: '<style>h1 { color: red }</style>',\n        state: { a: 1 },\n        url: '/test'\n      }\n      renderer.renderToString(context, (err, res) => {\n        expect(err).toBeNull()\n        expect(res).toContain(\n          `<html><head>${context.head}${context.styles}</head><body>` +\n          `<div data-server-rendered=\"true\">/test</div>` +\n          `<script>window.__INITIAL_STATE__={\"a\":1}</script>` +\n          `</body></html>`\n        )\n        expect(context.msg).toBe('hello')\n        done()\n      })\n    })\n  })\n\n  it('bundleRenderer + renderToStream', done => {\n    createBundleRenderer('app.js', {\n      asBundle: true,\n      template: defaultTemplate\n    }, renderer => {\n      const context = {\n        head: '<meta name=\"viewport\" content=\"width=device-width\">',\n        styles: '<style>h1 { color: red }</style>',\n        state: { a: 1 },\n        url: '/test'\n      }\n      const stream = renderer.renderToStream(context)\n      let res = ''\n      stream.on('data', chunk => {\n        res += chunk.toString()\n      })\n      stream.on('end', () => {\n        expect(res).toContain(\n          `<html><head>${context.head}${context.styles}</head><body>` +\n          `<div data-server-rendered=\"true\">/test</div>` +\n          `<script>window.__INITIAL_STATE__={\"a\":1}</script>` +\n          `</body></html>`\n        )\n        expect(context.msg).toBe('hello')\n        done()\n      })\n    })\n  })\n\n  const expectedHTMLWithManifest = (options = {}) =>\n    `<html><head>` +\n      // used chunks should have preload\n      `<link rel=\"preload\" href=\"/manifest.js\" as=\"script\">` +\n      `<link rel=\"preload\" href=\"/main.js\" as=\"script\">` +\n      `<link rel=\"preload\" href=\"/0.js\" as=\"script\">` +\n      `<link rel=\"preload\" href=\"/test.css\" as=\"style\">` +\n      // images and fonts are only preloaded when explicitly asked for\n      (options.preloadOtherAssets ? `<link rel=\"preload\" href=\"/test.png\" as=\"image\">` : ``) +\n      (options.preloadOtherAssets ? `<link rel=\"preload\" href=\"/test.woff2\" as=\"font\" type=\"font/woff2\" crossorigin>` : ``) +\n      // unused chunks should have prefetch\n      `<link rel=\"prefetch\" href=\"/1.js\">` +\n      // css assets should be loaded\n      `<link rel=\"stylesheet\" href=\"/test.css\">` +\n    `</head><body>` +\n      `<div data-server-rendered=\"true\"><div>async test.woff2 test.png</div></div>` +\n      // state should be inlined before scripts\n      `<script>window.${options.stateKey || '__INITIAL_STATE__'}={\"a\":1}</script>` +\n      // manifest chunk should be first\n      `<script src=\"/manifest.js\" defer></script>` +\n      // async chunks should be before main chunk\n      `<script src=\"/0.js\" defer></script>` +\n      `<script src=\"/main.js\" defer></script>` +\n    `</body></html>`\n\n  createClientManifestAssertions(true)\n  createClientManifestAssertions(false)\n\n  function createClientManifestAssertions (runInNewContext) {\n    it('bundleRenderer + renderToString + clientManifest ()', done => {\n      createRendererWithManifest('split.js', { runInNewContext }, renderer => {\n        renderer.renderToString({ state: { a: 1 }}, (err, res) => {\n          expect(err).toBeNull()\n          expect(res).toContain(expectedHTMLWithManifest())\n          done()\n        })\n      })\n    })\n\n    it('bundleRenderer + renderToStream + clientManifest + shouldPreload', done => {\n      createRendererWithManifest('split.js', {\n        runInNewContext,\n        shouldPreload: (file, type) => {\n          if (type === 'image' || type === 'script' || type === 'font' || type === 'style') {\n            return true\n          }\n        }\n      }, renderer => {\n        const stream = renderer.renderToStream({ state: { a: 1 }})\n        let res = ''\n        stream.on('data', chunk => {\n          res += chunk.toString()\n        })\n        stream.on('end', () => {\n          expect(res).toContain(expectedHTMLWithManifest({\n            preloadOtherAssets: true\n          }))\n          done()\n        })\n      })\n    })\n\n    it('bundleRenderer + renderToString + clientManifest + inject: false', done => {\n      createRendererWithManifest('split.js', {\n        runInNewContext,\n        template: `<html>` +\n          `<head>{{{ renderResourceHints() }}}{{{ renderStyles() }}}</head>` +\n          `<body><!--vue-ssr-outlet-->{{{ renderState({ windowKey: '__FOO__', contextKey: 'foo' }) }}}{{{ renderScripts() }}}</body>` +\n        `</html>`,\n        inject: false\n      }, renderer => {\n        const context = { foo: { a: 1 }}\n        renderer.renderToString(context, (err, res) => {\n          expect(err).toBeNull()\n          expect(res).toContain(expectedHTMLWithManifest({\n            stateKey: '__FOO__'\n          }))\n          done()\n        })\n      })\n    })\n\n    it('bundleRenderer + renderToString + clientManifest + no template', done => {\n      createRendererWithManifest('split.js', {\n        runInNewContext,\n        template: null\n      }, renderer => {\n        const context = { foo: { a: 1 }}\n        renderer.renderToString(context, (err, res) => {\n          expect(err).toBeNull()\n\n          const customOutput =\n            `<html><head>${\n              context.renderResourceHints() +\n              context.renderStyles()\n            }</head><body>${\n              res +\n              context.renderState({\n                windowKey: '__FOO__',\n                contextKey: 'foo'\n              }) +\n              context.renderScripts()\n            }</body></html>`\n\n          expect(customOutput).toContain(expectedHTMLWithManifest({\n            stateKey: '__FOO__'\n          }))\n          done()\n        })\n      })\n    })\n\n    it('whitespace insensitive interpolation', done => {\n      const interpolateTemplate = `<html><head><title>{{title}}</title></head><body><!--vue-ssr-outlet-->{{{snippet}}}</body></html>`\n      const renderer = createRenderer({\n        template: interpolateTemplate\n      })\n\n      const context = {\n        title: '<script>hacks</script>',\n        snippet: '<div>foo</div>',\n        head: '<meta name=\"viewport\" content=\"width=device-width\">',\n        styles: '<style>h1 { color: red }</style>',\n        state: { a: 1 }\n      }\n\n      renderer.renderToString(new Vue({\n        template: '<div>hi</div>'\n      }), context, (err, res) => {\n        expect(err).toBeNull()\n        expect(res).toContain(\n          `<html><head>` +\n          // double mustache should be escaped\n          `<title>&lt;script&gt;hacks&lt;/script&gt;</title>` +\n          `${context.head}${context.styles}</head><body>` +\n          `<div data-server-rendered=\"true\">hi</div>` +\n          `<script>window.__INITIAL_STATE__={\"a\":1}</script>` +\n          // triple should be raw\n          `<div>foo</div>` +\n          `</body></html>`\n        )\n        done()\n      })\n    })\n  }\n})\n"
  },
  {
    "path": "test/unit/.eslintrc",
    "content": "{\n  \"env\": {\n    \"jasmine\": true\n  },\n  \"globals\": {\n    \"waitForUpdate\": true,\n    \"triggerEvent\": true,\n    \"createTextVNode\": true\n  },\n  \"plugins\": [\"jasmine\"],\n  \"rules\": {\n    \"jasmine/no-focused-tests\": 2\n  }\n}\n"
  },
  {
    "path": "test/unit/features/component/component-async.spec.js",
    "content": "import Vue from 'vue'\nimport { Promise } from 'es6-promise'\n\ndescribe('Component async', () => {\n  it('normal', done => {\n    const vm = new Vue({\n      template: '<div><test></test></div>',\n      components: {\n        test: (resolve) => {\n          setTimeout(() => {\n            resolve({\n              template: '<div>hi</div>'\n            })\n            // wait for parent update\n            Vue.nextTick(next)\n          }, 0)\n        }\n      }\n    }).$mount()\n    expect(vm.$el.innerHTML).toBe('<!---->')\n    expect(vm.$children.length).toBe(0)\n    function next () {\n      expect(vm.$el.innerHTML).toBe('<div>hi</div>')\n      expect(vm.$children.length).toBe(1)\n      done()\n    }\n  })\n\n  it('resolve ES module default', done => {\n    const vm = new Vue({\n      template: '<div><test></test></div>',\n      components: {\n        test: (resolve) => {\n          setTimeout(() => {\n            resolve({\n              __esModule: true,\n              default: {\n                template: '<div>hi</div>'\n              }\n            })\n            // wait for parent update\n            Vue.nextTick(next)\n          }, 0)\n        }\n      }\n    }).$mount()\n    expect(vm.$el.innerHTML).toBe('<!---->')\n    expect(vm.$children.length).toBe(0)\n    function next () {\n      expect(vm.$el.innerHTML).toBe('<div>hi</div>')\n      expect(vm.$children.length).toBe(1)\n      done()\n    }\n  })\n\n  it('as root', done => {\n    const vm = new Vue({\n      template: '<test></test>',\n      components: {\n        test: resolve => {\n          setTimeout(() => {\n            resolve({\n              template: '<div>hi</div>'\n            })\n            // wait for parent update\n            Vue.nextTick(next)\n          }, 0)\n        }\n      }\n    }).$mount()\n    expect(vm.$el.nodeType).toBe(8)\n    expect(vm.$children.length).toBe(0)\n    function next () {\n      expect(vm.$el.nodeType).toBe(1)\n      expect(vm.$el.outerHTML).toBe('<div>hi</div>')\n      expect(vm.$children.length).toBe(1)\n      done()\n    }\n  })\n\n  it('dynamic', done => {\n    var vm = new Vue({\n      template: '<component :is=\"view\"></component>',\n      data: {\n        view: 'view-a'\n      },\n      components: {\n        'view-a': resolve => {\n          setTimeout(() => {\n            resolve({\n              template: '<div>A</div>'\n            })\n            Vue.nextTick(step1)\n          }, 0)\n        },\n        'view-b': resolve => {\n          setTimeout(() => {\n            resolve({\n              template: '<p>B</p>'\n            })\n            Vue.nextTick(step2)\n          }, 0)\n        }\n      }\n    }).$mount()\n    var aCalled = false\n    function step1 () {\n      // ensure A is resolved only once\n      expect(aCalled).toBe(false)\n      aCalled = true\n      expect(vm.$el.tagName).toBe('DIV')\n      expect(vm.$el.textContent).toBe('A')\n      vm.view = 'view-b'\n    }\n    function step2 () {\n      expect(vm.$el.tagName).toBe('P')\n      expect(vm.$el.textContent).toBe('B')\n      vm.view = 'view-a'\n      waitForUpdate(function () {\n        expect(vm.$el.tagName).toBe('DIV')\n        expect(vm.$el.textContent).toBe('A')\n      }).then(done)\n    }\n  })\n\n  it('warn reject', () => {\n    new Vue({\n      template: '<test></test>',\n      components: {\n        test: (resolve, reject) => {\n          reject('nooooo')\n        }\n      }\n    }).$mount()\n    expect('Reason: nooooo').toHaveBeenWarned()\n  })\n\n  it('with v-for', done => {\n    const vm = new Vue({\n      template: '<div><test v-for=\"n in list\" :key=\"n\" :n=\"n\"></test></div>',\n      data: {\n        list: [1, 2, 3]\n      },\n      components: {\n        test: resolve => {\n          setTimeout(() => {\n            resolve({\n              props: ['n'],\n              template: '<div>{{n}}</div>'\n            })\n            Vue.nextTick(next)\n          }, 0)\n        }\n      }\n    }).$mount()\n    function next () {\n      expect(vm.$el.innerHTML).toBe('<div>1</div><div>2</div><div>3</div>')\n      done()\n    }\n  })\n\n  it('returning Promise', done => {\n    const vm = new Vue({\n      template: '<div><test></test></div>',\n      components: {\n        test: () => {\n          return new Promise(resolve => {\n            setTimeout(() => {\n              resolve({\n                template: '<div>hi</div>'\n              })\n              // wait for promise resolve and then parent update\n              Promise.resolve().then(() => {\n                Vue.nextTick(next)\n              })\n            }, 0)\n          })\n        }\n      }\n    }).$mount()\n    expect(vm.$el.innerHTML).toBe('<!---->')\n    expect(vm.$children.length).toBe(0)\n    function next () {\n      expect(vm.$el.innerHTML).toBe('<div>hi</div>')\n      expect(vm.$children.length).toBe(1)\n      done()\n    }\n  })\n\n  describe('loading/error/timeout', () => {\n    it('with loading component', done => {\n      const vm = new Vue({\n        template: `<div><test/></div>`,\n        components: {\n          test: () => ({\n            component: new Promise(resolve => {\n              setTimeout(() => {\n                resolve({ template: '<div>hi</div>' })\n                // wait for promise resolve and then parent update\n                Promise.resolve().then(() => {\n                  Vue.nextTick(next)\n                })\n              }, 50)\n            }),\n            loading: { template: `<div>loading</div>` },\n            delay: 1\n          })\n        }\n      }).$mount()\n\n      expect(vm.$el.innerHTML).toBe('<!---->')\n\n      let loadingAsserted = false\n      setTimeout(() => {\n        Vue.nextTick(() => {\n          loadingAsserted = true\n          expect(vm.$el.textContent).toBe('loading')\n        })\n      }, 1)\n\n      function next () {\n        expect(loadingAsserted).toBe(true)\n        expect(vm.$el.textContent).toBe('hi')\n        done()\n      }\n    })\n\n    it('with loading component (0 delay)', done => {\n      const vm = new Vue({\n        template: `<div><test/></div>`,\n        components: {\n          test: () => ({\n            component: new Promise(resolve => {\n              setTimeout(() => {\n                resolve({ template: '<div>hi</div>' })\n                // wait for promise resolve and then parent update\n                Promise.resolve().then(() => {\n                  Vue.nextTick(next)\n                })\n              }, 50)\n            }),\n            loading: { template: `<div>loading</div>` },\n            delay: 0\n          })\n        }\n      }).$mount()\n\n      expect(vm.$el.textContent).toBe('loading')\n\n      function next () {\n        expect(vm.$el.textContent).toBe('hi')\n        done()\n      }\n    })\n\n    it('with error component', done => {\n      const vm = new Vue({\n        template: `<div><test/></div>`,\n        components: {\n          test: () => ({\n            component: new Promise((resolve, reject) => {\n              setTimeout(() => {\n                reject()\n                // wait for promise resolve and then parent update\n                Promise.resolve().then(() => {\n                  Vue.nextTick(next)\n                })\n              }, 50)\n            }),\n            loading: { template: `<div>loading</div>` },\n            error: { template: `<div>error</div>` },\n            delay: 0\n          })\n        }\n      }).$mount()\n\n      expect(vm.$el.textContent).toBe('loading')\n\n      function next () {\n        expect(`Failed to resolve async component`).toHaveBeenWarned()\n        expect(vm.$el.textContent).toBe('error')\n        done()\n      }\n    })\n\n    it('with error component + timeout', done => {\n      const vm = new Vue({\n        template: `<div><test/></div>`,\n        components: {\n          test: () => ({\n            component: new Promise((resolve, reject) => {\n              setTimeout(() => {\n                resolve({ template: '<div>hi</div>' })\n                // wait for promise resolve and then parent update\n                Promise.resolve().then(() => {\n                  Vue.nextTick(next)\n                })\n              }, 50)\n            }),\n            loading: { template: `<div>loading</div>` },\n            error: { template: `<div>error</div>` },\n            delay: 0,\n            timeout: 1\n          })\n        }\n      }).$mount()\n\n      expect(vm.$el.textContent).toBe('loading')\n\n      setTimeout(() => {\n        Vue.nextTick(() => {\n          expect(`Failed to resolve async component`).toHaveBeenWarned()\n          expect(vm.$el.textContent).toBe('error')\n        })\n      }, 1)\n\n      function next () {\n        expect(vm.$el.textContent).toBe('error') // late resolve ignored\n        done()\n      }\n    })\n\n    it('should not trigger timeout if resolved', done => {\n      const vm = new Vue({\n        template: `<div><test/></div>`,\n        components: {\n          test: () => ({\n            component: new Promise((resolve, reject) => {\n              setTimeout(() => {\n                resolve({ template: '<div>hi</div>' })\n              }, 10)\n            }),\n            error: { template: `<div>error</div>` },\n            timeout: 20\n          })\n        }\n      }).$mount()\n\n      setTimeout(() => {\n        expect(vm.$el.textContent).toBe('hi')\n        expect(`Failed to resolve async component`).not.toHaveBeenWarned()\n        done()\n      }, 50)\n    })\n  })\n})\n"
  },
  {
    "path": "test/unit/features/component/component-keep-alive.spec.js",
    "content": "import Vue from 'vue'\nimport injectStyles from '../transition/inject-styles'\nimport { isIE9 } from 'core/util/env'\nimport { nextFrame } from 'web/runtime/transition-util'\n\ndescribe('Component keep-alive', () => {\n  const { duration, buffer } = injectStyles()\n  let components, one, two, el\n  beforeEach(() => {\n    one = {\n      template: '<div>one</div>',\n      created: jasmine.createSpy('one created'),\n      mounted: jasmine.createSpy('one mounted'),\n      activated: jasmine.createSpy('one activated'),\n      deactivated: jasmine.createSpy('one deactivated'),\n      destroyed: jasmine.createSpy('one destroyed')\n    }\n    two = {\n      template: '<div>two</div>',\n      created: jasmine.createSpy('two created'),\n      mounted: jasmine.createSpy('two mounted'),\n      activated: jasmine.createSpy('two activated'),\n      deactivated: jasmine.createSpy('two deactivated'),\n      destroyed: jasmine.createSpy('two destroyed')\n    }\n    components = {\n      one,\n      two\n    }\n    el = document.createElement('div')\n    document.body.appendChild(el)\n  })\n\n  function assertHookCalls (component, callCounts) {\n    expect([\n      component.created.calls.count(),\n      component.mounted.calls.count(),\n      component.activated.calls.count(),\n      component.deactivated.calls.count(),\n      component.destroyed.calls.count()\n    ]).toEqual(callCounts)\n  }\n\n  it('should work', done => {\n    const vm = new Vue({\n      template: `\n        <div v-if=\"ok\">\n          <keep-alive>\n            <component :is=\"view\"></component>\n          </keep-alive>\n        </div>\n      `,\n      data: {\n        view: 'one',\n        ok: true\n      },\n      components\n    }).$mount()\n    expect(vm.$el.textContent).toBe('one')\n    assertHookCalls(one, [1, 1, 1, 0, 0])\n    assertHookCalls(two, [0, 0, 0, 0, 0])\n    vm.view = 'two'\n    waitForUpdate(() => {\n      expect(vm.$el.textContent).toBe('two')\n      assertHookCalls(one, [1, 1, 1, 1, 0])\n      assertHookCalls(two, [1, 1, 1, 0, 0])\n      vm.view = 'one'\n    }).then(() => {\n      expect(vm.$el.textContent).toBe('one')\n      assertHookCalls(one, [1, 1, 2, 1, 0])\n      assertHookCalls(two, [1, 1, 1, 1, 0])\n      vm.view = 'two'\n    }).then(() => {\n      expect(vm.$el.textContent).toBe('two')\n      assertHookCalls(one, [1, 1, 2, 2, 0])\n      assertHookCalls(two, [1, 1, 2, 1, 0])\n      vm.ok = false // teardown\n    }).then(() => {\n      expect(vm.$el.textContent).toBe('')\n      assertHookCalls(one, [1, 1, 2, 2, 1])\n      assertHookCalls(two, [1, 1, 2, 2, 1])\n    }).then(done)\n  })\n\n  it('should invoke hooks on the entire sub tree', done => {\n    one.template = '<two/>'\n    one.components = { two }\n\n    const vm = new Vue({\n      template: `\n        <div>\n          <keep-alive>\n            <one v-if=\"ok\"/>\n          </keep-alive>\n        </div>\n      `,\n      data: {\n        ok: true\n      },\n      components\n    }).$mount()\n\n    expect(vm.$el.textContent).toBe('two')\n    assertHookCalls(one, [1, 1, 1, 0, 0])\n    assertHookCalls(two, [1, 1, 1, 0, 0])\n    vm.ok = false\n    waitForUpdate(() => {\n      expect(vm.$el.textContent).toBe('')\n      assertHookCalls(one, [1, 1, 1, 1, 0])\n      assertHookCalls(two, [1, 1, 1, 1, 0])\n      vm.ok = true\n    }).then(() => {\n      expect(vm.$el.textContent).toBe('two')\n      assertHookCalls(one, [1, 1, 2, 1, 0])\n      assertHookCalls(two, [1, 1, 2, 1, 0])\n      vm.ok = false\n    }).then(() => {\n      expect(vm.$el.textContent).toBe('')\n      assertHookCalls(one, [1, 1, 2, 2, 0])\n      assertHookCalls(two, [1, 1, 2, 2, 0])\n    }).then(done)\n  })\n\n  it('should handle nested keep-alive hooks properly', done => {\n    one.template = '<keep-alive><two v-if=\"ok\" /></keep-alive>'\n    one.data = () => ({ ok: true })\n    one.components = { two }\n\n    const vm = new Vue({\n      template: `\n        <div>\n          <keep-alive>\n            <one v-if=\"ok\" ref=\"one\" />\n          </keep-alive>\n        </div>\n      `,\n      data: {\n        ok: true\n      },\n      components\n    }).$mount()\n\n    var oneInstance = vm.$refs.one\n    expect(vm.$el.textContent).toBe('two')\n    assertHookCalls(one, [1, 1, 1, 0, 0])\n    assertHookCalls(two, [1, 1, 1, 0, 0])\n    vm.ok = false\n    waitForUpdate(() => {\n      expect(vm.$el.textContent).toBe('')\n      assertHookCalls(one, [1, 1, 1, 1, 0])\n      assertHookCalls(two, [1, 1, 1, 1, 0])\n    }).then(() => {\n      vm.ok = true\n    }).then(() => {\n      expect(vm.$el.textContent).toBe('two')\n      assertHookCalls(one, [1, 1, 2, 1, 0])\n      assertHookCalls(two, [1, 1, 2, 1, 0])\n    }).then(() => {\n      // toggle sub component when activated\n      oneInstance.ok = false\n    }).then(() => {\n      expect(vm.$el.textContent).toBe('')\n      assertHookCalls(one, [1, 1, 2, 1, 0])\n      assertHookCalls(two, [1, 1, 2, 2, 0])\n    }).then(() => {\n      oneInstance.ok = true\n    }).then(() => {\n      expect(vm.$el.textContent).toBe('two')\n      assertHookCalls(one, [1, 1, 2, 1, 0])\n      assertHookCalls(two, [1, 1, 3, 2, 0])\n    }).then(() => {\n      vm.ok = false\n    }).then(() => {\n      expect(vm.$el.textContent).toBe('')\n      assertHookCalls(one, [1, 1, 2, 2, 0])\n      assertHookCalls(two, [1, 1, 3, 3, 0])\n    }).then(() => {\n      // toggle sub component when parent is deactivated\n      oneInstance.ok = false\n    }).then(() => {\n      expect(vm.$el.textContent).toBe('')\n      assertHookCalls(one, [1, 1, 2, 2, 0])\n      assertHookCalls(two, [1, 1, 3, 3, 0]) // should not be affected\n    }).then(() => {\n      oneInstance.ok = true\n    }).then(() => {\n      expect(vm.$el.textContent).toBe('')\n      assertHookCalls(one, [1, 1, 2, 2, 0])\n      assertHookCalls(two, [1, 1, 3, 3, 0]) // should not be affected\n    }).then(() => {\n      vm.ok = true\n    }).then(() => {\n      expect(vm.$el.textContent).toBe('two')\n      assertHookCalls(one, [1, 1, 3, 2, 0])\n      assertHookCalls(two, [1, 1, 4, 3, 0])\n    }).then(() => {\n      oneInstance.ok = false\n      vm.ok = false\n    }).then(() => {\n      expect(vm.$el.textContent).toBe('')\n      assertHookCalls(one, [1, 1, 3, 3, 0])\n      assertHookCalls(two, [1, 1, 4, 4, 0])\n    }).then(() => {\n      vm.ok = true\n    }).then(() => {\n      expect(vm.$el.textContent).toBe('')\n      assertHookCalls(one, [1, 1, 4, 3, 0])\n      assertHookCalls(two, [1, 1, 4, 4, 0]) // should remain inactive\n    }).then(done)\n  })\n\n  function sharedAssertions (vm, done) {\n    expect(vm.$el.textContent).toBe('one')\n    assertHookCalls(one, [1, 1, 1, 0, 0])\n    assertHookCalls(two, [0, 0, 0, 0, 0])\n    vm.view = 'two'\n    waitForUpdate(() => {\n      expect(vm.$el.textContent).toBe('two')\n      assertHookCalls(one, [1, 1, 1, 1, 0])\n      assertHookCalls(two, [1, 1, 0, 0, 0])\n      vm.view = 'one'\n    }).then(() => {\n      expect(vm.$el.textContent).toBe('one')\n      assertHookCalls(one, [1, 1, 2, 1, 0])\n      assertHookCalls(two, [1, 1, 0, 0, 1])\n      vm.view = 'two'\n    }).then(() => {\n      expect(vm.$el.textContent).toBe('two')\n      assertHookCalls(one, [1, 1, 2, 2, 0])\n      assertHookCalls(two, [2, 2, 0, 0, 1])\n      vm.ok = false // teardown\n    }).then(() => {\n      expect(vm.$el.textContent).toBe('')\n      assertHookCalls(one, [1, 1, 2, 2, 1])\n      assertHookCalls(two, [2, 2, 0, 0, 2])\n    }).then(done)\n  }\n\n  it('include (string)', done => {\n    const vm = new Vue({\n      template: `\n        <div v-if=\"ok\">\n          <keep-alive include=\"one\">\n            <component :is=\"view\"></component>\n          </keep-alive>\n        </div>\n      `,\n      data: {\n        view: 'one',\n        ok: true\n      },\n      components\n    }).$mount()\n    sharedAssertions(vm, done)\n  })\n\n  it('include (regex)', done => {\n    const vm = new Vue({\n      template: `\n        <div v-if=\"ok\">\n          <keep-alive :include=\"/^one$/\">\n            <component :is=\"view\"></component>\n          </keep-alive>\n        </div>\n      `,\n      data: {\n        view: 'one',\n        ok: true\n      },\n      components\n    }).$mount()\n    sharedAssertions(vm, done)\n  })\n\n  it('include (array)', done => {\n    const vm = new Vue({\n      template: `\n        <div v-if=\"ok\">\n          <keep-alive :include=\"['one']\">\n            <component :is=\"view\"></component>\n          </keep-alive>\n        </div>\n      `,\n      data: {\n        view: 'one',\n        ok: true\n      },\n      components\n    }).$mount()\n    sharedAssertions(vm, done)\n  })\n\n  it('exclude (string)', done => {\n    const vm = new Vue({\n      template: `\n        <div v-if=\"ok\">\n          <keep-alive exclude=\"two\">\n            <component :is=\"view\"></component>\n          </keep-alive>\n        </div>\n      `,\n      data: {\n        view: 'one',\n        ok: true\n      },\n      components\n    }).$mount()\n    sharedAssertions(vm, done)\n  })\n\n  it('exclude (regex)', done => {\n    const vm = new Vue({\n      template: `\n        <div v-if=\"ok\">\n          <keep-alive :exclude=\"/^two$/\">\n            <component :is=\"view\"></component>\n          </keep-alive>\n        </div>\n      `,\n      data: {\n        view: 'one',\n        ok: true\n      },\n      components\n    }).$mount()\n    sharedAssertions(vm, done)\n  })\n\n  it('exclude (array)', done => {\n    const vm = new Vue({\n      template: `\n        <div v-if=\"ok\">\n          <keep-alive :exclude=\"['two']\">\n            <component :is=\"view\"></component>\n          </keep-alive>\n        </div>\n      `,\n      data: {\n        view: 'one',\n        ok: true\n      },\n      components\n    }).$mount()\n    sharedAssertions(vm, done)\n  })\n\n  it('include + exclude', done => {\n    const vm = new Vue({\n      template: `\n        <div v-if=\"ok\">\n          <keep-alive include=\"one,two\" exclude=\"two\">\n            <component :is=\"view\"></component>\n          </keep-alive>\n        </div>\n      `,\n      data: {\n        view: 'one',\n        ok: true\n      },\n      components\n    }).$mount()\n    sharedAssertions(vm, done)\n  })\n\n  it('prune cache on include/exclude change', done => {\n    const vm = new Vue({\n      template: `\n        <div>\n          <keep-alive :include=\"include\">\n            <component :is=\"view\"></component>\n          </keep-alive>\n        </div>\n      `,\n      data: {\n        view: 'one',\n        include: 'one,two'\n      },\n      components\n    }).$mount()\n\n    vm.view = 'two'\n    waitForUpdate(() => {\n      assertHookCalls(one, [1, 1, 1, 1, 0])\n      assertHookCalls(two, [1, 1, 1, 0, 0])\n      vm.include = 'two'\n    }).then(() => {\n      assertHookCalls(one, [1, 1, 1, 1, 1])\n      assertHookCalls(two, [1, 1, 1, 0, 0])\n      vm.view = 'one'\n    }).then(() => {\n      assertHookCalls(one, [2, 2, 1, 1, 1])\n      assertHookCalls(two, [1, 1, 1, 1, 0])\n    }).then(done)\n  })\n\n  it('should not prune currently active instance', done => {\n    const vm = new Vue({\n      template: `\n        <div>\n          <keep-alive :include=\"include\">\n            <component :is=\"view\"></component>\n          </keep-alive>\n        </div>\n      `,\n      data: {\n        view: 'one',\n        include: 'one,two'\n      },\n      components\n    }).$mount()\n\n    vm.include = 'two'\n    waitForUpdate(() => {\n      assertHookCalls(one, [1, 1, 1, 0, 0])\n      assertHookCalls(two, [0, 0, 0, 0, 0])\n      vm.view = 'two'\n    }).then(() => {\n      assertHookCalls(one, [1, 1, 1, 0, 1])\n      assertHookCalls(two, [1, 1, 1, 0, 0])\n    }).then(done)\n  })\n\n  // #3882\n  it('deeply nested keep-alive should be destroyed properly', done => {\n    one.template = `<div><keep-alive><two></two></keep-alive></div>`\n    one.components = { two }\n    const vm = new Vue({\n      template: `<div><parent v-if=\"ok\"></parent></div>`,\n      data: { ok: true },\n      components: {\n        parent: {\n          template: `<div><keep-alive><one></one></keep-alive></div>`,\n          components: { one }\n        }\n      }\n    }).$mount()\n\n    assertHookCalls(one, [1, 1, 1, 0, 0])\n    assertHookCalls(two, [1, 1, 1, 0, 0])\n\n    vm.ok = false\n    waitForUpdate(() => {\n      assertHookCalls(one, [1, 1, 1, 1, 1])\n      assertHookCalls(two, [1, 1, 1, 1, 1])\n    }).then(done)\n  })\n\n  // #4237\n  it('should update latest props/listeners for a re-activated component', done => {\n    const one = {\n      props: ['prop'],\n      template: `<div>one {{ prop }}</div>`\n    }\n    const two = {\n      props: ['prop'],\n      template: `<div>two {{ prop }}</div>`\n    }\n    const vm = new Vue({\n      data: { view: 'one', n: 1 },\n      template: `\n        <div>\n          <keep-alive>\n            <component :is=\"view\" :prop=\"n\"></component>\n          </keep-alive>\n        </div>\n      `,\n      components: { one, two }\n    }).$mount()\n\n    expect(vm.$el.textContent).toBe('one 1')\n    vm.n++\n    waitForUpdate(() => {\n      expect(vm.$el.textContent).toBe('one 2')\n      vm.view = 'two'\n    }).then(() => {\n      expect(vm.$el.textContent).toBe('two 2')\n    }).then(done)\n  })\n\n  if (!isIE9) {\n    it('with transition-mode out-in', done => {\n      let next\n      const vm = new Vue({\n        template: `<div>\n          <transition name=\"test\" mode=\"out-in\" @after-leave=\"afterLeave\">\n            <keep-alive>\n              <component :is=\"view\" class=\"test\"></component>\n            </keep-alive>\n          </transition>\n        </div>`,\n        data: {\n          view: 'one'\n        },\n        components,\n        methods: {\n          afterLeave () {\n            next()\n          }\n        }\n      }).$mount(el)\n      expect(vm.$el.textContent).toBe('one')\n      assertHookCalls(one, [1, 1, 1, 0, 0])\n      assertHookCalls(two, [0, 0, 0, 0, 0])\n      vm.view = 'two'\n      waitForUpdate(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test test-leave test-leave-active\">one</div><!---->'\n        )\n        assertHookCalls(one, [1, 1, 1, 1, 0])\n        assertHookCalls(two, [0, 0, 0, 0, 0])\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test test-leave-active test-leave-to\">one</div><!---->'\n        )\n      }).thenWaitFor(_next => { next = _next }).then(() => {\n        expect(vm.$el.innerHTML).toBe('<!---->')\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test test-enter test-enter-active\">two</div>'\n        )\n        assertHookCalls(one, [1, 1, 1, 1, 0])\n        assertHookCalls(two, [1, 1, 1, 0, 0])\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test test-enter-active test-enter-to\">two</div>'\n        )\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test\">two</div>'\n        )\n        assertHookCalls(one, [1, 1, 1, 1, 0])\n        assertHookCalls(two, [1, 1, 1, 0, 0])\n      }).then(() => {\n        vm.view = 'one'\n      }).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test test-leave test-leave-active\">two</div><!---->'\n        )\n        assertHookCalls(one, [1, 1, 1, 1, 0])\n        assertHookCalls(two, [1, 1, 1, 1, 0])\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test test-leave-active test-leave-to\">two</div><!---->'\n        )\n      }).thenWaitFor(_next => { next = _next }).then(() => {\n        expect(vm.$el.innerHTML).toBe('<!---->')\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test test-enter test-enter-active\">one</div>'\n        )\n        assertHookCalls(one, [1, 1, 2, 1, 0])\n        assertHookCalls(two, [1, 1, 1, 1, 0])\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test test-enter-active test-enter-to\">one</div>'\n        )\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test\">one</div>'\n        )\n        assertHookCalls(one, [1, 1, 2, 1, 0])\n        assertHookCalls(two, [1, 1, 1, 1, 0])\n      }).then(done)\n    })\n\n    it('with transition-mode out-in + include', done => {\n      let next\n      const vm = new Vue({\n        template: `<div>\n          <transition name=\"test\" mode=\"out-in\" @after-leave=\"afterLeave\">\n            <keep-alive include=\"one\">\n              <component :is=\"view\" class=\"test\"></component>\n            </keep-alive>\n          </transition>\n        </div>`,\n        data: {\n          view: 'one'\n        },\n        components,\n        methods: {\n          afterLeave () {\n            next()\n          }\n        }\n      }).$mount(el)\n      expect(vm.$el.textContent).toBe('one')\n      assertHookCalls(one, [1, 1, 1, 0, 0])\n      assertHookCalls(two, [0, 0, 0, 0, 0])\n      vm.view = 'two'\n      waitForUpdate(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test test-leave test-leave-active\">one</div><!---->'\n        )\n        assertHookCalls(one, [1, 1, 1, 1, 0])\n        assertHookCalls(two, [0, 0, 0, 0, 0])\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test test-leave-active test-leave-to\">one</div><!---->'\n        )\n      }).thenWaitFor(_next => { next = _next }).then(() => {\n        expect(vm.$el.innerHTML).toBe('<!---->')\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test test-enter test-enter-active\">two</div>'\n        )\n        assertHookCalls(one, [1, 1, 1, 1, 0])\n        assertHookCalls(two, [1, 1, 0, 0, 0])\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test test-enter-active test-enter-to\">two</div>'\n        )\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test\">two</div>'\n        )\n        assertHookCalls(one, [1, 1, 1, 1, 0])\n        assertHookCalls(two, [1, 1, 0, 0, 0])\n      }).then(() => {\n        vm.view = 'one'\n      }).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test test-leave test-leave-active\">two</div><!---->'\n        )\n        assertHookCalls(one, [1, 1, 1, 1, 0])\n        assertHookCalls(two, [1, 1, 0, 0, 1])\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test test-leave-active test-leave-to\">two</div><!---->'\n        )\n      }).thenWaitFor(_next => { next = _next }).then(() => {\n        expect(vm.$el.innerHTML).toBe('<!---->')\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test test-enter test-enter-active\">one</div>'\n        )\n        assertHookCalls(one, [1, 1, 2, 1, 0])\n        assertHookCalls(two, [1, 1, 0, 0, 1])\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test test-enter-active test-enter-to\">one</div>'\n        )\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test\">one</div>'\n        )\n        assertHookCalls(one, [1, 1, 2, 1, 0])\n        assertHookCalls(two, [1, 1, 0, 0, 1])\n      }).then(done)\n    })\n\n    it('with transition-mode in-out', done => {\n      let next\n      const vm = new Vue({\n        template: `<div>\n          <transition name=\"test\" mode=\"in-out\" @after-enter=\"afterEnter\">\n            <keep-alive>\n              <component :is=\"view\" class=\"test\"></component>\n            </keep-alive>\n          </transition>\n        </div>`,\n        data: {\n          view: 'one'\n        },\n        components,\n        methods: {\n          afterEnter () {\n            next()\n          }\n        }\n      }).$mount(el)\n      expect(vm.$el.textContent).toBe('one')\n      assertHookCalls(one, [1, 1, 1, 0, 0])\n      assertHookCalls(two, [0, 0, 0, 0, 0])\n      vm.view = 'two'\n      waitForUpdate(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test\">one</div>' +\n          '<div class=\"test test-enter test-enter-active\">two</div>'\n        )\n        assertHookCalls(one, [1, 1, 1, 1, 0])\n        assertHookCalls(two, [1, 1, 1, 0, 0])\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test\">one</div>' +\n          '<div class=\"test test-enter-active test-enter-to\">two</div>'\n        )\n      }).thenWaitFor(_next => { next = _next }).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test\">one</div>' +\n          '<div class=\"test\">two</div>'\n        )\n      }).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test test-leave test-leave-active\">one</div>' +\n          '<div class=\"test\">two</div>'\n        )\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test test-leave-active test-leave-to\">one</div>' +\n          '<div class=\"test\">two</div>'\n        )\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test\">two</div>'\n        )\n        assertHookCalls(one, [1, 1, 1, 1, 0])\n        assertHookCalls(two, [1, 1, 1, 0, 0])\n      }).then(() => {\n        vm.view = 'one'\n      }).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test\">two</div>' +\n          '<div class=\"test test-enter test-enter-active\">one</div>'\n        )\n        assertHookCalls(one, [1, 1, 2, 1, 0])\n        assertHookCalls(two, [1, 1, 1, 1, 0])\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test\">two</div>' +\n          '<div class=\"test test-enter-active test-enter-to\">one</div>'\n        )\n      }).thenWaitFor(_next => { next = _next }).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test\">two</div>' +\n          '<div class=\"test\">one</div>'\n        )\n      }).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test test-leave test-leave-active\">two</div>' +\n          '<div class=\"test\">one</div>'\n        )\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test test-leave-active test-leave-to\">two</div>' +\n          '<div class=\"test\">one</div>'\n        )\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test\">one</div>'\n        )\n        assertHookCalls(one, [1, 1, 2, 1, 0])\n        assertHookCalls(two, [1, 1, 1, 1, 0])\n      }).then(done)\n    })\n\n    it('dynamic components, in-out with early cancel', done => {\n      let next\n      const vm = new Vue({\n        template: `<div>\n          <transition name=\"test\" mode=\"in-out\" @after-enter=\"afterEnter\">\n            <keep-alive>\n              <component :is=\"view\" class=\"test\"></component>\n            </keep-alive>\n          </transition>\n        </div>`,\n        data: { view: 'one' },\n        components,\n        methods: {\n          afterEnter () {\n            next()\n          }\n        }\n      }).$mount(el)\n      expect(vm.$el.textContent).toBe('one')\n      vm.view = 'two'\n      waitForUpdate(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test\">one</div>' +\n          '<div class=\"test test-enter test-enter-active\">two</div>'\n        )\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test\">one</div>' +\n          '<div class=\"test test-enter-active test-enter-to\">two</div>'\n        )\n        // switch again before enter finishes,\n        // this cancels both enter and leave.\n        vm.view = 'one'\n      }).then(() => {\n        // 1. the pending leaving \"one\" should be removed instantly.\n        // 2. the entering \"two\" should be placed into its final state instantly.\n        // 3. a new \"one\" is created and entering\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test\">two</div>' +\n          '<div class=\"test test-enter test-enter-active\">one</div>'\n        )\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test\">two</div>' +\n          '<div class=\"test test-enter-active test-enter-to\">one</div>'\n        )\n      }).thenWaitFor(_next => { next = _next }).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test\">two</div>' +\n          '<div class=\"test\">one</div>'\n        )\n      }).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test test-leave test-leave-active\">two</div>' +\n          '<div class=\"test\">one</div>'\n        )\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test test-leave-active test-leave-to\">two</div>' +\n          '<div class=\"test\">one</div>'\n        )\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test\">one</div>'\n        )\n      }).then(done).then(done)\n    })\n\n    // #4339\n    it('component with inner transition', done => {\n      const vm = new Vue({\n        template: `\n          <div>\n            <keep-alive>\n              <component ref=\"test\" :is=\"view\"></component>\n            </keep-alive>\n          </div>\n        `,\n        data: { view: 'foo' },\n        components: {\n          foo: { template: '<transition><div class=\"test\">foo</div></transition>' },\n          bar: { template: '<transition name=\"test\"><div class=\"test\">bar</div></transition>' }\n        }\n      }).$mount(el)\n\n      // should not apply transition on initial render by default\n      expect(vm.$el.innerHTML).toBe('<div class=\"test\">foo</div>')\n      vm.view = 'bar'\n      waitForUpdate(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test v-leave v-leave-active\">foo</div>' +\n          '<div class=\"test test-enter test-enter-active\">bar</div>'\n        )\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test v-leave-active v-leave-to\">foo</div>' +\n          '<div class=\"test test-enter-active test-enter-to\">bar</div>'\n        )\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test\">bar</div>'\n        )\n        vm.view = 'foo'\n      }).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test test-leave test-leave-active\">bar</div>' +\n          '<div class=\"test v-enter v-enter-active\">foo</div>'\n        )\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test test-leave-active test-leave-to\">bar</div>' +\n          '<div class=\"test v-enter-active v-enter-to\">foo</div>'\n        )\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test\">foo</div>'\n        )\n      }).then(done)\n    })\n  }\n})\n"
  },
  {
    "path": "test/unit/features/component/component-scoped-slot.spec.js",
    "content": "import Vue from 'vue'\n\ndescribe('Component scoped slot', () => {\n  it('default slot', done => {\n    const vm = new Vue({\n      template: `\n        <test ref=\"test\">\n          <template scope=\"props\">\n            <span>{{ props.msg }}</span>\n          </template>\n        </test>\n      `,\n      components: {\n        test: {\n          data () {\n            return { msg: 'hello' }\n          },\n          template: `\n            <div>\n              <slot :msg=\"msg\"></slot>\n            </div>\n          `\n        }\n      }\n    }).$mount()\n\n    expect(vm.$el.innerHTML).toBe('<span>hello</span>')\n    vm.$refs.test.msg = 'world'\n    waitForUpdate(() => {\n      expect(vm.$el.innerHTML).toBe('<span>world</span>')\n    }).then(done)\n  })\n\n  it('with v-bind', done => {\n    const vm = new Vue({\n      template: `\n        <test ref=\"test\">\n          <template scope=\"props\">\n            <span>{{ props.msg }} {{ props.msg2 }} {{ props.msg3 }}</span>\n          </template>\n        </test>\n      `,\n      components: {\n        test: {\n          data () {\n            return {\n              msg: 'hello',\n              obj: { msg2: 'world', msg3: '.' }\n            }\n          },\n          template: `\n            <div>\n              <slot :msg=\"msg\" v-bind=\"obj\" msg3=\"!\"></slot>\n            </div>\n          `\n        }\n      }\n    }).$mount()\n\n    expect(vm.$el.innerHTML).toBe('<span>hello world !</span>')\n    vm.$refs.test.msg = 'bye'\n    vm.$refs.test.obj.msg2 = 'bye'\n    waitForUpdate(() => {\n      expect(vm.$el.innerHTML).toBe('<span>bye bye !</span>')\n    }).then(done)\n  })\n\n  it('template slot', done => {\n    const vm = new Vue({\n      template: `\n        <test ref=\"test\">\n          <template slot=\"item\" scope=\"props\">\n            <span>{{ props.foo }}</span><span>{{ props.bar }}</span>\n          </template>\n        </test>\n      `,\n      components: {\n        test: {\n          data () {\n            return { foo: 'FOO', bar: 'BAR' }\n          },\n          template: `\n            <div>\n              <slot name=\"item\" :foo=\"foo\" :bar=\"bar\"></slot>\n            </div>\n          `\n        }\n      }\n    }).$mount()\n\n    expect(vm.$el.innerHTML).toBe('<span>FOO</span><span>BAR</span>')\n    vm.$refs.test.foo = 'BAZ'\n    waitForUpdate(() => {\n      expect(vm.$el.innerHTML).toBe('<span>BAZ</span><span>BAR</span>')\n    }).then(done)\n  })\n\n  it('fallback content', () => {\n    const vm = new Vue({\n      template: `<test></test>`,\n      components: {\n        test: {\n          data () {\n            return { msg: 'hello' }\n          },\n          template: `\n            <div>\n              <slot name=\"item\" :text=\"msg\">\n                <span>{{ msg }} fallback</span>\n              </slot>\n            </div>\n          `\n        }\n      }\n    }).$mount()\n    expect(vm.$el.innerHTML).toBe('<span>hello fallback</span>')\n  })\n\n  it('slot with v-for', done => {\n    const vm = new Vue({\n      template: `\n        <test ref=\"test\">\n          <template slot=\"item\" scope=\"props\">\n            <span>{{ props.text }}</span>\n          </template>\n        </test>\n      `,\n      components: {\n        test: {\n          data () {\n            return {\n              items: ['foo', 'bar', 'baz']\n            }\n          },\n          template: `\n            <div>\n              <slot v-for=\"item in items\" name=\"item\" :text=\"item\"></slot>\n            </div>\n          `\n        }\n      }\n    }).$mount()\n\n    function assertOutput () {\n      expect(vm.$el.innerHTML).toBe(vm.$refs.test.items.map(item => {\n        return `<span>${item}</span>`\n      }).join(''))\n    }\n\n    assertOutput()\n    vm.$refs.test.items.reverse()\n    waitForUpdate(assertOutput).then(() => {\n      vm.$refs.test.items.push('qux')\n    }).then(assertOutput).then(done)\n  })\n\n  it('slot inside v-for', done => {\n    const vm = new Vue({\n      template: `\n        <test ref=\"test\">\n          <template slot=\"item\" scope=\"props\">\n            <span>{{ props.text }}</span>\n          </template>\n        </test>\n      `,\n      components: {\n        test: {\n          data () {\n            return {\n              items: ['foo', 'bar', 'baz']\n            }\n          },\n          template: `\n            <ul>\n              <li v-for=\"item in items\">\n                <slot name=\"item\" :text=\"item\"></slot>\n              </li>\n            </ul>\n          `\n        }\n      }\n    }).$mount()\n\n    function assertOutput () {\n      expect(vm.$el.innerHTML).toBe(vm.$refs.test.items.map(item => {\n        return `<li><span>${item}</span></li>`\n      }).join(''))\n    }\n\n    assertOutput()\n    vm.$refs.test.items.reverse()\n    waitForUpdate(assertOutput).then(() => {\n      vm.$refs.test.items.push('qux')\n    }).then(assertOutput).then(done)\n  })\n\n  it('scoped slot without scope alias', () => {\n    const vm = new Vue({\n      template: `\n        <test ref=\"test\">\n          <span slot=\"item\">I am static</span>\n        </test>\n      `,\n      components: {\n        test: {\n          data () {\n            return { msg: 'hello' }\n          },\n          template: `\n            <div>\n              <slot name=\"item\" :text=\"msg\"></slot>\n            </div>\n          `\n        }\n      }\n    }).$mount()\n    expect(vm.$el.innerHTML).toBe('<span>I am static</span>')\n  })\n\n  it('non-scoped slot with scope alias', () => {\n    const vm = new Vue({\n      template: `\n        <test ref=\"test\">\n          <template slot=\"item\" scope=\"props\">\n            <span>{{ props.text || 'meh' }}</span>\n          </template>\n        </test>\n      `,\n      components: {\n        test: {\n          data () {\n            return { msg: 'hello' }\n          },\n          template: `\n            <div>\n              <slot name=\"item\"></slot>\n            </div>\n          `\n        }\n      }\n    }).$mount()\n    expect(vm.$el.innerHTML).toBe('<span>meh</span>')\n  })\n\n  it('warn key on slot', () => {\n    new Vue({\n      template: `\n        <test ref=\"test\">\n          <template slot=\"item\" scope=\"props\">\n            <span>{{ props.text }}</span>\n          </template>\n        </test>\n      `,\n      components: {\n        test: {\n          data () {\n            return {\n              items: ['foo', 'bar', 'baz']\n            }\n          },\n          template: `\n            <div>\n              <slot v-for=\"item in items\" name=\"item\" :text=\"item\" :key=\"item\"></slot>\n            </div>\n          `\n        }\n      }\n    }).$mount()\n    expect(`\\`key\\` does not work on <slot>`).toHaveBeenWarned()\n  })\n\n  it('render function usage (named, via data)', done => {\n    const vm = new Vue({\n      render (h) {\n        return h('test', {\n          ref: 'test',\n          scopedSlots: {\n            item: props => h('span', props.text)\n          }\n        })\n      },\n      components: {\n        test: {\n          data () {\n            return { msg: 'hello' }\n          },\n          render (h) {\n            return h('div', [\n              this.$scopedSlots.item({\n                text: this.msg\n              })\n            ])\n          }\n        }\n      }\n    }).$mount()\n\n    expect(vm.$el.innerHTML).toBe('<span>hello</span>')\n    vm.$refs.test.msg = 'world'\n    waitForUpdate(() => {\n      expect(vm.$el.innerHTML).toBe('<span>world</span>')\n    }).then(done)\n  })\n\n  it('render function usage (default, as children)', () => {\n    const vm = new Vue({\n      render (h) {\n        return h('test', [\n          props => h('span', [props.msg])\n        ])\n      },\n      components: {\n        test: {\n          data () {\n            return { msg: 'hello' }\n          },\n          render (h) {\n            return h('div', [\n              this.$scopedSlots.default({ msg: this.msg })\n            ])\n          }\n        }\n      }\n    }).$mount()\n    expect(vm.$el.innerHTML).toBe('<span>hello</span>')\n  })\n\n  // #4779\n  it('should support dynamic slot target', done => {\n    const Child = {\n      template: `\n        <div>\n          <slot name=\"a\" msg=\"a\" />\n          <slot name=\"b\" msg=\"b\" />\n        </div>\n      `\n    }\n\n    const vm = new Vue({\n      data: {\n        a: 'a',\n        b: 'b'\n      },\n      template: `\n        <child>\n          <template :slot=\"a\" scope=\"props\">A {{ props.msg }}</template>\n          <template :slot=\"b\" scope=\"props\">B {{ props.msg }}</template>\n        </child>\n      `,\n      components: { Child }\n    }).$mount()\n\n    expect(vm.$el.textContent.trim()).toBe('A a B b')\n\n    // switch slots\n    vm.a = 'b'\n    vm.b = 'a'\n    waitForUpdate(() => {\n      expect(vm.$el.textContent.trim()).toBe('B a A b')\n    }).then(done)\n  })\n\n  it('render function usage (JSX)', () => {\n    const vm = new Vue({\n      render (h) {\n        return <test>{\n          props => <span>{props.msg}</span>\n        }</test>\n      },\n      components: {\n        test: {\n          data () {\n            return { msg: 'hello' }\n          },\n          render (h) {\n            return <div>\n              {this.$scopedSlots.default({ msg: this.msg })}\n            </div>\n          }\n        }\n      }\n    }).$mount()\n    expect(vm.$el.innerHTML).toBe('<span>hello</span>')\n  })\n\n  // #5615\n  it('scoped slot with v-for', done => {\n    const vm = new Vue({\n      data: { names: ['foo', 'bar'] },\n      template: `\n        <test ref=\"test\">\n          <template v-for=\"n in names\" :slot=\"n\" scope=\"props\">\n            <span>{{ props.msg }}</span>\n          </template>\n          <template slot=\"abc\" scope=\"props\">\n            <span>{{ props.msg }}</span>\n          </template>\n        </test>\n      `,\n      components: {\n        test: {\n          data: () => ({ msg: 'hello' }),\n          template: `\n            <div>\n              <slot name=\"foo\" :msg=\"msg + ' foo'\"></slot>\n              <slot name=\"bar\" :msg=\"msg + ' bar'\"></slot>\n              <slot name=\"abc\" :msg=\"msg + ' abc'\"></slot>\n            </div>\n          `\n        }\n      }\n    }).$mount()\n\n    expect(vm.$el.innerHTML).toBe('<span>hello foo</span> <span>hello bar</span> <span>hello abc</span>')\n    vm.$refs.test.msg = 'world'\n    waitForUpdate(() => {\n      expect(vm.$el.innerHTML).toBe('<span>world foo</span> <span>world bar</span> <span>world abc</span>')\n    }).then(done)\n  })\n})\n"
  },
  {
    "path": "test/unit/features/component/component-slot.spec.js",
    "content": "import Vue from 'vue'\n\ndescribe('Component slot', () => {\n  let vm, child\n  function mount (options) {\n    vm = new Vue({\n      data: {\n        msg: 'parent message'\n      },\n      template: `<div><test>${options.parentContent || ''}</test></div>`,\n      components: {\n        test: {\n          template: options.childTemplate,\n          data () {\n            return {\n              msg: 'child message'\n            }\n          }\n        }\n      }\n    }).$mount()\n    child = vm.$children[0]\n  }\n\n  it('no content', () => {\n    mount({\n      childTemplate: '<div><slot></slot></div>'\n    })\n    expect(child.$el.childNodes.length).toBe(0)\n  })\n\n  it('default slot', done => {\n    mount({\n      childTemplate: '<div><slot></slot></div>',\n      parentContent: '<p>{{ msg }}</p>'\n    })\n    expect(child.$el.tagName).toBe('DIV')\n    expect(child.$el.children[0].tagName).toBe('P')\n    expect(child.$el.children[0].textContent).toBe('parent message')\n    vm.msg = 'changed'\n    waitForUpdate(() => {\n      expect(child.$el.children[0].textContent).toBe('changed')\n    }).then(done)\n  })\n\n  it('named slot', done => {\n    mount({\n      childTemplate: '<div><slot name=\"test\"></slot></div>',\n      parentContent: '<p slot=\"test\">{{ msg }}</p>'\n    })\n    expect(child.$el.tagName).toBe('DIV')\n    expect(child.$el.children[0].tagName).toBe('P')\n    expect(child.$el.children[0].textContent).toBe('parent message')\n    vm.msg = 'changed'\n    waitForUpdate(() => {\n      expect(child.$el.children[0].textContent).toBe('changed')\n    }).then(done)\n  })\n\n  it('named slot with 0 as a number', done => {\n    mount({\n      childTemplate: '<div><slot :name=\"0\"></slot></div>',\n      parentContent: '<p :slot=\"0\">{{ msg }}</p>'\n    })\n    expect(child.$el.tagName).toBe('DIV')\n    expect(child.$el.children[0].tagName).toBe('P')\n    expect(child.$el.children[0].textContent).toBe('parent message')\n    vm.msg = 'changed'\n    waitForUpdate(() => {\n      expect(child.$el.children[0].textContent).toBe('changed')\n    }).then(done)\n  })\n\n  it('fallback content', () => {\n    mount({\n      childTemplate: '<div><slot><p>{{msg}}</p></slot></div>'\n    })\n    expect(child.$el.children[0].tagName).toBe('P')\n    expect(child.$el.textContent).toBe('child message')\n  })\n\n  it('fallback content with multiple named slots', () => {\n    mount({\n      childTemplate: `\n        <div>\n          <slot name=\"a\"><p>fallback a</p></slot>\n          <slot name=\"b\">fallback b</slot>\n        </div>\n      `,\n      parentContent: '<p slot=\"b\">slot b</p>'\n    })\n    expect(child.$el.children.length).toBe(2)\n    expect(child.$el.children[0].textContent).toBe('fallback a')\n    expect(child.$el.children[1].textContent).toBe('slot b')\n  })\n\n  it('fallback content with mixed named/unnamed slots', () => {\n    mount({\n      childTemplate: `\n        <div>\n          <slot><p>fallback a</p></slot>\n          <slot name=\"b\">fallback b</slot>\n        </div>\n      `,\n      parentContent: '<p slot=\"b\">slot b</p>'\n    })\n    expect(child.$el.children.length).toBe(2)\n    expect(child.$el.children[0].textContent).toBe('fallback a')\n    expect(child.$el.children[1].textContent).toBe('slot b')\n  })\n\n  it('selector matching multiple elements', () => {\n    mount({\n      childTemplate: '<div><slot name=\"t\"></slot></div>',\n      parentContent: '<p slot=\"t\">1</p><div></div><p slot=\"t\">2</p>'\n    })\n    expect(child.$el.innerHTML).toBe('<p>1</p><p>2</p>')\n  })\n\n  it('default content should only render parts not selected', () => {\n    mount({\n      childTemplate: `\n        <div>\n          <slot name=\"a\"></slot>\n          <slot></slot>\n          <slot name=\"b\"></slot>\n        </div>\n      `,\n      parentContent: '<div>foo</div><p slot=\"a\">1</p><p slot=\"b\">2</p>'\n    })\n    expect(child.$el.innerHTML).toBe('<p>1</p> <div>foo</div> <p>2</p>')\n  })\n\n  it('name should only match children', function () {\n    mount({\n      childTemplate: `\n        <div>\n          <slot name=\"a\"><p>fallback a</p></slot>\n          <slot name=\"b\"><p>fallback b</p></slot>\n          <slot name=\"c\"><p>fallback c</p></slot>\n        </div>\n      `,\n      parentContent: `\n        '<p slot=\"b\">select b</p>\n        '<span><p slot=\"b\">nested b</p></span>\n        '<span><p slot=\"c\">nested c</p></span>\n      `\n    })\n    expect(child.$el.children.length).toBe(3)\n    expect(child.$el.children[0].textContent).toBe('fallback a')\n    expect(child.$el.children[1].textContent).toBe('select b')\n    expect(child.$el.children[2].textContent).toBe('fallback c')\n  })\n\n  it('should accept expressions in slot attribute and slot names', () => {\n    mount({\n      childTemplate: `<div><slot :name=\"'a'\"></slot></div>`,\n      parentContent: `<p>one</p><p :slot=\"'a'\">two</p>`\n    })\n    expect(child.$el.innerHTML).toBe('<p>two</p>')\n  })\n\n  it('slot inside v-if', done => {\n    const vm = new Vue({\n      data: {\n        a: 1,\n        b: 2,\n        show: true\n      },\n      template: '<test :show=\"show\"><p slot=\"b\">{{b}}</p><p>{{a}}</p></test>',\n      components: {\n        test: {\n          props: ['show'],\n          template: '<div v-if=\"show\"><slot></slot><slot name=\"b\"></slot></div>'\n        }\n      }\n    }).$mount()\n    expect(vm.$el.textContent).toBe('12')\n    vm.a = 2\n    waitForUpdate(() => {\n      expect(vm.$el.textContent).toBe('22')\n      vm.show = false\n    }).then(() => {\n      expect(vm.$el.textContent).toBe('')\n      vm.show = true\n      vm.a = 3\n    }).then(() => {\n      expect(vm.$el.textContent).toBe('32')\n    }).then(done)\n  })\n\n  it('slot inside v-for', () => {\n    mount({\n      childTemplate: '<div><slot v-for=\"i in 3\" :name=\"i\"></slot></div>',\n      parentContent: '<p v-for=\"i in 3\" :slot=\"i\">{{ i - 1 }}</p>'\n    })\n    expect(child.$el.innerHTML).toBe('<p>0</p><p>1</p><p>2</p>')\n  })\n\n  it('nested slots', done => {\n    const vm = new Vue({\n      template: '<test><test2><p>{{ msg }}</p></test2></test>',\n      data: {\n        msg: 'foo'\n      },\n      components: {\n        test: {\n          template: '<div><slot></slot></div>'\n        },\n        test2: {\n          template: '<div><slot></slot></div>'\n        }\n      }\n    }).$mount()\n    expect(vm.$el.innerHTML).toBe('<div><p>foo</p></div>')\n    vm.msg = 'bar'\n    waitForUpdate(() => {\n      expect(vm.$el.innerHTML).toBe('<div><p>bar</p></div>')\n    }).then(done)\n  })\n\n  it('v-if on inserted content', done => {\n    const vm = new Vue({\n      template: '<test><p v-if=\"ok\">{{ msg }}</p></test>',\n      data: {\n        ok: true,\n        msg: 'hi'\n      },\n      components: {\n        test: {\n          template: '<div><slot>fallback</slot></div>'\n        }\n      }\n    }).$mount()\n    expect(vm.$el.innerHTML).toBe('<p>hi</p>')\n    vm.ok = false\n    waitForUpdate(() => {\n      expect(vm.$el.innerHTML).toBe('fallback')\n      vm.ok = true\n      vm.msg = 'bye'\n    }).then(() => {\n      expect(vm.$el.innerHTML).toBe('<p>bye</p>')\n    }).then(done)\n  })\n\n  it('template slot', function () {\n    const vm = new Vue({\n      template: '<test><template slot=\"test\">hello</template></test>',\n      components: {\n        test: {\n          template: '<div><slot name=\"test\"></slot> world</div>'\n        }\n      }\n    }).$mount()\n    expect(vm.$el.innerHTML).toBe('hello world')\n  })\n\n  it('combined with v-for', () => {\n    const vm = new Vue({\n      template: '<div><test v-for=\"i in 3\" :key=\"i\">{{ i }}</test></div>',\n      components: {\n        test: {\n          template: '<div><slot></slot></div>'\n        }\n      }\n    }).$mount()\n    expect(vm.$el.innerHTML).toBe('<div>1</div><div>2</div><div>3</div>')\n  })\n\n  it('inside template v-if', () => {\n    mount({\n      childTemplate: `\n        <div>\n          <template v-if=\"true\"><slot></slot></template>\n        </div>\n      `,\n      parentContent: 'foo'\n    })\n    expect(child.$el.innerHTML).toBe('foo')\n  })\n\n  it('default slot should use fallback content if has only whitespace', () => {\n    mount({\n      childTemplate: `\n        <div>\n          <slot name=\"first\"><p>first slot</p></slot>\n          <slot><p>this is the default slot</p></slot>\n          <slot name=\"second\"><p>second named slot</p></slot>\n        </div>\n      `,\n      parentContent: `<div slot=\"first\">1</div> <div slot=\"second\">2</div> <div slot=\"second\">2+</div>`\n    })\n    expect(child.$el.innerHTML).toBe(\n      '<div>1</div> <p>this is the default slot</p> <div>2</div><div>2+</div>'\n    )\n  })\n\n  it('programmatic access to $slots', () => {\n    const vm = new Vue({\n      template: '<test><p slot=\"a\">A</p><div>C</div><p slot=\"b\">B</p></test>',\n      components: {\n        test: {\n          render () {\n            expect(this.$slots.a.length).toBe(1)\n            expect(this.$slots.a[0].tag).toBe('p')\n            expect(this.$slots.a[0].children.length).toBe(1)\n            expect(this.$slots.a[0].children[0].text).toBe('A')\n\n            expect(this.$slots.b.length).toBe(1)\n            expect(this.$slots.b[0].tag).toBe('p')\n            expect(this.$slots.b[0].children.length).toBe(1)\n            expect(this.$slots.b[0].children[0].text).toBe('B')\n\n            expect(this.$slots.default.length).toBe(1)\n            expect(this.$slots.default[0].tag).toBe('div')\n            expect(this.$slots.default[0].children.length).toBe(1)\n            expect(this.$slots.default[0].children[0].text).toBe('C')\n\n            return this.$slots.default[0]\n          }\n        }\n      }\n    }).$mount()\n    expect(vm.$el.tagName).toBe('DIV')\n    expect(vm.$el.textContent).toBe('C')\n  })\n\n  it('warn if user directly returns array', () => {\n    new Vue({\n      template: '<test><div></div></test>',\n      components: {\n        test: {\n          render () {\n            return this.$slots.default\n          }\n        }\n      }\n    }).$mount()\n    expect('Render function should return a single root node').toHaveBeenWarned()\n  })\n\n  // #3254\n  it('should not keep slot name when passed further down', () => {\n    const vm = new Vue({\n      template: '<test><span slot=\"foo\">foo</span></test>',\n      components: {\n        test: {\n          template: '<child><slot name=\"foo\"></slot></child>',\n          components: {\n            child: {\n              template: `\n                <div>\n                  <div class=\"default\"><slot></slot></div>\n                  <div class=\"named\"><slot name=\"foo\"></slot></div>\n                </div>\n              `\n            }\n          }\n        }\n      }\n    }).$mount()\n    expect(vm.$el.querySelector('.default').textContent).toBe('foo')\n    expect(vm.$el.querySelector('.named').textContent).toBe('')\n  })\n\n  it('should not keep slot name when passed further down (nested)', () => {\n    const vm = new Vue({\n      template: '<wrap><test><span slot=\"foo\">foo</span></test></wrap>',\n      components: {\n        wrap: {\n          template: '<div><slot></slot></div>'\n        },\n        test: {\n          template: '<child><slot name=\"foo\"></slot></child>',\n          components: {\n            child: {\n              template: `\n                <div>\n                  <div class=\"default\"><slot></slot></div>\n                  <div class=\"named\"><slot name=\"foo\"></slot></div>\n                </div>\n              `\n            }\n          }\n        }\n      }\n    }).$mount()\n    expect(vm.$el.querySelector('.default').textContent).toBe('foo')\n    expect(vm.$el.querySelector('.named').textContent).toBe('')\n  })\n\n  it('should not keep slot name when passed further down (functional)', () => {\n    const child = {\n      template: `\n        <div>\n          <div class=\"default\"><slot></slot></div>\n          <div class=\"named\"><slot name=\"foo\"></slot></div>\n        </div>\n      `\n    }\n\n    const vm = new Vue({\n      template: '<test><span slot=\"foo\">foo</span></test>',\n      components: {\n        test: {\n          functional: true,\n          render (h, ctx) {\n            const slots = ctx.slots()\n            return h(child, slots.foo)\n          }\n        }\n      }\n    }).$mount()\n    expect(vm.$el.querySelector('.default').textContent).toBe('foo')\n    expect(vm.$el.querySelector('.named').textContent).toBe('')\n  })\n\n  // #3400\n  it('named slots should be consistent across re-renders', done => {\n    const vm = new Vue({\n      template: `\n        <comp>\n          <div slot=\"foo\">foo</div>\n        </comp>\n      `,\n      components: {\n        comp: {\n          data () {\n            return { a: 1 }\n          },\n          template: `<div><slot name=\"foo\"></slot>{{ a }}</div>`\n        }\n      }\n    }).$mount()\n    expect(vm.$el.textContent).toBe('foo1')\n    vm.$children[0].a = 2\n    waitForUpdate(() => {\n      expect(vm.$el.textContent).toBe('foo2')\n    }).then(done)\n  })\n\n  // #3437\n  it('should correctly re-create components in slot', done => {\n    const calls = []\n    const vm = new Vue({\n      template: `\n        <comp ref=\"child\">\n          <div slot=\"foo\">\n            <child></child>\n          </div>\n        </comp>\n      `,\n      components: {\n        comp: {\n          data () {\n            return { ok: true }\n          },\n          template: `<div><slot name=\"foo\" v-if=\"ok\"></slot></div>`\n        },\n        child: {\n          template: '<div>child</div>',\n          created () {\n            calls.push(1)\n          },\n          destroyed () {\n            calls.push(2)\n          }\n        }\n      }\n    }).$mount()\n\n    expect(calls).toEqual([1])\n    vm.$refs.child.ok = false\n    waitForUpdate(() => {\n      expect(calls).toEqual([1, 2])\n      vm.$refs.child.ok = true\n    }).then(() => {\n      expect(calls).toEqual([1, 2, 1])\n      vm.$refs.child.ok = false\n    }).then(() => {\n      expect(calls).toEqual([1, 2, 1, 2])\n    }).then(done)\n  })\n\n  it('warn duplicate slots', () => {\n    new Vue({\n      template: `<div>\n        <test>\n          <div>foo</div>\n          <div slot=\"a\">bar</div>\n        </test>\n      </div>`,\n      components: {\n        test: {\n          template: `<div>\n            <slot></slot><slot></slot>\n            <div v-for=\"i in 3\"><slot name=\"a\"></slot></div>\n          </div>`\n        }\n      }\n    }).$mount()\n    expect('Duplicate presence of slot \"default\"').toHaveBeenWarned()\n    expect('Duplicate presence of slot \"a\"').toHaveBeenWarned()\n  })\n\n  it('should not warn valid conditional slots', () => {\n    new Vue({\n      template: `<div>\n        <test>\n          <div>foo</div>\n        </test>\n      </div>`,\n      components: {\n        test: {\n          template: `<div>\n            <slot v-if=\"true\"></slot>\n            <slot v-else></slot>\n          </div>`\n        }\n      }\n    }).$mount()\n    expect('Duplicate presence of slot \"default\"').not.toHaveBeenWarned()\n  })\n\n  // #3518\n  it('events should not break when slot is toggled by v-if', done => {\n    const spy = jasmine.createSpy()\n    const vm = new Vue({\n      template: `<test><div class=\"click\" @click=\"test\">hi</div></test>`,\n      methods: {\n        test: spy\n      },\n      components: {\n        test: {\n          data: () => ({\n            toggle: true\n          }),\n          template: `<div v-if=\"toggle\"><slot></slot></div>`\n        }\n      }\n    }).$mount()\n\n    expect(vm.$el.textContent).toBe('hi')\n    vm.$children[0].toggle = false\n    waitForUpdate(() => {\n      vm.$children[0].toggle = true\n    }).then(() => {\n      triggerEvent(vm.$el.querySelector('.click'), 'click')\n      expect(spy).toHaveBeenCalled()\n    }).then(done)\n  })\n\n  it('renders static tree with text', () => {\n    const vm = new Vue({\n      template: `<div><test><template><div></div>Hello<div></div></template></test></div>`,\n      components: {\n        test: {\n          template: '<div><slot></slot></div>'\n        }\n      }\n    })\n    vm.$mount()\n    expect('Error when rendering root').not.toHaveBeenWarned()\n  })\n\n  // #3872\n  it('functional component as slot', () => {\n    const vm = new Vue({\n      template: `\n        <parent>\n          <child>one</child>\n          <child slot=\"a\">two</child>\n        </parent>\n      `,\n      components: {\n        parent: {\n          template: `<div><slot name=\"a\"></slot><slot></slot></div>`\n        },\n        child: {\n          functional: true,\n          render (h, { slots }) {\n            return h('div', slots().default)\n          }\n        }\n      }\n    }).$mount()\n    expect(vm.$el.innerHTML.trim()).toBe('<div>two</div><div>one</div>')\n  })\n\n  // #4209\n  it('slot of multiple text nodes should not be infinitely merged', done => {\n    const wrap = {\n      template: `<inner ref=\"inner\">foo<slot></slot></inner>`,\n      components: {\n        inner: {\n          data: () => ({ a: 1 }),\n          template: `<div>{{a}}<slot></slot></div>`\n        }\n      }\n    }\n    const vm = new Vue({\n      template: `<wrap ref=\"wrap\">bar</wrap>`,\n      components: { wrap }\n    }).$mount()\n\n    expect(vm.$el.textContent).toBe('1foobar')\n    vm.$refs.wrap.$refs.inner.a++\n    waitForUpdate(() => {\n      expect(vm.$el.textContent).toBe('2foobar')\n    }).then(done)\n  })\n\n  // #4315\n  it('functional component passing slot content to stateful child component', done => {\n    const ComponentWithSlots = {\n      render (h) {\n        return h('div', this.$slots.slot1)\n      }\n    }\n\n    const FunctionalComp = {\n      functional: true,\n      render (h) {\n        return h(ComponentWithSlots, [h('span', { slot: 'slot1' }, 'foo')])\n      }\n    }\n\n    const vm = new Vue({\n      data: { n: 1 },\n      render (h) {\n        return h('div', [this.n, h(FunctionalComp)])\n      }\n    }).$mount()\n\n    expect(vm.$el.textContent).toBe('1foo')\n    vm.n++\n    waitForUpdate(() => {\n      // should not lose named slot\n      expect(vm.$el.textContent).toBe('2foo')\n    }).then(done)\n  })\n\n  it('the elements of slot should be updated correctly', done => {\n    const vm = new Vue({\n      data: { n: 1 },\n      template: '<div><test><span v-for=\"i in n\" :key=\"i\">{{ i }}</span><input value=\"a\"/></test></div>',\n      components: {\n        test: {\n          template: '<div><slot></slot></div>'\n        }\n      }\n    }).$mount()\n    expect(vm.$el.innerHTML).toBe('<div><span>1</span><input value=\"a\"></div>')\n    const input = vm.$el.querySelector('input')\n    input.value = 'b'\n    vm.n++\n    waitForUpdate(() => {\n      expect(vm.$el.innerHTML).toBe('<div><span>1</span><span>2</span><input value=\"a\"></div>')\n      expect(vm.$el.querySelector('input')).toBe(input)\n      expect(vm.$el.querySelector('input').value).toBe('b')\n    }).then(done)\n  })\n\n  // Github issue #5888\n  it('should resolve correctly slot with keep-alive', () => {\n    const vm = new Vue({\n      template: `\n      <div>\n        <container>\n          <keep-alive slot=\"foo\">\n            <child></child>\n          </keep-alive>\n        </container>\n      </div>\n      `,\n      components: {\n        container: {\n          template:\n            '<div><slot>default</slot><slot name=\"foo\">named</slot></div>'\n        },\n        child: {\n          template: '<span>foo</span>'\n        }\n      }\n    }).$mount()\n    expect(vm.$el.innerHTML).toBe('<div>default<span>foo</span></div>')\n  })\n})\n"
  },
  {
    "path": "test/unit/features/component/component.spec.js",
    "content": "import Vue from 'vue'\n\ndescribe('Component', () => {\n  it('static', () => {\n    const vm = new Vue({\n      template: '<test></test>',\n      components: {\n        test: {\n          data () {\n            return { a: 123 }\n          },\n          template: '<span>{{a}}</span>'\n        }\n      }\n    }).$mount()\n    expect(vm.$el.tagName).toBe('SPAN')\n    expect(vm.$el.innerHTML).toBe('123')\n  })\n\n  it('using component in restricted elements', () => {\n    const vm = new Vue({\n      template: '<div><table><tbody><test></test></tbody></table></div>',\n      components: {\n        test: {\n          data () {\n            return { a: 123 }\n          },\n          template: '<tr><td>{{a}}</td></tr>'\n        }\n      }\n    }).$mount()\n    expect(vm.$el.innerHTML).toBe('<table><tbody><tr><td>123</td></tr></tbody></table>')\n  })\n\n  it('\"is\" attribute', () => {\n    const vm = new Vue({\n      template: '<div><table><tbody><tr is=\"test\"></tr></tbody></table></div>',\n      components: {\n        test: {\n          data () {\n            return { a: 123 }\n          },\n          template: '<tr><td>{{a}}</td></tr>'\n        }\n      }\n    }).$mount()\n    expect(vm.$el.innerHTML).toBe('<table><tbody><tr><td>123</td></tr></tbody></table>')\n  })\n\n  it('inline-template', () => {\n    const vm = new Vue({\n      template: '<div><test inline-template><span>{{a}}</span></test></div>',\n      data: {\n        a: 'parent'\n      },\n      components: {\n        test: {\n          data () {\n            return { a: 'child' }\n          }\n        }\n      }\n    }).$mount()\n    expect(vm.$el.innerHTML).toBe('<span>child</span>')\n  })\n\n  it('fragment instance warning', () => {\n    new Vue({\n      template: '<test></test>',\n      components: {\n        test: {\n          data () {\n            return { a: 123, b: 234 }\n          },\n          template: '<p>{{a}}</p><p>{{b}}</p>'\n        }\n      }\n    }).$mount()\n    expect('Component template should contain exactly one root element').toHaveBeenWarned()\n  })\n\n  it('dynamic', done => {\n    const vm = new Vue({\n      template: '<component :is=\"view\" :view=\"view\"></component>',\n      data: {\n        view: 'view-a'\n      },\n      components: {\n        'view-a': {\n          template: '<div>foo {{view}}</div>',\n          data () {\n            return { view: 'a' }\n          }\n        },\n        'view-b': {\n          template: '<div>bar {{view}}</div>',\n          data () {\n            return { view: 'b' }\n          }\n        }\n      }\n    }).$mount()\n    expect(vm.$el.outerHTML).toBe('<div view=\"view-a\">foo a</div>')\n    vm.view = 'view-b'\n    waitForUpdate(() => {\n      expect(vm.$el.outerHTML).toBe('<div view=\"view-b\">bar b</div>')\n      vm.view = ''\n    })\n    .then(() => {\n      expect(vm.$el.nodeType).toBe(8)\n      expect(vm.$el.data).toBe('')\n    }).then(done)\n  })\n\n  it('dynamic with props', done => {\n    const vm = new Vue({\n      template: '<component :is=\"view\" :view=\"view\"></component>',\n      data: {\n        view: 'view-a'\n      },\n      components: {\n        'view-a': {\n          template: '<div>foo {{view}}</div>',\n          props: ['view']\n        },\n        'view-b': {\n          template: '<div>bar {{view}}</div>',\n          props: ['view']\n        }\n      }\n    }).$mount()\n    expect(vm.$el.outerHTML).toBe('<div>foo view-a</div>')\n    vm.view = 'view-b'\n    waitForUpdate(() => {\n      expect(vm.$el.outerHTML).toBe('<div>bar view-b</div>')\n      vm.view = ''\n    })\n    .then(() => {\n      expect(vm.$el.nodeType).toBe(8)\n      expect(vm.$el.data).toBe('')\n    }).then(done)\n  })\n\n  it(':is using raw component constructor', () => {\n    const vm = new Vue({\n      template:\n        '<div>' +\n          '<component :is=\"$options.components.test\"></component>' +\n          '<component :is=\"$options.components.async\"></component>' +\n        '</div>',\n      components: {\n        test: {\n          template: '<span>foo</span>'\n        },\n        async: function (resolve) {\n          resolve({\n            template: '<span>bar</span>'\n          })\n        }\n      }\n    }).$mount()\n    expect(vm.$el.innerHTML).toBe('<span>foo</span><span>bar</span>')\n  })\n\n  it('dynamic combined with v-for', done => {\n    const vm = new Vue({\n      template:\n        '<div>' +\n          '<component v-for=\"c in comps\" :key=\"c.type\" :is=\"c.type\"></component>' +\n        '</div>',\n      data: {\n        comps: [{ type: 'one' }, { type: 'two' }]\n      },\n      components: {\n        one: {\n          template: '<span>one</span>'\n        },\n        two: {\n          template: '<span>two</span>'\n        }\n      }\n    }).$mount()\n    expect(vm.$el.innerHTML).toBe('<span>one</span><span>two</span>')\n    vm.comps[1].type = 'one'\n    waitForUpdate(() => {\n      expect(vm.$el.innerHTML).toBe('<span>one</span><span>one</span>')\n    }).then(done)\n  })\n\n  it('should compile parent template directives & content in parent scope', done => {\n    const vm = new Vue({\n      data: {\n        ok: false,\n        message: 'hello'\n      },\n      template: '<test v-show=\"ok\">{{message}}</test>',\n      components: {\n        test: {\n          template: '<div><slot></slot> {{message}}</div>',\n          data () {\n            return {\n              message: 'world'\n            }\n          }\n        }\n      }\n    }).$mount()\n    expect(vm.$el.style.display).toBe('none')\n    expect(vm.$el.textContent).toBe('hello world')\n    vm.ok = true\n    vm.message = 'bye'\n    waitForUpdate(() => {\n      expect(vm.$el.style.display).toBe('')\n      expect(vm.$el.textContent).toBe('bye world')\n    }).then(done)\n  })\n\n  it('parent content + v-if', done => {\n    const vm = new Vue({\n      data: {\n        ok: false,\n        message: 'hello'\n      },\n      template: '<test v-if=\"ok\">{{message}}</test>',\n      components: {\n        test: {\n          template: '<div><slot></slot> {{message}}</div>',\n          data () {\n            return {\n              message: 'world'\n            }\n          }\n        }\n      }\n    }).$mount()\n    expect(vm.$el.textContent).toBe('')\n    expect(vm.$children.length).toBe(0)\n    vm.ok = true\n    waitForUpdate(() => {\n      expect(vm.$children.length).toBe(1)\n      expect(vm.$el.textContent).toBe('hello world')\n    }).then(done)\n  })\n\n  it('props', () => {\n    const vm = new Vue({\n      data: {\n        list: [{ a: 1 }, { a: 2 }]\n      },\n      template: '<test :collection=\"list\"></test>',\n      components: {\n        test: {\n          template: '<ul><li v-for=\"item in collection\">{{item.a}}</li></ul>',\n          props: ['collection']\n        }\n      }\n    }).$mount()\n    expect(vm.$el.outerHTML).toBe('<ul><li>1</li><li>2</li></ul>')\n  })\n\n  it('should warn when using camelCased props in in-DOM template', () => {\n    new Vue({\n      data: {\n        list: [{ a: 1 }, { a: 2 }]\n      },\n      template: '<test :somecollection=\"list\"></test>', // <-- simulate lowercased template\n      components: {\n        test: {\n          template: '<ul><li v-for=\"item in someCollection\">{{item.a}}</li></ul>',\n          props: ['someCollection']\n        }\n      }\n    }).$mount()\n    expect(\n      'You should probably use \"some-collection\" instead of \"someCollection\".'\n    ).toHaveBeenTipped()\n  })\n\n  it('should warn when using camelCased events in in-DOM template', () => {\n    new Vue({\n      template: '<test @foobar=\"a++\"></test>', // <-- simulate lowercased template\n      components: {\n        test: {\n          template: '<div></div>',\n          created () {\n            this.$emit('fooBar')\n          }\n        }\n      }\n    }).$mount()\n    expect(\n      'You should probably use \"foo-bar\" instead of \"fooBar\".'\n    ).toHaveBeenTipped()\n  })\n\n  it('not found component should not throw', () => {\n    expect(function () {\n      new Vue({\n        template: '<div is=\"non-existent\"></div>'\n      })\n    }).not.toThrow()\n  })\n\n  it('properly update replaced higher-order component root node', done => {\n    const vm = new Vue({\n      data: {\n        color: 'red'\n      },\n      template: '<test id=\"foo\" :class=\"color\"></test>',\n      components: {\n        test: {\n          data () {\n            return { tag: 'div' }\n          },\n          render (h) {\n            return h(this.tag, { class: 'test' }, 'hi')\n          }\n        }\n      }\n    }).$mount()\n\n    expect(vm.$el.tagName).toBe('DIV')\n    expect(vm.$el.id).toBe('foo')\n    expect(vm.$el.className).toBe('test red')\n\n    vm.color = 'green'\n    waitForUpdate(() => {\n      expect(vm.$el.tagName).toBe('DIV')\n      expect(vm.$el.id).toBe('foo')\n      expect(vm.$el.className).toBe('test green')\n      vm.$children[0].tag = 'p'\n    }).then(() => {\n      expect(vm.$el.tagName).toBe('P')\n      expect(vm.$el.id).toBe('foo')\n      expect(vm.$el.className).toBe('test green')\n      vm.color = 'red'\n    }).then(() => {\n      expect(vm.$el.tagName).toBe('P')\n      expect(vm.$el.id).toBe('foo')\n      expect(vm.$el.className).toBe('test red')\n    }).then(done)\n  })\n\n  it('catch component render error and preserve previous vnode', done => {\n    const spy = jasmine.createSpy()\n    Vue.config.errorHandler = spy\n    const vm = new Vue({\n      data: {\n        a: {\n          b: 123\n        }\n      },\n      render (h) {\n        return h('div', [this.a.b])\n      }\n    }).$mount()\n    expect(vm.$el.textContent).toBe('123')\n    expect(spy).not.toHaveBeenCalled()\n    vm.a = null\n    waitForUpdate(() => {\n      expect(spy).toHaveBeenCalled()\n      expect(vm.$el.textContent).toBe('123') // should preserve rendered DOM\n      vm.a = { b: 234 }\n    }).then(() => {\n      expect(vm.$el.textContent).toBe('234') // should be able to recover\n      Vue.config.errorHandler = null\n    }).then(done)\n  })\n\n  it('relocates node without error', done => {\n    const el = document.createElement('div')\n    document.body.appendChild(el)\n    const target = document.createElement('div')\n    document.body.appendChild(target)\n\n    const Test = {\n      render (h) {\n        return h('div', { class: 'test' }, this.$slots.default)\n      },\n      mounted () {\n        target.appendChild(this.$el)\n      },\n      beforeDestroy () {\n        const parent = this.$el.parentNode\n        if (parent) {\n          parent.removeChild(this.$el)\n        }\n      }\n    }\n    const vm = new Vue({\n      data () {\n        return {\n          view: true\n        }\n      },\n      template: `<div><test v-if=\"view\">Test</test></div>`,\n      components: {\n        test: Test\n      }\n    }).$mount(el)\n\n    expect(el.outerHTML).toBe('<div></div>')\n    expect(target.outerHTML).toBe('<div><div class=\"test\">Test</div></div>')\n    vm.view = false\n    waitForUpdate(() => {\n      expect(el.outerHTML).toBe('<div></div>')\n      expect(target.outerHTML).toBe('<div></div>')\n      vm.$destroy()\n    }).then(done)\n  })\n})\n"
  },
  {
    "path": "test/unit/features/debug.spec.js",
    "content": "import Vue from 'vue'\nimport { formatComponentName, warn } from 'core/util/debug'\n\ndescribe('Debug utilities', () => {\n  it('properly format component names', () => {\n    const vm = new Vue()\n    expect(formatComponentName(vm)).toBe('<Root>')\n\n    vm.$root = null\n    vm.$options.name = 'hello-there'\n    expect(formatComponentName(vm)).toBe('<HelloThere>')\n\n    vm.$options.name = null\n    vm.$options._componentTag = 'foo-bar-1'\n    expect(formatComponentName(vm)).toBe('<FooBar1>')\n\n    vm.$options._componentTag = null\n    vm.$options.__file = '/foo/bar/baz/SomeThing.vue'\n    expect(formatComponentName(vm)).toBe(`<SomeThing> at ${vm.$options.__file}`)\n    expect(formatComponentName(vm, false)).toBe('<SomeThing>')\n\n    vm.$options.__file = 'C:\\\\foo\\\\bar\\\\baz\\\\windows_file.vue'\n    expect(formatComponentName(vm)).toBe(`<WindowsFile> at ${vm.$options.__file}`)\n    expect(formatComponentName(vm, false)).toBe('<WindowsFile>')\n  })\n\n  it('generate correct component hierarchy trace', () => {\n    const one = {\n      name: 'one',\n      render: h => h(two)\n    }\n    const two = {\n      name: 'two',\n      render: h => h(three)\n    }\n    const three = {\n      name: 'three'\n    }\n    new Vue({\n      render: h => h(one)\n    }).$mount()\n\n    expect(\n`Failed to mount component: template or render function not defined.\n\nfound in\n\n---> <Three>\n       <Two>\n         <One>\n           <Root>`\n    ).toHaveBeenWarned()\n  })\n\n  it('generate correct component hierarchy trace (recursive)', () => {\n    let i = 0\n    const one = {\n      name: 'one',\n      render: h => i++ < 5 ? h(one) : h(two)\n    }\n    const two = {\n      name: 'two',\n      render: h => h(three)\n    }\n    const three = {\n      name: 'three'\n    }\n    new Vue({\n      render: h => h(one)\n    }).$mount()\n\n    expect(\n`Failed to mount component: template or render function not defined.\n\nfound in\n\n---> <Three>\n       <Two>\n         <One>... (5 recursive calls)\n           <Root>`\n    ).toHaveBeenWarned()\n  })\n\n  describe('warn', () => {\n    const msg = 'message'\n    const vm = new Vue()\n\n    it('calls warnHandler if warnHandler is set', () => {\n      Vue.config.warnHandler = jasmine.createSpy()\n\n      warn(msg, vm)\n\n      expect(Vue.config.warnHandler).toHaveBeenCalledWith(msg, vm, jasmine.any(String))\n\n      Vue.config.warnHandler = null\n    })\n\n    it('calls console.error if silent is false', () => {\n      Vue.config.silent = false\n\n      warn(msg, vm)\n\n      expect(msg).toHaveBeenWarned()\n      expect(console.error).toHaveBeenCalled()\n    })\n\n    it('does not call console.error if silent is true', () => {\n      Vue.config.silent = true\n\n      warn(msg, vm)\n\n      expect(console.error).not.toHaveBeenCalled()\n\n      Vue.config.silent = false\n    })\n  })\n})\n"
  },
  {
    "path": "test/unit/features/directives/bind.spec.js",
    "content": "import Vue from 'vue'\n\ndescribe('Directive v-bind', () => {\n  it('normal attr', done => {\n    const vm = new Vue({\n      template: '<div><span :test=\"foo\">hello</span></div>',\n      data: { foo: 'ok' }\n    }).$mount()\n    expect(vm.$el.firstChild.getAttribute('test')).toBe('ok')\n    vm.foo = 'again'\n    waitForUpdate(() => {\n      expect(vm.$el.firstChild.getAttribute('test')).toBe('again')\n      vm.foo = null\n    }).then(() => {\n      expect(vm.$el.firstChild.hasAttribute('test')).toBe(false)\n      vm.foo = false\n    }).then(() => {\n      expect(vm.$el.firstChild.hasAttribute('test')).toBe(false)\n      vm.foo = true\n    }).then(() => {\n      expect(vm.$el.firstChild.getAttribute('test')).toBe('true')\n      vm.foo = 0\n    }).then(() => {\n      expect(vm.$el.firstChild.getAttribute('test')).toBe('0')\n    }).then(done)\n  })\n\n  it('should set property for input value', done => {\n    const vm = new Vue({\n      template: `\n        <div>\n          <input type=\"text\" :value=\"foo\">\n          <input type=\"checkbox\" :checked=\"bar\">\n        </div>\n      `,\n      data: {\n        foo: 'ok',\n        bar: false\n      }\n    }).$mount()\n    expect(vm.$el.firstChild.value).toBe('ok')\n    expect(vm.$el.lastChild.checked).toBe(false)\n    vm.bar = true\n    waitForUpdate(() => {\n      expect(vm.$el.lastChild.checked).toBe(true)\n    }).then(done)\n  })\n\n  it('xlink', done => {\n    const vm = new Vue({\n      template: '<svg><a :xlink:special=\"foo\"></a></svg>',\n      data: {\n        foo: 'ok'\n      }\n    }).$mount()\n    const xlinkNS = 'http://www.w3.org/1999/xlink'\n    expect(vm.$el.firstChild.getAttributeNS(xlinkNS, 'special')).toBe('ok')\n    vm.foo = 'again'\n    waitForUpdate(() => {\n      expect(vm.$el.firstChild.getAttributeNS(xlinkNS, 'special')).toBe('again')\n      vm.foo = null\n    }).then(() => {\n      expect(vm.$el.firstChild.hasAttributeNS(xlinkNS, 'special')).toBe(false)\n      vm.foo = true\n    }).then(() => {\n      expect(vm.$el.firstChild.getAttributeNS(xlinkNS, 'special')).toBe('true')\n    }).then(done)\n  })\n\n  it('enumerated attr', done => {\n    const vm = new Vue({\n      template: '<div><span :draggable=\"foo\">hello</span></div>',\n      data: { foo: true }\n    }).$mount()\n    expect(vm.$el.firstChild.getAttribute('draggable')).toBe('true')\n    vm.foo = 'again'\n    waitForUpdate(() => {\n      expect(vm.$el.firstChild.getAttribute('draggable')).toBe('true')\n      vm.foo = null\n    }).then(() => {\n      expect(vm.$el.firstChild.getAttribute('draggable')).toBe('false')\n      vm.foo = ''\n    }).then(() => {\n      expect(vm.$el.firstChild.getAttribute('draggable')).toBe('true')\n      vm.foo = false\n    }).then(() => {\n      expect(vm.$el.firstChild.getAttribute('draggable')).toBe('false')\n      vm.foo = 'false'\n    }).then(() => {\n      expect(vm.$el.firstChild.getAttribute('draggable')).toBe('false')\n    }).then(done)\n  })\n\n  it('boolean attr', done => {\n    const vm = new Vue({\n      template: '<div><span :disabled=\"foo\">hello</span></div>',\n      data: { foo: true }\n    }).$mount()\n    expect(vm.$el.firstChild.getAttribute('disabled')).toBe('disabled')\n    vm.foo = 'again'\n    waitForUpdate(() => {\n      expect(vm.$el.firstChild.getAttribute('disabled')).toBe('disabled')\n      vm.foo = null\n    }).then(() => {\n      expect(vm.$el.firstChild.hasAttribute('disabled')).toBe(false)\n      vm.foo = ''\n    }).then(() => {\n      expect(vm.$el.firstChild.hasAttribute('disabled')).toBe(true)\n    }).then(done)\n  })\n\n  it('.prop modifier', () => {\n    const vm = new Vue({\n      template: '<div><span v-bind:text-content.prop=\"foo\"></span><span :inner-html.prop=\"bar\"></span></div>',\n      data: {\n        foo: 'hello',\n        bar: '<span>qux</span>'\n      }\n    }).$mount()\n    expect(vm.$el.children[0].textContent).toBe('hello')\n    expect(vm.$el.children[1].innerHTML).toBe('<span>qux</span>')\n  })\n\n  it('.prop modifier with normal attribute binding', () => {\n    const vm = new Vue({\n      template: '<input :some.prop=\"some\" :id=\"id\">',\n      data: {\n        some: 'hello',\n        id: false\n      }\n    }).$mount()\n    expect(vm.$el.some).toBe('hello')\n    expect(vm.$el.getAttribute('id')).toBe(null)\n  })\n\n  it('.camel modifier', () => {\n    const vm = new Vue({\n      template: '<svg :view-box.camel=\"viewBox\"></svg>',\n      data: {\n        viewBox: '0 0 1 1'\n      }\n    }).$mount()\n    expect(vm.$el.getAttribute('viewBox')).toBe('0 0 1 1')\n  })\n\n  it('.sync modifier', done => {\n    const vm = new Vue({\n      template: `<test :foo-bar.sync=\"bar\"/>`,\n      data: {\n        bar: 1\n      },\n      components: {\n        test: {\n          props: ['fooBar'],\n          template: `<div @click=\"$emit('update:fooBar', 2)\">{{ fooBar }}</div>`\n        }\n      }\n    }).$mount()\n\n    expect(vm.$el.textContent).toBe('1')\n    triggerEvent(vm.$el, 'click')\n    waitForUpdate(() => {\n      expect(vm.$el.textContent).toBe('2')\n    }).then(done)\n  })\n\n  it('bind object', done => {\n    const vm = new Vue({\n      template: '<input v-bind=\"test\">',\n      data: {\n        test: {\n          id: 'test',\n          class: 'ok',\n          value: 'hello'\n        }\n      }\n    }).$mount()\n    expect(vm.$el.getAttribute('id')).toBe('test')\n    expect(vm.$el.getAttribute('class')).toBe('ok')\n    expect(vm.$el.value).toBe('hello')\n    vm.test.id = 'hi'\n    vm.test.value = 'bye'\n    waitForUpdate(() => {\n      expect(vm.$el.getAttribute('id')).toBe('hi')\n      expect(vm.$el.getAttribute('class')).toBe('ok')\n      expect(vm.$el.value).toBe('bye')\n    }).then(done)\n  })\n\n  it('.sync modifier with bind object', done => {\n    const vm = new Vue({\n      template: `<test v-bind.sync=\"test\"/>`,\n      data: {\n        test: {\n          fooBar: 1\n        }\n      },\n      components: {\n        test: {\n          props: ['fooBar'],\n          template: `<div @click=\"handleUpdate\">{{ fooBar }}</div>`,\n          methods: {\n            handleUpdate () {\n              this.$emit('update:fooBar', 2)\n            }\n          }\n        }\n      }\n    }).$mount()\n    expect(vm.$el.textContent).toBe('1')\n    triggerEvent(vm.$el, 'click')\n    waitForUpdate(() => {\n      expect(vm.$el.textContent).toBe('2')\n      vm.test.fooBar = 3\n    }).then(() => {\n      expect(vm.$el.textContent).toBe('3')\n    }).then(done)\n  })\n\n  it('bind object with overwrite', done => {\n    const vm = new Vue({\n      template: '<input v-bind=\"test\" id=\"foo\" :class=\"test.value\">',\n      data: {\n        test: {\n          id: 'test',\n          class: 'ok',\n          value: 'hello'\n        }\n      }\n    }).$mount()\n    expect(vm.$el.getAttribute('id')).toBe('foo')\n    expect(vm.$el.getAttribute('class')).toBe('hello')\n    expect(vm.$el.value).toBe('hello')\n    vm.test.id = 'hi'\n    vm.test.value = 'bye'\n    waitForUpdate(() => {\n      expect(vm.$el.getAttribute('id')).toBe('foo')\n      expect(vm.$el.getAttribute('class')).toBe('bye')\n      expect(vm.$el.value).toBe('bye')\n    }).then(done)\n  })\n\n  it('bind object with class/style', done => {\n    const vm = new Vue({\n      template: '<input class=\"a\" style=\"color:red\" v-bind=\"test\">',\n      data: {\n        test: {\n          id: 'test',\n          class: ['b', 'c'],\n          style: { fontSize: '12px' }\n        }\n      }\n    }).$mount()\n    expect(vm.$el.id).toBe('test')\n    expect(vm.$el.className).toBe('a b c')\n    expect(vm.$el.style.color).toBe('red')\n    expect(vm.$el.style.fontSize).toBe('12px')\n    vm.test.id = 'hi'\n    vm.test.class = ['d']\n    vm.test.style = { fontSize: '14px' }\n    waitForUpdate(() => {\n      expect(vm.$el.id).toBe('hi')\n      expect(vm.$el.className).toBe('a d')\n      expect(vm.$el.style.color).toBe('red')\n      expect(vm.$el.style.fontSize).toBe('14px')\n    }).then(done)\n  })\n\n  it('bind object as prop', done => {\n    const vm = new Vue({\n      template: '<input v-bind.prop=\"test\">',\n      data: {\n        test: {\n          id: 'test',\n          className: 'ok',\n          value: 'hello'\n        }\n      }\n    }).$mount()\n    expect(vm.$el.id).toBe('test')\n    expect(vm.$el.className).toBe('ok')\n    expect(vm.$el.value).toBe('hello')\n    vm.test.id = 'hi'\n    vm.test.className = 'okay'\n    vm.test.value = 'bye'\n    waitForUpdate(() => {\n      expect(vm.$el.id).toBe('hi')\n      expect(vm.$el.className).toBe('okay')\n      expect(vm.$el.value).toBe('bye')\n    }).then(done)\n  })\n\n  it('bind array', done => {\n    const vm = new Vue({\n      template: '<input v-bind=\"test\">',\n      data: {\n        test: [\n          { id: 'test', class: 'ok' },\n          { value: 'hello' }\n        ]\n      }\n    }).$mount()\n    expect(vm.$el.getAttribute('id')).toBe('test')\n    expect(vm.$el.getAttribute('class')).toBe('ok')\n    expect(vm.$el.value).toBe('hello')\n    vm.test[0].id = 'hi'\n    vm.test[1].value = 'bye'\n    waitForUpdate(() => {\n      expect(vm.$el.getAttribute('id')).toBe('hi')\n      expect(vm.$el.getAttribute('class')).toBe('ok')\n      expect(vm.$el.value).toBe('bye')\n    }).then(done)\n  })\n\n  it('warn expect object', () => {\n    new Vue({\n      template: '<input v-bind=\"test\">',\n      data: {\n        test: 1\n      }\n    }).$mount()\n    expect('v-bind without argument expects an Object or Array value').toHaveBeenWarned()\n  })\n\n  it('set value for option element', () => {\n    const vm = new Vue({\n      template: '<select><option :value=\"val\">val</option></select>',\n      data: {\n        val: 'val'\n      }\n    }).$mount()\n    // check value attribute\n    expect(vm.$el.options[0].getAttribute('value')).toBe('val')\n  })\n\n  // a vdom patch edge case where the user has several un-keyed elements of the\n  // same tag next to each other, and toggling them.\n  it('properly update for toggling un-keyed children', done => {\n    const vm = new Vue({\n      template: `\n        <div>\n          <div v-if=\"ok\" id=\"a\" data-test=\"1\"></div>\n          <div v-if=\"!ok\" id=\"b\"></div>\n        </div>\n      `,\n      data: {\n        ok: true\n      }\n    }).$mount()\n    expect(vm.$el.children[0].id).toBe('a')\n    expect(vm.$el.children[0].getAttribute('data-test')).toBe('1')\n    vm.ok = false\n    waitForUpdate(() => {\n      expect(vm.$el.children[0].id).toBe('b')\n      expect(vm.$el.children[0].getAttribute('data-test')).toBe(null)\n    }).then(done)\n  })\n\n  describe('bind object with special attribute', () => {\n    function makeInstance (options) {\n      return new Vue({\n        template: `<div>${options.parentTemp}</div>`,\n        data: {\n          attrs: {\n            [options.attr]: options.value\n          }\n        },\n        components: {\n          comp: {\n            template: options.childTemp\n          }\n        }\n      }).$mount()\n    }\n\n    it('key', () => {\n      const vm = makeInstance({\n        attr: 'key',\n        value: 'test',\n        parentTemp: '<div v-bind=\"attrs\"></div>'\n      })\n      expect(vm._vnode.children[0].key).toBe('test')\n    })\n\n    it('ref', () => {\n      const vm = makeInstance({\n        attr: 'ref',\n        value: 'test',\n        parentTemp: '<div v-bind=\"attrs\"></div>'\n      })\n      expect(vm.$refs.test).toBe(vm.$el.firstChild)\n    })\n\n    it('slot', () => {\n      const vm = makeInstance({\n        attr: 'slot',\n        value: 'test',\n        parentTemp: '<comp><span v-bind=\"attrs\">123</span></comp>',\n        childTemp: '<div>slot:<slot name=\"test\"></slot></div>'\n      })\n      expect(vm.$el.innerHTML).toBe('<div>slot:<span>123</span></div>')\n    })\n\n    it('is', () => {\n      const vm = makeInstance({\n        attr: 'is',\n        value: 'comp',\n        parentTemp: '<component v-bind=\"attrs\"></component>',\n        childTemp: '<div>comp</div>'\n      })\n      expect(vm.$el.innerHTML).toBe('<div>comp</div>')\n    })\n  })\n})\n"
  },
  {
    "path": "test/unit/features/directives/class.spec.js",
    "content": "import Vue from 'vue'\n\nfunction assertClass (assertions, done) {\n  const vm = new Vue({\n    template: '<div class=\"foo\" :class=\"value\"></div>',\n    data: { value: '' }\n  }).$mount()\n  var chain = waitForUpdate()\n  assertions.forEach(([value, expected], i) => {\n    chain.then(() => {\n      if (typeof value === 'function') {\n        value(vm.value)\n      } else {\n        vm.value = value\n      }\n    }).then(() => {\n      expect(vm.$el.className).toBe(expected)\n      if (i >= assertions.length - 1) {\n        done()\n      }\n    })\n  })\n  chain.then(done)\n}\n\ndescribe('Directive v-bind:class', () => {\n  it('plain string', done => {\n    assertClass([\n      ['bar', 'foo bar'],\n      ['baz qux', 'foo baz qux'],\n      ['qux', 'foo qux'],\n      [undefined, 'foo']\n    ], done)\n  })\n\n  it('object value', done => {\n    assertClass([\n      [{ bar: true, baz: false }, 'foo bar'],\n      [{ baz: true }, 'foo baz'],\n      [null, 'foo'],\n      [{ 'bar baz': true, qux: false }, 'foo bar baz'],\n      [{ qux: true }, 'foo qux']\n    ], done)\n  })\n\n  it('array value', done => {\n    assertClass([\n      [['bar', 'baz'], 'foo bar baz'],\n      [['qux', 'baz'], 'foo qux baz'],\n      [['w', 'x y z'], 'foo w x y z'],\n      [undefined, 'foo'],\n      [['bar'], 'foo bar'],\n      [val => val.push('baz'), 'foo bar baz']\n    ], done)\n  })\n\n  it('array of mixed values', done => {\n    assertClass([\n      [['x', { y: true, z: true }], 'foo x y z'],\n      [['x', { y: true, z: false }], 'foo x y'],\n      [['f', { z: true }], 'foo f z'],\n      [['l', 'f', { n: true, z: true }], 'foo l f n z'],\n      [['x', {}], 'foo x'],\n      [undefined, 'foo']\n    ], done)\n  })\n\n  it('class merge between parent and child', done => {\n    const vm = new Vue({\n      template: '<child class=\"a\" :class=\"value\"></child>',\n      data: { value: 'b' },\n      components: {\n        child: {\n          template: '<div class=\"c\" :class=\"value\"></div>',\n          data: () => ({ value: 'd' })\n        }\n      }\n    }).$mount()\n    const child = vm.$children[0]\n    expect(vm.$el.className).toBe('c a d b')\n    vm.value = 'e'\n    waitForUpdate(() => {\n      expect(vm.$el.className).toBe('c a d e')\n    }).then(() => {\n      child.value = 'f'\n    }).then(() => {\n      expect(vm.$el.className).toBe('c a f e')\n    }).then(() => {\n      vm.value = { foo: true }\n      child.value = ['bar', 'baz']\n    }).then(() => {\n      expect(vm.$el.className).toBe('c a bar baz foo')\n    }).then(done)\n  })\n\n  it('class merge between multiple nested components sharing same element', done => {\n    const vm = new Vue({\n      template: `\n        <component1 :class=\"componentClass1\">\n          <component2 :class=\"componentClass2\">\n            <component3 :class=\"componentClass3\">\n              some text\n            </component3>\n          </component2>\n        </component1>\n      `,\n      data: {\n        componentClass1: 'componentClass1',\n        componentClass2: 'componentClass2',\n        componentClass3: 'componentClass3'\n      },\n      components: {\n        component1: {\n          render () {\n            return this.$slots.default[0]\n          }\n        },\n        component2: {\n          render () {\n            return this.$slots.default[0]\n          }\n        },\n        component3: {\n          template: '<div class=\"staticClass\"><slot></slot></div>'\n        }\n      }\n    }).$mount()\n    expect(vm.$el.className).toBe('staticClass componentClass3 componentClass2 componentClass1')\n    vm.componentClass1 = 'c1'\n    waitForUpdate(() => {\n      expect(vm.$el.className).toBe('staticClass componentClass3 componentClass2 c1')\n      vm.componentClass2 = 'c2'\n    }).then(() => {\n      expect(vm.$el.className).toBe('staticClass componentClass3 c2 c1')\n      vm.componentClass3 = 'c3'\n    }).then(() => {\n      expect(vm.$el.className).toBe('staticClass c3 c2 c1')\n    }).then(done)\n  })\n\n  it('deep update', done => {\n    const vm = new Vue({\n      template: '<div :class=\"test\"></div>',\n      data: {\n        test: { a: true, b: false }\n      }\n    }).$mount()\n    expect(vm.$el.className).toBe('a')\n    vm.test.b = true\n    waitForUpdate(() => {\n      expect(vm.$el.className).toBe('a b')\n    }).then(done)\n  })\n\n  // a vdom patch edge case where the user has several un-keyed elements of the\n  // same tag next to each other, and toggling them.\n  it('properly remove staticClass for toggling un-keyed children', done => {\n    const vm = new Vue({\n      template: `\n        <div>\n          <div v-if=\"ok\" class=\"a\"></div>\n          <div v-if=\"!ok\"></div>\n        </div>\n      `,\n      data: {\n        ok: true\n      }\n    }).$mount()\n    expect(vm.$el.children[0].className).toBe('a')\n    vm.ok = false\n    waitForUpdate(() => {\n      expect(vm.$el.children[0].className).toBe('')\n    }).then(done)\n  })\n})\n"
  },
  {
    "path": "test/unit/features/directives/cloak.spec.js",
    "content": "import Vue from 'vue'\n\ndescribe('Directive v-cloak', () => {\n  it('should be removed after compile', () => {\n    const el = document.createElement('div')\n    el.setAttribute('v-cloak', '')\n    const vm = new Vue({ el })\n    expect(vm.$el.hasAttribute('v-cloak')).toBe(false)\n  })\n})\n"
  },
  {
    "path": "test/unit/features/directives/for.spec.js",
    "content": "import Vue from 'vue'\n\ndescribe('Directive v-for', () => {\n  it('should render array of primitive values', done => {\n    const vm = new Vue({\n      template: `\n        <div>\n          <span v-for=\"item in list\">{{item}}</span>\n        </div>\n      `,\n      data: {\n        list: ['a', 'b', 'c']\n      }\n    }).$mount()\n    expect(vm.$el.innerHTML).toBe('<span>a</span><span>b</span><span>c</span>')\n    Vue.set(vm.list, 0, 'd')\n    waitForUpdate(() => {\n      expect(vm.$el.innerHTML).toBe('<span>d</span><span>b</span><span>c</span>')\n      vm.list.push('d')\n    }).then(() => {\n      expect(vm.$el.innerHTML).toBe('<span>d</span><span>b</span><span>c</span><span>d</span>')\n      vm.list.splice(1, 2)\n    }).then(() => {\n      expect(vm.$el.innerHTML).toBe('<span>d</span><span>d</span>')\n      vm.list = ['x', 'y']\n    }).then(() => {\n      expect(vm.$el.innerHTML).toBe('<span>x</span><span>y</span>')\n    }).then(done)\n  })\n\n  it('should render array of primitive values with index', done => {\n    const vm = new Vue({\n      template: `\n        <div>\n          <span v-for=\"(item, i) in list\">{{i}}-{{item}}</span>\n        </div>\n      `,\n      data: {\n        list: ['a', 'b', 'c']\n      }\n    }).$mount()\n    expect(vm.$el.innerHTML).toBe('<span>0-a</span><span>1-b</span><span>2-c</span>')\n    Vue.set(vm.list, 0, 'd')\n    waitForUpdate(() => {\n      expect(vm.$el.innerHTML).toBe('<span>0-d</span><span>1-b</span><span>2-c</span>')\n      vm.list.push('d')\n    }).then(() => {\n      expect(vm.$el.innerHTML).toBe('<span>0-d</span><span>1-b</span><span>2-c</span><span>3-d</span>')\n      vm.list.splice(1, 2)\n    }).then(() => {\n      expect(vm.$el.innerHTML).toBe('<span>0-d</span><span>1-d</span>')\n      vm.list = ['x', 'y']\n    }).then(() => {\n      expect(vm.$el.innerHTML).toBe('<span>0-x</span><span>1-y</span>')\n    }).then(done)\n  })\n\n  it('should render array of object values', done => {\n    const vm = new Vue({\n      template: `\n        <div>\n          <span v-for=\"item in list\">{{item.value}}</span>\n        </div>\n      `,\n      data: {\n        list: [\n          { value: 'a' },\n          { value: 'b' },\n          { value: 'c' }\n        ]\n      }\n    }).$mount()\n    expect(vm.$el.innerHTML).toBe('<span>a</span><span>b</span><span>c</span>')\n    Vue.set(vm.list, 0, { value: 'd' })\n    waitForUpdate(() => {\n      expect(vm.$el.innerHTML).toBe('<span>d</span><span>b</span><span>c</span>')\n      vm.list[0].value = 'e'\n    }).then(() => {\n      expect(vm.$el.innerHTML).toBe('<span>e</span><span>b</span><span>c</span>')\n      vm.list.push({})\n    }).then(() => {\n      expect(vm.$el.innerHTML).toBe('<span>e</span><span>b</span><span>c</span><span></span>')\n      vm.list.splice(1, 2)\n    }).then(() => {\n      expect(vm.$el.innerHTML).toBe('<span>e</span><span></span>')\n      vm.list = [{ value: 'x' }, { value: 'y' }]\n    }).then(() => {\n      expect(vm.$el.innerHTML).toBe('<span>x</span><span>y</span>')\n    }).then(done)\n  })\n\n  it('should render array of object values with index', done => {\n    const vm = new Vue({\n      template: `\n        <div>\n          <span v-for=\"(item, i) in list\">{{i}}-{{item.value}}</span>\n        </div>\n      `,\n      data: {\n        list: [\n          { value: 'a' },\n          { value: 'b' },\n          { value: 'c' }\n        ]\n      }\n    }).$mount()\n    expect(vm.$el.innerHTML).toBe('<span>0-a</span><span>1-b</span><span>2-c</span>')\n    Vue.set(vm.list, 0, { value: 'd' })\n    waitForUpdate(() => {\n      expect(vm.$el.innerHTML).toBe('<span>0-d</span><span>1-b</span><span>2-c</span>')\n      vm.list[0].value = 'e'\n    }).then(() => {\n      expect(vm.$el.innerHTML).toBe('<span>0-e</span><span>1-b</span><span>2-c</span>')\n      vm.list.push({})\n    }).then(() => {\n      expect(vm.$el.innerHTML).toBe('<span>0-e</span><span>1-b</span><span>2-c</span><span>3-</span>')\n      vm.list.splice(1, 2)\n    }).then(() => {\n      expect(vm.$el.innerHTML).toBe('<span>0-e</span><span>1-</span>')\n      vm.list = [{ value: 'x' }, { value: 'y' }]\n    }).then(() => {\n      expect(vm.$el.innerHTML).toBe('<span>0-x</span><span>1-y</span>')\n    }).then(done)\n  })\n\n  it('should render an Object', done => {\n    const vm = new Vue({\n      template: `\n        <div>\n          <span v-for=\"val in obj\">{{val}}</span>\n        </div>\n      `,\n      data: {\n        obj: { a: 0, b: 1, c: 2 }\n      }\n    }).$mount()\n    expect(vm.$el.innerHTML).toBe('<span>0</span><span>1</span><span>2</span>')\n    vm.obj.a = 3\n    waitForUpdate(() => {\n      expect(vm.$el.innerHTML).toBe('<span>3</span><span>1</span><span>2</span>')\n      Vue.set(vm.obj, 'd', 4)\n    }).then(() => {\n      expect(vm.$el.innerHTML).toBe('<span>3</span><span>1</span><span>2</span><span>4</span>')\n      Vue.delete(vm.obj, 'a')\n    }).then(() => {\n      expect(vm.$el.innerHTML).toBe('<span>1</span><span>2</span><span>4</span>')\n    }).then(done)\n  })\n\n  it('should render an Object with key', done => {\n    const vm = new Vue({\n      template: `\n        <div>\n          <span v-for=\"(val, key) in obj\">{{val}}-{{key}}</span>\n        </div>\n      `,\n      data: {\n        obj: { a: 0, b: 1, c: 2 }\n      }\n    }).$mount()\n    expect(vm.$el.innerHTML).toBe('<span>0-a</span><span>1-b</span><span>2-c</span>')\n    vm.obj.a = 3\n    waitForUpdate(() => {\n      expect(vm.$el.innerHTML).toBe('<span>3-a</span><span>1-b</span><span>2-c</span>')\n      Vue.set(vm.obj, 'd', 4)\n    }).then(() => {\n      expect(vm.$el.innerHTML).toBe('<span>3-a</span><span>1-b</span><span>2-c</span><span>4-d</span>')\n      Vue.delete(vm.obj, 'a')\n    }).then(() => {\n      expect(vm.$el.innerHTML).toBe('<span>1-b</span><span>2-c</span><span>4-d</span>')\n    }).then(done)\n  })\n\n  it('should render an Object with key and index', done => {\n    const vm = new Vue({\n      template: `\n        <div>\n          <span v-for=\"(val, key, i) in obj\">{{val}}-{{key}}-{{i}}</span>\n        </div>\n      `,\n      data: {\n        obj: { a: 0, b: 1, c: 2 }\n      }\n    }).$mount()\n    expect(vm.$el.innerHTML).toBe('<span>0-a-0</span><span>1-b-1</span><span>2-c-2</span>')\n    vm.obj.a = 3\n    waitForUpdate(() => {\n      expect(vm.$el.innerHTML).toBe('<span>3-a-0</span><span>1-b-1</span><span>2-c-2</span>')\n      Vue.set(vm.obj, 'd', 4)\n    }).then(() => {\n      expect(vm.$el.innerHTML).toBe('<span>3-a-0</span><span>1-b-1</span><span>2-c-2</span><span>4-d-3</span>')\n      Vue.delete(vm.obj, 'a')\n    }).then(() => {\n      expect(vm.$el.innerHTML).toBe('<span>1-b-0</span><span>2-c-1</span><span>4-d-2</span>')\n    }).then(done)\n  })\n\n  it('should render each key of data', done => {\n    const vm = new Vue({\n      template: `\n        <div>\n          <span v-for=\"(val, key) in $data\">{{val}}-{{key}}</span>\n        </div>\n      `,\n      data: { a: 0, b: 1, c: 2 }\n    }).$mount()\n    expect(vm.$el.innerHTML).toBe('<span>0-a</span><span>1-b</span><span>2-c</span>')\n    vm.a = 3\n    waitForUpdate(() => {\n      expect(vm.$el.innerHTML).toBe('<span>3-a</span><span>1-b</span><span>2-c</span>')\n    }).then(done)\n  })\n\n  it('check priorities: v-if before v-for', function () {\n    const vm = new Vue({\n      data: {\n        items: [1, 2, 3]\n      },\n      template: '<div><div v-if=\"item < 3\" v-for=\"item in items\">{{item}}</div></div>'\n    }).$mount()\n    expect(vm.$el.textContent).toBe('12')\n  })\n\n  it('check priorities: v-if after v-for', function () {\n    const vm = new Vue({\n      data: {\n        items: [1, 2, 3]\n      },\n      template: '<div><div v-for=\"item in items\" v-if=\"item < 3\">{{item}}</div></div>'\n    }).$mount()\n    expect(vm.$el.textContent).toBe('12')\n  })\n\n  it('range v-for', () => {\n    const vm = new Vue({\n      template: '<div><div v-for=\"n in 3\">{{n}}</div></div>'\n    }).$mount()\n    expect(vm.$el.textContent).toBe('123')\n  })\n\n  it('without key', done => {\n    const vm = new Vue({\n      data: {\n        items: [\n          { id: 1, msg: 'a' },\n          { id: 2, msg: 'b' },\n          { id: 3, msg: 'c' }\n        ]\n      },\n      template: '<div><div v-for=\"item in items\">{{ item.msg }}</div></div>'\n    }).$mount()\n    expect(vm.$el.textContent).toBe('abc')\n    const first = vm.$el.children[0]\n    vm.items.reverse()\n    waitForUpdate(() => {\n      expect(vm.$el.textContent).toBe('cba')\n      // assert reusing DOM element in place\n      expect(vm.$el.children[0]).toBe(first)\n    }).then(done)\n  })\n\n  it('with key', done => {\n    const vm = new Vue({\n      data: {\n        items: [\n          { id: 1, msg: 'a' },\n          { id: 2, msg: 'b' },\n          { id: 3, msg: 'c' }\n        ]\n      },\n      template: '<div><div v-for=\"item in items\" :key=\"item.id\">{{ item.msg }}</div></div>'\n    }).$mount()\n    expect(vm.$el.textContent).toBe('abc')\n    const first = vm.$el.children[0]\n    vm.items.reverse()\n    waitForUpdate(() => {\n      expect(vm.$el.textContent).toBe('cba')\n      // assert moving DOM element\n      expect(vm.$el.children[0]).not.toBe(first)\n      expect(vm.$el.children[2]).toBe(first)\n    }).then(done)\n  })\n\n  it('nested loops', () => {\n    const vm = new Vue({\n      data: {\n        items: [\n          { items: [{ a: 1 }, { a: 2 }], a: 1 },\n          { items: [{ a: 3 }, { a: 4 }], a: 2 }\n        ]\n      },\n      template:\n        '<div>' +\n          '<div v-for=\"(item, i) in items\">' +\n            '<p v-for=\"(subItem, j) in item.items\">{{j}} {{subItem.a}} {{i}} {{item.a}}</p>' +\n          '</div>' +\n        '</div>'\n    }).$mount()\n    expect(vm.$el.innerHTML).toBe(\n      '<div><p>0 1 0 1</p><p>1 2 0 1</p></div>' +\n      '<div><p>0 3 1 2</p><p>1 4 1 2</p></div>'\n    )\n  })\n\n  it('template v-for', done => {\n    const vm = new Vue({\n      data: {\n        list: [\n          { a: 1 },\n          { a: 2 },\n          { a: 3 }\n        ]\n      },\n      template:\n        '<div>' +\n          '<template v-for=\"item in list\">' +\n            '<p>{{item.a}}</p>' +\n            '<p>{{item.a + 1}}</p>' +\n          '</template>' +\n        '</div>'\n    }).$mount()\n    assertMarkup()\n    vm.list.reverse()\n    waitForUpdate(() => {\n      assertMarkup()\n      vm.list.splice(1, 1)\n    }).then(() => {\n      assertMarkup()\n      vm.list.splice(1, 0, { a: 2 })\n    }).then(done)\n\n    function assertMarkup () {\n      var markup = vm.list.map(function (item) {\n        return '<p>' + item.a + '</p><p>' + (item.a + 1) + '</p>'\n      }).join('')\n      expect(vm.$el.innerHTML).toBe(markup)\n    }\n  })\n\n  it('component v-for', done => {\n    const vm = new Vue({\n      data: {\n        list: [\n          { a: 1 },\n          { a: 2 },\n          { a: 3 }\n        ]\n      },\n      template:\n        '<div>' +\n          '<test v-for=\"item in list\" :msg=\"item.a\" :key=\"item.a\">' +\n            '<span>{{item.a}}</span>' +\n          '</test>' +\n        '</div>',\n      components: {\n        test: {\n          props: ['msg'],\n          template: '<p>{{msg}}<slot></slot></p>'\n        }\n      }\n    }).$mount()\n    assertMarkup()\n    vm.list.reverse()\n    waitForUpdate(() => {\n      assertMarkup()\n      vm.list.splice(1, 1)\n    }).then(() => {\n      assertMarkup()\n      vm.list.splice(1, 0, { a: 2 })\n    }).then(done)\n\n    function assertMarkup () {\n      var markup = vm.list.map(function (item) {\n        return `<p>${item.a}<span>${item.a}</span></p>`\n      }).join('')\n      expect(vm.$el.innerHTML).toBe(markup)\n    }\n  })\n\n  it('dynamic component v-for', done => {\n    const vm = new Vue({\n      data: {\n        list: [\n          { type: 'one' },\n          { type: 'two' }\n        ]\n      },\n      template:\n        '<div>' +\n          '<component v-for=\"item in list\" :key=\"item.type\" :is=\"item.type\"></component>' +\n        '</div>',\n      components: {\n        one: {\n          template: '<p>One!</p>'\n        },\n        two: {\n          template: '<div>Two!</div>'\n        }\n      }\n    }).$mount()\n    expect(vm.$el.innerHTML).toContain('<p>One!</p><div>Two!</div>')\n    vm.list.reverse()\n    waitForUpdate(() => {\n      expect(vm.$el.innerHTML).toContain('<div>Two!</div><p>One!</p>')\n    }).then(done)\n  })\n\n  it('should warn component v-for without keys', () => {\n    const warn = console.warn\n    console.warn = jasmine.createSpy()\n    new Vue({\n      template: `<div><test v-for=\"i in 3\"></test></div>`,\n      components: {\n        test: {\n          render () {}\n        }\n      }\n    }).$mount()\n    expect(console.warn.calls.argsFor(0)[0]).toContain(\n      `<test v-for=\"i in 3\">: component lists rendered with v-for should have explicit keys`\n    )\n    console.warn = warn\n  })\n\n  it('multi nested array reactivity', done => {\n    const vm = new Vue({\n      data: {\n        list: [[['foo']]]\n      },\n      template: `\n        <div>\n          <div v-for=\"i in list\">\n            <div v-for=\"j in i\">\n              <div v-for=\"k in j\">\n                {{ k }}\n              </div>\n            </div>\n          </div>\n        </div>\n      `\n    }).$mount()\n    expect(vm.$el.textContent).toMatch(/\\s+foo\\s+/)\n    vm.list[0][0].push('bar')\n    waitForUpdate(() => {\n      expect(vm.$el.textContent).toMatch(/\\s+foo\\s+bar\\s+/)\n    }).then(done)\n  })\n\n  it('strings', done => {\n    const vm = new Vue({\n      data: {\n        text: 'foo'\n      },\n      template: `\n        <div>\n          <span v-for=\"letter in text\">{{ letter }}.</span>\n        </div>\n      `\n    }).$mount()\n    expect(vm.$el.textContent).toMatch('f.o.o.')\n    vm.text += 'bar'\n    waitForUpdate(() => {\n      expect(vm.$el.textContent).toMatch('f.o.o.b.a.r.')\n    }).then(done)\n  })\n})\n"
  },
  {
    "path": "test/unit/features/directives/html.spec.js",
    "content": "import Vue from 'vue'\n\ndescribe('Directive v-html', () => {\n  it('should render html', () => {\n    const vm = new Vue({\n      template: '<div v-html=\"a\"></div>',\n      data: { a: 'hello' }\n    }).$mount()\n    expect(vm.$el.innerHTML).toBe('hello')\n  })\n\n  it('should encode html entities', () => {\n    const vm = new Vue({\n      template: '<div v-html=\"a\"></div>',\n      data: { a: '<span>&lt;</span>' }\n    }).$mount()\n    expect(vm.$el.innerHTML).toBe('<span>&lt;</span>')\n  })\n\n  it('should work inline', () => {\n    const vm = new Vue({\n      template: `<div v-html=\"'<span>&lt;</span>'\"></div>`\n    }).$mount()\n    expect(vm.$el.innerHTML).toBe('<span>&lt;</span>')\n  })\n\n  it('should work inline in DOM', () => {\n    const el = document.createElement('div')\n    el.innerHTML = `<div v-html=\"'<span>&lt;</span>'\"></div>`\n    const vm = new Vue({ el })\n    expect(vm.$el.children[0].innerHTML).toBe('<span>&lt;</span>')\n  })\n\n  it('should support all value types', done => {\n    const vm = new Vue({\n      template: '<div v-html=\"a\"></div>',\n      data: { a: false }\n    }).$mount()\n    waitForUpdate(() => {\n      expect(vm.$el.innerHTML).toBe('false')\n      vm.a = []\n    }).then(() => {\n      expect(vm.$el.innerHTML).toBe('[]')\n      vm.a = {}\n    }).then(() => {\n      expect(vm.$el.innerHTML).toBe('{}')\n      vm.a = 123\n    }).then(() => {\n      expect(vm.$el.innerHTML).toBe('123')\n      vm.a = 0\n    }).then(() => {\n      expect(vm.$el.innerHTML).toBe('0')\n      vm.a = ' '\n    }).then(() => {\n      expect(vm.$el.innerHTML).toBe(' ')\n      vm.a = '    '\n    }).then(() => {\n      expect(vm.$el.innerHTML).toBe('    ')\n      vm.a = null\n    }).then(() => {\n      expect(vm.$el.innerHTML).toBe('')\n      vm.a = undefined\n    }).then(() => {\n      expect(vm.$el.innerHTML).toBe('')\n    }).then(done)\n  })\n})\n"
  },
  {
    "path": "test/unit/features/directives/if.spec.js",
    "content": "import Vue from 'vue'\n\ndescribe('Directive v-if', () => {\n  it('should check if value is truthy', () => {\n    const vm = new Vue({\n      template: '<div><span v-if=\"foo\">hello</span></div>',\n      data: { foo: true }\n    }).$mount()\n    expect(vm.$el.innerHTML).toBe('<span>hello</span>')\n  })\n\n  it('should check if value is falsy', () => {\n    const vm = new Vue({\n      template: '<div><span v-if=\"foo\">hello</span></div>',\n      data: { foo: false }\n    }).$mount()\n    expect(vm.$el.innerHTML).toBe('<!---->')\n  })\n\n  it('should update if value changed', done => {\n    const vm = new Vue({\n      template: '<div><span v-if=\"foo\">hello</span></div>',\n      data: { foo: true }\n    }).$mount()\n    expect(vm.$el.innerHTML).toBe('<span>hello</span>')\n    vm.foo = false\n    waitForUpdate(() => {\n      expect(vm.$el.innerHTML).toBe('<!---->')\n      vm.foo = {}\n    }).then(() => {\n      expect(vm.$el.innerHTML).toBe('<span>hello</span>')\n      vm.foo = 0\n    }).then(() => {\n      expect(vm.$el.innerHTML).toBe('<!---->')\n      vm.foo = []\n    }).then(() => {\n      expect(vm.$el.innerHTML).toBe('<span>hello</span>')\n      vm.foo = null\n    }).then(() => {\n      expect(vm.$el.innerHTML).toBe('<!---->')\n      vm.foo = '0'\n    }).then(() => {\n      expect(vm.$el.innerHTML).toBe('<span>hello</span>')\n      vm.foo = undefined\n    }).then(() => {\n      expect(vm.$el.innerHTML).toBe('<!---->')\n      vm.foo = 1\n    }).then(() => {\n      expect(vm.$el.innerHTML).toBe('<span>hello</span>')\n    }).then(done)\n  })\n\n  it('should work well with v-else', done => {\n    const vm = new Vue({\n      template: `\n        <div>\n          <span v-if=\"foo\">hello</span>\n          <span v-else>bye</span>\n        </div>\n      `,\n      data: { foo: true }\n    }).$mount()\n    expect(vm.$el.innerHTML.trim()).toBe('<span>hello</span>')\n    vm.foo = false\n    waitForUpdate(() => {\n      expect(vm.$el.innerHTML.trim()).toBe('<span>bye</span>')\n      vm.foo = {}\n    }).then(() => {\n      expect(vm.$el.innerHTML.trim()).toBe('<span>hello</span>')\n      vm.foo = 0\n    }).then(() => {\n      expect(vm.$el.innerHTML.trim()).toBe('<span>bye</span>')\n      vm.foo = []\n    }).then(() => {\n      expect(vm.$el.innerHTML.trim()).toBe('<span>hello</span>')\n      vm.foo = null\n    }).then(() => {\n      expect(vm.$el.innerHTML.trim()).toBe('<span>bye</span>')\n      vm.foo = '0'\n    }).then(() => {\n      expect(vm.$el.innerHTML.trim()).toBe('<span>hello</span>')\n      vm.foo = undefined\n    }).then(() => {\n      expect(vm.$el.innerHTML.trim()).toBe('<span>bye</span>')\n      vm.foo = 1\n    }).then(() => {\n      expect(vm.$el.innerHTML.trim()).toBe('<span>hello</span>')\n    }).then(done)\n  })\n\n  it('should work well with v-else-if', done => {\n    const vm = new Vue({\n      template: `\n        <div>\n          <span v-if=\"foo\">hello</span>\n          <span v-else-if=\"bar\">elseif</span>\n          <span v-else>bye</span>\n        </div>\n      `,\n      data: { foo: true, bar: false }\n    }).$mount()\n    expect(vm.$el.innerHTML.trim()).toBe('<span>hello</span>')\n    vm.foo = false\n    waitForUpdate(() => {\n      expect(vm.$el.innerHTML.trim()).toBe('<span>bye</span>')\n      vm.bar = true\n    }).then(() => {\n      expect(vm.$el.innerHTML.trim()).toBe('<span>elseif</span>')\n      vm.bar = false\n    }).then(() => {\n      expect(vm.$el.innerHTML.trim()).toBe('<span>bye</span>')\n      vm.foo = true\n    }).then(() => {\n      expect(vm.$el.innerHTML.trim()).toBe('<span>hello</span>')\n      vm.foo = false\n      vm.bar = {}\n    }).then(() => {\n      expect(vm.$el.innerHTML.trim()).toBe('<span>elseif</span>')\n      vm.bar = 0\n    }).then(() => {\n      expect(vm.$el.innerHTML.trim()).toBe('<span>bye</span>')\n      vm.bar = []\n    }).then(() => {\n      expect(vm.$el.innerHTML.trim()).toBe('<span>elseif</span>')\n      vm.bar = null\n    }).then(() => {\n      expect(vm.$el.innerHTML.trim()).toBe('<span>bye</span>')\n      vm.bar = '0'\n    }).then(() => {\n      expect(vm.$el.innerHTML.trim()).toBe('<span>elseif</span>')\n      vm.bar = undefined\n    }).then(() => {\n      expect(vm.$el.innerHTML.trim()).toBe('<span>bye</span>')\n      vm.bar = 1\n    }).then(() => {\n      expect(vm.$el.innerHTML.trim()).toBe('<span>elseif</span>')\n    }).then(done)\n  })\n\n  it('should work well with v-for', done => {\n    const vm = new Vue({\n      template: `\n        <div>\n          <span v-for=\"(item, i) in list\" v-if=\"item.value\">{{i}}</span>\n        </div>\n      `,\n      data: {\n        list: [\n          { value: true },\n          { value: false },\n          { value: true }\n        ]\n      }\n    }).$mount()\n    expect(vm.$el.innerHTML).toBe('<span>0</span><!----><span>2</span>')\n    vm.list[0].value = false\n    waitForUpdate(() => {\n      expect(vm.$el.innerHTML).toBe('<!----><!----><span>2</span>')\n      vm.list.push({ value: true })\n    }).then(() => {\n      expect(vm.$el.innerHTML).toBe('<!----><!----><span>2</span><span>3</span>')\n      vm.list.splice(1, 2)\n    }).then(() => {\n      expect(vm.$el.innerHTML).toBe('<!----><span>1</span>')\n    }).then(done)\n  })\n\n  it('should work well with v-for and v-else', done => {\n    const vm = new Vue({\n      template: `\n        <div>\n          <span v-for=\"(item, i) in list\" v-if=\"item.value\">hello</span>\n          <span v-else>bye</span>\n        </div>\n      `,\n      data: {\n        list: [\n          { value: true },\n          { value: false },\n          { value: true }\n        ]\n      }\n    }).$mount()\n    expect(vm.$el.innerHTML.trim()).toBe('<span>hello</span><span>bye</span><span>hello</span>')\n    vm.list[0].value = false\n    waitForUpdate(() => {\n      expect(vm.$el.innerHTML.trim()).toBe('<span>bye</span><span>bye</span><span>hello</span>')\n      vm.list.push({ value: true })\n    }).then(() => {\n      expect(vm.$el.innerHTML.trim()).toBe('<span>bye</span><span>bye</span><span>hello</span><span>hello</span>')\n      vm.list.splice(1, 2)\n    }).then(() => {\n      expect(vm.$el.innerHTML.trim()).toBe('<span>bye</span><span>hello</span>')\n    }).then(done)\n  })\n\n  it('should work with v-for on v-else branch', done => {\n    const vm = new Vue({\n      template: `\n        <div>\n          <span v-if=\"false\">hello</span>\n          <span v-else v-for=\"item in list\">{{ item }}</span>\n        </div>\n      `,\n      data: {\n        list: [1, 2, 3]\n      }\n    }).$mount()\n    expect(vm.$el.textContent.trim()).toBe('123')\n    vm.list.reverse()\n    waitForUpdate(() => {\n      expect(vm.$el.textContent.trim()).toBe('321')\n    }).then(done)\n  })\n\n  it('should work properly on component root', done => {\n    const vm = new Vue({\n      template: `\n        <div>\n          <test class=\"test\"></test>\n        </div>\n      `,\n      components: {\n        test: {\n          data () {\n            return { ok: true }\n          },\n          template: '<div v-if=\"ok\" id=\"ok\" class=\"inner\">test</div>'\n        }\n      }\n    }).$mount()\n    expect(vm.$el.children[0].id).toBe('ok')\n    expect(vm.$el.children[0].className).toBe('inner test')\n    vm.$children[0].ok = false\n    waitForUpdate(() => {\n      // attrs / class modules should not attempt to patch the comment node\n      expect(vm.$el.innerHTML).toBe('<!---->')\n      vm.$children[0].ok = true\n    }).then(() => {\n      expect(vm.$el.children[0].id).toBe('ok')\n      expect(vm.$el.children[0].className).toBe('inner test')\n    }).then(done)\n  })\n\n  it('should maintain stable list to avoid unnecessary patches', done => {\n    const created = jasmine.createSpy()\n    const destroyed = jasmine.createSpy()\n    const vm = new Vue({\n      data: {\n        ok: true\n      },\n      // when the first div is toggled, the second div should be reused\n      // instead of re-created/destroyed\n      template: `\n        <div>\n          <div v-if=\"ok\"></div>\n          <div><test></test></div>\n        </div>\n      `,\n      components: {\n        test: {\n          template: '<div></div>',\n          created,\n          destroyed\n        }\n      }\n    }).$mount()\n\n    expect(created.calls.count()).toBe(1)\n    vm.ok = false\n    waitForUpdate(() => {\n      expect(created.calls.count()).toBe(1)\n      expect(destroyed).not.toHaveBeenCalled()\n    }).then(done)\n  })\n})\n"
  },
  {
    "path": "test/unit/features/directives/model-checkbox.spec.js",
    "content": "import Vue from 'vue'\n\ndescribe('Directive v-model checkbox', () => {\n  it('should work', done => {\n    const vm = new Vue({\n      data: {\n        test: true\n      },\n      template: '<input type=\"checkbox\" v-model=\"test\">'\n    }).$mount()\n    document.body.appendChild(vm.$el)\n    expect(vm.$el.checked).toBe(true)\n    vm.test = false\n    waitForUpdate(function () {\n      expect(vm.$el.checked).toBe(false)\n      expect(vm.test).toBe(false)\n      vm.$el.click()\n      expect(vm.$el.checked).toBe(true)\n      expect(vm.test).toBe(true)\n    }).then(() => {\n      document.body.removeChild(vm.$el)\n    }).then(done)\n  })\n\n  it('should respect value bindings', done => {\n    const vm = new Vue({\n      data: {\n        test: 1,\n        a: 1,\n        b: 2\n      },\n      template: '<input type=\"checkbox\" v-model=\"test\" :true-value=\"a\" :false-value=\"b\">'\n    }).$mount()\n    document.body.appendChild(vm.$el)\n    expect(vm.$el.checked).toBe(true)\n    vm.$el.click()\n    expect(vm.$el.checked).toBe(false)\n    expect(vm.test).toBe(2)\n    vm.$el.click()\n    expect(vm.$el.checked).toBe(true)\n    expect(vm.test).toBe(1)\n    vm.test = 2\n    waitForUpdate(() => {\n      expect(vm.$el.checked).toBe(false)\n      vm.test = 1\n    }).then(() => {\n      expect(vm.$el.checked).toBe(true)\n      document.body.removeChild(vm.$el)\n    }).then(done)\n  })\n\n  it('bind to Array value', done => {\n    const vm = new Vue({\n      data: {\n        test: ['1']\n      },\n      template: `\n        <div>\n          <input type=\"checkbox\" v-model=\"test\" value=\"1\">\n          <input type=\"checkbox\" v-model=\"test\" value=\"2\">\n        </div>\n      `\n    }).$mount()\n    document.body.appendChild(vm.$el)\n    expect(vm.$el.children[0].checked).toBe(true)\n    expect(vm.$el.children[1].checked).toBe(false)\n    vm.$el.children[0].click()\n    expect(vm.test.length).toBe(0)\n    vm.$el.children[1].click()\n    expect(vm.test).toEqual(['2'])\n    vm.$el.children[0].click()\n    expect(vm.test).toEqual(['2', '1'])\n    vm.test = ['1']\n    waitForUpdate(() => {\n      expect(vm.$el.children[0].checked).toBe(true)\n      expect(vm.$el.children[1].checked).toBe(false)\n    }).then(done)\n  })\n\n  it('bind to Array value with value bindings', done => {\n    const vm = new Vue({\n      data: {\n        test: [1]\n      },\n      template: `\n        <div>\n          <input type=\"checkbox\" v-model=\"test\" :value=\"1\">\n          <input type=\"checkbox\" v-model=\"test\" :value=\"2\">\n        </div>\n      `\n    }).$mount()\n    document.body.appendChild(vm.$el)\n    expect(vm.$el.children[0].checked).toBe(true)\n    expect(vm.$el.children[1].checked).toBe(false)\n    vm.$el.children[0].click()\n    expect(vm.test.length).toBe(0)\n    vm.$el.children[1].click()\n    expect(vm.test).toEqual([2])\n    vm.$el.children[0].click()\n    expect(vm.test).toEqual([2, 1])\n    vm.test = [1]\n    waitForUpdate(() => {\n      expect(vm.$el.children[0].checked).toBe(true)\n      expect(vm.$el.children[1].checked).toBe(false)\n    }).then(done)\n  })\n\n  it('bind to Array value with value bindings (object loose equal)', done => {\n    const vm = new Vue({\n      data: {\n        test: [{ a: 1 }]\n      },\n      template: `\n        <div>\n          <input type=\"checkbox\" v-model=\"test\" :value=\"{ a: 1 }\">\n          <input type=\"checkbox\" v-model=\"test\" :value=\"{ a: 2 }\">\n        </div>\n      `\n    }).$mount()\n    document.body.appendChild(vm.$el)\n    expect(vm.$el.children[0].checked).toBe(true)\n    expect(vm.$el.children[1].checked).toBe(false)\n    vm.$el.children[0].click()\n    expect(vm.test.length).toBe(0)\n    vm.$el.children[1].click()\n    expect(vm.test).toEqual([{ a: 2 }])\n    vm.$el.children[0].click()\n    expect(vm.test).toEqual([{ a: 2 }, { a: 1 }])\n    vm.test = [{ a: 1 }]\n    waitForUpdate(() => {\n      expect(vm.$el.children[0].checked).toBe(true)\n      expect(vm.$el.children[1].checked).toBe(false)\n    }).then(done)\n  })\n\n  it('.number modifier', () => {\n    const vm = new Vue({\n      data: {\n        test: [],\n        check: true\n      },\n      template: `\n        <div>\n          <input type=\"checkbox\" v-model.number=\"test\" value=\"1\">\n          <input type=\"checkbox\" v-model=\"test\" value=\"2\">\n          <input type=\"checkbox\" v-model.number=\"check\">\n        </div>\n      `\n    }).$mount()\n    document.body.appendChild(vm.$el)\n    const checkboxInputs = vm.$el.getElementsByTagName('input')\n    expect(checkboxInputs[0].checked).toBe(false)\n    expect(checkboxInputs[1].checked).toBe(false)\n    expect(checkboxInputs[2].checked).toBe(true)\n    checkboxInputs[0].click()\n    checkboxInputs[1].click()\n    checkboxInputs[2].click()\n    expect(vm.test).toEqual([1, '2'])\n    expect(vm.check).toEqual(false)\n  })\n\n  it('should respect different primitive type value', (done) => {\n    const vm = new Vue({\n      data: {\n        test: [0]\n      },\n      template:\n        '<div>' +\n          '<input type=\"checkbox\" value=\"\" v-model=\"test\">' +\n          '<input type=\"checkbox\" value=\"0\" v-model=\"test\">' +\n          '<input type=\"checkbox\" value=\"1\" v-model=\"test\">' +\n          '<input type=\"checkbox\" value=\"false\" v-model=\"test\">' +\n          '<input type=\"checkbox\" value=\"true\" v-model=\"test\">' +\n        '</div>'\n    }).$mount()\n    const checkboxInput = vm.$el.children\n    expect(checkboxInput[0].checked).toBe(false)\n    expect(checkboxInput[1].checked).toBe(true)\n    expect(checkboxInput[2].checked).toBe(false)\n    expect(checkboxInput[3].checked).toBe(false)\n    expect(checkboxInput[4].checked).toBe(false)\n    vm.test = [1]\n    waitForUpdate(() => {\n      expect(checkboxInput[0].checked).toBe(false)\n      expect(checkboxInput[1].checked).toBe(false)\n      expect(checkboxInput[2].checked).toBe(true)\n      expect(checkboxInput[3].checked).toBe(false)\n      expect(checkboxInput[4].checked).toBe(false)\n      vm.test = ['']\n    }).then(() => {\n      expect(checkboxInput[0].checked).toBe(true)\n      expect(checkboxInput[1].checked).toBe(false)\n      expect(checkboxInput[2].checked).toBe(false)\n      expect(checkboxInput[3].checked).toBe(false)\n      expect(checkboxInput[4].checked).toBe(false)\n      vm.test = [false]\n    }).then(() => {\n      expect(checkboxInput[0].checked).toBe(false)\n      expect(checkboxInput[1].checked).toBe(false)\n      expect(checkboxInput[2].checked).toBe(false)\n      expect(checkboxInput[3].checked).toBe(true)\n      expect(checkboxInput[4].checked).toBe(false)\n      vm.test = [true]\n    }).then(() => {\n      expect(checkboxInput[0].checked).toBe(false)\n      expect(checkboxInput[1].checked).toBe(false)\n      expect(checkboxInput[2].checked).toBe(false)\n      expect(checkboxInput[3].checked).toBe(false)\n      expect(checkboxInput[4].checked).toBe(true)\n      vm.test = ['', 0, 1, false, true]\n    }).then(() => {\n      expect(checkboxInput[0].checked).toBe(true)\n      expect(checkboxInput[1].checked).toBe(true)\n      expect(checkboxInput[2].checked).toBe(true)\n      expect(checkboxInput[3].checked).toBe(true)\n      expect(checkboxInput[4].checked).toBe(true)\n    }).then(done)\n  })\n\n  // #4521\n  it('should work with click event', (done) => {\n    const vm = new Vue({\n      data: {\n        num: 1,\n        checked: false\n      },\n      template: '<div @click=\"add\">click {{ num }}<input ref=\"checkbox\" type=\"checkbox\" v-model=\"checked\"/></div>',\n      methods: {\n        add: function () {\n          this.num++\n        }\n      }\n    }).$mount()\n    document.body.appendChild(vm.$el)\n    const checkbox = vm.$refs.checkbox\n    checkbox.click()\n    waitForUpdate(() => {\n      expect(checkbox.checked).toBe(true)\n      expect(vm.num).toBe(2)\n    }).then(done)\n  })\n\n  it('should get updated with model when in focus', (done) => {\n    const vm = new Vue({\n      data: {\n        a: 2\n      },\n      template: '<input type=\"checkbox\" v-model=\"a\"/>'\n    }).$mount()\n    document.body.appendChild(vm.$el)\n    vm.$el.click()\n    waitForUpdate(() => {\n      expect(vm.$el.checked).toBe(false)\n      vm.a = 2\n    }).then(() => {\n      expect(vm.$el.checked).toBe(true)\n    }).then(done)\n  })\n\n  it('triggers a watcher when binding to an array value in a checkbox', done => {\n    const vm = new Vue({\n      data: {\n        test: {\n          thing: false,\n          arr: [true]\n        }\n      },\n      template: `\n        <div>\n          <input type=\"checkbox\" v-model=\"test.arr[0]\">\n          <span>{{ test.arr[0] }}</span>\n        </div>\n      `\n    }).$mount()\n    document.body.appendChild(vm.$el)\n    expect(vm.$el.children[0].checked).toBe(true)\n    expect(vm.$el.children[1].textContent).toBe('true')\n    vm.$el.children[0].click()\n    expect(vm.$el.children[0].checked).toBe(false)\n    waitForUpdate(() => {\n      expect(vm.$el.children[1].textContent).toBe('false')\n    }).then(done)\n  })\n})\n"
  },
  {
    "path": "test/unit/features/directives/model-component.spec.js",
    "content": "import Vue from 'vue'\n\ndescribe('Directive v-model component', () => {\n  it('should work', done => {\n    const vm = new Vue({\n      data: {\n        msg: 'hello'\n      },\n      template: `\n        <div>\n          <p>{{ msg }}</p>\n          <test v-model=\"msg\"></test>\n        </div>\n      `,\n      components: {\n        test: {\n          props: ['value'],\n          template: `<input :value=\"value\" @input=\"$emit('input', $event.target.value)\">`\n        }\n      }\n    }).$mount()\n    document.body.appendChild(vm.$el)\n    waitForUpdate(() => {\n      const input = vm.$el.querySelector('input')\n      input.value = 'world'\n      triggerEvent(input, 'input')\n    }).then(() => {\n      expect(vm.msg).toEqual('world')\n      expect(vm.$el.querySelector('p').textContent).toEqual('world')\n      vm.msg = 'changed'\n    }).then(() => {\n      expect(vm.$el.querySelector('p').textContent).toEqual('changed')\n      expect(vm.$el.querySelector('input').value).toEqual('changed')\n    }).then(() => {\n      document.body.removeChild(vm.$el)\n    }).then(done)\n  })\n\n  it('should work with native tags with \"is\"', done => {\n    const vm = new Vue({\n      data: {\n        msg: 'hello'\n      },\n      template: `\n        <div>\n          <p>{{ msg }}</p>\n          <input is=\"test\" v-model=\"msg\">\n        </div>\n      `,\n      components: {\n        test: {\n          props: ['value'],\n          template: `<input :value=\"value\" @input=\"$emit('input', $event.target.value)\">`\n        }\n      }\n    }).$mount()\n    document.body.appendChild(vm.$el)\n    waitForUpdate(() => {\n      const input = vm.$el.querySelector('input')\n      input.value = 'world'\n      triggerEvent(input, 'input')\n    }).then(() => {\n      expect(vm.msg).toEqual('world')\n      expect(vm.$el.querySelector('p').textContent).toEqual('world')\n      vm.msg = 'changed'\n    }).then(() => {\n      expect(vm.$el.querySelector('p').textContent).toEqual('changed')\n      expect(vm.$el.querySelector('input').value).toEqual('changed')\n    }).then(() => {\n      document.body.removeChild(vm.$el)\n    }).then(done)\n  })\n\n  it('should support customization via model option', done => {\n    const spy = jasmine.createSpy('update')\n    const vm = new Vue({\n      data: {\n        msg: 'hello'\n      },\n      methods: {\n        spy\n      },\n      template: `\n        <div>\n          <p>{{ msg }}</p>\n          <test v-model=\"msg\" @update=\"spy\"></test>\n        </div>\n      `,\n      components: {\n        test: {\n          model: {\n            prop: 'currentValue',\n            event: 'update'\n          },\n          props: ['currentValue'],\n          template: `<input :value=\"currentValue\" @input=\"$emit('update', $event.target.value)\">`\n        }\n      }\n    }).$mount()\n    document.body.appendChild(vm.$el)\n    waitForUpdate(() => {\n      const input = vm.$el.querySelector('input')\n      input.value = 'world'\n      triggerEvent(input, 'input')\n    }).then(() => {\n      expect(vm.msg).toEqual('world')\n      expect(vm.$el.querySelector('p').textContent).toEqual('world')\n      expect(spy).toHaveBeenCalledWith('world')\n      vm.msg = 'changed'\n    }).then(() => {\n      expect(vm.$el.querySelector('p').textContent).toEqual('changed')\n      expect(vm.$el.querySelector('input').value).toEqual('changed')\n    }).then(() => {\n      document.body.removeChild(vm.$el)\n    }).then(done)\n  })\n\n  it('modifier: .number', () => {\n    const vm = new Vue({\n      template: `<div><my-input ref=\"input\" v-model.number=\"text\"></my-input></div>`,\n      data: { text: 'foo' },\n      components: {\n        'my-input': {\n          template: '<input>'\n        }\n      }\n    }).$mount()\n    expect(vm.text).toBe('foo')\n    vm.$refs.input.$emit('input', 'bar')\n    expect(vm.text).toBe('bar')\n    vm.$refs.input.$emit('input', '123')\n    expect(vm.text).toBe(123)\n  })\n\n  it('modifier: .trim', () => {\n    const vm = new Vue({\n      template: `<div><my-input ref=\"input\" v-model.trim=\"text\"></my-input></div>`,\n      data: { text: 'foo' },\n      components: {\n        'my-input': {\n          template: '<input>'\n        }\n      }\n    }).$mount()\n    expect(vm.text).toBe('foo')\n    vm.$refs.input.$emit('input', '  bar  ')\n    expect(vm.text).toBe('bar')\n    vm.$refs.input.$emit('input', '   foo o  ')\n    expect(vm.text).toBe('foo o')\n  })\n})\n"
  },
  {
    "path": "test/unit/features/directives/model-dynamic.spec.js",
    "content": "import Vue from 'vue'\n\ndescribe('Directive v-model dynamic input type', () => {\n  it('should warn', function () {\n    new Vue({\n      data: {\n        type: 'text',\n        text: 'hi'\n      },\n      template: `<input :type=\"type\" v-model=\"text\">`\n    }).$mount()\n    expect(`v-model does not support dynamic input types`).toHaveBeenWarned()\n  })\n})\n"
  },
  {
    "path": "test/unit/features/directives/model-file.spec.js",
    "content": "import Vue from 'vue'\n\ndescribe('Directive v-model file', () => {\n  it('warn to use @change instead', () => {\n    new Vue({\n      data: {\n        file: ''\n      },\n      template: '<input v-model=\"file\" type=\"file\">'\n    }).$mount()\n    expect('Use a v-on:change listener instead').toHaveBeenWarned()\n  })\n})\n"
  },
  {
    "path": "test/unit/features/directives/model-parse.spec.js",
    "content": "import { parseModel } from 'compiler/directives/model'\n\ndescribe('model expression parser', () => {\n  it('parse object dot notation', () => {\n    const res = parseModel('a.b.c')\n    expect(res.exp).toBe('a.b.c')\n    expect(res.idx).toBe(null)\n  })\n\n  it('parse string in brackets', () => {\n    const res = parseModel('a[\"b\"][c]')\n    expect(res.exp).toBe('a[\"b\"]')\n    expect(res.idx).toBe('c')\n  })\n\n  it('parse brackets with object dot notation', () => {\n    const res = parseModel('a[\"b\"][c].xxx')\n    expect(res.exp).toBe('a[\"b\"][c].xxx')\n    expect(res.idx).toBe(null)\n  })\n\n  it('parse nested brackets', () => {\n    const res = parseModel('a[i[c]]')\n    expect(res.exp).toBe('a')\n    expect(res.idx).toBe('i[c]')\n  })\n\n  it('combined', () => {\n    const res = parseModel('test.xxx.a[\"asa\"][test1[idx]]')\n    expect(res.exp).toBe('test.xxx.a[\"asa\"]')\n    expect(res.idx).toBe('test1[idx]')\n  })\n})\n"
  },
  {
    "path": "test/unit/features/directives/model-radio.spec.js",
    "content": "import Vue from 'vue'\n\ndescribe('Directive v-model radio', () => {\n  it('should work', done => {\n    const vm = new Vue({\n      data: {\n        test: '1'\n      },\n      template: `\n        <div>\n          <input type=\"radio\" value=\"1\" v-model=\"test\" name=\"test\">\n          <input type=\"radio\" value=\"2\" v-model=\"test\" name=\"test\">\n        </div>\n      `\n    }).$mount()\n    document.body.appendChild(vm.$el)\n    expect(vm.$el.children[0].checked).toBe(true)\n    expect(vm.$el.children[1].checked).toBe(false)\n    vm.test = '2'\n    waitForUpdate(() => {\n      expect(vm.$el.children[0].checked).toBe(false)\n      expect(vm.$el.children[1].checked).toBe(true)\n      vm.$el.children[0].click()\n      expect(vm.$el.children[0].checked).toBe(true)\n      expect(vm.$el.children[1].checked).toBe(false)\n      expect(vm.test).toBe('1')\n    }).then(() => {\n      document.body.removeChild(vm.$el)\n    }).then(done)\n  })\n\n  it('should respect value bindings', done => {\n    const vm = new Vue({\n      data: {\n        test: 1\n      },\n      template: `\n        <div>\n          <input type=\"radio\" :value=\"1\" v-model=\"test\" name=\"test\">\n          <input type=\"radio\" :value=\"2\" v-model=\"test\" name=\"test\">\n        </div>\n      `\n    }).$mount()\n    document.body.appendChild(vm.$el)\n    expect(vm.$el.children[0].checked).toBe(true)\n    expect(vm.$el.children[1].checked).toBe(false)\n    vm.test = 2\n    waitForUpdate(() => {\n      expect(vm.$el.children[0].checked).toBe(false)\n      expect(vm.$el.children[1].checked).toBe(true)\n      vm.$el.children[0].click()\n      expect(vm.$el.children[0].checked).toBe(true)\n      expect(vm.$el.children[1].checked).toBe(false)\n      expect(vm.test).toBe(1)\n    }).then(() => {\n      document.body.removeChild(vm.$el)\n    }).then(done)\n  })\n\n  it('should respect value bindings (object loose equal)', done => {\n    const vm = new Vue({\n      data: {\n        test: { a: 1 }\n      },\n      template: `\n        <div>\n          <input type=\"radio\" :value=\"{ a: 1 }\" v-model=\"test\" name=\"test\">\n          <input type=\"radio\" :value=\"{ a: 2 }\" v-model=\"test\" name=\"test\">\n        </div>\n      `\n    }).$mount()\n    document.body.appendChild(vm.$el)\n    expect(vm.$el.children[0].checked).toBe(true)\n    expect(vm.$el.children[1].checked).toBe(false)\n    vm.test = { a: 2 }\n    waitForUpdate(() => {\n      expect(vm.$el.children[0].checked).toBe(false)\n      expect(vm.$el.children[1].checked).toBe(true)\n      vm.$el.children[0].click()\n      expect(vm.$el.children[0].checked).toBe(true)\n      expect(vm.$el.children[1].checked).toBe(false)\n      expect(vm.test).toEqual({ a: 1 })\n    }).then(() => {\n      document.body.removeChild(vm.$el)\n    }).then(done)\n  })\n\n  it('multiple radios ', (done) => {\n    const spy = jasmine.createSpy()\n    const vm = new Vue({\n      data: {\n        selections: ['a', '1'],\n        radioList: [\n          {\n            name: 'questionA',\n            data: ['a', 'b', 'c']\n          },\n          {\n            name: 'questionB',\n            data: ['1', '2']\n          }\n        ]\n      },\n      watch: {\n        selections: spy\n      },\n      template:\n        '<div>' +\n          '<div v-for=\"(radioGroup, idx) in radioList\">' +\n            '<div>' +\n              '<span v-for=\"(item, index) in radioGroup.data\">' +\n                '<input :name=\"radioGroup.name\" type=\"radio\" :value=\"item\" v-model=\"selections[idx]\" :id=\"idx\"/>' +\n                '<label>{{item}}</label>' +\n              '</span>' +\n            '</div>' +\n          '</div>' +\n        '</div>'\n    }).$mount()\n    document.body.appendChild(vm.$el)\n    var inputs = vm.$el.getElementsByTagName('input')\n    inputs[1].click()\n    waitForUpdate(() => {\n      expect(vm.selections).toEqual(['b', '1'])\n      expect(spy).toHaveBeenCalled()\n    }).then(done)\n  })\n\n  it('.number modifier', () => {\n    const vm = new Vue({\n      data: {\n        test: 1\n      },\n      template: `\n        <div>\n          <input type=\"radio\" value=\"1\" v-model=\"test\" name=\"test\">\n          <input type=\"radio\" value=\"2\" v-model.number=\"test\" name=\"test\">\n        </div>\n      `\n    }).$mount()\n    document.body.appendChild(vm.$el)\n    expect(vm.$el.children[0].checked).toBe(true)\n    expect(vm.$el.children[1].checked).toBe(false)\n    vm.$el.children[1].click()\n    expect(vm.$el.children[0].checked).toBe(false)\n    expect(vm.$el.children[1].checked).toBe(true)\n    expect(vm.test).toBe(2)\n  })\n\n  it('should respect different primitive type value', (done) => {\n    const vm = new Vue({\n      data: {\n        test: 1\n      },\n      template:\n        '<div>' +\n          '<input type=\"radio\" value=\"\" v-model=\"test\" name=\"test\">' +\n          '<input type=\"radio\" value=\"0\" v-model=\"test\" name=\"test\">' +\n          '<input type=\"radio\" value=\"1\" v-model=\"test\" name=\"test\">' +\n          '<input type=\"radio\" value=\"false\" v-model=\"test\" name=\"test\">' +\n          '<input type=\"radio\" value=\"true\" v-model=\"test\" name=\"test\">' +\n        '</div>'\n    }).$mount()\n    var radioboxInput = vm.$el.children\n    expect(radioboxInput[0].checked).toBe(false)\n    expect(radioboxInput[1].checked).toBe(false)\n    expect(radioboxInput[2].checked).toBe(true)\n    expect(radioboxInput[3].checked).toBe(false)\n    expect(radioboxInput[4].checked).toBe(false)\n    vm.test = 0\n    waitForUpdate(() => {\n      expect(radioboxInput[0].checked).toBe(false)\n      expect(radioboxInput[1].checked).toBe(true)\n      expect(radioboxInput[2].checked).toBe(false)\n      expect(radioboxInput[3].checked).toBe(false)\n      expect(radioboxInput[4].checked).toBe(false)\n      vm.test = ''\n    }).then(() => {\n      expect(radioboxInput[0].checked).toBe(true)\n      expect(radioboxInput[1].checked).toBe(false)\n      expect(radioboxInput[2].checked).toBe(false)\n      expect(radioboxInput[3].checked).toBe(false)\n      expect(radioboxInput[4].checked).toBe(false)\n      vm.test = false\n    }).then(() => {\n      expect(radioboxInput[0].checked).toBe(false)\n      expect(radioboxInput[1].checked).toBe(false)\n      expect(radioboxInput[2].checked).toBe(false)\n      expect(radioboxInput[3].checked).toBe(true)\n      expect(radioboxInput[4].checked).toBe(false)\n      vm.test = true\n    }).then(() => {\n      expect(radioboxInput[0].checked).toBe(false)\n      expect(radioboxInput[1].checked).toBe(false)\n      expect(radioboxInput[2].checked).toBe(false)\n      expect(radioboxInput[3].checked).toBe(false)\n      expect(radioboxInput[4].checked).toBe(true)\n    }).then(done)\n  })\n\n  // #4521\n  it('should work with click event', (done) => {\n    const vm = new Vue({\n      data: {\n        num: 1,\n        checked: 1\n      },\n      template:\n        '<div @click=\"add\">' +\n          'click {{ num }}<input name=\"test\" type=\"radio\" value=\"1\" v-model=\"checked\"/>' +\n          '<input name=\"test\" type=\"radio\" value=\"2\" v-model=\"checked\"/>' +\n        '</div>',\n      methods: {\n        add: function () {\n          this.num++\n        }\n      }\n    }).$mount()\n    document.body.appendChild(vm.$el)\n    const radios = vm.$el.getElementsByTagName('input')\n    radios[0].click()\n    waitForUpdate(() => {\n      expect(radios[0].checked).toBe(true)\n      expect(radios[1].checked).toBe(false)\n      expect(vm.num).toBe(2)\n      radios[0].click()\n    }).then(() => {\n      expect(radios[0].checked).toBe(true)\n      expect(radios[1].checked).toBe(false)\n      expect(vm.num).toBe(3)\n      radios[1].click()\n    }).then(() => {\n      expect(radios[0].checked).toBe(false)\n      expect(radios[1].checked).toBe(true)\n      expect(vm.num).toBe(4)\n    }).then(done)\n  })\n\n  it('should get updated with model when in focus', (done) => {\n    const vm = new Vue({\n      data: {\n        a: '2'\n      },\n      template: '<input type=\"radio\" value=\"1\" v-model=\"a\"/>'\n    }).$mount()\n    document.body.appendChild(vm.$el)\n    vm.$el.click()\n    waitForUpdate(() => {\n      expect(vm.$el.checked).toBe(true)\n      vm.a = 2\n    }).then(() => {\n      expect(vm.$el.checked).toBe(false)\n    }).then(done)\n  })\n})\n"
  },
  {
    "path": "test/unit/features/directives/model-select.spec.js",
    "content": "import Vue from 'vue'\nimport { looseEqual } from 'shared/util'\n\n// Android 4.4 Chrome 30 has the bug that a multi-select option cannot be\n// deseleted by setting its \"selected\" prop via JavaScript.\nfunction hasMultiSelectBug () {\n  var s = document.createElement('select')\n  s.setAttribute('multiple', '')\n  var o = document.createElement('option')\n  s.appendChild(o)\n  o.selected = true\n  o.selected = false\n  return o.selected !== false\n}\n\n/**\n * setting <select>'s value in IE9 doesn't work\n * we have to manually loop through the options\n */\nfunction updateSelect (el, value) {\n  var options = el.options\n  var i = options.length\n  while (i--) {\n    if (looseEqual(getValue(options[i]), value)) {\n      options[i].selected = true\n      break\n    }\n  }\n}\n\nfunction getValue (option) {\n  return '_value' in option\n    ? option._value\n    : option.value || option.text\n}\n\ndescribe('Directive v-model select', () => {\n  it('should work', done => {\n    const vm = new Vue({\n      data: {\n        test: 'b'\n      },\n      template:\n        '<select v-model=\"test\">' +\n          '<option>a</option>' +\n          '<option>b</option>' +\n          '<option>c</option>' +\n        '</select>'\n    }).$mount()\n    document.body.appendChild(vm.$el)\n    expect(vm.test).toBe('b')\n    expect(vm.$el.value).toBe('b')\n    expect(vm.$el.childNodes[1].selected).toBe(true)\n    vm.test = 'c'\n    waitForUpdate(function () {\n      expect(vm.$el.value).toBe('c')\n      expect(vm.$el.childNodes[2].selected).toBe(true)\n      updateSelect(vm.$el, 'a')\n      triggerEvent(vm.$el, 'change')\n      expect(vm.test).toBe('a')\n    }).then(done)\n  })\n\n  it('should work with value bindings', done => {\n    const vm = new Vue({\n      data: {\n        test: 2\n      },\n      template:\n        '<select v-model=\"test\">' +\n          '<option value=\"1\">a</option>' +\n          '<option :value=\"2\">b</option>' +\n          '<option :value=\"3\">c</option>' +\n        '</select>'\n    }).$mount()\n    document.body.appendChild(vm.$el)\n    expect(vm.$el.value).toBe('2')\n    expect(vm.$el.childNodes[1].selected).toBe(true)\n    vm.test = 3\n    waitForUpdate(function () {\n      expect(vm.$el.value).toBe('3')\n      expect(vm.$el.childNodes[2].selected).toBe(true)\n\n      updateSelect(vm.$el, '1')\n      triggerEvent(vm.$el, 'change')\n      expect(vm.test).toBe('1')\n\n      updateSelect(vm.$el, '2')\n      triggerEvent(vm.$el, 'change')\n      expect(vm.test).toBe(2)\n    }).then(done)\n  })\n\n  it('should work with value bindings (object loose equal)', done => {\n    const vm = new Vue({\n      data: {\n        test: { a: 2 }\n      },\n      template:\n        '<select v-model=\"test\">' +\n          '<option value=\"1\">a</option>' +\n          '<option :value=\"{ a: 2 }\">b</option>' +\n          '<option :value=\"{ a: 3 }\">c</option>' +\n        '</select>'\n    }).$mount()\n    document.body.appendChild(vm.$el)\n    expect(vm.$el.childNodes[1].selected).toBe(true)\n    vm.test = { a: 3 }\n    waitForUpdate(function () {\n      expect(vm.$el.childNodes[2].selected).toBe(true)\n\n      updateSelect(vm.$el, '1')\n      triggerEvent(vm.$el, 'change')\n      expect(vm.test).toBe('1')\n\n      updateSelect(vm.$el, { a: 2 })\n      triggerEvent(vm.$el, 'change')\n      expect(vm.test).toEqual({ a: 2 })\n    }).then(done)\n  })\n\n  it('should work with v-for', done => {\n    const vm = new Vue({\n      data: {\n        test: 'b',\n        opts: ['a', 'b', 'c']\n      },\n      template:\n        '<select v-model=\"test\">' +\n          '<option v-for=\"o in opts\">{{ o }}</option>' +\n        '</select>'\n    }).$mount()\n    document.body.appendChild(vm.$el)\n    expect(vm.test).toBe('b')\n    expect(vm.$el.value).toBe('b')\n    expect(vm.$el.childNodes[1].selected).toBe(true)\n    vm.test = 'c'\n    waitForUpdate(function () {\n      expect(vm.$el.value).toBe('c')\n      expect(vm.$el.childNodes[2].selected).toBe(true)\n      updateSelect(vm.$el, 'a')\n      triggerEvent(vm.$el, 'change')\n      expect(vm.test).toBe('a')\n      // update v-for opts\n      vm.opts = ['d', 'a']\n    }).then(() => {\n      expect(vm.$el.childNodes[0].selected).toBe(false)\n      expect(vm.$el.childNodes[1].selected).toBe(true)\n    }).then(done)\n  })\n\n  it('should work with v-for & value bindings', done => {\n    const vm = new Vue({\n      data: {\n        test: 2,\n        opts: [1, 2, 3]\n      },\n      template:\n        '<select v-model=\"test\">' +\n          '<option v-for=\"o in opts\" :value=\"o\">option {{ o }}</option>' +\n        '</select>'\n    }).$mount()\n    document.body.appendChild(vm.$el)\n    expect(vm.$el.value).toBe('2')\n    expect(vm.$el.childNodes[1].selected).toBe(true)\n    vm.test = 3\n    waitForUpdate(function () {\n      expect(vm.$el.value).toBe('3')\n      expect(vm.$el.childNodes[2].selected).toBe(true)\n      updateSelect(vm.$el, 1)\n      triggerEvent(vm.$el, 'change')\n      expect(vm.test).toBe(1)\n      // update v-for opts\n      vm.opts = [0, 1]\n    }).then(() => {\n      expect(vm.$el.childNodes[0].selected).toBe(false)\n      expect(vm.$el.childNodes[1].selected).toBe(true)\n    }).then(done)\n  })\n\n  it('should work with select which has no default selected options', (done) => {\n    const spy = jasmine.createSpy()\n    const vm = new Vue({\n      data: {\n        id: 4,\n        list: [1, 2, 3],\n        testChange: 5\n      },\n      template:\n        '<div>' +\n          '<select @change=\"test\" v-model=\"id\">' +\n            '<option v-for=\"item in list\" :value=\"item\">{{item}}</option>' +\n          '</select>' +\n          '{{testChange}}' +\n        '</div>',\n      methods: {\n        test: spy\n      }\n    }).$mount()\n    document.body.appendChild(vm.$el)\n    vm.testChange = 10\n    waitForUpdate(() => {\n      expect(spy.calls.count()).toBe(0)\n    }).then(done)\n  })\n\n  if (!hasMultiSelectBug()) {\n    it('multiple', done => {\n      const vm = new Vue({\n        data: {\n          test: ['b']\n        },\n        template:\n          '<select v-model=\"test\" multiple>' +\n            '<option>a</option>' +\n            '<option>b</option>' +\n            '<option>c</option>' +\n          '</select>'\n      }).$mount()\n      var opts = vm.$el.options\n      expect(opts[0].selected).toBe(false)\n      expect(opts[1].selected).toBe(true)\n      expect(opts[2].selected).toBe(false)\n      vm.test = ['a', 'c']\n      waitForUpdate(() => {\n        expect(opts[0].selected).toBe(true)\n        expect(opts[1].selected).toBe(false)\n        expect(opts[2].selected).toBe(true)\n        opts[0].selected = false\n        opts[1].selected = true\n        triggerEvent(vm.$el, 'change')\n        expect(vm.test).toEqual(['b', 'c'])\n      }).then(done)\n    })\n\n    it('multiple + v-for', done => {\n      const vm = new Vue({\n        data: {\n          test: ['b'],\n          opts: ['a', 'b', 'c']\n        },\n        template:\n          '<select v-model=\"test\" multiple>' +\n            '<option v-for=\"o in opts\">{{ o }}</option>' +\n          '</select>'\n      }).$mount()\n      var opts = vm.$el.options\n      expect(opts[0].selected).toBe(false)\n      expect(opts[1].selected).toBe(true)\n      expect(opts[2].selected).toBe(false)\n      vm.test = ['a', 'c']\n      waitForUpdate(() => {\n        expect(opts[0].selected).toBe(true)\n        expect(opts[1].selected).toBe(false)\n        expect(opts[2].selected).toBe(true)\n        opts[0].selected = false\n        opts[1].selected = true\n        triggerEvent(vm.$el, 'change')\n        expect(vm.test).toEqual(['b', 'c'])\n        // update v-for opts\n        vm.opts = ['c', 'd']\n      }).then(() => {\n        expect(opts[0].selected).toBe(true)\n        expect(opts[1].selected).toBe(false)\n        expect(vm.test).toEqual(['c']) // should remove 'd' which no longer has a matching option\n      }).then(done)\n    })\n  }\n\n  it('should work with multiple binding', (done) => {\n    const spy = jasmine.createSpy()\n    const vm = new Vue({\n      data: {\n        isMultiple: true,\n        selections: ['1']\n      },\n      template:\n        '<select v-model=\"selections\" :multiple=\"isMultiple\">' +\n          '<option value=\"1\">item 1</option>' +\n          '<option value=\"2\">item 2</option>' +\n        '</select>',\n      watch: {\n        selections: spy\n      }\n    }).$mount()\n    document.body.appendChild(vm.$el)\n    vm.$el.options[1].selected = true\n    triggerEvent(vm.$el, 'change')\n    waitForUpdate(() => {\n      expect(spy).toHaveBeenCalled()\n      expect(vm.selections).toEqual(['1', '2'])\n    }).then(done)\n  })\n\n  it('should not have multiple attr with falsy values except \\'\\'', () => {\n    const vm = new Vue({\n      template:\n        '<div>' +\n          '<select id=\"undefined\" :multiple=\"undefined\"></select>' +\n          '<select id=\"null\" :multiple=\"null\"></select>' +\n          '<select id=\"false\" :multiple=\"false\"></select>' +\n          '<select id=\"string\" :multiple=\"\\'\\'\"></select>' +\n        '</div>'\n    }).$mount()\n    expect(vm.$el.querySelector('#undefined').multiple).toEqual(false)\n    expect(vm.$el.querySelector('#null').multiple).toEqual(false)\n    expect(vm.$el.querySelector('#false').multiple).toEqual(false)\n    expect(vm.$el.querySelector('#string').multiple).toEqual(true)\n  })\n\n  it('multiple with static template', () => {\n    const vm = new Vue({\n      template:\n      '<select multiple>' +\n        '<option selected>a</option>' +\n        '<option selected>b</option>' +\n        '<option selected>c</option>' +\n      '</select>'\n    }).$mount()\n    var opts = vm.$el.options\n    expect(opts[0].selected).toBe(true)\n    expect(opts[1].selected).toBe(true)\n    expect(opts[2].selected).toBe(true)\n  })\n\n  it('multiple selects', (done) => {\n    const spy = jasmine.createSpy()\n    const vm = new Vue({\n      data: {\n        selections: ['', ''],\n        selectBoxes: [\n          [\n            { value: 'foo', text: 'foo' },\n            { value: 'bar', text: 'bar' }\n          ],\n          [\n            { value: 'day', text: 'day' },\n            { value: 'night', text: 'night' }\n          ]\n        ]\n      },\n      watch: {\n        selections: spy\n      },\n      template:\n        '<div>' +\n          '<select v-for=\"(item, index) in selectBoxes\" v-model=\"selections[index]\">' +\n            '<option v-for=\"element in item\" v-bind:value=\"element.value\" v-text=\"element.text\"></option>' +\n          '</select>' +\n          '<span ref=\"rs\">{{selections}}</span>' +\n        '</div>'\n    }).$mount()\n    document.body.appendChild(vm.$el)\n    var selects = vm.$el.getElementsByTagName('select')\n    var select0 = selects[0]\n    select0.options[0].selected = true\n    triggerEvent(select0, 'change')\n    waitForUpdate(() => {\n      expect(spy).toHaveBeenCalled()\n      expect(vm.selections).toEqual(['foo', ''])\n    }).then(done)\n  })\n\n  it('.number modifier', () => {\n    const vm = new Vue({\n      data: {\n        test: 2\n      },\n      template:\n        '<select v-model.number=\"test\">' +\n          '<option value=\"1\">a</option>' +\n          '<option :value=\"2\">b</option>' +\n          '<option :value=\"3\">c</option>' +\n        '</select>'\n    }).$mount()\n    document.body.appendChild(vm.$el)\n    updateSelect(vm.$el, '1')\n    triggerEvent(vm.$el, 'change')\n    expect(vm.test).toBe(1)\n  })\n\n  it('should respect different primitive type value', (done) => {\n    const vm = new Vue({\n      data: {\n        test: 0\n      },\n      template:\n        '<select v-model.number=\"test\">' +\n          '<option value=\"\">a</option>' +\n          '<option value=\"0\">b</option>' +\n          '<option value=\"1\">c</option>' +\n          '<option value=\"false\">c</option>' +\n          '<option value=\"true\">c</option>' +\n        '</select>'\n    }).$mount()\n    var opts = vm.$el.options\n    expect(opts[0].selected).toBe(false)\n    expect(opts[1].selected).toBe(true)\n    expect(opts[2].selected).toBe(false)\n    expect(opts[3].selected).toBe(false)\n    expect(opts[4].selected).toBe(false)\n    vm.test = 1\n    waitForUpdate(() => {\n      expect(opts[0].selected).toBe(false)\n      expect(opts[1].selected).toBe(false)\n      expect(opts[2].selected).toBe(true)\n      expect(opts[3].selected).toBe(false)\n      expect(opts[4].selected).toBe(false)\n      vm.test = ''\n    }).then(() => {\n      expect(opts[0].selected).toBe(true)\n      expect(opts[1].selected).toBe(false)\n      expect(opts[2].selected).toBe(false)\n      expect(opts[3].selected).toBe(false)\n      expect(opts[4].selected).toBe(false)\n      vm.test = false\n    }).then(() => {\n      expect(opts[0].selected).toBe(false)\n      expect(opts[1].selected).toBe(false)\n      expect(opts[2].selected).toBe(false)\n      expect(opts[3].selected).toBe(true)\n      expect(opts[4].selected).toBe(false)\n      vm.test = true\n    }).then(() => {\n      expect(opts[0].selected).toBe(false)\n      expect(opts[1].selected).toBe(false)\n      expect(opts[2].selected).toBe(false)\n      expect(opts[3].selected).toBe(false)\n      expect(opts[4].selected).toBe(true)\n    }).then(done)\n  })\n\n  it('should warn multiple with non-Array value', done => {\n    new Vue({\n      data: {\n        test: 'meh'\n      },\n      template:\n        '<select v-model=\"test\" multiple></select>'\n    }).$mount()\n    // IE warns on a setTimeout as well\n    setTimeout(() => {\n      expect('<select multiple v-model=\"test\"> expects an Array value for its binding, but got String')\n        .toHaveBeenWarned()\n      done()\n    }, 0)\n  })\n\n  it('should work with option value that has circular reference', done => {\n    const circular = {}\n    circular.self = circular\n\n    const vm = new Vue({\n      data: {\n        test: 'b',\n        circular\n      },\n      template:\n        '<select v-model=\"test\">' +\n          '<option :value=\"circular\">a</option>' +\n          '<option>b</option>' +\n          '<option>c</option>' +\n        '</select>'\n    }).$mount()\n    document.body.appendChild(vm.$el)\n    expect(vm.test).toBe('b')\n    expect(vm.$el.value).toBe('b')\n    expect(vm.$el.childNodes[1].selected).toBe(true)\n    vm.test = circular\n    waitForUpdate(function () {\n      expect(vm.$el.childNodes[0].selected).toBe(true)\n    }).then(done)\n  })\n})\n"
  },
  {
    "path": "test/unit/features/directives/model-text.spec.js",
    "content": "import Vue from 'vue'\nimport { isIE9, isAndroid } from 'core/util/env'\n\ndescribe('Directive v-model text', () => {\n  it('should update value both ways', done => {\n    const vm = new Vue({\n      data: {\n        test: 'b'\n      },\n      template: '<input v-model=\"test\">'\n    }).$mount()\n    expect(vm.$el.value).toBe('b')\n    vm.test = 'a'\n    waitForUpdate(() => {\n      expect(vm.$el.value).toBe('a')\n      vm.$el.value = 'c'\n      triggerEvent(vm.$el, 'input')\n      expect(vm.test).toBe('c')\n    }).then(done)\n  })\n\n  it('.lazy modifier', () => {\n    const vm = new Vue({\n      data: {\n        test: 'b'\n      },\n      template: '<input v-model.lazy=\"test\">'\n    }).$mount()\n    expect(vm.$el.value).toBe('b')\n    expect(vm.test).toBe('b')\n    vm.$el.value = 'c'\n    triggerEvent(vm.$el, 'input')\n    expect(vm.test).toBe('b')\n    triggerEvent(vm.$el, 'change')\n    expect(vm.test).toBe('c')\n  })\n\n  it('.number modifier', () => {\n    const vm = new Vue({\n      data: {\n        test: 1\n      },\n      template: '<input v-model.number=\"test\">'\n    }).$mount()\n    expect(vm.test).toBe(1)\n    vm.$el.value = '2'\n    triggerEvent(vm.$el, 'input')\n    expect(vm.test).toBe(2)\n    // should let strings pass through\n    vm.$el.value = 'f'\n    triggerEvent(vm.$el, 'input')\n    expect(vm.test).toBe('f')\n  })\n\n  it('.trim modifier', () => {\n    const vm = new Vue({\n      data: {\n        test: 'hi'\n      },\n      template: '<input v-model.trim=\"test\">'\n    }).$mount()\n    expect(vm.test).toBe('hi')\n    vm.$el.value = ' what '\n    triggerEvent(vm.$el, 'input')\n    expect(vm.test).toBe('what')\n  })\n\n  it('.number focus and typing', (done) => {\n    const vm = new Vue({\n      data: {\n        test: 0,\n        update: 0\n      },\n      template:\n        '<div>' +\n          '<input ref=\"input\" v-model.number=\"test\">{{ update }}' +\n          '<input ref=\"blur\">' +\n        '</div>'\n    }).$mount()\n    document.body.appendChild(vm.$el)\n    vm.$refs.input.focus()\n    expect(vm.test).toBe(0)\n    vm.$refs.input.value = '1.0'\n    triggerEvent(vm.$refs.input, 'input')\n    expect(vm.test).toBe(1)\n    vm.update++\n    waitForUpdate(() => {\n      expect(vm.$refs.input.value).toBe('1.0')\n      vm.$refs.blur.focus()\n      vm.update++\n    }).then(() => {\n      expect(vm.$refs.input.value).toBe('1')\n    }).then(done)\n  })\n\n  it('.trim focus and typing', (done) => {\n    const vm = new Vue({\n      data: {\n        test: 'abc',\n        update: 0\n      },\n      template:\n        '<div>' +\n          '<input ref=\"input\" v-model.trim=\"test\" type=\"text\">{{ update }}' +\n          '<input ref=\"blur\"/>' +\n        '</div>'\n    }).$mount()\n    document.body.appendChild(vm.$el)\n    vm.$refs.input.focus()\n    vm.$refs.input.value = ' abc '\n    triggerEvent(vm.$refs.input, 'input')\n    expect(vm.test).toBe('abc')\n    vm.update++\n    waitForUpdate(() => {\n      expect(vm.$refs.input.value).toBe(' abc ')\n      vm.$refs.blur.focus()\n      vm.update++\n    }).then(() => {\n      expect(vm.$refs.input.value).toBe('abc')\n    }).then(done)\n  })\n\n  it('multiple inputs', (done) => {\n    const spy = jasmine.createSpy()\n    const vm = new Vue({\n      data: {\n        selections: [[1, 2, 3], [4, 5]],\n        inputList: [\n          {\n            name: 'questionA',\n            data: ['a', 'b', 'c']\n          },\n          {\n            name: 'questionB',\n            data: ['1', '2']\n          }\n        ]\n      },\n      watch: {\n        selections: spy\n      },\n      template:\n        '<div>' +\n          '<div v-for=\"(inputGroup, idx) in inputList\">' +\n            '<div>' +\n              '<span v-for=\"(item, index) in inputGroup.data\">' +\n                '<input v-bind:name=\"item\" type=\"text\" v-model.number=\"selections[idx][index]\" v-bind:id=\"idx+\\'-\\'+index\"/>' +\n                '<label>{{item}}</label>' +\n              '</span>' +\n            '</div>' +\n          '</div>' +\n          '<span ref=\"rs\">{{selections}}</span>' +\n        '</div>'\n    }).$mount()\n    var inputs = vm.$el.getElementsByTagName('input')\n    inputs[1].value = 'test'\n    triggerEvent(inputs[1], 'input')\n    waitForUpdate(() => {\n      expect(spy).toHaveBeenCalled()\n      expect(vm.selections).toEqual([[1, 'test', 3], [4, 5]])\n    }).then(done)\n  })\n\n  if (isIE9) {\n    it('IE9 selectionchange', done => {\n      const vm = new Vue({\n        data: {\n          test: 'foo'\n        },\n        template: '<input v-model=\"test\">'\n      }).$mount()\n      const input = vm.$el\n      input.value = 'bar'\n      document.body.appendChild(input)\n      input.focus()\n      triggerEvent(input, 'selectionchange')\n      waitForUpdate(() => {\n        expect(vm.test).toBe('bar')\n        input.value = 'a'\n        triggerEvent(input, 'selectionchange')\n        expect(vm.test).toBe('a')\n      }).then(done)\n    })\n  }\n\n  if (!isAndroid) {\n    it('compositionevents', function (done) {\n      const vm = new Vue({\n        data: {\n          test: 'foo'\n        },\n        template: '<input v-model=\"test\">'\n      }).$mount()\n      const input = vm.$el\n      triggerEvent(input, 'compositionstart')\n      input.value = 'baz'\n      // input before composition unlock should not call set\n      triggerEvent(input, 'input')\n      expect(vm.test).toBe('foo')\n      // after composition unlock it should work\n      triggerEvent(input, 'compositionend')\n      triggerEvent(input, 'input')\n      expect(vm.test).toBe('baz')\n      done()\n    })\n  }\n\n  it('warn invalid tag', () => {\n    new Vue({\n      data: {\n        test: 'foo'\n      },\n      template: '<div v-model=\"test\"></div>'\n    }).$mount()\n    expect('<div v-model=\"test\">: v-model is not supported on this element type').toHaveBeenWarned()\n  })\n\n  // #3468\n  it('should have higher priority than user v-on events', () => {\n    const spy = jasmine.createSpy()\n    const vm = new Vue({\n      data: {\n        a: 'a'\n      },\n      template: '<input v-model=\"a\" @input=\"onInput\">',\n      methods: {\n        onInput (e) {\n          spy(e.target.value)\n        }\n      }\n    }).$mount()\n    vm.$el.value = 'b'\n    triggerEvent(vm.$el, 'input')\n    expect(spy).toHaveBeenCalledWith('b')\n  })\n\n  it('warn binding to v-for alias', () => {\n    new Vue({\n      data: {\n        strings: ['hi']\n      },\n      template: `\n        <div>\n          <div v-for=\"str in strings\">\n            <input v-model=\"str\">\n          </div>\n        </div>\n      `\n    }).$mount()\n    expect('You are binding v-model directly to a v-for iteration alias').toHaveBeenWarned()\n  })\n\n  if (!isAndroid) {\n    it('does not trigger extra input events with single compositionend', () => {\n      const spy = jasmine.createSpy()\n      const vm = new Vue({\n        data: {\n          a: 'a'\n        },\n        template: '<input v-model=\"a\" @input=\"onInput\">',\n        methods: {\n          onInput (e) {\n            spy(e.target.value)\n          }\n        }\n      }).$mount()\n      expect(spy.calls.count()).toBe(0)\n      vm.$el.value = 'b'\n      triggerEvent(vm.$el, 'input')\n      expect(spy.calls.count()).toBe(1)\n      triggerEvent(vm.$el, 'compositionend')\n      expect(spy.calls.count()).toBe(1)\n    })\n\n    it('triggers extra input on compositionstart + end', () => {\n      const spy = jasmine.createSpy()\n      const vm = new Vue({\n        data: {\n          a: 'a'\n        },\n        template: '<input v-model=\"a\" @input=\"onInput\">',\n        methods: {\n          onInput (e) {\n            spy(e.target.value)\n          }\n        }\n      }).$mount()\n      expect(spy.calls.count()).toBe(0)\n      vm.$el.value = 'b'\n      triggerEvent(vm.$el, 'input')\n      expect(spy.calls.count()).toBe(1)\n      triggerEvent(vm.$el, 'compositionstart')\n      triggerEvent(vm.$el, 'compositionend')\n      expect(spy.calls.count()).toBe(2)\n    })\n  }\n})\n"
  },
  {
    "path": "test/unit/features/directives/on.spec.js",
    "content": "import Vue from 'vue'\nimport { supportsPassive } from 'core/util/env'\n\ndescribe('Directive v-on', () => {\n  let vm, spy, el\n\n  beforeEach(() => {\n    vm = null\n    spy = jasmine.createSpy()\n    el = document.createElement('div')\n    document.body.appendChild(el)\n  })\n\n  afterEach(() => {\n    if (vm) {\n      document.body.removeChild(vm.$el)\n    }\n  })\n\n  it('should bind event to a method', () => {\n    vm = new Vue({\n      el,\n      template: '<div v-on:click=\"foo\"></div>',\n      methods: { foo: spy }\n    })\n    triggerEvent(vm.$el, 'click')\n    expect(spy.calls.count()).toBe(1)\n\n    const args = spy.calls.allArgs()\n    const event = args[0] && args[0][0] || {}\n    expect(event.type).toBe('click')\n  })\n\n  it('should bind event to a inline statement', () => {\n    vm = new Vue({\n      el,\n      template: '<div v-on:click=\"foo(1,2,3,$event)\"></div>',\n      methods: { foo: spy }\n    })\n    triggerEvent(vm.$el, 'click')\n    expect(spy.calls.count()).toBe(1)\n\n    const args = spy.calls.allArgs()\n    const firstArgs = args[0]\n    expect(firstArgs.length).toBe(4)\n    expect(firstArgs[0]).toBe(1)\n    expect(firstArgs[1]).toBe(2)\n    expect(firstArgs[2]).toBe(3)\n    expect(firstArgs[3].type).toBe('click')\n  })\n\n  it('should support inline function expression', () => {\n    const spy = jasmine.createSpy()\n    vm = new Vue({\n      el,\n      template: `<div class=\"test\" @click=\"function (e) { log(e.target.className) }\"></div>`,\n      methods: {\n        log: spy\n      }\n    }).$mount()\n    triggerEvent(vm.$el, 'click')\n    expect(spy).toHaveBeenCalledWith('test')\n  })\n\n  it('should support shorthand', () => {\n    vm = new Vue({\n      el,\n      template: '<a href=\"#test\" @click.prevent=\"foo\"></a>',\n      methods: { foo: spy }\n    })\n    triggerEvent(vm.$el, 'click')\n    expect(spy.calls.count()).toBe(1)\n  })\n\n  it('should support stop propagation', () => {\n    vm = new Vue({\n      el,\n      template: `\n        <div @click.stop=\"foo\"></div>\n      `,\n      methods: { foo: spy }\n    })\n    const hash = window.location.hash\n    triggerEvent(vm.$el, 'click')\n    expect(window.location.hash).toBe(hash)\n  })\n\n  it('should support prevent default', () => {\n    vm = new Vue({\n      el,\n      template: `\n        <input type=\"checkbox\" ref=\"input\" @click.prevent=\"foo\">\n      `,\n      methods: {\n        foo ($event) {\n          spy($event.defaultPrevented)\n        }\n      }\n    })\n    vm.$refs.input.checked = false\n    triggerEvent(vm.$refs.input, 'click')\n    expect(spy).toHaveBeenCalledWith(true)\n  })\n\n  it('should support capture', () => {\n    const callOrder = []\n    vm = new Vue({\n      el,\n      template: `\n        <div @click.capture=\"foo\">\n          <div @click=\"bar\"></div>\n        </div>\n      `,\n      methods: {\n        foo () { callOrder.push(1) },\n        bar () { callOrder.push(2) }\n      }\n    })\n    triggerEvent(vm.$el.firstChild, 'click')\n    expect(callOrder.toString()).toBe('1,2')\n  })\n\n  it('should support once', () => {\n    vm = new Vue({\n      el,\n      template: `\n        <div @click.once=\"foo\">\n        </div>\n      `,\n      methods: { foo: spy }\n    })\n    triggerEvent(vm.$el, 'click')\n    expect(spy.calls.count()).toBe(1)\n    triggerEvent(vm.$el, 'click')\n    expect(spy.calls.count()).toBe(1) // should no longer trigger\n  })\n\n  // #4655\n  it('should handle .once on multiple elements properly', () => {\n    vm = new Vue({\n      el,\n      template: `\n        <div>\n          <button ref=\"one\" @click.once=\"foo\">one</button>\n          <button ref=\"two\" @click.once=\"foo\">two</button>\n        </div>\n      `,\n      methods: { foo: spy }\n    })\n    triggerEvent(vm.$refs.one, 'click')\n    expect(spy.calls.count()).toBe(1)\n    triggerEvent(vm.$refs.one, 'click')\n    expect(spy.calls.count()).toBe(1)\n    triggerEvent(vm.$refs.two, 'click')\n    expect(spy.calls.count()).toBe(2)\n    triggerEvent(vm.$refs.one, 'click')\n    triggerEvent(vm.$refs.two, 'click')\n    expect(spy.calls.count()).toBe(2)\n  })\n\n  it('should support capture and once', () => {\n    const callOrder = []\n    vm = new Vue({\n      el,\n      template: `\n        <div @click.capture.once=\"foo\">\n          <div @click=\"bar\"></div>\n        </div>\n      `,\n      methods: {\n        foo () { callOrder.push(1) },\n        bar () { callOrder.push(2) }\n      }\n    })\n    triggerEvent(vm.$el.firstChild, 'click')\n    expect(callOrder.toString()).toBe('1,2')\n    triggerEvent(vm.$el.firstChild, 'click')\n    expect(callOrder.toString()).toBe('1,2,2')\n  })\n\n  // #4846\n  it('should support once and other modifiers', () => {\n    vm = new Vue({\n      el,\n      template: `<div @click.once.self=\"foo\"><span/></div>`,\n      methods: { foo: spy }\n    })\n    triggerEvent(vm.$el.firstChild, 'click')\n    expect(spy).not.toHaveBeenCalled()\n    triggerEvent(vm.$el, 'click')\n    expect(spy).toHaveBeenCalled()\n    triggerEvent(vm.$el, 'click')\n    expect(spy.calls.count()).toBe(1)\n  })\n\n  it('should support keyCode', () => {\n    vm = new Vue({\n      el,\n      template: `<input @keyup.enter=\"foo\">`,\n      methods: { foo: spy }\n    })\n    triggerEvent(vm.$el, 'keyup', e => {\n      e.keyCode = 13\n    })\n    expect(spy).toHaveBeenCalled()\n  })\n\n  it('should support number keyCode', () => {\n    vm = new Vue({\n      el,\n      template: `<input @keyup.13=\"foo\">`,\n      methods: { foo: spy }\n    })\n    triggerEvent(vm.$el, 'keyup', e => {\n      e.keyCode = 13\n    })\n    expect(spy).toHaveBeenCalled()\n  })\n\n  it('should support mouse modifier', () => {\n    const left = 0\n    const middle = 1\n    const right = 2\n    const spyLeft = jasmine.createSpy()\n    const spyMiddle = jasmine.createSpy()\n    const spyRight = jasmine.createSpy()\n\n    vm = new Vue({\n      el,\n      template: `\n        <div>\n          <div ref=\"left\" @mousedown.left=\"foo\">left</div>\n          <div ref=\"right\" @mousedown.right=\"foo1\">right</div>\n          <div ref=\"middle\" @mousedown.middle=\"foo2\">right</div>\n        </div>\n      `,\n      methods: {\n        foo: spyLeft,\n        foo1: spyRight,\n        foo2: spyMiddle\n      }\n    })\n\n    triggerEvent(vm.$refs.left, 'mousedown', e => { e.button = right })\n    triggerEvent(vm.$refs.left, 'mousedown', e => { e.button = middle })\n    expect(spyLeft).not.toHaveBeenCalled()\n    triggerEvent(vm.$refs.left, 'mousedown', e => { e.button = left })\n    expect(spyLeft).toHaveBeenCalled()\n\n    triggerEvent(vm.$refs.right, 'mousedown', e => { e.button = left })\n    triggerEvent(vm.$refs.right, 'mousedown', e => { e.button = middle })\n    expect(spyRight).not.toHaveBeenCalled()\n    triggerEvent(vm.$refs.right, 'mousedown', e => { e.button = right })\n    expect(spyRight).toHaveBeenCalled()\n\n    triggerEvent(vm.$refs.middle, 'mousedown', e => { e.button = left })\n    triggerEvent(vm.$refs.middle, 'mousedown', e => { e.button = right })\n    expect(spyMiddle).not.toHaveBeenCalled()\n    triggerEvent(vm.$refs.middle, 'mousedown', e => { e.button = middle })\n    expect(spyMiddle).toHaveBeenCalled()\n  })\n\n  it('should support custom keyCode', () => {\n    Vue.config.keyCodes.test = 1\n    vm = new Vue({\n      el,\n      template: `<input @keyup.test=\"foo\">`,\n      methods: { foo: spy }\n    })\n    triggerEvent(vm.$el, 'keyup', e => {\n      e.keyCode = 1\n    })\n    expect(spy).toHaveBeenCalled()\n    Vue.config.keyCodes = Object.create(null)\n  })\n\n  it('should override build-in keyCode', () => {\n    Vue.config.keyCodes.up = [1, 87]\n    vm = new Vue({\n      el,\n      template: `<input @keyup.up=\"foo\" @keyup.down=\"foo\">`,\n      methods: { foo: spy }\n    })\n    triggerEvent(vm.$el, 'keyup', e => {\n      e.keyCode = 87\n    })\n    expect(spy).toHaveBeenCalled()\n    triggerEvent(vm.$el, 'keyup', e => {\n      e.keyCode = 1\n    })\n    expect(spy).toHaveBeenCalledTimes(2)\n    // should not affect build-in down keycode\n    triggerEvent(vm.$el, 'keyup', e => {\n      e.keyCode = 40\n    })\n    expect(spy).toHaveBeenCalledTimes(3)\n    Vue.config.keyCodes = Object.create(null)\n  })\n\n  it('should bind to a child component', () => {\n    vm = new Vue({\n      el,\n      template: '<bar @custom=\"foo\"></bar>',\n      methods: { foo: spy },\n      components: {\n        bar: {\n          template: '<span>Hello</span>'\n        }\n      }\n    })\n    vm.$children[0].$emit('custom', 'foo', 'bar')\n    expect(spy).toHaveBeenCalledWith('foo', 'bar')\n  })\n\n  it('should be able to bind native events for a child component', () => {\n    vm = new Vue({\n      el,\n      template: '<bar @click.native=\"foo\"></bar>',\n      methods: { foo: spy },\n      components: {\n        bar: {\n          template: '<span>Hello</span>'\n        }\n      }\n    })\n    vm.$children[0].$emit('click')\n    expect(spy).not.toHaveBeenCalled()\n    triggerEvent(vm.$children[0].$el, 'click')\n    expect(spy).toHaveBeenCalled()\n  })\n\n  it('.once modifier should work with child components', () => {\n    vm = new Vue({\n      el,\n      template: '<bar @custom.once=\"foo\"></bar>',\n      methods: { foo: spy },\n      components: {\n        bar: {\n          template: '<span>Hello</span>'\n        }\n      }\n    })\n    vm.$children[0].$emit('custom')\n    expect(spy.calls.count()).toBe(1)\n    vm.$children[0].$emit('custom')\n    expect(spy.calls.count()).toBe(1) // should not be called again\n  })\n\n  it('remove listener', done => {\n    const spy2 = jasmine.createSpy('remove listener')\n    vm = new Vue({\n      el,\n      methods: { foo: spy, bar: spy2 },\n      data: {\n        ok: true\n      },\n      render (h) {\n        return this.ok\n          ? h('input', { on: { click: this.foo }})\n          : h('input', { on: { input: this.bar }})\n      }\n    })\n    triggerEvent(vm.$el, 'click')\n    expect(spy.calls.count()).toBe(1)\n    expect(spy2.calls.count()).toBe(0)\n    vm.ok = false\n    waitForUpdate(() => {\n      triggerEvent(vm.$el, 'click')\n      expect(spy.calls.count()).toBe(1) // should no longer trigger\n      triggerEvent(vm.$el, 'input')\n      expect(spy2.calls.count()).toBe(1)\n    }).then(done)\n  })\n\n  it('remove capturing listener', done => {\n    const spy2 = jasmine.createSpy('remove listener')\n    vm = new Vue({\n      el,\n      methods: { foo: spy, bar: spy2, stopped (ev) { ev.stopPropagation() } },\n      data: {\n        ok: true\n      },\n      render (h) {\n        return this.ok\n          ? h('div', { on: { '!click': this.foo }}, [h('div', { on: { click: this.stopped }})])\n          : h('div', { on: { mouseOver: this.bar }}, [h('div')])\n      }\n    })\n    triggerEvent(vm.$el.firstChild, 'click')\n    expect(spy.calls.count()).toBe(1)\n    expect(spy2.calls.count()).toBe(0)\n    vm.ok = false\n    waitForUpdate(() => {\n      triggerEvent(vm.$el.firstChild, 'click')\n      expect(spy.calls.count()).toBe(1) // should no longer trigger\n      triggerEvent(vm.$el, 'mouseOver')\n      expect(spy2.calls.count()).toBe(1)\n    }).then(done)\n  })\n\n  it('remove once listener', done => {\n    const spy2 = jasmine.createSpy('remove listener')\n    vm = new Vue({\n      el,\n      methods: { foo: spy, bar: spy2 },\n      data: {\n        ok: true\n      },\n      render (h) {\n        return this.ok\n          ? h('input', { on: { '~click': this.foo }})\n          : h('input', { on: { input: this.bar }})\n      }\n    })\n    triggerEvent(vm.$el, 'click')\n    expect(spy.calls.count()).toBe(1)\n    triggerEvent(vm.$el, 'click')\n    expect(spy.calls.count()).toBe(1) // should no longer trigger\n    expect(spy2.calls.count()).toBe(0)\n    vm.ok = false\n    waitForUpdate(() => {\n      triggerEvent(vm.$el, 'click')\n      expect(spy.calls.count()).toBe(1) // should no longer trigger\n      triggerEvent(vm.$el, 'input')\n      expect(spy2.calls.count()).toBe(1)\n    }).then(done)\n  })\n\n  it('remove capturing and once listener', done => {\n    const spy2 = jasmine.createSpy('remove listener')\n    vm = new Vue({\n      el,\n      methods: { foo: spy, bar: spy2, stopped (ev) { ev.stopPropagation() } },\n      data: {\n        ok: true\n      },\n      render (h) {\n        return this.ok\n          ? h('div', { on: { '~!click': this.foo }}, [h('div', { on: { click: this.stopped }})])\n          : h('div', { on: { mouseOver: this.bar }}, [h('div')])\n      }\n    })\n    triggerEvent(vm.$el.firstChild, 'click')\n    expect(spy.calls.count()).toBe(1)\n    triggerEvent(vm.$el.firstChild, 'click')\n    expect(spy.calls.count()).toBe(1) // should no longer trigger\n    expect(spy2.calls.count()).toBe(0)\n    vm.ok = false\n    waitForUpdate(() => {\n      triggerEvent(vm.$el.firstChild, 'click')\n      expect(spy.calls.count()).toBe(1) // should no longer trigger\n      triggerEvent(vm.$el, 'mouseOver')\n      expect(spy2.calls.count()).toBe(1)\n    }).then(done)\n  })\n\n  it('remove listener on child component', done => {\n    const spy2 = jasmine.createSpy('remove listener')\n    vm = new Vue({\n      el,\n      methods: { foo: spy, bar: spy2 },\n      data: {\n        ok: true\n      },\n      components: {\n        test: {\n          template: '<div></div>'\n        }\n      },\n      render (h) {\n        return this.ok\n          ? h('test', { on: { foo: this.foo }})\n          : h('test', { on: { bar: this.bar }})\n      }\n    })\n    vm.$children[0].$emit('foo')\n    expect(spy.calls.count()).toBe(1)\n    expect(spy2.calls.count()).toBe(0)\n    vm.ok = false\n    waitForUpdate(() => {\n      vm.$children[0].$emit('foo')\n      expect(spy.calls.count()).toBe(1) // should no longer trigger\n      vm.$children[0].$emit('bar')\n      expect(spy2.calls.count()).toBe(1)\n    }).then(done)\n  })\n\n  it('warn missing handlers', () => {\n    vm = new Vue({\n      el,\n      data: { none: null },\n      template: `<div @click=\"none\"></div>`\n    })\n    expect(`Invalid handler for event \"click\": got null`).toHaveBeenWarned()\n    expect(() => {\n      triggerEvent(vm.$el, 'click')\n    }).not.toThrow()\n  })\n\n  // Github Issue #5046\n  it('should support keyboard modifier', () => {\n    const spyLeft = jasmine.createSpy()\n    const spyRight = jasmine.createSpy()\n    const spyUp = jasmine.createSpy()\n    const spyDown = jasmine.createSpy()\n    vm = new Vue({\n      el,\n      template: `\n        <div>\n          <input ref=\"left\" @keydown.left=\"foo\"></input>\n          <input ref=\"right\" @keydown.right=\"foo1\"></input>\n          <input ref=\"up\" @keydown.up=\"foo2\"></input>\n          <input ref=\"down\" @keydown.down=\"foo3\"></input>\n        </div>\n      `,\n      methods: {\n        foo: spyLeft,\n        foo1: spyRight,\n        foo2: spyUp,\n        foo3: spyDown\n      }\n    })\n    triggerEvent(vm.$refs.left, 'keydown', e => { e.keyCode = 37 })\n    triggerEvent(vm.$refs.left, 'keydown', e => { e.keyCode = 39 })\n\n    triggerEvent(vm.$refs.right, 'keydown', e => { e.keyCode = 39 })\n    triggerEvent(vm.$refs.right, 'keydown', e => { e.keyCode = 38 })\n\n    triggerEvent(vm.$refs.up, 'keydown', e => { e.keyCode = 38 })\n    triggerEvent(vm.$refs.up, 'keydown', e => { e.keyCode = 37 })\n\n    triggerEvent(vm.$refs.down, 'keydown', e => { e.keyCode = 40 })\n    triggerEvent(vm.$refs.down, 'keydown', e => { e.keyCode = 39 })\n\n    expect(spyLeft.calls.count()).toBe(1)\n    expect(spyRight.calls.count()).toBe(1)\n    expect(spyUp.calls.count()).toBe(1)\n    expect(spyDown.calls.count()).toBe(1)\n  })\n\n  // This test case should only run when the test browser supports passive.\n  if (supportsPassive) {\n    it('should support passive', () => {\n      vm = new Vue({\n        el,\n        template: `\n          <div>\n            <input type=\"checkbox\" ref=\"normal\" @click=\"foo\"/>\n            <input type=\"checkbox\" ref=\"passive\" @click.passive=\"foo\"/>\n            <input type=\"checkbox\" ref=\"exclusive\" @click.prevent.passive/>\n          </div>\n        `,\n        methods: {\n          foo (e) {\n            e.preventDefault()\n          }\n        }\n      })\n\n      vm.$refs.normal.checked = false\n      vm.$refs.passive.checked = false\n      vm.$refs.exclusive.checked = false\n      vm.$refs.normal.click()\n      vm.$refs.passive.click()\n      vm.$refs.exclusive.click()\n      expect(vm.$refs.normal.checked).toBe(false)\n      expect(vm.$refs.passive.checked).toBe(true)\n      expect(vm.$refs.exclusive.checked).toBe(true)\n      expect('passive and prevent can\\'t be used together. Passive handler can\\'t prevent default event.').toHaveBeenWarned()\n    })\n  }\n\n  // Github Issues #5146\n  it('should only prevent when match keycode', () => {\n    let prevented = false\n    vm = new Vue({\n      el,\n      template: `\n        <input ref=\"input\" @keydown.enter.prevent=\"foo\">\n      `,\n      methods: {\n        foo ($event) {\n          prevented = $event.defaultPrevented\n        }\n      }\n    })\n\n    triggerEvent(vm.$refs.input, 'keydown', e => { e.keyCode = 32 })\n    expect(prevented).toBe(false)\n    triggerEvent(vm.$refs.input, 'keydown', e => { e.keyCode = 13 })\n    expect(prevented).toBe(true)\n  })\n\n  it('should warn click.right', () => {\n    new Vue({\n      template: `<div @click.right=\"foo\"></div>`,\n      methods: { foo () {} }\n    }).$mount()\n\n    expect(`Use \"contextmenu\" instead`).toHaveBeenWarned()\n  })\n\n  it('object syntax (no argument)', () => {\n    const click = jasmine.createSpy('click')\n    const mouseup = jasmine.createSpy('mouseup')\n    vm = new Vue({\n      el,\n      template: `<button v-on=\"listeners\">foo</button>`,\n      created () {\n        this.listeners = {\n          click,\n          mouseup\n        }\n      }\n    })\n\n    triggerEvent(vm.$el, 'click')\n    expect(click.calls.count()).toBe(1)\n    expect(mouseup.calls.count()).toBe(0)\n\n    triggerEvent(vm.$el, 'mouseup')\n    expect(click.calls.count()).toBe(1)\n    expect(mouseup.calls.count()).toBe(1)\n  })\n\n  it('object syntax (no argument, mixed with normal listeners)', () => {\n    const click1 = jasmine.createSpy('click1')\n    const click2 = jasmine.createSpy('click2')\n    const mouseup = jasmine.createSpy('mouseup')\n    vm = new Vue({\n      el,\n      template: `<button v-on=\"listeners\" @click=\"click2\">foo</button>`,\n      created () {\n        this.listeners = {\n          click: click1,\n          mouseup\n        }\n      },\n      methods: {\n        click2\n      }\n    })\n\n    triggerEvent(vm.$el, 'click')\n    expect(click1.calls.count()).toBe(1)\n    expect(click2.calls.count()).toBe(1)\n    expect(mouseup.calls.count()).toBe(0)\n\n    triggerEvent(vm.$el, 'mouseup')\n    expect(click1.calls.count()).toBe(1)\n    expect(click2.calls.count()).toBe(1)\n    expect(mouseup.calls.count()).toBe(1)\n  })\n\n  it('object syntax (usage in HOC, mixed with native listners)', () => {\n    const click = jasmine.createSpy('click')\n    const mouseup = jasmine.createSpy('mouseup')\n    const mousedown = jasmine.createSpy('mousedown')\n\n    var vm = new Vue({\n      el,\n      template: `\n        <foo-button\n          @click=\"click\"\n          @mousedown=\"mousedown\"\n          @mouseup.native=\"mouseup\">\n        </foo-button>\n      `,\n      methods: {\n        click,\n        mouseup,\n        mousedown\n      },\n      components: {\n        fooButton: {\n          template: `\n            <button v-on=\"$listeners\"></button>\n          `\n        }\n      }\n    })\n\n    triggerEvent(vm.$el, 'click')\n    expect(click.calls.count()).toBe(1)\n    expect(mouseup.calls.count()).toBe(0)\n    expect(mousedown.calls.count()).toBe(0)\n\n    triggerEvent(vm.$el, 'mouseup')\n    expect(click.calls.count()).toBe(1)\n    expect(mouseup.calls.count()).toBe(1)\n    expect(mousedown.calls.count()).toBe(0)\n\n    triggerEvent(vm.$el, 'mousedown')\n    expect(click.calls.count()).toBe(1)\n    expect(mouseup.calls.count()).toBe(1)\n    expect(mousedown.calls.count()).toBe(1)\n  })\n\n  it('warn object syntax with modifier', () => {\n    new Vue({\n      template: `<button v-on.self=\"{}\"></button>`\n    }).$mount()\n    expect(`v-on without argument does not support modifiers`).toHaveBeenWarned()\n  })\n\n  it('warn object syntax with non-object value', () => {\n    new Vue({\n      template: `<button v-on=\"123\"></button>`\n    }).$mount()\n    expect(`v-on without argument expects an Object value`).toHaveBeenWarned()\n  })\n})\n"
  },
  {
    "path": "test/unit/features/directives/once.spec.js",
    "content": "import Vue from 'vue'\n\ndescribe('Directive v-once', () => {\n  it('should not rerender component', done => {\n    const vm = new Vue({\n      template: '<div v-once>{{ a }}</div>',\n      data: { a: 'hello' }\n    }).$mount()\n    expect(vm.$el.innerHTML).toBe('hello')\n    vm.a = 'world'\n    waitForUpdate(() => {\n      expect(vm.$el.innerHTML).toBe('hello')\n    }).then(done)\n  })\n\n  it('should not rerender self and child component', done => {\n    const vm = new Vue({\n      template: `\n        <div v-once>\n          <span>{{ a }}</span>\n          <item :b=\"a\"></item>\n        </div>`,\n      data: { a: 'hello' },\n      components: {\n        item: {\n          template: '<div>{{ b }}</div>',\n          props: ['b']\n        }\n      }\n    }).$mount()\n    expect(vm.$children.length).toBe(1)\n    expect(vm.$el.innerHTML)\n      .toBe('<span>hello</span> <div>hello</div>')\n    vm.a = 'world'\n    waitForUpdate(() => {\n      expect(vm.$el.innerHTML)\n        .toBe('<span>hello</span> <div>hello</div>')\n    }).then(done)\n  })\n\n  it('should rerender parent but not self', done => {\n    const vm = new Vue({\n      template: `\n        <div>\n          <span>{{ a }}</span>\n          <item v-once :b=\"a\"></item>\n        </div>`,\n      data: { a: 'hello' },\n      components: {\n        item: {\n          template: '<div>{{ b }}</div>',\n          props: ['b']\n        }\n      }\n    }).$mount()\n    expect(vm.$children.length).toBe(1)\n    expect(vm.$el.innerHTML)\n      .toBe('<span>hello</span> <div>hello</div>')\n    vm.a = 'world'\n    waitForUpdate(() => {\n      expect(vm.$el.innerHTML)\n        .toBe('<span>world</span> <div>hello</div>')\n    }).then(done)\n  })\n\n  it('should not rerender static sub nodes', done => {\n    const vm = new Vue({\n      template: `\n        <div>\n          <span v-once>{{ a }}</span>\n          <item :b=\"a\"></item>\n          <span>{{ suffix }}</span>\n        </div>`,\n      data: {\n        a: 'hello',\n        suffix: '?'\n      },\n      components: {\n        item: {\n          template: '<div>{{ b }}</div>',\n          props: ['b']\n        }\n      }\n    }).$mount()\n    expect(vm.$el.innerHTML)\n      .toBe('<span>hello</span> <div>hello</div> <span>?</span>')\n    vm.a = 'world'\n    waitForUpdate(() => {\n      expect(vm.$el.innerHTML)\n        .toBe('<span>hello</span> <div>world</div> <span>?</span>')\n      vm.suffix = '!'\n    }).then(() => {\n      expect(vm.$el.innerHTML)\n        .toBe('<span>hello</span> <div>world</div> <span>!</span>')\n    }).then(done)\n  })\n\n  it('should work with v-if', done => {\n    const vm = new Vue({\n      data: {\n        tester: true,\n        yes: 'y',\n        no: 'n'\n      },\n      template: `\n        <div>\n          <div v-if=\"tester\">{{ yes }}</div>\n          <div v-else>{{ no }}</div>\n          <div v-if=\"tester\" v-once>{{ yes }}</div>\n          <div v-else>{{ no }}</div>\n          <div v-if=\"tester\">{{ yes }}</div>\n          <div v-else v-once>{{ no }}</div>\n          <div v-if=\"tester\" v-once>{{ yes }}</div>\n          <div v-else v-once>{{ no }}</div>\n        </div>\n      `\n    }).$mount()\n    expectTextContent(vm, 'yyyy')\n    vm.yes = 'yes'\n    waitForUpdate(() => {\n      expectTextContent(vm, 'yesyyesy')\n      vm.tester = false\n    }).then(() => {\n      expectTextContent(vm, 'nnnn')\n      vm.no = 'no'\n    }).then(() => {\n      expectTextContent(vm, 'nononn')\n    }).then(done)\n  })\n\n  it('should work with v-for', done => {\n    const vm = new Vue({\n      data: {\n        list: [1, 2, 3]\n      },\n      template: `<div><div v-for=\"i in list\" v-once>{{i}}</div></div>`\n    }).$mount()\n    expect(vm.$el.textContent).toBe('123')\n    vm.list.reverse()\n    waitForUpdate(() => {\n      expect(vm.$el.textContent).toBe('123')\n    }).then(done)\n  })\n\n  it('should work inside v-for', done => {\n    const vm = new Vue({\n      data: {\n        list: [\n          { id: 0, text: 'a' },\n          { id: 1, text: 'b' },\n          { id: 2, text: 'c' }\n        ]\n      },\n      template: `\n        <div>\n          <div v-for=\"i in list\" :key=\"i.id\">\n            <div>\n              <span v-once>{{ i.text }}</span><span>{{ i.text }}</span>\n            </div>\n          </div>\n        </div>\n      `\n    }).$mount()\n\n    expect(vm.$el.textContent).toBe('aabbcc')\n\n    vm.list[0].text = 'd'\n    waitForUpdate(() => {\n      expect(vm.$el.textContent).toBe('adbbcc')\n      vm.list[1].text = 'e'\n    }).then(() => {\n      expect(vm.$el.textContent).toBe('adbecc')\n      vm.list.reverse()\n    }).then(() => {\n      expect(vm.$el.textContent).toBe('ccbead')\n    }).then(done)\n  })\n\n  it('should work inside v-for with v-if', done => {\n    const vm = new Vue({\n      data: {\n        list: [\n          { id: 0, text: 'a', tester: true, truthy: 'y' }\n        ]\n      },\n      template: `\n        <div>\n          <div v-for=\"i in list\" :key=\"i.id\">\n              <span v-if=\"i.tester\" v-once>{{ i.truthy }}</span>\n              <span v-else v-once>{{ i.text }}</span>\n              <span v-if=\"i.tester\" v-once>{{ i.truthy }}</span>\n              <span v-else>{{ i.text }}</span>\n              <span v-if=\"i.tester\">{{ i.truthy }}</span>\n              <span v-else v-once>{{ i.text }}</span>\n              <span v-if=\"i.tester\">{{ i.truthy }}</span>\n              <span v-else>{{ i.text }}</span>\n          </div>\n        </div>\n      `\n    }).$mount()\n\n    expectTextContent(vm, 'yyyy')\n\n    vm.list[0].truthy = 'yy'\n    waitForUpdate(() => {\n      expectTextContent(vm, 'yyyyyy')\n      vm.list[0].tester = false\n    }).then(() => {\n      expectTextContent(vm, 'aaaa')\n      vm.list[0].text = 'nn'\n    }).then(() => {\n      expectTextContent(vm, 'annann')\n    }).then(done)\n  })\n\n  it('should work inside v-for with nested v-else', done => {\n    const vm = new Vue({\n      data: {\n        list: [{ id: 0, text: 'a', tester: true, truthy: 'y' }]\n      },\n      template: `\n        <div v-if=\"0\"></div>\n        <div v-else>\n          <div v-for=\"i in list\" :key=\"i.id\">\n            <span v-if=\"i.tester\" v-once>{{ i.truthy }}</span>\n            <span v-else v-once>{{ i.text }}</span>\n          </div>\n        </div>\n      `\n    }).$mount()\n\n    expectTextContent(vm, 'y')\n    vm.list[0].truthy = 'yy'\n    waitForUpdate(() => {\n      expectTextContent(vm, 'y')\n      vm.list[0].tester = false\n    }).then(() => {\n      expectTextContent(vm, 'a')\n      vm.list[0].text = 'nn'\n    }).then(() => {\n      expectTextContent(vm, 'a')\n    }).then(done)\n  })\n\n  it('should work inside v-for with nested v-else-if and v-else', done => {\n    const vm = new Vue({\n      data: {\n        tester: false,\n        list: [{ id: 0, text: 'a', tester: true, truthy: 'y' }]\n      },\n      template: `\n        <div v-if=\"0\"></div>\n        <div v-else-if=\"tester\">\n          <div v-for=\"i in list\" :key=\"i.id\">\n            <span v-if=\"i.tester\" v-once>{{ i.truthy }}</span>\n            <span v-else-if=\"tester\" v-once>{{ i.text }}elseif</span>\n            <span v-else v-once>{{ i.text }}</span>\n          </div>\n        </div>\n        <div v-else>\n          <div v-for=\"i in list\" :key=\"i.id\">\n            <span v-if=\"i.tester\" v-once>{{ i.truthy }}</span>\n            <span v-else-if=\"tester\">{{ i.text }}elseif</span>\n            <span v-else v-once>{{ i.text }}</span>\n          </div>\n        </div>\n      `\n    }).$mount()\n\n    expectTextContent(vm, 'y')\n    vm.list[0].truthy = 'yy'\n    waitForUpdate(() => {\n      expectTextContent(vm, 'y')\n      vm.list[0].tester = false\n    }).then(() => {\n      expectTextContent(vm, 'a')\n      vm.list[0].text = 'nn'\n    }).then(() => {\n      expectTextContent(vm, 'a')\n      vm.tester = true\n    }).then(() => {\n      expectTextContent(vm, 'nnelseif')\n      vm.list[0].text = 'xx'\n    }).then(() => {\n      expectTextContent(vm, 'nnelseif')\n      vm.list[0].tester = true\n    }).then(() => {\n      expectTextContent(vm, 'yy')\n      vm.list[0].truthy = 'nn'\n    }).then(() => {\n      expectTextContent(vm, 'yy')\n    }).then(done)\n  })\n\n  it('should warn inside non-keyed v-for', () => {\n    const vm = new Vue({\n      data: {\n        list: [\n          { id: 0, text: 'a' },\n          { id: 1, text: 'b' },\n          { id: 2, text: 'c' }\n        ]\n      },\n      template: `\n        <div>\n          <div v-for=\"i in list\">\n            <span v-once>{{ i.text }}</span><span>{{ i.text }}</span>\n          </div>\n        </div>\n      `\n    }).$mount()\n\n    expect(vm.$el.textContent).toBe('aabbcc')\n    expect(`v-once can only be used inside v-for that is keyed.`).toHaveBeenWarned()\n  })\n\n  // #4288\n  it('should inherit child reference for v-once', done => {\n    const vm = new Vue({\n      template: `<div>{{a}}<test v-if=\"ok\" v-once></test></div>`,\n      data: {\n        a: 0,\n        ok: true\n      },\n      components: {\n        test: {\n          template: '<div>foo</div>'\n        }\n      }\n    }).$mount()\n    vm.a++ // first update to force a patch\n    waitForUpdate(() => {\n      expect(vm.$el.textContent).toBe('1foo')\n    }).then(() => {\n      vm.ok = false // teardown component with v-once\n    }).then(done) // should not throw\n  })\n})\n\nfunction expectTextContent (vm, text) {\n  expect(vm.$el.textContent.replace(/\\s+/g, '')).toBe(text)\n}\n"
  },
  {
    "path": "test/unit/features/directives/pre.spec.js",
    "content": "import Vue from 'vue'\n\ndescribe('Directive v-pre', function () {\n  it('should not compile inner content', function () {\n    const vm = new Vue({\n      template: `<div>\n        <div v-pre>{{ a }}</div>\n        <div>{{ a }}</div>\n        <div v-pre>\n          <component></component>\n        </div>\n      </div>`,\n      data: {\n        a: 123\n      }\n    })\n    vm.$mount()\n    expect(vm.$el.firstChild.textContent).toBe('{{ a }}')\n    expect(vm.$el.children[1].textContent).toBe('123')\n    expect(vm.$el.lastChild.innerHTML).toBe('<component></component>')\n  })\n\n  it('should not compile on root node', function () {\n    const vm = new Vue({\n      template: '<div v-pre>{{ a }}</div>',\n      replace: true,\n      data: {\n        a: 123\n      }\n    })\n    vm.$mount()\n    expect(vm.$el.firstChild.textContent).toBe('{{ a }}')\n  })\n})\n"
  },
  {
    "path": "test/unit/features/directives/show.spec.js",
    "content": "import Vue from 'vue'\n\ndescribe('Directive v-show', () => {\n  it('should check show value is truthy', () => {\n    const vm = new Vue({\n      template: '<div><span v-show=\"foo\">hello</span></div>',\n      data: { foo: true }\n    }).$mount()\n    expect(vm.$el.firstChild.style.display).toBe('')\n  })\n\n  it('should check show value is falsy', () => {\n    const vm = new Vue({\n      template: '<div><span v-show=\"foo\">hello</span></div>',\n      data: { foo: false }\n    }).$mount()\n    expect(vm.$el.firstChild.style.display).toBe('none')\n  })\n\n  it('should update show value changed', done => {\n    const vm = new Vue({\n      template: '<div><span v-show=\"foo\">hello</span></div>',\n      data: { foo: true }\n    }).$mount()\n    expect(vm.$el.firstChild.style.display).toBe('')\n    vm.foo = false\n    waitForUpdate(() => {\n      expect(vm.$el.firstChild.style.display).toBe('none')\n      vm.foo = {}\n    }).then(() => {\n      expect(vm.$el.firstChild.style.display).toBe('')\n      vm.foo = 0\n    }).then(() => {\n      expect(vm.$el.firstChild.style.display).toBe('none')\n      vm.foo = []\n    }).then(() => {\n      expect(vm.$el.firstChild.style.display).toBe('')\n      vm.foo = null\n    }).then(() => {\n      expect(vm.$el.firstChild.style.display).toBe('none')\n      vm.foo = '0'\n    }).then(() => {\n      expect(vm.$el.firstChild.style.display).toBe('')\n      vm.foo = undefined\n    }).then(() => {\n      expect(vm.$el.firstChild.style.display).toBe('none')\n      vm.foo = 1\n    }).then(() => {\n      expect(vm.$el.firstChild.style.display).toBe('')\n    }).then(done)\n  })\n\n  it('should respect display value in style attribute', done => {\n    const vm = new Vue({\n      template: '<div><span v-show=\"foo\" style=\"display:block\">hello</span></div>',\n      data: { foo: true }\n    }).$mount()\n    expect(vm.$el.firstChild.style.display).toBe('block')\n    vm.foo = false\n    waitForUpdate(() => {\n      expect(vm.$el.firstChild.style.display).toBe('none')\n      vm.foo = true\n    }).then(() => {\n      expect(vm.$el.firstChild.style.display).toBe('block')\n    }).then(done)\n  })\n\n  it('should support unbind when reused', done => {\n    const vm = new Vue({\n      template:\n        '<div v-if=\"tester\"><span v-show=\"false\"></span></div>' +\n        '<div v-else><span @click=\"tester=!tester\">show</span></div>',\n      data: { tester: true }\n    }).$mount()\n    expect(vm.$el.firstChild.style.display).toBe('none')\n    vm.tester = false\n    waitForUpdate(() => {\n      expect(vm.$el.firstChild.style.display).toBe('')\n      vm.tester = true\n    }).then(() => {\n      expect(vm.$el.firstChild.style.display).toBe('none')\n    }).then(done)\n  })\n})\n"
  },
  {
    "path": "test/unit/features/directives/static-style-parser.spec.js",
    "content": "import { parseStyleText } from 'web/util/style'\nconst base64ImgUrl = 'url(\"data:image/webp;base64,UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==\")'\nconst logoUrl = 'url(https://vuejs.org/images/logo.png)'\n\nit('should parse normal static style', () => {\n  const staticStyle = `font-size: 12px;background: ${logoUrl};color:red`\n  const res = parseStyleText(staticStyle)\n  expect(res.background).toBe(logoUrl)\n  expect(res.color).toBe('red')\n  expect(res['font-size']).toBe('12px')\n})\n\nit('should parse base64 background', () => {\n  const staticStyle = `background: ${base64ImgUrl}`\n  const res = parseStyleText(staticStyle)\n  expect(res.background).toBe(base64ImgUrl)\n})\n\nit('should parse multiple background images ', () => {\n  let staticStyle = `background: ${logoUrl}, ${logoUrl};`\n  let res = parseStyleText(staticStyle)\n  expect(res.background).toBe(`${logoUrl}, ${logoUrl}`)\n\n  staticStyle = `background: ${base64ImgUrl}, ${base64ImgUrl}`\n  res = parseStyleText(staticStyle)\n  expect(res.background).toBe(`${base64ImgUrl}, ${base64ImgUrl}`)\n})\n\nit('should parse other images ', () => {\n  let staticStyle = `shape-outside: ${logoUrl}`\n  let res = parseStyleText(staticStyle)\n  expect(res['shape-outside']).toBe(logoUrl)\n\n  staticStyle = `list-style-image: ${logoUrl}`\n  res = parseStyleText(staticStyle)\n  expect(res['list-style-image']).toBe(logoUrl)\n\n  staticStyle = `border-image: ${logoUrl} 30 30 repeat`\n  res = parseStyleText(staticStyle)\n  expect(res['border-image']).toBe(`${logoUrl} 30 30 repeat`)\n})\n"
  },
  {
    "path": "test/unit/features/directives/style.spec.js",
    "content": "import Vue from 'vue'\n\nfunction checkPrefixedProp (prop) {\n  var el = document.createElement('div')\n  var upper = prop.charAt(0).toUpperCase() + prop.slice(1)\n  if (!(prop in el.style)) {\n    var prefixes = ['Webkit', 'Moz', 'ms']\n    var i = prefixes.length\n    while (i--) {\n      if ((prefixes[i] + upper) in el.style) {\n        prop = prefixes[i] + upper\n      }\n    }\n  }\n  return prop\n}\n\ndescribe('Directive v-bind:style', () => {\n  let vm\n\n  beforeEach(() => {\n    vm = new Vue({\n      template: '<div :style=\"styles\"></div>',\n      data () {\n        return {\n          styles: {},\n          fontSize: 16\n        }\n      }\n    }).$mount()\n  })\n\n  it('string', done => {\n    vm.styles = 'color:red;'\n    waitForUpdate(() => {\n      expect(vm.$el.style.cssText.replace(/\\s/g, '')).toBe('color:red;')\n    }).then(done)\n  })\n\n  it('falsy number', done => {\n    vm.styles = { opacity: 0 }\n    waitForUpdate(() => {\n      expect(vm.$el.style.opacity).toBe('0')\n    }).then(done)\n  })\n\n  it('plain object', done => {\n    vm.styles = { color: 'red' }\n    waitForUpdate(() => {\n      expect(vm.$el.style.cssText.replace(/\\s/g, '')).toBe('color:red;')\n    }).then(done)\n  })\n\n  it('camelCase', done => {\n    vm.styles = { marginRight: '10px' }\n    waitForUpdate(() => {\n      expect(vm.$el.style.marginRight).toBe('10px')\n    }).then(done)\n  })\n\n  it('remove if falsy value', done => {\n    vm.$el.style.color = 'red'\n    waitForUpdate(() => {\n      vm.styles = { color: null }\n    }).then(() => {\n      expect(vm.$el.style.color).toBe('')\n    }).then(done)\n  })\n\n  it('ignore unsupported property', done => {\n    vm.styles = { foo: 'bar' }\n    waitForUpdate(() => {\n      expect(vm.$el.style.foo).not.toBe('bar')\n    }).then(done)\n  })\n\n  it('auto prefix', done => {\n    const prop = checkPrefixedProp('transform')\n    const val = 'scale(0.5)'\n    vm.styles = { transform: val }\n    waitForUpdate(() => {\n      expect(vm.$el.style[prop]).toBe(val)\n    }).then(done)\n  })\n\n  it('auto-prefixed style value as array', done => {\n    vm.styles = { display: ['-webkit-box', '-ms-flexbox', 'flex'] }\n    const testEl = document.createElement('div')\n    vm.styles.display.forEach(value => {\n      testEl.style.display = value\n    })\n    waitForUpdate(() => {\n      expect(vm.$el.style.display).toBe(testEl.style.display)\n    }).then(done)\n  })\n\n  it('!important', done => {\n    vm.styles = { display: 'block !important' }\n    waitForUpdate(() => {\n      expect(vm.$el.style.getPropertyPriority('display')).toBe('important')\n    }).then(done)\n  })\n\n  it('object with multiple entries', done => {\n    vm.$el.style.color = 'red'\n    vm.styles = {\n      marginLeft: '10px',\n      marginRight: '15px'\n    }\n    waitForUpdate(() => {\n      expect(vm.$el.style.getPropertyValue('color')).toBe('red')\n      expect(vm.$el.style.getPropertyValue('margin-left')).toBe('10px')\n      expect(vm.$el.style.getPropertyValue('margin-right')).toBe('15px')\n      vm.styles = {\n        color: 'blue',\n        padding: null\n      }\n    }).then(() => {\n      expect(vm.$el.style.getPropertyValue('color')).toBe('blue')\n      expect(vm.$el.style.getPropertyValue('padding')).toBeFalsy()\n      expect(vm.$el.style.getPropertyValue('margin-left')).toBeFalsy()\n      expect(vm.$el.style.getPropertyValue('margin-right')).toBeFalsy()\n      // handle falsy value\n      vm.styles = null\n    }).then(() => {\n      expect(vm.$el.style.getPropertyValue('color')).toBeFalsy()\n      expect(vm.$el.style.getPropertyValue('padding')).toBeFalsy()\n      expect(vm.$el.style.getPropertyValue('margin-left')).toBeFalsy()\n      expect(vm.$el.style.getPropertyValue('margin-right')).toBeFalsy()\n    }).then(done)\n  })\n\n  it('array of objects', done => {\n    vm.$el.style.padding = '10px'\n    vm.styles = [{ color: 'red' }, { marginRight: '20px' }]\n\n    waitForUpdate(() => {\n      expect(vm.$el.style.getPropertyValue('color')).toBe('red')\n      expect(vm.$el.style.getPropertyValue('margin-right')).toBe('20px')\n      expect(vm.$el.style.getPropertyValue('padding')).toBe('10px')\n      vm.styles = [{ color: 'blue' }, { padding: null }]\n    }).then(() => {\n      expect(vm.$el.style.getPropertyValue('color')).toBe('blue')\n      expect(vm.$el.style.getPropertyValue('margin-right')).toBeFalsy()\n      expect(vm.$el.style.getPropertyValue('padding')).toBeFalsy()\n    }).then(done)\n  })\n\n  it('updates objects deeply', done => {\n    vm.styles = { display: 'none' }\n    waitForUpdate(() => {\n      expect(vm.$el.style.display).toBe('none')\n      vm.styles.display = 'block'\n    }).then(() => {\n      expect(vm.$el.style.display).toBe('block')\n    }).then(done)\n  })\n\n  it('background size with only one value', done => {\n    vm.styles = { backgroundSize: '100%' }\n    waitForUpdate(() => {\n      expect(vm.$el.style.cssText.replace(/\\s/g, '')).toMatch(/background-size:100%(auto)?;/)\n    }).then(done)\n  })\n\n  it('should work with interpolation', done => {\n    vm.styles = { fontSize: `${vm.fontSize}px` }\n    waitForUpdate(() => {\n      expect(vm.$el.style.fontSize).toBe('16px')\n    }).then(done)\n  })\n\n  const supportCssVariable = () => {\n    const el = document.createElement('div')\n    el.style.setProperty('--color', 'red')\n    return el.style.getPropertyValue('--color') === 'red'\n  }\n\n  if (supportCssVariable()) {\n    it('CSS variables', done => {\n      vm.styles = { '--color': 'red' }\n      waitForUpdate(() => {\n        expect(vm.$el.style.getPropertyValue('--color')).toBe('red')\n      }).then(done)\n    })\n  }\n\n  it('should merge static style with binding style', () => {\n    const vm = new Vue({\n      template: '<div style=\"background: url(https://vuejs.org/images/logo.png);color: blue\" :style=\"test\"></div>',\n      data: {\n        test: { color: 'red', fontSize: '12px' }\n      }\n    }).$mount()\n    const style = vm.$el.style\n    expect(style.getPropertyValue('background-image')).toMatch('https://vuejs.org/images/logo.png')\n    expect(style.getPropertyValue('color')).toBe('red')\n    expect(style.getPropertyValue('font-size')).toBe('12px')\n  })\n\n  it('should merge between parent and child', done => {\n    const vm = new Vue({\n      template: '<child style=\"text-align: left;margin-right:20px\" :style=\"test\"></child>',\n      data: {\n        test: { color: 'red', fontSize: '12px' }\n      },\n      components: {\n        child: {\n          template: '<div style=\"margin-right:10px;\" :style=\"{marginLeft: marginLeft}\"></div>',\n          data: () => ({ marginLeft: '16px' })\n        }\n      }\n    }).$mount()\n    const style = vm.$el.style\n    const child = vm.$children[0]\n    const css = style.cssText.replace(/\\s/g, '')\n    expect(css).toContain('margin-right:20px;')\n    expect(css).toContain('margin-left:16px;')\n    expect(css).toContain('text-align:left;')\n    expect(css).toContain('color:red;')\n    expect(css).toContain('font-size:12px;')\n    expect(style.color).toBe('red')\n    expect(style.marginRight).toBe('20px')\n    vm.test.color = 'blue'\n    waitForUpdate(() => {\n      expect(style.color).toBe('blue')\n      child.marginLeft = '30px'\n    }).then(() => {\n      expect(style.marginLeft).toBe('30px')\n      child.fontSize = '30px'\n    }).then(() => {\n      expect(style.fontSize).toBe('12px')\n    }).then(done)\n  })\n\n  it('should not pass to child root element', () => {\n    const vm = new Vue({\n      template: '<child :style=\"test\"></child>',\n      data: {\n        test: { color: 'red', fontSize: '12px' }\n      },\n      components: {\n        child: {\n          template: '<div><nested ref=\"nested\" style=\"color: blue;text-align:left\"></nested></div>',\n          components: {\n            nested: {\n              template: '<div></div>'\n            }\n          }\n        }\n      }\n    }).$mount()\n    const style = vm.$el.style\n    expect(style.color).toBe('red')\n    expect(style.textAlign).toBe('')\n    expect(style.fontSize).toBe('12px')\n    expect(vm.$children[0].$refs.nested.$el.style.color).toBe('blue')\n  })\n\n  it('should merge between nested components', (done) => {\n    const vm = new Vue({\n      template: '<child :style=\"test\"></child>',\n      data: {\n        test: { color: 'red', fontSize: '12px' }\n      },\n      components: {\n        child: {\n          template: '<nested style=\"color: blue;text-align:left\"></nested>',\n          components: {\n            nested: {\n              template: '<div style=\"margin-left: 12px;\" :style=\"nestedStyle\"></div>',\n              data: () => ({ nestedStyle: { marginLeft: '30px' }})\n            }\n          }\n        }\n      }\n    }).$mount()\n    const style = vm.$el.style\n    const child = vm.$children[0].$children[0]\n    expect(style.color).toBe('red')\n    expect(style.marginLeft).toBe('30px')\n    expect(style.textAlign).toBe('left')\n    expect(style.fontSize).toBe('12px')\n    vm.test.color = 'yellow'\n    waitForUpdate(() => {\n      child.nestedStyle.marginLeft = '60px'\n    }).then(() => {\n      expect(style.marginLeft).toBe('60px')\n      child.nestedStyle = {\n        fontSize: '14px',\n        marginLeft: '40px'\n      }\n    }).then(() => {\n      expect(style.fontSize).toBe('12px')\n      expect(style.marginLeft).toBe('40px')\n    }).then(done)\n  })\n\n  it('should not merge for different adjacent elements', (done) => {\n    const vm = new Vue({\n      template:\n        '<div>' +\n          '<section style=\"color: blue\" :style=\"style\" v-if=\"!bool\"></section>' +\n          '<div></div>' +\n          '<section style=\"margin-top: 12px\" v-if=\"bool\"></section>' +\n        '</div>',\n      data: {\n        bool: false,\n        style: {\n          fontSize: '12px'\n        }\n      }\n    }).$mount()\n    const style = vm.$el.children[0].style\n    expect(style.fontSize).toBe('12px')\n    expect(style.color).toBe('blue')\n    waitForUpdate(() => {\n      vm.bool = true\n    }).then(() => {\n      expect(style.color).toBe('')\n      expect(style.fontSize).toBe('')\n      expect(style.marginTop).toBe('12px')\n    }).then(done)\n  })\n\n  it('should not merge for v-if, v-else-if and v-else elements', (done) => {\n    const vm = new Vue({\n      template:\n        '<div>' +\n          '<section style=\"color: blue\" :style=\"style\" v-if=\"foo\"></section>' +\n          '<section style=\"margin-top: 12px\" v-else-if=\"bar\"></section>' +\n          '<section style=\"margin-bottom: 24px\" v-else></section>' +\n          '<div></div>' +\n        '</div>',\n      data: {\n        foo: true,\n        bar: false,\n        style: {\n          fontSize: '12px'\n        }\n      }\n    }).$mount()\n    const style = vm.$el.children[0].style\n    expect(style.fontSize).toBe('12px')\n    expect(style.color).toBe('blue')\n    waitForUpdate(() => {\n      vm.foo = false\n    }).then(() => {\n      expect(style.color).toBe('')\n      expect(style.fontSize).toBe('')\n      expect(style.marginBottom).toBe('24px')\n      vm.bar = true\n    }).then(() => {\n      expect(style.color).toBe('')\n      expect(style.fontSize).toBe('')\n      expect(style.marginBottom).toBe('')\n      expect(style.marginTop).toBe('12px')\n    }).then(done)\n  })\n\n  // #5318\n  it('should work for elements passed down as a slot', done => {\n    const vm = new Vue({\n      template: `<test><div :style=\"style\"/></test>`,\n      data: {\n        style: { color: 'red' }\n      },\n      components: {\n        test: {\n          template: `<div><slot/></div>`\n        }\n      }\n    }).$mount()\n\n    expect(vm.$el.children[0].style.color).toBe('red')\n    vm.style.color = 'green'\n    waitForUpdate(() => {\n      expect(vm.$el.children[0].style.color).toBe('green')\n    }).then(done)\n  })\n})\n"
  },
  {
    "path": "test/unit/features/directives/text.spec.js",
    "content": "import Vue from 'vue'\n\ndescribe('Directive v-text', () => {\n  it('should render text', () => {\n    const vm = new Vue({\n      template: '<div v-text=\"a\"></div>',\n      data: { a: 'hello' }\n    }).$mount()\n    expect(vm.$el.innerHTML).toBe('hello')\n  })\n\n  it('should encode html entities', () => {\n    const vm = new Vue({\n      template: '<div v-text=\"a\"></div>',\n      data: { a: '<foo>' }\n    }).$mount()\n    expect(vm.$el.innerHTML).toBe('&lt;foo&gt;')\n  })\n\n  it('should support all value types', done => {\n    const vm = new Vue({\n      template: '<div v-text=\"a\"></div>',\n      data: { a: false }\n    }).$mount()\n    waitForUpdate(() => {\n      expect(vm.$el.innerHTML).toBe('false')\n      vm.a = []\n    }).then(() => {\n      expect(vm.$el.innerHTML).toBe('[]')\n      vm.a = {}\n    }).then(() => {\n      expect(vm.$el.innerHTML).toBe('{}')\n      vm.a = 123\n    }).then(() => {\n      expect(vm.$el.innerHTML).toBe('123')\n      vm.a = 0\n    }).then(() => {\n      expect(vm.$el.innerHTML).toBe('0')\n      vm.a = ' '\n    }).then(() => {\n      expect(vm.$el.innerHTML).toBe(' ')\n      vm.a = '    '\n    }).then(() => {\n      expect(vm.$el.innerHTML).toBe('    ')\n      vm.a = null\n    }).then(() => {\n      expect(vm.$el.innerHTML).toBe('')\n      vm.a = undefined\n    }).then(() => {\n      expect(vm.$el.innerHTML).toBe('')\n    }).then(done)\n  })\n})\n"
  },
  {
    "path": "test/unit/features/error-handling.spec.js",
    "content": "import Vue from 'vue'\n\nconst components = createErrorTestComponents()\n\ndescribe('Error handling', () => {\n  // hooks that prevents the component from rendering, but should not\n  // break parent component\n  ;[\n    ['data', 'data()'],\n    ['render', 'render function'],\n    ['beforeCreate', 'beforeCreate hook'],\n    ['created', 'created hook'],\n    ['beforeMount', 'beforeMount hook'],\n    ['directive bind', 'directive foo bind hook'],\n    ['event', 'event handler for \"e\"']\n  ].forEach(([type, description]) => {\n    it(`should recover from errors in ${type}`, done => {\n      const vm = createTestInstance(components[type])\n      expect(`Error in ${description}`).toHaveBeenWarned()\n      expect(`Error: ${type}`).toHaveBeenWarned()\n      assertRootInstanceActive(vm).then(done)\n    })\n  })\n\n  // error in mounted hook should affect neither child nor parent\n  it('should recover from errors in mounted hook', done => {\n    const vm = createTestInstance(components.mounted)\n    expect(`Error in mounted hook`).toHaveBeenWarned()\n    expect(`Error: mounted`).toHaveBeenWarned()\n    assertBothInstancesActive(vm).then(done)\n  })\n\n  // error in beforeUpdate/updated should affect neither child nor parent\n  ;[\n    ['beforeUpdate', 'beforeUpdate hook'],\n    ['updated', 'updated hook'],\n    ['directive update', 'directive foo update hook']\n  ].forEach(([type, description]) => {\n    it(`should recover from errors in ${type} hook`, done => {\n      const vm = createTestInstance(components[type])\n      assertBothInstancesActive(vm).then(() => {\n        expect(`Error in ${description}`).toHaveBeenWarned()\n        expect(`Error: ${type}`).toHaveBeenWarned()\n      }).then(done)\n    })\n  })\n\n  ;[\n    ['beforeDestroy', 'beforeDestroy hook'],\n    ['destroyed', 'destroyed hook'],\n    ['directive unbind', 'directive foo unbind hook']\n  ].forEach(([type, description]) => {\n    it(`should recover from errors in ${type} hook`, done => {\n      const vm = createTestInstance(components[type])\n      vm.ok = false\n      waitForUpdate(() => {\n        expect(`Error in ${description}`).toHaveBeenWarned()\n        expect(`Error: ${type}`).toHaveBeenWarned()\n      }).thenWaitFor(next => {\n        assertRootInstanceActive(vm).end(next)\n      }).then(done)\n    })\n  })\n\n  it('should recover from errors in user watcher getter', done => {\n    const vm = createTestInstance(components.userWatcherGetter)\n    vm.n++\n    waitForUpdate(() => {\n      expect(`Error in getter for watcher`).toHaveBeenWarned()\n      function getErrorMsg () {\n        try {\n          this.a.b.c\n        } catch (e) {\n          return e.toString()\n        }\n      }\n      const msg = getErrorMsg.call(vm)\n      expect(msg).toHaveBeenWarned()\n    }).thenWaitFor(next => {\n      assertBothInstancesActive(vm).end(next)\n    }).then(done)\n  })\n\n  it('should recover from errors in user watcher callback', done => {\n    const vm = createTestInstance(components.userWatcherCallback)\n    vm.n++\n    waitForUpdate(() => {\n      expect(`Error in callback for watcher \"n\"`).toHaveBeenWarned()\n      expect(`Error: userWatcherCallback`).toHaveBeenWarned()\n    }).thenWaitFor(next => {\n      assertBothInstancesActive(vm).end(next)\n    }).then(done)\n  })\n\n  it('config.errorHandler should capture errors', done => {\n    const spy = Vue.config.errorHandler = jasmine.createSpy('errorHandler')\n    const vm = createTestInstance(components.render)\n\n    const args = spy.calls.argsFor(0)\n    expect(args[0].toString()).toContain('Error: render') // error\n    expect(args[1]).toBe(vm.$refs.child) // vm\n    expect(args[2]).toContain('render function') // description\n\n    assertRootInstanceActive(vm).then(() => {\n      Vue.config.errorHandler = null\n    }).then(done)\n  })\n\n  it('should capture and recover from nextTick errors', done => {\n    const err1 = new Error('nextTick')\n    const err2 = new Error('nextTick2')\n    const spy = Vue.config.errorHandler = jasmine.createSpy('errorHandler')\n    Vue.nextTick(() => { throw err1 })\n    Vue.nextTick(() => {\n      expect(spy).toHaveBeenCalledWith(err1, undefined, 'nextTick')\n\n      const vm = new Vue()\n      vm.$nextTick(() => { throw err2 })\n      Vue.nextTick(() => {\n        // should be called with correct instance info\n        expect(spy).toHaveBeenCalledWith(err2, vm, 'nextTick')\n        Vue.config.errorHandler = null\n        done()\n      })\n    })\n  })\n})\n\nfunction createErrorTestComponents () {\n  const components = {}\n\n  // data\n  components.data = {\n    data () {\n      throw new Error('data')\n    },\n    render (h) {\n      return h('div')\n    }\n  }\n\n  // render error\n  components.render = {\n    render (h) {\n      throw new Error('render')\n    }\n  }\n\n  // lifecycle errors\n  ;['create', 'mount', 'update', 'destroy'].forEach(hook => {\n    // before\n    const before = 'before' + hook.charAt(0).toUpperCase() + hook.slice(1)\n    const beforeComp = components[before] = {\n      props: ['n'],\n      render (h) {\n        return h('div', this.n)\n      }\n    }\n    beforeComp[before] = function () {\n      throw new Error(before)\n    }\n\n    // after\n    const after = hook.replace(/e?$/, 'ed')\n    const afterComp = components[after] = {\n      props: ['n'],\n      render (h) {\n        return h('div', this.n)\n      }\n    }\n    afterComp[after] = function () {\n      throw new Error(after)\n    }\n  })\n\n  // directive hooks errors\n  ;['bind', 'update', 'unbind'].forEach(hook => {\n    const key = 'directive ' + hook\n    const dirComp = components[key] = {\n      props: ['n'],\n      template: `<div v-foo=\"n\">{{ n }}</div>`\n    }\n    const dirFoo = {}\n    dirFoo[hook] = function () {\n      throw new Error(key)\n    }\n    dirComp.directives = {\n      foo: dirFoo\n    }\n  })\n\n  // user watcher\n  components.userWatcherGetter = {\n    props: ['n'],\n    created () {\n      this.$watch(function () {\n        return this.n + this.a.b.c\n      }, val => {\n        console.log('user watcher fired: ' + val)\n      })\n    },\n    render (h) {\n      return h('div', this.n)\n    }\n  }\n\n  components.userWatcherCallback = {\n    props: ['n'],\n    watch: {\n      n () {\n        throw new Error('userWatcherCallback error')\n      }\n    },\n    render (h) {\n      return h('div', this.n)\n    }\n  }\n\n  // event errors\n  components.event = {\n    beforeCreate () {\n      this.$on('e', () => { throw new Error('event') })\n    },\n    mounted () {\n      this.$emit('e')\n    },\n    render (h) {\n      return h('div')\n    }\n  }\n\n  return components\n}\n\nfunction createTestInstance (Comp) {\n  return new Vue({\n    data: {\n      n: 0,\n      ok: true\n    },\n    render (h) {\n      return h('div', [\n        'n:' + this.n + '\\n',\n        this.ok\n          ? h(Comp, { ref: 'child', props: { n: this.n }})\n          : null\n      ])\n    }\n  }).$mount()\n}\n\nfunction assertRootInstanceActive (vm, chain) {\n  expect(vm.$el.innerHTML).toContain('n:0\\n')\n  vm.n++\n  return waitForUpdate(() => {\n    expect(vm.$el.innerHTML).toContain('n:1\\n')\n  })\n}\n\nfunction assertBothInstancesActive (vm) {\n  vm.n = 0\n  return waitForUpdate(() => {\n    expect(vm.$refs.child.$el.innerHTML).toContain('0')\n  }).thenWaitFor(next => {\n    assertRootInstanceActive(vm).then(() => {\n      expect(vm.$refs.child.$el.innerHTML).toContain('1')\n    }).end(next)\n  })\n}\n"
  },
  {
    "path": "test/unit/features/filter/filter.spec.js",
    "content": "import Vue from 'vue'\nimport { parseFilters } from 'compiler/parser/filter-parser'\n\ndescribe('Filters', () => {\n  it('basic usage', () => {\n    const vm = new Vue({\n      template: '<div>{{ msg | upper }}</div>',\n      data: {\n        msg: 'hi'\n      },\n      filters: {\n        upper: v => v.toUpperCase()\n      }\n    }).$mount()\n    expect(vm.$el.textContent).toBe('HI')\n  })\n\n  it('chained usage', () => {\n    const vm = new Vue({\n      template: '<div>{{ msg | upper | reverse }}</div>',\n      data: {\n        msg: 'hi'\n      },\n      filters: {\n        upper: v => v.toUpperCase(),\n        reverse: v => v.split('').reverse().join('')\n      }\n    }).$mount()\n    expect(vm.$el.textContent).toBe('IH')\n  })\n\n  it('in v-bind', () => {\n    const vm = new Vue({\n      template: `\n        <div\n          v-bind:id=\"id | upper | reverse\"\n          :class=\"cls | reverse\"\n          :ref=\"ref | lower\">\n        </div>\n      `,\n      filters: {\n        upper: v => v.toUpperCase(),\n        reverse: v => v.split('').reverse().join(''),\n        lower: v => v.toLowerCase()\n      },\n      data: {\n        id: 'abc',\n        cls: 'foo',\n        ref: 'BAR'\n      }\n    }).$mount()\n    expect(vm.$el.id).toBe('CBA')\n    expect(vm.$el.className).toBe('oof')\n    expect(vm.$refs.bar).toBe(vm.$el)\n  })\n\n  it('handle regex with pipe', () => {\n    const vm = new Vue({\n      template: `<test ref=\"test\" :pattern=\"/a|b\\\\// | identity\"></test>`,\n      filters: { identity: v => v },\n      components: {\n        test: {\n          props: ['pattern'],\n          template: '<div></div>'\n        }\n      }\n    }).$mount()\n    expect(vm.$refs.test.pattern instanceof RegExp).toBe(true)\n    expect(vm.$refs.test.pattern.toString()).toBe('/a|b\\\\//')\n  })\n\n  it('handle division', () => {\n    const vm = new Vue({\n      data: { a: 2 },\n      template: `<div>{{ 1/a / 4 | double }}</div>`,\n      filters: { double: v => v * 2 }\n    }).$mount()\n    expect(vm.$el.textContent).toBe(String(1 / 4))\n  })\n\n  it('handle division with parenthesis', () => {\n    const vm = new Vue({\n      data: { a: 20 },\n      template: `<div>{{ (a*2) / 5 | double }}</div>`,\n      filters: { double: v => v * 2 }\n    }).$mount()\n    expect(vm.$el.textContent).toBe(String(16))\n  })\n\n  it('handle division with dot', () => {\n    const vm = new Vue({\n      template: `<div>{{ 20. / 5 | double }}</div>`,\n      filters: { double: v => v * 2 }\n    }).$mount()\n    expect(vm.$el.textContent).toBe(String(8))\n  })\n\n  it('handle division with array values', () => {\n    const vm = new Vue({\n      data: { a: [20] },\n      template: `<div>{{ a[0] / 5 | double }}</div>`,\n      filters: { double: v => v * 2 }\n    }).$mount()\n    expect(vm.$el.textContent).toBe(String(8))\n  })\n\n  it('handle division with hash values', () => {\n    const vm = new Vue({\n      data: { a: { n: 20 }},\n      template: `<div>{{ a['n'] / 5 | double }}</div>`,\n      filters: { double: v => v * 2 }\n    }).$mount()\n    expect(vm.$el.textContent).toBe(String(8))\n  })\n\n  it('handle division with variable_', () => {\n    const vm = new Vue({\n      data: { a_: 8 },\n      template: `<div>{{ a_ / 2 | double }}</div>`,\n      filters: { double: v => v * 2 }\n    }).$mount()\n    expect(vm.$el.textContent).toBe(String(8))\n  })\n\n  it('arguments', () => {\n    const vm = new Vue({\n      template: `<div>{{ msg | add(a, 3) }}</div>`,\n      data: {\n        msg: 1,\n        a: 2\n      },\n      filters: {\n        add: (v, arg1, arg2) => v + arg1 + arg2\n      }\n    }).$mount()\n    expect(vm.$el.textContent).toBe('6')\n  })\n\n  it('quotes', () => {\n    const vm = new Vue({\n      template: `<div>{{ msg + \"b | c\" + 'd' | upper }}</div>`,\n      data: {\n        msg: 'a'\n      },\n      filters: {\n        upper: v => v.toUpperCase()\n      }\n    }).$mount()\n    expect(vm.$el.textContent).toBe('AB | CD')\n  })\n\n  it('double pipe', () => {\n    const vm = new Vue({\n      template: `<div>{{ b || msg | upper }}</div>`,\n      data: {\n        b: false,\n        msg: 'a'\n      },\n      filters: {\n        upper: v => v.toUpperCase()\n      }\n    }).$mount()\n    expect(vm.$el.textContent).toBe('A')\n  })\n\n  it('object literal', () => {\n    const vm = new Vue({\n      template: `<div>{{ { a: 123 } | pick('a') }}</div>`,\n      filters: {\n        pick: (v, key) => v[key]\n      }\n    }).$mount()\n    expect(vm.$el.textContent).toBe('123')\n  })\n\n  it('array literal', () => {\n    const vm = new Vue({\n      template: `<div>{{ [1, 2, 3] | reverse }}</div>`,\n      filters: {\n        reverse: arr => arr.reverse().join(',')\n      }\n    }).$mount()\n    expect(vm.$el.textContent).toBe('3,2,1')\n  })\n\n  it('warn non-existent', () => {\n    new Vue({\n      template: '<div>{{ msg | upper }}</div>',\n      data: { msg: 'foo' }\n    }).$mount()\n    expect('Failed to resolve filter: upper').toHaveBeenWarned()\n  })\n\n  it('support template string', () => {\n    expect(parseFilters('`a | ${b}c` | d')).toBe('_f(\"d\")(`a | ${b}c`)')\n  })\n})\n"
  },
  {
    "path": "test/unit/features/global-api/assets.spec.js",
    "content": "import Vue from 'vue'\n\ndescribe('Global API: assets', () => {\n  const Test = Vue.extend()\n\n  it('directive / filters', () => {\n    const assets = ['directive', 'filter']\n    assets.forEach(function (type) {\n      const def = {}\n      Test[type]('test', def)\n      expect(Test.options[type + 's'].test).toBe(def)\n      expect(Test[type]('test')).toBe(def)\n      // extended registration should not pollute global\n      expect(Vue.options[type + 's'].test).toBeUndefined()\n    })\n  })\n\n  describe('Vue.component', () => {\n    it('should register a component', () => {\n      Vue.component('foo', {\n        template: '<span>foo</span>'\n      })\n      Vue.component('bar', {\n        template: '<span>bar</span>'\n      })\n      const vm = new Vue({\n        template: '<div><foo></foo><bar></bar></div>'\n      }).$mount()\n      expect(vm.$el.innerHTML).toBe('<span>foo</span><span>bar</span>')\n      // unregister them\n      delete Vue.options.components.foo\n      delete Vue.options.components.bar\n    })\n  })\n\n  it('component on extended constructor', () => {\n    const def = { a: 1 }\n    Test.component('test', def)\n    const component = Test.options.components.test\n    expect(typeof component).toBe('function')\n    expect(component.super).toBe(Vue)\n    expect(component.options.a).toBe(1)\n    expect(component.options.name).toBe('test')\n    expect(Test.component('test')).toBe(component)\n    // already extended\n    Test.component('test2', component)\n    expect(Test.component('test2')).toBe(component)\n    // extended registration should not pollute global\n    expect(Vue.options.components.test).toBeUndefined()\n  })\n\n  // #4434\n  it('local registration should take priority regardless of naming convention', () => {\n    Vue.component('x-foo', {\n      template: '<span>global</span>'\n    })\n    const vm = new Vue({\n      components: {\n        xFoo: {\n          template: '<span>local</span>'\n        }\n      },\n      template: '<div><x-foo></x-foo></div>'\n    }).$mount()\n    expect(vm.$el.textContent).toBe('local')\n    delete Vue.options.components['x-foo']\n  })\n})\n"
  },
  {
    "path": "test/unit/features/global-api/compile.spec.js",
    "content": "import Vue from 'vue'\n\ndescribe('Global API: compile', () => {\n  it('should compile render functions', () => {\n    const res = Vue.compile('<div><span>{{ msg }}</span></div>')\n    const vm = new Vue({\n      data: {\n        msg: 'hello'\n      },\n      render: res.render,\n      staticRenderFns: res.staticRenderFns\n    }).$mount()\n    expect(vm.$el.innerHTML).toContain('<span>hello</span>')\n  })\n})\n"
  },
  {
    "path": "test/unit/features/global-api/config.spec.js",
    "content": "import Vue from 'vue'\nimport { warn } from 'core/util/debug'\n\ndescribe('Global config', () => {\n  it('should warn replacing config object', () => {\n    const originalConfig = Vue.config\n    Vue.config = {}\n    expect(Vue.config).toBe(originalConfig)\n    expect('Do not replace the Vue.config object').toHaveBeenWarned()\n  })\n\n  describe('silent', () => {\n    it('should be false by default', () => {\n      warn('foo')\n      expect('foo').toHaveBeenWarned()\n    })\n\n    it('should work when set to true', () => {\n      Vue.config.silent = true\n      warn('foo')\n      expect('foo').not.toHaveBeenWarned()\n      Vue.config.silent = false\n    })\n  })\n\n  describe('optionMergeStrategies', () => {\n    it('should allow defining custom option merging strategies', () => {\n      const spy = jasmine.createSpy('option merging')\n      Vue.config.optionMergeStrategies.__test__ = (parent, child, vm) => {\n        spy(parent, child, vm)\n        return child + 1\n      }\n      const Test = Vue.extend({\n        __test__: 1\n      })\n      expect(spy.calls.count()).toBe(1)\n      expect(spy).toHaveBeenCalledWith(undefined, 1, undefined)\n      expect(Test.options.__test__).toBe(2)\n      const test = new Test({\n        __test__: 2\n      })\n      expect(spy.calls.count()).toBe(2)\n      expect(spy).toHaveBeenCalledWith(2, 2, test)\n      expect(test.$options.__test__).toBe(3)\n    })\n  })\n})\n"
  },
  {
    "path": "test/unit/features/global-api/extend.spec.js",
    "content": "import Vue from 'vue'\n\ndescribe('Global API: extend', () => {\n  it('should correctly merge options', () => {\n    const Test = Vue.extend({\n      name: 'test',\n      a: 1,\n      b: 2\n    })\n    expect(Test.options.a).toBe(1)\n    expect(Test.options.b).toBe(2)\n    expect(Test.super).toBe(Vue)\n    const t = new Test({\n      a: 2\n    })\n    expect(t.$options.a).toBe(2)\n    expect(t.$options.b).toBe(2)\n    // inheritance\n    const Test2 = Test.extend({\n      a: 2\n    })\n    expect(Test2.options.a).toBe(2)\n    expect(Test2.options.b).toBe(2)\n    const t2 = new Test2({\n      a: 3\n    })\n    expect(t2.$options.a).toBe(3)\n    expect(t2.$options.b).toBe(2)\n  })\n\n  it('should warn invalid names', () => {\n    Vue.extend({ name: '123' })\n    expect('Invalid component name: \"123\"').toHaveBeenWarned()\n    Vue.extend({ name: '_fesf' })\n    expect('Invalid component name: \"_fesf\"').toHaveBeenWarned()\n    Vue.extend({ name: 'Some App' })\n    expect('Invalid component name: \"Some App\"').toHaveBeenWarned()\n  })\n\n  it('should work when used as components', () => {\n    const foo = Vue.extend({\n      template: '<span>foo</span>'\n    })\n    const bar = Vue.extend({\n      template: '<span>bar</span>'\n    })\n    const vm = new Vue({\n      template: '<div><foo></foo><bar></bar></div>',\n      components: { foo, bar }\n    }).$mount()\n    expect(vm.$el.innerHTML).toBe('<span>foo</span><span>bar</span>')\n  })\n\n  it('should merge lifecycle hooks', () => {\n    const calls = []\n    const A = Vue.extend({\n      created () {\n        calls.push(1)\n      }\n    })\n    const B = A.extend({\n      created () {\n        calls.push(2)\n      }\n    })\n    new B({\n      created () {\n        calls.push(3)\n      }\n    })\n    expect(calls).toEqual([1, 2, 3])\n  })\n\n  it('should merge methods', () => {\n    const A = Vue.extend({\n      methods: {\n        a () { return this.n }\n      }\n    })\n    const B = A.extend({\n      methods: {\n        b () { return this.n + 1 }\n      }\n    })\n    const b = new B({\n      data: { n: 0 },\n      methods: {\n        c () { return this.n + 2 }\n      }\n    })\n    expect(b.a()).toBe(0)\n    expect(b.b()).toBe(1)\n    expect(b.c()).toBe(2)\n  })\n\n  it('should merge assets', () => {\n    const A = Vue.extend({\n      components: {\n        aa: {\n          template: '<div>A</div>'\n        }\n      }\n    })\n    const B = A.extend({\n      components: {\n        bb: {\n          template: '<div>B</div>'\n        }\n      }\n    })\n    const b = new B({\n      template: '<div><aa></aa><bb></bb></div>'\n    }).$mount()\n    expect(b.$el.innerHTML).toBe('<div>A</div><div>B</div>')\n  })\n\n  it('caching', () => {\n    const options = {\n      template: '<div></div>'\n    }\n    const A = Vue.extend(options)\n    const B = Vue.extend(options)\n    expect(A).toBe(B)\n  })\n\n  // #4767\n  it('extended options should use different identify from parent', () => {\n    const A = Vue.extend({ computed: {}})\n    const B = A.extend()\n    B.options.computed.b = () => 'foo'\n    expect(B.options.computed).not.toBe(A.options.computed)\n    expect(A.options.computed.b).toBeUndefined()\n  })\n})\n"
  },
  {
    "path": "test/unit/features/global-api/mixin.spec.js",
    "content": "import Vue from 'vue'\n\ndescribe('Global API: mixin', () => {\n  let options\n  beforeEach(() => { options = Vue.options })\n  afterEach(() => { Vue.options = options })\n\n  it('should work', () => {\n    const spy = jasmine.createSpy('global mixin')\n    Vue.mixin({\n      created () {\n        spy(this.$options.myOption)\n      }\n    })\n    new Vue({\n      myOption: 'hello'\n    })\n    expect(spy).toHaveBeenCalledWith('hello')\n  })\n\n  it('should work for constructors created before mixin is applied', () => {\n    const calls = []\n    const Test = Vue.extend({\n      name: 'test',\n      beforeCreate () {\n        calls.push(this.$options.myOption + ' local')\n      }\n    })\n    Vue.mixin({\n      beforeCreate () {\n        calls.push(this.$options.myOption + ' global')\n      }\n    })\n    expect(Test.options.name).toBe('test')\n    new Test({\n      myOption: 'hello'\n    })\n    expect(calls).toEqual(['hello global', 'hello local'])\n  })\n\n  // #3957\n  it('should work for global props', () => {\n    const Test = Vue.extend({\n      template: `<div>{{ prop }}</div>`\n    })\n\n    Vue.mixin({\n      props: ['prop']\n    })\n\n    // test child component\n    const vm = new Vue({\n      template: '<test prop=\"hi\"></test>',\n      components: { Test }\n    }).$mount()\n\n    expect(vm.$el.textContent).toBe('hi')\n  })\n\n  // vue-loader#433\n  it('should not drop late-set render functions', () => {\n    const Test = Vue.extend({})\n    Test.options.render = h => h('div', 'hello')\n\n    Vue.mixin({})\n\n    const vm = new Vue({\n      render: h => h(Test)\n    }).$mount()\n\n    expect(vm.$el.textContent).toBe('hello')\n  })\n\n  // #4266\n  it('should not drop scopedId', () => {\n    const Test = Vue.extend({})\n    Test.options._scopeId = 'foo'\n\n    Vue.mixin({})\n\n    const vm = new Test({\n      template: '<div><p>hi</p></div>'\n    }).$mount()\n\n    expect(vm.$el.children[0].hasAttribute('foo')).toBe(true)\n  })\n\n  // #4976\n  it('should not drop late-attached custom options on existing constructors', () => {\n    const baseSpy = jasmine.createSpy('base')\n    const Base = Vue.extend({\n      beforeCreate: baseSpy\n    })\n\n    const Test = Base.extend({})\n\n    // Inject options later\n    // vue-loader and vue-hot-reload-api are doing like this\n    Test.options.computed = {\n      $style: () => 123\n    }\n\n    const spy = jasmine.createSpy('late attached')\n    Test.options.beforeCreate = Test.options.beforeCreate.concat(spy)\n\n    // Update super constructor's options\n    const mixinSpy = jasmine.createSpy('mixin')\n    Vue.mixin({\n      beforeCreate: mixinSpy\n    })\n\n    // mount the component\n    const vm = new Test({\n      template: '<div>{{ $style }}</div>'\n    }).$mount()\n\n    expect(spy.calls.count()).toBe(1)\n    expect(baseSpy.calls.count()).toBe(1)\n    expect(mixinSpy.calls.count()).toBe(1)\n    expect(vm.$el.textContent).toBe('123')\n    expect(vm.$style).toBe(123)\n\n    // Should not be dropped\n    expect(Test.options.computed.$style()).toBe(123)\n    expect(Test.options.beforeCreate).toEqual([mixinSpy, baseSpy, spy])\n  })\n\n  // vue-class-component#83\n  it('should work for a constructor mixin', () => {\n    const spy = jasmine.createSpy('global mixin')\n    const Mixin = Vue.extend({\n      created () {\n        spy(this.$options.myOption)\n      }\n    })\n\n    Vue.mixin(Mixin)\n\n    new Vue({\n      myOption: 'hello'\n    })\n    expect(spy).toHaveBeenCalledWith('hello')\n  })\n\n  // vue-class-component#87\n  it('should not drop original lifecycle hooks', () => {\n    const base = jasmine.createSpy('base')\n\n    const Base = Vue.extend({\n      beforeCreate: base\n    })\n\n    const injected = jasmine.createSpy('injected')\n\n    // inject a function\n    Base.options.beforeCreate = Base.options.beforeCreate.concat(injected)\n\n    Vue.mixin({})\n\n    new Base({})\n\n    expect(base).toHaveBeenCalled()\n    expect(injected).toHaveBeenCalled()\n  })\n})\n"
  },
  {
    "path": "test/unit/features/global-api/set-delete.spec.js",
    "content": "import Vue from 'vue'\n\ndescribe('Global API: set/delete', () => {\n  describe('Vue.set', () => {\n    it('should update a vue object', done => {\n      const vm = new Vue({\n        template: '<div>{{x}}</div>',\n        data: { x: 1 }\n      }).$mount()\n      expect(vm.$el.innerHTML).toBe('1')\n      Vue.set(vm, 'x', 2)\n      waitForUpdate(() => {\n        expect(vm.$el.innerHTML).toBe('2')\n      }).then(done)\n    })\n\n    it('should update a observing object', done => {\n      const vm = new Vue({\n        template: '<div>{{foo.x}}</div>',\n        data: { foo: { x: 1 }}\n      }).$mount()\n      expect(vm.$el.innerHTML).toBe('1')\n      Vue.set(vm.foo, 'x', 2)\n      waitForUpdate(() => {\n        expect(vm.$el.innerHTML).toBe('2')\n      }).then(done)\n    })\n\n    it('should update a observing array', done => {\n      const vm = new Vue({\n        template: '<div><div v-for=\"v,k in list\">{{k}}-{{v}}</div></div>',\n        data: { list: ['a', 'b', 'c'] }\n      }).$mount()\n      expect(vm.$el.innerHTML).toBe('<div>0-a</div><div>1-b</div><div>2-c</div>')\n      Vue.set(vm.list, 1, 'd')\n      waitForUpdate(() => {\n        expect(vm.$el.innerHTML).toBe('<div>0-a</div><div>1-d</div><div>2-c</div>')\n        Vue.set(vm.list, '2', 'e')\n      }).then(() => {\n        expect(vm.$el.innerHTML).toBe('<div>0-a</div><div>1-d</div><div>2-e</div>')\n        /* eslint-disable no-new-wrappers */\n        Vue.set(vm.list, new Number(1), 'f')\n      }).then(() => {\n        expect(vm.$el.innerHTML).toBe('<div>0-a</div><div>1-f</div><div>2-e</div>')\n        Vue.set(vm.list, '3g', 'g')\n      }).then(() => {\n        expect(vm.$el.innerHTML).toBe('<div>0-a</div><div>1-f</div><div>2-e</div>')\n      }).then(done)\n    })\n\n    it('should update a vue object with nothing', done => {\n      const vm = new Vue({\n        template: '<div>{{x}}</div>',\n        data: { x: 1 }\n      }).$mount()\n      expect(vm.$el.innerHTML).toBe('1')\n      Vue.set(vm, 'x', null)\n      waitForUpdate(() => {\n        expect(vm.$el.innerHTML).toBe('')\n        Vue.set(vm, 'x')\n      }).then(() => {\n        expect(vm.$el.innerHTML).toBe('')\n      }).then(done)\n    })\n\n    it('be able to use string type index in array', done => {\n      const vm = new Vue({\n        template: '<div><p v-for=\"obj in lists\">{{obj.name}}</p></div>',\n        data: {\n          lists: [\n            { name: 'A' },\n            { name: 'B' },\n            { name: 'C' }\n          ]\n        }\n      }).$mount()\n      expect(vm.$el.innerHTML).toBe('<p>A</p><p>B</p><p>C</p>')\n      Vue.set(vm.lists, '0', { name: 'D' })\n      waitForUpdate(() => {\n        expect(vm.$el.innerHTML).toBe('<p>D</p><p>B</p><p>C</p>')\n      }).then(done)\n    })\n  })\n\n  describe('Vue.delete', () => {\n    it('should delete a key', done => {\n      const vm = new Vue({\n        template: '<div>{{obj.x}}</div>',\n        data: { obj: { x: 1 }}\n      }).$mount()\n      expect(vm.$el.innerHTML).toBe('1')\n      vm.obj.x = 2\n      waitForUpdate(() => {\n        expect(vm.$el.innerHTML).toBe('2')\n        Vue.delete(vm.obj, 'x')\n      }).then(() => {\n        expect(vm.$el.innerHTML).toBe('')\n        vm.obj.x = 3\n      }).then(() => {\n        expect(vm.$el.innerHTML).toBe('')\n      }).then(done)\n    })\n\n    it('be able to delete an item in array', done => {\n      const vm = new Vue({\n        template: '<div><p v-for=\"obj in lists\">{{obj.name}}</p></div>',\n        data: {\n          lists: [\n            { name: 'A' },\n            { name: 'B' },\n            { name: 'C' }\n          ]\n        }\n      }).$mount()\n      expect(vm.$el.innerHTML).toBe('<p>A</p><p>B</p><p>C</p>')\n      Vue.delete(vm.lists, 1)\n      waitForUpdate(() => {\n        expect(vm.$el.innerHTML).toBe('<p>A</p><p>C</p>')\n        Vue.delete(vm.lists, NaN)\n      }).then(() => {\n        expect(vm.$el.innerHTML).toBe('<p>A</p><p>C</p>')\n        Vue.delete(vm.lists, -1)\n      }).then(() => {\n        expect(vm.$el.innerHTML).toBe('<p>A</p><p>C</p>')\n        Vue.delete(vm.lists, '1.3')\n      }).then(() => {\n        expect(vm.$el.innerHTML).toBe('<p>A</p><p>C</p>')\n        Vue.delete(vm.lists, true)\n      }).then(() => {\n        expect(vm.$el.innerHTML).toBe('<p>A</p><p>C</p>')\n        Vue.delete(vm.lists, {})\n      }).then(() => {\n        expect(vm.$el.innerHTML).toBe('<p>A</p><p>C</p>')\n        Vue.delete(vm.lists, '1')\n      }).then(() => {\n        expect(vm.$el.innerHTML).toBe('<p>A</p>')\n        /* eslint-disable no-new-wrappers */\n        Vue.delete(vm.lists, new Number(0))\n      }).then(() => {\n        expect(vm.$el.innerHTML).toBe('')\n      }).then(done)\n    })\n  })\n})\n"
  },
  {
    "path": "test/unit/features/global-api/use.spec.js",
    "content": "import Vue from 'vue'\n\ndescribe('Global API: use', () => {\n  const def = {}\n  const options = {}\n  const pluginStub = {\n    install: (Vue, opts) => {\n      Vue.directive('plugin-test', def)\n      expect(opts).toBe(options)\n    }\n  }\n\n  it('should apply Object plugin', () => {\n    Vue.use(pluginStub, options)\n    expect(Vue.options.directives['plugin-test']).toBe(def)\n    delete Vue.options.directives['plugin-test']\n    expect(Vue.options.directives['plugin-test']).toBeUndefined()\n\n    // should not double apply\n    Vue.use(pluginStub, options)\n    expect(Vue.options.directives['plugin-test']).toBeUndefined()\n  })\n\n  it('should apply Function plugin', () => {\n    Vue.use(pluginStub.install, options)\n    expect(Vue.options.directives['plugin-test']).toBe(def)\n    delete Vue.options.directives['plugin-test']\n  })\n\n  it('should work on extended constructors without polluting the base', () => {\n    const Ctor = Vue.extend({})\n    Ctor.use(pluginStub, options)\n    expect(Vue.options.directives['plugin-test']).toBeUndefined()\n    expect(Ctor.options.directives['plugin-test']).toBe(def)\n  })\n\n  // Github issue #5970\n  it('should work on multi version', () => {\n    const Ctor1 = Vue.extend({})\n    const Ctor2 = Vue.extend({})\n\n    Ctor1.use(pluginStub, options)\n    expect(Vue.options.directives['plugin-test']).toBeUndefined()\n    expect(Ctor1.options.directives['plugin-test']).toBe(def)\n\n    // multi version Vue Ctor with the same cid\n    Ctor2.cid = Ctor1.cid\n    Ctor2.use(pluginStub, options)\n    expect(Vue.options.directives['plugin-test']).toBeUndefined()\n    expect(Ctor2.options.directives['plugin-test']).toBe(def)\n  })\n})\n"
  },
  {
    "path": "test/unit/features/instance/init.spec.js",
    "content": "import Vue from 'vue'\n\ndescribe('Initialization', () => {\n  it('without new', () => {\n    try { Vue() } catch (e) {}\n    expect('Vue is a constructor and should be called with the `new` keyword').toHaveBeenWarned()\n  })\n\n  it('with new', () => {\n    expect(new Vue() instanceof Vue).toBe(true)\n  })\n})\n"
  },
  {
    "path": "test/unit/features/instance/methods-data.spec.js",
    "content": "import Vue from 'vue'\n\ndescribe('Instance methods data', () => {\n  it('$set/$delete', done => {\n    const vm = new Vue({\n      template: '<div>{{ a.msg }}</div>',\n      data: {\n        a: {}\n      }\n    }).$mount()\n    expect(vm.$el.innerHTML).toBe('')\n    vm.$set(vm.a, 'msg', 'hello')\n    waitForUpdate(() => {\n      expect(vm.$el.innerHTML).toBe('hello')\n      vm.$delete(vm.a, 'msg')\n    }).then(() => {\n      expect(vm.$el.innerHTML).toBe('')\n    }).then(done)\n  })\n\n  describe('$watch', () => {\n    let vm, spy\n    beforeEach(() => {\n      spy = jasmine.createSpy('watch')\n      vm = new Vue({\n        data: {\n          a: {\n            b: 1\n          }\n        },\n        methods: {\n          foo: spy\n        }\n      })\n    })\n\n    it('basic usage', done => {\n      vm.$watch('a.b', spy)\n      vm.a.b = 2\n      waitForUpdate(() => {\n        expect(spy.calls.count()).toBe(1)\n        expect(spy).toHaveBeenCalledWith(2, 1)\n        vm.a = { b: 3 }\n      }).then(() => {\n        expect(spy.calls.count()).toBe(2)\n        expect(spy).toHaveBeenCalledWith(3, 2)\n      }).then(done)\n    })\n\n    it('immediate', () => {\n      vm.$watch('a.b', spy, { immediate: true })\n      expect(spy.calls.count()).toBe(1)\n      expect(spy).toHaveBeenCalledWith(1)\n    })\n\n    it('unwatch', done => {\n      const unwatch = vm.$watch('a.b', spy)\n      unwatch()\n      vm.a.b = 2\n      waitForUpdate(() => {\n        expect(spy.calls.count()).toBe(0)\n      }).then(done)\n    })\n\n    it('function watch', done => {\n      vm.$watch(function () {\n        return this.a.b\n      }, spy)\n      vm.a.b = 2\n      waitForUpdate(() => {\n        expect(spy).toHaveBeenCalledWith(2, 1)\n      }).then(done)\n    })\n\n    it('deep watch', done => {\n      var oldA = vm.a\n      vm.$watch('a', spy, { deep: true })\n      vm.a.b = 2\n      waitForUpdate(() => {\n        expect(spy).toHaveBeenCalledWith(oldA, oldA)\n        vm.a = { b: 3 }\n      }).then(() => {\n        expect(spy).toHaveBeenCalledWith(vm.a, oldA)\n      }).then(done)\n    })\n\n    it('handler option', done => {\n      var oldA = vm.a\n      vm.$watch('a', {\n        handler: spy,\n        deep: true\n      })\n      vm.a.b = 2\n      waitForUpdate(() => {\n        expect(spy).toHaveBeenCalledWith(oldA, oldA)\n        vm.a = { b: 3 }\n      }).then(() => {\n        expect(spy).toHaveBeenCalledWith(vm.a, oldA)\n      }).then(done)\n    })\n\n    it('handler option in string', () => {\n      vm.$watch('a.b', {\n        handler: 'foo',\n        immediate: true\n      })\n      expect(spy.calls.count()).toBe(1)\n      expect(spy).toHaveBeenCalledWith(1)\n    })\n\n    it('warn expresssion', () => {\n      vm.$watch('a + b', spy)\n      expect('Watcher only accepts simple dot-delimited paths').toHaveBeenWarned()\n    })\n  })\n})\n"
  },
  {
    "path": "test/unit/features/instance/methods-events.spec.js",
    "content": "import Vue from 'vue'\n\ndescribe('Instance methods events', () => {\n  let vm, spy\n  beforeEach(() => {\n    vm = new Vue()\n    spy = jasmine.createSpy('emitter')\n  })\n\n  it('$on', () => {\n    vm.$on('test', function () {\n      // expect correct context\n      expect(this).toBe(vm)\n      spy.apply(this, arguments)\n    })\n    vm.$emit('test', 1, 2, 3, 4)\n    expect(spy.calls.count()).toBe(1)\n    expect(spy).toHaveBeenCalledWith(1, 2, 3, 4)\n  })\n\n  it('$on multi event', () => {\n    vm.$on(['test1', 'test2'], function () {\n      expect(this).toBe(vm)\n      spy.apply(this, arguments)\n    })\n    vm.$emit('test1', 1, 2, 3, 4)\n    expect(spy.calls.count()).toBe(1)\n    expect(spy).toHaveBeenCalledWith(1, 2, 3, 4)\n    vm.$emit('test2', 5, 6, 7, 8)\n    expect(spy.calls.count()).toBe(2)\n    expect(spy).toHaveBeenCalledWith(5, 6, 7, 8)\n  })\n\n  it('$off multi event', () => {\n    vm.$on(['test1', 'test2', 'test3'], spy)\n    vm.$off(['test1', 'test2'], spy)\n    vm.$emit('test1')\n    vm.$emit('test2')\n    expect(spy).not.toHaveBeenCalled()\n    vm.$emit('test3', 1, 2, 3, 4)\n    expect(spy.calls.count()).toBe(1)\n  })\n\n  it('$once', () => {\n    vm.$once('test', spy)\n    vm.$emit('test', 1, 2, 3)\n    vm.$emit('test', 2, 3, 4)\n    expect(spy.calls.count()).toBe(1)\n    expect(spy).toHaveBeenCalledWith(1, 2, 3)\n  })\n\n  it('$off', () => {\n    vm.$on('test1', spy)\n    vm.$on('test2', spy)\n    vm.$off()\n    vm.$emit('test1')\n    vm.$emit('test2')\n    expect(spy).not.toHaveBeenCalled()\n  })\n\n  it('$off event', () => {\n    vm.$on('test1', spy)\n    vm.$on('test2', spy)\n    vm.$off('test1')\n    vm.$off('test1') // test off something that's already off\n    vm.$emit('test1', 1)\n    vm.$emit('test2', 2)\n    expect(spy.calls.count()).toBe(1)\n    expect(spy).toHaveBeenCalledWith(2)\n  })\n\n  it('$off event + fn', () => {\n    var spy2 = jasmine.createSpy('emitter')\n    vm.$on('test', spy)\n    vm.$on('test', spy2)\n    vm.$off('test', spy)\n    vm.$emit('test', 1, 2, 3)\n    expect(spy).not.toHaveBeenCalled()\n    expect(spy2.calls.count()).toBe(1)\n    expect(spy2).toHaveBeenCalledWith(1, 2, 3)\n  })\n})\n"
  },
  {
    "path": "test/unit/features/instance/methods-lifecycle.spec.js",
    "content": "import Vue from 'vue'\n\ndescribe('Instance methods lifecycle', () => {\n  describe('$mount', () => {\n    it('empty mount', () => {\n      const vm = new Vue({\n        data: { msg: 'hi' },\n        template: '<div>{{ msg }}</div>'\n      }).$mount()\n      expect(vm.$el.tagName).toBe('DIV')\n      expect(vm.$el.textContent).toBe('hi')\n    })\n\n    it('mount to existing element', () => {\n      const el = document.createElement('div')\n      el.innerHTML = '{{ msg }}'\n      const vm = new Vue({\n        data: { msg: 'hi' }\n      }).$mount(el)\n      expect(vm.$el.tagName).toBe('DIV')\n      expect(vm.$el.textContent).toBe('hi')\n    })\n\n    it('mount to id', () => {\n      const el = document.createElement('div')\n      el.id = 'mount-test'\n      el.innerHTML = '{{ msg }}'\n      document.body.appendChild(el)\n      const vm = new Vue({\n        data: { msg: 'hi' }\n      }).$mount('#mount-test')\n      expect(vm.$el.tagName).toBe('DIV')\n      expect(vm.$el.textContent).toBe('hi')\n    })\n  })\n\n  describe('$destroy', () => {\n    it('remove self from parent', () => {\n      const vm = new Vue({\n        template: '<test></test>',\n        components: {\n          test: { template: '<div></div>' }\n        }\n      }).$mount()\n      vm.$children[0].$destroy()\n      expect(vm.$children.length).toBe(0)\n    })\n\n    it('teardown watchers', () => {\n      const vm = new Vue({\n        data: { a: 123 },\n        template: '<div></div>'\n      }).$mount()\n      vm.$watch('a', () => {})\n      vm.$destroy()\n      expect(vm._watcher.active).toBe(false)\n      expect(vm._watchers.every(w => !w.active)).toBe(true)\n    })\n\n    it('remove self from data observer', () => {\n      const vm = new Vue({ data: { a: 1 }})\n      vm.$destroy()\n      expect(vm.$data.__ob__.vmCount).toBe(0)\n    })\n\n    it('avoid duplicate calls', () => {\n      const spy = jasmine.createSpy('destroy')\n      const vm = new Vue({\n        beforeDestroy: spy\n      })\n      vm.$destroy()\n      vm.$destroy()\n      expect(spy.calls.count()).toBe(1)\n    })\n  })\n\n  describe('$forceUpdate', () => {\n    it('should force update', done => {\n      const vm = new Vue({\n        data: {\n          a: {}\n        },\n        template: '<div>{{ a.b }}</div>'\n      }).$mount()\n      expect(vm.$el.textContent).toBe('')\n      vm.a.b = 'foo'\n      waitForUpdate(() => {\n        // should not work because adding new property\n        expect(vm.$el.textContent).toBe('')\n        vm.$forceUpdate()\n      }).then(() => {\n        expect(vm.$el.textContent).toBe('foo')\n      }).then(done)\n    })\n  })\n\n  describe('$nextTick', () => {\n    it('should be called after DOM update in correct context', done => {\n      const vm = new Vue({\n        template: '<div>{{ msg }}</div>',\n        data: {\n          msg: 'foo'\n        }\n      }).$mount()\n      vm.msg = 'bar'\n      vm.$nextTick(function () {\n        expect(this).toBe(vm)\n        expect(vm.$el.textContent).toBe('bar')\n        done()\n      })\n    })\n\n    if (typeof Promise !== 'undefined') {\n      it('should be called after DOM update in correct context, when using Promise syntax', done => {\n        const vm = new Vue({\n          template: '<div>{{ msg }}</div>',\n          data: {\n            msg: 'foo'\n          }\n        }).$mount()\n        vm.msg = 'bar'\n        vm.$nextTick().then(ctx => {\n          expect(ctx).toBe(vm)\n          expect(vm.$el.textContent).toBe('bar')\n          done()\n        })\n      })\n    }\n  })\n})\n"
  },
  {
    "path": "test/unit/features/instance/properties.spec.js",
    "content": "import Vue from 'vue'\n\ndescribe('Instance properties', () => {\n  it('$data', () => {\n    const data = { a: 1 }\n    const vm = new Vue({\n      data\n    })\n    expect(vm.a).toBe(1)\n    expect(vm.$data).toBe(data)\n    // vm -> data\n    vm.a = 2\n    expect(data.a).toBe(2)\n    // data -> vm\n    data.a = 3\n    expect(vm.a).toBe(3)\n  })\n\n  it('$options', () => {\n    const A = Vue.extend({\n      methods: {\n        a () {}\n      }\n    })\n    const vm = new A({\n      methods: {\n        b () {}\n      }\n    })\n    expect(typeof vm.$options.methods.a).toBe('function')\n    expect(typeof vm.$options.methods.b).toBe('function')\n  })\n\n  it('$root/$children', done => {\n    const vm = new Vue({\n      template: '<div><test v-if=\"ok\"></test></div>',\n      data: { ok: true },\n      components: {\n        test: {\n          template: '<div></div>'\n        }\n      }\n    }).$mount()\n    expect(vm.$root).toBe(vm)\n    expect(vm.$children.length).toBe(1)\n    expect(vm.$children[0].$root).toBe(vm)\n    vm.ok = false\n    waitForUpdate(() => {\n      expect(vm.$children.length).toBe(0)\n      vm.ok = true\n    }).then(() => {\n      expect(vm.$children.length).toBe(1)\n      expect(vm.$children[0].$root).toBe(vm)\n    }).then(done)\n  })\n\n  it('$parent', () => {\n    const calls = []\n    const makeOption = name => ({\n      name,\n      template: `<div><slot></slot></div>`,\n      created () {\n        calls.push(`${name}:${this.$parent.$options.name}`)\n      }\n    })\n    new Vue({\n      template: `\n        <div>\n          <outer><middle><inner></inner></middle></outer>\n          <next></next>\n        </div>\n      `,\n      components: {\n        outer: makeOption('outer'),\n        middle: makeOption('middle'),\n        inner: makeOption('inner'),\n        next: makeOption('next')\n      }\n    }).$mount()\n    expect(calls).toEqual(['outer:undefined', 'middle:outer', 'inner:middle', 'next:undefined'])\n  })\n\n  it('$props', done => {\n    const Comp = Vue.extend({\n      props: ['msg'],\n      template: '<div>{{ msg }} {{ $props.msg }}</div>'\n    })\n    const vm = new Comp({\n      propsData: {\n        msg: 'foo'\n      }\n    }).$mount()\n    // check render\n    expect(vm.$el.textContent).toContain('foo foo')\n    // warn set\n    vm.$props = {}\n    expect('$props is readonly').toHaveBeenWarned()\n    // check existence\n    expect(vm.$props.msg).toBe('foo')\n    // check change\n    vm.msg = 'bar'\n    expect(vm.$props.msg).toBe('bar')\n    waitForUpdate(() => {\n      expect(vm.$el.textContent).toContain('bar bar')\n    }).then(() => {\n      vm.$props.msg = 'baz'\n      expect(vm.msg).toBe('baz')\n    }).then(() => {\n      expect(vm.$el.textContent).toContain('baz baz')\n    }).then(done)\n  })\n\n  it('warn mutating $props', () => {\n    const Comp = {\n      props: ['msg'],\n      render () {},\n      mounted () {\n        expect(this.$props.msg).toBe('foo')\n        this.$props.msg = 'bar'\n      }\n    }\n    new Vue({\n      template: `<comp ref=\"comp\" msg=\"foo\" />`,\n      components: { Comp }\n    }).$mount()\n    expect(`Avoid mutating a prop`).toHaveBeenWarned()\n  })\n\n  it('$attrs', done => {\n    const vm = new Vue({\n      template: `<foo :id=\"foo\" bar=\"1\"/>`,\n      data: { foo: 'foo' },\n      components: {\n        foo: {\n          props: ['bar'],\n          template: `<div><div v-bind=\"$attrs\"></div></div>`\n        }\n      }\n    }).$mount()\n    expect(vm.$el.children[0].id).toBe('foo')\n    expect(vm.$el.children[0].hasAttribute('bar')).toBe(false)\n    vm.foo = 'bar'\n    waitForUpdate(() => {\n      expect(vm.$el.children[0].id).toBe('bar')\n      expect(vm.$el.children[0].hasAttribute('bar')).toBe(false)\n    }).then(done)\n  })\n\n  it('warn mutating $attrs', () => {\n    const vm = new Vue()\n    vm.$attrs = {}\n    expect(`$attrs is readonly`).toHaveBeenWarned()\n  })\n\n  it('$listeners', done => {\n    const spyA = jasmine.createSpy('A')\n    const spyB = jasmine.createSpy('B')\n    const vm = new Vue({\n      template: `<foo @click=\"foo\"/>`,\n      data: { foo: spyA },\n      components: {\n        foo: {\n          template: `<div v-on=\"$listeners\"></div>`\n        }\n      }\n    }).$mount()\n\n    // has to be in dom for test to pass in IE\n    document.body.appendChild(vm.$el)\n\n    triggerEvent(vm.$el, 'click')\n    expect(spyA.calls.count()).toBe(1)\n    expect(spyB.calls.count()).toBe(0)\n\n    vm.foo = spyB\n    waitForUpdate(() => {\n      triggerEvent(vm.$el, 'click')\n      expect(spyA.calls.count()).toBe(1)\n      expect(spyB.calls.count()).toBe(1)\n      document.body.removeChild(vm.$el)\n    }).then(done)\n  })\n\n  it('warn mutating $listeners', () => {\n    const vm = new Vue()\n    vm.$listeners = {}\n    expect(`$listeners is readonly`).toHaveBeenWarned()\n  })\n})\n"
  },
  {
    "path": "test/unit/features/instance/render-proxy.spec.js",
    "content": "import Vue from 'vue'\n\nif (typeof Proxy !== 'undefined') {\n  describe('render proxy', () => {\n    it('should warn missing property in render fns with `with`', () => {\n      new Vue({\n        template: `<div>{{ a }}</div>`\n      }).$mount()\n      expect(`Property or method \"a\" is not defined`).toHaveBeenWarned()\n    })\n\n    it('should warn missing property in render fns without `with`', () => {\n      const render = function (h) {\n        return h('div', [this.a])\n      }\n      render._withStripped = true\n      new Vue({\n        render\n      }).$mount()\n      expect(`Property or method \"a\" is not defined`).toHaveBeenWarned()\n    })\n\n    it('should not warn for hand-written render functions', () => {\n      new Vue({\n        render (h) {\n          return h('div', [this.a])\n        }\n      }).$mount()\n      expect(`Property or method \"a\" is not defined`).not.toHaveBeenWarned()\n    })\n  })\n}\n"
  },
  {
    "path": "test/unit/features/options/_scopeId.spec.js",
    "content": "import Vue from 'vue'\n\ndescribe('Options _scopeId', () => {\n  it('should add scopeId attributes', () => {\n    const vm = new Vue({\n      _scopeId: 'foo',\n      template: '<div><p><span></span></p></div>'\n    }).$mount()\n    expect(vm.$el.hasAttribute('foo')).toBe(true)\n    expect(vm.$el.children[0].hasAttribute('foo')).toBe(true)\n    expect(vm.$el.children[0].children[0].hasAttribute('foo')).toBe(true)\n  })\n\n  it('should add scopedId attributes from both parent and child on child root', () => {\n    const vm = new Vue({\n      _scopeId: 'foo',\n      template: '<div><child></child></div>',\n      components: {\n        child: {\n          _scopeId: 'bar',\n          template: '<div></div>'\n        }\n      }\n    }).$mount()\n    expect(vm.$el.children[0].hasAttribute('foo')).toBe(true)\n    expect(vm.$el.children[0].hasAttribute('bar')).toBe(true)\n  })\n\n  it('should add scopedId attributes from both parent and child on slot contents', () => {\n    const vm = new Vue({\n      _scopeId: 'foo',\n      template: '<div><child><p>hi</p></child></div>',\n      components: {\n        child: {\n          _scopeId: 'bar',\n          template: '<div><slot></slot></div>'\n        }\n      }\n    }).$mount()\n    expect(vm.$el.children[0].children[0].hasAttribute('foo')).toBe(true)\n    expect(vm.$el.children[0].children[0].hasAttribute('bar')).toBe(true)\n  })\n\n  // #4774\n  it('should not discard parent scopeId when component root element is replaced', done => {\n    const vm = new Vue({\n      _scopeId: 'data-1',\n      template: `<div><child ref=\"child\" /></div>`,\n      components: {\n        child: {\n          _scopeId: 'data-2',\n          data: () => ({ show: true }),\n          template: '<div v-if=\"show\"></div>'\n        }\n      }\n    }).$mount()\n\n    const child = vm.$refs.child\n\n    expect(child.$el.hasAttribute('data-1')).toBe(true)\n    expect(child.$el.hasAttribute('data-2')).toBe(true)\n\n    child.show = false\n    waitForUpdate(() => {\n      child.show = true\n    }).then(() => {\n      expect(child.$el.hasAttribute('data-1')).toBe(true)\n      expect(child.$el.hasAttribute('data-2')).toBe(true)\n    }).then(done)\n  })\n})\n"
  },
  {
    "path": "test/unit/features/options/comments.spec.js",
    "content": "import Vue from 'vue'\n\ndescribe('Comments', () => {\n  it('comments should be kept', () => {\n    const vm = new Vue({\n      comments: true,\n      data () {\n        return {\n          foo: 1\n        }\n      },\n      template: '<div><span>node1</span><!--comment1-->{{foo}}<!--comment2--></div>'\n    }).$mount()\n    expect(vm.$el.innerHTML).toEqual('<span>node1</span><!--comment1-->1<!--comment2-->')\n  })\n})\n"
  },
  {
    "path": "test/unit/features/options/components.spec.js",
    "content": "import Vue from 'vue'\nimport { UA } from 'core/util/env'\n\ndescribe('Options components', () => {\n  it('should accept plain object', () => {\n    const vm = new Vue({\n      template: '<test></test>',\n      components: {\n        test: {\n          template: '<div>hi</div>'\n        }\n      }\n    }).$mount()\n    expect(vm.$el.tagName).toBe('DIV')\n    expect(vm.$el.textContent).toBe('hi')\n  })\n\n  it('should accept extended constructor', () => {\n    const Test = Vue.extend({\n      template: '<div>hi</div>'\n    })\n    const vm = new Vue({\n      template: '<test></test>',\n      components: {\n        test: Test\n      }\n    }).$mount()\n    expect(vm.$el.tagName).toBe('DIV')\n    expect(vm.$el.textContent).toBe('hi')\n  })\n\n  it('should accept camelCase', () => {\n    const myComp = {\n      template: '<div>hi</div>'\n    }\n    const vm = new Vue({\n      template: '<my-comp></my-comp>',\n      components: {\n        myComp\n      }\n    }).$mount()\n    expect(vm.$el.tagName).toBe('DIV')\n    expect(vm.$el.textContent).toBe('hi')\n  })\n\n  it('should accept PascalCase', () => {\n    const MyComp = {\n      template: '<div>hi</div>'\n    }\n    const vm = new Vue({\n      template: '<my-comp></my-comp>',\n      components: {\n        MyComp\n      }\n    }).$mount()\n    expect(vm.$el.tagName).toBe('DIV')\n    expect(vm.$el.textContent).toBe('hi')\n  })\n\n  it('should warn native HTML elements', () => {\n    new Vue({\n      components: {\n        div: { template: '<div></div>' }\n      }\n    })\n    expect('Do not use built-in or reserved HTML elements as component').toHaveBeenWarned()\n  })\n\n  it('should warn built-in elements', () => {\n    new Vue({\n      components: {\n        component: { template: '<div></div>' }\n      }\n    })\n    expect('Do not use built-in or reserved HTML elements as component').toHaveBeenWarned()\n  })\n\n  // the HTMLUnknownElement check doesn't work in Android 4.2\n  // but since it doesn't support custom elements nor will any dev use it\n  // as their primary debugging browser, it doesn't really matter.\n  if (!(UA && /android 4\\.2/.test(UA))) {\n    it('warn non-existent', () => {\n      new Vue({\n        template: '<test></test>'\n      }).$mount()\n      expect('Unknown custom element: <test>').toHaveBeenWarned()\n    })\n  }\n})\n"
  },
  {
    "path": "test/unit/features/options/computed.spec.js",
    "content": "import Vue from 'vue'\nimport testObjectOption from '../../../helpers/test-object-option'\n\ndescribe('Options computed', () => {\n  it('basic usage', done => {\n    const vm = new Vue({\n      template: '<div>{{ b }}</div>',\n      data: {\n        a: 1\n      },\n      computed: {\n        b () {\n          return this.a + 1\n        }\n      }\n    }).$mount()\n    expect(vm.b).toBe(2)\n    expect(vm.$el.textContent).toBe('2')\n    vm.a = 2\n    expect(vm.b).toBe(3)\n    waitForUpdate(() => {\n      expect(vm.$el.textContent).toBe('3')\n    }).then(done)\n  })\n\n  it('with setter', done => {\n    const vm = new Vue({\n      template: '<div>{{ b }}</div>',\n      data: {\n        a: 1\n      },\n      computed: {\n        b: {\n          get () { return this.a + 1 },\n          set (v) { this.a = v - 1 }\n        }\n      }\n    }).$mount()\n    expect(vm.b).toBe(2)\n    expect(vm.$el.textContent).toBe('2')\n    vm.a = 2\n    expect(vm.b).toBe(3)\n    waitForUpdate(() => {\n      expect(vm.$el.textContent).toBe('3')\n      vm.b = 1\n      expect(vm.a).toBe(0)\n    }).then(() => {\n      expect(vm.$el.textContent).toBe('1')\n    }).then(done)\n  })\n\n  testObjectOption('computed')\n\n  it('warn with setter and no getter', () => {\n    const vm = new Vue({\n      template: `\n        <div>\n          <test></test>\n        </div>\n      `,\n      components: {\n        test: {\n          data () {\n            return {\n              a: 1\n            }\n          },\n          computed: {\n            b: {\n              set (v) { this.a = v }\n            }\n          },\n          template: `<div>{{a}}</div>`\n        }\n      }\n    }).$mount()\n    expect(vm.$el.innerHTML).toBe('<div>1</div>')\n    expect('No getter function has been defined for computed property \"b\".').toHaveBeenWarned()\n  })\n\n  it('watching computed', done => {\n    const spy = jasmine.createSpy('watch computed')\n    const vm = new Vue({\n      data: {\n        a: 1\n      },\n      computed: {\n        b () { return this.a + 1 }\n      }\n    })\n    vm.$watch('b', spy)\n    vm.a = 2\n    waitForUpdate(() => {\n      expect(spy).toHaveBeenCalledWith(3, 2)\n    }).then(done)\n  })\n\n  it('caching', () => {\n    const spy = jasmine.createSpy('cached computed')\n    const vm = new Vue({\n      data: {\n        a: 1\n      },\n      computed: {\n        b () {\n          spy()\n          return this.a + 1\n        }\n      }\n    })\n    expect(spy.calls.count()).toBe(0)\n    vm.b\n    expect(spy.calls.count()).toBe(1)\n    vm.b\n    expect(spy.calls.count()).toBe(1)\n  })\n\n  it('cache: false', () => {\n    const spy = jasmine.createSpy('cached computed')\n    const vm = new Vue({\n      data: {\n        a: 1\n      },\n      computed: {\n        b: {\n          cache: false,\n          get () {\n            spy()\n            return this.a + 1\n          }\n        }\n      }\n    })\n    expect(spy.calls.count()).toBe(0)\n    vm.b\n    expect(spy.calls.count()).toBe(1)\n    vm.b\n    expect(spy.calls.count()).toBe(2)\n  })\n\n  it('as component', done => {\n    const Comp = Vue.extend({\n      template: `<div>{{ b }} {{ c }}</div>`,\n      data () {\n        return { a: 1 }\n      },\n      computed: {\n        // defined on prototype\n        b () {\n          return this.a + 1\n        }\n      }\n    })\n\n    const vm = new Comp({\n      computed: {\n        // defined at instantiation\n        c () {\n          return this.b + 1\n        }\n      }\n    }).$mount()\n    expect(vm.b).toBe(2)\n    expect(vm.c).toBe(3)\n    expect(vm.$el.textContent).toBe('2 3')\n    vm.a = 2\n    expect(vm.b).toBe(3)\n    expect(vm.c).toBe(4)\n    waitForUpdate(() => {\n      expect(vm.$el.textContent).toBe('3 4')\n    }).then(done)\n  })\n\n  it('warn conflict with data', () => {\n    new Vue({\n      data: {\n        a: 1\n      },\n      computed: {\n        a: () => 2\n      }\n    })\n    expect(`computed property \"a\" is already defined in data`).toHaveBeenWarned()\n  })\n\n  it('warn conflict with props', () => {\n    new Vue({\n      props: ['a'],\n      propsData: { a: 1 },\n      computed: {\n        a: () => 2\n      }\n    })\n    expect(`computed property \"a\" is already defined as a prop`).toHaveBeenWarned()\n  })\n\n  it('rethrow computed error', () => {\n    const vm = new Vue({\n      computed: {\n        a: () => {\n          throw new Error('rethrow')\n        }\n      }\n    })\n    expect(() => vm.a).toThrowError('rethrow')\n  })\n})\n"
  },
  {
    "path": "test/unit/features/options/data.spec.js",
    "content": "import Vue from 'vue'\n\ndescribe('Options data', () => {\n  it('should proxy and be reactive', done => {\n    const data = { msg: 'foo' }\n    const vm = new Vue({\n      data,\n      template: '<div>{{ msg }}</div>'\n    }).$mount()\n    expect(vm.$data).toEqual({ msg: 'foo' })\n    expect(vm.$data).toBe(data)\n    data.msg = 'bar'\n    waitForUpdate(() => {\n      expect(vm.$el.textContent).toBe('bar')\n    }).then(done)\n  })\n\n  it('should merge data properly', () => {\n    const Test = Vue.extend({\n      data () {\n        return { a: 1 }\n      }\n    })\n    let vm = new Test({\n      data: { b: 2 }\n    })\n    expect(vm.a).toBe(1)\n    expect(vm.b).toBe(2)\n    // no instance data\n    vm = new Test()\n    expect(vm.a).toBe(1)\n    // no child-val\n    const Extended = Test.extend({})\n    vm = new Extended()\n    expect(vm.a).toBe(1)\n    // recursively merge objects\n    const WithObject = Vue.extend({\n      data () {\n        return {\n          obj: {\n            a: 1\n          }\n        }\n      }\n    })\n    vm = new WithObject({\n      data: {\n        obj: {\n          b: 2\n        }\n      }\n    })\n    expect(vm.obj.a).toBe(1)\n    expect(vm.obj.b).toBe(2)\n  })\n\n  it('should warn non-function during extend', () => {\n    Vue.extend({\n      data: { msg: 'foo' }\n    })\n    expect('The \"data\" option should be a function').toHaveBeenWarned()\n  })\n\n  it('should warn non object return', () => {\n    new Vue({\n      data () {}\n    })\n    expect('data functions should return an object').toHaveBeenWarned()\n  })\n\n  it('should warn replacing root $data', () => {\n    const vm = new Vue({\n      data: {}\n    })\n    vm.$data = {}\n    expect('Avoid replacing instance root $data').toHaveBeenWarned()\n  })\n\n  it('should have access to props', () => {\n    const Test = {\n      props: ['a'],\n      render () {},\n      data () {\n        return {\n          b: this.a\n        }\n      }\n    }\n    const vm = new Vue({\n      template: `<test ref=\"test\" :a=\"1\"></test>`,\n      components: { Test }\n    }).$mount()\n    expect(vm.$refs.test.b).toBe(1)\n  })\n\n  it('should have access to methods', () => {\n    const vm = new Vue({\n      methods: {\n        get () {\n          return { a: 1 }\n        }\n      },\n      data () {\n        return this.get()\n      }\n    })\n    expect(vm.a).toBe(1)\n  })\n})\n"
  },
  {
    "path": "test/unit/features/options/delimiters.spec.js",
    "content": "import Vue from 'vue'\n\ndescribe('Delimiters', () => {\n  it('default delimiters should work', () => {\n    const vm = new Vue({\n      data: {\n        a: 1\n      },\n      template: '<div>{{ a }}</div>'\n    }).$mount()\n    expect(vm.$el.textContent).toEqual('1')\n  })\n\n  it('custom delimiters should work', () => {\n    const vm = new Vue({\n      delimiters: ['[[', ']]'],\n      template: '<div>[[ a ]]</div>',\n      data: {\n        a: 1\n      }\n    }).$mount()\n\n    expect(vm.$el.textContent).toEqual('1')\n  })\n\n  it('default delimiters should be ignored when custom delimiters defined', () => {\n    const vm = new Vue({\n      delimiters: ['[[', ']]'],\n      template: '<div>{{ a }}</div>',\n      data: {\n        a: 1\n      }\n    }).$mount()\n\n    expect(vm.$el.textContent).toEqual('{{ a }}')\n  })\n\n  it('delimiters should only affect vm', () => {\n    const Component = Vue.extend({\n      data: function () {\n        return {\n          b: 2\n        }\n      },\n      template: '<span>[[ b ]]</span>'\n    })\n\n    const vm = new Vue({\n      delimiters: ['[[', ']]'],\n      template: '<div>[[ a ]] - <test-component></test-component></div>',\n      data: {\n        a: 2\n      },\n      components: {\n        'test-component': Component\n      }\n    }).$mount()\n\n    expect(vm.$el.textContent).toEqual('2 - [[ b ]]')\n  })\n\n  it('delimiters defined globally should work on all vms', () => {\n    Vue.options.delimiters = ['[[', ']]']\n\n    const Component = Vue.extend({\n      template: '<span>[[ a ]]</span>',\n      data: function () {\n        return {\n          a: 2\n        }\n      }\n    })\n\n    const vm = new Vue({\n      data: {\n        b: 1\n      },\n      template: '<div>[[ b ]] - <test-component></test-component></div>',\n      components: {\n        'test-component': Component\n      }\n    }).$mount()\n\n    expect(vm.$el.textContent).toEqual('1 - 2')\n      // restore default options\n    delete Vue.options.delimiters\n  })\n\n  it('component specific delimiters should override global delimiters', () => {\n    Vue.options.delimiters = ['[[', ']]']\n\n    const Component = Vue.extend({\n      delimiters: ['@{{', '}}'],\n      template: '<span>@{{ a }}</span>',\n      data: function () {\n        return {\n          a: 2\n        }\n      }\n    })\n\n    const vm = new Vue({\n      data: {\n        b: 1\n      },\n      template: '<div>[[ b ]] - <test-component></test-component></div>',\n      components: {\n        'test-component': Component\n      }\n    }).$mount()\n\n    expect(vm.$el.textContent).toEqual('1 - 2')\n      // restore default options\n    delete Vue.options.delimiters\n  })\n})\n"
  },
  {
    "path": "test/unit/features/options/directives.spec.js",
    "content": "import Vue from 'vue'\n\ndescribe('Options directives', () => {\n  it('basic usage', done => {\n    const bindSpy = jasmine.createSpy('bind')\n    const insertedSpy = jasmine.createSpy('inserted')\n    const updateSpy = jasmine.createSpy('update')\n    const componentUpdatedSpy = jasmine.createSpy('componentUpdated')\n    const unbindSpy = jasmine.createSpy('unbind')\n\n    const assertContext = (el, binding, vnode) => {\n      expect(vnode.context).toBe(vm)\n      expect(binding.arg).toBe('arg')\n      expect(binding.modifiers).toEqual({ hello: true })\n    }\n\n    const vm = new Vue({\n      template: '<div class=\"hi\"><div v-if=\"ok\" v-test:arg.hello=\"a\">{{ msg }}</div></div>',\n      data: {\n        msg: 'hi',\n        a: 'foo',\n        ok: true\n      },\n      directives: {\n        test: {\n          bind (el, binding, vnode) {\n            bindSpy()\n            assertContext(el, binding, vnode)\n            expect(binding.value).toBe('foo')\n            expect(binding.expression).toBe('a')\n            expect(binding.oldValue).toBeUndefined()\n            expect(el.parentNode).toBeNull()\n          },\n          inserted (el, binding, vnode) {\n            insertedSpy()\n            assertContext(el, binding, vnode)\n            expect(binding.value).toBe('foo')\n            expect(binding.expression).toBe('a')\n            expect(binding.oldValue).toBeUndefined()\n            expect(el.parentNode.className).toBe('hi')\n          },\n          update (el, binding, vnode, oldVnode) {\n            updateSpy()\n            assertContext(el, binding, vnode)\n            expect(el).toBe(vm.$el.children[0])\n            expect(oldVnode).not.toBe(vnode)\n            expect(binding.expression).toBe('a')\n            if (binding.value !== binding.oldValue) {\n              expect(binding.value).toBe('bar')\n              expect(binding.oldValue).toBe('foo')\n            }\n          },\n          componentUpdated (el, binding, vnode) {\n            componentUpdatedSpy()\n            assertContext(el, binding, vnode)\n          },\n          unbind (el, binding, vnode) {\n            unbindSpy()\n            assertContext(el, binding, vnode)\n          }\n        }\n      }\n    })\n\n    vm.$mount()\n    expect(bindSpy).toHaveBeenCalled()\n    expect(insertedSpy).toHaveBeenCalled()\n    expect(updateSpy).not.toHaveBeenCalled()\n    expect(componentUpdatedSpy).not.toHaveBeenCalled()\n    expect(unbindSpy).not.toHaveBeenCalled()\n    vm.a = 'bar'\n    waitForUpdate(() => {\n      expect(updateSpy).toHaveBeenCalled()\n      expect(componentUpdatedSpy).toHaveBeenCalled()\n      expect(unbindSpy).not.toHaveBeenCalled()\n      vm.msg = 'bye'\n    }).then(() => {\n      expect(componentUpdatedSpy.calls.count()).toBe(2)\n      vm.ok = false\n    }).then(() => {\n      expect(unbindSpy).toHaveBeenCalled()\n    }).then(done)\n  })\n\n  it('function shorthand', done => {\n    const spy = jasmine.createSpy('directive')\n    const vm = new Vue({\n      template: '<div v-test:arg.hello=\"a\"></div>',\n      data: { a: 'foo' },\n      directives: {\n        test (el, binding, vnode) {\n          expect(vnode.context).toBe(vm)\n          expect(binding.arg).toBe('arg')\n          expect(binding.modifiers).toEqual({ hello: true })\n          spy(binding.value, binding.oldValue)\n        }\n      }\n    })\n    vm.$mount()\n    expect(spy).toHaveBeenCalledWith('foo', undefined)\n    vm.a = 'bar'\n    waitForUpdate(() => {\n      expect(spy).toHaveBeenCalledWith('bar', 'foo')\n    }).then(done)\n  })\n\n  it('function shorthand (global)', done => {\n    const spy = jasmine.createSpy('directive')\n    Vue.directive('test', function (el, binding, vnode) {\n      expect(vnode.context).toBe(vm)\n      expect(binding.arg).toBe('arg')\n      expect(binding.modifiers).toEqual({ hello: true })\n      spy(binding.value, binding.oldValue)\n    })\n    const vm = new Vue({\n      template: '<div v-test:arg.hello=\"a\"></div>',\n      data: { a: 'foo' }\n    })\n    vm.$mount()\n    expect(spy).toHaveBeenCalledWith('foo', undefined)\n    vm.a = 'bar'\n    waitForUpdate(() => {\n      expect(spy).toHaveBeenCalledWith('bar', 'foo')\n      delete Vue.options.directives.test\n    }).then(done)\n  })\n\n  it('should teardown directives on old vnodes when new vnodes have none', done => {\n    const vm = new Vue({\n      data: {\n        ok: true\n      },\n      template: `\n        <div>\n          <div v-if=\"ok\" v-test>a</div>\n          <div v-else class=\"b\">b</div>\n        </div>\n      `,\n      directives: {\n        test: {\n          bind: el => { el.id = 'a' },\n          unbind: el => { el.id = '' }\n        }\n      }\n    }).$mount()\n    expect(vm.$el.children[0].id).toBe('a')\n    vm.ok = false\n    waitForUpdate(() => {\n      expect(vm.$el.children[0].id).toBe('')\n      expect(vm.$el.children[0].className).toBe('b')\n    }).then(done)\n  })\n\n  it('should properly handle same node with different directive sets', done => {\n    const spies = {}\n    const createSpy = name => (spies[name] = jasmine.createSpy(name))\n    const vm = new Vue({\n      data: {\n        ok: true,\n        val: 123\n      },\n      template: `\n        <div>\n          <div v-if=\"ok\" v-test=\"val\" v-test.hi=\"val\"></div>\n          <div v-if=\"!ok\" v-test.hi=\"val\" v-test2=\"val\"></div>\n        </div>\n      `,\n      directives: {\n        test: {\n          bind: createSpy('bind1'),\n          inserted: createSpy('inserted1'),\n          update: createSpy('update1'),\n          componentUpdated: createSpy('componentUpdated1'),\n          unbind: createSpy('unbind1')\n        },\n        test2: {\n          bind: createSpy('bind2'),\n          inserted: createSpy('inserted2'),\n          update: createSpy('update2'),\n          componentUpdated: createSpy('componentUpdated2'),\n          unbind: createSpy('unbind2')\n        }\n      }\n    }).$mount()\n\n    expect(spies.bind1.calls.count()).toBe(2)\n    expect(spies.inserted1.calls.count()).toBe(2)\n    expect(spies.bind2.calls.count()).toBe(0)\n    expect(spies.inserted2.calls.count()).toBe(0)\n\n    vm.ok = false\n    waitForUpdate(() => {\n      // v-test with modifier should be updated\n      expect(spies.update1.calls.count()).toBe(1)\n      expect(spies.componentUpdated1.calls.count()).toBe(1)\n\n      // v-test without modifier should be unbound\n      expect(spies.unbind1.calls.count()).toBe(1)\n\n      // v-test2 should be bound\n      expect(spies.bind2.calls.count()).toBe(1)\n      expect(spies.inserted2.calls.count()).toBe(1)\n\n      vm.ok = true\n    }).then(() => {\n      // v-test without modifier should be bound again\n      expect(spies.bind1.calls.count()).toBe(3)\n      expect(spies.inserted1.calls.count()).toBe(3)\n\n      // v-test2 should be unbound\n      expect(spies.unbind2.calls.count()).toBe(1)\n\n      // v-test with modifier should be updated again\n      expect(spies.update1.calls.count()).toBe(2)\n      expect(spies.componentUpdated1.calls.count()).toBe(2)\n\n      vm.val = 234\n    }).then(() => {\n      expect(spies.update1.calls.count()).toBe(4)\n      expect(spies.componentUpdated1.calls.count()).toBe(4)\n    }).then(done)\n  })\n\n  it('warn non-existent', () => {\n    new Vue({\n      template: '<div v-test></div>'\n    }).$mount()\n    expect('Failed to resolve directive: test').toHaveBeenWarned()\n  })\n})\n"
  },
  {
    "path": "test/unit/features/options/el.spec.js",
    "content": "import Vue from 'vue'\n\ndescribe('Options el', () => {\n  it('basic usage', () => {\n    const el = document.createElement('div')\n    el.innerHTML = '<span>{{message}}</span>'\n    const vm = new Vue({\n      el,\n      data: { message: 'hello world' }\n    })\n    expect(vm.$el.tagName).toBe('DIV')\n    expect(vm.$el.textContent).toBe(vm.message)\n  })\n\n  it('should be replaced when use together with `template` option', () => {\n    const el = document.createElement('div')\n    el.innerHTML = '<span>{{message}}</span>'\n    const vm = new Vue({\n      el,\n      template: '<p id=\"app\"><span>{{message}}</span></p>',\n      data: { message: 'hello world' }\n    })\n    expect(vm.$el.tagName).toBe('P')\n    expect(vm.$el.textContent).toBe(vm.message)\n  })\n\n  it('should be replaced when use together with `render` option', () => {\n    const el = document.createElement('div')\n    el.innerHTML = '<span>{{message}}</span>'\n    const vm = new Vue({\n      el,\n      render (h) {\n        return h('p', { staticAttrs: { id: 'app' }}, [\n          h('span', {}, [this.message])\n        ])\n      },\n      data: { message: 'hello world' }\n    })\n    expect(vm.$el.tagName).toBe('P')\n    expect(vm.$el.textContent).toBe(vm.message)\n  })\n\n  it('svg element', () => {\n    const parent = document.createElement('div')\n    parent.innerHTML =\n      '<svg>' +\n        '<text :x=\"x\" :y=\"y\" :fill=\"color\">{{ text }}</text>' +\n        '<g><clipPath><foo></foo></clipPath></g>' +\n      '</svg>'\n    const vm = new Vue({\n      el: parent.childNodes[0],\n      data: {\n        x: 64,\n        y: 128,\n        color: 'red',\n        text: 'svg text'\n      }\n    })\n    expect(vm.$el.tagName).toBe('svg')\n    expect(vm.$el.childNodes[0].getAttribute('x')).toBe(vm.x.toString())\n    expect(vm.$el.childNodes[0].getAttribute('y')).toBe(vm.y.toString())\n    expect(vm.$el.childNodes[0].getAttribute('fill')).toBe(vm.color)\n    expect(vm.$el.childNodes[0].textContent).toBe(vm.text)\n    // nested, non-explicitly listed SVG elements\n    expect(vm.$el.childNodes[1].childNodes[0].namespaceURI).toContain('svg')\n    expect(vm.$el.childNodes[1].childNodes[0].childNodes[0].namespaceURI).toContain('svg')\n  })\n\n  // https://w3c.github.io/DOM-Parsing/#dfn-serializing-an-attribute-value\n  it('properly decode attribute values when parsing templates from DOM', () => {\n    const el = document.createElement('div')\n    el.innerHTML = '<a href=\"/a?foo=bar&baz=qux\" name=\"<abc>\" single=\\'\"hi\"\\'></a>'\n    const vm = new Vue({ el })\n    expect(vm.$el.children[0].getAttribute('href')).toBe('/a?foo=bar&baz=qux')\n    expect(vm.$el.children[0].getAttribute('name')).toBe('<abc>')\n    expect(vm.$el.children[0].getAttribute('single')).toBe('\"hi\"')\n  })\n\n  it('decode attribute value newlines when parsing templates from DOM in IE', () => {\n    const el = document.createElement('div')\n    el.innerHTML = `<a :style=\"{\\ncolor:'red'\\n}\"></a>`\n    const vm = new Vue({ el })\n    expect(vm.$el.children[0].style.color).toBe('red')\n  })\n\n  it('warn cannot find element', () => {\n    new Vue({ el: '#non-existent' })\n    expect('Cannot find element: #non-existent').toHaveBeenWarned()\n  })\n})\n"
  },
  {
    "path": "test/unit/features/options/extends.spec.js",
    "content": "import Vue from 'vue'\n\ndescribe('Options extends', () => {\n  it('should work on objects', () => {\n    const A = {\n      data () {\n        return { a: 1 }\n      }\n    }\n    const B = {\n      extends: A,\n      data () {\n        return { b: 2 }\n      }\n    }\n    const vm = new Vue({\n      extends: B,\n      data: {\n        c: 3\n      }\n    })\n    expect(vm.a).toBe(1)\n    expect(vm.b).toBe(2)\n    expect(vm.c).toBe(3)\n  })\n\n  it('should work on extended constructors', () => {\n    const A = Vue.extend({\n      data () {\n        return { a: 1 }\n      }\n    })\n    const B = Vue.extend({\n      extends: A,\n      data () {\n        return { b: 2 }\n      }\n    })\n    const vm = new Vue({\n      extends: B,\n      data: {\n        c: 3\n      }\n    })\n    expect(vm.a).toBe(1)\n    expect(vm.b).toBe(2)\n    expect(vm.c).toBe(3)\n  })\n\n  it('should work with global mixins + Object.prototype.watch', done => {\n    let fakeWatch = false\n    if (!Object.prototype.watch) {\n      fakeWatch = true\n      // eslint-disable-next-line no-extend-native\n      Object.defineProperty(Object.prototype, 'watch', {\n        writable: true,\n        configurable: true,\n        enumerable: false,\n        value: () => {}\n      })\n    }\n\n    Vue.mixin({})\n\n    const spy = jasmine.createSpy('watch')\n    const A = Vue.extend({\n      data: function () {\n        return { a: 1 }\n      },\n      watch: {\n        a: spy\n      },\n      created: function () {\n        this.a = 2\n      }\n    })\n    new Vue({\n      extends: A\n    })\n    waitForUpdate(() => {\n      expect(spy).toHaveBeenCalledWith(2, 1)\n\n      if (fakeWatch) {\n        delete Object.prototype.watch\n      }\n    }).then(done)\n  })\n})\n"
  },
  {
    "path": "test/unit/features/options/functional.spec.js",
    "content": "import Vue from 'vue'\nimport { createEmptyVNode } from 'core/vdom/vnode'\n\ndescribe('Options functional', () => {\n  it('should work', done => {\n    const vm = new Vue({\n      data: { test: 'foo' },\n      template: '<div><wrap :msg=\"test\">bar</wrap></div>',\n      components: {\n        wrap: {\n          functional: true,\n          props: ['msg'],\n          render (h, { props, children }) {\n            return h('div', null, [props.msg, ' '].concat(children))\n          }\n        }\n      }\n    }).$mount()\n    expect(vm.$el.innerHTML).toBe('<div>foo bar</div>')\n    vm.test = 'qux'\n    waitForUpdate(() => {\n      expect(vm.$el.innerHTML).toBe('<div>qux bar</div>')\n    }).then(done)\n  })\n\n  it('should expose all props when not declared', done => {\n    const fn = {\n      functional: true,\n      render (h, { props }) {\n        return h('div', `${props.msg} ${props.kebabMsg}`)\n      }\n    }\n\n    const vm = new Vue({\n      data: { test: 'foo' },\n      render (h) {\n        return h('div', [\n          h(fn, {\n            props: { msg: this.test },\n            attrs: { 'kebab-msg': 'bar' }\n          })\n        ])\n      }\n    }).$mount()\n\n    expect(vm.$el.innerHTML).toBe('<div>foo bar</div>')\n    vm.test = 'qux'\n    waitForUpdate(() => {\n      expect(vm.$el.innerHTML).toBe('<div>qux bar</div>')\n    }).then(done)\n  })\n\n  it('should expose data.on as listeners', () => {\n    const foo = jasmine.createSpy('foo')\n    const bar = jasmine.createSpy('bar')\n    const vm = new Vue({\n      template: '<div><wrap @click=\"foo\" @test=\"bar\"/></div>',\n      methods: { foo, bar },\n      components: {\n        wrap: {\n          functional: true,\n          render (h, { listeners }) {\n            return h('div', {\n              on: {\n                click: [listeners.click, () => listeners.test('bar')]\n              }\n            })\n          }\n        }\n      }\n    }).$mount()\n\n    triggerEvent(vm.$el.children[0], 'click')\n    expect(foo).toHaveBeenCalled()\n    expect(foo.calls.argsFor(0)[0].type).toBe('click') // should have click event\n    triggerEvent(vm.$el.children[0], 'mousedown')\n    expect(bar).toHaveBeenCalledWith('bar')\n  })\n\n  it('should support returning more than one root node', () => {\n    const vm = new Vue({\n      template: `<div><test></test></div>`,\n      components: {\n        test: {\n          functional: true,\n          render (h) {\n            return [h('span', 'foo'), h('span', 'bar')]\n          }\n        }\n      }\n    }).$mount()\n    expect(vm.$el.innerHTML).toBe('<span>foo</span><span>bar</span>')\n  })\n\n  it('should support slots', () => {\n    const vm = new Vue({\n      data: { test: 'foo' },\n      template: '<div><wrap><div slot=\"a\">foo</div><div slot=\"b\">bar</div></wrap></div>',\n      components: {\n        wrap: {\n          functional: true,\n          props: ['msg'],\n          render (h, { slots }) {\n            slots = slots()\n            return h('div', null, [slots.b, slots.a])\n          }\n        }\n      }\n    }).$mount()\n    expect(vm.$el.innerHTML).toBe('<div><div>bar</div><div>foo</div></div>')\n  })\n\n  it('should let vnode raw data pass through', done => {\n    const onValid = jasmine.createSpy('valid')\n    const vm = new Vue({\n      data: { msg: 'hello' },\n      template: `<div>\n        <validate field=\"field1\" @valid=\"onValid\">\n          <input type=\"text\" v-model=\"msg\">\n        </validate>\n      </div>`,\n      components: {\n        validate: {\n          functional: true,\n          props: ['field'],\n          render (h, { props, children, data: { on }}) {\n            props.child = children[0]\n            return h('validate-control', { props, on })\n          }\n        },\n        'validate-control': {\n          props: ['field', 'child'],\n          render () {\n            return this.child\n          },\n          mounted () {\n            this.$el.addEventListener('input', this.onInput)\n          },\n          destroyed () {\n            this.$el.removeEventListener('input', this.onInput)\n          },\n          methods: {\n            onInput (e) {\n              const value = e.target.value\n              if (this.validate(value)) {\n                this.$emit('valid', this)\n              }\n            },\n            // something validation logic here\n            validate (val) {\n              return val.length > 0\n            }\n          }\n        }\n      },\n      methods: { onValid }\n    }).$mount()\n    document.body.appendChild(vm.$el)\n    const input = vm.$el.querySelector('input')\n    expect(onValid).not.toHaveBeenCalled()\n    waitForUpdate(() => {\n      input.value = 'foo'\n      triggerEvent(input, 'input')\n    }).then(() => {\n      expect(onValid).toHaveBeenCalled()\n    }).then(() => {\n      document.body.removeChild(vm.$el)\n      vm.$destroy()\n    }).then(done)\n  })\n\n  it('create empty vnode when render return null', () => {\n    const child = {\n      functional: true,\n      render () {\n        return null\n      }\n    }\n    const vm = new Vue({\n      components: {\n        child\n      }\n    })\n    const h = vm.$createElement\n    const vnode = h('child')\n    expect(vnode).toEqual(createEmptyVNode())\n  })\n})\n"
  },
  {
    "path": "test/unit/features/options/inheritAttrs.spec.js",
    "content": "import Vue from 'vue'\n\ndescribe('Options inheritAttrs', () => {\n  it('should work', done => {\n    const vm = new Vue({\n      template: `<foo :id=\"foo\"/>`,\n      data: { foo: 'foo' },\n      components: {\n        foo: {\n          inheritAttrs: false,\n          template: `<div>foo</div>`\n        }\n      }\n    }).$mount()\n    expect(vm.$el.id).toBe('')\n    vm.foo = 'bar'\n    waitForUpdate(() => {\n      expect(vm.$el.id).toBe('')\n    }).then(done)\n  })\n\n  it('with inner v-bind', done => {\n    const vm = new Vue({\n      template: `<foo :id=\"foo\"/>`,\n      data: { foo: 'foo' },\n      components: {\n        foo: {\n          inheritAttrs: false,\n          template: `<div><div v-bind=\"$attrs\"></div></div>`\n        }\n      }\n    }).$mount()\n    expect(vm.$el.children[0].id).toBe('foo')\n    vm.foo = 'bar'\n    waitForUpdate(() => {\n      expect(vm.$el.children[0].id).toBe('bar')\n    }).then(done)\n  })\n})\n"
  },
  {
    "path": "test/unit/features/options/inject.spec.js",
    "content": "import Vue from 'vue'\nimport { Observer } from 'core/observer/index'\nimport { isNative, isObject, hasOwn } from 'core/util/index'\n\ndescribe('Options provide/inject', () => {\n  let injected\n  const injectedComp = {\n    inject: ['foo', 'bar'],\n    render () {},\n    created () {\n      injected = [this.foo, this.bar]\n    }\n  }\n\n  beforeEach(() => {\n    injected = null\n  })\n\n  it('should work', () => {\n    new Vue({\n      template: `<child/>`,\n      provide: {\n        foo: 1,\n        bar: false\n      },\n      components: {\n        child: {\n          template: `<injected-comp/>`,\n          components: {\n            injectedComp\n          }\n        }\n      }\n    }).$mount()\n\n    expect(injected).toEqual([1, false])\n  })\n\n  it('should use closest parent', () => {\n    new Vue({\n      template: `<child/>`,\n      provide: {\n        foo: 1,\n        bar: null\n      },\n      components: {\n        child: {\n          provide: {\n            foo: 3\n          },\n          template: `<injected-comp/>`,\n          components: {\n            injectedComp\n          }\n        }\n      }\n    }).$mount()\n\n    expect(injected).toEqual([3, null])\n  })\n\n  it('provide function', () => {\n    new Vue({\n      template: `<child/>`,\n      data: {\n        a: 1,\n        b: false\n      },\n      provide () {\n        return {\n          foo: this.a,\n          bar: this.b\n        }\n      },\n      components: {\n        child: {\n          template: `<injected-comp/>`,\n          components: {\n            injectedComp\n          }\n        }\n      }\n    }).$mount()\n\n    expect(injected).toEqual([1, false])\n  })\n\n  it('inject with alias', () => {\n    const injectAlias = {\n      inject: {\n        baz: 'foo',\n        qux: 'bar'\n      },\n      render () {},\n      created () {\n        injected = [this.baz, this.qux]\n      }\n    }\n\n    new Vue({\n      template: `<child/>`,\n      provide: {\n        foo: false,\n        bar: 2\n      },\n      components: {\n        child: {\n          template: `<inject-alias/>`,\n          components: {\n            injectAlias\n          }\n        }\n      }\n    }).$mount()\n\n    expect(injected).toEqual([false, 2])\n  })\n\n  it('inject before resolving data/props', () => {\n    const vm = new Vue({\n      provide: {\n        foo: 1\n      }\n    })\n\n    const child = new Vue({\n      parent: vm,\n      inject: ['foo'],\n      data () {\n        return {\n          bar: this.foo + 1\n        }\n      },\n      props: {\n        baz: {\n          default () {\n            return this.foo + 2\n          }\n        }\n      }\n    })\n\n    expect(child.foo).toBe(1)\n    expect(child.bar).toBe(2)\n    expect(child.baz).toBe(3)\n  })\n\n  // Github issue #5194\n  it('should work with functional', () => {\n    new Vue({\n      template: `<child/>`,\n      provide: {\n        foo: 1,\n        bar: false\n      },\n      components: {\n        child: {\n          functional: true,\n          inject: ['foo', 'bar'],\n          render (h, context) {\n            const { injections } = context\n            injected = [injections.foo, injections.bar]\n          }\n        }\n      }\n    }).$mount()\n\n    expect(injected).toEqual([1, false])\n  })\n\n  if (typeof Reflect !== 'undefined' && isNative(Reflect.ownKeys)) {\n    it('with Symbol keys', () => {\n      const s = Symbol()\n      const vm = new Vue({\n        template: `<child/>`,\n        provide: {\n          [s]: 123\n        },\n        components: {\n          child: {\n            inject: { s },\n            template: `<div>{{ s }}</div>`\n          }\n        }\n      }).$mount()\n      expect(vm.$el.textContent).toBe('123')\n    })\n  }\n\n  // Github issue #5223\n  it('should work with reactive array', done => {\n    const vm = new Vue({\n      template: `<div><child></child></div>`,\n      data () {\n        return {\n          foo: []\n        }\n      },\n      provide () {\n        return {\n          foo: this.foo\n        }\n      },\n      components: {\n        child: {\n          inject: ['foo'],\n          template: `<span>{{foo.length}}</span>`\n        }\n      }\n    }).$mount()\n\n    expect(vm.$el.innerHTML).toEqual(`<span>0</span>`)\n    vm.foo.push(vm.foo.length)\n    vm.$nextTick(() => {\n      expect(vm.$el.innerHTML).toEqual(`<span>1</span>`)\n      vm.foo.pop()\n      vm.$nextTick(() => {\n        expect(vm.$el.innerHTML).toEqual(`<span>0</span>`)\n        done()\n      })\n    })\n  })\n\n  it('should extend properly', () => {\n    const parent = Vue.extend({\n      template: `<span/>`,\n      inject: ['foo']\n    })\n\n    const child = parent.extend({\n      template: `<span/>`,\n      inject: ['bar'],\n      created () {\n        injected = [this.foo, this.bar]\n      }\n    })\n\n    new Vue({\n      template: `<div><parent/><child/></div>`,\n      provide: {\n        foo: 1,\n        bar: false\n      },\n      components: {\n        parent,\n        child\n      }\n    }).$mount()\n\n    expect(injected).toEqual([1, false])\n  })\n\n  it('should warn when injections has been modified', () => {\n    const key = 'foo'\n    const vm = new Vue({\n      provide: {\n        foo: 1\n      }\n    })\n\n    const child = new Vue({\n      parent: vm,\n      inject: ['foo']\n    })\n\n    expect(child.foo).toBe(1)\n    child.foo = 2\n    expect(\n      `Avoid mutating an injected value directly since the changes will be ` +\n      `overwritten whenever the provided component re-renders. ` +\n      `injection being mutated: \"${key}\"`).toHaveBeenWarned()\n  })\n\n  it('should warn when injections cannot be found', () => {\n    const vm = new Vue({})\n    new Vue({\n      parent: vm,\n      inject: ['foo', 'bar'],\n      created () {}\n    })\n    expect(`Injection \"foo\" not found`).toHaveBeenWarned()\n    expect(`Injection \"bar\" not found`).toHaveBeenWarned()\n  })\n\n  it('should not warn when injections can be found', () => {\n    const vm = new Vue({\n      provide: {\n        foo: 1,\n        bar: false,\n        baz: undefined\n      }\n    })\n    new Vue({\n      parent: vm,\n      inject: ['foo', 'bar', 'baz'],\n      created () {}\n    })\n    expect(`Injection \"foo\" not found`).not.toHaveBeenWarned()\n    expect(`Injection \"bar\" not found`).not.toHaveBeenWarned()\n    expect(`Injection \"baz\" not found`).not.toHaveBeenWarned()\n  })\n\n  // Github issue #6008\n  it('should merge provide from mixins (objects)', () => {\n    const mixinA = { provide: { foo: 'foo' }}\n    const mixinB = { provide: { bar: 'bar' }}\n    const child = {\n      inject: ['foo', 'bar'],\n      template: `<span/>`,\n      created () {\n        injected = [this.foo, this.bar]\n      }\n    }\n    new Vue({\n      mixins: [mixinA, mixinB],\n      render (h) {\n        return h(child)\n      }\n    }).$mount()\n\n    expect(injected).toEqual(['foo', 'bar'])\n  })\n  it('should merge provide from mixins (functions)', () => {\n    const mixinA = { provide: () => ({ foo: 'foo' }) }\n    const mixinB = { provide: () => ({ bar: 'bar' }) }\n    const child = {\n      inject: ['foo', 'bar'],\n      template: `<span/>`,\n      created () {\n        injected = [this.foo, this.bar]\n      }\n    }\n    new Vue({\n      mixins: [mixinA, mixinB],\n      render (h) {\n        return h(child)\n      }\n    }).$mount()\n\n    expect(injected).toEqual(['foo', 'bar'])\n  })\n  it('should merge provide from mixins (mix of objects and functions)', () => {\n    const mixinA = { provide: { foo: 'foo' }}\n    const mixinB = { provide: () => ({ bar: 'bar' }) }\n    const mixinC = { provide: { baz: 'baz' }}\n    const mixinD = { provide: () => ({ bam: 'bam' }) }\n    const child = {\n      inject: ['foo', 'bar', 'baz', 'bam'],\n      template: `<span/>`,\n      created () {\n        injected = [this.foo, this.bar, this.baz, this.bam]\n      }\n    }\n    new Vue({\n      mixins: [mixinA, mixinB, mixinC, mixinD],\n      render (h) {\n        return h(child)\n      }\n    }).$mount()\n\n    expect(injected).toEqual(['foo', 'bar', 'baz', 'bam'])\n  })\n  it('should merge provide from mixins and override existing keys', () => {\n    const mixinA = { provide: { foo: 'foo' }}\n    const mixinB = { provide: { foo: 'bar' }}\n    const child = {\n      inject: ['foo'],\n      template: `<span/>`,\n      created () {\n        injected = [this.foo]\n      }\n    }\n    new Vue({\n      mixins: [mixinA, mixinB],\n      render (h) {\n        return h(child)\n      }\n    }).$mount()\n\n    expect(injected).toEqual(['bar'])\n  })\n  it('should merge provide when Vue.extend', () => {\n    const mixinA = { provide: () => ({ foo: 'foo' }) }\n    const child = {\n      inject: ['foo', 'bar'],\n      template: `<span/>`,\n      created () {\n        injected = [this.foo, this.bar]\n      }\n    }\n    const Ctor = Vue.extend({\n      mixins: [mixinA],\n      provide: { bar: 'bar' },\n      render (h) {\n        return h(child)\n      }\n    })\n\n    new Ctor().$mount()\n\n    expect(injected).toEqual(['foo', 'bar'])\n  })\n\n  // #5913\n  it('should keep the reactive with provide', () => {\n    function isObserver (obj) {\n      if (isObject(obj)) {\n        return hasOwn(obj, '__ob__') && obj.__ob__ instanceof Observer\n      }\n      return false\n    }\n\n    const vm = new Vue({\n      template: `<div><child ref='child'></child></div>`,\n      data () {\n        return {\n          foo: {},\n          $foo: {},\n          foo1: []\n        }\n      },\n      provide () {\n        return {\n          foo: this.foo,\n          $foo: this.$foo,\n          foo1: this.foo1,\n          bar: {},\n          baz: []\n        }\n      },\n      components: {\n        child: {\n          inject: ['foo', '$foo', 'foo1', 'bar', 'baz'],\n          template: `<span/>`\n        }\n      }\n    }).$mount()\n    const child = vm.$refs.child\n    expect(isObserver(child.foo)).toBe(true)\n    expect(isObserver(child.$foo)).toBe(false)\n    expect(isObserver(child.foo1)).toBe(true)\n    expect(isObserver(child.bar)).toBe(false)\n    expect(isObserver(child.baz)).toBe(false)\n  })\n})\n"
  },
  {
    "path": "test/unit/features/options/lifecycle.spec.js",
    "content": "import Vue from 'vue'\n\ndescribe('Options lifecycle hooks', () => {\n  let spy\n  beforeEach(() => {\n    spy = jasmine.createSpy('hook')\n  })\n\n  describe('beforeCreate', () => {\n    it('should allow modifying options', () => {\n      const vm = new Vue({\n        data: {\n          a: 1\n        },\n        beforeCreate () {\n          spy()\n          expect(this.a).toBeUndefined()\n          this.$options.computed = {\n            b () {\n              return this.a + 1\n            }\n          }\n        }\n      })\n      expect(spy).toHaveBeenCalled()\n      expect(vm.b).toBe(2)\n    })\n  })\n\n  describe('created', () => {\n    it('should have completed observation', () => {\n      new Vue({\n        data: {\n          a: 1\n        },\n        created () {\n          expect(this.a).toBe(1)\n          spy()\n        }\n      })\n      expect(spy).toHaveBeenCalled()\n    })\n  })\n\n  describe('beforeMount', () => {\n    it('should not have mounted', () => {\n      const vm = new Vue({\n        render () {},\n        beforeMount () {\n          spy()\n          expect(this._isMounted).toBe(false)\n          expect(this.$el).toBeUndefined() // due to empty mount\n          expect(this._vnode).toBeNull()\n          expect(this._watcher).toBeNull()\n        }\n      })\n      expect(spy).not.toHaveBeenCalled()\n      vm.$mount()\n      expect(spy).toHaveBeenCalled()\n    })\n  })\n\n  describe('mounted', () => {\n    it('should have mounted', () => {\n      const vm = new Vue({\n        template: '<div></div>',\n        mounted () {\n          spy()\n          expect(this._isMounted).toBe(true)\n          expect(this.$el.tagName).toBe('DIV')\n          expect(this._vnode.tag).toBe('div')\n        }\n      })\n      expect(spy).not.toHaveBeenCalled()\n      vm.$mount()\n      expect(spy).toHaveBeenCalled()\n    })\n\n    // #3898\n    it('should call for manually mounted instance with parent', () => {\n      const parent = new Vue()\n      expect(spy).not.toHaveBeenCalled()\n      new Vue({\n        parent,\n        template: '<div></div>',\n        mounted () {\n          spy()\n        }\n      }).$mount()\n      expect(spy).toHaveBeenCalled()\n    })\n\n    it('should mount child parent in correct order', () => {\n      const calls = []\n      new Vue({\n        template: '<div><test></test></div>',\n        mounted () {\n          calls.push('parent')\n        },\n        components: {\n          test: {\n            template: '<nested></nested>',\n            mounted () {\n              expect(this.$el.parentNode).toBeTruthy()\n              calls.push('child')\n            },\n            components: {\n              nested: {\n                template: '<div></div>',\n                mounted () {\n                  expect(this.$el.parentNode).toBeTruthy()\n                  calls.push('nested')\n                }\n              }\n            }\n          }\n        }\n      }).$mount()\n      expect(calls).toEqual(['nested', 'child', 'parent'])\n    })\n  })\n\n  describe('beforeUpdate', () => {\n    it('should be called before update', done => {\n      const vm = new Vue({\n        template: '<div>{{ msg }}</div>',\n        data: { msg: 'foo' },\n        beforeUpdate () {\n          spy()\n          expect(this.$el.textContent).toBe('foo')\n        }\n      }).$mount()\n      expect(spy).not.toHaveBeenCalled()\n      vm.msg = 'bar'\n      expect(spy).not.toHaveBeenCalled() // should be async\n      waitForUpdate(() => {\n        expect(spy).toHaveBeenCalled()\n      }).then(done)\n    })\n  })\n\n  describe('updated', () => {\n    it('should be called after update', done => {\n      const vm = new Vue({\n        template: '<div>{{ msg }}</div>',\n        data: { msg: 'foo' },\n        updated () {\n          spy()\n          expect(this.$el.textContent).toBe('bar')\n        }\n      }).$mount()\n      expect(spy).not.toHaveBeenCalled()\n      vm.msg = 'bar'\n      expect(spy).not.toHaveBeenCalled() // should be async\n      waitForUpdate(() => {\n        expect(spy).toHaveBeenCalled()\n      }).then(done)\n    })\n\n    it('should be called after children are updated', done => {\n      const calls = []\n      const vm = new Vue({\n        template: '<div><test ref=\"child\">{{ msg }}</test></div>',\n        data: { msg: 'foo' },\n        components: {\n          test: {\n            template: `<div><slot></slot></div>`,\n            updated () {\n              expect(this.$el.textContent).toBe('bar')\n              calls.push('child')\n            }\n          }\n        },\n        updated () {\n          expect(this.$el.textContent).toBe('bar')\n          calls.push('parent')\n        }\n      }).$mount()\n\n      expect(calls).toEqual([])\n      vm.msg = 'bar'\n      expect(calls).toEqual([])\n      waitForUpdate(() => {\n        expect(calls).toEqual(['child', 'parent'])\n      }).then(done)\n    })\n  })\n\n  describe('beforeDestroy', () => {\n    it('should be called before destroy', () => {\n      const vm = new Vue({\n        render () {},\n        beforeDestroy () {\n          spy()\n          expect(this._isBeingDestroyed).toBe(false)\n          expect(this._isDestroyed).toBe(false)\n        }\n      }).$mount()\n      expect(spy).not.toHaveBeenCalled()\n      vm.$destroy()\n      vm.$destroy()\n      expect(spy).toHaveBeenCalled()\n      expect(spy.calls.count()).toBe(1)\n    })\n  })\n\n  describe('destroyed', () => {\n    it('should be called after destroy', () => {\n      const vm = new Vue({\n        render () {},\n        destroyed () {\n          spy()\n          expect(this._isBeingDestroyed).toBe(true)\n          expect(this._isDestroyed).toBe(true)\n        }\n      }).$mount()\n      expect(spy).not.toHaveBeenCalled()\n      vm.$destroy()\n      vm.$destroy()\n      expect(spy).toHaveBeenCalled()\n      expect(spy.calls.count()).toBe(1)\n    })\n  })\n\n  it('should emit hook events', () => {\n    const created = jasmine.createSpy()\n    const mounted = jasmine.createSpy()\n    const destroyed = jasmine.createSpy()\n    const vm = new Vue({\n      render () {},\n      beforeCreate () {\n        this.$on('hook:created', created)\n        this.$on('hook:mounted', mounted)\n        this.$on('hook:destroyed', destroyed)\n      }\n    })\n\n    expect(created).toHaveBeenCalled()\n    expect(mounted).not.toHaveBeenCalled()\n    expect(destroyed).not.toHaveBeenCalled()\n\n    vm.$mount()\n    expect(mounted).toHaveBeenCalled()\n    expect(destroyed).not.toHaveBeenCalled()\n\n    vm.$destroy()\n    expect(destroyed).toHaveBeenCalled()\n  })\n})\n"
  },
  {
    "path": "test/unit/features/options/methods.spec.js",
    "content": "import Vue from 'vue'\nimport testObjectOption from '../../../helpers/test-object-option'\n\ndescribe('Options methods', () => {\n  it('should have correct context', () => {\n    const vm = new Vue({\n      data: {\n        a: 1\n      },\n      methods: {\n        plus () {\n          this.a++\n        }\n      }\n    })\n    vm.plus()\n    expect(vm.a).toBe(2)\n  })\n\n  testObjectOption('methods')\n\n  it('should warn undefined methods', () => {\n    new Vue({\n      methods: {\n        hello: undefined\n      }\n    })\n    expect(`method \"hello\" has an undefined value in the component definition`).toHaveBeenWarned()\n  })\n\n  it('should warn methods conflicting with data', () => {\n    new Vue({\n      data: {\n        foo: 1\n      },\n      methods: {\n        foo () {}\n      }\n    })\n    expect(`method \"foo\" has already been defined as a data property`).toHaveBeenWarned()\n  })\n})\n"
  },
  {
    "path": "test/unit/features/options/mixins.spec.js",
    "content": "import Vue from 'vue'\nimport { mergeOptions } from 'core/util/index'\n\ndescribe('Options mixins', () => {\n  it('vm should have options from mixin', () => {\n    const mixin = {\n      directives: {\n        c: {}\n      },\n      methods: {\n        a: function () {}\n      }\n    }\n\n    const vm = new Vue({\n      mixins: [mixin],\n      methods: {\n        b: function () {}\n      }\n    })\n\n    expect(vm.a).toBeDefined()\n    expect(vm.b).toBeDefined()\n    expect(vm.$options.directives.c).toBeDefined()\n  })\n\n  it('should call hooks from mixins first', () => {\n    const a = {}\n    const b = {}\n    const c = {}\n    const f1 = function () {}\n    const f2 = function () {}\n    const f3 = function () {}\n    const mixinA = {\n      a: 1,\n      template: 'foo',\n      directives: {\n        a: a\n      },\n      created: f1\n    }\n    const mixinB = {\n      b: 1,\n      directives: {\n        b: b\n      },\n      created: f2\n    }\n    const result = mergeOptions({}, {\n      directives: {\n        c: c\n      },\n      template: 'bar',\n      mixins: [mixinA, mixinB],\n      created: f3\n    })\n    expect(result.a).toBe(1)\n    expect(result.b).toBe(1)\n    expect(result.directives.a).toBe(a)\n    expect(result.directives.b).toBe(b)\n    expect(result.directives.c).toBe(c)\n    expect(result.created[0]).toBe(f1)\n    expect(result.created[1]).toBe(f2)\n    expect(result.created[2]).toBe(f3)\n    expect(result.template).toBe('bar')\n  })\n\n  it('mixin methods should not override defined method', () => {\n    const f1 = function () {}\n    const f2 = function () {}\n    const f3 = function () {}\n    const mixinA = {\n      methods: {\n        xyz: f1\n      }\n    }\n    const mixinB = {\n      methods: {\n        xyz: f2\n      }\n    }\n    const result = mergeOptions({}, {\n      mixins: [mixinA, mixinB],\n      methods: {\n        xyz: f3\n      }\n    })\n    expect(result.methods.xyz).toBe(f3)\n  })\n\n  it('should accept constructors as mixins', () => {\n    const mixin = Vue.extend({\n      directives: {\n        c: {}\n      },\n      methods: {\n        a: function () {}\n      }\n    })\n\n    const vm = new Vue({\n      mixins: [mixin],\n      methods: {\n        b: function () {}\n      }\n    })\n\n    expect(vm.a).toBeDefined()\n    expect(vm.b).toBeDefined()\n    expect(vm.$options.directives.c).toBeDefined()\n  })\n})\n"
  },
  {
    "path": "test/unit/features/options/name.spec.js",
    "content": "import Vue from 'vue'\n\ndescribe('Options name', () => {\n  it('should contain itself in self components', () => {\n    const vm = Vue.extend({\n      name: 'SuperVue'\n    })\n\n    expect(vm.options.components['SuperVue']).toEqual(vm)\n  })\n\n  it('should warn when incorrect name given', () => {\n    Vue.extend({\n      name: 'Hyper*Vue'\n    })\n\n    /* eslint-disable */\n    expect(`Invalid component name: \"Hyper*Vue\". Component names can only contain alphanumeric characters and the hyphen, and must start with a letter.`)\n      .toHaveBeenWarned()\n    /* eslint-enable */\n\n    Vue.extend({\n      name: '2Cool2BValid'\n    })\n\n    /* eslint-disable */\n    expect(`Invalid component name: \"2Cool2BValid\". Component names can only contain alphanumeric characters and the hyphen, and must start with a letter.`)\n      .toHaveBeenWarned()\n    /* eslint-enable */\n  })\n\n  it('id should not override given name when using Vue.component', () => {\n    const SuperComponent = Vue.component('super-component', {\n      name: 'SuperVue'\n    })\n\n    expect(SuperComponent.options.components['SuperVue']).toEqual(SuperComponent)\n    expect(SuperComponent.options.components['super-component']).toEqual(SuperComponent)\n  })\n})\n"
  },
  {
    "path": "test/unit/features/options/parent.spec.js",
    "content": "import Vue from 'vue'\n\ndescribe('Options parent', () => {\n  it('should work', () => {\n    const parent = new Vue({\n      render () {}\n    }).$mount()\n\n    const child = new Vue({\n      parent: parent,\n      render () {}\n    }).$mount()\n\n    // this option is straight-forward\n    // it should register 'parent' as a $parent for 'child'\n    // and push 'child' to $children array on 'parent'\n    expect(child.$options.parent).toBeDefined()\n    expect(child.$options.parent).toEqual(parent)\n    expect(child.$parent).toBeDefined()\n    expect(child.$parent).toEqual(parent)\n    expect(parent.$children).toContain(child)\n\n    // destroy 'child' and check if it was removed from 'parent' $children\n    child.$destroy()\n    expect(parent.$children.length).toEqual(0)\n    parent.$destroy()\n  })\n})\n"
  },
  {
    "path": "test/unit/features/options/props.spec.js",
    "content": "import Vue from 'vue'\nimport { hasSymbol } from 'core/util/env'\n\ndescribe('Options props', () => {\n  it('array syntax', done => {\n    const vm = new Vue({\n      data: {\n        b: 'bar'\n      },\n      template: '<test v-bind:b=\"b\" ref=\"child\"></test>',\n      components: {\n        test: {\n          props: ['b'],\n          template: '<div>{{b}}</div>'\n        }\n      }\n    }).$mount()\n    expect(vm.$el.innerHTML).toBe('bar')\n    vm.b = 'baz'\n    waitForUpdate(() => {\n      expect(vm.$el.innerHTML).toBe('baz')\n      vm.$refs.child.b = 'qux'\n    }).then(() => {\n      expect(vm.$el.innerHTML).toBe('qux')\n      expect('Avoid mutating a prop directly').toHaveBeenWarned()\n    }).then(done)\n  })\n\n  it('object syntax', done => {\n    const vm = new Vue({\n      data: {\n        b: 'bar'\n      },\n      template: '<test v-bind:b=\"b\" ref=\"child\"></test>',\n      components: {\n        test: {\n          props: { b: String },\n          template: '<div>{{b}}</div>'\n        }\n      }\n    }).$mount()\n    expect(vm.$el.innerHTML).toBe('bar')\n    vm.b = 'baz'\n    waitForUpdate(() => {\n      expect(vm.$el.innerHTML).toBe('baz')\n      vm.$refs.child.b = 'qux'\n    }).then(() => {\n      expect(vm.$el.innerHTML).toBe('qux')\n      expect('Avoid mutating a prop directly').toHaveBeenWarned()\n    }).then(done)\n  })\n\n  it('warn mixed syntax', () => {\n    new Vue({\n      props: [{ b: String }]\n    })\n    expect('props must be strings when using array syntax').toHaveBeenWarned()\n  })\n\n  it('default values', () => {\n    const vm = new Vue({\n      data: {\n        b: undefined\n      },\n      template: '<test :b=\"b\"></test>',\n      components: {\n        test: {\n          props: {\n            a: {\n              default: 'A' // absent\n            },\n            b: {\n              default: 'B' // undefined\n            }\n          },\n          template: '<div>{{a}}{{b}}</div>'\n        }\n      }\n    }).$mount()\n    expect(vm.$el.textContent).toBe('AB')\n  })\n\n  it('default value reactivity', done => {\n    const vm = new Vue({\n      props: {\n        a: {\n          default: () => ({ b: 1 })\n        }\n      },\n      propsData: {\n        a: undefined\n      },\n      template: '<div>{{ a.b }}</div>'\n    }).$mount()\n    expect(vm.$el.textContent).toBe('1')\n    vm.a.b = 2\n    waitForUpdate(() => {\n      expect(vm.$el.textContent).toBe('2')\n    }).then(done)\n  })\n\n  it('default value Function', () => {\n    const func = () => 132\n    const vm = new Vue({\n      props: {\n        a: {\n          type: Function,\n          default: func\n        }\n      },\n      propsData: {\n        a: undefined\n      }\n    })\n    expect(vm.a).toBe(func)\n  })\n\n  it('warn object/array default values', () => {\n    new Vue({\n      props: {\n        a: {\n          default: { b: 1 }\n        }\n      },\n      propsData: {\n        a: undefined\n      }\n    })\n    expect('Props with type Object/Array must use a factory function').toHaveBeenWarned()\n  })\n\n  it('warn missing required', () => {\n    new Vue({\n      template: '<test></test>',\n      components: {\n        test: {\n          props: { a: { required: true }},\n          template: '<div>{{a}}</div>'\n        }\n      }\n    }).$mount()\n    expect('Missing required prop: \"a\"').toHaveBeenWarned()\n  })\n\n  describe('assertions', () => {\n    function makeInstance (value, type, validator, required) {\n      return new Vue({\n        template: '<test :test=\"val\"></test>',\n        data: {\n          val: value\n        },\n        components: {\n          test: {\n            template: '<div></div>',\n            props: {\n              test: {\n                type,\n                validator,\n                required\n              }\n            }\n          }\n        }\n      }).$mount()\n    }\n\n    it('string', () => {\n      makeInstance('hello', String)\n      expect(console.error.calls.count()).toBe(0)\n      makeInstance(123, String)\n      expect('Expected String').toHaveBeenWarned()\n    })\n\n    it('number', () => {\n      makeInstance(123, Number)\n      expect(console.error.calls.count()).toBe(0)\n      makeInstance('123', Number)\n      expect('Expected Number').toHaveBeenWarned()\n    })\n\n    it('boolean', () => {\n      makeInstance(true, Boolean)\n      expect(console.error.calls.count()).toBe(0)\n      makeInstance('123', Boolean)\n      expect('Expected Boolean').toHaveBeenWarned()\n    })\n\n    it('function', () => {\n      makeInstance(() => {}, Function)\n      expect(console.error.calls.count()).toBe(0)\n      makeInstance(123, Function)\n      expect('Expected Function').toHaveBeenWarned()\n    })\n\n    it('object', () => {\n      makeInstance({}, Object)\n      expect(console.error.calls.count()).toBe(0)\n      makeInstance([], Object)\n      expect('Expected Object').toHaveBeenWarned()\n    })\n\n    it('array', () => {\n      makeInstance([], Array)\n      expect(console.error.calls.count()).toBe(0)\n      makeInstance({}, Array)\n      expect('Expected Array').toHaveBeenWarned()\n    })\n\n    if (hasSymbol) {\n      it('symbol', () => {\n        makeInstance(Symbol('foo'), Symbol)\n        expect(console.error.calls.count()).toBe(0)\n        makeInstance({}, Symbol)\n        expect('Expected Symbol').toHaveBeenWarned()\n      })\n    }\n\n    it('custom constructor', () => {\n      function Class () {}\n      makeInstance(new Class(), Class)\n      expect(console.error.calls.count()).toBe(0)\n      makeInstance({}, Class)\n      expect('type check failed').toHaveBeenWarned()\n    })\n\n    it('multiple types', () => {\n      makeInstance([], [Array, Number, Boolean])\n      expect(console.error.calls.count()).toBe(0)\n      makeInstance({}, [Array, Number, Boolean])\n      expect('Expected Array, Number, Boolean, got Object').toHaveBeenWarned()\n    })\n\n    it('custom validator', () => {\n      makeInstance(123, null, v => v === 123)\n      expect(console.error.calls.count()).toBe(0)\n      makeInstance(123, null, v => v === 234)\n      expect('custom validator check failed').toHaveBeenWarned()\n    })\n\n    it('type check + custom validator', () => {\n      makeInstance(123, Number, v => v === 123)\n      expect(console.error.calls.count()).toBe(0)\n      makeInstance(123, Number, v => v === 234)\n      expect('custom validator check failed').toHaveBeenWarned()\n      makeInstance(123, String, v => v === 123)\n      expect('Expected String').toHaveBeenWarned()\n    })\n\n    it('multiple types + custom validator', () => {\n      makeInstance(123, [Number, String, Boolean], v => v === 123)\n      expect(console.error.calls.count()).toBe(0)\n      makeInstance(123, [Number, String, Boolean], v => v === 234)\n      expect('custom validator check failed').toHaveBeenWarned()\n      makeInstance(123, [String, Boolean], v => v === 123)\n      expect('Expected String, Boolean').toHaveBeenWarned()\n    })\n\n    it('optional with type + null/undefined', () => {\n      makeInstance(undefined, String)\n      expect(console.error.calls.count()).toBe(0)\n      makeInstance(null, String)\n      expect(console.error.calls.count()).toBe(0)\n    })\n\n    it('required with type + null/undefined', () => {\n      makeInstance(undefined, String, null, true)\n      expect(console.error.calls.count()).toBe(1)\n      expect('Expected String').toHaveBeenWarned()\n      makeInstance(null, Boolean, null, true)\n      expect(console.error.calls.count()).toBe(2)\n      expect('Expected Boolean').toHaveBeenWarned()\n    })\n\n    it('optional prop of any type (type: true or prop: true)', () => {\n      makeInstance(1, true)\n      expect(console.error.calls.count()).toBe(0)\n      makeInstance('any', true)\n      expect(console.error.calls.count()).toBe(0)\n      makeInstance({}, true)\n      expect(console.error.calls.count()).toBe(0)\n      makeInstance(undefined, true)\n      expect(console.error.calls.count()).toBe(0)\n      makeInstance(null, true)\n      expect(console.error.calls.count()).toBe(0)\n    })\n  })\n\n  it('should work with v-bind', () => {\n    const vm = new Vue({\n      template: `<test v-bind=\"{ a: 1, b: 2 }\"></test>`,\n      components: {\n        test: {\n          props: ['a', 'b'],\n          template: '<div>{{ a }} {{ b }}</div>'\n        }\n      }\n    }).$mount()\n    expect(vm.$el.textContent).toBe('1 2')\n  })\n\n  it('should warn data fields already defined as a prop', () => {\n    new Vue({\n      template: '<test a=\"1\"></test>',\n      components: {\n        test: {\n          template: '<div></div>',\n          data: function () {\n            return { a: 123 }\n          },\n          props: {\n            a: null\n          }\n        }\n      }\n    }).$mount()\n    expect('already declared as a prop').toHaveBeenWarned()\n  })\n\n  it('should warn methods already defined as a prop', () => {\n    new Vue({\n      template: '<test a=\"1\"></test>',\n      components: {\n        test: {\n          template: '<div></div>',\n          props: {\n            a: null\n          },\n          methods: {\n            a () {\n\n            }\n          }\n        }\n      }\n    }).$mount()\n    expect(`method \"a\" has already been defined as a prop`).toHaveBeenWarned()\n    expect(`Avoid mutating a prop directly`).toHaveBeenWarned()\n  })\n\n  it('treat boolean props properly', () => {\n    const vm = new Vue({\n      template: '<comp ref=\"child\" prop-a prop-b=\"prop-b\"></comp>',\n      components: {\n        comp: {\n          template: '<div></div>',\n          props: {\n            propA: Boolean,\n            propB: Boolean,\n            propC: Boolean\n          }\n        }\n      }\n    }).$mount()\n    expect(vm.$refs.child.propA).toBe(true)\n    expect(vm.$refs.child.propB).toBe(true)\n    expect(vm.$refs.child.propC).toBe(false)\n  })\n\n  it('should respect default value of a Boolean prop', function () {\n    const vm = new Vue({\n      template: '<test></test>',\n      components: {\n        test: {\n          props: {\n            prop: {\n              type: Boolean,\n              default: true\n            }\n          },\n          template: '<div>{{prop}}</div>'\n        }\n      }\n    }).$mount()\n    expect(vm.$el.textContent).toBe('true')\n  })\n\n  it('non reactive values passed down as prop should not be converted', done => {\n    const a = Object.freeze({\n      nested: {\n        msg: 'hello'\n      }\n    })\n    const parent = new Vue({\n      template: '<comp :a=\"a.nested\"></comp>',\n      data: {\n        a: a\n      },\n      components: {\n        comp: {\n          template: '<div></div>',\n          props: ['a']\n        }\n      }\n    }).$mount()\n    const child = parent.$children[0]\n    expect(child.a.msg).toBe('hello')\n    expect(child.a.__ob__).toBeUndefined() // should not be converted\n    parent.a = Object.freeze({\n      nested: {\n        msg: 'yo'\n      }\n    })\n    waitForUpdate(() => {\n      expect(child.a.msg).toBe('yo')\n      expect(child.a.__ob__).toBeUndefined()\n    }).then(done)\n  })\n\n  it('should not warn for non-required, absent prop', function () {\n    new Vue({\n      template: '<test></test>',\n      components: {\n        test: {\n          template: '<div></div>',\n          props: {\n            prop: {\n              type: String\n            }\n          }\n        }\n      }\n    }).$mount()\n    expect(console.error.calls.count()).toBe(0)\n  })\n\n  // #3453\n  it('should not fire watcher on object/array props when parent re-renders', done => {\n    const spy = jasmine.createSpy()\n    const vm = new Vue({\n      data: {\n        arr: []\n      },\n      template: '<test :prop=\"arr\">hi</test>',\n      components: {\n        test: {\n          props: ['prop'],\n          watch: {\n            prop: spy\n          },\n          template: '<div><slot></slot></div>'\n        }\n      }\n    }).$mount()\n    vm.$forceUpdate()\n    waitForUpdate(() => {\n      expect(spy).not.toHaveBeenCalled()\n    }).then(done)\n  })\n\n  // #4090\n  it('should not trigger watcher on default value', done => {\n    const spy = jasmine.createSpy()\n    const vm = new Vue({\n      template: `<test :value=\"a\" :test=\"b\"></test>`,\n      data: {\n        a: 1,\n        b: undefined\n      },\n      components: {\n        test: {\n          template: '<div>{{ value }}</div>',\n          props: {\n            value: { type: Number },\n            test: {\n              type: Object,\n              default: () => ({})\n            }\n          },\n          watch: {\n            test: spy\n          }\n        }\n      }\n    }).$mount()\n\n    vm.a++\n    waitForUpdate(() => {\n      expect(spy).not.toHaveBeenCalled()\n      vm.b = {}\n    }).then(() => {\n      expect(spy.calls.count()).toBe(1)\n    }).then(() => {\n      vm.b = undefined\n    }).then(() => {\n      expect(spy.calls.count()).toBe(2)\n      vm.a++\n    }).then(() => {\n      expect(spy.calls.count()).toBe(2)\n    }).then(done)\n  })\n\n  it('warn reserved props', () => {\n    const specialAttrs = ['key', 'ref', 'slot', 'is']\n    new Vue({\n      props: specialAttrs\n    })\n    specialAttrs.forEach(attr => {\n      expect(`\"${attr}\" is a reserved attribute`).toHaveBeenWarned()\n    })\n  })\n})\n"
  },
  {
    "path": "test/unit/features/options/propsData.spec.js",
    "content": "import Vue from 'vue'\n\ndescribe('Options propsData', () => {\n  it('should work', done => {\n    const A = Vue.extend({\n      props: ['a'],\n      template: '<div>{{ a }}</div>'\n    })\n    const vm = new A({\n      propsData: {\n        a: 123\n      }\n    }).$mount()\n    expect(vm.a).toBe(123)\n    expect(vm.$el.textContent).toBe('123')\n    vm.a = 234\n    waitForUpdate(() => {\n      expect(vm.$el.textContent).toBe('234')\n    }).then(done)\n  })\n\n  it('warn non instantiation usage', () => {\n    Vue.extend({\n      propsData: {\n        a: 123\n      }\n    })\n    expect('option \"propsData\" can only be used during instance creation').toHaveBeenWarned()\n  })\n})\n"
  },
  {
    "path": "test/unit/features/options/render.spec.js",
    "content": "import Vue from 'vue'\n\ndescribe('Options render', () => {\n  it('basic usage', () => {\n    const vm = new Vue({\n      render (h) {\n        const children = []\n        for (let i = 0; i < this.items.length; i++) {\n          children.push(h('li', { staticClass: 'task' }, [this.items[i].name]))\n        }\n        return h('ul', { staticClass: 'tasks' }, children)\n      },\n      data: {\n        items: [{ id: 1, name: 'task1' }, { id: 2, name: 'task2' }]\n      }\n    }).$mount()\n    expect(vm.$el.tagName).toBe('UL')\n    for (let i = 0; i < vm.$el.children.length; i++) {\n      const li = vm.$el.children[i]\n      expect(li.tagName).toBe('LI')\n      expect(li.textContent).toBe(vm.items[i].name)\n    }\n  })\n\n  it('allow null data', () => {\n    const vm = new Vue({\n      render (h) {\n        return h('div', null, 'hello' /* string as children*/)\n      }\n    }).$mount()\n    expect(vm.$el.tagName).toBe('DIV')\n    expect(vm.$el.textContent).toBe('hello')\n  })\n\n  it('should warn non `render` option and non `template` option', () => {\n    new Vue().$mount()\n    expect('Failed to mount component: template or render function not defined.').toHaveBeenWarned()\n  })\n})\n"
  },
  {
    "path": "test/unit/features/options/renderError.spec.js",
    "content": "import Vue from 'vue'\n\ndescribe('Options renderError', () => {\n  it('should be used on render errors', done => {\n    Vue.config.errorHandler = () => {}\n    const vm = new Vue({\n      data: {\n        ok: true\n      },\n      render (h) {\n        if (this.ok) {\n          return h('div', 'ok')\n        } else {\n          throw new Error('no')\n        }\n      },\n      renderError (h, err) {\n        return h('div', err.toString())\n      }\n    }).$mount()\n    expect(vm.$el.textContent).toBe('ok')\n    vm.ok = false\n    waitForUpdate(() => {\n      expect(vm.$el.textContent).toBe('Error: no')\n      Vue.config.errorHandler = null\n    }).then(done)\n  })\n})\n"
  },
  {
    "path": "test/unit/features/options/template.spec.js",
    "content": "import Vue from 'vue'\n\ndescribe('Options template', () => {\n  let el\n  beforeEach(() => {\n    el = document.createElement('script')\n    el.type = 'x-template'\n    el.id = 'app'\n    el.innerHTML = '<p>{{message}}</p>'\n    document.body.appendChild(el)\n  })\n\n  afterEach(() => {\n    document.body.removeChild(el)\n  })\n\n  it('basic usage', () => {\n    const vm = new Vue({\n      template: '<div>{{message}}</div>',\n      data: { message: 'hello world' }\n    }).$mount()\n    expect(vm.$el.tagName).toBe('DIV')\n    expect(vm.$el.textContent).toBe(vm.message)\n  })\n\n  it('id reference', () => {\n    const vm = new Vue({\n      template: '#app',\n      data: { message: 'hello world' }\n    }).$mount()\n    expect(vm.$el.tagName).toBe('P')\n    expect(vm.$el.textContent).toBe(vm.message)\n  })\n\n  it('DOM element', () => {\n    const elm = document.createElement('p')\n    elm.innerHTML = '<p>{{message}}</p>'\n    const vm = new Vue({\n      template: elm,\n      data: { message: 'hello world' }\n    }).$mount()\n    expect(vm.$el.tagName).toBe('P')\n    expect(vm.$el.textContent).toBe(vm.message)\n  })\n\n  it('invalid template', () => {\n    new Vue({\n      template: Vue,\n      data: { message: 'hello world' }\n    }).$mount()\n    expect('invalid template option').toHaveBeenWarned()\n  })\n\n  it('warn error in generated function', () => {\n    new Vue({\n      template: '<div v-if=\"!@\"><span>{{ a\"\" }}</span><span>{{ do + 1 }}</span></div>'\n    }).$mount()\n    expect('Error compiling template').toHaveBeenWarned()\n    expect('invalid expression: v-if=\"!@\"').toHaveBeenWarned()\n    expect('invalid expression: {{ a\"\" }}').toHaveBeenWarned()\n    expect('avoid using JavaScript keyword as property name: \"do\" in expression {{ do + 1 }}').toHaveBeenWarned()\n  })\n\n  it('should not warn $ prefixed keywords', () => {\n    new Vue({\n      template: `<div @click=\"$delete(foo, 'bar')\"></div>`\n    }).$mount()\n    expect('avoid using JavaScript keyword as property name').not.toHaveBeenWarned()\n  })\n\n  it('warn error in generated function (v-for)', () => {\n    new Vue({\n      template: '<div><div v-for=\"(1, 2) in a----\"></div></div>'\n    }).$mount()\n    expect('Error compiling template').toHaveBeenWarned()\n    expect('invalid v-for alias \"1\"').toHaveBeenWarned()\n    expect('invalid v-for iterator \"2\"').toHaveBeenWarned()\n    expect('invalid expression: v-for=\"(1, 2) in a----\"').toHaveBeenWarned()\n  })\n\n  it('warn error in generated function (v-on)', () => {\n    new Vue({\n      template: `<div @click=\"delete('Delete')\"></div>`,\n      methods: { delete: function () {} }\n    }).$mount()\n    expect('Error compiling template').toHaveBeenWarned()\n    expect(\n      `avoid using JavaScript unary operator as property name: \"delete()\" in expression @click=\"delete('Delete')\"`\n    ).toHaveBeenWarned()\n  })\n})\n"
  },
  {
    "path": "test/unit/features/options/watch.spec.js",
    "content": "import Vue from 'vue'\nimport testObjectOption from '../../../helpers/test-object-option'\n\ndescribe('Options watch', () => {\n  let spy\n  beforeEach(() => {\n    spy = jasmine.createSpy('watch')\n  })\n\n  testObjectOption('watch')\n\n  it('basic usage', done => {\n    const vm = new Vue({\n      data: {\n        a: 1\n      },\n      watch: {\n        a: spy\n      }\n    })\n    expect(spy).not.toHaveBeenCalled()\n    vm.a = 2\n    expect(spy).not.toHaveBeenCalled()\n    waitForUpdate(() => {\n      expect(spy).toHaveBeenCalledWith(2, 1)\n    }).then(done)\n  })\n\n  it('string method name', done => {\n    const vm = new Vue({\n      data: {\n        a: 1\n      },\n      watch: {\n        a: 'onChange'\n      },\n      methods: {\n        onChange: spy\n      }\n    })\n    expect(spy).not.toHaveBeenCalled()\n    vm.a = 2\n    expect(spy).not.toHaveBeenCalled()\n    waitForUpdate(() => {\n      expect(spy).toHaveBeenCalledWith(2, 1)\n    }).then(done)\n  })\n\n  it('multiple cbs (after option merge)', done => {\n    const spy1 = jasmine.createSpy('watch')\n    const Test = Vue.extend({\n      watch: {\n        a: spy1\n      }\n    })\n    const vm = new Test({\n      data: { a: 1 },\n      watch: {\n        a: spy\n      }\n    })\n    vm.a = 2\n    waitForUpdate(() => {\n      expect(spy1).toHaveBeenCalledWith(2, 1)\n      expect(spy).toHaveBeenCalledWith(2, 1)\n    }).then(done)\n  })\n\n  it('with option: immediate', done => {\n    const vm = new Vue({\n      data: { a: 1 },\n      watch: {\n        a: {\n          handler: spy,\n          immediate: true\n        }\n      }\n    })\n    expect(spy).toHaveBeenCalledWith(1)\n    vm.a = 2\n    waitForUpdate(() => {\n      expect(spy).toHaveBeenCalledWith(2, 1)\n    }).then(done)\n  })\n\n  it('with option: deep', done => {\n    const vm = new Vue({\n      data: { a: { b: 1 }},\n      watch: {\n        a: {\n          handler: spy,\n          deep: true\n        }\n      }\n    })\n    const oldA = vm.a\n    expect(spy).not.toHaveBeenCalled()\n    vm.a.b = 2\n    expect(spy).not.toHaveBeenCalled()\n    waitForUpdate(() => {\n      expect(spy).toHaveBeenCalledWith(vm.a, vm.a)\n      vm.a = { b: 3 }\n    }).then(() => {\n      expect(spy).toHaveBeenCalledWith(vm.a, oldA)\n    }).then(done)\n  })\n\n  it('correctly merges multiple extends', done => {\n    var spy2 = jasmine.createSpy('A')\n    var spy3 = jasmine.createSpy('B')\n    var A = Vue.extend({\n      data: function () {\n        return {\n          a: 0,\n          b: 0\n        }\n      },\n      watch: {\n        b: spy\n      }\n    })\n\n    var B = Vue.extend({\n      extends: A,\n      watch: {\n        a: spy2\n      }\n    })\n\n    var C = Vue.extend({\n      extends: B,\n      watch: {\n        a: spy3\n      }\n    })\n\n    var vm = new C()\n    vm.a = 1\n\n    waitForUpdate(() => {\n      expect(spy).not.toHaveBeenCalled()\n      expect(spy2).toHaveBeenCalledWith(1, 0)\n      expect(spy3).toHaveBeenCalledWith(1, 0)\n    }).then(done)\n  })\n})\n"
  },
  {
    "path": "test/unit/features/ref.spec.js",
    "content": "import Vue from 'vue'\n\ndescribe('ref', () => {\n  const components = {\n    test: {\n      id: 'test',\n      template: '<div>test</div>'\n    },\n    test2: {\n      id: 'test2',\n      template: '<div>test2</div>'\n    }\n  }\n\n  it('should work', () => {\n    const vm = new Vue({\n      data: {\n        value: 'bar'\n      },\n      template: `<div>\n        <test ref=\"foo\"></test>\n        <test2 :ref=\"value\"></test2>\n      </div>`,\n      components\n    })\n    vm.$mount()\n    expect(vm.$refs.foo).toBeTruthy()\n    expect(vm.$refs.foo.$options.id).toBe('test')\n    expect(vm.$refs.bar).toBeTruthy()\n    expect(vm.$refs.bar.$options.id).toBe('test2')\n  })\n\n  it('should dynamically update refs', done => {\n    const vm = new Vue({\n      data: {\n        value: 'foo'\n      },\n      template: '<div :ref=\"value\"></div>'\n    }).$mount()\n    expect(vm.$refs.foo).toBe(vm.$el)\n    vm.value = 'bar'\n    waitForUpdate(() => {\n      expect(vm.$refs.foo).toBeUndefined()\n      expect(vm.$refs.bar).toBe(vm.$el)\n    }).then(done)\n  })\n\n  it('should work as a hyperscript prop', () => {\n    const vm = new Vue({\n      components,\n      render (h) {\n        return h('div', null, [\n          h('test', { ref: 'test' })\n        ])\n      }\n    })\n    vm.$mount()\n    expect(vm.$refs.test).toBeTruthy()\n    expect(vm.$refs.test.$options.id).toBe('test')\n  })\n\n  it('should accept HOC component', () => {\n    const vm = new Vue({\n      template: '<test ref=\"test\"></test>',\n      components\n    })\n    vm.$mount()\n    expect(vm.$refs.test).toBeTruthy()\n    expect(vm.$refs.test.$options.id).toBe('test')\n  })\n\n  it('should accept dynamic component', done => {\n    const vm = new Vue({\n      template: `<div>\n        <component :is=\"test\" ref=\"test\"></component>\n      </div>`,\n      components,\n      data: { test: 'test' }\n    })\n    vm.$mount()\n    expect(vm.$refs.test.$options.id).toBe('test')\n    vm.test = 'test2'\n    waitForUpdate(() => {\n      expect(vm.$refs.test.$options.id).toBe('test2')\n      vm.test = ''\n    }).then(() => {\n      expect(vm.$refs.test).toBeUndefined()\n    }).then(done)\n  })\n\n  it('should register as Array when used with v-for', done => {\n    const vm = new Vue({\n      data: {\n        items: [1, 2, 3]\n      },\n      template: `\n        <div>\n          <div v-for=\"n in items\" ref=\"list\">{{n}}</div>\n        </div>\n      `\n    }).$mount()\n    assertRefs()\n    // updating\n    vm.items.push(4)\n    waitForUpdate(assertRefs)\n      .then(() => { vm.items = [] })\n      .then(assertRefs)\n      .then(done)\n\n    function assertRefs () {\n      expect(Array.isArray(vm.$refs.list)).toBe(true)\n      expect(vm.$refs.list.length).toBe(vm.items.length)\n      expect(vm.$refs.list.every((item, i) => item.textContent === String(i + 1))).toBe(true)\n    }\n  })\n\n  it('should register as Array when used with v-for (components)', done => {\n    const vm = new Vue({\n      data: {\n        items: [1, 2, 3]\n      },\n      template: `\n        <div>\n          <test v-for=\"n in items\" ref=\"list\" :key=\"n\" :n=\"n\"></test>\n        </div>\n      `,\n      components: {\n        test: {\n          props: ['n'],\n          template: '<div>{{ n }}</div>'\n        }\n      }\n    }).$mount()\n    assertRefs()\n    // updating\n    vm.items.push(4)\n    waitForUpdate(assertRefs)\n      .then(() => { vm.items = [] })\n      .then(assertRefs)\n      .then(done)\n\n    function assertRefs () {\n      expect(Array.isArray(vm.$refs.list)).toBe(true)\n      expect(vm.$refs.list.length).toBe(vm.items.length)\n      expect(vm.$refs.list.every((comp, i) => comp.$el.textContent === String(i + 1))).toBe(true)\n    }\n  })\n\n  it('should work with v-for on dynamic component', done => {\n    components.test3 = {\n      id: 'test3',\n      template: `<test1 v-if=\"!normal\"></test1><div v-else>test3</div>`,\n      data () {\n        return { normal: false }\n      },\n      components: { test1: components.test }\n    }\n    // a flag that representing whether to test component content or not\n    let testContent = false\n\n    const vm = new Vue({\n      template: `\n        <div>\n          <component\n            v-for=\"(item, index) in items\"\n            :key=\"index\"\n            :is=\"item\"\n            ref=\"children\">\n          </component>\n        </div>\n      `,\n      data: {\n        items: ['test2', 'test3']\n      },\n      components\n    }).$mount()\n    assertRefs()\n    expect(vm.$refs.children[0].$el.textContent).toBe('test2')\n    expect(vm.$refs.children[1].$el.textContent).toBe('test')\n    // updating\n    vm.$refs.children[1].normal = true\n    testContent = true\n    waitForUpdate(assertRefs)\n      .then(() => { vm.items.push('test') })\n      .then(assertRefs)\n      .then(done)\n\n    function assertRefs () {\n      expect(Array.isArray(vm.$refs.children)).toBe(true)\n      expect(vm.$refs.children.length).toBe(vm.items.length)\n      if (testContent) {\n        expect(\n          vm.$refs.children.every((comp, i) => comp.$el.textContent === vm.items[i])\n        ).toBe(true)\n      }\n    }\n  })\n\n  it('should register on component with empty roots', () => {\n    const vm = new Vue({\n      template: '<child ref=\"test\"></child>',\n      components: {\n        child: {\n          template: '<div v-if=\"false\"></div>'\n        }\n      }\n    }).$mount()\n    expect(vm.$refs.test).toBe(vm.$children[0])\n  })\n})\n"
  },
  {
    "path": "test/unit/features/transition/inject-styles.js",
    "content": "function insertCSS (text) {\n  var cssEl = document.createElement('style')\n  cssEl.textContent = text.trim()\n  document.head.appendChild(cssEl)\n}\n\nconst duration = process.env.TRANSITION_DURATION || 50\nconst buffer = process.env.TRANSITION_BUFFER || 10\nlet injected = false\n\nexport default function injectStyles () {\n  if (injected) return { duration, buffer }\n  injected = true\n  insertCSS(`\n    .test {\n      -webkit-transition: opacity ${duration}ms ease;\n      transition: opacity ${duration}ms ease;\n    }\n    .group-move {\n      -webkit-transition: -webkit-transform ${duration}ms ease;\n      transition: transform ${duration}ms ease;\n    }\n    .v-appear, .v-enter, .v-leave-active,\n    .test-appear, .test-enter, .test-leave-active,\n    .hello, .bye.active,\n    .changed-enter {\n      opacity: 0;\n    }\n    .test-anim-enter-active {\n      animation: test-enter ${duration}ms;\n      -webkit-animation: test-enter ${duration}ms;\n    }\n    .test-anim-leave-active {\n      animation: test-leave ${duration}ms;\n      -webkit-animation: test-leave ${duration}ms;\n    }\n    .test-anim-long-enter-active {\n      animation: test-enter ${duration * 2}ms;\n      -webkit-animation: test-enter ${duration * 2}ms;\n    }\n    .test-anim-long-leave-active {\n      animation: test-leave ${duration * 2}ms;\n      -webkit-animation: test-leave ${duration * 2}ms;\n    }\n    @keyframes test-enter {\n      from { opacity: 0 }\n      to { opacity: 1 }\n    }\n    @-webkit-keyframes test-enter {\n      from { opacity: 0 }\n      to { opacity: 1 }\n    }\n    @keyframes test-leave {\n      from { opacity: 1 }\n      to { opacity: 0 }\n    }\n    @-webkit-keyframes test-leave {\n      from { opacity: 1 }\n      to { opacity: 0 }\n    }\n  `)\n  return { duration, buffer }\n}\n\n"
  },
  {
    "path": "test/unit/features/transition/transition-group.spec.js",
    "content": "import Vue from 'vue'\nimport injectStyles from './inject-styles'\nimport { isIE9 } from 'core/util/env'\nimport { nextFrame } from 'web/runtime/transition-util'\n\nif (!isIE9) {\n  describe('Transition group', () => {\n    const { duration, buffer } = injectStyles()\n\n    let el\n    beforeEach(() => {\n      el = document.createElement('div')\n      document.body.appendChild(el)\n    })\n\n    function createBasicVM (useIs, appear) {\n      const vm = new Vue({\n        template: `\n          <div>\n            ${useIs ? `<span is=\"transition-group\">` : `<transition-group${appear ? ` appear` : ``}>`}\n              <div v-for=\"item in items\" :key=\"item\" class=\"test\">{{ item }}</div>\n            ${useIs ? `</span>` : `</transition-group>`}\n          </div>\n        `,\n        data: {\n          items: ['a', 'b', 'c']\n        }\n      }).$mount(el)\n      if (!appear) {\n        expect(vm.$el.innerHTML).toBe(\n          `<span>` +\n            vm.items.map(i => `<div class=\"test\">${i}</div>`).join('') +\n          `</span>`\n        )\n      }\n      return vm\n    }\n\n    it('enter', done => {\n      const vm = createBasicVM()\n      vm.items.push('d', 'e')\n      waitForUpdate(() => {\n        expect(vm.$el.innerHTML).toBe(\n          `<span>` +\n            ['a', 'b', 'c'].map(i => `<div class=\"test\">${i}</div>`).join('') +\n            `<div class=\"test v-enter v-enter-active\">d</div>` +\n            `<div class=\"test v-enter v-enter-active\">e</div>` +\n          `</span>`\n        )\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          `<span>` +\n            ['a', 'b', 'c'].map(i => `<div class=\"test\">${i}</div>`).join('') +\n            `<div class=\"test v-enter-active v-enter-to\">d</div>` +\n            `<div class=\"test v-enter-active v-enter-to\">e</div>` +\n          `</span>`\n        )\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          `<span>` +\n            vm.items.map(i => `<div class=\"test\">${i}</div>`).join('') +\n          `</span>`\n        )\n      }).then(done)\n    })\n\n    it('leave', done => {\n      const vm = createBasicVM()\n      vm.items = ['b']\n      waitForUpdate(() => {\n        expect(vm.$el.innerHTML).toBe(\n          `<span>` +\n            `<div class=\"test v-leave v-leave-active\">a</div>` +\n            `<div class=\"test\">b</div>` +\n            `<div class=\"test v-leave v-leave-active\">c</div>` +\n          `</span>`\n        )\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          `<span>` +\n            `<div class=\"test v-leave-active v-leave-to\">a</div>` +\n            `<div class=\"test\">b</div>` +\n            `<div class=\"test v-leave-active v-leave-to\">c</div>` +\n          `</span>`\n        )\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          `<span>` +\n            vm.items.map(i => `<div class=\"test\">${i}</div>`).join('') +\n          `</span>`\n        )\n      }).then(done)\n    })\n\n    it('enter + leave', done => {\n      const vm = createBasicVM()\n      vm.items = ['b', 'c', 'd']\n      waitForUpdate(() => {\n        expect(vm.$el.innerHTML).toBe(\n          `<span>` +\n            `<div class=\"test v-leave v-leave-active\">a</div>` +\n            `<div class=\"test\">b</div>` +\n            `<div class=\"test\">c</div>` +\n            `<div class=\"test v-enter v-enter-active\">d</div>` +\n          `</span>`\n        )\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          `<span>` +\n            `<div class=\"test v-leave-active v-leave-to\">a</div>` +\n            `<div class=\"test\">b</div>` +\n            `<div class=\"test\">c</div>` +\n            `<div class=\"test v-enter-active v-enter-to\">d</div>` +\n          `</span>`\n        )\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          `<span>` +\n            vm.items.map(i => `<div class=\"test\">${i}</div>`).join('') +\n          `</span>`\n        )\n      }).then(done)\n    })\n\n    it('use with \"is\" attribute', done => {\n      const vm = createBasicVM(true)\n      vm.items = ['b', 'c', 'd']\n      waitForUpdate(() => {\n        expect(vm.$el.innerHTML).toBe(\n          `<span>` +\n            `<div class=\"test v-leave v-leave-active\">a</div>` +\n            `<div class=\"test\">b</div>` +\n            `<div class=\"test\">c</div>` +\n            `<div class=\"test v-enter v-enter-active\">d</div>` +\n          `</span>`\n        )\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          `<span>` +\n            `<div class=\"test v-leave-active v-leave-to\">a</div>` +\n            `<div class=\"test\">b</div>` +\n            `<div class=\"test\">c</div>` +\n            `<div class=\"test v-enter-active v-enter-to\">d</div>` +\n          `</span>`\n        )\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          `<span>` +\n            vm.items.map(i => `<div class=\"test\">${i}</div>`).join('') +\n          `</span>`\n        )\n      }).then(done)\n    })\n\n    it('appear', done => {\n      const vm = createBasicVM(false, true /* appear */)\n      waitForUpdate(() => {\n        expect(vm.$el.innerHTML).toBe(\n          `<span>` +\n            vm.items.map(i => `<div class=\"test v-enter v-enter-active\">${i}</div>`).join('') +\n          `</span>`\n        )\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          `<span>` +\n            vm.items.map(i => `<div class=\"test v-enter-active v-enter-to\">${i}</div>`).join('') +\n          `</span>`\n        )\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          `<span>` +\n            vm.items.map(i => `<div class=\"test\">${i}</div>`).join('') +\n          `</span>`\n        )\n      }).then(done)\n    })\n\n    it('events', done => {\n      let next\n      const beforeEnterSpy = jasmine.createSpy()\n      const afterEnterSpy = jasmine.createSpy()\n      const afterLeaveSpy = jasmine.createSpy()\n      const vm = new Vue({\n        template: `\n          <div>\n            <transition-group @before-enter=\"beforeEnter\" @after-enter=\"afterEnter\" @after-leave=\"afterLeave\">\n              <div v-for=\"item in items\" :key=\"item\" class=\"test\">{{ item }}</div>\n            </transition-group>\n          </div>\n        `,\n        data: {\n          items: ['a', 'b', 'c']\n        },\n        methods: {\n          beforeEnter (el) {\n            expect(el.textContent).toBe('d')\n            beforeEnterSpy()\n          },\n          afterEnter (el) {\n            expect(el.textContent).toBe('d')\n            afterEnterSpy()\n            next()\n          },\n          afterLeave (el) {\n            expect(el.textContent).toBe('a')\n            afterLeaveSpy()\n            next()\n          }\n        }\n      }).$mount(el)\n\n      vm.items.push('d')\n      waitForUpdate(() => {\n        expect(vm.$el.innerHTML).toBe(\n          `<span>` +\n            `<div class=\"test\">a</div>` +\n            `<div class=\"test\">b</div>` +\n            `<div class=\"test\">c</div>` +\n            `<div class=\"test v-enter v-enter-active\">d</div>` +\n          `</span>`\n        )\n        expect(beforeEnterSpy.calls.count()).toBe(1)\n      }).thenWaitFor(_next => { next = _next }).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          `<span>` +\n            `<div class=\"test\">a</div>` +\n            `<div class=\"test\">b</div>` +\n            `<div class=\"test\">c</div>` +\n            `<div class=\"test\">d</div>` +\n          `</span>`\n        )\n        expect(afterEnterSpy.calls.count()).toBe(1)\n        vm.items.shift()\n      }).thenWaitFor(_next => { next = _next }).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          `<span>` +\n            `<div class=\"test\">b</div>` +\n            `<div class=\"test\">c</div>` +\n            `<div class=\"test\">d</div>` +\n          `</span>`\n        )\n        expect(afterLeaveSpy.calls.count()).toBe(1)\n      }).then(done)\n    })\n\n    it('move', done => {\n      const vm = new Vue({\n        template: `\n          <div>\n            <transition-group name=\"group\">\n              <div v-for=\"item in items\" :key=\"item\" class=\"test\">{{ item }}</div>\n            </transition-group>\n          </div>\n        `,\n        data: {\n          items: ['a', 'b', 'c']\n        }\n      }).$mount(el)\n\n      vm.items = ['d', 'b', 'a']\n      waitForUpdate(() => {\n        expect(vm.$el.innerHTML.replace(/\\s?style=\"\"(\\s?)/g, '$1')).toBe(\n          `<span>` +\n            `<div class=\"test group-enter group-enter-active\">d</div>` +\n            `<div class=\"test\">b</div>` +\n            `<div class=\"test group-move\">a</div>` +\n            `<div class=\"test group-leave group-leave-active group-move\">c</div>` +\n          `</span>`\n        )\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.innerHTML.replace(/\\s?style=\"\"(\\s?)/g, '$1')).toBe(\n          `<span>` +\n            `<div class=\"test group-enter-active group-enter-to\">d</div>` +\n            `<div class=\"test\">b</div>` +\n            `<div class=\"test group-move\">a</div>` +\n            `<div class=\"test group-leave-active group-move group-leave-to\">c</div>` +\n          `</span>`\n        )\n      }).thenWaitFor(duration * 2).then(() => {\n        expect(vm.$el.innerHTML.replace(/\\s?style=\"\"(\\s?)/g, '$1')).toBe(\n          `<span>` +\n            `<div class=\"test\">d</div>` +\n            `<div class=\"test\">b</div>` +\n            `<div class=\"test\">a</div>` +\n          `</span>`\n        )\n      }).then(done)\n    })\n\n    it('warn unkeyed children', () => {\n      new Vue({\n        template: `<div><transition-group><div v-for=\"i in 3\"></div></transition-group></div>`\n      }).$mount()\n      expect('<transition-group> children must be keyed: <div>').toHaveBeenWarned()\n    })\n\n    // Github issue #6006\n    it('should work with dynamic name', done => {\n      const vm = new Vue({\n        template: `\n          <div>\n            <transition-group :name=\"name\">\n              <div v-for=\"item in items\" :key=\"item\">{{ item }}</div>\n            </transition-group>\n          </div>\n        `,\n        data: {\n          items: ['a', 'b', 'c'],\n          name: 'group'\n        }\n      }).$mount(el)\n\n      vm.name = 'invalid-name'\n      vm.items = ['b', 'c', 'a']\n      waitForUpdate(() => {\n        expect(vm.$el.innerHTML.replace(/\\s?style=\"\"(\\s?)/g, '$1')).toBe(\n          `<span>` +\n            `<div>b</div>` +\n            `<div>c</div>` +\n            `<div>a</div>` +\n          `</span>`\n        )\n        vm.name = 'group'\n        vm.items = ['a', 'b', 'c']\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.innerHTML.replace(/\\s?style=\"\"(\\s?)/g, '$1')).toBe(\n          `<span>` +\n            `<div class=\"group-move\">a</div>` +\n            `<div class=\"group-move\">b</div>` +\n            `<div class=\"group-move\">c</div>` +\n          `</span>`\n        )\n      }).thenWaitFor(duration * 2 + buffer).then(() => {\n        expect(vm.$el.innerHTML.replace(/\\s?style=\"\"(\\s?)/g, '$1')).toBe(\n          `<span>` +\n            `<div>a</div>` +\n            `<div>b</div>` +\n            `<div>c</div>` +\n          `</span>`\n        )\n      }).then(done)\n    })\n  })\n}\n"
  },
  {
    "path": "test/unit/features/transition/transition-mode.spec.js",
    "content": "import Vue from 'vue'\nimport injectStyles from './inject-styles'\nimport { isIE9 } from 'core/util/env'\nimport { nextFrame } from 'web/runtime/transition-util'\n\nif (!isIE9) {\n  describe('Transition mode', () => {\n    const { duration, buffer } = injectStyles()\n    const components = {\n      one: { template: '<div>one</div>' },\n      two: { template: '<div>two</div>' }\n    }\n\n    let el\n    beforeEach(() => {\n      el = document.createElement('div')\n      document.body.appendChild(el)\n    })\n\n    it('dynamic components, simultaneous', done => {\n      const vm = new Vue({\n        template: `<div>\n          <transition>\n            <component :is=\"view\" class=\"test\">\n            </component>\n          </transition>\n        </div>`,\n        data: { view: 'one' },\n        components\n      }).$mount(el)\n      expect(vm.$el.textContent).toBe('one')\n      vm.view = 'two'\n      waitForUpdate(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test v-leave v-leave-active\">one</div>' +\n          '<div class=\"test v-enter v-enter-active\">two</div>'\n        )\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test v-leave-active v-leave-to\">one</div>' +\n          '<div class=\"test v-enter-active v-enter-to\">two</div>'\n        )\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test\">two</div>'\n        )\n      }).then(done)\n    })\n\n    it('dynamic components, out-in', done => {\n      let next\n      const vm = new Vue({\n        template: `<div>\n          <transition name=\"test\" mode=\"out-in\" @after-leave=\"afterLeave\">\n            <component :is=\"view\" class=\"test\">\n            </component>\n          </transition>\n        </div>`,\n        data: { view: 'one' },\n        components,\n        methods: {\n          afterLeave () {\n            next()\n          }\n        }\n      }).$mount(el)\n      expect(vm.$el.textContent).toBe('one')\n      vm.view = 'two'\n      waitForUpdate(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test test-leave test-leave-active\">one</div><!---->'\n        )\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test test-leave-active test-leave-to\">one</div><!---->'\n        )\n      }).thenWaitFor(_next => { next = _next }).then(() => {\n        expect(vm.$el.innerHTML).toBe('<!---->')\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test test-enter test-enter-active\">two</div>'\n        )\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test test-enter-active test-enter-to\">two</div>'\n        )\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test\">two</div>'\n        )\n      }).then(done)\n    })\n\n    // #3440\n    it('dynamic components, out-in (with extra re-render)', done => {\n      let next\n      const vm = new Vue({\n        template: `<div>\n          <transition name=\"test\" mode=\"out-in\" @after-leave=\"afterLeave\">\n            <component :is=\"view\" class=\"test\">\n            </component>\n          </transition>\n        </div>`,\n        data: { view: 'one' },\n        components,\n        methods: {\n          afterLeave () {\n            next()\n          }\n        }\n      }).$mount(el)\n      expect(vm.$el.textContent).toBe('one')\n      vm.view = 'two'\n      waitForUpdate(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test test-leave test-leave-active\">one</div><!---->'\n        )\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test test-leave-active test-leave-to\">one</div><!---->'\n        )\n        // Force re-render before the element finishes leaving\n        // this should not cause the incoming element to enter early\n        vm.$forceUpdate()\n      }).thenWaitFor(_next => { next = _next }).then(() => {\n        expect(vm.$el.innerHTML).toBe('<!---->')\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test test-enter test-enter-active\">two</div>'\n        )\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test test-enter-active test-enter-to\">two</div>'\n        )\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test\">two</div>'\n        )\n      }).then(done)\n    })\n\n    it('dynamic components, in-out', done => {\n      let next\n      const vm = new Vue({\n        template: `<div>\n          <transition name=\"test\" mode=\"in-out\" @after-enter=\"afterEnter\">\n            <component :is=\"view\" class=\"test\">\n            </component>\n          </transition>\n        </div>`,\n        data: { view: 'one' },\n        components,\n        methods: {\n          afterEnter () {\n            next()\n          }\n        }\n      }).$mount(el)\n      expect(vm.$el.textContent).toBe('one')\n      vm.view = 'two'\n      waitForUpdate(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test\">one</div>' +\n          '<div class=\"test test-enter test-enter-active\">two</div>'\n        )\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test\">one</div>' +\n          '<div class=\"test test-enter-active test-enter-to\">two</div>'\n        )\n      }).thenWaitFor(_next => { next = _next }).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test\">one</div>' +\n          '<div class=\"test\">two</div>'\n        )\n      }).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test test-leave test-leave-active\">one</div>' +\n          '<div class=\"test\">two</div>'\n        )\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test test-leave-active test-leave-to\">one</div>' +\n          '<div class=\"test\">two</div>'\n        )\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test\">two</div>'\n        )\n      }).then(done)\n    })\n\n    it('dynamic components, in-out with early cancel', done => {\n      let next\n      const vm = new Vue({\n        template: `<div>\n          <transition name=\"test\" mode=\"in-out\" @after-enter=\"afterEnter\">\n            <component :is=\"view\" class=\"test\"></component>\n          </transition>\n        </div>`,\n        data: { view: 'one' },\n        components,\n        methods: {\n          afterEnter () {\n            next()\n          }\n        }\n      }).$mount(el)\n      expect(vm.$el.textContent).toBe('one')\n      vm.view = 'two'\n      waitForUpdate(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test\">one</div>' +\n          '<div class=\"test test-enter test-enter-active\">two</div>'\n        )\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test\">one</div>' +\n          '<div class=\"test test-enter-active test-enter-to\">two</div>'\n        )\n        // switch again before enter finishes,\n        // this cancels both enter and leave.\n        vm.view = 'one'\n      }).then(() => {\n        // 1. the pending leaving \"one\" should be removed instantly.\n        // 2. the entering \"two\" should be placed into its final state instantly.\n        // 3. a new \"one\" is created and entering\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test\">two</div>' +\n          '<div class=\"test test-enter test-enter-active\">one</div>'\n        )\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test\">two</div>' +\n          '<div class=\"test test-enter-active test-enter-to\">one</div>'\n        )\n      }).thenWaitFor(_next => { next = _next }).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test\">two</div>' +\n          '<div class=\"test\">one</div>'\n        )\n      }).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test test-leave test-leave-active\">two</div>' +\n          '<div class=\"test\">one</div>'\n        )\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test test-leave-active test-leave-to\">two</div>' +\n          '<div class=\"test\">one</div>'\n        )\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test\">one</div>'\n        )\n      }).then(done).then(done)\n    })\n\n    it('normal elements with different keys, simultaneous', done => {\n      const vm = new Vue({\n        template: `<div>\n          <transition>\n            <div :key=\"view\" class=\"test\">{{view}}</div>\n          </transition>\n        </div>`,\n        data: { view: 'one' },\n        components\n      }).$mount(el)\n      expect(vm.$el.textContent).toBe('one')\n      vm.view = 'two'\n      waitForUpdate(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test v-leave v-leave-active\">one</div>' +\n          '<div class=\"test v-enter v-enter-active\">two</div>'\n        )\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test v-leave-active v-leave-to\">one</div>' +\n          '<div class=\"test v-enter-active v-enter-to\">two</div>'\n        )\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test\">two</div>'\n        )\n      }).then(done)\n    })\n\n    it('normal elements with different keys, out-in', done => {\n      let next\n      const vm = new Vue({\n        template: `<div>\n          <transition name=\"test\" mode=\"out-in\" @after-leave=\"afterLeave\">\n            <div :key=\"view\" class=\"test\">{{view}}</div>\n          </transition>\n        </div>`,\n        data: { view: 'one' },\n        components,\n        methods: {\n          afterLeave () {\n            next()\n          }\n        }\n      }).$mount(el)\n      expect(vm.$el.textContent).toBe('one')\n      vm.view = 'two'\n      waitForUpdate(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test test-leave test-leave-active\">one</div><!---->'\n        )\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test test-leave-active test-leave-to\">one</div><!---->'\n        )\n      }).thenWaitFor(_next => { next = _next }).then(() => {\n        expect(vm.$el.innerHTML).toBe('<!---->')\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test test-enter test-enter-active\">two</div>'\n        )\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test test-enter-active test-enter-to\">two</div>'\n        )\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test\">two</div>'\n        )\n      }).then(done)\n    })\n\n    it('normal elements with different keys, in-out', done => {\n      let next\n      const vm = new Vue({\n        template: `<div>\n          <transition name=\"test\" mode=\"in-out\" @after-enter=\"afterEnter\">\n            <div :key=\"view\" class=\"test\">{{view}}</div>\n          </transition>\n        </div>`,\n        data: { view: 'one' },\n        components,\n        methods: {\n          afterEnter () {\n            next()\n          }\n        }\n      }).$mount(el)\n      expect(vm.$el.textContent).toBe('one')\n      vm.view = 'two'\n      waitForUpdate(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test\">one</div>' +\n          '<div class=\"test test-enter test-enter-active\">two</div>'\n        )\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test\">one</div>' +\n          '<div class=\"test test-enter-active test-enter-to\">two</div>'\n        )\n      }).thenWaitFor(_next => { next = _next }).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test\">one</div>' +\n          '<div class=\"test\">two</div>'\n        )\n      }).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test test-leave test-leave-active\">one</div>' +\n          '<div class=\"test\">two</div>'\n        )\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test test-leave-active test-leave-to\">one</div>' +\n          '<div class=\"test\">two</div>'\n        )\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.innerHTML).toBe(\n          '<div class=\"test\">two</div>'\n        )\n      }).then(done)\n    })\n\n    it('transition out-in on async component (resolve before leave complete)', done => {\n      const vm = new Vue({\n        template: `\n          <div>\n            <transition name=\"test-anim\" mode=\"out-in\">\n              <component-a v-if=\"ok\"></component-a>\n              <component-b v-else></component-b>\n            </transition>\n          </div>\n        `,\n        components: {\n          componentA: resolve => {\n            setTimeout(() => {\n              resolve({ template: '<div><h1>component A</h1></div>' })\n              next1()\n            }, duration / 2)\n          },\n          componentB: resolve => {\n            setTimeout(() => {\n              resolve({ template: '<div><h1>component B</h1></div>' })\n            }, duration / 2)\n          }\n        },\n        data: {\n          ok: true\n        }\n      }).$mount(el)\n\n      expect(vm.$el.innerHTML).toBe('<!---->')\n\n      function next1 () {\n        Vue.nextTick(() => {\n          expect(vm.$el.children.length).toBe(1)\n          expect(vm.$el.textContent).toBe('component A')\n          expect(vm.$el.children[0].className).toBe('test-anim-enter test-anim-enter-active')\n          nextFrame(() => {\n            expect(vm.$el.children[0].className).toBe('test-anim-enter-active test-anim-enter-to')\n            setTimeout(() => {\n              expect(vm.$el.children[0].className).toBe('')\n              vm.ok = false\n              next2()\n            }, duration + buffer)\n          })\n        })\n      }\n\n      function next2 () {\n        waitForUpdate(() => {\n          expect(vm.$el.children.length).toBe(1)\n          expect(vm.$el.textContent).toBe('component A')\n          expect(vm.$el.children[0].className).toBe('test-anim-leave test-anim-leave-active')\n        }).thenWaitFor(nextFrame).then(() => {\n          expect(vm.$el.children[0].className).toBe('test-anim-leave-active test-anim-leave-to')\n        }).thenWaitFor(duration + buffer).then(() => {\n          expect(vm.$el.children.length).toBe(1)\n          expect(vm.$el.textContent).toBe('component B')\n          expect(vm.$el.children[0].className).toMatch('test-anim-enter-active')\n        }).thenWaitFor(duration * 2).then(() => {\n          expect(vm.$el.children[0].className).toBe('')\n        }).then(done)\n      }\n    })\n\n    it('transition out-in on async component (resolve after leave complete)', done => {\n      const vm = new Vue({\n        template: `\n          <div>\n            <transition name=\"test-anim\" mode=\"out-in\">\n              <component-a v-if=\"ok\"></component-a>\n              <component-b v-else></component-b>\n            </transition>\n          </div>\n        `,\n        components: {\n          componentA: { template: '<div><h1>component A</h1></div>' },\n          componentB: resolve => {\n            setTimeout(() => {\n              resolve({ template: '<div><h1>component B</h1></div>' })\n              Vue.nextTick(next)\n            }, (duration + buffer) * 1.5)\n          }\n        },\n        data: {\n          ok: true\n        }\n      }).$mount(el)\n\n      expect(vm.$el.innerHTML).toBe('<div><h1>component A</h1></div>')\n\n      let next\n\n      vm.ok = false\n      waitForUpdate(() => {\n        expect(vm.$el.children.length).toBe(1)\n        expect(vm.$el.textContent).toBe('component A')\n        expect(vm.$el.children[0].className).toBe('test-anim-leave test-anim-leave-active')\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.children[0].className).toBe('test-anim-leave-active test-anim-leave-to')\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.children.length).toBe(0)\n        expect(vm.$el.innerHTML).toBe('<!---->')\n      }).thenWaitFor(_next => { next = _next }).then(() => {\n        expect(vm.$el.children.length).toBe(1)\n        expect(vm.$el.textContent).toBe('component B')\n        expect(vm.$el.children[0].className).toBe('test-anim-enter test-anim-enter-active')\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.children[0].className).toBe('test-anim-enter-active test-anim-enter-to')\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.children.length).toBe(1)\n        expect(vm.$el.textContent).toBe('component B')\n        expect(vm.$el.children[0].className).toBe('')\n      }).then(done)\n    })\n\n    it('transition in-out on async component', done => {\n      const vm = new Vue({\n        template: `\n          <div>\n            <transition name=\"test-anim\" mode=\"in-out\">\n              <component-a v-if=\"ok\"></component-a>\n              <component-b v-else></component-b>\n            </transition>\n          </div>\n        `,\n        components: {\n          componentA: resolve => {\n            setTimeout(() => {\n              resolve({ template: '<div><h1>component A</h1></div>' })\n              next1()\n            }, duration / 2)\n          },\n          componentB: resolve => {\n            setTimeout(() => {\n              resolve({ template: '<div><h1>component B</h1></div>' })\n              next2()\n            }, duration / 2)\n          }\n        },\n        data: {\n          ok: true\n        }\n      }).$mount(el)\n\n      expect(vm.$el.innerHTML).toBe('<!---->')\n\n      function next1 () {\n        Vue.nextTick(() => {\n          expect(vm.$el.children.length).toBe(1)\n          expect(vm.$el.textContent).toBe('component A')\n          expect(vm.$el.children[0].className).toBe('test-anim-enter test-anim-enter-active')\n          nextFrame(() => {\n            expect(vm.$el.children[0].className).toBe('test-anim-enter-active test-anim-enter-to')\n            setTimeout(() => {\n              expect(vm.$el.children[0].className).toBe('')\n              vm.ok = false\n            }, duration + buffer)\n          })\n        })\n      }\n\n      function next2 () {\n        waitForUpdate(() => {\n          expect(vm.$el.children.length).toBe(2)\n          expect(vm.$el.textContent).toBe('component Acomponent B')\n          expect(vm.$el.children[0].className).toBe('')\n          expect(vm.$el.children[1].className).toBe('test-anim-enter test-anim-enter-active')\n        }).thenWaitFor(nextFrame).then(() => {\n          expect(vm.$el.children[1].className).toBe('test-anim-enter-active test-anim-enter-to')\n        }).thenWaitFor(duration + buffer).then(() => {\n          expect(vm.$el.children.length).toBe(2)\n          expect(vm.$el.textContent).toBe('component Acomponent B')\n          expect(vm.$el.children[0].className).toMatch('test-anim-leave-active')\n          expect(vm.$el.children[1].className).toBe('')\n        }).thenWaitFor(duration + buffer).then(() => {\n          expect(vm.$el.children.length).toBe(1)\n          expect(vm.$el.textContent).toBe('component B')\n          expect(vm.$el.children[0].className).toBe('')\n        }).then(done)\n      }\n    })\n\n    it('warn invalid mode', () => {\n      new Vue({\n        template: '<transition mode=\"foo\"><div>123</div></transition>'\n      }).$mount()\n      expect('invalid <transition> mode: foo').toHaveBeenWarned()\n    })\n  })\n}\n"
  },
  {
    "path": "test/unit/features/transition/transition.spec.js",
    "content": "import Vue from 'vue'\nimport injectStyles from './inject-styles'\nimport { isIE9 } from 'core/util/env'\nimport { nextFrame } from 'web/runtime/transition-util'\n\nif (!isIE9) {\n  describe('Transition basic', () => {\n    const { duration, buffer } = injectStyles()\n    const explicitDuration = duration * 2\n\n    let el\n    beforeEach(() => {\n      el = document.createElement('div')\n      document.body.appendChild(el)\n    })\n\n    it('basic transition', done => {\n      const vm = new Vue({\n        template: '<div><transition><div v-if=\"ok\" class=\"test\">foo</div></transition></div>',\n        data: { ok: true }\n      }).$mount(el)\n\n      // should not apply transition on initial render by default\n      expect(vm.$el.innerHTML).toBe('<div class=\"test\">foo</div>')\n      vm.ok = false\n      waitForUpdate(() => {\n        expect(vm.$el.children[0].className).toBe('test v-leave v-leave-active')\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.children[0].className).toBe('test v-leave-active v-leave-to')\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.children.length).toBe(0)\n        vm.ok = true\n      }).then(() => {\n        expect(vm.$el.children[0].className).toBe('test v-enter v-enter-active')\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.children[0].className).toBe('test v-enter-active v-enter-to')\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.children[0].className).toBe('test')\n      }).then(done)\n    })\n\n    it('named transition', done => {\n      const vm = new Vue({\n        template: '<div><transition name=\"test\"><div v-if=\"ok\" class=\"test\">foo</div></transition></div>',\n        data: { ok: true }\n      }).$mount(el)\n\n      // should not apply transition on initial render by default\n      expect(vm.$el.innerHTML).toBe('<div class=\"test\">foo</div>')\n      vm.ok = false\n      waitForUpdate(() => {\n        expect(vm.$el.children[0].className).toBe('test test-leave test-leave-active')\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.children[0].className).toBe('test test-leave-active test-leave-to')\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.children.length).toBe(0)\n        vm.ok = true\n      }).then(() => {\n        expect(vm.$el.children[0].className).toBe('test test-enter test-enter-active')\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.children[0].className).toBe('test test-enter-active test-enter-to')\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.children[0].className).toBe('test')\n      }).then(done)\n    })\n\n    it('custom transition classes', done => {\n      const vm = new Vue({\n        template: `\n          <div>\n            <transition\n              enter-class=\"hello\"\n              enter-active-class=\"hello-active\"\n              enter-to-class=\"hello-to\"\n              leave-class=\"bye\"\n              leave-to-class=\"bye-to\"\n              leave-active-class=\"byebye active more \">\n              <div v-if=\"ok\" class=\"test\">foo</div>\n            </transition>\n          </div>\n        `,\n        data: { ok: true }\n      }).$mount(el)\n\n      // should not apply transition on initial render by default\n      expect(vm.$el.innerHTML).toBe('<div class=\"test\">foo</div>')\n      vm.ok = false\n      waitForUpdate(() => {\n        expect(vm.$el.children[0].className).toBe('test bye byebye active more')\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.children[0].className).toBe('test byebye active more bye-to')\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.children.length).toBe(0)\n        vm.ok = true\n      }).then(() => {\n        expect(vm.$el.children[0].className).toBe('test hello hello-active')\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.children[0].className).toBe('test hello-active hello-to')\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.children[0].className).toBe('test')\n      }).then(done)\n    })\n\n    it('dynamic transition', done => {\n      const vm = new Vue({\n        template: `\n          <div>\n            <transition :name=\"trans\">\n              <div v-if=\"ok\" class=\"test\">foo</div>\n            </transition>\n          </div>\n        `,\n        data: {\n          ok: true,\n          trans: 'test'\n        }\n      }).$mount(el)\n\n      // should not apply transition on initial render by default\n      expect(vm.$el.innerHTML).toBe('<div class=\"test\">foo</div>')\n      vm.ok = false\n      waitForUpdate(() => {\n        expect(vm.$el.children[0].className).toBe('test test-leave test-leave-active')\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.children[0].className).toBe('test test-leave-active test-leave-to')\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.children.length).toBe(0)\n        vm.ok = true\n        vm.trans = 'changed'\n      }).then(() => {\n        expect(vm.$el.children[0].className).toBe('test changed-enter changed-enter-active')\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.children[0].className).toBe('test changed-enter-active changed-enter-to')\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.children[0].className).toBe('test')\n      }).then(done)\n    })\n\n    it('inline transition object', done => {\n      const enter = jasmine.createSpy('enter')\n      const leave = jasmine.createSpy('leave')\n      const vm = new Vue({\n        render (h) {\n          return h('div', null, [\n            h('transition', {\n              props: {\n                name: 'inline',\n                enterClass: 'hello',\n                enterToClass: 'hello-to',\n                enterActiveClass: 'hello-active',\n                leaveClass: 'bye',\n                leaveToClass: 'bye-to',\n                leaveActiveClass: 'byebye active'\n              },\n              on: {\n                enter,\n                leave\n              }\n            }, this.ok ? [h('div', { class: 'test' }, 'foo')] : undefined)\n          ])\n        },\n        data: { ok: true }\n      }).$mount(el)\n\n      // should not apply transition on initial render by default\n      expect(vm.$el.innerHTML).toBe('<div class=\"test\">foo</div>')\n      vm.ok = false\n      waitForUpdate(() => {\n        expect(vm.$el.children[0].className).toBe('test bye byebye active')\n        expect(leave).toHaveBeenCalled()\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.children[0].className).toBe('test byebye active bye-to')\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.children.length).toBe(0)\n        vm.ok = true\n      }).then(() => {\n        expect(vm.$el.children[0].className).toBe('test hello hello-active')\n        expect(enter).toHaveBeenCalled()\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.children[0].className).toBe('test hello-active hello-to')\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.children[0].className).toBe('test')\n      }).then(done)\n    })\n\n    it('transition events', done => {\n      const onLeaveSpy = jasmine.createSpy('leave')\n      const onEnterSpy = jasmine.createSpy('enter')\n      const beforeLeaveSpy = jasmine.createSpy('beforeLeave')\n      const beforeEnterSpy = jasmine.createSpy('beforeEnter')\n      const afterLeaveSpy = jasmine.createSpy('afterLeave')\n      const afterEnterSpy = jasmine.createSpy('afterEnter')\n\n      const vm = new Vue({\n        template: `\n          <div>\n            <transition\n              name=\"test\"\n              @before-enter=\"beforeEnter\"\n              @enter=\"enter\"\n              @after-enter=\"afterEnter\"\n              @before-leave=\"beforeLeave\"\n              @leave=\"leave\"\n              @after-leave=\"afterLeave\">\n              <div v-if=\"ok\" class=\"test\">foo</div>\n            </transition>\n          </div>\n        `,\n        data: { ok: true },\n        methods: {\n          beforeLeave: (el) => {\n            expect(el).toBe(vm.$el.children[0])\n            expect(el.className).toBe('test')\n            beforeLeaveSpy(el)\n          },\n          leave: (el) => onLeaveSpy(el),\n          afterLeave: (el) => afterLeaveSpy(el),\n          beforeEnter: (el) => {\n            expect(vm.$el.contains(el)).toBe(false)\n            expect(el.className).toBe('test')\n            beforeEnterSpy(el)\n          },\n          enter: (el) => {\n            expect(vm.$el.contains(el)).toBe(true)\n            onEnterSpy(el)\n          },\n          afterEnter: (el) => afterEnterSpy(el)\n        }\n      }).$mount(el)\n\n      // should not apply transition on initial render by default\n      expect(vm.$el.innerHTML).toBe('<div class=\"test\">foo</div>')\n\n      let _el = vm.$el.children[0]\n      vm.ok = false\n      waitForUpdate(() => {\n        expect(beforeLeaveSpy).toHaveBeenCalledWith(_el)\n        expect(onLeaveSpy).toHaveBeenCalledWith(_el)\n        expect(vm.$el.children[0].className).toBe('test test-leave test-leave-active')\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(afterLeaveSpy).not.toHaveBeenCalled()\n        expect(vm.$el.children[0].className).toBe('test test-leave-active test-leave-to')\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(afterLeaveSpy).toHaveBeenCalledWith(_el)\n        expect(vm.$el.children.length).toBe(0)\n        vm.ok = true\n      }).then(() => {\n        _el = vm.$el.children[0]\n        expect(beforeEnterSpy).toHaveBeenCalledWith(_el)\n        expect(onEnterSpy).toHaveBeenCalledWith(_el)\n        expect(vm.$el.children[0].className).toBe('test test-enter test-enter-active')\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(afterEnterSpy).not.toHaveBeenCalled()\n        expect(vm.$el.children[0].className).toBe('test test-enter-active test-enter-to')\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(afterEnterSpy).toHaveBeenCalledWith(_el)\n        expect(vm.$el.children[0].className).toBe('test')\n      }).then(done)\n    })\n\n    it('transition events (v-show)', done => {\n      const onLeaveSpy = jasmine.createSpy('leave')\n      const onEnterSpy = jasmine.createSpy('enter')\n      const beforeLeaveSpy = jasmine.createSpy('beforeLeave')\n      const beforeEnterSpy = jasmine.createSpy('beforeEnter')\n      const afterLeaveSpy = jasmine.createSpy('afterLeave')\n      const afterEnterSpy = jasmine.createSpy('afterEnter')\n\n      const vm = new Vue({\n        template: `\n          <div>\n            <transition\n              name=\"test\"\n              @before-enter=\"beforeEnter\"\n              @enter=\"enter\"\n              @after-enter=\"afterEnter\"\n              @before-leave=\"beforeLeave\"\n              @leave=\"leave\"\n              @after-leave=\"afterLeave\">\n              <div v-show=\"ok\" class=\"test\">foo</div>\n            </transition>\n          </div>\n        `,\n        data: { ok: true },\n        methods: {\n          beforeLeave: (el) => {\n            expect(el.style.display).toBe('')\n            expect(el).toBe(vm.$el.children[0])\n            expect(el.className).toBe('test')\n            beforeLeaveSpy(el)\n          },\n          leave: (el) => {\n            expect(el.style.display).toBe('')\n            onLeaveSpy(el)\n          },\n          afterLeave: (el) => {\n            expect(el.style.display).toBe('none')\n            afterLeaveSpy(el)\n          },\n          beforeEnter: (el) => {\n            expect(el.className).toBe('test')\n            expect(el.style.display).toBe('none')\n            beforeEnterSpy(el)\n          },\n          enter: (el) => {\n            expect(el.style.display).toBe('')\n            onEnterSpy(el)\n          },\n          afterEnter: (el) => {\n            expect(el.style.display).toBe('')\n            afterEnterSpy(el)\n          }\n        }\n      }).$mount(el)\n\n      // should not apply transition on initial render by default\n      expect(vm.$el.innerHTML).toBe('<div class=\"test\">foo</div>')\n\n      let _el = vm.$el.children[0]\n      vm.ok = false\n      waitForUpdate(() => {\n        expect(beforeLeaveSpy).toHaveBeenCalledWith(_el)\n        expect(onLeaveSpy).toHaveBeenCalledWith(_el)\n        expect(vm.$el.children[0].className).toBe('test test-leave test-leave-active')\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(afterLeaveSpy).not.toHaveBeenCalled()\n        expect(vm.$el.children[0].className).toBe('test test-leave-active test-leave-to')\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(afterLeaveSpy).toHaveBeenCalledWith(_el)\n        expect(vm.$el.children[0].style.display).toBe('none')\n        vm.ok = true\n      }).then(() => {\n        _el = vm.$el.children[0]\n        expect(beforeEnterSpy).toHaveBeenCalledWith(_el)\n        expect(onEnterSpy).toHaveBeenCalledWith(_el)\n        expect(vm.$el.children[0].className).toBe('test test-enter test-enter-active')\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(afterEnterSpy).not.toHaveBeenCalled()\n        expect(vm.$el.children[0].className).toBe('test test-enter-active test-enter-to')\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(afterEnterSpy).toHaveBeenCalledWith(_el)\n        expect(vm.$el.children[0].className).toBe('test')\n      }).then(done)\n    })\n\n    it('explicit user callback in JavaScript hooks', done => {\n      let next\n      const vm = new Vue({\n        template: `<div>\n          <transition name=\"test\" @enter=\"enter\" @leave=\"leave\">\n            <div v-if=\"ok\" class=\"test\">foo</div>\n          </transition>\n        </div>`,\n        data: { ok: true },\n        methods: {\n          enter: (el, cb) => {\n            next = cb\n          },\n          leave: (el, cb) => {\n            next = cb\n          }\n        }\n      }).$mount(el)\n      vm.ok = false\n      waitForUpdate(() => {\n        expect(vm.$el.children[0].className).toBe('test test-leave test-leave-active')\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.children[0].className).toBe('test test-leave-active test-leave-to')\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.children[0].className).toBe('test test-leave-active test-leave-to')\n        expect(next).toBeTruthy()\n        next()\n        expect(vm.$el.children.length).toBe(0)\n      }).then(() => {\n        vm.ok = true\n      }).then(() => {\n        expect(vm.$el.children[0].className).toBe('test test-enter test-enter-active')\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.children[0].className).toBe('test test-enter-active test-enter-to')\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.children[0].className).toBe('test test-enter-active test-enter-to')\n        expect(next).toBeTruthy()\n        next()\n        expect(vm.$el.children[0].className).toBe('test')\n      }).then(done)\n    })\n\n    it('css: false', done => {\n      const enterSpy = jasmine.createSpy('enter')\n      const leaveSpy = jasmine.createSpy('leave')\n      const vm = new Vue({\n        template: `\n          <div>\n            <transition :css=\"false\" name=\"test\" @enter=\"enter\" @leave=\"leave\">\n              <div v-if=\"ok\" class=\"test\">foo</div>\n            </transition>\n          </div>\n        `,\n        data: { ok: true },\n        methods: {\n          enter: enterSpy,\n          leave: leaveSpy\n        }\n      }).$mount(el)\n\n      vm.ok = false\n      waitForUpdate(() => {\n        expect(leaveSpy).toHaveBeenCalled()\n        expect(vm.$el.innerHTML).toBe('<!---->')\n        vm.ok = true\n      }).then(() => {\n        expect(enterSpy).toHaveBeenCalled()\n        expect(vm.$el.innerHTML).toBe('<div class=\"test\">foo</div>')\n      }).then(done)\n    })\n\n    it('no transition detected', done => {\n      const enterSpy = jasmine.createSpy('enter')\n      const leaveSpy = jasmine.createSpy('leave')\n      const vm = new Vue({\n        template: '<div><transition name=\"nope\" @enter=\"enter\" @leave=\"leave\"><div v-if=\"ok\">foo</div></transition></div>',\n        data: { ok: true },\n        methods: {\n          enter: enterSpy,\n          leave: leaveSpy\n        }\n      }).$mount(el)\n\n      vm.ok = false\n      waitForUpdate(() => {\n        expect(leaveSpy).toHaveBeenCalled()\n        expect(vm.$el.innerHTML).toBe('<div class=\"nope-leave nope-leave-active\">foo</div><!---->')\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.innerHTML).toBe('<!---->')\n        vm.ok = true\n      }).then(() => {\n        expect(enterSpy).toHaveBeenCalled()\n        expect(vm.$el.innerHTML).toBe('<div class=\"nope-enter nope-enter-active\">foo</div>')\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.innerHTML).toBe('<div>foo</div>')\n      }).then(done)\n    })\n\n    it('enterCancelled', done => {\n      const spy = jasmine.createSpy('enterCancelled')\n      const vm = new Vue({\n        template: `\n          <div>\n            <transition name=\"test\" @enter-cancelled=\"enterCancelled\">\n              <div v-if=\"ok\" class=\"test\">foo</div>\n            </transition>\n          </div>\n        `,\n        data: { ok: false },\n        methods: {\n          enterCancelled: spy\n        }\n      }).$mount(el)\n\n      expect(vm.$el.innerHTML).toBe('<!---->')\n      vm.ok = true\n      waitForUpdate(() => {\n        expect(vm.$el.children[0].className).toBe('test test-enter test-enter-active')\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.children[0].className).toBe('test test-enter-active test-enter-to')\n      }).thenWaitFor(duration / 2).then(() => {\n        vm.ok = false\n      }).then(() => {\n        expect(spy).toHaveBeenCalled()\n        expect(vm.$el.children[0].className).toBe('test test-leave test-leave-active')\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.children[0].className).toBe('test test-leave-active test-leave-to')\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.children.length).toBe(0)\n      }).then(done)\n    })\n\n    it('should remove stale leaving elements', done => {\n      const spy = jasmine.createSpy('afterLeave')\n      const vm = new Vue({\n        template: `\n          <div>\n            <transition name=\"test\" @after-leave=\"afterLeave\">\n              <div v-if=\"ok\" class=\"test\">foo</div>\n            </transition>\n          </div>\n        `,\n        data: { ok: true },\n        methods: {\n          afterLeave: spy\n        }\n      }).$mount(el)\n\n      expect(vm.$el.innerHTML).toBe('<div class=\"test\">foo</div>')\n      vm.ok = false\n      waitForUpdate(() => {\n        expect(vm.$el.children[0].className).toBe('test test-leave test-leave-active')\n      }).thenWaitFor(duration / 2).then(() => {\n        vm.ok = true\n      }).then(() => {\n        expect(spy).toHaveBeenCalled()\n        expect(vm.$el.children.length).toBe(1) // should have removed leaving element\n        expect(vm.$el.children[0].className).toBe('test test-enter test-enter-active')\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.children[0].className).toBe('test test-enter-active test-enter-to')\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.innerHTML).toBe('<div class=\"test\">foo</div>')\n      }).then(done)\n    })\n\n    it('transition with v-show', done => {\n      const vm = new Vue({\n        template: `\n          <div>\n            <transition name=\"test\">\n              <div v-show=\"ok\" class=\"test\">foo</div>\n            </transition>\n          </div>\n        `,\n        data: { ok: true }\n      }).$mount(el)\n\n      // should not apply transition on initial render by default\n      expect(vm.$el.textContent).toBe('foo')\n      expect(vm.$el.children[0].style.display).toBe('')\n      expect(vm.$el.children[0].className).toBe('test')\n      vm.ok = false\n      waitForUpdate(() => {\n        expect(vm.$el.children[0].className).toBe('test test-leave test-leave-active')\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.children[0].className).toBe('test test-leave-active test-leave-to')\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.children[0].style.display).toBe('none')\n        vm.ok = true\n      }).then(() => {\n        expect(vm.$el.children[0].style.display).toBe('')\n        expect(vm.$el.children[0].className).toBe('test test-enter test-enter-active')\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.children[0].className).toBe('test test-enter-active test-enter-to')\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.children[0].className).toBe('test')\n      }).then(done)\n    })\n\n    it('transition with v-show, inside child component', done => {\n      const vm = new Vue({\n        template: `\n          <div>\n            <test v-show=\"ok\"></test>\n          </div>\n        `,\n        data: { ok: true },\n        components: {\n          test: {\n            template: `<transition name=\"test\"><div class=\"test\">foo</div></transition>`\n          }\n        }\n      }).$mount(el)\n\n      // should not apply transition on initial render by default\n      expect(vm.$el.textContent).toBe('foo')\n      expect(vm.$el.children[0].style.display).toBe('')\n      vm.ok = false\n      waitForUpdate(() => {\n        expect(vm.$el.children[0].className).toBe('test test-leave test-leave-active')\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.children[0].className).toBe('test test-leave-active test-leave-to')\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.children[0].style.display).toBe('none')\n        vm.ok = true\n      }).then(() => {\n        expect(vm.$el.children[0].style.display).toBe('')\n        expect(vm.$el.children[0].className).toBe('test test-enter test-enter-active')\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.children[0].className).toBe('test test-enter-active test-enter-to')\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.children[0].className).toBe('test')\n      }).then(done)\n    })\n\n    it('leaveCancelled (v-show only)', done => {\n      const spy = jasmine.createSpy('leaveCancelled')\n      const vm = new Vue({\n        template: `\n          <div>\n            <transition name=\"test\" @leave-cancelled=\"leaveCancelled\">\n              <div v-show=\"ok\" class=\"test\">foo</div>\n            </transition>\n          </div>\n        `,\n        data: { ok: true },\n        methods: {\n          leaveCancelled: spy\n        }\n      }).$mount(el)\n\n      expect(vm.$el.children[0].style.display).toBe('')\n      vm.ok = false\n      waitForUpdate(() => {\n        expect(vm.$el.children[0].className).toBe('test test-leave test-leave-active')\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.children[0].className).toBe('test test-leave-active test-leave-to')\n      }).thenWaitFor(10).then(() => {\n        vm.ok = true\n      }).then(() => {\n        expect(spy).toHaveBeenCalled()\n        expect(vm.$el.children[0].className).toBe('test test-enter test-enter-active')\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.children[0].className).toBe('test test-enter-active test-enter-to')\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.children[0].style.display).toBe('')\n      }).then(done)\n    })\n\n    it('animations', done => {\n      const vm = new Vue({\n        template: `\n          <div>\n            <transition name=\"test-anim\">\n              <div v-if=\"ok\">foo</div>\n            </transition>\n          </div>\n        `,\n        data: { ok: true }\n      }).$mount(el)\n\n      // should not apply transition on initial render by default\n      expect(vm.$el.innerHTML).toBe('<div>foo</div>')\n      vm.ok = false\n      waitForUpdate(() => {\n        expect(vm.$el.children[0].className).toBe('test-anim-leave test-anim-leave-active')\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.children[0].className).toBe('test-anim-leave-active test-anim-leave-to')\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.children.length).toBe(0)\n        vm.ok = true\n      }).then(() => {\n        expect(vm.$el.children[0].className).toBe('test-anim-enter test-anim-enter-active')\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.children[0].className).toBe('test-anim-enter-active test-anim-enter-to')\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.children[0].className).toBe('')\n      }).then(done)\n    })\n\n    it('explicit transition type', done => {\n      const vm = new Vue({\n        template: `\n          <div>\n            <transition name=\"test-anim-long\" type=\"animation\">\n              <div v-if=\"ok\" class=\"test\">foo</div>\n            </transition>\n          </div>\n        `,\n        data: { ok: true }\n      }).$mount(el)\n\n      // should not apply transition on initial render by default\n      expect(vm.$el.innerHTML).toBe('<div class=\"test\">foo</div>')\n      vm.ok = false\n      waitForUpdate(() => {\n        expect(vm.$el.children[0].className).toBe('test test-anim-long-leave test-anim-long-leave-active')\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.children[0].className).toBe('test test-anim-long-leave-active test-anim-long-leave-to')\n      }).thenWaitFor(duration + 5).then(() => {\n        // should not end early due to transition presence\n        expect(vm.$el.children[0].className).toBe('test test-anim-long-leave-active test-anim-long-leave-to')\n      }).thenWaitFor(duration + 5).then(() => {\n        expect(vm.$el.children.length).toBe(0)\n        vm.ok = true\n      }).then(() => {\n        expect(vm.$el.children[0].className).toBe('test test-anim-long-enter test-anim-long-enter-active')\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.children[0].className).toBe('test test-anim-long-enter-active test-anim-long-enter-to')\n      }).thenWaitFor(duration + 5).then(() => {\n        expect(vm.$el.children[0].className).toBe('test test-anim-long-enter-active test-anim-long-enter-to')\n      }).thenWaitFor(duration + 5).then(() => {\n        expect(vm.$el.children[0].className).toBe('test')\n      }).then(done)\n    })\n\n    it('transition on appear', done => {\n      const vm = new Vue({\n        template: `\n          <div>\n            <transition name=\"test\"\n              appear\n              appear-class=\"test-appear\"\n              appear-to-class=\"test-appear-to\"\n              appear-active-class=\"test-appear-active\">\n              <div v-if=\"ok\" class=\"test\">foo</div>\n            </transition>\n          </div>\n        `,\n        data: { ok: true }\n      }).$mount(el)\n\n      waitForUpdate(() => {\n        expect(vm.$el.children[0].className).toBe('test test-appear test-appear-active')\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.children[0].className).toBe('test test-appear-active test-appear-to')\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.children[0].className).toBe('test')\n      }).then(done)\n    })\n\n    it('transition on appear with v-show', done => {\n      const vm = new Vue({\n        template: `\n          <div>\n            <transition name=\"test\" appear>\n              <div v-show=\"ok\" class=\"test\">foo</div>\n            </transition>\n          </div>\n        `,\n        data: { ok: true }\n      }).$mount(el)\n\n      waitForUpdate(() => {\n        expect(vm.$el.children[0].className).toBe('test test-enter test-enter-active')\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.children[0].className).toBe('test test-enter-active test-enter-to')\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.children[0].className).toBe('test')\n      }).then(done)\n    })\n\n    it('transition on SVG elements', done => {\n      const vm = new Vue({\n        template: `\n          <svg>\n            <transition>\n              <circle cx=\"0\" cy=\"0\" r=\"10\" v-if=\"ok\" class=\"test\"></circle>\n            </transition>\n          </svg>\n        `,\n        data: { ok: true }\n      }).$mount(el)\n\n      // should not apply transition on initial render by default\n      expect(vm.$el.childNodes[0].getAttribute('class')).toBe('test')\n      vm.ok = false\n      waitForUpdate(() => {\n        expect(vm.$el.childNodes[0].getAttribute('class')).toBe('test v-leave v-leave-active')\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.childNodes[0].getAttribute('class')).toBe('test v-leave-active v-leave-to')\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.childNodes.length).toBe(1)\n        expect(vm.$el.childNodes[0].nodeType).toBe(8) // should be an empty comment node\n        expect(vm.$el.childNodes[0].textContent).toBe('')\n        vm.ok = true\n      }).then(() => {\n        expect(vm.$el.childNodes[0].getAttribute('class')).toBe('test v-enter v-enter-active')\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.childNodes[0].getAttribute('class')).toBe('test v-enter-active v-enter-to')\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.childNodes[0].getAttribute('class')).toBe('test')\n      }).then(done)\n    })\n\n    it('transition on child components', done => {\n      const vm = new Vue({\n        template: `\n          <div>\n            <transition>\n              <test v-if=\"ok\" class=\"test\"></test>\n            </transition>\n          </div>\n        `,\n        data: { ok: true },\n        components: {\n          test: {\n            template: `\n              <transition name=\"test\">\n                <div>foo</div>\n              </transition>\n            ` // test transition override from parent\n          }\n        }\n      }).$mount(el)\n\n      // should not apply transition on initial render by default\n      expect(vm.$el.innerHTML).toBe('<div class=\"test\">foo</div>')\n      vm.ok = false\n      waitForUpdate(() => {\n        expect(vm.$el.children[0].className).toBe('test v-leave v-leave-active')\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.children[0].className).toBe('test v-leave-active v-leave-to')\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.children.length).toBe(0)\n        vm.ok = true\n      }).then(() => {\n        expect(vm.$el.children[0].className).toBe('test v-enter v-enter-active')\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.children[0].className).toBe('test v-enter-active v-enter-to')\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.children[0].className).toBe('test')\n      }).then(done)\n    })\n\n    it('transition inside child component', done => {\n      const vm = new Vue({\n        template: `\n          <div>\n            <test v-if=\"ok\" class=\"test\"></test>\n          </div>\n        `,\n        data: { ok: true },\n        components: {\n          test: {\n            template: `\n              <transition>\n                <div>foo</div>\n              </transition>\n            `\n          }\n        }\n      }).$mount(el)\n\n      // should not apply transition on initial render by default\n      expect(vm.$el.innerHTML).toBe('<div class=\"test\">foo</div>')\n      vm.ok = false\n      waitForUpdate(() => {\n        expect(vm.$el.children[0].className).toBe('test v-leave v-leave-active')\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.children[0].className).toBe('test v-leave-active v-leave-to')\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.children.length).toBe(0)\n        vm.ok = true\n      }).then(() => {\n        expect(vm.$el.children[0].className).toBe('test v-enter v-enter-active')\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.children[0].className).toBe('test v-enter-active v-enter-to')\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.children[0].className).toBe('test')\n      }).then(done)\n    })\n\n    it('custom transition higher-order component', done => {\n      const vm = new Vue({\n        template: '<div><my-transition><div v-if=\"ok\" class=\"test\">foo</div></my-transition></div>',\n        data: { ok: true },\n        components: {\n          'my-transition': {\n            functional: true,\n            render (h, { data, children }) {\n              (data.props || (data.props = {})).name = 'test'\n              return h('transition', data, children)\n            }\n          }\n        }\n      }).$mount(el)\n\n      // should not apply transition on initial render by default\n      expect(vm.$el.innerHTML).toBe('<div class=\"test\">foo</div>')\n      vm.ok = false\n      waitForUpdate(() => {\n        expect(vm.$el.children[0].className).toBe('test test-leave test-leave-active')\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.children[0].className).toBe('test test-leave-active test-leave-to')\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.children.length).toBe(0)\n        vm.ok = true\n      }).then(() => {\n        expect(vm.$el.children[0].className).toBe('test test-enter test-enter-active')\n      }).thenWaitFor(nextFrame).then(() => {\n        expect(vm.$el.children[0].className).toBe('test test-enter-active test-enter-to')\n      }).thenWaitFor(duration + buffer).then(() => {\n        expect(vm.$el.children[0].className).toBe('test')\n      }).then(done)\n    })\n\n    it('warn when used on multiple elements', () => {\n      new Vue({\n        template: `<transition><p>1</p><p>2</p></transition>`\n      }).$mount()\n      expect(`<transition> can only be used on a single element`).toHaveBeenWarned()\n    })\n\n    describe('explicit durations -', () => {\n      it('single value', done => {\n        const vm = new Vue({\n          template: `\n            <div>\n              <transition duration=\"${explicitDuration}\">\n                <div v-if=\"ok\" class=\"test\">foo</div>\n              </transition>\n            </div>\n          `,\n          data: { ok: true }\n        }).$mount(el)\n\n        vm.ok = false\n\n        waitForUpdate(() => {\n          expect(vm.$el.children[0].className).toBe('test v-leave v-leave-active')\n        }).thenWaitFor(nextFrame).then(() => {\n          expect(vm.$el.children[0].className).toBe('test v-leave-active v-leave-to')\n        }).thenWaitFor(explicitDuration + buffer).then(() => {\n          expect(vm.$el.children.length).toBe(0)\n          vm.ok = true\n        }).then(() => {\n          expect(vm.$el.children[0].className).toBe('test v-enter v-enter-active')\n        }).thenWaitFor(nextFrame).then(() => {\n          expect(vm.$el.children[0].className).toBe('test v-enter-active v-enter-to')\n        }).thenWaitFor(explicitDuration + buffer).then(() => {\n          expect(vm.$el.children[0].className).toBe('test')\n        }).then(done)\n      })\n\n      it('enter and auto leave', done => {\n        const vm = new Vue({\n          template: `\n            <div>\n              <transition :duration=\"{ enter: ${explicitDuration} }\">\n                <div v-if=\"ok\" class=\"test\">foo</div>\n              </transition>\n            </div>\n          `,\n          data: { ok: true }\n        }).$mount(el)\n\n        vm.ok = false\n\n        waitForUpdate(() => {\n          expect(vm.$el.children[0].className).toBe('test v-leave v-leave-active')\n        }).thenWaitFor(nextFrame).then(() => {\n          expect(vm.$el.children[0].className).toBe('test v-leave-active v-leave-to')\n        }).thenWaitFor(duration + buffer).then(() => {\n          expect(vm.$el.children.length).toBe(0)\n          vm.ok = true\n        }).then(() => {\n          expect(vm.$el.children[0].className).toBe('test v-enter v-enter-active')\n        }).thenWaitFor(nextFrame).then(() => {\n          expect(vm.$el.children[0].className).toBe('test v-enter-active v-enter-to')\n        }).thenWaitFor(explicitDuration + buffer).then(() => {\n          expect(vm.$el.children[0].className).toBe('test')\n        }).then(done)\n      })\n\n      it('leave and auto enter', done => {\n        const vm = new Vue({\n          template: `\n            <div>\n              <transition :duration=\"{ leave: ${explicitDuration} }\">\n                <div v-if=\"ok\" class=\"test\">foo</div>\n              </transition>\n            </div>\n          `,\n          data: { ok: true }\n        }).$mount(el)\n\n        vm.ok = false\n\n        waitForUpdate(() => {\n          expect(vm.$el.children[0].className).toBe('test v-leave v-leave-active')\n        }).thenWaitFor(nextFrame).then(() => {\n          expect(vm.$el.children[0].className).toBe('test v-leave-active v-leave-to')\n        }).thenWaitFor(explicitDuration + buffer).then(() => {\n          expect(vm.$el.children.length).toBe(0)\n          vm.ok = true\n        }).then(() => {\n          expect(vm.$el.children[0].className).toBe('test v-enter v-enter-active')\n        }).thenWaitFor(nextFrame).then(() => {\n          expect(vm.$el.children[0].className).toBe('test v-enter-active v-enter-to')\n        }).thenWaitFor(duration + buffer).then(() => {\n          expect(vm.$el.children[0].className).toBe('test')\n        }).then(done)\n      })\n\n      it('separate enter and leave', done => {\n        const enter = explicitDuration\n        const leave = explicitDuration * 2\n\n        const vm = new Vue({\n          template: `\n            <div>\n              <transition :duration=\"{ enter: ${enter}, leave: ${leave} }\">\n                <div v-if=\"ok\" class=\"test\">foo</div>\n              </transition>\n            </div>\n          `,\n          data: { ok: true }\n        }).$mount(el)\n\n        vm.ok = false\n\n        waitForUpdate(() => {\n          expect(vm.$el.children[0].className).toBe('test v-leave v-leave-active')\n        }).thenWaitFor(nextFrame).then(() => {\n          expect(vm.$el.children[0].className).toBe('test v-leave-active v-leave-to')\n        }).thenWaitFor(leave + buffer).then(() => {\n          expect(vm.$el.children.length).toBe(0)\n          vm.ok = true\n        }).then(() => {\n          expect(vm.$el.children[0].className).toBe('test v-enter v-enter-active')\n        }).thenWaitFor(nextFrame).then(() => {\n          expect(vm.$el.children[0].className).toBe('test v-enter-active v-enter-to')\n        }).thenWaitFor(enter + buffer).then(() => {\n          expect(vm.$el.children[0].className).toBe('test')\n        }).then(done)\n      })\n\n      it('enter and leave + duration change', done => {\n        const enter1 = explicitDuration * 2\n        const enter2 = explicitDuration\n        const leave1 = explicitDuration * 0.5\n        const leave2 = explicitDuration * 3\n\n        const vm = new Vue({\n          template: `\n            <div>\n              <transition :duration=\"{ enter: enter, leave: leave }\">\n                <div v-if=\"ok\" class=\"test\">foo</div>\n              </transition>\n            </div>\n          `,\n          data: {\n            ok: true,\n            enter: enter1,\n            leave: leave1\n          }\n        }).$mount(el)\n\n        vm.ok = false\n\n        waitForUpdate(() => {\n          expect(vm.$el.children[0].className).toBe('test v-leave v-leave-active')\n        }).thenWaitFor(nextFrame).then(() => {\n          expect(vm.$el.children[0].className).toBe('test v-leave-active v-leave-to')\n        }).thenWaitFor(leave1 + buffer).then(() => {\n          expect(vm.$el.children.length).toBe(0)\n          vm.ok = true\n        }).then(() => {\n          expect(vm.$el.children[0].className).toBe('test v-enter v-enter-active')\n        }).thenWaitFor(nextFrame).then(() => {\n          expect(vm.$el.children[0].className).toBe('test v-enter-active v-enter-to')\n        }).thenWaitFor(enter1 + buffer).then(() => {\n          expect(vm.$el.children[0].className).toBe('test')\n          vm.enter = enter2\n          vm.leave = leave2\n        }).then(() => {\n          vm.ok = false\n        }).then(() => {\n          expect(vm.$el.children[0].className).toBe('test v-leave v-leave-active')\n        }).thenWaitFor(nextFrame).then(() => {\n          expect(vm.$el.children[0].className).toBe('test v-leave-active v-leave-to')\n        }).thenWaitFor(leave2 + buffer).then(() => {\n          expect(vm.$el.children.length).toBe(0)\n          vm.ok = true\n        }).then(() => {\n          expect(vm.$el.children[0].className).toBe('test v-enter v-enter-active')\n        }).thenWaitFor(nextFrame).then(() => {\n          expect(vm.$el.children[0].className).toBe('test v-enter-active v-enter-to')\n        }).thenWaitFor(enter2 + buffer).then(() => {\n          expect(vm.$el.children[0].className).toBe('test')\n        }).then(done)\n      }, 10000)\n\n      it('warn invalid durations', done => {\n        const vm = new Vue({\n          template: `\n            <div>\n              <transition :duration=\"{ enter: NaN, leave: 'foo' }\">\n                <div v-if=\"ok\" class=\"test\">foo</div>\n              </transition>\n            </div>\n          `,\n          data: {\n            ok: true\n          }\n        }).$mount(el)\n\n        vm.ok = false\n        waitForUpdate(() => {\n          expect(`<transition> explicit leave duration is not a valid number - got \"foo\"`).toHaveBeenWarned()\n        }).thenWaitFor(duration + buffer).then(() => {\n          vm.ok = true\n        }).then(() => {\n          expect(`<transition> explicit enter duration is NaN`).toHaveBeenWarned()\n        }).then(done)\n      })\n    })\n  })\n}\n"
  },
  {
    "path": "test/unit/index.js",
    "content": "require('es6-promise/auto')\n\n// import all helpers\nconst helpersContext = require.context('../helpers', true)\nhelpersContext.keys().forEach(helpersContext)\n\n// require all test files\nconst testsContext = require.context('./', true, /\\.spec$/)\ntestsContext.keys().forEach(testsContext)\n"
  },
  {
    "path": "test/unit/karma.base.config.js",
    "content": "var alias = require('../../build/alias')\nvar webpack = require('webpack')\n\nvar webpackConfig = {\n  resolve: {\n    alias: alias\n  },\n  module: {\n    rules: [\n      {\n        test: /\\.js$/,\n        loader: 'babel-loader',\n        exclude: /node_modules/\n      }\n    ]\n  },\n  plugins: [\n    new webpack.DefinePlugin({\n      __WEEX__: false,\n      'process.env': {\n        NODE_ENV: '\"development\"',\n        TRANSITION_DURATION: 50,\n        TRANSITION_BUFFER: 10\n      }\n    })\n  ],\n  devtool: '#inline-source-map'\n}\n\n// shared config for all unit tests\nmodule.exports = {\n  frameworks: ['jasmine'],\n  files: [\n    './index.js'\n  ],\n  preprocessors: {\n    './index.js': ['webpack', 'sourcemap']\n  },\n  webpack: webpackConfig,\n  webpackMiddleware: {\n    noInfo: true\n  },\n  plugins: [\n    'karma-jasmine',\n    'karma-mocha-reporter',\n    'karma-sourcemap-loader',\n    'karma-webpack'\n  ]\n}\n"
  },
  {
    "path": "test/unit/karma.cover.config.js",
    "content": "var base = require('./karma.base.config.js')\n\nmodule.exports = function (config) {\n  var options = Object.assign(base, {\n    browsers: ['PhantomJS'],\n    reporters: ['mocha', 'coverage'],\n    coverageReporter: {\n      reporters: [\n        { type: 'lcov', dir: '../../coverage', subdir: '.' },\n        { type: 'text-summary', dir: '../../coverage', subdir: '.' }\n      ]\n    },\n    singleRun: true,\n    plugins: base.plugins.concat([\n      'karma-coverage',\n      'karma-phantomjs-launcher'\n    ])\n  })\n\n  // add babel-plugin-istanbul for code intrumentation\n  options.webpack.module.rules[0].options = {\n    plugins: [['istanbul', {\n      exclude: [\n        'test/',\n        'src/compiler/parser/html-parser.js',\n        'src/core/instance/proxy.js',\n        'src/sfc/deindent.js'\n      ]\n    }]]\n  }\n\n  config.set(options)\n}\n"
  },
  {
    "path": "test/unit/karma.dev.config.js",
    "content": "var base = require('./karma.base.config.js')\n\nmodule.exports = function (config) {\n  config.set(Object.assign(base, {\n    browsers: ['Chrome'],\n    reporters: ['progress'],\n    plugins: base.plugins.concat([\n      'karma-chrome-launcher'\n    ])\n  }))\n}\n"
  },
  {
    "path": "test/unit/karma.sauce.config.js",
    "content": "var webpack = require('webpack')\nvar base = require('./karma.base.config.js')\n\nbase.webpack.plugins = [\n  new webpack.DefinePlugin({\n    __WEEX__: false,\n    'process.env': {\n      NODE_ENV: '\"development\"',\n      // sauce lab vms are slow!\n      TRANSITION_DURATION: 500,\n      TRANSITION_BUFFER: 50\n    }\n  })\n]\n\n/**\n * Having too many tests running concurrently on saucelabs\n * causes timeouts and errors, so we have to run them in\n * smaller batches.\n */\n\nvar batches = [\n  // the cool kids\n  {\n    sl_chrome: {\n      base: 'SauceLabs',\n      browserName: 'chrome',\n      platform: 'Windows 7'\n    },\n    sl_firefox: {\n      base: 'SauceLabs',\n      browserName: 'firefox'\n    },\n    sl_mac_safari: {\n      base: 'SauceLabs',\n      browserName: 'safari',\n      platform: 'OS X 10.10'\n    }\n  },\n  // ie family\n  {\n    sl_ie_9: {\n      base: 'SauceLabs',\n      browserName: 'internet explorer',\n      platform: 'Windows 7',\n      version: '9'\n    },\n    sl_ie_10: {\n      base: 'SauceLabs',\n      browserName: 'internet explorer',\n      platform: 'Windows 8',\n      version: '10'\n    },\n    sl_ie_11: {\n      base: 'SauceLabs',\n      browserName: 'internet explorer',\n      platform: 'Windows 8.1',\n      version: '11'\n    },\n    sl_edge: {\n      base: 'SauceLabs',\n      browserName: 'MicrosoftEdge',\n      platform: 'Windows 10'\n    }\n  },\n  // mobile\n  {\n    sl_ios_safari_9: {\n      base: 'SauceLabs',\n      browserName: 'iphone',\n      version: '10.3'\n    },\n    sl_android_6_0: {\n      base: 'SauceLabs',\n      browserName: 'android',\n      version: '6.0'\n    }\n  }\n]\n\nmodule.exports = function (config) {\n  var batch = batches[process.argv[4] || 0]\n\n  config.set(Object.assign(base, {\n    singleRun: true,\n    browsers: Object.keys(batch),\n    customLaunchers: batch,\n    reporters: process.env.CI\n      ? ['dots', 'saucelabs'] // avoid spamming CI output\n      : ['progress', 'saucelabs'],\n    sauceLabs: {\n      testName: 'Vue.js unit tests',\n      recordScreenshots: false,\n      connectOptions: {\n        'no-ssl-bump-domains': 'all' // Ignore SSL error on Android emulator\n      },\n      build: process.env.CIRCLE_BUILD_NUM || process.env.SAUCE_BUILD_ID || Date.now()\n    },\n    // mobile emulators are really slow\n    captureTimeout: 300000,\n    browserNoActivityTimeout: 300000,\n    plugins: base.plugins.concat([\n      'karma-sauce-launcher'\n    ])\n  }))\n}\n"
  },
  {
    "path": "test/unit/karma.unit.config.js",
    "content": "var base = require('./karma.base.config.js')\n\nmodule.exports = function (config) {\n  config.set(Object.assign(base, {\n    browsers: ['Chrome', 'Firefox', 'Safari'],\n    reporters: ['progress'],\n    singleRun: true,\n    plugins: base.plugins.concat([\n      'karma-chrome-launcher',\n      'karma-firefox-launcher',\n      'karma-safari-launcher'\n    ])\n  }))\n}\n"
  },
  {
    "path": "test/unit/modules/compiler/codegen.spec.js",
    "content": "import { parse } from 'compiler/parser/index'\nimport { optimize } from 'compiler/optimizer'\nimport { generate } from 'compiler/codegen'\nimport { isObject, extend } from 'shared/util'\nimport { isReservedTag } from 'web/util/index'\nimport { baseOptions } from 'web/compiler/options'\n\nfunction assertCodegen (template, generatedCode, ...args) {\n  let staticRenderFnCodes = []\n  let generateOptions = baseOptions\n  let proc = null\n  let len = args.length\n  while (len--) {\n    const arg = args[len]\n    if (Array.isArray(arg)) {\n      staticRenderFnCodes = arg\n    } else if (isObject(arg)) {\n      generateOptions = arg\n    } else if (typeof arg === 'function') {\n      proc = arg\n    }\n  }\n  const ast = parse(template, baseOptions)\n  optimize(ast, baseOptions)\n  proc && proc(ast)\n  const res = generate(ast, generateOptions)\n  expect(res.render).toBe(generatedCode)\n  expect(res.staticRenderFns).toEqual(staticRenderFnCodes)\n}\n\n/* eslint-disable quotes */\ndescribe('codegen', () => {\n  it('generate directive', () => {\n    assertCodegen(\n      '<p v-custom1:arg1.modifier=\"value1\" v-custom2></p>',\n      `with(this){return _c('p',{directives:[{name:\"custom1\",rawName:\"v-custom1:arg1.modifier\",value:(value1),expression:\"value1\",arg:\"arg1\",modifiers:{\"modifier\":true}},{name:\"custom2\",rawName:\"v-custom2\"}]})}`\n    )\n  })\n\n  it('generate filters', () => {\n    assertCodegen(\n      '<div :id=\"a | b | c\">{{ d | e | f }}</div>',\n      `with(this){return _c('div',{attrs:{\"id\":_f(\"c\")(_f(\"b\")(a))}},[_v(_s(_f(\"f\")(_f(\"e\")(d))))])}`\n    )\n  })\n\n  it('generate v-for directive', () => {\n    assertCodegen(\n      '<div><li v-for=\"item in items\" :key=\"item.uid\"></li></div>',\n      `with(this){return _c('div',_l((items),function(item){return _c('li',{key:item.uid})}))}`\n    )\n    // iterator syntax\n    assertCodegen(\n      '<div><li v-for=\"(item, i) in items\"></li></div>',\n      `with(this){return _c('div',_l((items),function(item,i){return _c('li')}))}`\n    )\n    assertCodegen(\n      '<div><li v-for=\"(item, key, index) in items\"></li></div>',\n      `with(this){return _c('div',_l((items),function(item,key,index){return _c('li')}))}`\n    )\n    // destructuring\n    assertCodegen(\n      '<div><li v-for=\"{ a, b } in items\"></li></div>',\n      `with(this){return _c('div',_l((items),function({ a, b }){return _c('li')}))}`\n    )\n    assertCodegen(\n      '<div><li v-for=\"({ a, b }, key, index) in items\"></li></div>',\n      `with(this){return _c('div',_l((items),function({ a, b },key,index){return _c('li')}))}`\n    )\n    // v-for with extra element\n    assertCodegen(\n      '<div><p></p><li v-for=\"item in items\"></li></div>',\n      `with(this){return _c('div',[_c('p'),_l((items),function(item){return _c('li')})],2)}`\n    )\n  })\n\n  it('generate v-if directive', () => {\n    assertCodegen(\n      '<p v-if=\"show\">hello</p>',\n      `with(this){return (show)?_c('p',[_v(\"hello\")]):_e()}`\n    )\n  })\n\n  it('generate v-else directive', () => {\n    assertCodegen(\n      '<div><p v-if=\"show\">hello</p><p v-else>world</p></div>',\n      `with(this){return _c('div',[(show)?_c('p',[_v(\"hello\")]):_c('p',[_v(\"world\")])])}`\n    )\n  })\n\n  it('generate v-else-if directive', () => {\n    assertCodegen(\n      '<div><p v-if=\"show\">hello</p><p v-else-if=\"hide\">world</p></div>',\n      `with(this){return _c('div',[(show)?_c('p',[_v(\"hello\")]):(hide)?_c('p',[_v(\"world\")]):_e()])}`\n    )\n  })\n\n  it('generate v-else-if with v-else directive', () => {\n    assertCodegen(\n      '<div><p v-if=\"show\">hello</p><p v-else-if=\"hide\">world</p><p v-else>bye</p></div>',\n      `with(this){return _c('div',[(show)?_c('p',[_v(\"hello\")]):(hide)?_c('p',[_v(\"world\")]):_c('p',[_v(\"bye\")])])}`\n    )\n  })\n\n  it('generate multi v-else-if with v-else directive', () => {\n    assertCodegen(\n        '<div><p v-if=\"show\">hello</p><p v-else-if=\"hide\">world</p><p v-else-if=\"3\">elseif</p><p v-else>bye</p></div>',\n        `with(this){return _c('div',[(show)?_c('p',[_v(\"hello\")]):(hide)?_c('p',[_v(\"world\")]):(3)?_c('p',[_v(\"elseif\")]):_c('p',[_v(\"bye\")])])}`\n    )\n  })\n\n  it('generate ref', () => {\n    assertCodegen(\n      '<p ref=\"component1\"></p>',\n      `with(this){return _c('p',{ref:\"component1\"})}`\n    )\n  })\n\n  it('generate ref on v-for', () => {\n    assertCodegen(\n      '<ul><li v-for=\"item in items\" ref=\"component1\"></li></ul>',\n      `with(this){return _c('ul',_l((items),function(item){return _c('li',{ref:\"component1\",refInFor:true})}))}`\n    )\n  })\n\n  it('generate v-bind directive', () => {\n    assertCodegen(\n      '<p v-bind=\"test\"></p>',\n      `with(this){return _c('p',_b({},'p',test,false))}`\n    )\n  })\n\n  it('generate v-bind with prop directive', () => {\n    assertCodegen(\n      '<p v-bind.prop=\"test\"></p>',\n      `with(this){return _c('p',_b({},'p',test,true))}`\n    )\n  })\n\n  it('generate v-bind directive with sync modifier', () => {\n    assertCodegen(\n      '<p v-bind.sync=\"test\"></p>',\n      `with(this){return _c('p',_b({},'p',test,false,true))}`\n    )\n  })\n\n  it('generate template tag', () => {\n    assertCodegen(\n      '<div><template><p>{{hello}}</p></template></div>',\n      `with(this){return _c('div',[[_c('p',[_v(_s(hello))])]],2)}`\n    )\n  })\n\n  it('generate single slot', () => {\n    assertCodegen(\n      '<div><slot></slot></div>',\n      `with(this){return _c('div',[_t(\"default\")],2)}`\n    )\n  })\n\n  it('generate named slot', () => {\n    assertCodegen(\n      '<div><slot name=\"one\"></slot></div>',\n      `with(this){return _c('div',[_t(\"one\")],2)}`\n    )\n  })\n\n  it('generate slot fallback content', () => {\n    assertCodegen(\n      '<div><slot><div>hi</div></slot></div>',\n      `with(this){return _c('div',[_t(\"default\",[_c('div',[_v(\"hi\")])])],2)}`\n    )\n  })\n\n  it('generate slot target', () => {\n    assertCodegen(\n      '<p slot=\"one\">hello world</p>',\n      `with(this){return _c('p',{slot:\"one\"},[_v(\"hello world\")])}`\n    )\n  })\n\n  it('generate class binding', () => {\n    // static\n    assertCodegen(\n      '<p class=\"class1\">hello world</p>',\n      `with(this){return _c('p',{staticClass:\"class1\"},[_v(\"hello world\")])}`,\n    )\n    // dynamic\n    assertCodegen(\n      '<p :class=\"class1\">hello world</p>',\n      `with(this){return _c('p',{class:class1},[_v(\"hello world\")])}`\n    )\n  })\n\n  it('generate style binding', () => {\n    assertCodegen(\n      '<p :style=\"error\">hello world</p>',\n      `with(this){return _c('p',{style:(error)},[_v(\"hello world\")])}`\n    )\n  })\n\n  it('generate v-show directive', () => {\n    assertCodegen(\n      '<p v-show=\"shown\">hello world</p>',\n      `with(this){return _c('p',{directives:[{name:\"show\",rawName:\"v-show\",value:(shown),expression:\"shown\"}]},[_v(\"hello world\")])}`\n    )\n  })\n\n  it('generate DOM props with v-bind directive', () => {\n    // input + value\n    assertCodegen(\n      '<input :value=\"msg\">',\n      `with(this){return _c('input',{domProps:{\"value\":msg}})}`\n    )\n    // non input\n    assertCodegen(\n      '<p :value=\"msg\"/>',\n      `with(this){return _c('p',{attrs:{\"value\":msg}})}`\n    )\n  })\n\n  it('generate attrs with v-bind directive', () => {\n    assertCodegen(\n      '<input :name=\"field1\">',\n      `with(this){return _c('input',{attrs:{\"name\":field1}})}`\n    )\n  })\n\n  it('generate static attrs', () => {\n    assertCodegen(\n      '<input name=\"field1\">',\n      `with(this){return _c('input',{attrs:{\"name\":\"field1\"}})}`\n    )\n  })\n\n  it('generate events with v-on directive', () => {\n    assertCodegen(\n      '<input @input=\"onInput\">',\n      `with(this){return _c('input',{on:{\"input\":onInput}})}`\n    )\n  })\n\n  it('generate events with keycode', () => {\n    assertCodegen(\n      '<input @input.enter=\"onInput\">',\n      `with(this){return _c('input',{on:{\"input\":function($event){if(!('button' in $event)&&_k($event.keyCode,\"enter\",13))return null;onInput($event)}}})}`\n    )\n    // multiple keycodes (delete)\n    assertCodegen(\n      '<input @input.delete=\"onInput\">',\n      `with(this){return _c('input',{on:{\"input\":function($event){if(!('button' in $event)&&_k($event.keyCode,\"delete\",[8,46]))return null;onInput($event)}}})}`\n    )\n    // multiple keycodes (chained)\n    assertCodegen(\n      '<input @keydown.enter.delete=\"onInput\">',\n      `with(this){return _c('input',{on:{\"keydown\":function($event){if(!('button' in $event)&&_k($event.keyCode,\"enter\",13)&&_k($event.keyCode,\"delete\",[8,46]))return null;onInput($event)}}})}`\n    )\n    // number keycode\n    assertCodegen(\n      '<input @input.13=\"onInput\">',\n      `with(this){return _c('input',{on:{\"input\":function($event){if(!('button' in $event)&&$event.keyCode!==13)return null;onInput($event)}}})}`\n    )\n    // custom keycode\n    assertCodegen(\n      '<input @input.custom=\"onInput\">',\n      `with(this){return _c('input',{on:{\"input\":function($event){if(!('button' in $event)&&_k($event.keyCode,\"custom\"))return null;onInput($event)}}})}`\n    )\n  })\n\n  it('generate events with generic modifiers', () => {\n    assertCodegen(\n      '<input @input.stop=\"onInput\">',\n      `with(this){return _c('input',{on:{\"input\":function($event){$event.stopPropagation();onInput($event)}}})}`\n    )\n    assertCodegen(\n      '<input @input.prevent=\"onInput\">',\n      `with(this){return _c('input',{on:{\"input\":function($event){$event.preventDefault();onInput($event)}}})}`\n    )\n    assertCodegen(\n      '<input @input.self=\"onInput\">',\n      `with(this){return _c('input',{on:{\"input\":function($event){if($event.target !== $event.currentTarget)return null;onInput($event)}}})}`\n    )\n  })\n\n  // Github Issues #5146\n  it('generate events with generic modifiers and keycode correct order', () => {\n    assertCodegen(\n      '<input @keydown.enter.prevent=\"onInput\">',\n      `with(this){return _c('input',{on:{\"keydown\":function($event){if(!('button' in $event)&&_k($event.keyCode,\"enter\",13))return null;$event.preventDefault();onInput($event)}}})}`\n    )\n\n    assertCodegen(\n      '<input @keydown.enter.stop=\"onInput\">',\n      `with(this){return _c('input',{on:{\"keydown\":function($event){if(!('button' in $event)&&_k($event.keyCode,\"enter\",13))return null;$event.stopPropagation();onInput($event)}}})}`\n    )\n  })\n\n  it('generate events with mouse event modifiers', () => {\n    assertCodegen(\n      '<input @click.ctrl=\"onClick\">',\n      `with(this){return _c('input',{on:{\"click\":function($event){if(!$event.ctrlKey)return null;onClick($event)}}})}`\n    )\n    assertCodegen(\n      '<input @click.shift=\"onClick\">',\n      `with(this){return _c('input',{on:{\"click\":function($event){if(!$event.shiftKey)return null;onClick($event)}}})}`\n    )\n    assertCodegen(\n      '<input @click.alt=\"onClick\">',\n      `with(this){return _c('input',{on:{\"click\":function($event){if(!$event.altKey)return null;onClick($event)}}})}`\n    )\n    assertCodegen(\n      '<input @click.meta=\"onClick\">',\n      `with(this){return _c('input',{on:{\"click\":function($event){if(!$event.metaKey)return null;onClick($event)}}})}`\n    )\n  })\n\n  it('generate events with multiple modifiers', () => {\n    assertCodegen(\n      '<input @input.stop.prevent.self=\"onInput\">',\n      `with(this){return _c('input',{on:{\"input\":function($event){$event.stopPropagation();$event.preventDefault();if($event.target !== $event.currentTarget)return null;onInput($event)}}})}`\n    )\n  })\n\n  it('generate events with capture modifier', () => {\n    assertCodegen(\n      '<input @input.capture=\"onInput\">',\n      `with(this){return _c('input',{on:{\"!input\":function($event){onInput($event)}}})}`\n    )\n  })\n\n  it('generate events with once modifier', () => {\n    assertCodegen(\n      '<input @input.once=\"onInput\">',\n      `with(this){return _c('input',{on:{\"~input\":function($event){onInput($event)}}})}`\n    )\n  })\n\n  it('generate events with capture and once modifier', () => {\n    assertCodegen(\n      '<input @input.capture.once=\"onInput\">',\n      `with(this){return _c('input',{on:{\"~!input\":function($event){onInput($event)}}})}`\n    )\n  })\n\n  it('generate events with once and capture modifier', () => {\n    assertCodegen(\n      '<input @input.once.capture=\"onInput\">',\n      `with(this){return _c('input',{on:{\"~!input\":function($event){onInput($event)}}})}`\n    )\n  })\n\n  it('generate events with inline statement', () => {\n    assertCodegen(\n      '<input @input=\"current++\">',\n      `with(this){return _c('input',{on:{\"input\":function($event){current++}}})}`\n    )\n  })\n\n  it('generate events with inline function expression', () => {\n    // normal function\n    assertCodegen(\n      '<input @input=\"function () { current++ }\">',\n      `with(this){return _c('input',{on:{\"input\":function () { current++ }}})}`\n    )\n    // arrow with no args\n    assertCodegen(\n      '<input @input=\"()=>current++\">',\n      `with(this){return _c('input',{on:{\"input\":()=>current++}})}`\n    )\n    // arrow with parens, single arg\n    assertCodegen(\n      '<input @input=\"(e) => current++\">',\n      `with(this){return _c('input',{on:{\"input\":(e) => current++}})}`\n    )\n    // arrow with parens, multi args\n    assertCodegen(\n      '<input @input=\"(a, b, c) => current++\">',\n      `with(this){return _c('input',{on:{\"input\":(a, b, c) => current++}})}`\n    )\n    // arrow with destructuring\n    assertCodegen(\n      '<input @input=\"({ a, b }) => current++\">',\n      `with(this){return _c('input',{on:{\"input\":({ a, b }) => current++}})}`\n    )\n    // arrow single arg no parens\n    assertCodegen(\n      '<input @input=\"e=>current++\">',\n      `with(this){return _c('input',{on:{\"input\":e=>current++}})}`\n    )\n    // with modifiers\n    assertCodegen(\n      `<input @keyup.enter=\"e=>current++\">`,\n      `with(this){return _c('input',{on:{\"keyup\":function($event){if(!('button' in $event)&&_k($event.keyCode,\"enter\",13))return null;(e=>current++)($event)}}})}`\n    )\n  })\n\n  // #3893\n  it('should not treat handler with unexpected whitespace as inline statement', () => {\n    assertCodegen(\n      '<input @input=\" onInput \">',\n      `with(this){return _c('input',{on:{\"input\": onInput }})}`\n    )\n  })\n\n  it('generate unhandled events', () => {\n    assertCodegen(\n      '<input @input=\"current++\">',\n      `with(this){return _c('input',{on:{\"input\":function(){}}})}`,\n      ast => {\n        ast.events.input = undefined\n      }\n    )\n  })\n\n  it('generate multiple event handlers', () => {\n    assertCodegen(\n      '<input @input=\"current++\" @input.stop=\"onInput\">',\n      `with(this){return _c('input',{on:{\"input\":[function($event){current++},function($event){$event.stopPropagation();onInput($event)}]}})}`\n    )\n  })\n\n  it('generate component', () => {\n    assertCodegen(\n      '<my-component name=\"mycomponent1\" :msg=\"msg\" @notify=\"onNotify\"><div>hi</div></my-component>',\n      `with(this){return _c('my-component',{attrs:{\"name\":\"mycomponent1\",\"msg\":msg},on:{\"notify\":onNotify}},[_c('div',[_v(\"hi\")])])}`\n    )\n  })\n\n  it('generate svg component with children', () => {\n    assertCodegen(\n      '<svg><my-comp><circle :r=\"10\"></circle></my-comp></svg>',\n      `with(this){return _c('svg',[_c('my-comp',[_c('circle',{attrs:{\"r\":10}})])],1)}`\n    )\n  })\n\n  it('generate is attribute', () => {\n    assertCodegen(\n      '<div is=\"component1\"></div>',\n      `with(this){return _c(\"component1\",{tag:\"div\"})}`\n    )\n    assertCodegen(\n      '<div :is=\"component1\"></div>',\n      `with(this){return _c(component1,{tag:\"div\"})}`\n    )\n  })\n\n  it('generate component with inline-template', () => {\n    // have \"inline-template'\"\n    assertCodegen(\n      '<my-component inline-template><p><span>hello world</span></p></my-component>',\n      `with(this){return _c('my-component',{inlineTemplate:{render:function(){with(this){return _m(0)}},staticRenderFns:[function(){with(this){return _c('p',[_c('span',[_v(\"hello world\")])])}}]}})}`\n    )\n    // \"have inline-template attrs, but not having exactly one child element\n    assertCodegen(\n      '<my-component inline-template><hr><hr></my-component>',\n      `with(this){return _c('my-component',{inlineTemplate:{render:function(){with(this){return _c('hr')}},staticRenderFns:[]}})}`\n    )\n    expect('Inline-template components must have exactly one child element.').toHaveBeenWarned()\n  })\n\n  it('generate static trees inside v-for', () => {\n    assertCodegen(\n      `<div><div v-for=\"i in 10\"><p><span></span></p></div></div>`,\n      `with(this){return _c('div',_l((10),function(i){return _c('div',[_m(0,true)])}))}`,\n      [`with(this){return _c('p',[_c('span')])}`]\n    )\n  })\n\n  it('generate component with v-for', () => {\n    // normalize type: 2\n    assertCodegen(\n      '<div><child></child><template v-for=\"item in list\">{{ item }}</template></div>',\n      `with(this){return _c('div',[_c('child'),_l((list),function(item){return [_v(_s(item))]})],2)}`\n    )\n  })\n\n  it('generate component with comment', () => {\n    const options = extend({\n      comments: true\n    }, baseOptions)\n    const template = '<div><!--comment--></div>'\n    const generatedCode = `with(this){return _c('div',[_e('comment')])}`\n\n    const ast = parse(template, options)\n    optimize(ast, options)\n    const res = generate(ast, options)\n    expect(res.render).toBe(generatedCode)\n  })\n\n  it('not specified ast type', () => {\n    const res = generate(null, baseOptions)\n    expect(res.render).toBe(`with(this){return _c(\"div\")}`)\n    expect(res.staticRenderFns).toEqual([])\n  })\n\n  it('not specified directives option', () => {\n    assertCodegen(\n      '<p v-if=\"show\">hello world</p>',\n      `with(this){return (show)?_c('p',[_v(\"hello world\")]):_e()}`,\n      { isReservedTag }\n    )\n  })\n})\n/* eslint-enable quotes */\n"
  },
  {
    "path": "test/unit/modules/compiler/compiler-options.spec.js",
    "content": "import Vue from 'vue'\nimport { compile } from 'web/compiler'\nimport { getAndRemoveAttr } from 'compiler/helpers'\n\ndescribe('compile options', () => {\n  it('should be compiled', () => {\n    const { render, staticRenderFns, errors } = compile(`\n      <div>\n        <input type=\"text\" v-model=\"msg\" required max=\"8\" v-validate:field1.group1.group2>\n      </div>\n    `, {\n      directives: {\n        validate (el, dir) {\n          if (dir.name === 'validate' && dir.arg) {\n            el.validate = {\n              field: dir.arg,\n              groups: dir.modifiers ? Object.keys(dir.modifiers) : []\n            }\n          }\n        }\n      },\n      modules: [{\n        transformNode (el) {\n          el.validators = el.validators || []\n          const validators = ['required', 'min', 'max', 'pattern', 'maxlength', 'minlength']\n          validators.forEach(name => {\n            const rule = getAndRemoveAttr(el, name)\n            if (rule !== undefined) {\n              el.validators.push({ name, rule })\n            }\n          })\n        },\n        genData (el) {\n          let data = ''\n          if (el.validate) {\n            data += `validate:${JSON.stringify(el.validate)},`\n          }\n          if (el.validators) {\n            data += `validators:${JSON.stringify(el.validators)},`\n          }\n          return data\n        },\n        transformCode (el, code) {\n          // check\n          if (!el.validate || !el.validators) {\n            return code\n          }\n          // setup validation result props\n          const result = { dirty: false } // define something other prop\n          el.validators.forEach(validator => {\n            result[validator.name] = null\n          })\n          // generate code\n          return `_c('validate',{props:{\n            field:${JSON.stringify(el.validate.field)},\n            groups:${JSON.stringify(el.validate.groups)},\n            validators:${JSON.stringify(el.validators)},\n            result:${JSON.stringify(result)},\n            child:${code}}\n          })`\n        }\n      }]\n    })\n    expect(render).not.toBeUndefined()\n    expect(staticRenderFns).toEqual([])\n    expect(errors).toEqual([])\n\n    const renderFn = new Function(render)\n    const vm = new Vue({\n      data: {\n        msg: 'hello'\n      },\n      components: {\n        validate: {\n          props: ['field', 'groups', 'validators', 'result', 'child'],\n          render (h) {\n            return this.child\n          },\n          computed: {\n            valid () {\n              let ret = true\n              for (let i = 0; i > this.validators.length; i++) {\n                const { name } = this.validators[i]\n                if (!this.result[name]) {\n                  ret = false\n                  break\n                }\n              }\n              return ret\n            }\n          },\n          mounted () {\n            // initialize validation\n            const value = this.$el.value\n            this.validators.forEach(validator => {\n              const ret = this[validator.name](value, validator.rule)\n              this.result[validator.name] = ret\n            })\n          },\n          methods: {\n            // something validators logic\n            required (val) {\n              return val.length > 0\n            },\n            max (val, rule) {\n              return !(parseInt(val, 10) > parseInt(rule, 10))\n            }\n          }\n        }\n      },\n      render: renderFn,\n      staticRenderFns\n    }).$mount()\n    expect(vm.$el.innerHTML).toBe('<input type=\"text\">')\n    expect(vm.$children[0].valid).toBe(true)\n  })\n\n  it('should collect errors', () => {\n    let compiled = compile('hello')\n    expect(compiled.errors.length).toBe(1)\n    expect(compiled.errors[0]).toContain('root element')\n\n    compiled = compile('<div v-if=\"a----\">{{ b++++ }}</div>')\n    expect(compiled.errors.length).toBe(2)\n    expect(compiled.errors[0]).toContain('invalid expression: v-if=\"a----\"')\n    expect(compiled.errors[1]).toContain('invalid expression: {{ b++++ }}')\n  })\n})\n"
  },
  {
    "path": "test/unit/modules/compiler/optimizer.spec.js",
    "content": "import { parse } from 'compiler/parser/index'\nimport { extend } from 'shared/util'\nimport { optimize } from 'compiler/optimizer'\nimport { baseOptions } from 'web/compiler/options'\n\ndescribe('optimizer', () => {\n  it('simple', () => {\n    const ast = parse('<h1 id=\"section1\"><span>hello world</span></h1>', baseOptions)\n    optimize(ast, baseOptions)\n    expect(ast.static).toBe(true) // h1\n    expect(ast.staticRoot).toBe(true)\n    expect(ast.children[0].static).toBe(true) // span\n  })\n\n  it('simple with comment', () => {\n    const options = extend({\n      comments: true\n    }, baseOptions)\n    const ast = parse('<h1 id=\"section1\"><span>hello world</span><!--comment--></h1>', options)\n    optimize(ast, options)\n    expect(ast.static).toBe(true) // h1\n    expect(ast.staticRoot).toBe(true)\n    expect(ast.children.length).toBe(2)\n    expect(ast.children[0].static).toBe(true) // span\n    expect(ast.children[1].static).toBe(true) // comment\n  })\n\n  it('skip simple nodes', () => {\n    const ast = parse('<h1 id=\"section1\">hello</h1>', baseOptions)\n    optimize(ast, baseOptions)\n    expect(ast.static).toBe(true)\n    expect(ast.staticRoot).toBe(false) // this is too simple to warrant a static tree\n  })\n\n  it('interpolation', () => {\n    const ast = parse('<h1>{{msg}}</h1>', baseOptions)\n    optimize(ast, baseOptions)\n    expect(ast.static).toBe(false) // h1\n    expect(ast.children[0].static).toBe(false) // text node with interpolation\n  })\n\n  it('nested elements', () => {\n    const ast = parse('<ul><li>hello</li><li>world</li></ul>', baseOptions)\n    optimize(ast, baseOptions)\n    // ul\n    expect(ast.static).toBe(true)\n    expect(ast.staticRoot).toBe(true)\n    // li\n    expect(ast.children[0].static).toBe(true) // first\n    expect(ast.children[1].static).toBe(true) // second\n    // text node inside li\n    expect(ast.children[0].children[0].static).toBe(true) // first\n    expect(ast.children[1].children[0].static).toBe(true) // second\n  })\n\n  it('nested complex elements', () => {\n    const ast = parse('<ul><li>{{msg1}}</li><li>---</li><li>{{msg2}}</li></ul>', baseOptions)\n    optimize(ast, baseOptions)\n    // ul\n    expect(ast.static).toBe(false) // ul\n    // li\n    expect(ast.children[0].static).toBe(false) // first\n    expect(ast.children[1].static).toBe(true) // second\n    expect(ast.children[2].static).toBe(false) // third\n    // text node inside li\n    expect(ast.children[0].children[0].static).toBe(false) // first\n    expect(ast.children[1].children[0].static).toBe(true) // second\n    expect(ast.children[2].children[0].static).toBe(false) // third\n  })\n\n  it('v-if directive', () => {\n    const ast = parse('<div id=\"section1\" v-if=\"show\"><p><span>hello world</span></p></div>', baseOptions)\n    optimize(ast, baseOptions)\n    expect(ast.static).toBe(false)\n    expect(ast.children[0].static).toBe(true)\n  })\n\n  it('v-else directive', () => {\n    const ast = parse('<div><p v-if=\"show\">hello world</p><div v-else><p><span>foo bar</span></p></div></div>', baseOptions)\n    optimize(ast, baseOptions)\n    expect(ast.static).toBe(false)\n    expect(ast.children[0].static).toBe(false)\n    expect(ast.children[0].ifConditions[0].block.static).toBe(false)\n    expect(ast.children[0].ifConditions[1].block.static).toBe(false)\n    expect(ast.children[0].ifConditions[0].block.children[0].static).toBe(true)\n    expect(ast.children[0].ifConditions[1].block.children[0].static).toBe(true)\n  })\n\n  it('v-pre directive', () => {\n    const ast = parse('<ul v-pre><li>{{msg}}</li><li>world</li></ul>', baseOptions)\n    optimize(ast, baseOptions)\n    expect(ast.static).toBe(true)\n    expect(ast.staticRoot).toBe(true)\n    expect(ast.children[0].static).toBe(true)\n    expect(ast.children[1].static).toBe(true)\n    expect(ast.children[0].children[0].static).toBe(true)\n    expect(ast.children[1].children[0].static).toBe(true)\n  })\n\n  it('v-for directive', () => {\n    const ast = parse('<ul><li v-for=\"item in items\">hello world {{$index}}</li></ul>', baseOptions)\n    optimize(ast, baseOptions)\n    // ul\n    expect(ast.static).toBe(false)\n    // li with v-for\n    expect(ast.children[0].static).toBe(false)\n    expect(ast.children[0].children[0].static).toBe(false)\n  })\n\n  it('v-once directive', () => {\n    const ast = parse('<p v-once>{{msg}}</p>', baseOptions)\n    optimize(ast, baseOptions)\n    expect(ast.static).toBe(false) // p\n    expect(ast.children[0].static).toBe(false) // text node\n  })\n\n  it('single slot', () => {\n    const ast = parse('<div><slot>hello</slot></div>', baseOptions)\n    optimize(ast, baseOptions)\n    expect(ast.children[0].static).toBe(false) // slot\n    expect(ast.children[0].children[0].static).toBe(true) // text node\n  })\n\n  it('named slot', () => {\n    const ast = parse('<div><slot name=\"one\">hello world</slot></div>', baseOptions)\n    optimize(ast, baseOptions)\n    expect(ast.children[0].static).toBe(false) // slot\n    expect(ast.children[0].children[0].static).toBe(true) // text node\n  })\n\n  it('slot target', () => {\n    const ast = parse('<p slot=\"one\">hello world</p>', baseOptions)\n    optimize(ast, baseOptions)\n    expect(ast.static).toBe(false) // slot\n    expect(ast.children[0].static).toBe(true) // text node\n  })\n\n  it('component', () => {\n    const ast = parse('<my-component></my-component>', baseOptions)\n    optimize(ast, baseOptions)\n    expect(ast.static).toBe(false) // component\n  })\n\n  it('component for inline-template', () => {\n    const ast = parse('<my-component inline-template><p>hello world</p><p>{{msg}}</p></my-component>', baseOptions)\n    optimize(ast, baseOptions)\n    // component\n    expect(ast.static).toBe(false) // component\n    // p\n    expect(ast.children[0].static).toBe(true) // first\n    expect(ast.children[1].static).toBe(false) // second\n    // text node inside p\n    expect(ast.children[0].children[0].static).toBe(true) // first\n    expect(ast.children[1].children[0].static).toBe(false) // second\n  })\n\n  it('class binding', () => {\n    const ast = parse('<p :class=\"class1\">hello world</p>', baseOptions)\n    optimize(ast, baseOptions)\n    expect(ast.static).toBe(false)\n    expect(ast.children[0].static).toBe(true)\n  })\n\n  it('style binding', () => {\n    const ast = parse('<p :style=\"error\">{{msg}}</p>', baseOptions)\n    optimize(ast, baseOptions)\n    expect(ast.static).toBe(false)\n    expect(ast.children[0].static).toBe(false)\n  })\n\n  it('key', () => {\n    const ast = parse('<p key=\"foo\">hello world</p>', baseOptions)\n    optimize(ast, baseOptions)\n    expect(ast.static).toBe(false)\n    expect(ast.children[0].static).toBe(true)\n  })\n\n  it('ref', () => {\n    const ast = parse('<p ref=\"foo\">hello world</p>', baseOptions)\n    optimize(ast, baseOptions)\n    expect(ast.static).toBe(false)\n    expect(ast.children[0].static).toBe(true)\n  })\n\n  it('transition', () => {\n    const ast = parse('<p v-if=\"show\" transition=\"expand\">hello world</p>', baseOptions)\n    optimize(ast, baseOptions)\n    expect(ast.static).toBe(false)\n    expect(ast.children[0].static).toBe(true)\n  })\n\n  it('v-bind directive', () => {\n    const ast = parse('<input type=\"text\" name=\"field1\" :value=\"msg\">', baseOptions)\n    optimize(ast, baseOptions)\n    expect(ast.static).toBe(false)\n  })\n\n  it('v-on directive', () => {\n    const ast = parse('<input type=\"text\" name=\"field1\" :value=\"msg\" @input=\"onInput\">', baseOptions)\n    optimize(ast, baseOptions)\n    expect(ast.static).toBe(false)\n  })\n\n  it('custom directive', () => {\n    const ast = parse('<form><input type=\"text\" name=\"field1\" :value=\"msg\" v-validate:field1=\"required\"></form>', baseOptions)\n    optimize(ast, baseOptions)\n    expect(ast.static).toBe(false)\n    expect(ast.children[0].static).toBe(false)\n  })\n\n  it('not root ast', () => {\n    const ast = null\n    optimize(ast, baseOptions)\n    expect(ast).toBe(null)\n  })\n\n  it('not specified isReservedTag option', () => {\n    const ast = parse('<h1 id=\"section1\">hello world</h1>', baseOptions)\n    optimize(ast, {})\n    expect(ast.static).toBe(false)\n  })\n\n  it('mark static trees inside v-for', () => {\n    const ast = parse(`<div><div v-for=\"i in 10\"><p><span>hi</span></p></div></div>`, baseOptions)\n    optimize(ast, baseOptions)\n    expect(ast.children[0].children[0].staticRoot).toBe(true)\n    expect(ast.children[0].children[0].staticInFor).toBe(true)\n  })\n\n  it('mark static trees inside v-for with nested v-else and v-once', () => {\n    const ast = parse(`\n      <div v-if=\"1\"></div>\n      <div v-else-if=\"2\">\n        <div v-for=\"i in 10\" :key=\"i\">\n          <div v-if=\"1\">{{ i }}</div>\n          <div v-else-if=\"2\" v-once>{{ i }}</div>\n          <div v-else v-once>{{ i }}</div>\n        </div>\n      </div>\n      <div v-else>\n        <div v-for=\"i in 10\" :key=\"i\">\n          <div v-if=\"1\">{{ i }}</div>\n          <div v-else v-once>{{ i }}</div>\n        </div>\n      </div>\n      `, baseOptions)\n    optimize(ast, baseOptions)\n    expect(ast.ifConditions[1].block.children[0].children[0].ifConditions[1].block.staticRoot).toBe(false)\n    expect(ast.ifConditions[1].block.children[0].children[0].ifConditions[1].block.staticInFor).toBe(true)\n\n    expect(ast.ifConditions[1].block.children[0].children[0].ifConditions[2].block.staticRoot).toBe(false)\n    expect(ast.ifConditions[1].block.children[0].children[0].ifConditions[2].block.staticInFor).toBe(true)\n\n    expect(ast.ifConditions[2].block.children[0].children[0].ifConditions[1].block.staticRoot).toBe(false)\n    expect(ast.ifConditions[2].block.children[0].children[0].ifConditions[1].block.staticInFor).toBe(true)\n  })\n})\n"
  },
  {
    "path": "test/unit/modules/compiler/parser.spec.js",
    "content": "import { parse } from 'compiler/parser/index'\nimport { extend } from 'shared/util'\nimport { baseOptions } from 'web/compiler/options'\nimport { isIE, isEdge } from 'core/util/env'\n\ndescribe('parser', () => {\n  it('simple element', () => {\n    const ast = parse('<h1>hello world</h1>', baseOptions)\n    expect(ast.tag).toBe('h1')\n    expect(ast.plain).toBe(true)\n    expect(ast.children[0].text).toBe('hello world')\n  })\n\n  it('interpolation in element', () => {\n    const ast = parse('<h1>{{msg}}</h1>', baseOptions)\n    expect(ast.tag).toBe('h1')\n    expect(ast.plain).toBe(true)\n    expect(ast.children[0].expression).toBe('_s(msg)')\n  })\n\n  it('child elements', () => {\n    const ast = parse('<ul><li>hello world</li></ul>', baseOptions)\n    expect(ast.tag).toBe('ul')\n    expect(ast.plain).toBe(true)\n    expect(ast.children[0].tag).toBe('li')\n    expect(ast.children[0].plain).toBe(true)\n    expect(ast.children[0].children[0].text).toBe('hello world')\n    expect(ast.children[0].parent).toBe(ast)\n  })\n\n  it('unary element', () => {\n    const ast = parse('<hr>', baseOptions)\n    expect(ast.tag).toBe('hr')\n    expect(ast.plain).toBe(true)\n    expect(ast.children.length).toBe(0)\n  })\n\n  it('svg element', () => {\n    const ast = parse('<svg><text>hello world</text></svg>', baseOptions)\n    expect(ast.tag).toBe('svg')\n    expect(ast.ns).toBe('svg')\n    expect(ast.plain).toBe(true)\n    expect(ast.children[0].tag).toBe('text')\n    expect(ast.children[0].children[0].text).toBe('hello world')\n    expect(ast.children[0].parent).toBe(ast)\n  })\n\n  it('camelCase element', () => {\n    const ast = parse('<MyComponent><p>hello world</p></MyComponent>', baseOptions)\n    expect(ast.tag).toBe('MyComponent')\n    expect(ast.plain).toBe(true)\n    expect(ast.children[0].tag).toBe('p')\n    expect(ast.children[0].plain).toBe(true)\n    expect(ast.children[0].children[0].text).toBe('hello world')\n    expect(ast.children[0].parent).toBe(ast)\n  })\n\n  it('forbidden element', () => {\n    // style\n    const styleAst = parse('<style>error { color: red; }</style>', baseOptions)\n    expect(styleAst.tag).toBe('style')\n    expect(styleAst.plain).toBe(true)\n    expect(styleAst.forbidden).toBe(true)\n    expect(styleAst.children[0].text).toBe('error { color: red; }')\n    expect('Templates should only be responsible for mapping the state').toHaveBeenWarned()\n    // script\n    const scriptAst = parse('<script type=\"text/javascript\">alert(\"hello world!\")</script>', baseOptions)\n    expect(scriptAst.tag).toBe('script')\n    expect(scriptAst.plain).toBe(false)\n    expect(scriptAst.forbidden).toBe(true)\n    expect(scriptAst.children[0].text).toBe('alert(\"hello world!\")')\n    expect('Templates should only be responsible for mapping the state').toHaveBeenWarned()\n  })\n\n  it('not contain root element', () => {\n    parse('hello world', baseOptions)\n    expect('Component template requires a root element, rather than just text').toHaveBeenWarned()\n  })\n\n  it('warn text before root element', () => {\n    parse('before root {{ interpolation }}<div></div>', baseOptions)\n    expect('text \"before root {{ interpolation }}\" outside root element will be ignored.').toHaveBeenWarned()\n  })\n\n  it('warn text after root element', () => {\n    parse('<div></div>after root {{ interpolation }}', baseOptions)\n    expect('text \"after root {{ interpolation }}\" outside root element will be ignored.').toHaveBeenWarned()\n  })\n\n  it('warn multiple root elements', () => {\n    parse('<div></div><div></div>', baseOptions)\n    expect('Component template should contain exactly one root element').toHaveBeenWarned()\n  })\n\n  it('remove duplicate whitespace text nodes caused by comments', () => {\n    const ast = parse(`<div><a></a> <!----> <a></a></div>`, baseOptions)\n    expect(ast.children.length).toBe(3)\n    expect(ast.children[0].tag).toBe('a')\n    expect(ast.children[1].text).toBe(' ')\n    expect(ast.children[2].tag).toBe('a')\n  })\n\n  it('remove text nodes between v-if conditions', () => {\n    const ast = parse(`<div><div v-if=\"1\"></div> <div v-else-if=\"2\"></div> <div v-else></div> <span></span></div>`, baseOptions)\n    expect(ast.children.length).toBe(3)\n    expect(ast.children[0].tag).toBe('div')\n    expect(ast.children[0].ifConditions.length).toBe(3)\n    expect(ast.children[1].text).toBe(' ') // text\n    expect(ast.children[2].tag).toBe('span')\n  })\n\n  it('warn non whitespace text between v-if conditions', () => {\n    parse(`<div><div v-if=\"1\"></div> foo <div v-else></div></div>`, baseOptions)\n    expect(`text \"foo\" between v-if and v-else(-if) will be ignored`).toHaveBeenWarned()\n  })\n\n  it('not warn 2 root elements with v-if and v-else', () => {\n    parse('<div v-if=\"1\"></div><div v-else></div>', baseOptions)\n    expect('Component template should contain exactly one root element')\n      .not.toHaveBeenWarned()\n  })\n\n  it('not warn 3 root elements with v-if, v-else-if and v-else', () => {\n    parse('<div v-if=\"1\"></div><div v-else-if=\"2\"></div><div v-else></div>', baseOptions)\n    expect('Component template should contain exactly one root element')\n        .not.toHaveBeenWarned()\n  })\n\n  it('not warn 2 root elements with v-if and v-else on separate lines', () => {\n    parse(`\n      <div v-if=\"1\"></div>\n      <div v-else></div>\n    `, baseOptions)\n    expect('Component template should contain exactly one root element')\n      .not.toHaveBeenWarned()\n  })\n\n  it('not warn 3 or more root elements with v-if, v-else-if and v-else on separate lines', () => {\n    parse(`\n      <div v-if=\"1\"></div>\n      <div v-else-if=\"2\"></div>\n      <div v-else></div>\n    `, baseOptions)\n    expect('Component template should contain exactly one root element')\n        .not.toHaveBeenWarned()\n\n    parse(`\n      <div v-if=\"1\"></div>\n      <div v-else-if=\"2\"></div>\n      <div v-else-if=\"3\"></div>\n      <div v-else-if=\"4\"></div>\n      <div v-else></div>\n    `, baseOptions)\n    expect('Component template should contain exactly one root element')\n        .not.toHaveBeenWarned()\n  })\n\n  it('generate correct ast for 2 root elements with v-if and v-else on separate lines', () => {\n    const ast = parse(`\n      <div v-if=\"1\"></div>\n      <p v-else></p>\n    `, baseOptions)\n    expect(ast.tag).toBe('div')\n    expect(ast.ifConditions[1].block.tag).toBe('p')\n  })\n\n  it('generate correct ast for 3 or more root elements with v-if and v-else on separate lines', () => {\n    const ast = parse(`\n      <div v-if=\"1\"></div>\n      <span v-else-if=\"2\"></span>\n      <p v-else></p>\n    `, baseOptions)\n    expect(ast.tag).toBe('div')\n    expect(ast.ifConditions[0].block.tag).toBe('div')\n    expect(ast.ifConditions[1].block.tag).toBe('span')\n    expect(ast.ifConditions[2].block.tag).toBe('p')\n\n    const astMore = parse(`\n      <div v-if=\"1\"></div>\n      <span v-else-if=\"2\"></span>\n      <div v-else-if=\"3\"></div>\n      <span v-else-if=\"4\"></span>\n      <p v-else></p>\n    `, baseOptions)\n    expect(astMore.tag).toBe('div')\n    expect(astMore.ifConditions[0].block.tag).toBe('div')\n    expect(astMore.ifConditions[1].block.tag).toBe('span')\n    expect(astMore.ifConditions[2].block.tag).toBe('div')\n    expect(astMore.ifConditions[3].block.tag).toBe('span')\n    expect(astMore.ifConditions[4].block.tag).toBe('p')\n  })\n\n  it('warn 2 root elements with v-if', () => {\n    parse('<div v-if=\"1\"></div><div v-if=\"2\"></div>', baseOptions)\n    expect('Component template should contain exactly one root element').toHaveBeenWarned()\n  })\n\n  it('warn 3 root elements with v-if and v-else on first 2', () => {\n    parse('<div v-if=\"1\"></div><div v-else></div><div></div>', baseOptions)\n    expect('Component template should contain exactly one root element').toHaveBeenWarned()\n  })\n\n  it('warn 3 root elements with v-if and v-else-if on first 2', () => {\n    parse('<div v-if=\"1\"></div><div v-else-if></div><div></div>', baseOptions)\n    expect('Component template should contain exactly one root element').toHaveBeenWarned()\n  })\n\n  it('warn 4 root elements with v-if, v-else-if and v-else on first 2', () => {\n    parse('<div v-if=\"1\"></div><div v-else-if></div><div v-else></div><div></div>', baseOptions)\n    expect('Component template should contain exactly one root element').toHaveBeenWarned()\n  })\n\n  it('warn 2 root elements with v-if and v-else with v-for on 2nd', () => {\n    parse('<div v-if=\"1\"></div><div v-else v-for=\"i in [1]\"></div>', baseOptions)\n    expect('Cannot use v-for on stateful component root element because it renders multiple elements')\n      .toHaveBeenWarned()\n  })\n\n  it('warn 2 root elements with v-if and v-else-if with v-for on 2nd', () => {\n    parse('<div v-if=\"1\"></div><div v-else-if=\"2\" v-for=\"i in [1]\"></div>', baseOptions)\n    expect('Cannot use v-for on stateful component root element because it renders multiple elements')\n        .toHaveBeenWarned()\n  })\n\n  it('warn <template> as root element', () => {\n    parse('<template></template>', baseOptions)\n    expect('Cannot use <template> as component root element').toHaveBeenWarned()\n  })\n\n  it('warn <slot> as root element', () => {\n    parse('<slot></slot>', baseOptions)\n    expect('Cannot use <slot> as component root element').toHaveBeenWarned()\n  })\n\n  it('warn v-for on root element', () => {\n    parse('<div v-for=\"item in items\"></div>', baseOptions)\n    expect('Cannot use v-for on stateful component root element').toHaveBeenWarned()\n  })\n\n  it('warn <template> key', () => {\n    parse('<div><template v-for=\"i in 10\" :key=\"i\"></template></div>', baseOptions)\n    expect('<template> cannot be keyed').toHaveBeenWarned()\n  })\n\n  it('v-pre directive', () => {\n    const ast = parse('<div v-pre id=\"message1\"><p>{{msg}}</p></div>', baseOptions)\n    expect(ast.pre).toBe(true)\n    expect(ast.attrs[0].name).toBe('id')\n    expect(ast.attrs[0].value).toBe('\"message1\"')\n    expect(ast.children[0].children[0].text).toBe('{{msg}}')\n  })\n\n  it('v-for directive basic syntax', () => {\n    const ast = parse('<ul><li v-for=\"item in items\"></li></ul>', baseOptions)\n    const liAst = ast.children[0]\n    expect(liAst.for).toBe('items')\n    expect(liAst.alias).toBe('item')\n  })\n\n  it('v-for directive iteration syntax', () => {\n    const ast = parse('<ul><li v-for=\"(item, index) in items\"></li></ul>', baseOptions)\n    const liAst = ast.children[0]\n    expect(liAst.for).toBe('items')\n    expect(liAst.alias).toBe('item')\n    expect(liAst.iterator1).toBe('index')\n    expect(liAst.iterator2).toBeUndefined()\n  })\n\n  it('v-for directive iteration syntax (multiple)', () => {\n    const ast = parse('<ul><li v-for=\"(item, key, index) in items\"></li></ul>', baseOptions)\n    const liAst = ast.children[0]\n    expect(liAst.for).toBe('items')\n    expect(liAst.alias).toBe('item')\n    expect(liAst.iterator1).toBe('key')\n    expect(liAst.iterator2).toBe('index')\n  })\n\n  it('v-for directive key', () => {\n    const ast = parse('<ul><li v-for=\"item in items\" :key=\"item.uid\"></li></ul>', baseOptions)\n    const liAst = ast.children[0]\n    expect(liAst.for).toBe('items')\n    expect(liAst.alias).toBe('item')\n    expect(liAst.key).toBe('item.uid')\n  })\n\n  it('v-for directive invalid syntax', () => {\n    parse('<ul><li v-for=\"item into items\"></li></ul>', baseOptions)\n    expect('Invalid v-for expression').toHaveBeenWarned()\n  })\n\n  it('v-if directive syntax', () => {\n    const ast = parse('<p v-if=\"show\">hello world</p>', baseOptions)\n    expect(ast.if).toBe('show')\n    expect(ast.ifConditions[0].exp).toBe('show')\n  })\n\n  it('v-else-if directive syntax', () => {\n    const ast = parse('<div><p v-if=\"show\">hello</p><span v-else-if=\"2\">elseif</span><p v-else>world</p></div>', baseOptions)\n    const ifAst = ast.children[0]\n    const conditionsAst = ifAst.ifConditions\n    expect(conditionsAst.length).toBe(3)\n    expect(conditionsAst[1].block.children[0].text).toBe('elseif')\n    expect(conditionsAst[1].block.parent).toBe(ast)\n    expect(conditionsAst[2].block.children[0].text).toBe('world')\n    expect(conditionsAst[2].block.parent).toBe(ast)\n  })\n\n  it('v-else directive syntax', () => {\n    const ast = parse('<div><p v-if=\"show\">hello</p><p v-else>world</p></div>', baseOptions)\n    const ifAst = ast.children[0]\n    const conditionsAst = ifAst.ifConditions\n    expect(conditionsAst.length).toBe(2)\n    expect(conditionsAst[1].block.children[0].text).toBe('world')\n    expect(conditionsAst[1].block.parent).toBe(ast)\n  })\n\n  it('v-else-if directive invalid syntax', () => {\n    parse('<div><p v-else-if=\"1\">world</p></div>', baseOptions)\n    expect('v-else-if=\"1\" used on element').toHaveBeenWarned()\n  })\n\n  it('v-else directive invalid syntax', () => {\n    parse('<div><p v-else>world</p></div>', baseOptions)\n    expect('v-else used on element').toHaveBeenWarned()\n  })\n\n  it('v-once directive syntax', () => {\n    const ast = parse('<p v-once>world</p>', baseOptions)\n    expect(ast.once).toBe(true)\n  })\n\n  it('slot tag single syntax', () => {\n    const ast = parse('<div><slot></slot></div>', baseOptions)\n    expect(ast.children[0].tag).toBe('slot')\n    expect(ast.children[0].slotName).toBeUndefined()\n  })\n\n  it('slot tag named syntax', () => {\n    const ast = parse('<div><slot name=\"one\">hello world</slot></div>', baseOptions)\n    expect(ast.children[0].tag).toBe('slot')\n    expect(ast.children[0].slotName).toBe('\"one\"')\n  })\n\n  it('slot target', () => {\n    const ast = parse('<p slot=\"one\">hello world</p>', baseOptions)\n    expect(ast.slotTarget).toBe('\"one\"')\n  })\n\n  it('component properties', () => {\n    const ast = parse('<my-component :msg=\"hello\"></my-component>', baseOptions)\n    expect(ast.attrs[0].name).toBe('msg')\n    expect(ast.attrs[0].value).toBe('hello')\n  })\n\n  it('component \"is\" attribute', () => {\n    const ast = parse('<my-component is=\"component1\"></my-component>', baseOptions)\n    expect(ast.component).toBe('\"component1\"')\n  })\n\n  it('component \"inline-template\" attribute', () => {\n    const ast = parse('<my-component inline-template>hello world</my-component>', baseOptions)\n    expect(ast.inlineTemplate).toBe(true)\n  })\n\n  it('class binding', () => {\n    // static\n    const ast1 = parse('<p class=\"class1\">hello world</p>', baseOptions)\n    expect(ast1.staticClass).toBe('\"class1\"')\n    // dynamic\n    const ast2 = parse('<p :class=\"class1\">hello world</p>', baseOptions)\n    expect(ast2.classBinding).toBe('class1')\n    // interpolation warning\n    parse('<p class=\"{{error}}\">hello world</p>', baseOptions)\n    expect('Interpolation inside attributes has been removed').toHaveBeenWarned()\n  })\n\n  it('style binding', () => {\n    const ast = parse('<p :style=\"error\">hello world</p>', baseOptions)\n    expect(ast.styleBinding).toBe('error')\n  })\n\n  it('attribute with v-bind', () => {\n    const ast = parse('<input type=\"text\" name=\"field1\" :value=\"msg\">', baseOptions)\n    expect(ast.attrsList[0].name).toBe('type')\n    expect(ast.attrsList[0].value).toBe('text')\n    expect(ast.attrsList[1].name).toBe('name')\n    expect(ast.attrsList[1].value).toBe('field1')\n    expect(ast.attrsMap['type']).toBe('text')\n    expect(ast.attrsMap['name']).toBe('field1')\n    expect(ast.attrs[0].name).toBe('type')\n    expect(ast.attrs[0].value).toBe('\"text\"')\n    expect(ast.attrs[1].name).toBe('name')\n    expect(ast.attrs[1].value).toBe('\"field1\"')\n    expect(ast.props[0].name).toBe('value')\n    expect(ast.props[0].value).toBe('msg')\n  })\n\n  it('attribute with v-on', () => {\n    const ast = parse('<input type=\"text\" name=\"field1\" :value=\"msg\" @input=\"onInput\">', baseOptions)\n    expect(ast.events.input.value).toBe('onInput')\n  })\n\n  it('attribute with directive', () => {\n    const ast = parse('<input type=\"text\" name=\"field1\" :value=\"msg\" v-validate:field1=\"required\">', baseOptions)\n    expect(ast.directives[0].name).toBe('validate')\n    expect(ast.directives[0].value).toBe('required')\n    expect(ast.directives[0].arg).toBe('field1')\n  })\n\n  it('attribute with modifiered directive', () => {\n    const ast = parse('<input type=\"text\" name=\"field1\" :value=\"msg\" v-validate.on.off>', baseOptions)\n    expect(ast.directives[0].modifiers.on).toBe(true)\n    expect(ast.directives[0].modifiers.off).toBe(true)\n  })\n\n  it('literal attribute', () => {\n    // basic\n    const ast1 = parse('<input type=\"text\" name=\"field1\" value=\"hello world\">', baseOptions)\n    expect(ast1.attrsList[0].name).toBe('type')\n    expect(ast1.attrsList[0].value).toBe('text')\n    expect(ast1.attrsList[1].name).toBe('name')\n    expect(ast1.attrsList[1].value).toBe('field1')\n    expect(ast1.attrsList[2].name).toBe('value')\n    expect(ast1.attrsList[2].value).toBe('hello world')\n    expect(ast1.attrsMap['type']).toBe('text')\n    expect(ast1.attrsMap['name']).toBe('field1')\n    expect(ast1.attrsMap['value']).toBe('hello world')\n    expect(ast1.attrs[0].name).toBe('type')\n    expect(ast1.attrs[0].value).toBe('\"text\"')\n    expect(ast1.attrs[1].name).toBe('name')\n    expect(ast1.attrs[1].value).toBe('\"field1\"')\n    expect(ast1.attrs[2].name).toBe('value')\n    expect(ast1.attrs[2].value).toBe('\"hello world\"')\n    // interpolation warning\n    parse('<input type=\"text\" name=\"field1\" value=\"{{msg}}\">', baseOptions)\n    expect('Interpolation inside attributes has been removed').toHaveBeenWarned()\n  })\n\n  if (!isIE && !isEdge) {\n    it('duplicate attribute', () => {\n      parse('<p class=\"class1\" class=\"class1\">hello world</p>', baseOptions)\n      expect('duplicate attribute').toHaveBeenWarned()\n    })\n  }\n\n  it('custom delimiter', () => {\n    const ast = parse('<p>{msg}</p>', extend({ delimiters: ['{', '}'] }, baseOptions))\n    expect(ast.children[0].expression).toBe('_s(msg)')\n  })\n\n  it('not specified getTagNamespace option', () => {\n    const options = extend({}, baseOptions)\n    delete options.getTagNamespace\n    const ast = parse('<svg><text>hello world</text></svg>', options)\n    expect(ast.tag).toBe('svg')\n    expect(ast.ns).toBeUndefined()\n  })\n\n  it('not specified mustUseProp', () => {\n    const options = extend({}, baseOptions)\n    delete options.mustUseProp\n    const ast = parse('<input type=\"text\" name=\"field1\" :value=\"msg\">', options)\n    expect(ast.props).toBeUndefined()\n  })\n\n  it('pre/post transforms', () => {\n    const options = extend({}, baseOptions)\n    const spy1 = jasmine.createSpy('preTransform')\n    const spy2 = jasmine.createSpy('postTransform')\n    options.modules = options.modules.concat([{\n      preTransformNode (el) {\n        spy1(el.tag)\n      },\n      postTransformNode (el) {\n        expect(el.attrs.length).toBe(1)\n        spy2(el.tag)\n      }\n    }])\n    parse('<img v-pre src=\"hi\">', options)\n    expect(spy1).toHaveBeenCalledWith('img')\n    expect(spy2).toHaveBeenCalledWith('img')\n  })\n\n  it('preserve whitespace in <pre> tag', function () {\n    const options = extend({}, baseOptions)\n    const ast = parse('<pre><code>  \\n<span>hi</span>\\n  </code><span> </span></pre>', options)\n    const code = ast.children[0]\n    expect(code.children[0].type).toBe(3)\n    expect(code.children[0].text).toBe('  \\n')\n    expect(code.children[2].type).toBe(3)\n    expect(code.children[2].text).toBe('\\n  ')\n\n    const span = ast.children[1]\n    expect(span.children[0].type).toBe(3)\n    expect(span.children[0].text).toBe(' ')\n  })\n\n  // #5992\n  it('ignore the first newline in <pre> tag', function () {\n    const options = extend({}, baseOptions)\n    const ast = parse('<div><pre>\\nabc</pre>\\ndef<pre>\\n\\nabc</pre></div>', options)\n    const pre = ast.children[0]\n    expect(pre.children[0].type).toBe(3)\n    expect(pre.children[0].text).toBe('abc')\n    const text = ast.children[1]\n    expect(text.type).toBe(3)\n    expect(text.text).toBe('\\ndef')\n    const pre2 = ast.children[2]\n    expect(pre2.children[0].type).toBe(3)\n    expect(pre2.children[0].text).toBe('\\nabc')\n  })\n\n  it('forgivingly handle < in plain text', () => {\n    const options = extend({}, baseOptions)\n    const ast = parse('<p>1 < 2 < 3</p>', options)\n    expect(ast.tag).toBe('p')\n    expect(ast.children.length).toBe(1)\n    expect(ast.children[0].type).toBe(3)\n    expect(ast.children[0].text).toBe('1 < 2 < 3')\n  })\n\n  it('IE conditional comments', () => {\n    const options = extend({}, baseOptions)\n    const ast = parse(`\n      <div>\n        <!--[if lte IE 8]>\n          <p>Test 1</p>\n        <![endif]-->\n      </div>\n    `, options)\n    expect(ast.tag).toBe('div')\n    expect(ast.children.length).toBe(0)\n  })\n\n  it('parse content in textarea as text', () => {\n    const options = extend({}, baseOptions)\n\n    const whitespace = parse(`\n      <textarea>\n        <p>Test 1</p>\n        test2\n      </textarea>\n    `, options)\n    expect(whitespace.tag).toBe('textarea')\n    expect(whitespace.children.length).toBe(1)\n    expect(whitespace.children[0].type).toBe(3)\n    // textarea is whitespace sensitive\n    expect(whitespace.children[0].text).toBe(`        <p>Test 1</p>\n        test2\n      `)\n\n    const comment = parse('<textarea><!--comment--></textarea>', options)\n    expect(comment.tag).toBe('textarea')\n    expect(comment.children.length).toBe(1)\n    expect(comment.children[0].type).toBe(3)\n    expect(comment.children[0].text).toBe('<!--comment-->')\n  })\n\n  // #5526\n  it('should not decode text in script tags', () => {\n    const options = extend({}, baseOptions)\n    const ast = parse(`<script type=\"x/template\">&gt;<foo>&lt;</script>`, options)\n    expect(ast.children[0].text).toBe(`&gt;<foo>&lt;`)\n  })\n\n  it('should ignore comments', () => {\n    const options = extend({}, baseOptions)\n    const ast = parse(`<div>123<!--comment here--></div>`, options)\n    expect(ast.tag).toBe('div')\n    expect(ast.children.length).toBe(1)\n    expect(ast.children[0].type).toBe(3)\n    expect(ast.children[0].text).toBe('123')\n  })\n\n  it('should kept comments', () => {\n    const options = extend({\n      comments: true\n    }, baseOptions)\n    const ast = parse(`<div>123<!--comment here--></div>`, options)\n    expect(ast.tag).toBe('div')\n    expect(ast.children.length).toBe(2)\n    expect(ast.children[0].type).toBe(3)\n    expect(ast.children[0].text).toBe('123')\n    expect(ast.children[1].type).toBe(3) // parse comment with ASTText\n    expect(ast.children[1].isComment).toBe(true) // parse comment with ASTText\n    expect(ast.children[1].text).toBe('comment here')\n  })\n})\n"
  },
  {
    "path": "test/unit/modules/observer/observer.spec.js",
    "content": "import Vue from 'vue'\nimport {\n  Observer,\n  observe,\n  set as setProp,\n  del as delProp\n} from 'core/observer/index'\nimport Dep from 'core/observer/dep'\nimport { hasOwn } from 'core/util/index'\n\ndescribe('Observer', () => {\n  it('create on non-observables', () => {\n    // skip primitive value\n    const ob1 = observe(1)\n    expect(ob1).toBeUndefined()\n    // avoid vue instance\n    const ob2 = observe(new Vue())\n    expect(ob2).toBeUndefined()\n    // avoid frozen objects\n    const ob3 = observe(Object.freeze({}))\n    expect(ob3).toBeUndefined()\n  })\n\n  it('create on object', () => {\n    // on object\n    const obj = {\n      a: {},\n      b: {}\n    }\n    const ob1 = observe(obj)\n    expect(ob1 instanceof Observer).toBe(true)\n    expect(ob1.value).toBe(obj)\n    expect(obj.__ob__).toBe(ob1)\n    // should've walked children\n    expect(obj.a.__ob__ instanceof Observer).toBe(true)\n    expect(obj.b.__ob__ instanceof Observer).toBe(true)\n    // should return existing ob on already observed objects\n    const ob2 = observe(obj)\n    expect(ob2).toBe(ob1)\n  })\n\n  it('create on null', () => {\n    // on null\n    const obj = Object.create(null)\n    obj.a = {}\n    obj.b = {}\n    const ob1 = observe(obj)\n    expect(ob1 instanceof Observer).toBe(true)\n    expect(ob1.value).toBe(obj)\n    expect(obj.__ob__).toBe(ob1)\n    // should've walked children\n    expect(obj.a.__ob__ instanceof Observer).toBe(true)\n    expect(obj.b.__ob__ instanceof Observer).toBe(true)\n    // should return existing ob on already observed objects\n    const ob2 = observe(obj)\n    expect(ob2).toBe(ob1)\n  })\n\n  it('create on already observed object', () => {\n    // on object\n    const obj = {}\n    let val = 0\n    let getCount = 0\n    Object.defineProperty(obj, 'a', {\n      configurable: true,\n      enumerable: true,\n      get () {\n        getCount++\n        return val\n      },\n      set (v) { val = v }\n    })\n\n    const ob1 = observe(obj)\n    expect(ob1 instanceof Observer).toBe(true)\n    expect(ob1.value).toBe(obj)\n    expect(obj.__ob__).toBe(ob1)\n\n    getCount = 0\n    // Each read of 'a' should result in only one get underlying get call\n    obj.a\n    expect(getCount).toBe(1)\n    obj.a\n    expect(getCount).toBe(2)\n\n    // should return existing ob on already observed objects\n    const ob2 = observe(obj)\n    expect(ob2).toBe(ob1)\n\n    // should call underlying setter\n    obj.a = 10\n    expect(val).toBe(10)\n  })\n\n  it('create on property with only getter', () => {\n    // on object\n    const obj = {}\n    Object.defineProperty(obj, 'a', {\n      configurable: true,\n      enumerable: true,\n      get () { return 123 }\n    })\n\n    const ob1 = observe(obj)\n    expect(ob1 instanceof Observer).toBe(true)\n    expect(ob1.value).toBe(obj)\n    expect(obj.__ob__).toBe(ob1)\n\n    // should be able to read\n    expect(obj.a).toBe(123)\n\n    // should return existing ob on already observed objects\n    const ob2 = observe(obj)\n    expect(ob2).toBe(ob1)\n\n    // since there is no setter, you shouldn't be able to write to it\n    // PhantomJS throws when a property with no setter is set\n    // but other real browsers don't\n    try {\n      obj.a = 101\n    } catch (e) {}\n    expect(obj.a).toBe(123)\n  })\n\n  it('create on property with only setter', () => {\n    // on object\n    const obj = {}\n    let val = 10\n    Object.defineProperty(obj, 'a', { // eslint-disable-line accessor-pairs\n      configurable: true,\n      enumerable: true,\n      set (v) { val = v }\n    })\n\n    const ob1 = observe(obj)\n    expect(ob1 instanceof Observer).toBe(true)\n    expect(ob1.value).toBe(obj)\n    expect(obj.__ob__).toBe(ob1)\n\n    // reads should return undefined\n    expect(obj.a).toBe(undefined)\n\n    // should return existing ob on already observed objects\n    const ob2 = observe(obj)\n    expect(ob2).toBe(ob1)\n\n    // writes should call the set function\n    obj.a = 100\n    expect(val).toBe(100)\n  })\n\n  it('create on property which is marked not configurable', () => {\n    // on object\n    const obj = {}\n    Object.defineProperty(obj, 'a', {\n      configurable: false,\n      enumerable: true,\n      val: 10\n    })\n\n    const ob1 = observe(obj)\n    expect(ob1 instanceof Observer).toBe(true)\n    expect(ob1.value).toBe(obj)\n    expect(obj.__ob__).toBe(ob1)\n  })\n\n  it('create on array', () => {\n    // on object\n    const arr = [{}, {}]\n    const ob1 = observe(arr)\n    expect(ob1 instanceof Observer).toBe(true)\n    expect(ob1.value).toBe(arr)\n    expect(arr.__ob__).toBe(ob1)\n    // should've walked children\n    expect(arr[0].__ob__ instanceof Observer).toBe(true)\n    expect(arr[1].__ob__ instanceof Observer).toBe(true)\n  })\n\n  it('observing object prop change', () => {\n    const obj = { a: { b: 2 }, c: NaN }\n    observe(obj)\n    // mock a watcher!\n    const watcher = {\n      deps: [],\n      addDep (dep) {\n        this.deps.push(dep)\n        dep.addSub(this)\n      },\n      update: jasmine.createSpy()\n    }\n    // collect dep\n    Dep.target = watcher\n    obj.a.b\n    Dep.target = null\n    expect(watcher.deps.length).toBe(3) // obj.a + a + a.b\n    obj.a.b = 3\n    expect(watcher.update.calls.count()).toBe(1)\n    // swap object\n    obj.a = { b: 4 }\n    expect(watcher.update.calls.count()).toBe(2)\n    watcher.deps = []\n\n    Dep.target = watcher\n    obj.a.b\n    obj.c\n    Dep.target = null\n    expect(watcher.deps.length).toBe(4)\n    // set on the swapped object\n    obj.a.b = 5\n    expect(watcher.update.calls.count()).toBe(3)\n    // should not trigger on NaN -> NaN set\n    obj.c = NaN\n    expect(watcher.update.calls.count()).toBe(3)\n  })\n\n  it('observing object prop change on defined property', () => {\n    const obj = { val: 2 }\n    Object.defineProperty(obj, 'a', {\n      configurable: true,\n      enumerable: true,\n      get () { return this.val },\n      set (v) {\n        this.val = v\n        return this.val\n      }\n    })\n\n    observe(obj)\n    // mock a watcher!\n    const watcher = {\n      deps: [],\n      addDep: function (dep) {\n        this.deps.push(dep)\n        dep.addSub(this)\n      },\n      update: jasmine.createSpy()\n    }\n    // collect dep\n    Dep.target = watcher\n    expect(obj.a).toBe(2) // Make sure 'this' is preserved\n    Dep.target = null\n    obj.a = 3\n    expect(obj.val).toBe(3) // make sure 'setter' was called\n    obj.val = 5\n    expect(obj.a).toBe(5) // make sure 'getter' was called\n  })\n\n  it('observing set/delete', () => {\n    const obj1 = { a: 1 }\n    const ob1 = observe(obj1)\n    const dep1 = ob1.dep\n    spyOn(dep1, 'notify')\n    setProp(obj1, 'b', 2)\n    expect(obj1.b).toBe(2)\n    expect(dep1.notify.calls.count()).toBe(1)\n    delProp(obj1, 'a')\n    expect(hasOwn(obj1, 'a')).toBe(false)\n    expect(dep1.notify.calls.count()).toBe(2)\n    // set existing key, should be a plain set and not\n    // trigger own ob's notify\n    setProp(obj1, 'b', 3)\n    expect(obj1.b).toBe(3)\n    expect(dep1.notify.calls.count()).toBe(2)\n    // set non-existing key\n    setProp(obj1, 'c', 1)\n    expect(obj1.c).toBe(1)\n    expect(dep1.notify.calls.count()).toBe(3)\n    // should ignore deleting non-existing key\n    delProp(obj1, 'a')\n    expect(dep1.notify.calls.count()).toBe(3)\n    // should work on non-observed objects\n    const obj2 = { a: 1 }\n    delProp(obj2, 'a')\n    expect(hasOwn(obj2, 'a')).toBe(false)\n    // should work on Object.create(null)\n    const obj3 = Object.create(null)\n    obj3.a = 1\n    const ob3 = observe(obj3)\n    const dep3 = ob3.dep\n    spyOn(dep3, 'notify')\n    setProp(obj3, 'b', 2)\n    expect(obj3.b).toBe(2)\n    expect(dep3.notify.calls.count()).toBe(1)\n    delProp(obj3, 'a')\n    expect(hasOwn(obj3, 'a')).toBe(false)\n    expect(dep3.notify.calls.count()).toBe(2)\n    // set and delete non-numeric key on array\n    const arr2 = ['a']\n    const ob2 = observe(arr2)\n    const dep2 = ob2.dep\n    spyOn(dep2, 'notify')\n    setProp(arr2, 'b', 2)\n    expect(arr2.b).toBe(2)\n    expect(dep2.notify.calls.count()).toBe(1)\n    delProp(arr2, 'b')\n    expect(hasOwn(arr2, 'b')).toBe(false)\n    expect(dep2.notify.calls.count()).toBe(2)\n  })\n\n  it('warning set/delete on a Vue instance', done => {\n    const vm = new Vue({\n      template: '<div>{{a}}</div>',\n      data: { a: 1 }\n    }).$mount()\n    expect(vm.$el.outerHTML).toBe('<div>1</div>')\n    Vue.set(vm, 'a', 2)\n    waitForUpdate(() => {\n      expect(vm.$el.outerHTML).toBe('<div>2</div>')\n      expect('Avoid adding reactive properties to a Vue instance').not.toHaveBeenWarned()\n      Vue.delete(vm, 'a')\n    }).then(() => {\n      expect('Avoid deleting properties on a Vue instance').toHaveBeenWarned()\n      expect(vm.$el.outerHTML).toBe('<div>2</div>')\n      Vue.set(vm, 'b', 123)\n      expect('Avoid adding reactive properties to a Vue instance').toHaveBeenWarned()\n    }).then(done)\n  })\n\n  it('warning set/delete on Vue instance root $data', done => {\n    const data = { a: 1 }\n    const vm = new Vue({\n      template: '<div>{{a}}</div>',\n      data\n    }).$mount()\n    expect(vm.$el.outerHTML).toBe('<div>1</div>')\n    expect(Vue.set(data, 'a', 2)).toBe(2)\n    waitForUpdate(() => {\n      expect(vm.$el.outerHTML).toBe('<div>2</div>')\n      expect('Avoid adding reactive properties to a Vue instance').not.toHaveBeenWarned()\n      Vue.delete(data, 'a')\n    }).then(() => {\n      expect('Avoid deleting properties on a Vue instance').toHaveBeenWarned()\n      expect(vm.$el.outerHTML).toBe('<div>2</div>')\n      expect(Vue.set(data, 'b', 123)).toBe(123)\n      expect('Avoid adding reactive properties to a Vue instance').toHaveBeenWarned()\n    }).then(done)\n  })\n\n  it('observing array mutation', () => {\n    const arr = []\n    const ob = observe(arr)\n    const dep = ob.dep\n    spyOn(dep, 'notify')\n    const objs = [{}, {}, {}]\n    arr.push(objs[0])\n    arr.pop()\n    arr.unshift(objs[1])\n    arr.shift()\n    arr.splice(0, 0, objs[2])\n    arr.sort()\n    arr.reverse()\n    expect(dep.notify.calls.count()).toBe(7)\n    // inserted elements should be observed\n    objs.forEach(obj => {\n      expect(obj.__ob__ instanceof Observer).toBe(true)\n    })\n  })\n})\n"
  },
  {
    "path": "test/unit/modules/observer/scheduler.spec.js",
    "content": "import Vue from 'vue'\nimport {\n  MAX_UPDATE_COUNT,\n  queueWatcher as _queueWatcher\n} from 'core/observer/scheduler'\n\nfunction queueWatcher (watcher) {\n  watcher.vm = {} // mock vm\n  _queueWatcher(watcher)\n}\n\ndescribe('Scheduler', () => {\n  let spy\n  beforeEach(() => {\n    spy = jasmine.createSpy('scheduler')\n  })\n\n  it('queueWatcher', done => {\n    queueWatcher({\n      run: spy\n    })\n    waitForUpdate(() => {\n      expect(spy.calls.count()).toBe(1)\n    }).then(done)\n  })\n\n  it('dedup', done => {\n    queueWatcher({\n      id: 1,\n      run: spy\n    })\n    queueWatcher({\n      id: 1,\n      run: spy\n    })\n    waitForUpdate(() => {\n      expect(spy.calls.count()).toBe(1)\n    }).then(done)\n  })\n\n  it('allow duplicate when flushing', done => {\n    const job = {\n      id: 1,\n      run: spy\n    }\n    queueWatcher(job)\n    queueWatcher({\n      id: 2,\n      run () { queueWatcher(job) }\n    })\n    waitForUpdate(() => {\n      expect(spy.calls.count()).toBe(2)\n    }).then(done)\n  })\n\n  it('call user watchers before component re-render', done => {\n    const calls = []\n    const vm = new Vue({\n      data: {\n        a: 1\n      },\n      template: '<div>{{ a }}</div>',\n      watch: {\n        a () { calls.push(1) }\n      },\n      beforeUpdate () {\n        calls.push(2)\n      }\n    }).$mount()\n    vm.a = 2\n    waitForUpdate(() => {\n      expect(calls).toEqual([1, 2])\n    }).then(done)\n  })\n\n  it('call user watcher triggered by component re-render immediately', done => {\n    // this happens when a component re-render updates the props of a child\n    const calls = []\n    const vm = new Vue({\n      data: {\n        a: 1\n      },\n      watch: {\n        a () {\n          calls.push(1)\n        }\n      },\n      beforeUpdate () {\n        calls.push(2)\n      },\n      template: '<div><test :a=\"a\"></test></div>',\n      components: {\n        test: {\n          props: ['a'],\n          template: '<div>{{ a }}</div>',\n          watch: {\n            a () {\n              calls.push(3)\n            }\n          },\n          beforeUpdate () {\n            calls.push(4)\n          }\n        }\n      }\n    }).$mount()\n    vm.a = 2\n    waitForUpdate(() => {\n      expect(calls).toEqual([1, 2, 3, 4])\n    }).then(done)\n  })\n\n  it('warn against infinite update loops', function (done) {\n    let count = 0\n    const job = {\n      id: 1,\n      run () {\n        count++\n        queueWatcher(job)\n      }\n    }\n    queueWatcher(job)\n    waitForUpdate(() => {\n      expect(count).toBe(MAX_UPDATE_COUNT + 1)\n      expect('infinite update loop').toHaveBeenWarned()\n    }).then(done)\n  })\n\n  it('should call newly pushed watcher after current watcher is done', done => {\n    const callOrder = []\n    queueWatcher({\n      id: 1,\n      user: true,\n      run () {\n        callOrder.push(1)\n        queueWatcher({\n          id: 2,\n          run () {\n            callOrder.push(3)\n          }\n        })\n        callOrder.push(2)\n      }\n    })\n    waitForUpdate(() => {\n      expect(callOrder).toEqual([1, 2, 3])\n    }).then(done)\n  })\n\n  // Github issue #5191\n  it('emit should work when updated hook called', done => {\n    const el = document.createElement('div')\n    const vm = new Vue({\n      template: `<div><child @change=\"bar\" :foo=\"foo\"></child></div>`,\n      data: {\n        foo: 0\n      },\n      methods: {\n        bar: spy\n      },\n      components: {\n        child: {\n          template: `<div>{{foo}}</div>`,\n          props: ['foo'],\n          updated () {\n            this.$emit('change')\n          }\n        }\n      }\n    }).$mount(el)\n    vm.$nextTick(() => {\n      vm.foo = 1\n      vm.$nextTick(() => {\n        expect(vm.$el.innerHTML).toBe('<div>1</div>')\n        expect(spy).toHaveBeenCalled()\n        done()\n      })\n    })\n  })\n})\n"
  },
  {
    "path": "test/unit/modules/observer/watcher.spec.js",
    "content": "import Vue from 'vue'\nimport Watcher from 'core/observer/watcher'\n\ndescribe('Watcher', () => {\n  let vm, spy\n  beforeEach(() => {\n    vm = new Vue({\n      template: '<div></div>',\n      data: {\n        a: 1,\n        b: {\n          c: 2,\n          d: 4\n        },\n        c: 'c',\n        msg: 'yo'\n      }\n    }).$mount()\n    spy = jasmine.createSpy('watcher')\n  })\n\n  it('path', done => {\n    const watcher = new Watcher(vm, 'b.c', spy)\n    expect(watcher.value).toBe(2)\n    vm.b.c = 3\n    waitForUpdate(() => {\n      expect(watcher.value).toBe(3)\n      expect(spy).toHaveBeenCalledWith(3, 2)\n      vm.b = { c: 4 } // swapping the object\n    }).then(() => {\n      expect(watcher.value).toBe(4)\n      expect(spy).toHaveBeenCalledWith(4, 3)\n    }).then(done)\n  })\n\n  it('non-existent path, set later', done => {\n    const watcher1 = new Watcher(vm, 'b.e', spy)\n    expect(watcher1.value).toBeUndefined()\n    // check $add should not affect isolated children\n    const child2 = new Vue({ parent: vm })\n    const watcher2 = new Watcher(child2, 'b.e', spy)\n    expect(watcher2.value).toBeUndefined()\n    Vue.set(vm.b, 'e', 123)\n    waitForUpdate(() => {\n      expect(watcher1.value).toBe(123)\n      expect(watcher2.value).toBeUndefined()\n      expect(spy.calls.count()).toBe(1)\n      expect(spy).toHaveBeenCalledWith(123, undefined)\n    }).then(done)\n  })\n\n  it('delete', done => {\n    const watcher = new Watcher(vm, 'b.c', spy)\n    expect(watcher.value).toBe(2)\n    Vue.delete(vm.b, 'c')\n    waitForUpdate(() => {\n      expect(watcher.value).toBeUndefined()\n      expect(spy).toHaveBeenCalledWith(undefined, 2)\n    }).then(done)\n  })\n\n  it('path containing $data', done => {\n    const watcher = new Watcher(vm, '$data.b.c', spy)\n    expect(watcher.value).toBe(2)\n    vm.b = { c: 3 }\n    waitForUpdate(() => {\n      expect(watcher.value).toBe(3)\n      expect(spy).toHaveBeenCalledWith(3, 2)\n      vm.$data.b.c = 4\n    }).then(() => {\n      expect(watcher.value).toBe(4)\n      expect(spy).toHaveBeenCalledWith(4, 3)\n    }).then(done)\n  })\n\n  it('deep watch', done => {\n    let oldB\n    new Watcher(vm, 'b', spy, {\n      deep: true\n    })\n    vm.b.c = { d: 4 }\n    waitForUpdate(() => {\n      expect(spy).toHaveBeenCalledWith(vm.b, vm.b)\n      oldB = vm.b\n      vm.b = { c: [{ a: 1 }] }\n    }).then(() => {\n      expect(spy).toHaveBeenCalledWith(vm.b, oldB)\n      expect(spy.calls.count()).toBe(2)\n      vm.b.c[0].a = 2\n    }).then(() => {\n      expect(spy).toHaveBeenCalledWith(vm.b, vm.b)\n      expect(spy.calls.count()).toBe(3)\n    }).then(done)\n  })\n\n  it('deep watch $data', done => {\n    new Watcher(vm, '$data', spy, {\n      deep: true\n    })\n    vm.b.c = 3\n    waitForUpdate(() => {\n      expect(spy).toHaveBeenCalledWith(vm.$data, vm.$data)\n    }).then(done)\n  })\n\n  it('deep watch with circular references', done => {\n    new Watcher(vm, 'b', spy, {\n      deep: true\n    })\n    Vue.set(vm.b, '_', vm.b)\n    waitForUpdate(() => {\n      expect(spy).toHaveBeenCalledWith(vm.b, vm.b)\n      expect(spy.calls.count()).toBe(1)\n      vm.b._.c = 1\n    }).then(() => {\n      expect(spy).toHaveBeenCalledWith(vm.b, vm.b)\n      expect(spy.calls.count()).toBe(2)\n    }).then(done)\n  })\n\n  it('fire change for prop addition/deletion in non-deep mode', done => {\n    new Watcher(vm, 'b', spy)\n    Vue.set(vm.b, 'e', 123)\n    waitForUpdate(() => {\n      expect(spy).toHaveBeenCalledWith(vm.b, vm.b)\n      expect(spy.calls.count()).toBe(1)\n      Vue.delete(vm.b, 'e')\n    }).then(() => {\n      expect(spy.calls.count()).toBe(2)\n    }).then(done)\n  })\n\n  it('watch function', done => {\n    const watcher = new Watcher(vm, function () {\n      return this.a + this.b.d\n    }, spy)\n    expect(watcher.value).toBe(5)\n    vm.a = 2\n    waitForUpdate(() => {\n      expect(spy).toHaveBeenCalledWith(6, 5)\n      vm.b = { d: 2 }\n    }).then(() => {\n      expect(spy).toHaveBeenCalledWith(4, 6)\n    }).then(done)\n  })\n\n  it('lazy mode', done => {\n    const watcher = new Watcher(vm, function () {\n      return this.a + this.b.d\n    }, null, { lazy: true })\n    expect(watcher.lazy).toBe(true)\n    expect(watcher.value).toBeUndefined()\n    expect(watcher.dirty).toBe(true)\n    watcher.evaluate()\n    expect(watcher.value).toBe(5)\n    expect(watcher.dirty).toBe(false)\n    vm.a = 2\n    waitForUpdate(() => {\n      expect(watcher.value).toBe(5)\n      expect(watcher.dirty).toBe(true)\n      watcher.evaluate()\n      expect(watcher.value).toBe(6)\n      expect(watcher.dirty).toBe(false)\n    }).then(done)\n  })\n\n  it('teardown', done => {\n    const watcher = new Watcher(vm, 'b.c', spy)\n    watcher.teardown()\n    vm.b.c = 3\n    waitForUpdate(() => {\n      expect(watcher.active).toBe(false)\n      expect(spy).not.toHaveBeenCalled()\n    }).then(done)\n  })\n\n  it('warn not support path', () => {\n    new Watcher(vm, 'd.e + c', spy)\n    expect('Failed watching path:').toHaveBeenWarned()\n  })\n})\n"
  },
  {
    "path": "test/unit/modules/server-compiler/optimizer.spec.js",
    "content": ""
  },
  {
    "path": "test/unit/modules/sfc/sfc-parser.spec.js",
    "content": "import { parseComponent } from 'sfc/parser'\n\ndescribe('Single File Component parser', () => {\n  it('should parse', () => {\n    const res = parseComponent(`\n      <template>\n        <div>hi</div>\n      </template>\n      <style src=\"./test.css\"></style>\n      <style lang=\"stylus\" scoped>\n        h1\n          color red\n        h2\n          color green\n      </style>\n      <style module>\n        h1 { font-weight: bold }\n      </style>\n      <style bool-attr val-attr=\"test\"></style>\n      <script>\n        export default {}\n      </script>\n      <div>\n        <style>nested should be ignored</style>\n      </div>\n    `)\n    expect(res.template.content.trim()).toBe('<div>hi</div>')\n    expect(res.styles.length).toBe(4)\n    expect(res.styles[0].src).toBe('./test.css')\n    expect(res.styles[1].lang).toBe('stylus')\n    expect(res.styles[1].scoped).toBe(true)\n    expect(res.styles[1].content.trim()).toBe('h1\\n  color red\\nh2\\n  color green')\n    expect(res.styles[2].module).toBe(true)\n    expect(res.styles[3].attrs['bool-attr']).toBe(true)\n    expect(res.styles[3].attrs['val-attr']).toBe('test')\n    expect(res.script.content.trim()).toBe('export default {}')\n  })\n\n  it('should parse template with closed input', () => {\n    const res = parseComponent(`\n      <template>\n        <input type=\"text\"/>\n      </template>\n    `)\n\n    expect(res.template.content.trim()).toBe('<input type=\"text\"/>')\n  })\n\n  it('should handle nested template', () => {\n    const res = parseComponent(`\n      <template>\n        <div><template v-if=\"ok\">hi</template></div>\n      </template>\n    `)\n    expect(res.template.content.trim()).toBe('<div><template v-if=\"ok\">hi</template></div>')\n  })\n\n  it('pad content', () => {\n    const content = `\n      <template>\n        <div></div>\n      </template>\n      <script>\n        export default {}\n      </script>\n      <style>\n        h1 { color: red }\n      </style>\n`\n    const padDefault = parseComponent(content.trim(), { pad: true })\n    const padLine = parseComponent(content.trim(), { pad: 'line' })\n    const padSpace = parseComponent(content.trim(), { pad: 'space' })\n\n    expect(padDefault.script.content).toBe(Array(3 + 1).join('//\\n') + '\\nexport default {}\\n')\n    expect(padDefault.styles[0].content).toBe(Array(6 + 1).join('\\n') + '\\nh1 { color: red }\\n')\n    expect(padLine.script.content).toBe(Array(3 + 1).join('//\\n') + '\\nexport default {}\\n')\n    expect(padLine.styles[0].content).toBe(Array(6 + 1).join('\\n') + '\\nh1 { color: red }\\n')\n    expect(padSpace.script.content).toBe(`<template>\n        <div></div>\n      </template>\n      <script>`.replace(/./g, ' ') + '\\nexport default {}\\n')\n    expect(padSpace.styles[0].content).toBe(`<template>\n        <div></div>\n      </template>\n      <script>\n        export default {}\n      </script>\n      <style>`.replace(/./g, ' ') + '\\nh1 { color: red }\\n')\n  })\n\n  it('should handle template blocks with lang as special text', () => {\n    const res = parseComponent(`\n      <template lang=\"pug\">\n        div\n          h1(v-if='1 < 2') hello\n      </template>\n    `)\n    expect(res.template.content.trim()).toBe(`div\\n  h1(v-if='1 < 2') hello`)\n  })\n\n  it('should handle component contains \"<\" only', () => {\n    const res = parseComponent(`\n      <template>\n        <span><</span>\n      </template>\n    `)\n    expect(res.template.content.trim()).toBe(`<span><</span>`)\n  })\n\n  it('should handle custom blocks without parsing them', () => {\n    const res = parseComponent(`\n      <template>\n        <div></div>\n      </template>\n      <example name=\"simple\">\n        <my-button ref=\"button\">Hello</my-button>\n      </example>\n      <example name=\"with props\">\n        <my-button color=\"red\">Hello</my-button>\n      </example>\n      <test name=\"simple\" foo=\"bar\">\n      export default function simple (vm) {\n        describe('Hello', () => {\n          it('should display Hello', () => {\n            this.vm.$refs.button.$el.innerText.should.equal('Hello')\n          }))\n        }))\n      }\n      </test>\n    `)\n    expect(res.customBlocks.length).toBe(3)\n\n    const simpleExample = res.customBlocks[0]\n    expect(simpleExample.type).toBe('example')\n    expect(simpleExample.content.trim()).toBe('<my-button ref=\"button\">Hello</my-button>')\n    expect(simpleExample.attrs.name).toBe('simple')\n\n    const withProps = res.customBlocks[1]\n    expect(withProps.type).toBe('example')\n    expect(withProps.content.trim()).toBe('<my-button color=\"red\">Hello</my-button>')\n    expect(withProps.attrs.name).toBe('with props')\n\n    const simpleTest = res.customBlocks[2]\n    expect(simpleTest.type).toBe('test')\n    expect(simpleTest.content.trim()).toBe(`export default function simple (vm) {\n  describe('Hello', () => {\n    it('should display Hello', () => {\n      this.vm.$refs.button.$el.innerText.should.equal('Hello')\n    }))\n  }))\n}`)\n    expect(simpleTest.attrs.name).toBe('simple')\n    expect(simpleTest.attrs.foo).toBe('bar')\n  })\n\n  // Regression #4289\n  it('accepts nested template tag', () => {\n    const raw = `<div>\n      <template v-if=\"true === true\">\n        <section class=\"section\">\n          <div class=\"container\">\n            Should be shown\n          </div>\n        </section>\n      </template>\n      <template v-else>\n        <p>Should not be shown</p>\n      </template>\n    </div>`\n    const res = parseComponent(`<template>${raw}</template>`)\n    expect(res.template.content.trim()).toBe(raw)\n  })\n\n  it('should not hang on trailing text', () => {\n    const res = parseComponent(`<template>hi</`)\n    expect(res.template.content).toBe('hi')\n  })\n})\n"
  },
  {
    "path": "test/unit/modules/util/next-tick.spec.js",
    "content": "import { nextTick } from 'core/util/env'\n\ndescribe('nextTick', () => {\n  it('accepts a callback', done => {\n    nextTick(done)\n  })\n\n  it('returns undefined when passed a callback', () => {\n    expect(nextTick(() => {})).toBeUndefined()\n  })\n\n  if (typeof Promise !== 'undefined') {\n    it('returns a Promise when provided no callback', done => {\n      nextTick().then(done)\n    })\n\n    it('returns a Promise with a context argument when provided a falsy callback and an object', done => {\n      const obj = {}\n      nextTick(undefined, obj).then(ctx => {\n        expect(ctx).toBe(obj)\n        done()\n      })\n    })\n\n    it('returned Promise should resolve correctly vs callback', done => {\n      const spy = jasmine.createSpy()\n      nextTick(spy)\n      nextTick().then(() => {\n        expect(spy).toHaveBeenCalled()\n        done()\n      })\n    })\n  }\n})\n"
  },
  {
    "path": "test/unit/modules/vdom/create-component.spec.js",
    "content": "import Vue from 'vue'\nimport { createComponent } from 'core/vdom/create-component'\n\ndescribe('create-component', () => {\n  let vm\n  beforeEach(done => {\n    vm = new Vue({\n      template: '<p>{{msg}}</p>',\n      data () {\n        return { msg: 'hello, my children' }\n      }\n    }).$mount()\n    Vue.nextTick(done)\n  })\n\n  it('create a component basically', () => {\n    const child = {\n      name: 'child',\n      props: ['msg'],\n      render () {}\n    }\n    const init = jasmine.createSpy()\n    const data = {\n      props: { msg: 'hello world' },\n      attrs: { id: 1 },\n      staticAttrs: { class: 'foo' },\n      hook: { init },\n      on: { notify: 'onNotify' }\n    }\n    const vnode = createComponent(child, data, vm, vm)\n    expect(vnode.tag).toMatch(/vue-component-[0-9]+-child/)\n    expect(vnode.data.attrs).toEqual({ id: 1 })\n    expect(vnode.data.staticAttrs).toEqual({ class: 'foo' })\n    expect(vnode.componentOptions.propsData).toEqual({ msg: 'hello world' })\n    expect(vnode.componentOptions.listeners).toEqual({ notify: 'onNotify' })\n    expect(vnode.children).toBeUndefined()\n    expect(vnode.text).toBeUndefined()\n    expect(vnode.elm).toBeUndefined()\n    expect(vnode.ns).toBeUndefined()\n    expect(vnode.context).toEqual(vm)\n\n    vnode.data.hook.init(vnode)\n    expect(init.calls.argsFor(0)[0]).toBe(vnode)\n  })\n\n  it('create a component when resolved with async loading', done => {\n    let vnode = null\n    const data = {\n      props: {},\n      staticAttrs: { class: 'foo' }\n    }\n    spyOn(vm, '$forceUpdate')\n    function async (resolve, reject) {\n      setTimeout(() => {\n        resolve({\n          name: 'child',\n          props: ['msg']\n        })\n        Vue.nextTick(loaded)\n      }, 0)\n    }\n    function go () {\n      vnode = createComponent(async, data, vm, vm)\n      expect(vnode.isComment).toBe(true) // not to be loaded yet.\n      expect(vnode.asyncFactory).toBe(async)\n    }\n    function loaded () {\n      vnode = createComponent(async, data, vm, vm)\n      expect(vnode.tag).toMatch(/vue-component-[0-9]+-child/)\n      expect(vnode.data.staticAttrs).toEqual({ class: 'foo' })\n      expect(vnode.children).toBeUndefined()\n      expect(vnode.text).toBeUndefined()\n      expect(vnode.elm).toBeUndefined()\n      expect(vnode.ns).toBeUndefined()\n      expect(vnode.context).toEqual(vm)\n      expect(vm.$forceUpdate).toHaveBeenCalled()\n      done()\n    }\n    go()\n  })\n\n  it('not create a component when rejected with async loading', done => {\n    let vnode = null\n    const data = {\n      props: { msg: 'hello world' },\n      attrs: { id: 1 }\n    }\n    const reason = 'failed!!'\n    function async (resolve, reject) {\n      setTimeout(() => {\n        reject(reason)\n        Vue.nextTick(failed)\n      }, 0)\n    }\n    function go () {\n      vnode = createComponent(async, data, vm, vm)\n      expect(vnode.isComment).toBe(true) // not to be loaded yet.\n    }\n    function failed () {\n      vnode = createComponent(async, data, vm, vm)\n      expect(vnode.isComment).toBe(true) // failed, still a comment node\n      expect(`Failed to resolve async component: ${async}\\nReason: ${reason}`).toHaveBeenWarned()\n      done()\n    }\n    go()\n  })\n\n  it('not create a component when specified with falsy', () => {\n    const vnode = createComponent(null, {}, vm, vm)\n    expect(vnode).toBeUndefined()\n  })\n\n  it('warn component definition type', () => {\n    const Ctor = 'child'\n    const vnode = createComponent(Ctor, {}, vm, vm)\n    expect(vnode).toBeUndefined()\n    expect(`Invalid Component definition: ${Ctor}`).toHaveBeenWarned()\n  })\n})\n"
  },
  {
    "path": "test/unit/modules/vdom/create-element.spec.js",
    "content": "import Vue from 'vue'\nimport { createEmptyVNode } from 'core/vdom/vnode'\n\ndescribe('create-element', () => {\n  it('render vnode with basic reserved tag using createElement', () => {\n    const vm = new Vue({\n      data: { msg: 'hello world' }\n    })\n    const h = vm.$createElement\n    const vnode = h('p', {})\n    expect(vnode.tag).toBe('p')\n    expect(vnode.data).toEqual({})\n    expect(vnode.children).toBeUndefined()\n    expect(vnode.text).toBeUndefined()\n    expect(vnode.elm).toBeUndefined()\n    expect(vnode.ns).toBeUndefined()\n    expect(vnode.context).toEqual(vm)\n  })\n\n  it('render vnode with component using createElement', () => {\n    const vm = new Vue({\n      data: { message: 'hello world' },\n      components: {\n        'my-component': {\n          props: ['msg']\n        }\n      }\n    })\n    const h = vm.$createElement\n    const vnode = h('my-component', { props: { msg: vm.message }})\n    expect(vnode.tag).toMatch(/vue-component-[0-9]+/)\n    expect(vnode.componentOptions.propsData).toEqual({ msg: vm.message })\n    expect(vnode.children).toBeUndefined()\n    expect(vnode.text).toBeUndefined()\n    expect(vnode.elm).toBeUndefined()\n    expect(vnode.ns).toBeUndefined()\n    expect(vnode.context).toEqual(vm)\n  })\n\n  it('render vnode with custom tag using createElement', () => {\n    const vm = new Vue({\n      data: { msg: 'hello world' }\n    })\n    const h = vm.$createElement\n    const tag = 'custom-tag'\n    const vnode = h(tag, {})\n    expect(vnode.tag).toBe('custom-tag')\n    expect(vnode.data).toEqual({})\n    expect(vnode.children).toBeUndefined()\n    expect(vnode.text).toBeUndefined()\n    expect(vnode.elm).toBeUndefined()\n    expect(vnode.ns).toBeUndefined()\n    expect(vnode.context).toEqual(vm)\n    expect(vnode.componentOptions).toBeUndefined()\n  })\n\n  it('render empty vnode with falsy tag using createElement', () => {\n    const vm = new Vue({\n      data: { msg: 'hello world' }\n    })\n    const h = vm.$createElement\n    const vnode = h(null, {})\n    expect(vnode).toEqual(createEmptyVNode())\n  })\n\n  it('render vnode with not string tag using createElement', () => {\n    const vm = new Vue({\n      data: { msg: 'hello world' }\n    })\n    const h = vm.$createElement\n    const vnode = h(Vue.extend({ // Component class\n      props: ['msg']\n    }), { props: { msg: vm.message }})\n    expect(vnode.tag).toMatch(/vue-component-[0-9]+/)\n    expect(vnode.componentOptions.propsData).toEqual({ msg: vm.message })\n    expect(vnode.children).toBeUndefined()\n    expect(vnode.text).toBeUndefined()\n    expect(vnode.elm).toBeUndefined()\n    expect(vnode.ns).toBeUndefined()\n    expect(vnode.context).toEqual(vm)\n  })\n\n  it('render vnode with createElement with children', () => {\n    const vm = new Vue({})\n    const h = vm.$createElement\n    const vnode = h('p', void 0, [h('br'), 'hello world', h('br')])\n    expect(vnode.children[0].tag).toBe('br')\n    expect(vnode.children[1].text).toBe('hello world')\n    expect(vnode.children[2].tag).toBe('br')\n  })\n\n  it('render vnode with children, omitting data', () => {\n    const vm = new Vue({})\n    const h = vm.$createElement\n    const vnode = h('p', [h('br'), 'hello world', h('br')])\n    expect(vnode.children[0].tag).toBe('br')\n    expect(vnode.children[1].text).toBe('hello world')\n    expect(vnode.children[2].tag).toBe('br')\n  })\n\n  it('render vnode with children, including boolean and null type', () => {\n    const vm = new Vue({})\n    const h = vm.$createElement\n    const vnode = h('p', [h('br'), true, 123, h('br'), 'abc', null])\n    expect(vnode.children.length).toBe(4)\n    expect(vnode.children[0].tag).toBe('br')\n    expect(vnode.children[1].text).toBe('123')\n    expect(vnode.children[2].tag).toBe('br')\n    expect(vnode.children[3].text).toBe('abc')\n  })\n\n  it('render svg elements with correct namespace', () => {\n    const vm = new Vue({})\n    const h = vm.$createElement\n    const vnode = h('svg', [h('a', [h('foo', [h('bar')])])])\n    expect(vnode.ns).toBe('svg')\n    // should apply ns to children recursively\n    expect(vnode.children[0].ns).toBe('svg')\n    expect(vnode.children[0].children[0].ns).toBe('svg')\n    expect(vnode.children[0].children[0].children[0].ns).toBe('svg')\n  })\n\n  it('render MathML elements with correct namespace', () => {\n    const vm = new Vue({})\n    const h = vm.$createElement\n    const vnode = h('math', [h('matrix')])\n    expect(vnode.ns).toBe('math')\n    // should apply ns to children\n    expect(vnode.children[0].ns).toBe('math')\n    // although not explicitly listed, elements nested under <math>\n    // should not be treated as component\n    expect(vnode.children[0].componentOptions).toBeUndefined()\n  })\n\n  it('render svg foreignObject with correct namespace', () => {\n    const vm = new Vue({})\n    const h = vm.$createElement\n    const vnode = h('svg', [h('foreignObject', [h('p')])])\n    expect(vnode.ns).toBe('svg')\n    expect(vnode.children[0].ns).toBe('svg')\n    expect(vnode.children[0].children[0].ns).toBeUndefined()\n  })\n\n  it('warn observed data objects', () => {\n    new Vue({\n      data: {\n        data: {}\n      },\n      render (h) {\n        return h('div', this.data)\n      }\n    }).$mount()\n    expect('Avoid using observed data object as vnode data').toHaveBeenWarned()\n  })\n\n  it('warn non-primitive key', () => {\n    new Vue({\n      render (h) {\n        return h('div', { key: {}})\n      }\n    }).$mount()\n    expect('Avoid using non-primitive value as key').toHaveBeenWarned()\n  })\n\n  it('nested child elements should be updated correctly', done => {\n    const vm = new Vue({\n      data: { n: 1 },\n      render (h) {\n        const list = []\n        for (let i = 0; i < this.n; i++) {\n          list.push(h('span', i))\n        }\n        const input = h('input', {\n          attrs: {\n            value: 'a',\n            type: 'text'\n          }\n        })\n        return h('div', [[...list, input]])\n      }\n    }).$mount()\n    expect(vm.$el.innerHTML).toContain('<span>0</span><input')\n    const el = vm.$el.querySelector('input')\n    el.value = 'b'\n    vm.n++\n    waitForUpdate(() => {\n      expect(vm.$el.innerHTML).toContain('<span>0</span><span>1</span><input')\n      expect(vm.$el.querySelector('input')).toBe(el)\n      expect(vm.$el.querySelector('input').value).toBe('b')\n    }).then(done)\n  })\n})\n"
  },
  {
    "path": "test/unit/modules/vdom/modules/attrs.spec.js",
    "content": "import Vue from 'vue'\nimport { patch } from 'web/runtime/patch'\nimport VNode from 'core/vdom/vnode'\nimport { xlinkNS } from 'web/util/index'\n\ndescribe('vdom attrs module', () => {\n  it('should create an element with attrs', () => {\n    const vnode = new VNode('p', { attrs: { id: 1, class: 'class1' }})\n    const elm = patch(null, vnode)\n    expect(elm.id).toBe('1')\n    expect(elm).toHaveClass('class1')\n  })\n\n  it('should change the elements attrs', () => {\n    const vnode1 = new VNode('i', { attrs: { id: '1', class: 'i am vdom' }})\n    const vnode2 = new VNode('i', { attrs: { id: '2', class: 'i am' }})\n    patch(null, vnode1)\n    const elm = patch(vnode1, vnode2)\n    expect(elm.id).toBe('2')\n    expect(elm).toHaveClass('i')\n    expect(elm).toHaveClass('am')\n    expect(elm).not.toHaveClass('vdom')\n  })\n\n  it('should remove the elements attrs', () => {\n    const vnode1 = new VNode('i', { attrs: { id: '1', class: 'i am vdom' }})\n    const vnode2 = new VNode('i', { attrs: { id: '1' }})\n    patch(null, vnode1)\n    const elm = patch(vnode1, vnode2)\n    expect(elm.id).toBe('1')\n    expect(elm.className).toBe('')\n  })\n\n  it('should remove the elements attrs for new nodes without attrs data', () => {\n    const vnode1 = new VNode('i', { attrs: { id: '1', class: 'i am vdom' }})\n    const vnode2 = new VNode('i', {})\n    patch(null, vnode1)\n    const elm = patch(vnode1, vnode2)\n    expect(elm.id).toBe('')\n    expect(elm.className).toBe('')\n  })\n\n  it('should remove the falsy value from boolean attr', () => {\n    const vnode = new VNode('option', { attrs: { disabled: null }})\n    const elm = patch(null, vnode)\n    expect(elm.getAttribute('disabled')).toBe(null)\n  })\n\n  it('should set the attr name to boolean attr', () => {\n    const vnode = new VNode('option', { attrs: { disabled: true }})\n    const elm = patch(null, vnode)\n    expect(elm.getAttribute('disabled')).toBe('disabled')\n  })\n\n  it('should set the falsy value to enumerated attr', () => {\n    const vnode = new VNode('div', { attrs: { contenteditable: null }})\n    const elm = patch(null, vnode)\n    expect(elm.getAttribute('contenteditable')).toBe('false')\n  })\n\n  it('should set the boolean string value to enumerated attr', () => {\n    const vnode = new VNode('div', { attrs: { contenteditable: 'true' }})\n    const elm = patch(null, vnode)\n    expect(elm.getAttribute('contenteditable')).toBe('true')\n  })\n\n  it('should set the xlink value to attr', () => {\n    const vnode = new VNode('a', { attrs: { 'xlink:href': '#id1' }})\n    const elm = patch(null, vnode)\n    expect(elm.getAttributeNS(xlinkNS, 'href')).toBe('#id1')\n  })\n\n  it('should set the xlink boolean string value to attr', () => {\n    const vnode = new VNode('option', { attrs: { 'xlink:disabled': true }})\n    const elm = patch(null, vnode)\n    expect(elm.getAttributeNS(xlinkNS, 'disabled')).toBe('true')\n  })\n\n  it('should handle mutating observed attrs object', done => {\n    const vm = new Vue({\n      data: {\n        attrs: {\n          id: 'foo'\n        }\n      },\n      render (h) {\n        return h('div', {\n          attrs: this.attrs\n        })\n      }\n    }).$mount()\n\n    expect(vm.$el.id).toBe('foo')\n    vm.attrs.id = 'bar'\n    waitForUpdate(() => {\n      expect(vm.$el.id).toBe('bar')\n      vm.attrs = { id: 'baz' }\n    }).then(() => {\n      expect(vm.$el.id).toBe('baz')\n    }).then(done)\n  })\n})\n"
  },
  {
    "path": "test/unit/modules/vdom/modules/class.spec.js",
    "content": "import { patch } from 'web/runtime/patch'\nimport VNode from 'core/vdom/vnode'\n\ndescribe('vdom class module', () => {\n  it('should create an element with staticClass', () => {\n    const vnode = new VNode('p', { staticClass: 'class1' })\n    const elm = patch(null, vnode)\n    expect(elm).toHaveClass('class1')\n  })\n\n  it('should create an element with class', () => {\n    const vnode = new VNode('p', { class: 'class1' })\n    const elm = patch(null, vnode)\n    expect(elm).toHaveClass('class1')\n  })\n\n  it('should create an element with array class', () => {\n    const vnode = new VNode('p', { class: ['class1', 'class2'] })\n    const elm = patch(null, vnode)\n    expect(elm).toHaveClass('class1')\n    expect(elm).toHaveClass('class2')\n  })\n\n  it('should create an element with object class', () => {\n    const vnode = new VNode('p', {\n      class: { class1: true, class2: false, class3: true }\n    })\n    const elm = patch(null, vnode)\n    expect(elm).toHaveClass('class1')\n    expect(elm).not.toHaveClass('class2')\n    expect(elm).toHaveClass('class3')\n  })\n\n  it('should create an element with mixed class', () => {\n    const vnode = new VNode('p', {\n      class: [{ class1: false, class2: true, class3: false }, 'class4', ['class5', 'class6']]\n    })\n    const elm = patch(null, vnode)\n    expect(elm).not.toHaveClass('class1')\n    expect(elm).toHaveClass('class2')\n    expect(elm).not.toHaveClass('class3')\n    expect(elm).toHaveClass('class4')\n    expect(elm).toHaveClass('class5')\n    expect(elm).toHaveClass('class6')\n  })\n\n  it('should create an element with staticClass and class', () => {\n    const vnode = new VNode('p', { staticClass: 'class1', class: 'class2' })\n    const elm = patch(null, vnode)\n    expect(elm).toHaveClass('class1')\n    expect(elm).toHaveClass('class2')\n  })\n\n  it('should handle transition class', () => {\n    const vnode1 = new VNode('p', {\n      class: { class1: true, class2: false, class3: true }\n    })\n    let elm = patch(null, vnode1)\n    elm._transitionClasses = ['class4']\n    const vnode2 = new VNode('p', {\n      class: { class1: true, class2: true, class3: true }\n    })\n    elm = patch(vnode1, vnode2)\n    expect(elm).toHaveClass('class1')\n    expect(elm).toHaveClass('class2')\n    expect(elm).toHaveClass('class3')\n    expect(elm).toHaveClass('class4')\n  })\n\n  it('should change the elements class', () => {\n    const vnode1 = new VNode('p', {\n      class: { class1: true, class2: false, class3: true }\n    })\n    const vnode2 = new VNode('p', { staticClass: 'foo bar' })\n    let elm = patch(null, vnode1)\n    elm = patch(vnode1, vnode2)\n    expect(elm).not.toHaveClass('class1')\n    expect(elm).not.toHaveClass('class2')\n    expect(elm).not.toHaveClass('class3')\n    expect(elm).toHaveClass('foo')\n    expect(elm).toHaveClass('bar')\n  })\n\n  it('should remove the elements class', () => {\n    const vnode1 = new VNode('p', {\n      class: { class1: true, class2: false, class3: true }\n    })\n    const vnode2 = new VNode('p', { class: {}})\n    let elm = patch(null, vnode1)\n    elm = patch(vnode1, vnode2)\n    expect(elm).not.toHaveClass('class1')\n    expect(elm).not.toHaveClass('class2')\n    expect(elm).not.toHaveClass('class3')\n  })\n\n  it('should remove class for new nodes without class data', () => {\n    const vnode1 = new VNode('p', {\n      class: { class1: true, class2: false, class3: true }\n    })\n    const vnode2 = new VNode('p', {})\n    let elm = patch(null, vnode1)\n    elm = patch(vnode1, vnode2)\n    expect(elm).not.toHaveClass('class1')\n    expect(elm).not.toHaveClass('class2')\n    expect(elm).not.toHaveClass('class3')\n  })\n})\n"
  },
  {
    "path": "test/unit/modules/vdom/modules/directive.spec.js",
    "content": "import Vue from 'vue'\nimport { patch } from 'web/runtime/patch'\nimport VNode from 'core/vdom/vnode'\n\ndescribe('vdom directive module', () => {\n  it('should work', () => {\n    const directive1 = {\n      bind: jasmine.createSpy('bind'),\n      update: jasmine.createSpy('update'),\n      unbind: jasmine.createSpy('unbind')\n    }\n    const vm = new Vue({ directives: { directive1 }})\n    // create\n    const vnode1 = new VNode('div', {}, [\n      new VNode('p', {\n        directives: [{\n          name: 'directive1', value: 'hello', arg: 'arg1', modifiers: { modifire1: true }\n        }]\n      }, undefined, 'hello world', undefined, vm)\n    ])\n    patch(null, vnode1)\n    expect(directive1.bind).toHaveBeenCalled()\n    // update\n    const vnode2 = new VNode('div', {}, [\n      new VNode('p', {\n        directives: [{\n          name: 'directive1', value: 'world', arg: 'arg1', modifiers: { modifire1: true }\n        }]\n      }, undefined, 'hello world', undefined, vm)\n    ])\n    patch(vnode1, vnode2)\n    expect(directive1.update).toHaveBeenCalled()\n    // destroy\n    const vnode3 = new VNode('div')\n    patch(vnode2, vnode3)\n    expect(directive1.unbind).toHaveBeenCalled()\n  })\n})\n"
  },
  {
    "path": "test/unit/modules/vdom/modules/dom-props.spec.js",
    "content": "import Vue from 'vue'\nimport { patch } from 'web/runtime/patch'\nimport VNode from 'core/vdom/vnode'\n\ndescribe('vdom domProps module', () => {\n  it('should create an element with domProps', () => {\n    const vnode = new VNode('a', { domProps: { src: 'http://localhost/' }})\n    const elm = patch(null, vnode)\n    expect(elm.src).toBe('http://localhost/')\n  })\n\n  it('should change the elements domProps', () => {\n    const vnode1 = new VNode('a', { domProps: { src: 'http://localhost/' }})\n    const vnode2 = new VNode('a', { domProps: { src: 'https://vuejs.org/' }})\n    patch(null, vnode1)\n    const elm = patch(vnode1, vnode2)\n    expect(elm.src).toBe('https://vuejs.org/')\n  })\n\n  it('should remove the elements domProps', () => {\n    const vnode1 = new VNode('a', { domProps: { src: 'http://localhost/' }})\n    const vnode2 = new VNode('a', { domProps: {}})\n    patch(null, vnode1)\n    const elm = patch(vnode1, vnode2)\n    expect(elm.src).toBe('')\n  })\n\n  it('should initialize the elements value to zero', () => {\n    const vnode = new VNode('input', { domProps: { value: 0 }})\n    const elm = patch(null, vnode)\n    expect(elm.value).toBe('0')\n  })\n\n  it('should save raw value on element', () => {\n    const value = {}\n    const vnode = new VNode('input', { domProps: { value }})\n    const elm = patch(null, vnode)\n    expect(elm._value).toBe(value)\n  })\n\n  it('should discard vnode children if the node has innerHTML or textContent as a prop', () => {\n    const vnode = new VNode('div', { domProps: { innerHTML: 'hi' }}, [\n      new VNode('span'), new VNode('span')\n    ])\n    const elm = patch(null, vnode)\n    expect(elm.innerHTML).toBe('hi')\n    expect(vnode.children.length).toBe(0)\n\n    const vnode2 = new VNode('div', { domProps: { textContent: 'hi' }}, [\n      new VNode('span'), new VNode('span')\n    ])\n    const elm2 = patch(null, vnode2)\n    expect(elm2.textContent).toBe('hi')\n    expect(vnode2.children.length).toBe(0)\n\n    const vnode3 = new VNode('div', undefined, undefined, '123')\n    patch(null, vnode3)\n    const elm3 = patch(vnode3, vnode2)\n    expect(elm3.textContent).toBe('hi')\n\n    const vnode4 = new VNode('div', undefined, undefined, new VNode('span'))\n    patch(null, vnode4)\n    const elm4 = patch(vnode4, vnode)\n    expect(elm4.textContent).toBe('hi')\n  })\n\n  it('should handle mutating observed props object', done => {\n    const vm = new Vue({\n      data: {\n        props: {\n          id: 'foo'\n        }\n      },\n      render (h) {\n        return h('div', {\n          domProps: this.props\n        })\n      }\n    }).$mount()\n\n    expect(vm.$el.id).toBe('foo')\n    vm.props.id = 'bar'\n    waitForUpdate(() => {\n      expect(vm.$el.id).toBe('bar')\n      vm.props = { id: 'baz' }\n    }).then(() => {\n      expect(vm.$el.id).toBe('baz')\n    }).then(done)\n  })\n})\n"
  },
  {
    "path": "test/unit/modules/vdom/modules/events.spec.js",
    "content": "import { patch } from 'web/runtime/patch'\nimport VNode from 'core/vdom/vnode'\n\ndescribe('vdom events module', () => {\n  it('should attach event handler to element', () => {\n    const click = jasmine.createSpy()\n    const vnode = new VNode('a', { on: { click }})\n\n    const elm = patch(null, vnode)\n    document.body.appendChild(elm)\n    triggerEvent(elm, 'click')\n    expect(click.calls.count()).toBe(1)\n  })\n\n  it('should not duplicate the same listener', () => {\n    const click = jasmine.createSpy()\n    const vnode1 = new VNode('a', { on: { click }})\n    const vnode2 = new VNode('a', { on: { click }})\n\n    const elm = patch(null, vnode1)\n    patch(vnode1, vnode2)\n    document.body.appendChild(elm)\n    triggerEvent(elm, 'click')\n    expect(click.calls.count()).toBe(1)\n  })\n\n  it('should update different listener', () => {\n    const click = jasmine.createSpy()\n    const click2 = jasmine.createSpy()\n    const vnode1 = new VNode('a', { on: { click }})\n    const vnode2 = new VNode('a', { on: { click: click2 }})\n\n    const elm = patch(null, vnode1)\n    document.body.appendChild(elm)\n    triggerEvent(elm, 'click')\n    expect(click.calls.count()).toBe(1)\n    expect(click2.calls.count()).toBe(0)\n\n    patch(vnode1, vnode2)\n    triggerEvent(elm, 'click')\n    expect(click.calls.count()).toBe(1)\n    expect(click2.calls.count()).toBe(1)\n  })\n\n  it('should attach Array of multiple handlers', () => {\n    const click = jasmine.createSpy()\n    const vnode = new VNode('a', { on: { click: [click, click] }})\n\n    const elm = patch(null, vnode)\n    document.body.appendChild(elm)\n    triggerEvent(elm, 'click')\n    expect(click.calls.count()).toBe(2)\n  })\n\n  it('should update Array of multiple handlers', () => {\n    const click = jasmine.createSpy()\n    const click2 = jasmine.createSpy()\n    const vnode1 = new VNode('a', { on: { click: [click, click2] }})\n    const vnode2 = new VNode('a', { on: { click: [click] }})\n\n    const elm = patch(null, vnode1)\n    document.body.appendChild(elm)\n    triggerEvent(elm, 'click')\n    expect(click.calls.count()).toBe(1)\n    expect(click2.calls.count()).toBe(1)\n\n    patch(vnode1, vnode2)\n    triggerEvent(elm, 'click')\n    expect(click.calls.count()).toBe(2)\n    expect(click2.calls.count()).toBe(1)\n  })\n\n  it('should remove handlers that are no longer present', () => {\n    const click = jasmine.createSpy()\n    const vnode1 = new VNode('a', { on: { click }})\n    const vnode2 = new VNode('a', {})\n\n    const elm = patch(null, vnode1)\n    document.body.appendChild(elm)\n    triggerEvent(elm, 'click')\n    expect(click.calls.count()).toBe(1)\n\n    patch(vnode1, vnode2)\n    triggerEvent(elm, 'click')\n    expect(click.calls.count()).toBe(1)\n  })\n\n  it('should remove Array handlers that are no longer present', () => {\n    const click = jasmine.createSpy()\n    const vnode1 = new VNode('a', { on: { click: [click, click] }})\n    const vnode2 = new VNode('a', {})\n\n    const elm = patch(null, vnode1)\n    document.body.appendChild(elm)\n    triggerEvent(elm, 'click')\n    expect(click.calls.count()).toBe(2)\n\n    patch(vnode1, vnode2)\n    triggerEvent(elm, 'click')\n    expect(click.calls.count()).toBe(2)\n  })\n\n  // #4650\n  it('should handle single -> array or array -> single handler changes', () => {\n    const click = jasmine.createSpy()\n    const click2 = jasmine.createSpy()\n    const click3 = jasmine.createSpy()\n    const vnode0 = new VNode('a', { on: { click: click }})\n    const vnode1 = new VNode('a', { on: { click: [click, click2] }})\n    const vnode2 = new VNode('a', { on: { click: click }})\n    const vnode3 = new VNode('a', { on: { click: [click2, click3] }})\n\n    const elm = patch(null, vnode0)\n    document.body.appendChild(elm)\n    triggerEvent(elm, 'click')\n    expect(click.calls.count()).toBe(1)\n    expect(click2.calls.count()).toBe(0)\n\n    patch(vnode0, vnode1)\n    triggerEvent(elm, 'click')\n    expect(click.calls.count()).toBe(2)\n    expect(click2.calls.count()).toBe(1)\n\n    patch(vnode1, vnode2)\n    triggerEvent(elm, 'click')\n    expect(click.calls.count()).toBe(3)\n    expect(click2.calls.count()).toBe(1)\n\n    patch(vnode2, vnode3)\n    triggerEvent(elm, 'click')\n    expect(click.calls.count()).toBe(3)\n    expect(click2.calls.count()).toBe(2)\n    expect(click3.calls.count()).toBe(1)\n  })\n})\n"
  },
  {
    "path": "test/unit/modules/vdom/modules/style.spec.js",
    "content": "import { patch } from 'web/runtime/patch'\nimport VNode from 'core/vdom/vnode'\n\ndescribe('vdom style module', () => {\n  it('should create an element with style', () => {\n    const vnode = new VNode('p', { style: { fontSize: '12px' }})\n    const elm = patch(null, vnode)\n    expect(elm.style.fontSize).toBe('12px')\n  })\n\n  it('should create an element with array style', () => {\n    const vnode = new VNode('p', { style: [{ fontSize: '12px' }, { color: 'red' }] })\n    const elm = patch(null, vnode)\n    expect(elm.style.fontSize).toBe('12px')\n    expect(elm.style.color).toBe('red')\n  })\n\n  it('should change elements style', () => {\n    const vnode1 = new VNode('p', { style: { fontSize: '12px' }})\n    const vnode2 = new VNode('p', { style: { fontSize: '10px', display: 'block' }})\n    patch(null, vnode1)\n    const elm = patch(vnode1, vnode2)\n    expect(elm.style.fontSize).toBe('10px')\n    expect(elm.style.display).toBe('block')\n  })\n\n  it('should remove elements attrs', () => {\n    const vnode1 = new VNode('p', { style: { fontSize: '12px' }})\n    const vnode2 = new VNode('p', { style: { display: 'block' }})\n    patch(null, vnode1)\n    const elm = patch(vnode1, vnode2)\n    expect(elm.style.fontSize).toBe('')\n    expect(elm.style.display).toBe('block')\n  })\n})\n"
  },
  {
    "path": "test/unit/modules/vdom/patch/children.spec.js",
    "content": "import { patch } from 'web/runtime/patch'\nimport VNode from 'core/vdom/vnode'\n\nfunction prop (name) {\n  return obj => { return obj[name] }\n}\n\nfunction map (fn, list) {\n  const ret = []\n  for (let i = 0; i < list.length; i++) {\n    ret[i] = fn(list[i])\n  }\n  return ret\n}\n\nfunction spanNum (n) {\n  if (typeof n === 'string') {\n    return new VNode('span', {}, undefined, n)\n  } else {\n    return new VNode('span', { key: n }, undefined, n.toString())\n  }\n}\n\nfunction shuffle (array) {\n  let currentIndex = array.length\n  let temporaryValue\n  let randomIndex\n\n  // while there remain elements to shuffle...\n  while (currentIndex !== 0) {\n    // pick a remaining element...\n    randomIndex = Math.floor(Math.random() * currentIndex)\n    currentIndex -= 1\n    // and swap it with the current element.\n    temporaryValue = array[currentIndex]\n    array[currentIndex] = array[randomIndex]\n    array[randomIndex] = temporaryValue\n  }\n  return array\n}\n\nconst inner = prop('innerHTML')\nconst tag = prop('tagName')\n\ndescribe('vdom patch: children', () => {\n  let vnode0\n  beforeEach(() => {\n    vnode0 = new VNode('p', { attrs: { id: '1' }}, [createTextVNode('hello world')])\n    patch(null, vnode0)\n  })\n\n  it('should appends elements', () => {\n    const vnode1 = new VNode('p', {}, [1].map(spanNum))\n    const vnode2 = new VNode('p', {}, [1, 2, 3].map(spanNum))\n    let elm = patch(vnode0, vnode1)\n    expect(elm.children.length).toBe(1)\n    elm = patch(vnode1, vnode2)\n    expect(elm.children.length).toBe(3)\n    expect(elm.children[1].innerHTML).toBe('2')\n    expect(elm.children[2].innerHTML).toBe('3')\n  })\n\n  it('should prepends elements', () => {\n    const vnode1 = new VNode('p', {}, [4, 5].map(spanNum))\n    const vnode2 = new VNode('p', {}, [1, 2, 3, 4, 5].map(spanNum))\n    let elm = patch(vnode0, vnode1)\n    expect(elm.children.length).toBe(2)\n    elm = patch(vnode1, vnode2)\n    expect(map(inner, elm.children)).toEqual(['1', '2', '3', '4', '5'])\n  })\n\n  it('should add elements in the middle', () => {\n    const vnode1 = new VNode('p', {}, [1, 2, 4, 5].map(spanNum))\n    const vnode2 = new VNode('p', {}, [1, 2, 3, 4, 5].map(spanNum))\n    let elm = patch(vnode0, vnode1)\n    expect(elm.children.length).toBe(4)\n    elm = patch(vnode1, vnode2)\n    expect(map(inner, elm.children)).toEqual(['1', '2', '3', '4', '5'])\n  })\n\n  it('should add elements at begin and end', () => {\n    const vnode1 = new VNode('p', {}, [2, 3, 4].map(spanNum))\n    const vnode2 = new VNode('p', {}, [1, 2, 3, 4, 5].map(spanNum))\n    let elm = patch(vnode0, vnode1)\n    expect(elm.children.length).toBe(3)\n    elm = patch(vnode1, vnode2)\n    expect(map(inner, elm.children)).toEqual(['1', '2', '3', '4', '5'])\n  })\n\n  it('should add children to parent with no children', () => {\n    const vnode1 = new VNode('p', { key: 'p' })\n    const vnode2 = new VNode('p', { key: 'p' }, [1, 2, 3].map(spanNum))\n    let elm = patch(vnode0, vnode1)\n    expect(elm.children.length).toBe(0)\n    elm = patch(vnode1, vnode2)\n    expect(map(inner, elm.children)).toEqual(['1', '2', '3'])\n  })\n\n  it('should remove all children from parent', () => {\n    const vnode1 = new VNode('p', { key: 'p' }, [1, 2, 3].map(spanNum))\n    const vnode2 = new VNode('p', { key: 'p' })\n    let elm = patch(vnode0, vnode1)\n    expect(map(inner, elm.children)).toEqual(['1', '2', '3'])\n    elm = patch(vnode1, vnode2)\n    expect(elm.children.length).toBe(0)\n  })\n\n  it('should remove elements from the beginning', () => {\n    const vnode1 = new VNode('p', {}, [1, 2, 3, 4, 5].map(spanNum))\n    const vnode2 = new VNode('p', {}, [3, 4, 5].map(spanNum))\n    let elm = patch(vnode0, vnode1)\n    expect(elm.children.length).toBe(5)\n    elm = patch(vnode1, vnode2)\n    expect(map(inner, elm.children)).toEqual(['3', '4', '5'])\n  })\n\n  it('should removes elements from end', () => {\n    const vnode1 = new VNode('p', {}, [1, 2, 3, 4, 5].map(spanNum))\n    const vnode2 = new VNode('p', {}, [1, 2, 3].map(spanNum))\n    let elm = patch(vnode0, vnode1)\n    expect(elm.children.length).toBe(5)\n    elm = patch(vnode1, vnode2)\n    expect(elm.children.length).toBe(3)\n    expect(map(inner, elm.children)).toEqual(['1', '2', '3'])\n  })\n\n  it('should remove elements from the middle', () => {\n    const vnode1 = new VNode('p', {}, [1, 2, 3, 4, 5].map(spanNum))\n    const vnode2 = new VNode('p', {}, [1, 2, 4, 5].map(spanNum))\n    let elm = patch(vnode0, vnode1)\n    expect(elm.children.length).toBe(5)\n    elm = patch(vnode1, vnode2)\n    expect(elm.children.length).toBe(4)\n    expect(map(inner, elm.children)).toEqual(['1', '2', '4', '5'])\n  })\n\n  it('should moves element forward', () => {\n    const vnode1 = new VNode('p', {}, [1, 2, 3, 4].map(spanNum))\n    const vnode2 = new VNode('p', {}, [2, 3, 1, 4].map(spanNum))\n    let elm = patch(vnode0, vnode1)\n    expect(elm.children.length).toBe(4)\n    elm = patch(vnode1, vnode2)\n    expect(elm.children.length).toBe(4)\n    expect(map(inner, elm.children)).toEqual(['2', '3', '1', '4'])\n  })\n\n  it('should move elements to end', () => {\n    const vnode1 = new VNode('p', {}, [1, 2, 3].map(spanNum))\n    const vnode2 = new VNode('p', {}, [2, 3, 1].map(spanNum))\n    let elm = patch(vnode0, vnode1)\n    expect(elm.children.length).toBe(3)\n    elm = patch(vnode1, vnode2)\n    expect(elm.children.length).toBe(3)\n    expect(map(inner, elm.children)).toEqual(['2', '3', '1'])\n  })\n\n  it('should move element backwards', () => {\n    const vnode1 = new VNode('p', {}, [1, 2, 3, 4].map(spanNum))\n    const vnode2 = new VNode('p', {}, [1, 4, 2, 3].map(spanNum))\n    let elm = patch(vnode0, vnode1)\n    expect(elm.children.length).toBe(4)\n    elm = patch(vnode1, vnode2)\n    expect(elm.children.length).toBe(4)\n    expect(map(inner, elm.children)).toEqual(['1', '4', '2', '3'])\n  })\n\n  it('should swap first and last', () => {\n    const vnode1 = new VNode('p', {}, [1, 2, 3, 4].map(spanNum))\n    const vnode2 = new VNode('p', {}, [4, 2, 3, 1].map(spanNum))\n    let elm = patch(vnode0, vnode1)\n    expect(elm.children.length).toBe(4)\n    elm = patch(vnode1, vnode2)\n    expect(elm.children.length).toBe(4)\n    expect(map(inner, elm.children)).toEqual(['4', '2', '3', '1'])\n  })\n\n  it('should move to left and replace', () => {\n    const vnode1 = new VNode('p', {}, [1, 2, 3, 4, 5].map(spanNum))\n    const vnode2 = new VNode('p', {}, [4, 1, 2, 3, 6].map(spanNum))\n    let elm = patch(vnode0, vnode1)\n    expect(elm.children.length).toBe(5)\n    elm = patch(vnode1, vnode2)\n    expect(elm.children.length).toBe(5)\n    expect(map(inner, elm.children)).toEqual(['4', '1', '2', '3', '6'])\n  })\n\n  it('should move to left and leaves hold', () => {\n    const vnode1 = new VNode('p', {}, [1, 4, 5].map(spanNum))\n    const vnode2 = new VNode('p', {}, [4, 6].map(spanNum))\n    let elm = patch(vnode0, vnode1)\n    expect(elm.children.length).toBe(3)\n    elm = patch(vnode1, vnode2)\n    expect(map(inner, elm.children)).toEqual(['4', '6'])\n  })\n\n  it('should handle moved and set to undefined element ending at the end', () => {\n    const vnode1 = new VNode('p', {}, [2, 4, 5].map(spanNum))\n    const vnode2 = new VNode('p', {}, [4, 5, 3].map(spanNum))\n    let elm = patch(vnode0, vnode1)\n    expect(elm.children.length).toBe(3)\n    elm = patch(vnode1, vnode2)\n    expect(elm.children.length).toBe(3)\n    expect(map(inner, elm.children)).toEqual(['4', '5', '3'])\n  })\n\n  it('should move a key in non-keyed nodes with a size up', () => {\n    const vnode1 = new VNode('p', {}, [1, 'a', 'b', 'c'].map(spanNum))\n    const vnode2 = new VNode('p', {}, ['d', 'a', 'b', 'c', 1, 'e'].map(spanNum))\n    let elm = patch(vnode0, vnode1)\n    expect(elm.children.length).toBe(4)\n    expect(elm.textContent, '1abc')\n    elm = patch(vnode1, vnode2)\n    expect(elm.children.length).toBe(6)\n    expect(elm.textContent, 'dabc1e')\n  })\n\n  it('should reverse element', () => {\n    const vnode1 = new VNode('p', {}, [1, 2, 3, 4, 5, 6, 7, 8].map(spanNum))\n    const vnode2 = new VNode('p', {}, [8, 7, 6, 5, 4, 3, 2, 1].map(spanNum))\n    let elm = patch(vnode0, vnode1)\n    expect(elm.children.length).toBe(8)\n    elm = patch(vnode1, vnode2)\n    expect(map(inner, elm.children)).toEqual(['8', '7', '6', '5', '4', '3', '2', '1'])\n  })\n\n  it('something', () => {\n    const vnode1 = new VNode('p', {}, [0, 1, 2, 3, 4, 5].map(spanNum))\n    const vnode2 = new VNode('p', {}, [4, 3, 2, 1, 5, 0].map(spanNum))\n    let elm = patch(vnode0, vnode1)\n    expect(elm.children.length).toBe(6)\n    elm = patch(vnode1, vnode2)\n    expect(map(inner, elm.children)).toEqual(['4', '3', '2', '1', '5', '0'])\n  })\n\n  it('should handle random shuffle', () => {\n    let n\n    let i\n    const arr = []\n    const opacities = []\n    const elms = 14\n    const samples = 5\n    function spanNumWithOpacity (n, o) {\n      return new VNode('span', { key: n, style: { opacity: o }}, undefined, n.toString())\n    }\n\n    for (n = 0; n < elms; ++n) { arr[n] = n }\n    for (n = 0; n < samples; ++n) {\n      const vnode1 = new VNode('span', {}, arr.map(n => {\n        return spanNumWithOpacity(n, '1')\n      }))\n      const shufArr = shuffle(arr.slice(0))\n      let elm = patch(vnode0, vnode1)\n      for (i = 0; i < elms; ++i) {\n        expect(elm.children[i].innerHTML).toBe(i.toString())\n        opacities[i] = Math.random().toFixed(5).toString()\n      }\n      const vnode2 = new VNode('span', {}, arr.map(n => {\n        return spanNumWithOpacity(shufArr[n], opacities[n])\n      }))\n      elm = patch(vnode1, vnode2)\n      for (i = 0; i < elms; ++i) {\n        expect(elm.children[i].innerHTML).toBe(shufArr[i].toString())\n        expect(opacities[i].indexOf(elm.children[i].style.opacity)).toBe(0)\n      }\n    }\n  })\n\n  it('should append elements with updating children without keys', () => {\n    const vnode1 = new VNode('div', {}, [\n      new VNode('span', {}, undefined, 'hello')\n    ])\n    const vnode2 = new VNode('div', {}, [\n      new VNode('span', {}, undefined, 'hello'),\n      new VNode('span', {}, undefined, 'world')\n    ])\n    let elm = patch(vnode0, vnode1)\n    expect(map(inner, elm.children)).toEqual(['hello'])\n    elm = patch(vnode1, vnode2)\n    expect(map(inner, elm.children)).toEqual(['hello', 'world'])\n  })\n\n  it('should handle unmoved text nodes with updating children without keys', () => {\n    const vnode1 = new VNode('div', {}, [\n      createTextVNode('text'),\n      new VNode('span', {}, undefined, 'hello')\n    ])\n    const vnode2 = new VNode('div', {}, [\n      createTextVNode('text'),\n      new VNode('span', {}, undefined, 'hello')\n    ])\n    let elm = patch(vnode0, vnode1)\n    expect(elm.childNodes[0].textContent).toBe('text')\n    elm = patch(vnode1, vnode2)\n    expect(elm.childNodes[0].textContent).toBe('text')\n  })\n\n  it('should handle changing text children with updating children without keys', () => {\n    const vnode1 = new VNode('div', {}, [\n      createTextVNode('text'),\n      new VNode('span', {}, undefined, 'hello')\n    ])\n    const vnode2 = new VNode('div', {}, [\n      createTextVNode('text2'),\n      new VNode('span', {}, undefined, 'hello')\n    ])\n    let elm = patch(vnode0, vnode1)\n    expect(elm.childNodes[0].textContent).toBe('text')\n    elm = patch(vnode1, vnode2)\n    expect(elm.childNodes[0].textContent).toBe('text2')\n  })\n\n  it('should prepend element with updating children without keys', () => {\n    const vnode1 = new VNode('div', {}, [\n      new VNode('span', {}, undefined, 'world')\n    ])\n    const vnode2 = new VNode('div', {}, [\n      new VNode('span', {}, undefined, 'hello'),\n      new VNode('span', {}, undefined, 'world')\n    ])\n    let elm = patch(vnode0, vnode1)\n    expect(map(inner, elm.children)).toEqual(['world'])\n    elm = patch(vnode1, vnode2)\n    expect(map(inner, elm.children)).toEqual(['hello', 'world'])\n  })\n\n  it('should prepend element of different tag type with updating children without keys', () => {\n    const vnode1 = new VNode('div', {}, [\n      new VNode('span', {}, undefined, 'world')\n    ])\n    const vnode2 = new VNode('div', {}, [\n      new VNode('div', {}, undefined, 'hello'),\n      new VNode('span', {}, undefined, 'world')\n    ])\n    let elm = patch(vnode0, vnode1)\n    expect(map(inner, elm.children)).toEqual(['world'])\n    elm = patch(vnode1, vnode2)\n    expect(map(prop('tagName'), elm.children)).toEqual(['DIV', 'SPAN'])\n    expect(map(inner, elm.children)).toEqual(['hello', 'world'])\n  })\n\n  it('should remove elements with updating children without keys', () => {\n    const vnode1 = new VNode('div', {}, [\n      new VNode('span', {}, undefined, 'one'),\n      new VNode('span', {}, undefined, 'two'),\n      new VNode('span', {}, undefined, 'three')\n    ])\n    const vnode2 = new VNode('div', {}, [\n      new VNode('span', {}, undefined, 'one'),\n      new VNode('span', {}, undefined, 'three')\n    ])\n    let elm = patch(vnode0, vnode1)\n    expect(map(inner, elm.children)).toEqual(['one', 'two', 'three'])\n    elm = patch(vnode1, vnode2)\n    expect(map(inner, elm.children)).toEqual(['one', 'three'])\n  })\n\n  it('should remove a single text node with updating children without keys', () => {\n    const vnode1 = new VNode('div', {}, undefined, 'one')\n    const vnode2 = new VNode('div', {})\n    let elm = patch(vnode0, vnode1)\n    expect(elm.textContent).toBe('one')\n    elm = patch(vnode1, vnode2)\n    expect(elm.textContent).toBe('')\n  })\n\n  it('should remove a single text node when children are updated', () => {\n    const vnode1 = new VNode('div', {}, undefined, 'one')\n    const vnode2 = new VNode('div', {}, [\n      new VNode('div', {}, undefined, 'two'),\n      new VNode('span', {}, undefined, 'three')\n    ])\n    let elm = patch(vnode0, vnode1)\n    expect(elm.textContent).toBe('one')\n    elm = patch(vnode1, vnode2)\n    expect(map(prop('textContent'), elm.childNodes)).toEqual(['two', 'three'])\n  })\n\n  it('should remove a text node among other elements', () => {\n    const vnode1 = new VNode('div', {}, [\n      createTextVNode('one'),\n      new VNode('span', {}, undefined, 'two')\n    ])\n    const vnode2 = new VNode('div', {}, [\n      new VNode('div', {}, undefined, 'three')\n    ])\n    let elm = patch(vnode0, vnode1)\n    expect(map(prop('textContent'), elm.childNodes)).toEqual(['one', 'two'])\n    elm = patch(vnode1, vnode2)\n    expect(elm.childNodes.length).toBe(1)\n    expect(elm.childNodes[0].tagName).toBe('DIV')\n    expect(elm.childNodes[0].textContent).toBe('three')\n  })\n\n  it('should reorder elements', () => {\n    const vnode1 = new VNode('div', {}, [\n      new VNode('span', {}, undefined, 'one'),\n      new VNode('div', {}, undefined, 'two'),\n      new VNode('b', {}, undefined, 'three')\n    ])\n    const vnode2 = new VNode('div', {}, [\n      new VNode('b', {}, undefined, 'three'),\n      new VNode('span', {}, undefined, 'two'),\n      new VNode('div', {}, undefined, 'one')\n    ])\n    let elm = patch(vnode0, vnode1)\n    expect(map(inner, elm.children)).toEqual(['one', 'two', 'three'])\n    elm = patch(vnode1, vnode2)\n    expect(map(inner, elm.children)).toEqual(['three', 'two', 'one'])\n  })\n\n  it('should handle children with the same key but with different tag', () => {\n    const vnode1 = new VNode('div', {}, [\n      new VNode('div', { key: 1 }, undefined, 'one'),\n      new VNode('div', { key: 2 }, undefined, 'two'),\n      new VNode('div', { key: 3 }, undefined, 'three'),\n      new VNode('div', { key: 4 }, undefined, 'four')\n    ])\n    const vnode2 = new VNode('div', {}, [\n      new VNode('div', { key: 4 }, undefined, 'four'),\n      new VNode('span', { key: 3 }, undefined, 'three'),\n      new VNode('span', { key: 2 }, undefined, 'two'),\n      new VNode('div', { key: 1 }, undefined, 'one')\n    ])\n    let elm = patch(vnode0, vnode1)\n    expect(map(tag, elm.children)).toEqual(['DIV', 'DIV', 'DIV', 'DIV'])\n    expect(map(inner, elm.children)).toEqual(['one', 'two', 'three', 'four'])\n    elm = patch(vnode1, vnode2)\n    expect(map(tag, elm.children)).toEqual(['DIV', 'SPAN', 'SPAN', 'DIV'])\n    expect(map(inner, elm.children)).toEqual(['four', 'three', 'two', 'one'])\n  })\n\n  it('should handle children with the same tag, same key, but one with data and one without data', () => {\n    const vnode1 = new VNode('div', {}, [\n      new VNode('div', { class: 'hi' }, undefined, 'one')\n    ])\n    const vnode2 = new VNode('div', {}, [\n      new VNode('div', undefined, undefined, 'four')\n    ])\n    let elm = patch(vnode0, vnode1)\n    const child1 = elm.children[0]\n    expect(child1.className).toBe('hi')\n    elm = patch(vnode1, vnode2)\n    const child2 = elm.children[0]\n    expect(child1).not.toBe(child2)\n    expect(child2.className).toBe('')\n  })\n\n  it('should handle static vnodes properly', function () {\n    function makeNode (text) {\n      return new VNode('div', undefined, [\n        new VNode(undefined, undefined, undefined, text)\n      ])\n    }\n    const b = makeNode('B')\n    b.isStatic = true\n    b.key = `__static__1`\n    const vnode1 = new VNode('div', {}, [makeNode('A'), b, makeNode('C')])\n    const vnode2 = new VNode('div', {}, [b])\n    const vnode3 = new VNode('div', {}, [makeNode('A'), b, makeNode('C')])\n\n    let elm = patch(vnode0, vnode1)\n    expect(elm.textContent).toBe('ABC')\n    elm = patch(vnode1, vnode2)\n    expect(elm.textContent).toBe('B')\n    elm = patch(vnode2, vnode3)\n    expect(elm.textContent).toBe('ABC')\n  })\n\n  it('should handle static vnodes inside ', function () {\n    function makeNode (text) {\n      return new VNode('div', undefined, [\n        new VNode(undefined, undefined, undefined, text)\n      ])\n    }\n    const b = makeNode('B')\n    b.isStatic = true\n    b.key = `__static__1`\n    const vnode1 = new VNode('div', {}, [makeNode('A'), b, makeNode('C')])\n    const vnode2 = new VNode('div', {}, [b])\n    const vnode3 = new VNode('div', {}, [makeNode('A'), b, makeNode('C')])\n\n    let elm = patch(vnode0, vnode1)\n    expect(elm.textContent).toBe('ABC')\n    elm = patch(vnode1, vnode2)\n    expect(elm.textContent).toBe('B')\n    elm = patch(vnode2, vnode3)\n    expect(elm.textContent).toBe('ABC')\n  })\n})\n"
  },
  {
    "path": "test/unit/modules/vdom/patch/edge-cases.spec.js",
    "content": "import Vue from 'vue'\n\ndescribe('vdom patch: edge cases', () => {\n  // exposed by #3406\n  // When a static vnode is inside v-for, it's possible for the same vnode\n  // to be used in multiple places, and its element will be replaced. This\n  // causes patch errors when node ops depend on the vnode's element position.\n  it('should handle static vnodes by key', done => {\n    const vm = new Vue({\n      data: {\n        ok: true\n      },\n      template: `\n        <div>\n          <div v-for=\"i in 2\">\n            <div v-if=\"ok\">a</div><div>b</div><div v-if=\"!ok\">c</div><div>d</div>\n          </div>\n        </div>\n      `\n    }).$mount()\n    expect(vm.$el.textContent).toBe('abdabd')\n    vm.ok = false\n    waitForUpdate(() => {\n      expect(vm.$el.textContent).toBe('bcdbcd')\n    }).then(done)\n  })\n\n  // #3533\n  // a static node (<br>) is reused in createElm, which changes its elm reference\n  // and is inserted into a different parent.\n  // later when patching the next element a DOM insertion uses it as the\n  // reference node, causing a parent mismatch.\n  it('should handle static node edge case when it\\'s reused AND used as a reference node for insertion', done => {\n    const vm = new Vue({\n      data: {\n        ok: true\n      },\n      template: `\n        <div>\n          <button @click=\"ok = !ok\">toggle</button>\n          <div class=\"b\" v-if=\"ok\">123</div>\n          <div class=\"c\">\n            <br><p>{{ 1 }}</p>\n          </div>\n          <div class=\"d\">\n            <label>{{ 2 }}</label>\n          </div>\n        </div>\n      `\n    }).$mount()\n\n    expect(vm.$el.querySelector('.c').textContent).toBe('1')\n    expect(vm.$el.querySelector('.d').textContent).toBe('2')\n    vm.ok = false\n    waitForUpdate(() => {\n      expect(vm.$el.querySelector('.c').textContent).toBe('1')\n      expect(vm.$el.querySelector('.d').textContent).toBe('2')\n    }).then(done)\n  })\n\n  it('should synchronize vm\\' vnode', done => {\n    const comp = {\n      data: () => ({ swap: true }),\n      render (h) {\n        return this.swap\n          ? h('a', 'atag')\n          : h('span', 'span')\n      }\n    }\n\n    const wrapper = {\n      render: h => h('comp'),\n      components: { comp }\n    }\n\n    const vm = new Vue({\n      render (h) {\n        const children = [\n          h('wrapper'),\n          h('div', 'row')\n        ]\n        if (this.swap) {\n          children.reverse()\n        }\n        return h('div', children)\n      },\n      data: () => ({ swap: false }),\n      components: { wrapper }\n    }).$mount()\n\n    expect(vm.$el.innerHTML).toBe('<a>atag</a><div>row</div>')\n    const wrapperVm = vm.$children[0]\n    const compVm = wrapperVm.$children[0]\n    vm.swap = true\n    waitForUpdate(() => {\n      expect(compVm.$vnode.parent).toBe(wrapperVm.$vnode)\n      expect(vm.$el.innerHTML).toBe('<div>row</div><a>atag</a>')\n      vm.swap = false\n    })\n    .then(() => {\n      expect(compVm.$vnode.parent).toBe(wrapperVm.$vnode)\n      expect(vm.$el.innerHTML).toBe('<a>atag</a><div>row</div>')\n      compVm.swap = false\n    })\n    .then(() => {\n      expect(vm.$el.innerHTML).toBe('<span>span</span><div>row</div>')\n      expect(compVm.$vnode.parent).toBe(wrapperVm.$vnode)\n      vm.swap = true\n    })\n    .then(() => {\n      expect(vm.$el.innerHTML).toBe('<div>row</div><span>span</span>')\n      expect(compVm.$vnode.parent).toBe(wrapperVm.$vnode)\n      vm.swap = true\n    })\n    .then(done)\n  })\n\n  // #4530\n  it('should not reset value when patching between dynamic/static bindings', done => {\n    const vm = new Vue({\n      data: { ok: true },\n      template: `\n        <div>\n          <input type=\"button\" v-if=\"ok\" value=\"a\">\n          <input type=\"button\" :value=\"'b'\">\n        </div>\n      `\n    }).$mount()\n    expect(vm.$el.children[0].value).toBe('a')\n    vm.ok = false\n    waitForUpdate(() => {\n      expect(vm.$el.children[0].value).toBe('b')\n      vm.ok = true\n    }).then(() => {\n      expect(vm.$el.children[0].value).toBe('a')\n    }).then(done)\n  })\n})\n"
  },
  {
    "path": "test/unit/modules/vdom/patch/element.spec.js",
    "content": "import Vue from 'vue'\nimport { patch } from 'web/runtime/patch'\nimport VNode from 'core/vdom/vnode'\n\ndescribe('vdom patch: element', () => {\n  it('should create an element', () => {\n    const vnode = new VNode('p', { attrs: { id: '1' }}, [createTextVNode('hello world')])\n    const elm = patch(null, vnode)\n    expect(elm.tagName).toBe('P')\n    expect(elm.outerHTML).toBe('<p id=\"1\">hello world</p>')\n  })\n\n  it('should create an element which having the namespace', () => {\n    const vnode = new VNode('svg', {})\n    vnode.ns = 'svg'\n    const elm = patch(null, vnode)\n    expect(elm.namespaceURI).toBe('http://www.w3.org/2000/svg')\n  })\n\n  const el = document.createElement('unknown')\n  // Android Browser <= 4.2 doesn't use correct class name,\n  // but it doesn't matter because no one's gonna use it as their primary\n  // development browser.\n  if (/HTMLUnknownElement/.test(el.toString())) {\n    it('should warn unknown element', () => {\n      const vnode = new VNode('unknown')\n      patch(null, vnode)\n      expect(`Unknown custom element: <unknown>`).toHaveBeenWarned()\n    })\n  }\n\n  it('should warn unknown element with hyphen', () => {\n    const vnode = new VNode('unknown-foo')\n    patch(null, vnode)\n    expect(`Unknown custom element: <unknown-foo>`).toHaveBeenWarned()\n  })\n\n  it('should create an elements which having text content', () => {\n    const vnode = new VNode('div', {}, [createTextVNode('hello world')])\n    const elm = patch(null, vnode)\n    expect(elm.innerHTML).toBe('hello world')\n  })\n\n  it('should create create an elements which having span and text content', () => {\n    const vnode = new VNode('div', {}, [\n      new VNode('span'),\n      createTextVNode('hello world')\n    ])\n    const elm = patch(null, vnode)\n    expect(elm.childNodes[0].tagName).toBe('SPAN')\n    expect(elm.childNodes[1].textContent).toBe('hello world')\n  })\n\n  it('should create element with scope attribute', () => {\n    const vnode = new VNode('div')\n    vnode.context = new Vue({ _scopeId: 'foo' })\n    const elm = patch(null, vnode)\n    expect(elm.hasAttribute('foo')).toBe(true)\n  })\n})\n"
  },
  {
    "path": "test/unit/modules/vdom/patch/hooks.spec.js",
    "content": "import { patch } from 'web/runtime/patch'\nimport { createPatchFunction } from 'core/vdom/patch'\nimport baseModules from 'core/vdom/modules/index'\nimport * as nodeOps from 'web/runtime/node-ops'\nimport platformModules from 'web/runtime/modules/index'\nimport VNode from 'core/vdom/vnode'\n\nconst modules = baseModules.concat(platformModules)\n\ndescribe('vdom patch: hooks', () => {\n  let vnode0\n  beforeEach(() => {\n    vnode0 = new VNode('p', { attrs: { id: '1' }}, [createTextVNode('hello world')])\n    patch(null, vnode0)\n  })\n\n  it('should call `insert` listener after both parents, siblings and children have been inserted', () => {\n    const result = []\n    function insert (vnode) {\n      expect(vnode.elm.children.length).toBe(2)\n      expect(vnode.elm.parentNode.children.length).toBe(3)\n      result.push(vnode)\n    }\n    const vnode1 = new VNode('div', {}, [\n      new VNode('span', {}, undefined, 'first sibling'),\n      new VNode('div', { hook: { insert }}, [\n        new VNode('span', {}, undefined, 'child 1'),\n        new VNode('span', {}, undefined, 'child 2')\n      ]),\n      new VNode('span', {}, undefined, 'can touch me')\n    ])\n    patch(vnode0, vnode1)\n    expect(result.length).toBe(1)\n  })\n\n  it('should call `prepatch` listener', () => {\n    const result = []\n    function prepatch (oldVnode, newVnode) {\n      expect(oldVnode).toEqual(vnode1.children[1])\n      expect(newVnode).toEqual(vnode2.children[1])\n      result.push(newVnode)\n    }\n    const vnode1 = new VNode('div', {}, [\n      new VNode('span', {}, undefined, 'first sibling'),\n      new VNode('div', { hook: { prepatch }}, [\n        new VNode('span', {}, undefined, 'child 1'),\n        new VNode('span', {}, undefined, 'child 2')\n      ])\n    ])\n    const vnode2 = new VNode('div', {}, [\n      new VNode('span', {}, undefined, 'first sibling'),\n      new VNode('div', { hook: { prepatch }}, [\n        new VNode('span', {}, undefined, 'child 1'),\n        new VNode('span', {}, undefined, 'child 2')\n      ])\n    ])\n    patch(vnode0, vnode1)\n    patch(vnode1, vnode2)\n    expect(result.length).toBe(1)\n  })\n\n  it('should call `postpatch` after `prepatch` listener', () => {\n    const pre = []\n    const post = []\n    function prepatch (oldVnode, newVnode) {\n      pre.push(pre)\n    }\n    function postpatch (oldVnode, newVnode) {\n      expect(pre.length).toBe(post.length + 1)\n      post.push(post)\n    }\n    const vnode1 = new VNode('div', {}, [\n      new VNode('span', {}, undefined, 'first sibling'),\n      new VNode('div', { hook: { prepatch, postpatch }}, [\n        new VNode('span', {}, undefined, 'child 1'),\n        new VNode('span', {}, undefined, 'child 2')\n      ])\n    ])\n    const vnode2 = new VNode('div', {}, [\n      new VNode('span', {}, undefined, 'first sibling'),\n      new VNode('div', { hook: { prepatch, postpatch }}, [\n        new VNode('span', {}, undefined, 'child 1'),\n        new VNode('span', {}, undefined, 'child 2')\n      ])\n    ])\n    patch(vnode0, vnode1)\n    patch(vnode1, vnode2)\n    expect(pre.length).toBe(1)\n    expect(post.length).toBe(1)\n  })\n\n  it('should call `update` listener', () => {\n    const result1 = []\n    const result2 = []\n    function cb (result, oldVnode, newVnode) {\n      if (result.length > 1) {\n        expect(result[result.length - 1]).toEqual(oldVnode)\n      }\n      result.push(newVnode)\n    }\n    const vnode1 = new VNode('div', {}, [\n      new VNode('span', {}, undefined, 'first sibling'),\n      new VNode('div', { hook: { update: cb.bind(null, result1) }}, [\n        new VNode('span', {}, undefined, 'child 1'),\n        new VNode('span', { hook: { update: cb.bind(null, result2) }}, undefined, 'child 2')\n      ])\n    ])\n    const vnode2 = new VNode('div', {}, [\n      new VNode('span', {}, undefined, 'first sibling'),\n      new VNode('div', { hook: { update: cb.bind(null, result1) }}, [\n        new VNode('span', {}, undefined, 'child 1'),\n        new VNode('span', { hook: { update: cb.bind(null, result2) }}, undefined, 'child 2')\n      ])\n    ])\n    patch(vnode0, vnode1)\n    patch(vnode1, vnode2)\n    expect(result1.length).toBe(1)\n    expect(result2.length).toBe(1)\n  })\n\n  it('should call `remove` listener', () => {\n    const result = []\n    function remove (vnode, rm) {\n      const parent = vnode.elm.parentNode\n      expect(vnode.elm.children.length).toBe(2)\n      expect(vnode.elm.children.length).toBe(2)\n      result.push(vnode)\n      rm()\n      expect(parent.children.length).toBe(1)\n    }\n    const vnode1 = new VNode('div', {}, [\n      new VNode('span', {}, undefined, 'first sibling'),\n      new VNode('div', { hook: { remove }}, [\n        new VNode('span', {}, undefined, 'child 1'),\n        new VNode('span', {}, undefined, 'child 2')\n      ])\n    ])\n    const vnode2 = new VNode('div', {}, [\n      new VNode('span', {}, undefined, 'first sibling')\n    ])\n    patch(vnode0, vnode1)\n    patch(vnode1, vnode2)\n    expect(result.length).toBe(1)\n  })\n\n  it('should call `init` and `prepatch` listeners on root', () => {\n    let count = 0\n    function init (vnode) { count++ }\n    function prepatch (oldVnode, newVnode) { count++ }\n    const vnode1 = new VNode('div', { hook: { init, prepatch }})\n    patch(vnode0, vnode1)\n    expect(count).toBe(1)\n    const vnode2 = new VNode('span', { hook: { init, prepatch }})\n    patch(vnode1, vnode2)\n    expect(count).toBe(2)\n  })\n\n  it('should remove element when all remove listeners are done', () => {\n    let rm1, rm2, rm3\n    const patch1 = createPatchFunction({\n      nodeOps,\n      modules: modules.concat([\n        { remove (_, rm) { rm1 = rm } },\n        { remove (_, rm) { rm2 = rm } }\n      ])\n    })\n    const vnode1 = new VNode('div', {}, [\n      new VNode('a', { hook: { remove (_, rm) { rm3 = rm } }})\n    ])\n    const vnode2 = new VNode('div', {}, [])\n    let elm = patch1(vnode0, vnode1)\n    expect(elm.children.length).toBe(1)\n    elm = patch1(vnode1, vnode2)\n    expect(elm.children.length).toBe(1)\n    rm1()\n    expect(elm.children.length).toBe(1)\n    rm3()\n    expect(elm.children.length).toBe(1)\n    rm2()\n    expect(elm.children.length).toBe(0)\n  })\n\n  it('should invoke the remove hook on replaced root', () => {\n    const result = []\n    const parent = nodeOps.createElement('div')\n    vnode0 = nodeOps.createElement('div')\n    parent.appendChild(vnode0)\n    function remove (vnode, rm) {\n      result.push(vnode)\n      rm()\n    }\n    const vnode1 = new VNode('div', { hook: { remove }}, [\n      new VNode('b', {}, undefined, 'child 1'),\n      new VNode('i', {}, undefined, 'child 2')\n    ])\n    const vnode2 = new VNode('span', {}, [\n      new VNode('b', {}, undefined, 'child 1'),\n      new VNode('i', {}, undefined, 'child 2')\n    ])\n    patch(vnode0, vnode1)\n    patch(vnode1, vnode2)\n    expect(result.length).toBe(1)\n  })\n\n  it('should invoke global `destroy` hook for all removed children', () => {\n    const result = []\n    function destroy (vnode) { result.push(vnode) }\n    const vnode1 = new VNode('div', {}, [\n      new VNode('span', {}, undefined, 'first sibling'),\n      new VNode('div', {}, [\n        new VNode('span', { hook: { destroy }}, undefined, 'child 1'),\n        new VNode('span', {}, undefined, 'child 2')\n      ])\n    ])\n    const vnode2 = new VNode('div')\n    patch(vnode0, vnode1)\n    patch(vnode1, vnode2)\n    expect(result.length).toBe(1)\n  })\n\n  it('should handle text vnodes with `undefined` `data` property', () => {\n    const vnode1 = new VNode('div', {}, [createTextVNode(' ')])\n    const vnode2 = new VNode('div', {}, [])\n    patch(vnode0, vnode1)\n    patch(vnode1, vnode2)\n  })\n\n  it('should invoke `destroy` module hook for all removed children', () => {\n    let created = 0\n    let destroyed = 0\n    const patch1 = createPatchFunction({\n      nodeOps,\n      modules: modules.concat([\n        { create () { created++ } },\n        { destroy () { destroyed++ } }\n      ])\n    })\n    const vnode1 = new VNode('div', {}, [\n      new VNode('span', {}, undefined, 'first sibling'),\n      new VNode('div', {}, [\n        new VNode('span', {}, undefined, 'child 1'),\n        new VNode('span', {}, undefined, 'child 2')\n      ])\n    ])\n    const vnode2 = new VNode('div', {})\n    patch1(vnode0, vnode1)\n    expect(destroyed).toBe(1) // should invoke for replaced root nodes too\n    patch1(vnode1, vnode2)\n    expect(created).toBe(5)\n    expect(destroyed).toBe(5)\n  })\n\n  it('should not invoke `create` and `remove` module hook for text nodes', () => {\n    let created = 0\n    let removed = 0\n    const patch1 = createPatchFunction({\n      nodeOps,\n      modules: modules.concat([\n        { create () { created++ } },\n        { remove () { removed++ } }\n      ])\n    })\n    const vnode1 = new VNode('div', {}, [\n      new VNode('span', {}, undefined, 'first child'),\n      createTextVNode(''),\n      new VNode('span', {}, undefined, 'third child')\n    ])\n    const vnode2 = new VNode('div', {})\n    patch1(vnode0, vnode1)\n    patch1(vnode1, vnode2)\n    expect(created).toBe(3)\n    expect(removed).toBe(2)\n  })\n\n  it('should not invoke `destroy` module hook for text nodes', () => {\n    let created = 0\n    let destroyed = 0\n    const patch1 = createPatchFunction({\n      nodeOps,\n      modules: modules.concat([\n        { create () { created++ } },\n        { destroy () { destroyed++ } }\n      ])\n    })\n    const vnode1 = new VNode('div', {}, [\n      new VNode('span', {}, undefined, 'first sibling'),\n      new VNode('div', {}, [\n        new VNode('span', {}, undefined, 'child 1'),\n        new VNode('span', {}, [\n          createTextVNode('text1'),\n          createTextVNode('text2')\n        ])\n      ])\n    ])\n    const vnode2 = new VNode('div', {})\n    patch1(vnode0, vnode1)\n    expect(destroyed).toBe(1) // should invoke for replaced root nodes too\n    patch1(vnode1, vnode2)\n    expect(created).toBe(5)\n    expect(destroyed).toBe(5)\n  })\n\n  it('should call `create` listener before inserted into parent but after children', () => {\n    const result = []\n    function create (empty, vnode) {\n      expect(vnode.elm.children.length).toBe(2)\n      expect(vnode.elm.parentNode).toBe(null)\n      result.push(vnode)\n    }\n    const vnode1 = new VNode('div', {}, [\n      new VNode('span', {}, undefined, 'first sibling'),\n      new VNode('div', { hook: { create }}, [\n        new VNode('span', {}, undefined, 'child 1'),\n        new VNode('span', {}, undefined, 'child 2')\n      ]),\n      new VNode('span', {}, undefined, 'can\\'t touch me')\n    ])\n    patch(vnode0, vnode1)\n    expect(result.length).toBe(1)\n  })\n})\n"
  },
  {
    "path": "test/unit/modules/vdom/patch/hydration.spec.js",
    "content": "import Vue from 'vue'\nimport VNode from 'core/vdom/vnode'\nimport { patch } from 'web/runtime/patch'\nimport { SSR_ATTR } from 'shared/constants'\n\nfunction createMockSSRDOM (innerHTML) {\n  const dom = document.createElement('div')\n  dom.setAttribute(SSR_ATTR, 'true')\n  dom.innerHTML = innerHTML\n  return dom\n}\n\ndescribe('vdom patch: hydration', () => {\n  let vnode0\n  beforeEach(() => {\n    vnode0 = new VNode('p', { attrs: { id: '1' }}, [createTextVNode('hello world')])\n    patch(null, vnode0)\n  })\n\n  it('should hydrate elements when server-rendered DOM tree is same as virtual DOM tree', () => {\n    const result = []\n    function init (vnode) { result.push(vnode) }\n    function createServerRenderedDOM () {\n      const root = document.createElement('div')\n      root.setAttribute(SSR_ATTR, 'true')\n      const span = document.createElement('span')\n      root.appendChild(span)\n      const div = document.createElement('div')\n      const child1 = document.createElement('span')\n      const child2 = document.createElement('span')\n      child1.textContent = 'hi'\n      child2.textContent = 'ho'\n      div.appendChild(child1)\n      div.appendChild(child2)\n      root.appendChild(div)\n      return root\n    }\n    const node0 = createServerRenderedDOM()\n    const vnode1 = new VNode('div', {}, [\n      new VNode('span', {}),\n      new VNode('div', { hook: { init }}, [\n        new VNode('span', {}, [new VNode(undefined, undefined, undefined, 'hi')]),\n        new VNode('span', {}, [new VNode(undefined, undefined, undefined, 'ho')])\n      ])\n    ])\n    patch(node0, vnode1)\n    expect(result.length).toBe(1)\n\n    function traverseAndAssert (vnode, element) {\n      expect(vnode.elm).toBe(element)\n      if (vnode.children) {\n        vnode.children.forEach((node, i) => {\n          traverseAndAssert(node, element.childNodes[i])\n        })\n      }\n    }\n    // ensure vnodes are correctly associated with actual DOM\n    traverseAndAssert(vnode1, node0)\n\n    // check update\n    const vnode2 = new VNode('div', { attrs: { id: 'foo' }}, [\n      new VNode('span', { attrs: { id: 'bar' }}),\n      new VNode('div', { hook: { init }}, [\n        new VNode('span', {}),\n        new VNode('span', {})\n      ])\n    ])\n    patch(vnode1, vnode2)\n    expect(node0.id).toBe('foo')\n    expect(node0.children[0].id).toBe('bar')\n  })\n\n  it('should warn message that virtual DOM tree is not matching when hydrate element', () => {\n    function createServerRenderedDOM () {\n      const root = document.createElement('div')\n      root.setAttribute(SSR_ATTR, 'true')\n      const span = document.createElement('span')\n      root.appendChild(span)\n      const div = document.createElement('div')\n      const child1 = document.createElement('span')\n      div.appendChild(child1)\n      root.appendChild(div)\n      return root\n    }\n    const node0 = createServerRenderedDOM()\n    const vnode1 = new VNode('div', {}, [\n      new VNode('span', {}),\n      new VNode('div', {}, [\n        new VNode('span', {}),\n        new VNode('span', {})\n      ])\n    ])\n    patch(node0, vnode1)\n    expect('The client-side rendered virtual DOM tree is not matching').toHaveBeenWarned()\n  })\n\n  // component hydration is better off with a more e2e approach\n  it('should hydrate components when server-rendered DOM tree is same as virtual DOM tree', done => {\n    const dom = createMockSSRDOM('<span>foo</span><div class=\"b a\"><span>foo qux</span></div><!---->')\n    const originalNode1 = dom.children[0]\n    const originalNode2 = dom.children[1]\n\n    const vm = new Vue({\n      template: '<div><span>{{msg}}</span><test class=\"a\" :msg=\"msg\"></test><p v-if=\"ok\"></p></div>',\n      data: {\n        msg: 'foo',\n        ok: false\n      },\n      components: {\n        test: {\n          props: ['msg'],\n          data () {\n            return { a: 'qux' }\n          },\n          template: '<div class=\"b\"><span>{{msg}} {{a}}</span></div>'\n        }\n      }\n    })\n\n    expect(() => { vm.$mount(dom) }).not.toThrow()\n    expect('not matching server-rendered content').not.toHaveBeenWarned()\n    expect(vm.$el).toBe(dom)\n    expect(vm.$children[0].$el).toBe(originalNode2)\n    expect(vm.$el.children[0]).toBe(originalNode1)\n    expect(vm.$el.children[1]).toBe(originalNode2)\n    vm.msg = 'bar'\n    waitForUpdate(() => {\n      expect(vm.$el.innerHTML).toBe('<span>bar</span><div class=\"b a\"><span>bar qux</span></div><!---->')\n      vm.$children[0].a = 'ququx'\n    }).then(() => {\n      expect(vm.$el.innerHTML).toBe('<span>bar</span><div class=\"b a\"><span>bar ququx</span></div><!---->')\n      vm.ok = true\n    }).then(() => {\n      expect(vm.$el.innerHTML).toBe('<span>bar</span><div class=\"b a\"><span>bar ququx</span></div><p></p>')\n    }).then(done)\n  })\n\n  it('should warn failed hydration for non-matching DOM in child component', () => {\n    const dom = createMockSSRDOM('<div><span></span></div>')\n\n    new Vue({\n      template: '<div><test></test></div>',\n      components: {\n        test: {\n          template: '<div><a></a></div>'\n        }\n      }\n    }).$mount(dom)\n\n    expect('not matching server-rendered content').toHaveBeenWarned()\n  })\n\n  it('should overwrite textNodes in the correct position but with mismatching text without warning', () => {\n    const dom = createMockSSRDOM('<div><span>foo</span></div>')\n\n    new Vue({\n      template: '<div><test></test></div>',\n      components: {\n        test: {\n          data () {\n            return { a: 'qux' }\n          },\n          template: '<div><span>{{a}}</span></div>'\n        }\n      }\n    }).$mount(dom)\n\n    expect('not matching server-rendered content').not.toHaveBeenWarned()\n    expect(dom.querySelector('span').textContent).toBe('qux')\n  })\n\n  it('should pick up elements with no children and populate without warning', done => {\n    const dom = createMockSSRDOM('<div><span></span></div>')\n    const span = dom.querySelector('span')\n\n    const vm = new Vue({\n      template: '<div><test></test></div>',\n      components: {\n        test: {\n          data () {\n            return { a: 'qux' }\n          },\n          template: '<div><span>{{a}}</span></div>'\n        }\n      }\n    }).$mount(dom)\n\n    expect('not matching server-rendered content').not.toHaveBeenWarned()\n    expect(span).toBe(vm.$el.querySelector('span'))\n    expect(vm.$el.innerHTML).toBe('<div><span>qux</span></div>')\n\n    vm.$children[0].a = 'foo'\n    waitForUpdate(() => {\n      expect(vm.$el.innerHTML).toBe('<div><span>foo</span></div>')\n    }).then(done)\n  })\n\n  it('should hydrate async component', done => {\n    const dom = createMockSSRDOM('<span>foo</span>')\n    const span = dom.querySelector('span')\n\n    const Foo = resolve => setTimeout(() => {\n      resolve({\n        data: () => ({ msg: 'foo' }),\n        template: `<span>{{ msg }}</span>`\n      })\n    }, 0)\n\n    const vm = new Vue({\n      template: '<div><foo ref=\"foo\" /></div>',\n      components: { Foo }\n    }).$mount(dom)\n\n    expect('not matching server-rendered content').not.toHaveBeenWarned()\n    expect(dom.innerHTML).toBe('<span>foo</span>')\n    expect(vm.$refs.foo).toBeUndefined()\n\n    setTimeout(() => {\n      expect(dom.innerHTML).toBe('<span>foo</span>')\n      expect(vm.$refs.foo).not.toBeUndefined()\n      vm.$refs.foo.msg = 'bar'\n      waitForUpdate(() => {\n        expect(dom.innerHTML).toBe('<span>bar</span>')\n        expect(dom.querySelector('span')).toBe(span)\n      }).then(done)\n    }, 10)\n  })\n\n  it('should hydrate async component without showing loading', done => {\n    const dom = createMockSSRDOM('<span>foo</span>')\n    const span = dom.querySelector('span')\n\n    const Foo = () => ({\n      component: new Promise(resolve => {\n        setTimeout(() => {\n          resolve({\n            data: () => ({ msg: 'foo' }),\n            template: `<span>{{ msg }}</span>`\n          })\n        }, 10)\n      }),\n      delay: 1,\n      loading: {\n        render: h => h('span', 'loading')\n      }\n    })\n\n    const vm = new Vue({\n      template: '<div><foo ref=\"foo\" /></div>',\n      components: { Foo }\n    }).$mount(dom)\n\n    expect('not matching server-rendered content').not.toHaveBeenWarned()\n    expect(dom.innerHTML).toBe('<span>foo</span>')\n    expect(vm.$refs.foo).toBeUndefined()\n\n    setTimeout(() => {\n      expect(dom.innerHTML).toBe('<span>foo</span>')\n    }, 2)\n\n    setTimeout(() => {\n      expect(dom.innerHTML).toBe('<span>foo</span>')\n      expect(vm.$refs.foo).not.toBeUndefined()\n      vm.$refs.foo.msg = 'bar'\n      waitForUpdate(() => {\n        expect(dom.innerHTML).toBe('<span>bar</span>')\n        expect(dom.querySelector('span')).toBe(span)\n      }).then(done)\n    }, 50)\n  })\n\n  it('should hydrate async component by replacing DOM if error occurs', done => {\n    const dom = createMockSSRDOM('<span>foo</span>')\n\n    const Foo = () => ({\n      component: new Promise((resolve, reject) => {\n        setTimeout(() => {\n          reject('something went wrong')\n        }, 10)\n      }),\n      error: {\n        render: h => h('span', 'error')\n      }\n    })\n\n    new Vue({\n      template: '<div><foo ref=\"foo\" /></div>',\n      components: { Foo }\n    }).$mount(dom)\n\n    expect('not matching server-rendered content').not.toHaveBeenWarned()\n    expect(dom.innerHTML).toBe('<span>foo</span>')\n\n    setTimeout(() => {\n      expect('Failed to resolve async').toHaveBeenWarned()\n      expect(dom.innerHTML).toBe('<span>error</span>')\n      done()\n    }, 50)\n  })\n})\n"
  },
  {
    "path": "test/weex/.eslintrc",
    "content": "{\n  \"env\": {\n    \"jasmine\": true\n  },\n  \"plugins\": [\"jasmine\"],\n  \"rules\": {\n    \"jasmine/no-focused-tests\": 2\n  }\n}\n"
  },
  {
    "path": "test/weex/compiler/append.spec.js",
    "content": "import { compile } from '../../../packages/weex-template-compiler'\nimport { strToRegExp } from '../helpers/index'\n\ndescribe('append props', () => {\n  it('append=\"tree\"', () => {\n    const { render, staticRenderFns, errors } = compile(`<list><cell></cell></list>`)\n    expect(render).not.toBeUndefined()\n    expect(staticRenderFns).not.toBeUndefined()\n    expect(staticRenderFns.length).toEqual(1)\n    expect(staticRenderFns).toMatch(strToRegExp(`appendAsTree:true`))\n    expect(staticRenderFns).toMatch(strToRegExp(`attrs:{\"append\":\"tree\"}`))\n    expect(errors).toEqual([])\n  })\n})\n"
  },
  {
    "path": "test/weex/compiler/class.spec.js",
    "content": "import { compile } from '../../../packages/weex-template-compiler'\nimport { strToRegExp } from '../helpers/index'\n\ndescribe('compile class', () => {\n  it('should be compiled', () => {\n    const { render, staticRenderFns, errors } = compile(`<div class=\"a b c\"></div>`)\n    expect(render).not.toBeUndefined()\n    expect(staticRenderFns).not.toBeUndefined()\n    expect(staticRenderFns.length).toEqual(0)\n    expect(render).toMatch(strToRegExp(`staticClass:[\"a\",\"b\",\"c\"]`))\n    expect(errors).toEqual([])\n  })\n\n  it('should compile dynamic class', () => {\n    const { render, staticRenderFns, errors } = compile(`<div class=\"a {{b}} c\"></div>`)\n    expect(render).not.toBeUndefined()\n    expect(staticRenderFns).toEqual([])\n    expect(render).toMatch(strToRegExp(`class:[\"a\",_s(b),\"c\"]`))\n    expect(errors).not.toBeUndefined()\n    expect(errors.length).toEqual(1)\n    expect(errors[0]).toMatch(strToRegExp(`a {{b}} c`))\n    expect(errors[0]).toMatch(strToRegExp(`v-bind`))\n  })\n\n  it('should compile class binding of array', () => {\n    const { render, staticRenderFns, errors } = compile(`<div v-bind:class=\"['a', 'b', c]\"></div>`)\n    expect(render).not.toBeUndefined()\n    expect(staticRenderFns).toEqual([])\n    expect(render).toMatch(strToRegExp(`class:['a', 'b', c]`))\n    expect(errors).toEqual([])\n  })\n\n  it('should compile class binding of map', () => {\n    const { render, staticRenderFns, errors } = compile(`<div v-bind:class=\"{ a: true, b: x }\"></div>`)\n    expect(render).not.toBeUndefined()\n    expect(staticRenderFns).toEqual([])\n    expect(render).toMatch(strToRegExp(`class:{ a: true, b: x }`))\n    expect(errors).toEqual([])\n  })\n\n  it('should compile class binding of a variable', () => {\n    const { render, staticRenderFns, errors } = compile(`<div v-bind:class=\"x\"></div>`)\n    expect(render).not.toBeUndefined()\n    expect(staticRenderFns).toEqual([])\n    expect(render).toMatch(strToRegExp(`class:x`))\n    expect(errors).toEqual([])\n  })\n\n  it('should compile class binding by shorthand', () => {\n    const { render, staticRenderFns, errors } = compile(`<div :class=\"['a', 'b', c]\"></div>`)\n    expect(render).not.toBeUndefined()\n    expect(staticRenderFns).toEqual([])\n    expect(render).toMatch(strToRegExp(`class:['a', 'b', c]`))\n    expect(errors).toEqual([])\n  })\n})\n"
  },
  {
    "path": "test/weex/compiler/compile.spec.js",
    "content": "import { compile } from '../../../packages/weex-template-compiler'\nimport { strToRegExp } from '../helpers/index'\n\ndescribe('compile basic', () => {\n  it('should be compiled', () => {\n    const { render, staticRenderFns, errors } = compile(`<div>{{hi}}</div>`)\n    expect(render).toEqual(`with(this){return _c('div',[_v(_s(hi))])}`)\n    expect(staticRenderFns.length).toBe(0)\n    expect(errors).toEqual([])\n  })\n\n  it('should compile data bindings', () => {\n    const { render, staticRenderFns, errors } = compile(`<div :a=\"b\"></div>`)\n    expect(render).toEqual(`with(this){return _c('div',{attrs:{\"a\":b}})}`)\n    expect(staticRenderFns).toEqual([])\n    expect(errors).toEqual([])\n  })\n\n  it('should compile event bindings', () => {\n    const { render, staticRenderFns, errors } = compile(`<div @click=\"x\"></div>`)\n    expect(render).toEqual(`with(this){return _c('div',{on:{\"click\":x}})}`)\n    expect(staticRenderFns).toEqual([])\n    expect(errors).toEqual([])\n  })\n\n  it('should compile data bindings with children', () => {\n    const { render, staticRenderFns, errors } = compile(`<foo :a=\"b\"><text>Hello</text></foo>`)\n    expect(render).toEqual(`with(this){return _c('foo',{attrs:{\"a\":b}},[_c('text',[_v(\"Hello\")])])}`)\n    expect(staticRenderFns).toEqual([])\n    expect(errors).toEqual([])\n  })\n\n  it('should compile unary tag', () => {\n    const inputCase = compile(`<div><input><text>abc</text></div>`)\n    expect(inputCase.render).toMatch(strToRegExp(`return _m(0)`))\n    expect(inputCase.staticRenderFns).toMatch(strToRegExp(`_c('div',[_c('input'),_c('text',[_v(\"abc\")])])`))\n    expect(inputCase.errors).toEqual([])\n\n    const imageCase = compile(`<div><image src=\"path\"><text>abc</text></div>`)\n    expect(imageCase.render).toMatch(strToRegExp(`return _m(0)`))\n    expect(imageCase.staticRenderFns).toMatch(strToRegExp(`_c('div',[_c('image',{attrs:{\"src\":\"path\"}}),_c('text',[_v(\"abc\")])])`))\n    expect(imageCase.errors).toEqual([])\n\n    const complexCase = compile(`\n      <div>\n        <image src=\"path\">\n        <image></image>\n        <div>\n          <embed>\n          <text>start</text>\n          <input type=\"text\">\n          <input type=\"url\" />\n          <text>end</text>\n        </div>\n      </div>\n    `)\n    expect(complexCase.render).toMatch(strToRegExp(`return _m(0)`))\n    expect(complexCase.staticRenderFns).toMatch(strToRegExp(`_c('image',{attrs:{\"src\":\"path\"}}),_c('image'),_c('div'`))\n    expect(complexCase.staticRenderFns).toMatch(strToRegExp(`_c('div',[_c('embed'),_c('text',[_v(\"start\")]),_c('input',{attrs:{\"type\":\"text\"}}),_c('input',{attrs:{\"type\":\"url\"}}),_c('text',[_v(\"end\")])]`))\n    expect(complexCase.errors).toEqual([])\n  })\n\n  it('should compile more complex situation', () => {\n    // from examples of https://github.com/alibaba/weex\n    const { render, staticRenderFns, errors } = compile(`\n      <refresh class=\"refresh\" @refresh=\"handleRefresh\" :display=\"displayRefresh\"\n        style=\"flex-direction:row;\">\n        <loading-indicator></loading-indicator>\n        <text style=\"margin-left:36px;color:#eee;\">Load more...</text>\n      </refresh>\n    `)\n    expect(render).toEqual(`with(this){return _c('refresh',{staticClass:[\"refresh\"],staticStyle:{flexDirection:\"row\"},attrs:{\"display\":displayRefresh},on:{\"refresh\":handleRefresh}},[_c('loading-indicator'),_c('text',{staticStyle:{marginLeft:\"36px\",color:\"#eee\"}},[_v(\"Load more...\")])])}`)\n    expect(staticRenderFns).toEqual([])\n    expect(errors).toEqual([])\n  })\n})\n"
  },
  {
    "path": "test/weex/compiler/props.spec.js",
    "content": "import { compile } from '../../../packages/weex-template-compiler'\nimport { strToRegExp } from '../helpers/index'\n\ndescribe('compile props', () => {\n  it('custom props', () => {\n    const { render, staticRenderFns, errors } = compile(`<div custom=\"whatever\"></div>`)\n    expect(render).not.toBeUndefined()\n    expect(staticRenderFns).not.toBeUndefined()\n    expect(staticRenderFns.length).toEqual(0)\n    expect(render).toMatch(strToRegExp(`attrs:{\"custom\":\"whatever\"}`))\n    expect(errors).toEqual([])\n  })\n\n  it('camelize props', () => {\n    const { render, staticRenderFns, errors } = compile(`<div kebab-case=\"whatever\"></div>`)\n    expect(render).not.toBeUndefined()\n    expect(staticRenderFns).not.toBeUndefined()\n    expect(staticRenderFns.length).toEqual(0)\n    expect(render).toMatch(strToRegExp(`attrs:{\"kebabCase\":\"whatever\"}`))\n    expect(errors).toEqual([])\n  })\n})\n"
  },
  {
    "path": "test/weex/compiler/style.spec.js",
    "content": "import { compile } from '../../../packages/weex-template-compiler'\nimport { strToRegExp } from '../helpers/index'\n\ndescribe('compile style', () => {\n  it('should be compiled', () => {\n    const { render, staticRenderFns, errors } = compile(`<div style=\"a: x; b: y\"></div>`)\n    expect(render).not.toBeUndefined()\n    expect(staticRenderFns).not.toBeUndefined()\n    expect(staticRenderFns.length).toEqual(0)\n    expect(render).toMatch(strToRegExp(`staticStyle:{a:\"x\",b:\"y\"}`))\n    expect(errors).toEqual([])\n  })\n\n  it('should compile empty style value', () => {\n    const { render, staticRenderFns, errors } = compile(`<div style=\"\"></div>`)\n    expect(render).not.toBeUndefined()\n    expect(staticRenderFns).not.toBeUndefined()\n    expect(staticRenderFns.length).toEqual(0)\n    expect(render).toMatch(/[(^style|^staticStyle)]/)\n    expect(errors).toEqual([])\n  })\n\n  it('should compile style value with trailing semicolon', () => {\n    const { render, staticRenderFns, errors } = compile(`<div style=\"a: x; b: y;\"></div>`)\n    expect(render).not.toBeUndefined()\n    expect(staticRenderFns).not.toBeUndefined()\n    expect(staticRenderFns.length).toEqual(0)\n    expect(render).toMatch(strToRegExp(`staticStyle:{a:\"x\",b:\"y\"}`))\n    expect(errors).toEqual([])\n  })\n\n  it('should compile hyphenated style name & value', () => {\n    const { render, staticRenderFns, errors } = compile(`<div style=\"-abc-def: x-y; abc-def: x-y\"></div>`)\n    expect(render).not.toBeUndefined()\n    expect(staticRenderFns).not.toBeUndefined()\n    expect(staticRenderFns.length).toEqual(0)\n    expect(render).toMatch(strToRegExp(`staticStyle:{AbcDef:\"x-y\",abcDef:\"x-y\"}`))\n    expect(errors).toEqual([])\n  })\n\n  it('should compile dynamic style', () => {\n    const { render, staticRenderFns, errors } = compile(`<div style=\"a: x; b: {{y}}\"></div>`)\n    expect(render).not.toBeUndefined()\n    expect(staticRenderFns).toEqual([])\n    expect(render).toMatch(strToRegExp(`style:{a:\"x\",b:_s(y)}`))\n    expect(errors).not.toBeUndefined()\n    expect(errors.length).toEqual(1)\n    expect(errors[0]).toMatch(strToRegExp(`b: {{y}}`))\n    expect(errors[0]).toMatch(strToRegExp(`v-bind`))\n  })\n\n  it('should compile style binding of array', () => {\n    const { render, staticRenderFns, errors } = compile(`<div v-bind:style=\"[a, b, c]\"></div>`)\n    expect(render).not.toBeUndefined()\n    expect(staticRenderFns).toEqual([])\n    expect(render).toMatch(strToRegExp(`style:[a, b, c]`))\n    expect(errors).toEqual([])\n  })\n\n  it('should compile style binding of map', () => {\n    const { render, staticRenderFns, errors } = compile(`<div v-bind:style=\"{ a: x, b: 'y' + z }\"></div>`)\n    expect(render).not.toBeUndefined()\n    expect(staticRenderFns).toEqual([])\n    expect(render).toMatch(strToRegExp(`style:{ a: x, b: 'y' + z }`))\n    expect(errors).toEqual([])\n  })\n\n  it('should compile style binding of a variable', () => {\n    const { render, staticRenderFns, errors } = compile(`<div v-bind:style=\"x\"></div>`)\n    expect(render).not.toBeUndefined()\n    expect(staticRenderFns).toEqual([])\n    expect(render).toMatch(strToRegExp(`style:x`))\n    expect(errors).toEqual([])\n  })\n\n  it('should compile style binding by shorthand', () => {\n    const { render, staticRenderFns, errors } = compile(`<div :style=\"[a, b, c]\"></div>`)\n    expect(render).not.toBeUndefined()\n    expect(staticRenderFns).toEqual([])\n    expect(render).toMatch(strToRegExp(`style:[a, b, c]`))\n    expect(errors).toEqual([])\n  })\n})\n"
  },
  {
    "path": "test/weex/compiler/v-model.spec.js",
    "content": "import { compile } from '../../../packages/weex-template-compiler'\nimport { strToRegExp } from '../helpers/index'\n\ndescribe('compile v-model', () => {\n  it('should compile modelable native component', () => {\n    const { render, staticRenderFns, errors } = compile(`<div><input v-model=\"x\" /></div>`)\n    expect(render).not.toBeUndefined()\n    expect(render).toMatch(strToRegExp(`attrs:{\"value\":(x)}`))\n    expect(render).toMatch(strToRegExp(`on:{\"input\":function($event){x=$event.target.attr.value}}`))\n    expect(staticRenderFns).toEqual([])\n    expect(errors).toEqual([])\n  })\n\n  it('should compile other component with whole $event as the value', () => {\n    const { render, staticRenderFns, errors } = compile(`<div><foo v-model=\"x\" /></div>`)\n    expect(render).not.toBeUndefined()\n    expect(render).toMatch(strToRegExp(`model:{value:(x),callback:function ($$v) {x=$$v},expression:\"x\"}`))\n    expect(staticRenderFns).toEqual([])\n    expect(errors).toEqual([])\n  })\n\n  it('should compile with trim modifier for modelable native component', () => {\n    const { render, staticRenderFns, errors } = compile(`<div><input v-model.trim=\"x\" /></div>`)\n    expect(render).not.toBeUndefined()\n    expect(render).toMatch(strToRegExp(`attrs:{\"value\":(x)}`))\n    expect(render).toMatch(strToRegExp(`on:{\"input\":function($event){x=$event.target.attr.value.trim()}}`))\n    expect(staticRenderFns).toEqual([])\n    expect(errors).toEqual([])\n  })\n\n  it('should compile with trim & lazy modifier', () => {\n    const { render, staticRenderFns, errors } = compile(`<div><input v-model.trim.lazy=\"x\" /><input v-model.lazy.trim=\"y\" /></div>`)\n    expect(render).not.toBeUndefined()\n    expect(render).toMatch(strToRegExp(`attrs:{\"value\":(x)}`))\n    expect(render).toMatch(strToRegExp(`attrs:{\"value\":(y)}`))\n    expect(render).toMatch(strToRegExp(`on:{\"change\":function($event){x=$event.target.attr.value.trim()}}`))\n    expect(render).toMatch(strToRegExp(`on:{\"change\":function($event){y=$event.target.attr.value.trim()}}`))\n    expect(staticRenderFns).toEqual([])\n    expect(errors).toEqual([])\n  })\n})\n"
  },
  {
    "path": "test/weex/helpers/index.js",
    "content": "// suppress logs from vdom-tester\nconst domModule = require('weex-vdom-tester/lib/modules/dom')\ndomModule.updateFinish = domModule.createFinish = domModule.refreshFinish = () => {}\n\nimport * as Vue from '../../../packages/weex-vue-framework'\nimport { compile } from '../../../packages/weex-template-compiler'\nimport { Runtime, Instance } from 'weex-vdom-tester'\nimport { init, config } from 'weex-js-runtime'\n\ninit()\n\n// http://stackoverflow.com/a/35478115\nconst matchOperatorsRe = /[|\\\\{}()[\\]^$+*?.]/g\nexport function strToRegExp (str) {\n  return new RegExp(str.replace(matchOperatorsRe, '\\\\$&'))\n}\n\nexport function compileAndStringify (template) {\n  const { render, staticRenderFns } = compile(template)\n  return {\n    render: `function () { ${render} }`,\n    staticRenderFns: parseStatic(staticRenderFns)\n  }\n}\n\nfunction parseStatic (fns) {\n  return '[' + fns.map(fn => `function () { ${fn} }`).join(',') + ']'\n}\n\nexport function prepareRuntime () {\n  let sendTasksHandler = function () {}\n  config.sendTasks = config.Document.handler = function () {\n    sendTasksHandler.apply(null, arguments)\n  }\n  Vue.init(config)\n  const runtime = new Runtime(Vue)\n  sendTasksHandler = function () {\n    runtime.target.callNative.apply(runtime.target, arguments)\n  }\n  return runtime\n}\n\nexport function resetRuntime () {\n  delete config.Document.handler\n  Vue.reset()\n}\n\nexport function createInstance (runtime, code) {\n  const instance = new Instance(runtime)\n  if (code) {\n    instance.$create(code)\n  }\n  return instance\n}\n\nexport function syncPromise (arr) {\n  let p = Promise.resolve()\n  arr.forEach(item => {\n    p = p.then(item)\n  })\n  return p\n}\n\nexport function checkRefresh (instance, data, checker) {\n  return () => new Promise(res => {\n    instance.$refresh(data)\n    setTimeout(() => {\n      checker(instance.getRealRoot())\n      res()\n    })\n  })\n}\n"
  },
  {
    "path": "test/weex/jasmine.json",
    "content": "{\n  \"spec_dir\": \"test/weex\",\n  \"spec_files\": [\n    \"**/*[sS]pec.js\"\n  ],\n  \"helpers\": [\n    \"../../node_modules/babel-register/lib/node.js\"\n  ]\n}\n"
  },
  {
    "path": "test/weex/runtime/attrs.spec.js",
    "content": "import {\n  compileAndStringify,\n  prepareRuntime,\n  resetRuntime,\n  createInstance\n} from '../helpers/index'\n\ndescribe('generate attribute', () => {\n  let runtime\n\n  beforeAll(() => {\n    runtime = prepareRuntime()\n  })\n\n  afterAll(() => {\n    resetRuntime()\n    runtime = null\n  })\n\n  it('should be generated', () => {\n    const { render, staticRenderFns } = compileAndStringify(`\n      <div>\n        <text value=\"Hello World\" style=\"font-size: 100\"></text>\n      </div>\n    `)\n    const instance = createInstance(runtime, `\n      new Vue({\n        render: ${render},\n        staticRenderFns: ${staticRenderFns},\n        el: 'body'\n      })\n    `)\n    expect(instance.getRealRoot()).toEqual({\n      type: 'div',\n      children: [\n        { type: 'text', style: { fontSize: '100' }, attr: { value: 'Hello World' }}\n      ]\n    })\n  })\n\n  it('should be updated', (done) => {\n    const { render, staticRenderFns } = compileAndStringify(`\n      <div @click=\"foo\">\n        <text :value=\"x\"></text>\n      </div>\n    `)\n    const instance = createInstance(runtime, `\n      new Vue({\n        data: {\n          x: 'Hello World'\n        },\n        methods: {\n          foo: function () {\n            this.x = 'Hello Vue'\n          }\n        },\n        render: ${render},\n        staticRenderFns: ${staticRenderFns},\n        el: \"body\"\n      })\n    `)\n    expect(instance.getRealRoot()).toEqual({\n      type: 'div',\n      event: ['click'],\n      children: [\n        { type: 'text', attr: { value: 'Hello World' }}\n      ]\n    })\n\n    instance.$fireEvent(instance.doc.body.ref, 'click', {})\n    setTimeout(() => {\n      expect(instance.getRealRoot()).toEqual({\n        type: 'div',\n        event: ['click'],\n        children: [\n          { type: 'text', attr: { value: 'Hello Vue' }}\n        ]\n      })\n      done()\n    })\n  })\n\n  it('should be cleared', (done) => {\n    const { render, staticRenderFns } = compileAndStringify(`\n      <div @click=\"foo\">\n        <text :value=\"x\"></text>\n      </div>\n    `)\n    const instance = createInstance(runtime, `\n      new Vue({\n        data: {\n          x: 'Hello World'\n        },\n        methods: {\n          foo: function () {\n            this.x = ''\n          }\n        },\n        render: ${render},\n        staticRenderFns: ${staticRenderFns},\n        el: \"body\"\n      })\n    `)\n    expect(instance.getRealRoot()).toEqual({\n      type: 'div',\n      event: ['click'],\n      children: [\n        { type: 'text', attr: { value: 'Hello World' }}\n      ]\n    })\n\n    instance.$fireEvent(instance.doc.body.ref, 'click', {})\n    setTimeout(() => {\n      expect(instance.getRealRoot()).toEqual({\n        type: 'div',\n        event: ['click'],\n        children: [\n          { type: 'text', attr: { value: '' }}\n        ]\n      })\n      done()\n    })\n  })\n})\n"
  },
  {
    "path": "test/weex/runtime/class.spec.js",
    "content": "import {\n  compileAndStringify,\n  prepareRuntime,\n  resetRuntime,\n  createInstance\n} from '../helpers/index'\n\ndescribe('generate class', () => {\n  let runtime\n\n  beforeAll(() => {\n    runtime = prepareRuntime()\n  })\n\n  afterAll(() => {\n    resetRuntime()\n    runtime = null\n  })\n\n  it('should be generated', () => {\n    const { render, staticRenderFns } = compileAndStringify(`\n      <div>\n        <text class=\"a b c\">Hello World</text>\n      </div>\n    `)\n    const instance = createInstance(runtime, `\n      new Vue({\n        render: ${render},\n        staticRenderFns: ${staticRenderFns},\n        style: {\n          a: {\n            fontSize: '100'\n          },\n          b: {\n            color: '#ff0000'\n          },\n          c: {\n            fontWeight: 'bold'\n          }\n        },\n        el: 'body'\n      })\n    `)\n    expect(instance.getRealRoot()).toEqual({\n      type: 'div',\n      children: [\n        { type: 'text', style: { fontSize: '100', color: '#ff0000', fontWeight: 'bold' }, attr: { value: 'Hello World' }}\n      ]\n    })\n  })\n\n  it('should be updated', (done) => {\n    const { render, staticRenderFns } = compileAndStringify(`\n      <div>\n        <text :class=\"['a', x]\" @click=\"foo\">Hello World</text>\n      </div>\n    `)\n    const instance = createInstance(runtime, `\n      new Vue({\n        data: {\n          x: 'b'\n        },\n        render: ${render},\n        staticRenderFns: ${staticRenderFns},\n        style: {\n          a: {\n            fontSize: '100'\n          },\n          b: {\n            color: '#ff0000'\n          },\n          c: {\n            fontWeight: 'bold'\n          },\n          d: {\n            color: '#0000ff',\n            fontWeight: 'bold'\n          }\n        },\n        methods: {\n          foo: function () {\n            this.x = 'd'\n          }\n        },\n        el: 'body'\n      })\n    `)\n    expect(instance.getRealRoot()).toEqual({\n      type: 'div',\n      children: [\n        {\n          type: 'text',\n          event: ['click'],\n          style: { fontSize: '100', color: '#ff0000' },\n          attr: { value: 'Hello World' }\n        }\n      ]\n    })\n\n    instance.$fireEvent(instance.doc.body.children[0].ref, 'click', {})\n    setTimeout(() => {\n      expect(instance.getRealRoot()).toEqual({\n        type: 'div',\n        children: [\n          {\n            type: 'text',\n            event: ['click'],\n            style: { fontSize: '100', color: '#0000ff', fontWeight: 'bold' },\n            attr: { value: 'Hello World' }\n          }\n        ]\n      })\n      done()\n    })\n  })\n\n  it('should be applied in order', (done) => {\n    const { render, staticRenderFns } = compileAndStringify(`\n      <div>\n        <text :class=\"arr\" @click=\"foo\">Hello World</text>\n      </div>\n    `)\n    const instance = createInstance(runtime, `\n      new Vue({\n        data: {\n          arr: ['b', 'a']\n        },\n        render: ${render},\n        staticRenderFns: ${staticRenderFns},\n        style: {\n          a: {\n            color: '#ff0000'\n          },\n          b: {\n            color: '#00ff00'\n          },\n          c: {\n            color: '#0000ff'\n          }\n        },\n        methods: {\n          foo: function () {\n            this.arr.push('c')\n          }\n        },\n        el: 'body'\n      })\n    `)\n    expect(instance.getRealRoot()).toEqual({\n      type: 'div',\n      children: [\n        {\n          type: 'text',\n          event: ['click'],\n          style: { color: '#ff0000' },\n          attr: { value: 'Hello World' }\n        }\n      ]\n    })\n\n    instance.$fireEvent(instance.doc.body.children[0].ref, 'click', {})\n    setTimeout(() => {\n      expect(instance.getRealRoot()).toEqual({\n        type: 'div',\n        children: [\n          {\n            type: 'text',\n            event: ['click'],\n            style: { color: '#0000ff' },\n            attr: { value: 'Hello World' }\n          }\n        ]\n      })\n      done()\n    })\n  })\n\n  it('should be cleared', (done) => {\n    const { render, staticRenderFns } = compileAndStringify(`\n      <div>\n        <text :class=\"['a', x]\" @click=\"foo\">Hello World</text>\n      </div>\n    `)\n    const instance = createInstance(runtime, `\n      new Vue({\n        data: {\n          x: 'b'\n        },\n        render: ${render},\n        staticRenderFns: ${staticRenderFns},\n        style: {\n          a: {\n            fontSize: '100'\n          },\n          b: {\n            color: '#ff0000'\n          },\n          c: {\n            fontWeight: 'bold'\n          }\n        },\n        methods: {\n          foo: function () {\n            this.x = 'c'\n          }\n        },\n        el: 'body'\n      })\n    `)\n    expect(instance.getRealRoot()).toEqual({\n      type: 'div',\n      children: [\n        {\n          type: 'text',\n          event: ['click'],\n          style: { fontSize: '100', color: '#ff0000' },\n          attr: { value: 'Hello World' }\n        }\n      ]\n    })\n\n    instance.$fireEvent(instance.doc.body.children[0].ref, 'click', {})\n    setTimeout(() => {\n      expect(instance.getRealRoot()).toEqual({\n        type: 'div',\n        children: [\n          {\n            type: 'text',\n            event: ['click'],\n            style: { fontSize: '100', color: '', fontWeight: 'bold' },\n            attr: { value: 'Hello World' }\n          }\n        ]\n      })\n      done()\n    })\n  })\n})\n"
  },
  {
    "path": "test/weex/runtime/events.spec.js",
    "content": "import {\n  compileAndStringify,\n  prepareRuntime,\n  resetRuntime,\n  createInstance\n} from '../helpers/index'\n\ndescribe('generate events', () => {\n  let runtime\n\n  beforeAll(() => {\n    runtime = prepareRuntime()\n  })\n\n  afterAll(() => {\n    resetRuntime()\n    runtime = null\n  })\n\n  it('should be bound and fired for native component', (done) => {\n    const { render, staticRenderFns } = compileAndStringify(`\n      <div>\n        <text @click=\"foo\">Hello {{x}}</text>\n      </div>\n    `)\n    const instance = createInstance(runtime, `\n      new Vue({\n        data: {\n          x: 'World'\n        },\n        render: ${render},\n        staticRenderFns: ${staticRenderFns},\n        methods: {\n          foo: function () {\n            this.x = 'Weex'\n          }\n        },\n        el: 'body'\n      })\n    `)\n    expect(instance.getRealRoot()).toEqual({\n      type: 'div',\n      children: [\n        {\n          type: 'text',\n          event: ['click'],\n          attr: { value: 'Hello World' }\n        }\n      ]\n    })\n\n    instance.$fireEvent(instance.doc.body.children[0].ref, 'click', {})\n    setTimeout(() => {\n      expect(instance.getRealRoot()).toEqual({\n        type: 'div',\n        children: [\n          {\n            type: 'text',\n            event: ['click'],\n            attr: { value: 'Hello Weex' }\n          }\n        ]\n      })\n      done()\n    })\n  })\n\n  it('should be bound and fired by custom component', (done) => {\n    const subTemplate = compileAndStringify(`<text>Hello {{x}}</text>`)\n    const { render, staticRenderFns } = compileAndStringify(`\n      <div>\n        <text>Hello {{x}}</text>\n        <sub @click=\"foo\" @click.native=\"bar\"></sub>\n      </div>\n    `)\n    const instance = createInstance(runtime, `\n      new Vue({\n        data: {\n          x: 'World'\n        },\n        render: ${render},\n        staticRenderFns: ${staticRenderFns},\n        components: {\n          sub: {\n            data: function () {\n              return {\n                x: 'Sub'\n              }\n            },\n            render: ${subTemplate.render},\n            staticRenderFns: ${subTemplate.staticRenderFns},\n            created: function () {\n              this.$emit('click')\n            }\n          }\n        },\n        methods: {\n          foo: function () {\n            this.x = 'Foo'\n          },\n          bar: function () {\n            this.x = 'Bar'\n          }\n        },\n        el: 'body'\n      })\n    `)\n    setTimeout(() => {\n      expect(instance.getRealRoot()).toEqual({\n        type: 'div',\n        children: [\n          {\n            type: 'text',\n            attr: { value: 'Hello Foo' }\n          },\n          {\n            type: 'text',\n            event: ['click'],\n            attr: { value: 'Hello Sub' }\n          }\n        ]\n      })\n\n      instance.$fireEvent(instance.doc.body.children[1].ref, 'click', {})\n      setTimeout(() => {\n        expect(instance.getRealRoot()).toEqual({\n          type: 'div',\n          children: [\n            {\n              type: 'text',\n              attr: { value: 'Hello Bar' }\n            },\n            {\n              type: 'text',\n              event: ['click'],\n              attr: { value: 'Hello Sub' }\n            }\n          ]\n        })\n        done()\n      })\n    })\n  })\n})\n"
  },
  {
    "path": "test/weex/runtime/framework.spec.js",
    "content": "import * as framework from '../../../packages/weex-vue-framework'\nimport { DEFAULT_ENV, Runtime, Instance } from 'weex-vdom-tester'\nimport { config } from 'weex-js-runtime'\n\nimport {\n  syncPromise,\n  checkRefresh\n} from '../helpers/index'\n\nlet sendTasksHandler = () => {}\nconst { Document, Element, Comment } = config\nfunction sendTasks () {\n  sendTasksHandler.apply(null, arguments)\n}\n\ndescribe('framework APIs', () => {\n  let runtime\n\n  beforeEach(() => {\n    Document.handler = sendTasks\n    framework.init({ Document, Element, Comment, sendTasks })\n    runtime = new Runtime(framework)\n    sendTasksHandler = function () {\n      runtime.target.callNative(...arguments)\n    }\n  })\n\n  afterEach(() => {\n    delete Document.handler\n    framework.reset()\n  })\n\n  it('createInstance', () => {\n    const instance = new Instance(runtime)\n    framework.createInstance(instance.id, `\n      new Vue({\n        render: function (createElement) {\n          return createElement('div', {}, [\n            createElement('text', { attrs: { value: 'Hello' }}, [])\n          ])\n        },\n        el: \"body\"\n      })\n    `)\n    expect(instance.getRealRoot()).toEqual({\n      type: 'div',\n      children: [{ type: 'text', attr: { value: 'Hello' }}]\n    })\n  })\n\n  it('createInstance with config', () => {\n    const instance = new Instance(runtime)\n    framework.createInstance(instance.id, `\n      new Vue({\n        render: function (createElement) {\n          return createElement('div', {}, [\n            createElement('text', { attrs: { value: JSON.stringify(this.$getConfig()) }}, [])\n          ])\n        },\n        el: \"body\"\n      })\n    `, { bundleUrl: 'http://example.com/', a: 1, b: 2 })\n    expect(instance.getRealRoot()).toEqual({\n      type: 'div',\n      children: [{ type: 'text', attr: { value: '{\"bundleUrl\":\"http://example.com/\",\"a\":1,\"b\":2}' }}]\n    })\n  })\n\n  it('createInstance with external data', () => {\n    const instance = new Instance(runtime)\n    framework.createInstance(instance.id, `\n      new Vue({\n        data: {\n          a: 1,\n          b: 2\n        },\n        render: function (createElement) {\n          return createElement('div', {}, [\n            createElement('text', { attrs: { value: this.a + '-' + this.b }}, [])\n          ])\n        },\n        el: \"body\"\n      })\n    `, undefined, { a: 111 })\n    expect(instance.getRealRoot()).toEqual({\n      type: 'div',\n      children: [{ type: 'text', attr: { value: '111-2' }}]\n    })\n  })\n\n  it('destroyInstance', (done) => {\n    const instance = new Instance(runtime)\n    framework.createInstance(instance.id, `\n      new Vue({\n        data: {\n          x: 'Hello'\n        },\n        render: function (createElement) {\n          return createElement('div', {}, [\n            createElement('text', { attrs: { value: this.x }}, [])\n          ])\n        },\n        el: \"body\"\n      })\n    `)\n    expect(instance.getRealRoot()).toEqual({\n      type: 'div',\n      children: [{ type: 'text', attr: { value: 'Hello' }}]\n    })\n\n    syncPromise([\n      checkRefresh(instance, { x: 'World' }, result => {\n        expect(result).toEqual({\n          type: 'div',\n          children: [{ type: 'text', attr: { value: 'World' }}]\n        })\n        framework.destroyInstance(instance.id)\n      }),\n      checkRefresh(instance, { x: 'Weex' }, result => {\n        expect(result).toEqual({\n          type: 'div',\n          children: [{ type: 'text', attr: { value: 'World' }}]\n        })\n        done()\n      })\n    ])\n  })\n\n  it('refreshInstance', (done) => {\n    const instance = new Instance(runtime)\n    framework.createInstance(instance.id, `\n      new Vue({\n        data: {\n          x: 'Hello'\n        },\n        render: function (createElement) {\n          return createElement('div', {}, [\n            createElement('text', { attrs: { value: this.x }}, [])\n          ])\n        },\n        el: \"body\"\n      })\n    `)\n    expect(instance.getRealRoot()).toEqual({\n      type: 'div',\n      children: [{ type: 'text', attr: { value: 'Hello' }}]\n    })\n\n    framework.refreshInstance(instance.id, { x: 'World' })\n    setTimeout(() => {\n      expect(instance.getRealRoot()).toEqual({\n        type: 'div',\n        children: [{ type: 'text', attr: { value: 'World' }}]\n      })\n\n      framework.destroyInstance(instance.id)\n      const result = framework.refreshInstance(instance.id, { x: 'Weex' })\n      expect(result instanceof Error).toBe(true)\n      expect(result).toMatch(/refreshInstance/)\n      expect(result).toMatch(/not found/)\n\n      setTimeout(() => {\n        expect(instance.getRealRoot()).toEqual({\n          type: 'div',\n          children: [{ type: 'text', attr: { value: 'World' }}]\n        })\n        done()\n      })\n    })\n  })\n\n  it('getRoot', () => {\n    const instance = new Instance(runtime)\n    framework.createInstance(instance.id, `\n      new Vue({\n        data: {\n          x: 'Hello'\n        },\n        render: function (createElement) {\n          return createElement('div', {}, [\n            createElement('text', { attrs: { value: this.x }}, [])\n          ])\n        },\n        el: \"body\"\n      })\n    `)\n\n    let root = framework.getRoot(instance.id)\n    expect(root.ref).toEqual('_root')\n    expect(root.type).toEqual('div')\n    expect(root.children.length).toEqual(1)\n    expect(root.children[0].type).toEqual('text')\n    expect(root.children[0].attr).toEqual({ value: 'Hello' })\n    framework.destroyInstance(instance.id)\n\n    root = framework.getRoot(instance.id)\n    expect(root instanceof Error).toBe(true)\n    expect(root).toMatch(/getRoot/)\n    expect(root).toMatch(/not found/)\n  })\n\n  it('receiveTasks: fireEvent', (done) => {\n    const instance = new Instance(runtime)\n    framework.createInstance(instance.id, `\n      new Vue({\n        data: {\n          x: 'Hello'\n        },\n        methods: {\n          update: function (e) {\n            this.x = 'World'\n          }\n        },\n        render: function (createElement) {\n          return createElement('div', {}, [\n            createElement('text', { attrs: { value: this.x }, on: { click: this.update }}, [])\n          ])\n        },\n        el: \"body\"\n      })\n    `)\n    expect(instance.getRealRoot()).toEqual({\n      type: 'div',\n      children: [{\n        type: 'text',\n        attr: { value: 'Hello' },\n        event: ['click']\n      }]\n    })\n\n    const textRef = framework.getRoot(instance.id).children[0].ref\n    framework.receiveTasks(instance.id, [\n      { method: 'fireEvent', args: [textRef, 'click'] }\n    ])\n\n    setTimeout(() => {\n      expect(instance.getRealRoot()).toEqual({\n        type: 'div',\n        children: [{\n          type: 'text',\n          attr: { value: 'World' },\n          event: ['click']\n        }]\n      })\n\n      framework.destroyInstance(instance.id)\n      const result = framework.receiveTasks(instance.id, [\n        { method: 'fireEvent', args: [textRef, 'click'] }\n      ])\n      expect(result instanceof Error).toBe(true)\n      expect(result).toMatch(/invalid\\sinstance\\sid/)\n      expect(result).toMatch(instance.id)\n      done()\n    })\n  })\n\n  it('receiveTasks: callback', (done) => {\n    framework.registerModules({\n      foo: ['a', 'b', 'c']\n    })\n\n    const instance = new Instance(runtime)\n    framework.createInstance(instance.id, `\n      const moduleFoo = __weex_require_module__('foo')\n      new Vue({\n        data: {\n          x: 'Hello'\n        },\n        methods: {\n          update: function (data = {}) {\n            this.x = data.value || 'World'\n          }\n        },\n        mounted: function () {\n          moduleFoo.a(data => {\n            this.update(data)\n          })\n        },\n        render: function (createElement) {\n          return createElement('div', {}, [\n            createElement('text', { attrs: { value: this.x }}, [])\n          ])\n        },\n        el: \"body\"\n      })\n    `)\n    expect(instance.getRealRoot()).toEqual({\n      type: 'div',\n      children: [{\n        type: 'text',\n        attr: { value: 'Hello' }\n      }]\n    })\n\n    let callbackId\n    instance.history.callNative.some(task => {\n      if (task.module === 'foo' && task.method === 'a') {\n        callbackId = task.args[0]\n        return true\n      }\n    })\n    framework.receiveTasks(instance.id, [\n      { method: 'callback', args: [callbackId, undefined, true] }\n    ])\n\n    setTimeout(() => {\n      expect(instance.getRealRoot()).toEqual({\n        type: 'div',\n        children: [{\n          type: 'text',\n          attr: { value: 'World' }\n        }]\n      })\n\n      framework.receiveTasks(instance.id, [\n        { method: 'callback', args: [callbackId, { value: 'Weex' }, true] }\n      ])\n      setTimeout(() => {\n        expect(instance.getRealRoot()).toEqual({\n          type: 'div',\n          children: [{\n            type: 'text',\n            attr: { value: 'Weex' }\n          }]\n        })\n\n        framework.receiveTasks(instance.id, [\n          { method: 'callback', args: [callbackId] }\n        ])\n        setTimeout(() => {\n          expect(instance.getRealRoot()).toEqual({\n            type: 'div',\n            children: [{\n              type: 'text',\n              attr: { value: 'World' }\n            }]\n          })\n\n          framework.destroyInstance(instance.id)\n          const result = framework.receiveTasks(instance.id, [\n            { method: 'callback', args: [callbackId] }\n          ])\n          expect(result instanceof Error).toBe(true)\n          expect(result).toMatch(/invalid\\sinstance\\sid/)\n          expect(result).toMatch(instance.id)\n          done()\n        })\n      })\n    })\n  })\n\n  it('registerModules', () => {\n    framework.registerModules({\n      foo: ['a', 'b', 'c'],\n      bar: [\n        { name: 'a', args: ['string'] },\n        { name: 'b', args: ['number'] },\n        { name: 'c', args: ['string', 'number'] }\n      ]\n    })\n\n    const instance = new Instance(runtime)\n    framework.createInstance(instance.id, `\n      const moduleFoo = __weex_require_module__('foo')\n      const moduleBar = __weex_require_module__('bar')\n      const moduleBaz = __weex_require_module__('baz')\n      new Vue({\n        render: function (createElement) {\n          const value = []\n          if (typeof moduleFoo === 'object') {\n            value.push('foo')\n            value.push(Object.keys(moduleFoo))\n          }\n          if (typeof moduleBar === 'object') {\n            value.push('bar')\n            value.push(Object.keys(moduleBar))\n          }\n          if (typeof moduleBaz === 'object') {\n            value.push('baz')\n            value.push(Object.keys(moduleBaz))\n          }\n          return createElement('div', {}, [\n            createElement('text', { attrs: { value: value.toString() }}, [])\n          ])\n        },\n        mounted: function () {\n          moduleFoo.a(1, '2', true)\n          moduleBar.b(1)\n        },\n        el: \"body\"\n      })\n    `)\n    expect(instance.getRealRoot()).toEqual({\n      type: 'div',\n      children: [{\n        type: 'text',\n        attr: { value: 'foo,a,b,c,bar,a,b,c,baz,' }\n      }]\n    })\n\n    expect(instance.history.callNative\n      .filter(task => task.module === 'foo')\n      .map(task => `${task.method}(${task.args})`)\n    ).toEqual(['a(1,2,true)'])\n\n    expect(instance.history.callNative\n      .filter(task => task.module === 'bar')\n      .map(task => `${task.method}(${task.args})`)\n    ).toEqual(['b(1)'])\n  })\n\n  it('isRegisteredModule', () => {\n    framework.registerModules({\n      foo: ['a', 'b'],\n      bar: [\n        { name: 'x', args: ['string'] },\n        { name: 'y', args: ['number'] }\n      ]\n    })\n    expect(framework.isRegisteredModule('foo')).toBe(true)\n    expect(framework.isRegisteredModule('bar')).toBe(true)\n    expect(framework.isRegisteredModule('foo', 'a')).toBe(true)\n    expect(framework.isRegisteredModule('foo', 'b')).toBe(true)\n    expect(framework.isRegisteredModule('bar', 'x')).toBe(true)\n    expect(framework.isRegisteredModule('bar', 'y')).toBe(true)\n    expect(framework.isRegisteredModule('FOO')).toBe(false)\n    expect(framework.isRegisteredModule(' bar ')).toBe(false)\n    expect(framework.isRegisteredModule('unknown')).toBe(false)\n    expect(framework.isRegisteredModule('#}{)=}')).toBe(false)\n    expect(framework.isRegisteredModule('foo', '')).toBe(false)\n    expect(framework.isRegisteredModule('foo', 'c')).toBe(false)\n    expect(framework.isRegisteredModule('bar', 'z')).toBe(false)\n    expect(framework.isRegisteredModule('unknown', 'unknown')).toBe(false)\n  })\n\n  it('registerComponents', () => {\n    framework.registerComponents(['foo', { type: 'bar' }, 'text'])\n    const instance = new Instance(runtime)\n    framework.createInstance(instance.id, `\n      new Vue({\n        render: function (createElement) {\n          return createElement('div', {}, [\n            createElement('text', {}, []),\n            createElement('foo', {}, []),\n            createElement('bar', {}, []),\n            createElement('baz', {}, [])\n          ])\n        },\n        el: \"body\"\n      })\n    `)\n    expect(instance.getRealRoot()).toEqual({\n      type: 'div',\n      children: [{ type: 'text' }, { type: 'foo' }, { type: 'bar' }, { type: 'baz' }]\n    })\n  })\n\n  it('isRegisteredComponent', () => {\n    framework.registerComponents(['foo', { type: 'bar' }, 'text'])\n    expect(framework.isRegisteredComponent('foo')).toBe(true)\n    expect(framework.isRegisteredComponent('bar')).toBe(true)\n    expect(framework.isRegisteredComponent('text')).toBe(true)\n    expect(framework.isRegisteredComponent('FOO')).toBe(false)\n    expect(framework.isRegisteredComponent(' bar ')).toBe(false)\n    expect(framework.isRegisteredComponent('<text>')).toBe(false)\n    expect(framework.isRegisteredComponent('#}{)=}')).toBe(false)\n  })\n\n  it('weex.supports', () => {\n    framework.registerComponents(['apple', { type: 'banana' }])\n    framework.registerModules({\n      cat: ['eat', 'sleep'],\n      dog: [\n        { name: 'bark', args: ['string'] }\n      ]\n    })\n    expect(framework.supports('@component/apple')).toBe(true)\n    expect(framework.supports('@component/banana')).toBe(true)\n    expect(framework.supports('@module/cat')).toBe(true)\n    expect(framework.supports('@module/cat.eat')).toBe(true)\n    expect(framework.supports('@module/cat.sleep')).toBe(true)\n    expect(framework.supports('@module/dog.bark')).toBe(true)\n    expect(framework.supports('@component/candy')).toBe(false)\n    expect(framework.supports('@module/bird')).toBe(false)\n    expect(framework.supports('@module/bird.sing')).toBe(false)\n    expect(framework.supports('@module/dog.sleep')).toBe(false)\n    expect(framework.supports('apple')).toBe(null)\n    expect(framework.supports('<banana>')).toBe(null)\n    expect(framework.supports('cat')).toBe(null)\n    expect(framework.supports('@dog')).toBe(null)\n    expect(framework.supports('@component/dog#bark')).toBe(null)\n  })\n\n  it('vm.$getConfig', () => {\n    const instance = new Instance(runtime)\n    instance.$create(`\n      new Vue({\n        render: function (createElement) {\n          return createElement('div', {}, [\n            createElement('text', { attrs: { value: JSON.stringify(this.$getConfig()) }}, [])\n          ])\n        },\n        el: \"body\"\n      })\n    `)\n    expect(JSON.parse(instance.getRealRoot().children[0].attr.value)).toEqual({ env: DEFAULT_ENV })\n\n    const instance2 = new Instance(runtime)\n    instance2.$create(`\n      new Vue({\n        render: function (createElement) {\n          return createElement('div', {}, [\n            createElement('text', { attrs: { value: JSON.stringify(this.$getConfig()) }}, [])\n          ])\n        },\n        el: \"body\"\n      })\n    `, undefined, { a: 1, b: 2 })\n    expect(JSON.parse(instance2.getRealRoot().children[0].attr.value)).toEqual({ a: 1, b: 2, env: DEFAULT_ENV })\n  })\n\n  it('Timer', (done) => {\n    const instance = new Instance(runtime)\n    instance.$create(`\n      new Vue({\n        data: {\n          x: 0,\n          y: 0\n        },\n        render: function (createElement) {\n          return createElement('div', {}, [\n            createElement('text', { attrs: { value: this.x + '-' + this.y }}, [])\n          ])\n        },\n        mounted: function () {\n          const now = Date.now()\n          let timer, timer2\n          setTimeout(() => {\n            this.x = 1\n            clearTimeout(timer)\n            clearInterval(timer2)\n            setInterval(() => {\n              this.y++\n            }, 600)\n          }, 2000)\n          timer = setTimeout(() => {\n            this.x = 3\n          }, 3000)\n          setTimeout(() => {\n            this.x = 3\n          }, 4000)\n          timer2 = setInterval(() => {\n            this.y++\n          }, 900)\n        },\n        el: \"body\"\n      })\n    `)\n    expect(instance.getRealRoot()).toEqual({\n      type: 'div',\n      children: [{ type: 'text', attr: { value: '0-0' }}]\n    })\n\n    setTimeout(() => {\n      expect(instance.getRealRoot().children[0].attr.value).toEqual('0-1')\n    }, 950)\n    setTimeout(() => {\n      expect(instance.getRealRoot().children[0].attr.value).toEqual('0-2')\n    }, 1850)\n    setTimeout(() => {\n      expect(instance.getRealRoot().children[0].attr.value).toEqual('1-2')\n    }, 2050)\n    setTimeout(() => {\n      expect(instance.getRealRoot().children[0].attr.value).toEqual('1-3')\n    }, 2650)\n    setTimeout(() => {\n      expect(instance.getRealRoot().children[0].attr.value).toEqual('1-4')\n    }, 3250)\n    setTimeout(() => {\n      framework.destroyInstance(instance.id)\n    }, 3500)\n    setTimeout(() => {\n      expect(instance.getRealRoot().children[0].attr.value).toEqual('1-4')\n      done()\n    }, 4100)\n  })\n\n  it('send function param', () => {\n    framework.registerModules({\n      foo: ['a']\n    })\n\n    const instance = new Instance(runtime)\n    framework.createInstance(instance.id, `\n      const moduleFoo = __weex_require_module__('foo')\n      new Vue({\n        mounted: function () {\n          moduleFoo.a(a => a + 1)\n        },\n        render: function (createElement) {\n          return createElement('div', {}, [\n            createElement('text', { attrs: { value: 'Hello' }}, [])\n          ])\n        },\n        el: \"body\"\n      })\n    `)\n\n    let callbackId\n    instance.history.callNative.some(task => {\n      if (task.module === 'foo' && task.method === 'a') {\n        callbackId = task.args[0]\n        return true\n      }\n    })\n\n    expect(typeof callbackId).toEqual('string')\n  })\n\n  it('send Element param', () => {\n    framework.registerModules({\n      foo: ['a']\n    })\n\n    const instance = new Instance(runtime)\n    framework.createInstance(instance.id, `\n      const moduleFoo = __weex_require_module__('foo')\n      new Vue({\n        mounted: function () {\n          moduleFoo.a(this.$refs.x)\n        },\n        render: function (createElement) {\n          return createElement('div', {}, [\n            createElement('text', { attrs: { value: 'Hello' }, ref: 'x' }, [])\n          ])\n        },\n        el: \"body\"\n      })\n    `)\n\n    let callbackId\n    instance.history.callNative.some(task => {\n      if (task.module === 'foo' && task.method === 'a') {\n        callbackId = task.args[0]\n        return true\n      }\n    })\n\n    expect(typeof callbackId).toEqual('string')\n  })\n\n  it('registering global assets', () => {\n    const instance = new Instance(runtime)\n    framework.createInstance(instance.id, `\n      Vue.component('test', {\n        render (h) {\n          return h('div', 'Hello')\n        }\n      })\n      new Vue({\n        render (h) {\n          return h('test')\n        },\n        el: 'body'\n      })\n    `)\n    expect(instance.getRealRoot()).toEqual({\n      type: 'div',\n      children: [{ type: 'text', attr: { value: 'Hello' }}]\n    })\n  })\n\n  it('adding prototype methods', () => {\n    const instance = new Instance(runtime)\n    framework.createInstance(instance.id, `\n      Vue.prototype.$test = () => 'Hello'\n      const Test = {\n        render (h) {\n          return h('div', this.$test())\n        }\n      }\n      new Vue({\n        render (h) {\n          return h(Test)\n        },\n        el: 'body'\n      })\n    `)\n    expect(instance.getRealRoot()).toEqual({\n      type: 'div',\n      children: [{ type: 'text', attr: { value: 'Hello' }}]\n    })\n  })\n\n  it('using global mixins', () => {\n    const instance = new Instance(runtime)\n    framework.createInstance(instance.id, `\n      Vue.mixin({\n        created () {\n          this.test = true\n        }\n      })\n      const Test = {\n        data: () => ({ test: false }),\n        render (h) {\n          return h('div', this.test ? 'Hello' : 'nope')\n        }\n      }\n      new Vue({\n        data: { test: false },\n        render (h) {\n          return this.test ? h(Test) : h('p')\n        },\n        el: 'body'\n      })\n    `)\n    expect(instance.getRealRoot()).toEqual({\n      type: 'div',\n      children: [{ type: 'text', attr: { value: 'Hello' }}]\n    })\n  })\n})\n"
  },
  {
    "path": "test/weex/runtime/node.spec.js",
    "content": "import {\n  compileAndStringify,\n  prepareRuntime,\n  resetRuntime,\n  createInstance,\n  syncPromise,\n  checkRefresh\n} from '../helpers/index'\n\ndescribe('node in render function', () => {\n  let runtime\n\n  beforeAll(() => {\n    runtime = prepareRuntime()\n  })\n\n  afterAll(() => {\n    resetRuntime()\n    runtime = null\n  })\n\n  it('should be generated', () => {\n    const instance = createInstance(runtime, `\n      new Vue({\n        render: function (createElement) {\n          return createElement('div', {}, [\n            createElement('text', { attrs: { value: 'Hello' }}, [])\n          ])\n        },\n        el: \"body\"\n      })\n    `)\n    expect(instance.getRealRoot()).toEqual({\n      type: 'div',\n      children: [\n        { type: 'text', attr: { value: 'Hello' }}\n      ]\n    })\n  })\n\n  it('should be generated with all types of text', () => {\n    const instance = createInstance(runtime, `\n      new Vue({\n        render: function (createElement) {\n          return createElement('div', {}, [\n            createElement('text', { attrs: { value: 'Hello' }}, []),\n            'World',\n            createElement('text', {}, ['Weex'])\n          ])\n        },\n        el: \"body\"\n      })\n    `)\n    expect(instance.getRealRoot()).toEqual({\n      type: 'div',\n      children: [\n        { type: 'text', attr: { value: 'Hello' }},\n        { type: 'text', attr: { value: 'World' }},\n        { type: 'text', attr: { value: 'Weex' }}\n      ]\n    })\n  })\n\n  it('should be generated with comments', () => {\n    // todo\n  })\n\n  it('should be generated with module diff', (done) => {\n    const instance = createInstance(runtime, `\n      new Vue({\n        data: {\n          counter: 0\n        },\n        methods: {\n          foo: function () {}\n        },\n        render: function (createElement) {\n          switch (this.counter) {\n            case 1:\n            return createElement('div', {}, [\n              createElement('text', { attrs: { value: 'World' }}, [])\n            ])\n\n            case 2:\n            return createElement('div', {}, [\n              createElement('text', { attrs: { value: 'World' }, style: { fontSize: 100 }}, [])\n            ])\n\n            case 3:\n            return createElement('div', {}, [\n              createElement('text', {\n                attrs: { value: 'World' },\n                style: { fontSize: 100 },\n                on: { click: this.foo }\n              }, [])\n            ])\n\n            case 4:\n            return createElement('div', {}, [\n              createElement('text', {\n                attrs: { value: 'Weex' },\n                style: { color: '#ff0000' }\n              }, [])\n            ])\n\n            default:\n            return createElement('div', {}, [\n              createElement('text', { attrs: { value: 'Hello' }}, [])\n            ])\n          }\n        },\n        el: \"body\"\n      })\n    `)\n    expect(instance.getRealRoot()).toEqual({\n      type: 'div',\n      children: [\n        { type: 'text', attr: { value: 'Hello' }}\n      ]\n    })\n\n    syncPromise([\n      checkRefresh(instance, { counter: 1 }, result => {\n        expect(result).toEqual({\n          type: 'div',\n          children: [\n            { type: 'text', attr: { value: 'World' }}\n          ]\n        })\n      }),\n      checkRefresh(instance, { counter: 2 }, result => {\n        expect(result).toEqual({\n          type: 'div',\n          children: [\n            { type: 'text', attr: { value: 'World' }, style: { fontSize: 100 }}\n          ]\n        })\n      }),\n      checkRefresh(instance, { counter: 3 }, result => {\n        expect(result).toEqual({\n          type: 'div',\n          children: [\n            { type: 'text', attr: { value: 'World' }, style: { fontSize: 100 }, event: ['click'] }\n          ]\n        })\n      }),\n      checkRefresh(instance, { counter: 4 }, result => {\n        expect(result).toEqual({\n          type: 'div',\n          children: [\n            { type: 'text', attr: { value: 'Weex' }, style: { fontSize: '', color: '#ff0000' }}\n          ]\n        })\n        done()\n      })\n    ])\n  })\n\n  it('should be generated with sub components', () => {\n    const instance = createInstance(runtime, `\n      new Vue({\n        render: function (createElement) {\n          return createElement('div', {}, [\n            createElement('text', { attrs: { value: 'Hello' }}, []),\n            createElement('foo', { props: { x: 'Weex' }})\n          ])\n        },\n        components: {\n          foo: {\n            props: {\n              x: { default: 'World' }\n            },\n            render: function (createElement) {\n              return createElement('text', { attrs: { value: this.x }}, [])\n            }\n          }\n        },\n        el: \"body\"\n      })\n    `)\n    expect(instance.getRealRoot()).toEqual({\n      type: 'div',\n      children: [\n        { type: 'text', attr: { value: 'Hello' }},\n        { type: 'text', attr: { value: 'Weex' }}\n      ]\n    })\n  })\n\n  it('should be generated with if/for diff', (done) => {\n    const { render, staticRenderFns } = compileAndStringify(`\n      <div>\n        <text v-for=\"item in list\" v-if=\"item.x\">{{item.v}}</text>\n      </div>\n    `)\n    const instance = createInstance(runtime, `\n      new Vue({\n        data: {\n          list: [\n            { v: 'Hello', x: true },\n            { v: 'World', x: false },\n            { v: 'Weex', x: true }\n          ]\n        },\n        computed: {\n          x: {\n            get: function () { return 0 },\n            set: function (v) {\n              switch (v) {\n                case 1:\n                this.list[1].x = true\n                break\n                case 2:\n                this.list.push({ v: 'v-if' })\n                break\n                case 3:\n                this.list.push({ v: 'v-for', x: true })\n                break\n                case 4:\n                this.list.splice(1, 2)\n                break\n              }\n            }\n          }\n        },\n        render: ${render},\n        staticRenderFns: ${staticRenderFns},\n        el: \"body\"\n      })\n    `)\n    expect(instance.getRealRoot()).toEqual({\n      type: 'div',\n      children: [\n        { type: 'text', attr: { value: 'Hello' }},\n        { type: 'text', attr: { value: 'Weex' }}\n      ]\n    })\n\n    syncPromise([\n      checkRefresh(instance, { x: 1 }, result => {\n        expect(result).toEqual({\n          type: 'div',\n          children: [\n            { type: 'text', attr: { value: 'Hello' }},\n            { type: 'text', attr: { value: 'World' }},\n            { type: 'text', attr: { value: 'Weex' }}\n          ]\n        })\n      }),\n      checkRefresh(instance, { x: 2 }, result => {\n        expect(result).toEqual({\n          type: 'div',\n          children: [\n            { type: 'text', attr: { value: 'Hello' }},\n            { type: 'text', attr: { value: 'World' }},\n            { type: 'text', attr: { value: 'Weex' }}\n          ]\n        })\n      }),\n      checkRefresh(instance, { x: 3 }, result => {\n        expect(result).toEqual({\n          type: 'div',\n          children: [\n            { type: 'text', attr: { value: 'Hello' }},\n            { type: 'text', attr: { value: 'World' }},\n            { type: 'text', attr: { value: 'Weex' }},\n            { type: 'text', attr: { value: 'v-for' }}\n          ]\n        })\n      }),\n      checkRefresh(instance, { x: 4 }, result => {\n        expect(result).toEqual({\n          type: 'div',\n          children: [\n            { type: 'text', attr: { value: 'Hello' }},\n            { type: 'text', attr: { value: 'v-for' }}\n          ]\n        })\n        done()\n      })\n    ])\n  })\n\n  it('should be generated with node structure diff', (done) => {\n    const instance = createInstance(runtime, `\n      new Vue({\n        data: {\n          counter: 0\n        },\n        render: function (createElement) {\n          switch (this.counter) {\n            case 1:\n            return createElement('div', {}, [\n              createElement('text', { attrs: { value: 'Hello' }}, []),\n              createElement('text', { attrs: { value: 'World' }}, [])\n            ])\n\n            case 2:\n            return createElement('div', {}, [\n              createElement('text', { attrs: { value: 'Hello' }}, []),\n              createElement('text', { attrs: { value: 'World' }}, []),\n              createElement('text', { attrs: { value: 'Weex' }}, [])\n            ])\n\n            case 3:\n            return createElement('div', {}, [\n              createElement('text', { attrs: { value: 'Hello' }}, []),\n              createElement('text', { attrs: { value: 'Weex' }}, [])\n            ])\n\n            case 4:\n            return createElement('div', {}, [\n              createElement('text', { attrs: { value: 'Weex' }}, [])\n            ])\n\n            case 5:\n            return createElement('div', {}, [\n              createElement('text', { attrs: { value: 'Hello' }}, []),\n              createElement('text', { attrs: { value: 'Weex' }}, [])\n            ])\n\n            case 6:\n            return createElement('div', {}, [\n              createElement('input', { attrs: { value: 'Hello' }}, []),\n              createElement('text', { attrs: { value: 'Weex' }}, [])\n            ])\n\n            default:\n            return createElement('div', {}, [\n              createElement('text', { attrs: { value: 'Hello' }}, []),\n            ])\n          }\n        },\n        el: \"body\"\n      })\n    `)\n    expect(instance.getRealRoot()).toEqual({\n      type: 'div',\n      children: [\n        { type: 'text', attr: { value: 'Hello' }}\n      ]\n    })\n\n    syncPromise([\n      checkRefresh(instance, { counter: 1 }, result => {\n        expect(result).toEqual({\n          type: 'div',\n          children: [\n            { type: 'text', attr: { value: 'Hello' }},\n            { type: 'text', attr: { value: 'World' }}\n          ]\n        })\n      }),\n      checkRefresh(instance, { counter: 2 }, result => {\n        expect(result).toEqual({\n          type: 'div',\n          children: [\n            { type: 'text', attr: { value: 'Hello' }},\n            { type: 'text', attr: { value: 'World' }},\n            { type: 'text', attr: { value: 'Weex' }}\n          ]\n        })\n      }),\n      checkRefresh(instance, { counter: 3 }, result => {\n        expect(result).toEqual({\n          type: 'div',\n          children: [\n            { type: 'text', attr: { value: 'Hello' }},\n            { type: 'text', attr: { value: 'Weex' }}\n          ]\n        })\n      }),\n      checkRefresh(instance, { counter: 4 }, result => {\n        expect(result).toEqual({\n          type: 'div',\n          children: [\n            { type: 'text', attr: { value: 'Weex' }}\n          ]\n        })\n      }),\n      checkRefresh(instance, { counter: 5 }, result => {\n        expect(result).toEqual({\n          type: 'div',\n          children: [\n            { type: 'text', attr: { value: 'Hello' }},\n            { type: 'text', attr: { value: 'Weex' }}\n          ]\n        })\n      }),\n      checkRefresh(instance, { counter: 6 }, result => {\n        expect(result).toEqual({\n          type: 'div',\n          children: [\n            { type: 'input', attr: { value: 'Hello' }},\n            { type: 'text', attr: { value: 'Weex' }}\n          ]\n        })\n        done()\n      })\n    ])\n  })\n\n  it('should be generated with component diff', (done) => {\n    const instance = createInstance(runtime, `\n      new Vue({\n        data: {\n          counter: 0\n        },\n        components: {\n          foo: {\n            props: { a: { default: '1' }, b: { default: '2' }},\n            render: function (createElement) {\n              return createElement('text', { attrs: { value: this.a + '-' + this.b }}, [])\n            }\n          },\n          bar: {\n            render: function (createElement) {\n              return createElement('text', { attrs: { value: 'Bar' }, style: { fontSize: 100 }})\n            }\n          },\n          baz: {\n            render: function (createElement) {\n              return createElement('image', { attrs: { src: 'http://example.com/favicon.ico' }})\n            }\n          }\n        },\n        render: function (createElement) {\n          switch (this.counter) {\n            case 1:\n            return createElement('div', {}, [\n              createElement('foo', { props: { a: '111', b: '222' }}, [])\n            ])\n\n            case 2:\n            return createElement('div', {}, [\n              createElement('foo', {}, [])\n            ])\n\n            case 3:\n            return createElement('div', {}, [\n              createElement('bar', {}, [])\n            ])\n\n            case 4:\n            return createElement('div', {}, [\n              createElement('baz', {}, [])\n            ])\n\n            case 5:\n            return createElement('div', {}, [\n              createElement('foo', {}, []),\n              createElement('bar', {}, []),\n              createElement('baz', {}, [])\n            ])\n\n            default:\n            return createElement('div', {}, [\n              createElement('foo', { props: { a: '111' }}, [])\n            ])\n          }\n        },\n        el: \"body\"\n      })\n    `)\n    expect(instance.getRealRoot()).toEqual({\n      type: 'div',\n      children: [\n        { type: 'text', attr: { value: '111-2' }}\n      ]\n    })\n\n    syncPromise([\n      checkRefresh(instance, { counter: 1 }, result => {\n        expect(result).toEqual({\n          type: 'div',\n          children: [\n            { type: 'text', attr: { value: '111-222' }}\n          ]\n        })\n      }),\n      checkRefresh(instance, { counter: 2 }, result => {\n        expect(result).toEqual({\n          type: 'div',\n          children: [\n            { type: 'text', attr: { value: '1-2' }}\n          ]\n        })\n      }),\n      checkRefresh(instance, { counter: 3 }, result => {\n        expect(result).toEqual({\n          type: 'div',\n          children: [\n            { type: 'text', attr: { value: 'Bar' }, style: { fontSize: 100 }}\n          ]\n        })\n      }),\n      checkRefresh(instance, { counter: 4 }, result => {\n        expect(result).toEqual({\n          type: 'div',\n          children: [\n            { type: 'image', attr: { src: 'http://example.com/favicon.ico' }}\n          ]\n        })\n      }),\n      checkRefresh(instance, { counter: 5 }, result => {\n        expect(result).toEqual({\n          type: 'div',\n          children: [\n            { type: 'text', attr: { value: '1-2' }},\n            { type: 'text', attr: { value: 'Bar' }, style: { fontSize: 100 }},\n            { type: 'image', attr: { src: 'http://example.com/favicon.ico' }}\n          ]\n        })\n        done()\n      })\n    ])\n  })\n})\n"
  },
  {
    "path": "test/weex/runtime/style.spec.js",
    "content": "import {\n  compileAndStringify,\n  prepareRuntime,\n  resetRuntime,\n  createInstance\n} from '../helpers/index'\n\ndescribe('generate style', () => {\n  let runtime\n\n  beforeAll(() => {\n    runtime = prepareRuntime()\n  })\n\n  afterAll(() => {\n    resetRuntime()\n    runtime = null\n  })\n\n  it('should be generated', () => {\n    const { render, staticRenderFns } = compileAndStringify(`\n      <div>\n        <text style=\"font-size: 100\">Hello World</text>\n      </div>\n    `)\n    const instance = createInstance(runtime, `\n      new Vue({\n        render: ${render},\n        staticRenderFns: ${staticRenderFns},\n        el: 'body'\n      })\n    `)\n    expect(instance.getRealRoot()).toEqual({\n      type: 'div',\n      children: [\n        { type: 'text', style: { fontSize: '100' }, attr: { value: 'Hello World' }}\n      ]\n    })\n  })\n\n  it('should be generated by array binding', (done) => {\n    const { render, staticRenderFns } = compileAndStringify(`\n      <div>\n        <text :style=\"[x, y]\" @click=\"foo\">Hello {{z}}</text>\n      </div>\n    `)\n    const instance = createInstance(runtime, `\n      new Vue({\n        data: {\n          x: { fontSize: 100, color: '#00ff00' },\n          y: { color: '#ff0000', fontWeight: 'bold' },\n          z: 'World'\n        },\n        methods: {\n          foo: function () {\n            this.x.fontSize = 200\n            this.x.color = '#0000ff'\n            Vue.delete(this.y, 'fontWeight')\n            this.z = 'Weex'\n          }\n        },\n        render: ${render},\n        staticRenderFns: ${staticRenderFns},\n        el: 'body'\n      })\n    `)\n    expect(instance.getRealRoot()).toEqual({\n      type: 'div',\n      children: [\n        {\n          type: 'text',\n          event: ['click'],\n          style: { fontSize: 100, color: '#ff0000', fontWeight: 'bold' },\n          attr: { value: 'Hello World' }\n        }\n      ]\n    })\n\n    instance.$fireEvent(instance.doc.body.children[0].ref, 'click', {})\n    setTimeout(() => {\n      expect(instance.getRealRoot()).toEqual({\n        type: 'div',\n        children: [\n          {\n            type: 'text',\n            event: ['click'],\n            style: { fontSize: 200, color: '#ff0000', fontWeight: '' },\n            attr: { value: 'Hello Weex' }\n          }\n        ]\n      })\n      done()\n    })\n  })\n\n  it('should be generated by map binding', (done) => {\n    const { render, staticRenderFns } = compileAndStringify(`\n      <div>\n        <text :style=\"{ fontSize: x, color: '#00ff00' }\" @click=\"foo\">Hello</text>\n        <text :style=\"y\">{{z}}</text>\n      </div>\n    `)\n    const instance = createInstance(runtime, `\n      new Vue({\n        data: {\n          x: 100,\n          y: { color: '#ff0000', fontWeight: 'bold' },\n          z: 'World'\n        },\n        methods: {\n          foo: function () {\n            this.x = 200\n            this.y.color = '#0000ff'\n            Vue.delete(this.y, 'fontWeight')\n            this.z = 'Weex'\n          }\n        },\n        render: ${render},\n        staticRenderFns: ${staticRenderFns},\n        el: 'body'\n      })\n    `)\n    expect(instance.getRealRoot()).toEqual({\n      type: 'div',\n      children: [\n        {\n          type: 'text',\n          event: ['click'],\n          style: { fontSize: 100, color: '#00ff00' },\n          attr: { value: 'Hello' }\n        },\n        {\n          type: 'text',\n          style: { color: '#ff0000', fontWeight: 'bold' },\n          attr: { value: 'World' }\n        }\n      ]\n    })\n\n    instance.$fireEvent(instance.doc.body.children[0].ref, 'click', {})\n    setTimeout(() => {\n      expect(instance.getRealRoot()).toEqual({\n        type: 'div',\n        children: [\n          {\n            type: 'text',\n            event: ['click'],\n            style: { fontSize: 200, color: '#00ff00' },\n            attr: { value: 'Hello' }\n          },\n          {\n            type: 'text',\n            style: { color: '#0000ff', fontWeight: '' },\n            attr: { value: 'Weex' }\n          }\n        ]\n      })\n      done()\n    })\n  })\n})\n"
  },
  {
    "path": "types/index.d.ts",
    "content": "import * as V from \"./vue\";\nimport * as Options from \"./options\";\nimport * as Plugin from \"./plugin\";\nimport * as VNode from \"./vnode\";\n\n// `Vue` in `export = Vue` must be a namespace\n// All available types are exported via this namespace\ndeclare namespace Vue {\n  export type CreateElement = V.CreateElement;\n\n  export type Component = Options.Component;\n  export type AsyncComponent = Options.AsyncComponent;\n  export type ComponentOptions<V extends Vue> = Options.ComponentOptions<V>;\n  export type FunctionalComponentOptions = Options.FunctionalComponentOptions;\n  export type RenderContext = Options.RenderContext;\n  export type PropOptions = Options.PropOptions;\n  export type ComputedOptions<V extends Vue> = Options.ComputedOptions<V>;\n  export type WatchHandler<V extends Vue> = Options.WatchHandler<V, any>;\n  export type WatchOptions = Options.WatchOptions;\n  export type DirectiveFunction = Options.DirectiveFunction;\n  export type DirectiveOptions = Options.DirectiveOptions;\n\n  export type PluginFunction<T> = Plugin.PluginFunction<T>;\n  export type PluginObject<T> = Plugin.PluginObject<T>;\n\n  export type VNodeChildren = VNode.VNodeChildren;\n  export type VNodeChildrenArrayContents = VNode.VNodeChildrenArrayContents;\n  export type VNode = VNode.VNode;\n  export type VNodeComponentOptions = VNode.VNodeComponentOptions;\n  export type VNodeData = VNode.VNodeData;\n  export type VNodeDirective = VNode.VNodeDirective;\n}\n\n// TS cannot merge imported class with namespace, declare a subclass to bypass\ndeclare class Vue extends V.Vue {}\n\nexport = Vue;\n"
  },
  {
    "path": "types/options.d.ts",
    "content": "import { Vue, CreateElement } from \"./vue\";\nimport { VNode, VNodeData, VNodeDirective } from \"./vnode\";\n\ntype Constructor = {\n  new (...args: any[]): any;\n}\n\nexport type Component = typeof Vue | ComponentOptions<Vue> | FunctionalComponentOptions;\nexport type AsyncComponent = (\n  resolve: (component: Component) => void,\n  reject: (reason?: any) => void\n) => Promise<Component> | Component | void;\n\nexport interface ComponentOptions<V extends Vue> {\n  data?: Object | ((this: V) => Object);\n  props?: string[] | { [key: string]: PropOptions | Constructor | Constructor[] };\n  propsData?: Object;\n  computed?: { [key: string]: ((this: V) => any) | ComputedOptions<V> };\n  methods?: { [key: string]: (this: V, ...args: any[]) => any };\n  watch?: { [key: string]: ({ handler: WatchHandler<V, any> } & WatchOptions) | WatchHandler<V, any> | string };\n\n  el?: Element | String;\n  template?: string;\n  render?(this: V, createElement: CreateElement): VNode;\n  renderError?: (h: () => VNode, err: Error) => VNode;\n  staticRenderFns?: ((createElement: CreateElement) => VNode)[];\n\n  beforeCreate?(this: V): void;\n  created?(this: V): void;\n  beforeDestroy?(this: V): void;\n  destroyed?(this: V): void;\n  beforeMount?(this: V): void;\n  mounted?(this: V): void;\n  beforeUpdate?(this: V): void;\n  updated?(this: V): void;\n  activated?(this: V): void;\n  deactivated?(this: V): void;\n\n  directives?: { [key: string]: DirectiveOptions | DirectiveFunction };\n  components?: { [key: string]: Component | AsyncComponent };\n  transitions?: { [key: string]: Object };\n  filters?: { [key: string]: Function };\n\n  provide?: Object | (() => Object);\n  inject?: { [key: string]: string | symbol } | Array<string>;\n\n  model?: {\n    prop?: string;\n    event?: string;\n  };\n\n  parent?: Vue;\n  mixins?: (ComponentOptions<Vue> | typeof Vue)[];\n  name?: string;\n  extends?: ComponentOptions<Vue> | typeof Vue;\n  delimiters?: [string, string];\n  comments?: boolean;\n  inheritAttrs?: boolean;\n}\n\nexport interface FunctionalComponentOptions {\n  name?: string;\n  props?: string[] | { [key: string]: PropOptions | Constructor | Constructor[] };\n  functional: boolean;\n  render(this: never, createElement: CreateElement, context: RenderContext): VNode | void;\n}\n\nexport interface RenderContext {\n  props: any;\n  children: VNode[];\n  slots(): any;\n  data: VNodeData;\n  parent: Vue;\n  injections: any\n}\n\nexport interface PropOptions {\n  type?: Constructor | Constructor[] | null;\n  required?: boolean;\n  default?: any;\n  validator?(value: any): boolean;\n}\n\nexport interface ComputedOptions<V> {\n  get?(this: V): any;\n  set?(this: V, value: any): void;\n  cache?: boolean;\n}\n\nexport type WatchHandler<V, T> = (this: V, val: T, oldVal: T) => void;\n\nexport interface WatchOptions {\n  deep?: boolean;\n  immediate?: boolean;\n}\n\nexport type DirectiveFunction = (\n  el: HTMLElement,\n  binding: VNodeDirective,\n  vnode: VNode,\n  oldVnode: VNode\n) => void;\n\nexport interface DirectiveOptions {\n  bind?: DirectiveFunction;\n  inserted?: DirectiveFunction;\n  update?: DirectiveFunction;\n  componentUpdated?: DirectiveFunction;\n  unbind?: DirectiveFunction;\n}\n"
  },
  {
    "path": "types/plugin.d.ts",
    "content": "import { Vue as _Vue } from \"./vue\";\n\nexport type PluginFunction<T> = (Vue: typeof _Vue, options?: T) => void;\n\nexport interface PluginObject<T> {\n  install: PluginFunction<T>;\n  [key: string]: any;\n}\n"
  },
  {
    "path": "types/test/augmentation-test.ts",
    "content": "import Vue = require(\"../index\");\n\ndeclare module \"../vue\" {\n  // add instance property and method\n  interface Vue {\n    $instanceProperty: string;\n    $instanceMethod(): void;\n  }\n\n  // add static property and method\n  namespace Vue {\n    const staticProperty: string;\n    function staticMethod(): void;\n  }\n}\n\n// augment ComponentOptions\ndeclare module \"../options\" {\n  interface ComponentOptions<V extends Vue> {\n    foo?: string;\n  }\n}\n\nconst vm = new Vue({\n  data: {\n    a: true\n  },\n  foo: \"foo\"\n});\n\nvm.$instanceProperty;\nvm.$instanceMethod();\n\nVue.staticProperty;\nVue.staticMethod();\n"
  },
  {
    "path": "types/test/options-test.ts",
    "content": "import Vue = require(\"../index\");\nimport { ComponentOptions, FunctionalComponentOptions } from \"../index\";\n\ninterface Component extends Vue {\n  a: number;\n}\n\nVue.component('component', {\n  data() {\n    this.$mount\n    this.a\n    return {\n      a: 1\n    }\n  },\n  props: {\n    size: Number,\n    name: {\n      type: String,\n      default: 0,\n      required: true,\n      validator(value) {\n        return value > 0;\n      }\n    }\n  },\n  propsData: {\n    msg: \"Hello\"\n  },\n  computed: {\n    aDouble(this: Component) {\n      return this.a * 2;\n    },\n    aPlus: {\n      get(this: Component) {\n        return this.a + 1;\n      },\n      set(this: Component, v: number) {\n        this.a = v - 1;\n      },\n      cache: false\n    }\n  },\n  methods: {\n    plus() {\n      this.a++;\n    }\n  },\n  watch: {\n    'a': function(val: number, oldVal: number) {\n      console.log(`new: ${val}, old: ${oldVal}`);\n    },\n    'b': 'someMethod',\n    'c': {\n      handler(val, oldVal) {\n        this.a = val\n      },\n      deep: true\n    }\n  },\n  el: \"#app\",\n  template: \"<div>{{ message }}</div>\",\n  render(createElement) {\n    return createElement(\"div\", {\n      attrs: {\n        id: \"foo\"\n      },\n      props: {\n        myProp: \"bar\"\n      },\n      domProps: {\n        innerHTML: \"baz\"\n      },\n      on: {\n        click: new Function\n      },\n      nativeOn: {\n        click: new Function\n      },\n      class: {\n        foo: true,\n        bar: false\n      },\n      style: {\n        color: 'red',\n        fontSize: '14px'\n      },\n      key: 'myKey',\n      ref: 'myRef'\n    }, [\n      createElement(),\n      createElement(\"div\", \"message\"),\n      createElement(Vue.component(\"component\")),\n      createElement({} as ComponentOptions<Vue>),\n      createElement({ functional: true, render () {}}),\n\n      createElement(() => Vue.component(\"component\")),\n      createElement(() => ( {} as ComponentOptions<Vue> )),\n      createElement(() => {\n        return new Promise((resolve) => {\n          resolve({} as ComponentOptions<Vue>);\n        })\n      }),\n      createElement((resolve, reject) => {\n        resolve({} as ComponentOptions<Vue>);\n        reject();\n      }),\n\n      \"message\",\n\n      [createElement(\"div\", \"message\")]\n    ]);\n  },\n  staticRenderFns: [],\n\n  beforeCreate() {\n    this.a = 1;\n  },\n  created() {},\n  beforeDestroy() {},\n  destroyed() {},\n  beforeMount() {},\n  mounted() {},\n  beforeUpdate() {},\n  updated() {},\n  activated() {},\n  deactivated() {},\n\n  directives: {\n    a: {\n      bind() {},\n      inserted() {},\n      update() {},\n      componentMounted() {},\n      unbind() {}\n    },\n    b(el, binding, vnode, oldVnode) {\n      el.textContent;\n\n      binding.name;\n      binding.value;\n      binding.oldValue;\n      binding.expression;\n      binding.arg;\n      binding.modifiers[\"modifier\"];\n    }\n  },\n  components: {\n    a: Vue.component(\"\"),\n    b: {} as ComponentOptions<Vue>\n  },\n  transitions: {},\n  filters: {\n    double(value: number) {\n      return value * 2;\n    }\n  },\n  parent: new Vue,\n  mixins: [Vue.component(\"\"), ({} as ComponentOptions<Vue>)],\n  name: \"Component\",\n  extends: {} as ComponentOptions<Vue>,\n  delimiters: [\"${\", \"}\"]\n} as ComponentOptions<Component>);\n\nVue.component('component-with-scoped-slot', {\n  render (h) {\n    interface ScopedSlotProps {\n      msg: string\n    }\n\n    return h('div', [\n      h('child', [\n        // default scoped slot as children\n        (props: ScopedSlotProps) => [h('span', [props.msg])]\n      ]),\n      h('child', {\n        scopedSlots: {\n          // named scoped slot as vnode data\n          item: (props: ScopedSlotProps) => [h('span', [props.msg])]\n        }\n      })\n    ])\n  },\n  components: {\n    child: {\n      render (h) {\n        return h('div', [\n          this.$scopedSlots['default']({ msg: 'hi' }),\n          this.$scopedSlots['item']({ msg: 'hello' })\n        ])\n      }\n    } as ComponentOptions<Vue>\n  }\n} as ComponentOptions<Vue>)\n\nVue.component('functional-component', {\n  props: ['prop'],\n  functional: true,\n  render(createElement, context) {\n    context.props;\n    context.children;\n    context.slots();\n    context.data;\n    context.parent;\n    return createElement(\"div\", {}, context.children);\n  }\n} as FunctionalComponentOptions);\n\nVue.component(\"async-component\", (resolve, reject) => {\n  setTimeout(() => {\n    resolve(Vue.component(\"component\"));\n  }, 0);\n  return new Promise((resolve) => {\n    resolve({ functional: true } as FunctionalComponentOptions);\n  })\n});\n"
  },
  {
    "path": "types/test/plugin-test.ts",
    "content": "import Vue = require(\"../index\");\nimport { PluginFunction, PluginObject } from \"../index\";\n\nclass Option {\n  prefix: string;\n  suffix: string;\n}\n\nconst plugin: PluginObject<Option> = {\n  install(Vue, option) {\n    if (typeof option !== \"undefined\") {\n      const {prefix, suffix} = option;\n    }\n  }\n}\nconst installer: PluginFunction<Option> = function(Vue, option) { }\n\nVue.use(plugin, new Option);\nVue.use(installer, new Option);\n"
  },
  {
    "path": "types/test/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"es5\",\n    \"lib\": [\n      \"es5\",\n      \"dom\",\n      \"es2015.promise\",\n      \"es2015.core\"\n    ],\n    \"module\": \"commonjs\",\n    \"noImplicitAny\": true,\n    \"strictNullChecks\": true,\n    \"noEmit\": true\n  },\n  \"files\": [\n    \"../index.d.ts\",\n    \"../options.d.ts\",\n    \"../plugin.d.ts\",\n    \"../vnode.d.ts\",\n    \"../vue.d.ts\",\n    \"options-test.ts\",\n    \"plugin-test.ts\",\n    \"vue-test.ts\",\n    \"augmentation-test.ts\"\n  ],\n  \"compileOnSave\": false\n}\n"
  },
  {
    "path": "types/test/vue-test.ts",
    "content": "import Vue = require(\"../index\");\n\nclass Test extends Vue {\n  a: number;\n\n  testProperties() {\n    this.$data;\n    this.$el;\n    this.$options;\n    this.$parent;\n    this.$root;\n    this.$children;\n    this.$refs;\n    this.$slots;\n    this.$isServer;\n    this.$ssrContext;\n    this.$vnode;\n  }\n\n  // test property reification\n  $refs: {\n    vue: Vue,\n    element: HTMLInputElement,\n    vues: Vue[],\n    elements: HTMLInputElement[]\n  }\n  testReification() {\n    this.$refs.vue.$data;\n    this.$refs.element.value;\n    this.$refs.vues[0].$data;\n    this.$refs.elements[0].value;\n  }\n\n  testMethods() {\n    this.$mount(\"#app\", false);\n    this.$forceUpdate();\n    this.$destroy();\n    this.$set({}, \"key\", \"value\");\n    this.$delete({}, \"key\");\n    this.$watch(\"a\", (val: number, oldVal: number) => {}, {\n      immediate: true,\n      deep: false\n    })();\n    this.$watch(() => this.a, (val: number) => {});\n    this.$on(\"\", () => {});\n    this.$once(\"\", () => {});\n    this.$off(\"\", () => {});\n    this.$emit(\"\", 1, 2, 3);\n    this.$nextTick(function() {\n      this.$nextTick;\n    });\n    this.$nextTick().then(() => {});\n    this.$createElement(\"div\", {}, \"message\");\n  }\n\n  static testConfig() {\n    const { config } = this;\n    config.silent;\n    config.optionMergeStrategies;\n    config.devtools;\n    config.errorHandler = (err, vm) => {\n      if (vm instanceof Test) {\n        vm.testProperties();\n        vm.testMethods();\n      }\n    };\n    config.warnHandler = (msg, vm) => {\n      if (vm instanceof Test) {\n        vm.testProperties();\n        vm.testMethods();\n      }\n    };\n    config.keyCodes = { esc: 27 };\n  }\n\n  static testMethods() {\n    this.extend({\n      data() {\n        return {\n          msg: \"\"\n        };\n      }\n    });\n    this.nextTick(() => {});\n    this.nextTick().then(() => {});\n    this.set({}, \"\", \"\");\n    this.set([true, false, true], 1, true);\n    this.delete({}, \"\");\n    this.delete([true, false], 0);\n    this.directive(\"\", {bind() {}});\n    this.filter(\"\", (value: number) => value);\n    this.component(\"\", { data: () => ({}) });\n    this.component(\"\", { functional: true, render () {}});\n    this.use;\n    this.mixin(Test);\n    this.compile(\"<div>{{ message }}</div>\");\n  }\n}\n"
  },
  {
    "path": "types/typings.json",
    "content": "{\n  \"name\": \"vue\",\n  \"main\": \"index.d.ts\"\n}\n"
  },
  {
    "path": "types/vnode.d.ts",
    "content": "import { Vue } from \"./vue\";\n\nexport type ScopedSlot = (props: any) => VNodeChildrenArrayContents | string;\n\nexport type VNodeChildren = VNodeChildrenArrayContents | [ScopedSlot] | string;\nexport interface VNodeChildrenArrayContents {\n  [x: number]: VNode | string | VNodeChildren;\n}\n\nexport interface VNode {\n  tag?: string;\n  data?: VNodeData;\n  children?: VNode[];\n  text?: string;\n  elm?: Node;\n  ns?: string;\n  context?: Vue;\n  key?: string | number;\n  componentOptions?: VNodeComponentOptions;\n  componentInstance?: Vue;\n  parent?: VNode;\n  raw?: boolean;\n  isStatic?: boolean;\n  isRootInsert: boolean;\n  isComment: boolean;\n}\n\nexport interface VNodeComponentOptions {\n  Ctor: typeof Vue;\n  propsData?: Object;\n  listeners?: Object;\n  children?: VNodeChildren;\n  tag?: string;\n}\n\nexport interface VNodeData {\n  key?: string | number;\n  slot?: string;\n  scopedSlots?: { [key: string]: ScopedSlot };\n  ref?: string;\n  tag?: string;\n  staticClass?: string;\n  class?: any;\n  staticStyle?: { [key: string]: any };\n  style?: Object[] | Object;\n  props?: { [key: string]: any };\n  attrs?: { [key: string]: any };\n  domProps?: { [key: string]: any };\n  hook?: { [key: string]: Function };\n  on?: { [key: string]: Function | Function[] };\n  nativeOn?: { [key: string]: Function | Function[] };\n  transition?: Object;\n  show?: boolean;\n  inlineTemplate?: {\n    render: Function;\n    staticRenderFns: Function[];\n  };\n  directives?: VNodeDirective[];\n  keepAlive?: boolean;\n}\n\nexport interface VNodeDirective {\n  readonly name: string;\n  readonly value: any;\n  readonly oldValue: any;\n  readonly expression: any;\n  readonly arg: string;\n  readonly modifiers: { [key: string]: boolean };\n}\n"
  },
  {
    "path": "types/vue.d.ts",
    "content": "import {\n  Component,\n  AsyncComponent,\n  ComponentOptions,\n  FunctionalComponentOptions,\n  WatchOptions,\n  WatchHandler,\n  DirectiveOptions,\n  DirectiveFunction\n} from \"./options\";\nimport { VNode, VNodeData, VNodeChildren, ScopedSlot } from \"./vnode\";\nimport { PluginFunction, PluginObject } from \"./plugin\";\n\nexport type CreateElement = {\n  // empty node\n  (): VNode;\n\n  // element or component name\n  (tag: string, children: VNodeChildren): VNode;\n  (tag: string, data?: VNodeData, children?: VNodeChildren): VNode;\n\n  // component constructor or options\n  (tag: Component, children: VNodeChildren): VNode;\n  (tag: Component, data?: VNodeData, children?: VNodeChildren): VNode;\n\n  // async component\n  (tag: AsyncComponent, children: VNodeChildren): VNode;\n  (tag: AsyncComponent, data?: VNodeData, children?: VNodeChildren): VNode;\n}\n\nexport declare class Vue {\n\n  constructor(options?: ComponentOptions<Vue>);\n\n  $data: Object;\n  readonly $el: HTMLElement;\n  readonly $options: ComponentOptions<this>;\n  readonly $parent: Vue;\n  readonly $root: Vue;\n  readonly $children: Vue[];\n  readonly $refs: { [key: string]: Vue | Element | Vue[] | Element[]};\n  readonly $slots: { [key: string]: VNode[] };\n  readonly $scopedSlots: { [key: string]: ScopedSlot };\n  readonly $isServer: boolean;\n  readonly $ssrContext: any;\n  readonly $props: any;\n  readonly $vnode: VNode;\n  readonly $attrs: { [key: string] : string } | void;\n  readonly $listeners: { [key: string]: Function | Array<Function> } | void;\n\n  $mount(elementOrSelector?: Element | String, hydrating?: boolean): this;\n  $forceUpdate(): void;\n  $destroy(): void;\n  $set: typeof Vue.set;\n  $delete: typeof Vue.delete;\n  $watch(\n    expOrFn: string,\n    callback: WatchHandler<this, any>,\n    options?: WatchOptions\n  ): (() => void);\n  $watch<T>(\n    expOrFn: (this: this) => T,\n    callback: WatchHandler<this, T>,\n    options?: WatchOptions\n  ): (() => void);\n  $on(event: string | string[], callback: Function): this;\n  $once(event: string, callback: Function): this;\n  $off(event?: string | string[], callback?: Function): this;\n  $emit(event: string, ...args: any[]): this;\n  $nextTick(callback: (this: this) => void): void;\n  $nextTick(): Promise<void>;\n  $createElement: CreateElement;\n\n  static config: {\n    silent: boolean;\n    optionMergeStrategies: any;\n    devtools: boolean;\n    productionTip: boolean;\n    performance: boolean;\n    errorHandler(err: Error, vm: Vue, info: string): void;\n    warnHandler(msg: string, vm: Vue, trace: string): void;\n    ignoredElements: string[];\n    keyCodes: { [key: string]: number };\n  }\n\n  static extend(options: ComponentOptions<Vue> | FunctionalComponentOptions): typeof Vue;\n  static nextTick(callback: () => void, context?: any[]): void;\n  static nextTick(): Promise<void>\n  static set<T>(object: Object, key: string, value: T): T;\n  static set<T>(array: T[], key: number, value: T): T;\n  static delete(object: Object, key: string): void;\n  static delete<T>(array: T[], key: number): void;\n\n  static directive(\n    id: string,\n    definition?: DirectiveOptions | DirectiveFunction\n  ): DirectiveOptions;\n  static filter(id: string, definition?: Function): Function;\n  static component(id: string, definition?: Component | AsyncComponent): typeof Vue;\n\n  static use<T>(plugin: PluginObject<T> | PluginFunction<T>, options?: T): void;\n  static mixin(mixin: typeof Vue | ComponentOptions<Vue>): void;\n  static compile(template: string): {\n    render(createElement: typeof Vue.prototype.$createElement): VNode;\n    staticRenderFns: (() => VNode)[];\n  };\n}\n"
  }
]