[Pkg-javascript-commits] [vue.js] 01/03: New upstream version 2.5.9+dfsg

Paolo Greppi paolog-guest at moszumanska.debian.org
Wed Nov 29 09:14:05 UTC 2017


This is an automated email from the git hooks/post-receive script.

paolog-guest pushed a commit to branch master
in repository vue.js.

commit 59b1c44ae52355d25b921953282daa0dd125dc42
Author: Paolo Greppi <paolo.greppi at libpf.com>
Date:   Wed Nov 29 10:13:19 2017 +0100

    New upstream version 2.5.9+dfsg
---
 .circleci/config.yml                               |    1 -
 BACKERS.md                                         |  224 +++--
 README.md                                          |   41 +-
 build/install-hooks.js                             |    8 -
 build/release.sh                                   |    5 +-
 build/setup.js                                     |   12 +
 flow/compiler.js                                   |    3 +-
 flow/component.js                                  |    1 +
 package-lock.json                                  |   64 +-
 package.json                                       |    9 +-
 packages/vue-server-renderer/basic.js              |  394 +++++---
 packages/vue-server-renderer/build.js              |  396 +++++---
 packages/vue-server-renderer/package.json          |    2 +-
 packages/vue-server-renderer/types/index.d.ts      |    3 +
 packages/vue-template-compiler/browser.js          |  174 +++-
 packages/vue-template-compiler/build.js            |  174 +++-
 packages/vue-template-compiler/package.json        |    2 +-
 packages/weex-template-compiler/build.js           | 1063 ++++++++++++--------
 packages/weex-vue-framework/factory.js             |  893 +++++++++-------
 packages/weex-vue-framework/index.js               |   54 -
 src/compiler/codegen/events.js                     |   13 +-
 src/compiler/codegen/index.js                      |   12 +-
 src/compiler/error-detector.js                     |   18 +-
 src/compiler/helpers.js                            |   33 +-
 src/compiler/parser/html-parser.js                 |   13 +-
 src/compiler/parser/index.js                       |   24 +-
 src/core/components/keep-alive.js                  |   18 +-
 src/core/instance/events.js                        |    5 +-
 src/core/instance/lifecycle.js                     |    5 +-
 src/core/instance/render-helpers/render-slot.js    |   26 +-
 src/core/instance/render-helpers/render-static.js  |   15 +-
 src/core/instance/render-helpers/resolve-slots.js  |   15 +-
 src/core/instance/render.js                        |    5 +-
 src/core/observer/index.js                         |    2 +-
 src/core/observer/traverse.js                      |   39 +
 src/core/observer/watcher.js                       |   53 +-
 src/core/util/env.js                               |   13 +-
 src/core/util/error.js                             |    4 +-
 src/core/util/lang.js                              |    2 -
 src/core/util/options.js                           |    4 +-
 src/core/vdom/create-functional-component.js       |    8 +-
 src/core/vdom/helpers/merge-hook.js                |    4 +
 src/core/vdom/modules/directives.js                |    4 +-
 src/core/vdom/patch.js                             |   89 +-
 src/core/vdom/vnode.js                             |   27 +-
 src/platforms/web/compiler/directives/model.js     |   13 +
 src/platforms/web/compiler/modules/model.js        |    9 +
 src/platforms/web/entry-runtime-with-compiler.js   |    3 +-
 src/platforms/web/runtime/components/transition.js |    6 +-
 src/platforms/web/runtime/directives/model.js      |   17 +-
 src/platforms/web/runtime/modules/attrs.js         |   21 +-
 src/platforms/web/runtime/modules/events.js        |    3 +-
 src/platforms/web/runtime/modules/transition.js    |    6 +-
 src/platforms/web/server/directives/index.js       |    4 +-
 src/platforms/web/server/directives/model.js       |   44 +
 src/platforms/web/server/modules/dom-props.js      |    3 +
 src/platforms/web/util/compat.js                   |   16 +-
 src/platforms/weex/runtime/components/richtext.js  |   37 +-
 src/platforms/weex/runtime/modules/attrs.js        |   13 +-
 src/platforms/weex/runtime/modules/class.js        |    8 +-
 src/platforms/weex/runtime/modules/events.js       |    1 +
 src/platforms/weex/runtime/modules/style.js        |   22 +-
 src/platforms/weex/runtime/modules/transition.js   |    8 +-
 src/server/bundle-renderer/create-bundle-runner.js |    2 +-
 src/server/optimizing-compiler/codegen.js          |    3 +
 src/server/optimizing-compiler/modules.js          |    4 +
 src/server/optimizing-compiler/optimizer.js        |   16 +-
 src/server/render.js                               |    4 +-
 src/shared/util.js                                 |    2 +
 test/ssr/ssr-string.spec.js                        |  123 +++
 .../features/component/component-async.spec.js     |   29 +
 .../component/component-keep-alive.spec.js         |  273 +++--
 .../unit/features/component/component-slot.spec.js |   93 +-
 test/unit/features/directives/for.spec.js          |   19 +-
 .../unit/features/directives/model-dynamic.spec.js |   42 +
 test/unit/features/directives/model-select.spec.js |   42 +
 test/unit/features/directives/model-text.spec.js   |   60 +-
 test/unit/features/directives/on.spec.js           |   22 +-
 test/unit/features/directives/once.spec.js         |   22 +
 test/unit/features/global-api/set-delete.spec.js   |   26 +
 test/unit/features/instance/methods-events.spec.js |    7 +
 test/unit/features/transition/transition.spec.js   |   42 +
 test/unit/karma.base.config.js                     |    2 +-
 test/unit/modules/compiler/codegen.spec.js         |    4 +-
 test/unit/modules/compiler/parser.spec.js          |   48 +
 test/unit/modules/vdom/patch/edge-cases.spec.js    |   21 +
 test/unit/modules/vdom/patch/hydration.spec.js     |   46 +
 test/weex/cases/cases.spec.js                      |   72 ++
 test/weex/cases/event/click.after.vdom.js          |   10 +
 test/weex/cases/event/click.before.vdom.js         |   10 +
 test/weex/cases/event/click.vue                    |   20 +
 test/weex/cases/render/sample.vdom.js              |   17 +
 test/weex/cases/render/sample.vue                  |   23 +
 test/weex/compiler/compile.spec.js                 |    6 +-
 test/weex/helpers/index.js                         |   71 +-
 test/weex/runtime/components/richtext.spec.js      |   10 +-
 types/index.d.ts                                   |    3 +-
 types/options.d.ts                                 |   11 +-
 types/test/options-test.ts                         |    7 +-
 types/test/ssr-test.ts                             |   16 +
 types/test/tsconfig.json                           |    6 +-
 types/vnode.d.ts                                   |    8 +-
 types/vue.d.ts                                     |   18 +-
 103 files changed, 3767 insertions(+), 1701 deletions(-)

diff --git a/.circleci/config.yml b/.circleci/config.yml
index 99fa889..0c5f49e 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -16,7 +16,6 @@ jobs:
             - v1-vue-{{ .Branch }}-
             - v1-vue-
       - run: npm install
-      - run: cd packages/vue-server-renderer && npm install vue
       - save_cache:
           key: v1-vue-{{ .Branch }}-{{ checksum "package-lock.json" }}
           paths:
diff --git a/BACKERS.md b/BACKERS.md
index 85d7e33..951ec5d 100644
--- a/BACKERS.md
+++ b/BACKERS.md
@@ -21,12 +21,16 @@ Funds donated via Patreon goes directly to support Evan You's full-time work on
   <a href="https://xiaozhuanlan.com">
     <img width="200px" src="https://raw.githubusercontent.com/vuejs/cn.vuejs.org/master/themes/vue/source/images/xiaozhuanlan.png">
   </a>
+  <br><br>
+  <a href="http://tooltwist.com" target="_blank">
+    <img width="280px" src="https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/tooltwist.png">
+  </a>
 </p>
 
 <h2 align="center">Platinum via OpenCollective</h2>
 
-<a href="https://opencollective.com/vuejs/platinumsponsor/0/website" target="_blank"><img src="https://opencollective.com/vuejs/platinumsponsor/0/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/platinumsponsor/1/website" target="_blank"><img src="https://opencollective.com/vuejs/platinumsponsor/1/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/platinumsponsors/0/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/platinumsponsors/0/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/platinumsponsors/1/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/platinumsponsors/1/avatar.svg"></a>
 
 <h2 align="center">Gold via Patreon</h2>
 
@@ -95,11 +99,6 @@ Funds donated via Patreon goes directly to support Evan You's full-time work on
         </a>
       </td>
       <td align="center" valign="middle">
-        <a href="https://www.v2ex.com/t/379389" target="_blank">
-          <img width="170px" src="https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/v2exer.png">
-        </a>
-      </td>
-      <td align="center" valign="middle">
         <a href="https://www.xfive.co/" target="_blank">
           <img width="100px" src="https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/xfive.png">
         </a>
@@ -114,13 +113,9 @@ Funds donated via Patreon goes directly to support Evan You's full-time work on
           <img width="170px" src="https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/onsen-ui.png">
         </a>
       </td>
-    </tr>
-    <tr></tr>
-    <tr>
       <td align="center" valign="middle">
-        <a href="http://tooltwist.com/" target="_blank">
-          <img width="170px" src="https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/tooltwist
-          .png">
+        <a href="https://themeforest.net/item/clear-bootstrap-vuejs-admin-template/19339739?ref=jyostna&utm_source=vuejs&utm_campaign=vuejs_patreon&clickthrough_id=1113830525&redirect_back=true" target="_blank">
+          <img width="150px" src="https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/vuejsadmin.png">
         </a>
       </td>
     </tr>
@@ -129,36 +124,36 @@ Funds donated via Patreon goes directly to support Evan You's full-time work on
 
 <h2 align="center">Gold via OpenCollective</h2>
 
-<a href="https://opencollective.com/vuejs/goldsponsor/0/website" target="_blank"><img src="https://opencollective.com/vuejs/goldsponsor/0/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/goldsponsor/1/website" target="_blank"><img src="https://opencollective.com/vuejs/goldsponsor/1/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/goldsponsor/2/website" target="_blank"><img src="https://opencollective.com/vuejs/goldsponsor/2/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/goldsponsor/3/website" target="_blank"><img src="https://opencollective.com/vuejs/goldsponsor/3/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/goldsponsor/4/website" target="_blank"><img src="https://opencollective.com/vuejs/goldsponsor/4/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/goldsponsor/5/website" target="_blank"><img src="https://opencollective.com/vuejs/goldsponsor/5/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/goldsponsor/6/website" target="_blank"><img src="https://opencollective.com/vuejs/goldsponsor/6/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/goldsponsor/7/website" target="_blank"><img src="https://opencollective.com/vuejs/goldsponsor/7/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/goldsponsor/8/website" target="_blank"><img src="https://opencollective.com/vuejs/goldsponsor/8/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/goldsponsor/9/website" target="_blank"><img src="https://opencollective.com/vuejs/goldsponsor/9/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/goldsponsor/10/website" target="_blank"><img src="https://opencollective.com/vuejs/goldsponsor/10/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/goldsponsor/11/website" target="_blank"><img src="https://opencollective.com/vuejs/goldsponsor/11/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/goldsponsor/12/website" target="_blank"><img src="https://opencollective.com/vuejs/goldsponsor/12/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/goldsponsor/13/website" target="_blank"><img src="https://opencollective.com/vuejs/goldsponsor/13/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/goldsponsor/14/website" target="_blank"><img src="https://opencollective.com/vuejs/goldsponsor/14/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/goldsponsor/15/website" target="_blank"><img src="https://opencollective.com/vuejs/goldsponsor/15/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/goldsponsor/16/website" target="_blank"><img src="https://opencollective.com/vuejs/goldsponsor/16/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/goldsponsor/17/website" target="_blank"><img src="https://opencollective.com/vuejs/goldsponsor/17/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/goldsponsor/18/website" target="_blank"><img src="https://opencollective.com/vuejs/goldsponsor/18/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/goldsponsor/19/website" target="_blank"><img src="https://opencollective.com/vuejs/goldsponsor/19/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/goldsponsor/20/website" target="_blank"><img src="https://opencollective.com/vuejs/goldsponsor/20/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/goldsponsor/21/website" target="_blank"><img src="https://opencollective.com/vuejs/goldsponsor/21/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/goldsponsor/22/website" target="_blank"><img src="https://opencollective.com/vuejs/goldsponsor/22/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/goldsponsor/23/website" target="_blank"><img src="https://opencollective.com/vuejs/goldsponsor/23/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/goldsponsor/24/website" target="_blank"><img src="https://opencollective.com/vuejs/goldsponsor/24/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/goldsponsor/25/website" target="_blank"><img src="https://opencollective.com/vuejs/goldsponsor/25/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/goldsponsor/26/website" target="_blank"><img src="https://opencollective.com/vuejs/goldsponsor/26/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/goldsponsor/27/website" target="_blank"><img src="https://opencollective.com/vuejs/goldsponsor/27/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/goldsponsor/28/website" target="_blank"><img src="https://opencollective.com/vuejs/goldsponsor/28/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/goldsponsor/29/website" target="_blank"><img src="https://opencollective.com/vuejs/goldsponsor/29/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/goldsponsors/0/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/goldsponsors/0/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/goldsponsors/1/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/goldsponsors/1/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/goldsponsors/2/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/goldsponsors/2/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/goldsponsors/3/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/goldsponsors/3/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/goldsponsors/4/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/goldsponsors/4/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/goldsponsors/5/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/goldsponsors/5/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/goldsponsors/6/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/goldsponsors/6/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/goldsponsors/7/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/goldsponsors/7/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/goldsponsors/8/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/goldsponsors/8/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/goldsponsors/9/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/goldsponsors/9/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/goldsponsors/10/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/goldsponsors/10/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/goldsponsors/11/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/goldsponsors/11/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/goldsponsors/12/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/goldsponsors/12/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/goldsponsors/13/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/goldsponsors/13/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/goldsponsors/14/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/goldsponsors/14/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/goldsponsors/15/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/goldsponsors/15/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/goldsponsors/16/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/goldsponsors/16/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/goldsponsors/17/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/goldsponsors/17/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/goldsponsors/18/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/goldsponsors/18/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/goldsponsors/19/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/goldsponsors/19/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/goldsponsors/20/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/goldsponsors/20/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/goldsponsors/21/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/goldsponsors/21/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/goldsponsors/22/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/goldsponsors/22/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/goldsponsors/23/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/goldsponsors/23/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/goldsponsors/24/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/goldsponsors/24/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/goldsponsors/25/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/goldsponsors/25/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/goldsponsors/26/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/goldsponsors/26/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/goldsponsors/27/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/goldsponsors/27/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/goldsponsors/28/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/goldsponsors/28/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/goldsponsors/29/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/goldsponsors/29/avatar.svg"></a>
 
 <h2 align="center">Silver via Patreon</h2>
 
@@ -166,36 +161,36 @@ Funds donated via Patreon goes directly to support Evan You's full-time work on
 
 <h2 align="center">Silver via OpenCollective</h2>
 
-<a href="https://opencollective.com/vuejs/silversponsor/0/website" target="_blank"><img src="https://opencollective.com/vuejs/silversponsor/0/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/silversponsor/1/website" target="_blank"><img src="https://opencollective.com/vuejs/silversponsor/1/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/silversponsor/2/website" target="_blank"><img src="https://opencollective.com/vuejs/silversponsor/2/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/silversponsor/3/website" target="_blank"><img src="https://opencollective.com/vuejs/silversponsor/3/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/silversponsor/4/website" target="_blank"><img src="https://opencollective.com/vuejs/silversponsor/4/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/silversponsor/5/website" target="_blank"><img src="https://opencollective.com/vuejs/silversponsor/5/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/silversponsor/6/website" target="_blank"><img src="https://opencollective.com/vuejs/silversponsor/6/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/silversponsor/7/website" target="_blank"><img src="https://opencollective.com/vuejs/silversponsor/7/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/silversponsor/8/website" target="_blank"><img src="https://opencollective.com/vuejs/silversponsor/8/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/silversponsor/9/website" target="_blank"><img src="https://opencollective.com/vuejs/silversponsor/9/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/silversponsor/10/website" target="_blank"><img src="https://opencollective.com/vuejs/silversponsor/10/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/silversponsor/11/website" target="_blank"><img src="https://opencollective.com/vuejs/silversponsor/11/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/silversponsor/12/website" target="_blank"><img src="https://opencollective.com/vuejs/silversponsor/12/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/silversponsor/13/website" target="_blank"><img src="https://opencollective.com/vuejs/silversponsor/13/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/silversponsor/14/website" target="_blank"><img src="https://opencollective.com/vuejs/silversponsor/14/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/silversponsor/15/website" target="_blank"><img src="https://opencollective.com/vuejs/silversponsor/15/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/silversponsor/16/website" target="_blank"><img src="https://opencollective.com/vuejs/silversponsor/16/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/silversponsor/17/website" target="_blank"><img src="https://opencollective.com/vuejs/silversponsor/17/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/silversponsor/18/website" target="_blank"><img src="https://opencollective.com/vuejs/silversponsor/18/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/silversponsor/19/website" target="_blank"><img src="https://opencollective.com/vuejs/silversponsor/19/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/silversponsor/20/website" target="_blank"><img src="https://opencollective.com/vuejs/silversponsor/20/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/silversponsor/21/website" target="_blank"><img src="https://opencollective.com/vuejs/silversponsor/21/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/silversponsor/22/website" target="_blank"><img src="https://opencollective.com/vuejs/silversponsor/22/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/silversponsor/23/website" target="_blank"><img src="https://opencollective.com/vuejs/silversponsor/23/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/silversponsor/24/website" target="_blank"><img src="https://opencollective.com/vuejs/silversponsor/24/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/silversponsor/25/website" target="_blank"><img src="https://opencollective.com/vuejs/silversponsor/25/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/silversponsor/26/website" target="_blank"><img src="https://opencollective.com/vuejs/silversponsor/26/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/silversponsor/27/website" target="_blank"><img src="https://opencollective.com/vuejs/silversponsor/27/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/silversponsor/28/website" target="_blank"><img src="https://opencollective.com/vuejs/silversponsor/28/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/silversponsor/29/website" target="_blank"><img src="https://opencollective.com/vuejs/silversponsor/29/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/silversponsors/0/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/silversponsors/0/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/silversponsors/1/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/silversponsors/1/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/silversponsors/2/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/silversponsors/2/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/silversponsors/3/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/silversponsors/3/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/silversponsors/4/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/silversponsors/4/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/silversponsors/5/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/silversponsors/5/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/silversponsors/6/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/silversponsors/6/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/silversponsors/7/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/silversponsors/7/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/silversponsors/8/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/silversponsors/8/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/silversponsors/9/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/silversponsors/9/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/silversponsors/10/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/silversponsors/10/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/silversponsors/11/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/silversponsors/11/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/silversponsors/12/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/silversponsors/12/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/silversponsors/13/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/silversponsors/13/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/silversponsors/14/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/silversponsors/14/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/silversponsors/15/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/silversponsors/15/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/silversponsors/16/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/silversponsors/16/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/silversponsors/17/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/silversponsors/17/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/silversponsors/18/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/silversponsors/18/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/silversponsors/19/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/silversponsors/19/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/silversponsors/20/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/silversponsors/20/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/silversponsors/21/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/silversponsors/21/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/silversponsors/22/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/silversponsors/22/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/silversponsors/23/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/silversponsors/23/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/silversponsors/24/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/silversponsors/24/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/silversponsors/25/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/silversponsors/25/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/silversponsors/26/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/silversponsors/26/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/silversponsors/27/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/silversponsors/27/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/silversponsors/28/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/silversponsors/28/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/silversponsors/29/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/silversponsors/29/avatar.svg"></a>
 
 <h2 align="center">Bronze via Patreon</h2>
 
@@ -246,36 +241,36 @@ Funds donated via Patreon goes directly to support Evan You's full-time work on
 
 <h2 align="center">Bronze via OpenCollective</h2>
 
-<a href="https://opencollective.com/vuejs/bronzesponsor/0/website" target="_blank"><img src="https://opencollective.com/vuejs/bronzesponsor/0/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/bronzesponsor/1/website" target="_blank"><img src="https://opencollective.com/vuejs/bronzesponsor/1/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/bronzesponsor/2/website" target="_blank"><img src="https://opencollective.com/vuejs/bronzesponsor/2/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/bronzesponsor/3/website" target="_blank"><img src="https://opencollective.com/vuejs/bronzesponsor/3/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/bronzesponsor/4/website" target="_blank"><img src="https://opencollective.com/vuejs/bronzesponsor/4/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/bronzesponsor/5/website" target="_blank"><img src="https://opencollective.com/vuejs/bronzesponsor/5/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/bronzesponsor/6/website" target="_blank"><img src="https://opencollective.com/vuejs/bronzesponsor/6/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/bronzesponsor/7/website" target="_blank"><img src="https://opencollective.com/vuejs/bronzesponsor/7/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/bronzesponsor/8/website" target="_blank"><img src="https://opencollective.com/vuejs/bronzesponsor/8/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/bronzesponsor/9/website" target="_blank"><img src="https://opencollective.com/vuejs/bronzesponsor/9/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/bronzesponsor/10/website" target="_blank"><img src="https://opencollective.com/vuejs/bronzesponsor/10/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/bronzesponsor/11/website" target="_blank"><img src="https://opencollective.com/vuejs/bronzesponsor/11/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/bronzesponsor/12/website" target="_blank"><img src="https://opencollective.com/vuejs/bronzesponsor/12/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/bronzesponsor/13/website" target="_blank"><img src="https://opencollective.com/vuejs/bronzesponsor/13/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/bronzesponsor/14/website" target="_blank"><img src="https://opencollective.com/vuejs/bronzesponsor/14/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/bronzesponsor/15/website" target="_blank"><img src="https://opencollective.com/vuejs/bronzesponsor/15/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/bronzesponsor/16/website" target="_blank"><img src="https://opencollective.com/vuejs/bronzesponsor/16/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/bronzesponsor/17/website" target="_blank"><img src="https://opencollective.com/vuejs/bronzesponsor/17/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/bronzesponsor/18/website" target="_blank"><img src="https://opencollective.com/vuejs/bronzesponsor/18/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/bronzesponsor/19/website" target="_blank"><img src="https://opencollective.com/vuejs/bronzesponsor/19/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/bronzesponsor/20/website" target="_blank"><img src="https://opencollective.com/vuejs/bronzesponsor/20/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/bronzesponsor/21/website" target="_blank"><img src="https://opencollective.com/vuejs/bronzesponsor/21/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/bronzesponsor/22/website" target="_blank"><img src="https://opencollective.com/vuejs/bronzesponsor/22/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/bronzesponsor/23/website" target="_blank"><img src="https://opencollective.com/vuejs/bronzesponsor/23/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/bronzesponsor/24/website" target="_blank"><img src="https://opencollective.com/vuejs/bronzesponsor/24/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/bronzesponsor/25/website" target="_blank"><img src="https://opencollective.com/vuejs/bronzesponsor/25/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/bronzesponsor/26/website" target="_blank"><img src="https://opencollective.com/vuejs/bronzesponsor/26/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/bronzesponsor/27/website" target="_blank"><img src="https://opencollective.com/vuejs/bronzesponsor/27/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/bronzesponsor/28/website" target="_blank"><img src="https://opencollective.com/vuejs/bronzesponsor/28/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/bronzesponsor/29/website" target="_blank"><img src="https://opencollective.com/vuejs/bronzesponsor/29/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/bronzesponsors/0/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronzesponsors/0/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/bronzesponsors/1/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronzesponsors/1/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/bronzesponsors/2/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronzesponsors/2/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/bronzesponsors/3/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronzesponsors/3/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/bronzesponsors/4/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronzesponsors/4/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/bronzesponsors/5/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronzesponsors/5/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/bronzesponsors/6/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronzesponsors/6/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/bronzesponsors/7/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronzesponsors/7/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/bronzesponsors/8/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronzesponsors/8/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/bronzesponsors/9/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronzesponsors/9/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/bronzesponsors/10/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronzesponsors/10/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/bronzesponsors/11/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronzesponsors/11/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/bronzesponsors/12/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronzesponsors/12/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/bronzesponsors/13/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronzesponsors/13/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/bronzesponsors/14/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronzesponsors/14/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/bronzesponsors/15/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronzesponsors/15/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/bronzesponsors/16/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronzesponsors/16/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/bronzesponsors/17/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronzesponsors/17/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/bronzesponsors/18/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronzesponsors/18/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/bronzesponsors/19/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronzesponsors/19/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/bronzesponsors/20/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronzesponsors/20/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/bronzesponsors/21/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronzesponsors/21/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/bronzesponsors/22/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronzesponsors/22/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/bronzesponsors/23/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronzesponsors/23/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/bronzesponsors/24/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronzesponsors/24/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/bronzesponsors/25/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronzesponsors/25/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/bronzesponsors/26/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronzesponsors/26/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/bronzesponsors/27/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronzesponsors/27/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/bronzesponsors/28/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronzesponsors/28/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/bronzesponsors/29/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronzesponsors/29/avatar.svg"></a>
 
 <h2 align="center">Generous Backers via Patreon ($50+)</h2>
 
@@ -291,6 +286,7 @@ Funds donated via Patreon goes directly to support Evan You's full-time work on
 - Alex Balashov
 - Konstantin Levinski
 - Samuel Smith
+- Harri J Salomaa
 
 <h2 align="center">Backers via Patreon</h2>
 
@@ -465,6 +461,28 @@ Funds donated via Patreon goes directly to support Evan You's full-time work on
 - Keith Mancuso
 - Alexander Karelas
 - Matias Verdier
+- Jamie McElwain
+- Travis Gertz
+- Ale Mohamad
+- Jonas Galvez
+- William Correa
+- Raphael Belvederese
+- Mickaël Andrieu
+- Guilherme S L de Souza
+- Rob Yedlin
+- Daniel Waghorn
+- Eric Githinji
+- Vivekanandhan Natarajan
+- Chih-Hsuan Fan
+- Jordan Oroshiba
+- Brian Jorden
+- Cliff Hess
+- Joe Gregory
+- Johnny Eshan
+- Alexander Karelas
+- Kamil Ocean
+- Orney Enrique Martinez Said
+- Tom Striker
 
 <h2 align="center">Backers via OpenCollective</h2>
 
diff --git a/README.md b/README.md
index f3c43fb..bae6837 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@
   <a href="https://www.npmjs.com/package/vue"><img src="https://img.shields.io/npm/dm/vue.svg" alt="Downloads"></a>
   <a href="https://www.npmjs.com/package/vue"><img src="https://img.shields.io/npm/v/vue.svg" alt="Version"></a>
   <a href="https://www.npmjs.com/package/vue"><img src="https://img.shields.io/npm/l/vue.svg" alt="License"></a>
-  <a href="https://chat.vuejs.org/"><img src="https://img.shields.io/badge/chat-on%20discord-7289da.svg" alt="Chat">
+  <a href="https://chat.vuejs.org/"><img src="https://img.shields.io/badge/chat-on%20discord-7289da.svg" alt="Chat"></a>
   <br>
   <a href="https://saucelabs.com/u/vuejs"><img src="https://saucelabs.com/browser-matrix/vuejs.svg" alt="Sauce Test Status"></a>
 </p>
@@ -16,7 +16,7 @@
 Vue.js is an MIT-licensed open source project. It's an independent project with its ongoing development made possible entirely thanks to the support by these awesome [backers](https://github.com/vuejs/vue/blob/dev/BACKERS.md). If you'd like to join them, please consider:
 
 - [Become a backer or sponsor on Patreon](https://www.patreon.com/evanyou).
-- [Become a backer or sponsor on OpenCollective](https://opencollective.com/vuejs).
+- [Become a backer or sponsor on Open Collective](https://opencollective.com/vuejs).
 
 #### What's the difference between Patreon and OpenCollective?
 
@@ -34,6 +34,10 @@ Funds donated via Patreon goes directly to support Evan You's full-time work on
   <a href="https://xiaozhuanlan.com">
     <img width="160px" src="https://raw.githubusercontent.com/vuejs/cn.vuejs.org/master/themes/vue/source/images/xiaozhuanlan.png">
   </a>
+  <br><br>
+  <a href="http://tooltwist.com" target="_blank">
+    <img width="220px" src="https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/tooltwist.png">
+  </a>
 </p>
 
 <h4 align="center">Gold</h4>
@@ -100,19 +104,14 @@ Funds donated via Patreon goes directly to support Evan You's full-time work on
         </a>
       </td>
       <td align="center" valign="middle">
-        <a href="https://www.v2ex.com/t/379389" target="_blank">
-          <img width="130px" src="https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/v2exer.png">
+        <a href="https://www.xfive.co/" target="_blank">
+          <img width="80px" src="https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/xfive.png">
         </a>
       </td>
     </tr>
     <tr></tr>
     <tr>
       <td align="center" valign="middle">
-        <a href="https://www.xfive.co/" target="_blank">
-          <img width="80px" src="https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/xfive.png">
-        </a>
-      </td>
-      <td align="center" valign="middle">
         <a href="http://www.frontenddevelopermeetups.com/" target="_blank">
           <img width="160px" src="https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/frontend-meetups.png">
         </a>
@@ -123,30 +122,28 @@ Funds donated via Patreon goes directly to support Evan You's full-time work on
         </a>
       </td>
       <td align="center" valign="middle">
-        <a href="http://tooltwist.com" target="_blank">
-          <img width="140px" src="https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/tooltwist.png">
+        <a href="https://themeforest.net/item/clear-bootstrap-vuejs-admin-template/19339739?ref=jyostna&utm_source=vuejs.org&utm_campaign=vuejs_patreon" target="_blank">
+          <img width="150px" src="https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/vuejsadmin.png">
         </a>
       </td>
     </tr>
   </tbody>
 </table>
 
-<h3 align="center">Sponsors via OpenCollective</h3>
+<h3 align="center">Sponsors via <a href="https://opencollective.com/vuejs">Open Collective</a></h3>
 
 <h4 align="center">Platinum</h4>
 
-<a href="https://opencollective.com/vuejs/platinumsponsor/0/website" target="_blank"><img src="https://opencollective.com/vuejs/platinumsponsor/0/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/platinumsponsor/1/website" target="_blank"><img src="https://opencollective.com/vuejs/platinumsponsor/1/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/platinumsponsors/0/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/platinumsponsors/0/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/platinumsponsors/1/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/platinumsponsors/1/avatar.svg"></a>
 
 <h4 align="center">Gold</h4>
 
-<a href="https://opencollective.com/vuejs/goldsponsor/0/website" target="_blank"><img src="https://opencollective.com/vuejs/goldsponsor/0/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/bronzesponsor/1/website" target="_blank"><img src="https://opencollective.com/vuejs/bronzesponsor/1/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/goldsponsor/1/website" target="_blank"><img src="https://opencollective.com/vuejs/goldsponsor/1/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/goldsponsor/2/website" target="_blank"><img src="https://opencollective.com/vuejs/goldsponsor/2/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/goldsponsor/3/website" target="_blank"><img src="https://opencollective.com/vuejs/goldsponsor/3/avatar.svg"></a>
-<a href="https://opencollective.com/vuejs/goldsponsor/4/website" target="_blank"><img src="https://opencollective.com/vuejs/goldsponsor/4
-  /avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/goldsponsors/0/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/goldsponsors/0/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/goldsponsors/1/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/goldsponsors/1/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/goldsponsors/2/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/goldsponsors/2/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/goldsponsors/3/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/goldsponsors/3/avatar.svg"></a>
+<a href="https://opencollective.com/vuejs/tiers/goldsponsors/4/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/goldsponsors/4/avatar.svg"></a>
 
 ---
 
@@ -200,7 +197,7 @@ Vue.js supports all browsers that are [ES5-compliant](http://kangax.github.io/co
 
 ## Documentation
 
-To check out live examples and docs, visit [vuejs.org](https://vuejs.org).
+To check out [live examples](https://vuejs.org/v2/examples/) and docs, visit [vuejs.org](https://vuejs.org).
 
 ## Questions
 
diff --git a/build/install-hooks.js b/build/install-hooks.js
deleted file mode 100644
index e5f8ad8..0000000
--- a/build/install-hooks.js
+++ /dev/null
@@ -1,8 +0,0 @@
-const { test, ln, chmod } = require('shelljs')
-
-if (test('-e', '.git/hooks')) {
-  ln('-sf', '../../build/git-hooks/pre-commit', '.git/hooks/pre-commit')
-  chmod('+x', '.git/hooks/pre-commit')
-  ln('-sf', '../../build/git-hooks/commit-msg', '.git/hooks/commit-msg')
-  chmod('+x', '.git/hooks/commit-msg')
-}
diff --git a/build/release.sh b/build/release.sh
index 8452944..ea2acf2 100644
--- a/build/release.sh
+++ b/build/release.sh
@@ -20,7 +20,7 @@ if [[ $REPLY =~ ^[Yy]$ ]]; then
     npm run test:ssr
   fi
 
-  # Sauce Labs tests has a decent change of failing
+  # Sauce Labs tests has a decent chance of failing
   # so we usually manually run them before running the release script.
 
   # if [[ -z $SKIP_SAUCE ]]; then
@@ -60,6 +60,9 @@ if [[ $REPLY =~ ^[Yy]$ ]]; then
     packages/vue-server-renderer/client-plugin.js \
     packages/vue-template-compiler/build.js
   git commit -m "build: build $VERSION"
+  # generate release note
+  npm run release:note
+  # tag version
   npm version $VERSION --message "build: release $VERSION"
 
   # publish
diff --git a/build/setup.js b/build/setup.js
new file mode 100644
index 0000000..3427c5a
--- /dev/null
+++ b/build/setup.js
@@ -0,0 +1,12 @@
+const { test, ln, chmod } = require('shelljs')
+
+function installHooks () {
+  if (test('-e', '.git/hooks')) {
+    ln('-sf', '../../build/git-hooks/pre-commit', '.git/hooks/pre-commit')
+    chmod('+x', '.git/hooks/pre-commit')
+    ln('-sf', '../../build/git-hooks/commit-msg', '.git/hooks/commit-msg')
+    chmod('+x', '.git/hooks/commit-msg')
+  }
+}
+
+installHooks()
diff --git a/flow/compiler.js b/flow/compiler.js
index 8947378..a5ebc5f 100644
--- a/flow/compiler.js
+++ b/flow/compiler.js
@@ -14,7 +14,8 @@ declare type CompilerOptions = {
   preserveWhitespace?: boolean;
   isFromDOM?: boolean;
   shouldDecodeTags?: boolean;
-  shouldDecodeNewlines?: boolean;
+  shouldDecodeNewlines?:  boolean;
+  shouldDecodeNewlinesForHref?: boolean;
 
   // for ssr optimization compiler
   scopeId?: string;
diff --git a/flow/component.js b/flow/component.js
index 5286944..9fbade0 100644
--- a/flow/component.js
+++ b/flow/component.js
@@ -66,6 +66,7 @@ declare interface Component {
   _isDestroyed: boolean;
   _isBeingDestroyed: boolean;
   _vnode: ?VNode; // self root node
+  _staticTrees: ?Array<VNode>; // v-once cached trees
   _hasHookEvent: boolean;
   _provided: ?Object;
 
diff --git a/package-lock.json b/package-lock.json
index 9e19ef4..77ce83f 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
 {
   "name": "vue",
-  "version": "2.5.2",
+  "version": "2.5.9",
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
@@ -42,16 +42,6 @@
         "@types/uglify-js": "2.6.29"
       }
     },
-    "JSONStream": {
-      "version": "1.3.1",
-      "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.1.tgz",
-      "integrity": "sha1-cH92HgHa6eFvG8+TcDt4xwlmV5o=",
-      "dev": true,
-      "requires": {
-        "jsonparse": "1.3.1",
-        "through": "2.3.8"
-      }
-    },
     "abbrev": {
       "version": "1.0.9",
       "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz",
@@ -2129,8 +2119,8 @@
       "integrity": "sha512-8od6g684Fhi5Vpp4ABRv/RBsW1AY6wSHbJHEK6FGTv+8jvAAnlABniZu/FVmX9TcirkHepaEsa1QGkRvbg0CKw==",
       "dev": true,
       "requires": {
-        "JSONStream": "1.3.1",
         "is-text-path": "1.0.1",
+        "JSONStream": "1.3.1",
         "lodash": "4.17.4",
         "meow": "3.7.0",
         "split2": "2.1.1",
@@ -4310,22 +4300,22 @@
             }
           }
         },
-        "string-width": {
-          "version": "1.0.2",
+        "string_decoder": {
+          "version": "1.0.1",
           "bundled": true,
           "dev": true,
           "requires": {
-            "code-point-at": "1.1.0",
-            "is-fullwidth-code-point": "1.0.0",
-            "strip-ansi": "3.0.1"
+            "safe-buffer": "5.0.1"
           }
         },
-        "string_decoder": {
-          "version": "1.0.1",
+        "string-width": {
+          "version": "1.0.2",
           "bundled": true,
           "dev": true,
           "requires": {
-            "safe-buffer": "5.0.1"
+            "code-point-at": "1.1.0",
+            "is-fullwidth-code-point": "1.0.0",
+            "strip-ansi": "3.0.1"
           }
         },
         "stringstream": {
@@ -5531,6 +5521,16 @@
       "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=",
       "dev": true
     },
+    "JSONStream": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.1.tgz",
+      "integrity": "sha1-cH92HgHa6eFvG8+TcDt4xwlmV5o=",
+      "dev": true,
+      "requires": {
+        "jsonparse": "1.3.1",
+        "through": "2.3.8"
+      }
+    },
     "jsprim": {
       "version": "1.4.1",
       "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
@@ -8387,6 +8387,15 @@
         "xtend": "4.0.1"
       }
     },
+    "string_decoder": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
+      "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
+      "dev": true,
+      "requires": {
+        "safe-buffer": "5.1.1"
+      }
+    },
     "string-width": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
@@ -8398,15 +8407,6 @@
         "strip-ansi": "3.0.1"
       }
     },
-    "string_decoder": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
-      "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
-      "dev": true,
-      "requires": {
-        "safe-buffer": "5.1.1"
-      }
-    },
     "stringstream": {
       "version": "0.0.5",
       "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz",
@@ -8726,9 +8726,9 @@
       "dev": true
     },
     "typescript": {
-      "version": "2.5.2",
-      "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.5.2.tgz",
-      "integrity": "sha1-A4qV99m7tCCxvzW6MdTFwd0//jQ=",
+      "version": "2.6.1",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.6.1.tgz",
+      "integrity": "sha1-7znN6ierrAtQAkLWcmq5DgyEZjE=",
       "dev": true
     },
     "uglify-js": {
diff --git a/package.json b/package.json
index a8c2ad3..2713abb 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "vue",
-  "version": "2.5.2",
+  "version": "2.5.9",
   "description": "Reactive, component-oriented view layer for modern web interfaces.",
   "main": "dist/vue.runtime.common.js",
   "module": "dist/vue.runtime.esm.js",
@@ -40,7 +40,7 @@
     "release": "bash build/release.sh",
     "release:weex": "bash build/release-weex.sh",
     "release:note": "node build/gen-release-note.js",
-    "setup": "node build/install-hooks.js",
+    "setup": "node build/setup.js",
     "commit": "git-cz"
   },
   "repository": {
@@ -122,10 +122,11 @@
     "selenium-server": "^2.53.1",
     "serialize-javascript": "^1.3.0",
     "shelljs": "^0.7.8",
-    "typescript": "^2.5.2",
+    "typescript": "^2.6.1",
     "uglify-js": "^3.0.15",
     "webpack": "^2.6.1",
-    "weex-js-runtime": "^0.23.0"
+    "weex-js-runtime": "^0.23.0",
+    "weex-styler": "^0.3.0"
   },
   "config": {
     "commitizen": {
diff --git a/packages/vue-server-renderer/basic.js b/packages/vue-server-renderer/basic.js
index 300a12d..b77f50a 100644
--- a/packages/vue-server-renderer/basic.js
+++ b/packages/vue-server-renderer/basic.js
@@ -6,6 +6,8 @@
 
 /*  */
 
+var emptyObject = Object.freeze({});
+
 // these helpers produces better vm code in JS engines due to their
 // explicitness and function inlining
 function isUndef (v) {
@@ -438,9 +440,9 @@ var VNode = function VNode (
   this.elm = elm;
   this.ns = undefined;
   this.context = context;
-  this.functionalContext = undefined;
-  this.functionalOptions = undefined;
-  this.functionalScopeId = undefined;
+  this.fnContext = undefined;
+  this.fnOptions = undefined;
+  this.fnScopeId = undefined;
   this.key = data && data.key;
   this.componentOptions = componentOptions;
   this.componentInstance = undefined;
@@ -484,6 +486,7 @@ function createTextVNode (val) {
 // multiple renders, cloning them avoids errors when DOM manipulations rely
 // on their elm reference.
 function cloneVNode (vnode, deep) {
+  var componentOptions = vnode.componentOptions;
   var cloned = new VNode(
     vnode.tag,
     vnode.data,
@@ -491,16 +494,24 @@ function cloneVNode (vnode, deep) {
     vnode.text,
     vnode.elm,
     vnode.context,
-    vnode.componentOptions,
+    componentOptions,
     vnode.asyncFactory
   );
   cloned.ns = vnode.ns;
   cloned.isStatic = vnode.isStatic;
   cloned.key = vnode.key;
   cloned.isComment = vnode.isComment;
+  cloned.fnContext = vnode.fnContext;
+  cloned.fnOptions = vnode.fnOptions;
+  cloned.fnScopeId = vnode.fnScopeId;
   cloned.isCloned = true;
-  if (deep && vnode.children) {
-    cloned.children = cloneVNodes(vnode.children);
+  if (deep) {
+    if (vnode.children) {
+      cloned.children = cloneVNodes(vnode.children, true);
+    }
+    if (componentOptions && componentOptions.children) {
+      componentOptions.children = cloneVNodes(componentOptions.children, true);
+    }
   }
   return cloned
 }
@@ -538,7 +549,10 @@ function renderDOMProps (node) {
       setText(node, props[key], true);
     } else if (key === 'textContent') {
       setText(node, props[key], false);
+    } else if (key === 'value' && node.tag === 'textarea') {
+      setText(node, props[key], false);
     } else {
+      // $flow-disable-line (WTF?)
       var attr = propsToAttrMap[key] || key.toLowerCase();
       if (isRenderableAttr(attr) &&
         // avoid rendering double-bound props/attrs twice
@@ -559,8 +573,6 @@ function setText (node, text, raw) {
 
 /*  */
 
-var emptyObject = Object.freeze({});
-
 /**
  * Check if a string starts with $ or _
  */
@@ -598,17 +610,20 @@ function parsePath (path) {
 
 /*  */
 
+
 // can we use __proto__?
 var hasProto = '__proto__' in {};
 
 // Browser environment sniffing
 var inBrowser = typeof window !== 'undefined';
+var inWeex = typeof WXEnvironment !== 'undefined' && !!WXEnvironment.platform;
+var weexPlatform = inWeex && WXEnvironment.platform.toLowerCase();
 var UA = inBrowser && window.navigator.userAgent.toLowerCase();
 var isIE = UA && /msie|trident/.test(UA);
 var isIE9 = UA && UA.indexOf('msie 9.0') > 0;
 var isEdge = UA && UA.indexOf('edge/') > 0;
-var isAndroid = UA && UA.indexOf('android') > 0;
-var isIOS = UA && /iphone|ipad|ipod|ios/.test(UA);
+var isAndroid = (UA && UA.indexOf('android') > 0) || (weexPlatform === 'android');
+var isIOS = (UA && /iphone|ipad|ipod|ios/.test(UA)) || (weexPlatform === 'ios');
 var isChrome = UA && /chrome\/\d+/.test(UA) && !isEdge;
 
 // Firefox has a "watch" function on Object.prototype...
@@ -1156,7 +1171,7 @@ function set (target, key, val) {
     target.splice(key, 1, val);
     return val
   }
-  if (hasOwn(target, key)) {
+  if (key in target && !(key in Object.prototype)) {
     target[key] = val;
     return val
   }
@@ -1267,7 +1282,7 @@ function mergeDataOrFn (
         typeof parentVal === 'function' ? parentVal.call(this) : parentVal
       )
     }
-  } else if (parentVal || childVal) {
+  } else {
     return function mergedInstanceDataFn () {
       // instance merge
       var instanceData = typeof childVal === 'function'
@@ -1301,7 +1316,7 @@ strats.data = function (
 
       return parentVal
     }
-    return mergeDataOrFn.call(this, parentVal, childVal)
+    return mergeDataOrFn(parentVal, childVal)
   }
 
   return mergeDataOrFn(parentVal, childVal, vm)
@@ -1811,7 +1826,7 @@ function logError (err, vm, info) {
     warn(("Error in " + info + ": \"" + (err.toString()) + "\""), vm);
   }
   /* istanbul ignore else */
-  if (inBrowser && typeof console !== 'undefined') {
+  if ((inBrowser || inWeex) && typeof console !== 'undefined') {
     console.error(err);
   } else {
     throw err
@@ -2179,8 +2194,52 @@ function show (node, dir) {
   }
 }
 
+/*  */
+
+// this is only applied for <select v-model> because it is the only edge case
+// that must be done at runtime instead of compile time.
+function model (node, dir) {
+  if (!node.children) { return }
+  var value = dir.value;
+  var isMultiple = node.data.attrs && node.data.attrs.multiple;
+  for (var i = 0, l = node.children.length; i < l; i++) {
+    var option = node.children[i];
+    if (option.tag === 'option') {
+      if (isMultiple) {
+        var selected =
+          Array.isArray(value) &&
+          (looseIndexOf(value, getValue(option)) > -1);
+        if (selected) {
+          setSelected(option);
+        }
+      } else {
+        if (looseEqual(value, getValue(option))) {
+          setSelected(option);
+          return
+        }
+      }
+    }
+  }
+}
+
+function getValue (option) {
+  var data = option.data || {};
+  return (
+    (data.attrs && data.attrs.value) ||
+    (data.domProps && data.domProps.value) ||
+    (option.children && option.children[0] && option.children[0].text)
+  )
+}
+
+function setSelected (option) {
+  var data = option.data || (option.data = {});
+  var attrs = data.attrs || (data.attrs = {});
+  attrs.selected = '';
+}
+
 var directives = {
-  show: show
+  show: show,
+  model: model
 };
 
 /*  */
@@ -2524,39 +2583,59 @@ function addHandler (
   important,
   warn
 ) {
+  modifiers = modifiers || emptyObject;
   // warn prevent and passive modifier
   /* istanbul ignore if */
   if (
     "development" !== 'production' && warn &&
-    modifiers && modifiers.prevent && modifiers.passive
+    modifiers.prevent && modifiers.passive
   ) {
     warn(
       'passive and prevent can\'t be used together. ' +
       'Passive handler can\'t prevent default event.'
     );
   }
+
   // check capture modifier
-  if (modifiers && modifiers.capture) {
+  if (modifiers.capture) {
     delete modifiers.capture;
     name = '!' + name; // mark the event as captured
   }
-  if (modifiers && modifiers.once) {
+  if (modifiers.once) {
     delete modifiers.once;
     name = '~' + name; // mark the event as once
   }
   /* istanbul ignore if */
-  if (modifiers && modifiers.passive) {
+  if (modifiers.passive) {
     delete modifiers.passive;
     name = '&' + name; // mark the event as passive
   }
+
+  // normalize click.right and click.middle since they don't actually fire
+  // this is technically browser-specific, but at least for now browsers are
+  // the only target envs that have right/middle clicks.
+  if (name === 'click') {
+    if (modifiers.right) {
+      name = 'contextmenu';
+      delete modifiers.right;
+    } else if (modifiers.middle) {
+      name = 'mouseup';
+    }
+  }
+
   var events;
-  if (modifiers && modifiers.native) {
+  if (modifiers.native) {
     delete modifiers.native;
     events = el.nativeEvents || (el.nativeEvents = {});
   } else {
     events = el.events || (el.events = {});
   }
-  var newHandler = { value: value, modifiers: modifiers };
+
+  var newHandler = { value: value };
+  if (modifiers !== emptyObject) {
+    newHandler.modifiers = modifiers;
+  }
+
   var handlers = events[name];
   /* istanbul ignore if */
   if (Array.isArray(handlers)) {
@@ -3090,10 +3169,11 @@ var decodingMap = {
   '>': '>',
   '"': '"',
   '&': '&',
-  '
': '\n'
+  '
': '\n',
+  '	': '\t'
 };
 var encodedAttr = /&(?:lt|gt|quot|amp);/g;
-var encodedAttrWithNewLines = /&(?:lt|gt|quot|amp|#10);/g;
+var encodedAttrWithNewLines = /&(?:lt|gt|quot|amp|#10|#9);/g;
 
 // #5992
 var isIgnoreNewlineTag = makeMap('pre,textarea', true);
@@ -3284,12 +3364,12 @@ function parseHTML (html, options) {
         if (args[5] === '') { delete args[5]; }
       }
       var value = args[3] || args[4] || args[5] || '';
+      var shouldDecodeNewlines = tagName === 'a' && args[1] === 'href'
+        ? options.shouldDecodeNewlinesForHref
+        : options.shouldDecodeNewlines;
       attrs[i] = {
         name: args[1],
-        value: decodeAttr(
-          value,
-          options.shouldDecodeNewlines
-        )
+        value: decodeAttr(value, shouldDecodeNewlines)
       };
     }
 
@@ -3513,7 +3593,8 @@ function parseString (chr) {
 var onRE = /^@|^v-on:/;
 var dirRE = /^v-|^@|^:/;
 var forAliasRE = /(.*?)\s+(?:in|of)\s+(.*)/;
-var forIteratorRE = /\((\{[^}]*\}|[^,]*),([^,]*)(?:,([^,]*))?\)/;
+var forIteratorRE = /\((\{[^}]*\}|[^,{]*),([^,]*)(?:,([^,]*))?\)/;
+var stripParensRE = /^\(|\)$/g;
 
 var argRE = /:(.*)$/;
 var bindRE = /^:|^v-bind:/;
@@ -3598,6 +3679,7 @@ function parse (
     isUnaryTag: options.isUnaryTag,
     canBeLeftOpenTag: options.canBeLeftOpenTag,
     shouldDecodeNewlines: options.shouldDecodeNewlines,
+    shouldDecodeNewlinesForHref: options.shouldDecodeNewlinesForHref,
     shouldKeepComment: options.comments,
     start: function start (tag, attrs, unary) {
       // check namespace.
@@ -3853,7 +3935,7 @@ function processFor (el) {
         el.iterator2 = iteratorMatch[3].trim();
       }
     } else {
-      el.alias = alias;
+      el.alias = alias.replace(stripParensRE, '');
     }
   }
 }
@@ -3949,6 +4031,15 @@ function processSlot (el) {
       }
       el.slotScope = slotScope || getAndRemoveAttr(el, 'slot-scope');
     } else if ((slotScope = getAndRemoveAttr(el, 'slot-scope'))) {
+      /* istanbul ignore if */
+      if ("development" !== 'production' && el.attrsMap['v-for']) {
+        warn$1(
+          "Ambiguous combined usage of slot-scope and v-for on <" + (el.tag) + "> " +
+          "(v-for takes higher priority). Use a wrapper <template> for the " +
+          "scoped slot to make it clearer.",
+          true
+        );
+      }
       el.slotScope = slotScope;
     }
     var slotTarget = getBindingAttr(el, 'slot');
@@ -3956,7 +4047,7 @@ function processSlot (el) {
       el.slotTarget = slotTarget === '""' ? '"default"' : slotTarget;
       // preserve slot as an attribute for native shadow DOM compat
       // only for non-scoped slots.
-      if (!el.slotScope) {
+      if (el.tag !== 'template' && !el.slotScope) {
         addAttr(el, 'slot', slotTarget);
       }
     }
@@ -4045,6 +4136,13 @@ function processAttrs (el) {
         }
       }
       addAttr(el, name, JSON.stringify(value));
+      // #6887 firefox doesn't update muted state if set via attribute
+      // even immediately after element creation
+      if (!el.component &&
+          name === 'muted' &&
+          platformMustUseProp(el.tag, el.attrsMap.type, name)) {
+        addProp(el, name, 'true');
+      }
     }
   }
 }
@@ -4149,6 +4247,8 @@ function preTransformNode (el, options) {
       var typeBinding = getBindingAttr(el, 'type');
       var ifCondition = getAndRemoveAttr(el, 'v-if', true);
       var ifConditionExtra = ifCondition ? ("&&(" + ifCondition + ")") : "";
+      var hasElse = getAndRemoveAttr(el, 'v-else', true) != null;
+      var elseIfCondition = getAndRemoveAttr(el, 'v-else-if', true);
       // 1. checkbox
       var branch0 = cloneASTElement(el);
       // process for on the main node
@@ -4179,6 +4279,13 @@ function preTransformNode (el, options) {
         exp: ifCondition,
         block: branch2
       });
+
+      if (hasElse) {
+        branch0.else = true;
+      } else if (elseIfCondition) {
+        branch0.elseif = elseIfCondition;
+      }
+
       return branch0
     }
   }
@@ -4193,14 +4300,14 @@ function addRawAttr (el, name, value) {
   el.attrsList.push({ name: name, value: value });
 }
 
-var model = {
+var model$1 = {
   preTransformNode: preTransformNode
 };
 
 var modules$1 = [
   klass,
   style,
-  model
+  model$1
 ];
 
 /*  */
@@ -4212,7 +4319,7 @@ var warn$2;
 var RANGE_TOKEN = '__r';
 
 
-function model$1 (
+function model$2 (
   el,
   dir,
   _warn
@@ -4329,6 +4436,19 @@ function genDefaultModel (
   modifiers
 ) {
   var type = el.attrsMap.type;
+
+  // warn if v-bind:value conflicts with v-model
+  {
+    var value$1 = el.attrsMap['v-bind:value'] || el.attrsMap[':value'];
+    if (value$1) {
+      var binding = el.attrsMap['v-bind:value'] ? 'v-bind:value' : ':value';
+      warn$2(
+        binding + "=\"" + value$1 + "\" conflicts with v-model on the same element " +
+        'because the latter already expands to a value binding internally'
+      );
+    }
+  }
+
   var ref = modifiers || {};
   var lazy = ref.lazy;
   var number = ref.number;
@@ -4377,7 +4497,7 @@ function html (el, dir) {
 }
 
 var directives$1 = {
-  model: model$1,
+  model: model$2,
   text: text,
   html: html
 };
@@ -4440,18 +4560,7 @@ function genHandlers (
 ) {
   var res = isNative ? 'nativeOn:{' : 'on:{';
   for (var name in events) {
-    var handler = events[name];
-    // #5330: warn click.right, since right clicks do not actually fire click events.
-    if ("development" !== 'production' &&
-      name === 'click' &&
-      handler && handler.modifiers && handler.modifiers.right
-    ) {
-      warn(
-        "Use \"contextmenu\" instead of \"click.right\" since right clicks " +
-        "do not actually fire \"click\" events."
-      );
-    }
-    res += "\"" + name + "\":" + (genHandler(name, handler)) + ",";
+    res += "\"" + name + "\":" + (genHandler(name, events[name])) + ",";
   }
   return res.slice(0, -1) + '}'
 }
@@ -4618,10 +4727,10 @@ function genElement (el, state) {
 }
 
 // hoist static sub-trees out
-function genStatic (el, state) {
+function genStatic (el, state, once$$1) {
   el.staticProcessed = true;
   state.staticRenderFns.push(("with(this){return " + (genElement(el, state)) + "}"));
-  return ("_m(" + (state.staticRenderFns.length - 1) + (el.staticInFor ? ',true' : '') + ")")
+  return ("_m(" + (state.staticRenderFns.length - 1) + "," + (el.staticInFor ? 'true' : 'false') + "," + (once$$1 ? 'true' : 'false') + ")")
 }
 
 // v-once
@@ -4647,7 +4756,7 @@ function genOnce (el, state) {
     }
     return ("_o(" + (genElement(el, state)) + "," + (state.onceId++) + "," + key + ")")
   } else {
-    return genStatic(el, state)
+    return genStatic(el, state, true)
   }
 }
 
@@ -5011,6 +5120,10 @@ function applyModelTransform (el, state) {
       var dir = el.directives[i];
       if (dir.name === 'model') {
         state.directives.model(el, dir, state.warn);
+        // remove value for textarea as its converted to text
+        if (el.tag === 'textarea' && el.props) {
+          el.props = el.props.filter(function (p) { return p.name !== 'value'; });
+        }
         break
       }
     }
@@ -5158,7 +5271,7 @@ function walk (node, isRoot) {
     if (node.ifConditions) {
       for (var i$1 = 1, l$1 = node.ifConditions.length; i$1 < l$1; i$1++) {
         var block = node.ifConditions[i$1].block;
-        walk(block);
+        walk(block, isRoot);
         check(block);
       }
     }
@@ -5216,7 +5329,8 @@ function isUnOptimizableTree (node) {
   return (
     isBuiltInTag(node.tag) || // built-in (slot, component)
     !isPlatformReservedTag(node.tag) || // custom component
-    !!node.component // "is" component
+    !!node.component || // "is" component
+    isSelectWithModel(node) // <select v-model> requires runtime inspection
   )
 }
 
@@ -5230,6 +5344,17 @@ function hasCustomDirective (node) {
   )
 }
 
+// <select v-model> cannot be optimized because it requires a runtime check
+// to determine proper selected option
+function isSelectWithModel (node) {
+  return (
+    node.type === 1 &&
+    node.tag === 'select' &&
+    node.directives != null &&
+    node.directives.some(function (d) { return d.name === 'model'; })
+  )
+}
+
 /*  */
 
 // The SSR codegen is essentially extending the default codegen to handle
@@ -5403,6 +5528,9 @@ function childrenToSegments (el, state) {
   if ((binding = el.attrsMap['v-text'])) {
     return [{ type: INTERPOLATION, value: ("_s(" + binding + ")") }]
   }
+  if (el.tag === 'textarea' && (binding = el.attrsMap['v-model'])) {
+    return [{ type: INTERPOLATION, value: ("_s(" + binding + ")") }]
+  }
   return el.children
     ? nodesToSegments(el.children, state)
     : []
@@ -5469,9 +5597,6 @@ var unaryOperatorsRE = new RegExp('\\b' + (
   'delete,typeof,void'
 ).split(',').join('\\s*\\([^\\)]*\\)|\\b') + '\\s*\\([^\\)]*\\)');
 
-// check valid identifier for v-for
-var identRE = /[A-Za-z_$][\w$]*/;
-
 // strip strings in expressions
 var stripStringRE = /'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"|`(?:[^`\\]|\\.)*\$\{|\}(?:[^`\\]|\\.)*`|`(?:[^`\\]|\\.)*`/g;
 
@@ -5529,9 +5654,18 @@ function checkFor (node, text, errors) {
   checkIdentifier(node.iterator2, 'v-for iterator', text, errors);
 }
 
-function checkIdentifier (ident, type, text, errors) {
-  if (typeof ident === 'string' && !identRE.test(ident)) {
-    errors.push(("invalid " + type + " \"" + ident + "\" in expression: " + (text.trim())));
+function checkIdentifier (
+  ident,
+  type,
+  text,
+  errors
+) {
+  if (typeof ident === 'string') {
+    try {
+      new Function(("var " + ident + "=_"));
+    } catch (e) {
+      errors.push(("invalid " + type + " \"" + ident + "\" in expression: " + (text.trim())));
+    }
   }
 }
 
@@ -5957,6 +6091,43 @@ function renderSSRStyle (
   
 }
 
+/*  */
+
+var seenObjects = new _Set();
+
+/**
+ * Recursively traverse an object to evoke all converted
+ * getters, so that every nested property inside the object
+ * is collected as a "deep" dependency.
+ */
+function traverse (val) {
+  _traverse(val, seenObjects);
+  seenObjects.clear();
+}
+
+function _traverse (val, seen) {
+  var i, keys;
+  var isA = Array.isArray(val);
+  if ((!isA && !isObject(val)) || Object.isFrozen(val)) {
+    return
+  }
+  if (val.__ob__) {
+    var depId = val.__ob__.dep.id;
+    if (seen.has(depId)) {
+      return
+    }
+    seen.add(depId);
+  }
+  if (isA) {
+    i = val.length;
+    while (i--) { _traverse(val[i], seen); }
+  } else {
+    keys = Object.keys(val);
+    i = keys.length;
+    while (i--) { _traverse(val[keys[i]], seen); }
+  }
+}
+
 {
   
 }
@@ -6260,6 +6431,7 @@ function updateComponentListeners (
 ) {
   target = vm;
   updateListeners(listeners, oldListeners || {}, add, remove$1, vm);
+  target = undefined;
 }
 
 /*  */
@@ -6275,7 +6447,6 @@ function resolveSlots (
   if (!children) {
     return slots
   }
-  var defaultSlot = [];
   for (var i = 0, l = children.length; i < l; i++) {
     var child = children[i];
     var data = child.data;
@@ -6285,7 +6456,7 @@ function resolveSlots (
     }
     // named slots should only be respected if the vnode was rendered in the
     // same context.
-    if ((child.context === context || child.functionalContext === context) &&
+    if ((child.context === context || child.fnContext === context) &&
       data && data.slot != null
     ) {
       var name = child.data.slot;
@@ -6296,18 +6467,20 @@ function resolveSlots (
         slot.push(child);
       }
     } else {
-      defaultSlot.push(child);
+      (slots.default || (slots.default = [])).push(child);
     }
   }
-  // ignore whitespace
-  if (!defaultSlot.every(isWhitespace)) {
-    slots.default = defaultSlot;
+  // ignore slots that contains only whitespace
+  for (var name$1 in slots) {
+    if (slots[name$1].every(isWhitespace)) {
+      delete slots[name$1];
+    }
   }
   return slots
 }
 
 function isWhitespace (node) {
-  return node.isComment || node.text === ' '
+  return (node.isComment && !node.asyncFactory) || node.text === ' '
 }
 
 function resolveScopedSlots (
@@ -6611,9 +6784,13 @@ var Watcher = function Watcher (
   vm,
   expOrFn,
   cb,
-  options
+  options,
+  isRenderWatcher
 ) {
   this.vm = vm;
+  if (isRenderWatcher) {
+    vm._watcher = this;
+  }
   vm._watchers.push(this);
   // options
   if (options) {
@@ -6805,40 +6982,6 @@ Watcher.prototype.teardown = function teardown () {
   }
 };
 
-/**
- * Recursively traverse an object to evoke all converted
- * getters, so that every nested property inside the object
- * is collected as a "deep" dependency.
- */
-var seenObjects = new _Set();
-function traverse (val) {
-  seenObjects.clear();
-  _traverse(val, seenObjects);
-}
-
-function _traverse (val, seen) {
-  var i, keys;
-  var isA = Array.isArray(val);
-  if ((!isA && !isObject(val)) || !Object.isExtensible(val)) {
-    return
-  }
-  if (val.__ob__) {
-    var depId = val.__ob__.dep.id;
-    if (seen.has(depId)) {
-      return
-    }
-    seen.add(depId);
-  }
-  if (isA) {
-    i = val.length;
-    while (i--) { _traverse(val[i], seen); }
-  } else {
-    keys = Object.keys(val);
-    i = keys.length;
-    while (i--) { _traverse(val[keys[i]], seen); }
-  }
-}
-
 /*  */
 
 /*  */
@@ -7010,6 +7153,7 @@ function renderSlot (
   bindObject
 ) {
   var scopedSlotFn = this.$scopedSlots[name];
+  var nodes;
   if (scopedSlotFn) { // scoped slot
     props = props || {};
     if (bindObject) {
@@ -7021,19 +7165,28 @@ function renderSlot (
       }
       props = extend(extend({}, bindObject), props);
     }
-    return scopedSlotFn(props) || fallback
+    nodes = scopedSlotFn(props) || fallback;
   } else {
     var slotNodes = this.$slots[name];
     // warn duplicate slot usage
-    if (slotNodes && "development" !== 'production') {
-      slotNodes._rendered && warn(
-        "Duplicate presence of slot \"" + name + "\" found in the same render tree " +
-        "- this will likely cause render errors.",
-        this
-      );
+    if (slotNodes) {
+      if ("development" !== 'production' && slotNodes._rendered) {
+        warn(
+          "Duplicate presence of slot \"" + name + "\" found in the same render tree " +
+          "- this will likely cause render errors.",
+          this
+        );
+      }
       slotNodes._rendered = true;
     }
-    return slotNodes || fallback
+    nodes = slotNodes || fallback;
+  }
+
+  var target = props && props.slot;
+  if (target) {
+    return this.$createElement('template', { slot: target }, nodes)
+  } else {
+    return nodes
   }
 }
 
@@ -7132,12 +7285,19 @@ function bindObjectProps (
  */
 function renderStatic (
   index,
-  isInFor
+  isInFor,
+  isOnce
 ) {
-  // static trees can be rendered once and cached on the contructor options
-  // so every instance shares the same cached trees
+  // render fns generated by compiler < 2.5.4 does not provide v-once
+  // information to runtime so be conservative
+  var isOldVersion = arguments.length < 3;
+  // if a static tree is generated by v-once, it is cached on the instance;
+  // otherwise it is purely static and can be cached on the shared options
+  // across all instances.
   var renderFns = this.$options.staticRenderFns;
-  var cached = renderFns.cached || (renderFns.cached = []);
+  var cached = isOldVersion || isOnce
+    ? (this._staticTrees || (this._staticTrees = []))
+    : (renderFns.cached || (renderFns.cached = []));
   var tree = cached[index];
   // if has already-rendered static tree and not inside v-for,
   // we can reuse the same tree by doing a shallow clone.
@@ -7371,8 +7531,8 @@ function FunctionalRenderContext (
     this._c = function (a, b, c, d) {
       var vnode = createElement(contextVm, a, b, c, d, needNormalization);
       if (vnode) {
-        vnode.functionalScopeId = options._scopeId;
-        vnode.functionalContext = parent;
+        vnode.fnScopeId = options._scopeId;
+        vnode.fnContext = parent;
       }
       return vnode
     };
@@ -7413,8 +7573,8 @@ function createFunctionalComponent (
   var vnode = options.render.call(null, renderContext._c, renderContext);
 
   if (vnode instanceof VNode) {
-    vnode.functionalContext = contextVm;
-    vnode.functionalOptions = options;
+    vnode.fnContext = contextVm;
+    vnode.fnOptions = options;
     if (data.slot) {
       (vnode.data || (vnode.data = {})).slot = data.slot;
     }
@@ -7905,8 +8065,8 @@ function renderElement (el, isRoot, context) {
     el.data.attrs[SSR_ATTR] = 'true';
   }
 
-  if (el.functionalOptions) {
-    registerComponentForCache(el.functionalOptions, write);
+  if (el.fnOptions) {
+    registerComponentForCache(el.fnOptions, write);
   }
 
   var startTag = renderStartingTag(el, context);
diff --git a/packages/vue-server-renderer/build.js b/packages/vue-server-renderer/build.js
index c1e672a..60cc160 100644
--- a/packages/vue-server-renderer/build.js
+++ b/packages/vue-server-renderer/build.js
@@ -8,6 +8,8 @@ var he = _interopDefault(require('he'));
 
 /*  */
 
+var emptyObject = Object.freeze({});
+
 // these helpers produces better vm code in JS engines due to their
 // explicitness and function inlining
 function isUndef (v) {
@@ -440,9 +442,9 @@ var VNode = function VNode (
   this.elm = elm;
   this.ns = undefined;
   this.context = context;
-  this.functionalContext = undefined;
-  this.functionalOptions = undefined;
-  this.functionalScopeId = undefined;
+  this.fnContext = undefined;
+  this.fnOptions = undefined;
+  this.fnScopeId = undefined;
   this.key = data && data.key;
   this.componentOptions = componentOptions;
   this.componentInstance = undefined;
@@ -486,6 +488,7 @@ function createTextVNode (val) {
 // multiple renders, cloning them avoids errors when DOM manipulations rely
 // on their elm reference.
 function cloneVNode (vnode, deep) {
+  var componentOptions = vnode.componentOptions;
   var cloned = new VNode(
     vnode.tag,
     vnode.data,
@@ -493,16 +496,24 @@ function cloneVNode (vnode, deep) {
     vnode.text,
     vnode.elm,
     vnode.context,
-    vnode.componentOptions,
+    componentOptions,
     vnode.asyncFactory
   );
   cloned.ns = vnode.ns;
   cloned.isStatic = vnode.isStatic;
   cloned.key = vnode.key;
   cloned.isComment = vnode.isComment;
+  cloned.fnContext = vnode.fnContext;
+  cloned.fnOptions = vnode.fnOptions;
+  cloned.fnScopeId = vnode.fnScopeId;
   cloned.isCloned = true;
-  if (deep && vnode.children) {
-    cloned.children = cloneVNodes(vnode.children);
+  if (deep) {
+    if (vnode.children) {
+      cloned.children = cloneVNodes(vnode.children, true);
+    }
+    if (componentOptions && componentOptions.children) {
+      componentOptions.children = cloneVNodes(componentOptions.children, true);
+    }
   }
   return cloned
 }
@@ -540,7 +551,10 @@ function renderDOMProps (node) {
       setText(node, props[key], true);
     } else if (key === 'textContent') {
       setText(node, props[key], false);
+    } else if (key === 'value' && node.tag === 'textarea') {
+      setText(node, props[key], false);
     } else {
+      // $flow-disable-line (WTF?)
       var attr = propsToAttrMap[key] || key.toLowerCase();
       if (isRenderableAttr(attr) &&
         // avoid rendering double-bound props/attrs twice
@@ -561,8 +575,6 @@ function setText (node, text, raw) {
 
 /*  */
 
-var emptyObject = Object.freeze({});
-
 /**
  * Check if a string starts with $ or _
  */
@@ -600,17 +612,20 @@ function parsePath (path) {
 
 /*  */
 
+
 // can we use __proto__?
 var hasProto = '__proto__' in {};
 
 // Browser environment sniffing
 var inBrowser = typeof window !== 'undefined';
+var inWeex = typeof WXEnvironment !== 'undefined' && !!WXEnvironment.platform;
+var weexPlatform = inWeex && WXEnvironment.platform.toLowerCase();
 var UA = inBrowser && window.navigator.userAgent.toLowerCase();
 var isIE = UA && /msie|trident/.test(UA);
 var isIE9 = UA && UA.indexOf('msie 9.0') > 0;
 var isEdge = UA && UA.indexOf('edge/') > 0;
-var isAndroid = UA && UA.indexOf('android') > 0;
-var isIOS = UA && /iphone|ipad|ipod|ios/.test(UA);
+var isAndroid = (UA && UA.indexOf('android') > 0) || (weexPlatform === 'android');
+var isIOS = (UA && /iphone|ipad|ipod|ios/.test(UA)) || (weexPlatform === 'ios');
 var isChrome = UA && /chrome\/\d+/.test(UA) && !isEdge;
 
 // Firefox has a "watch" function on Object.prototype...
@@ -1158,7 +1173,7 @@ function set (target, key, val) {
     target.splice(key, 1, val);
     return val
   }
-  if (hasOwn(target, key)) {
+  if (key in target && !(key in Object.prototype)) {
     target[key] = val;
     return val
   }
@@ -1269,7 +1284,7 @@ function mergeDataOrFn (
         typeof parentVal === 'function' ? parentVal.call(this) : parentVal
       )
     }
-  } else if (parentVal || childVal) {
+  } else {
     return function mergedInstanceDataFn () {
       // instance merge
       var instanceData = typeof childVal === 'function'
@@ -1303,7 +1318,7 @@ strats.data = function (
 
       return parentVal
     }
-    return mergeDataOrFn.call(this, parentVal, childVal)
+    return mergeDataOrFn(parentVal, childVal)
   }
 
   return mergeDataOrFn(parentVal, childVal, vm)
@@ -1813,7 +1828,7 @@ function logError (err, vm, info) {
     warn(("Error in " + info + ": \"" + (err.toString()) + "\""), vm);
   }
   /* istanbul ignore else */
-  if (inBrowser && typeof console !== 'undefined') {
+  if ((inBrowser || inWeex) && typeof console !== 'undefined') {
     console.error(err);
   } else {
     throw err
@@ -2181,8 +2196,52 @@ function show (node, dir) {
   }
 }
 
+/*  */
+
+// this is only applied for <select v-model> because it is the only edge case
+// that must be done at runtime instead of compile time.
+function model (node, dir) {
+  if (!node.children) { return }
+  var value = dir.value;
+  var isMultiple = node.data.attrs && node.data.attrs.multiple;
+  for (var i = 0, l = node.children.length; i < l; i++) {
+    var option = node.children[i];
+    if (option.tag === 'option') {
+      if (isMultiple) {
+        var selected =
+          Array.isArray(value) &&
+          (looseIndexOf(value, getValue(option)) > -1);
+        if (selected) {
+          setSelected(option);
+        }
+      } else {
+        if (looseEqual(value, getValue(option))) {
+          setSelected(option);
+          return
+        }
+      }
+    }
+  }
+}
+
+function getValue (option) {
+  var data = option.data || {};
+  return (
+    (data.attrs && data.attrs.value) ||
+    (data.domProps && data.domProps.value) ||
+    (option.children && option.children[0] && option.children[0].text)
+  )
+}
+
+function setSelected (option) {
+  var data = option.data || (option.data = {});
+  var attrs = data.attrs || (data.attrs = {});
+  attrs.selected = '';
+}
+
 var baseDirectives = {
-  show: show
+  show: show,
+  model: model
 };
 
 /*  */
@@ -2618,39 +2677,59 @@ function addHandler (
   important,
   warn
 ) {
+  modifiers = modifiers || emptyObject;
   // warn prevent and passive modifier
   /* istanbul ignore if */
   if (
     process.env.NODE_ENV !== 'production' && warn &&
-    modifiers && modifiers.prevent && modifiers.passive
+    modifiers.prevent && modifiers.passive
   ) {
     warn(
       'passive and prevent can\'t be used together. ' +
       'Passive handler can\'t prevent default event.'
     );
   }
+
   // check capture modifier
-  if (modifiers && modifiers.capture) {
+  if (modifiers.capture) {
     delete modifiers.capture;
     name = '!' + name; // mark the event as captured
   }
-  if (modifiers && modifiers.once) {
+  if (modifiers.once) {
     delete modifiers.once;
     name = '~' + name; // mark the event as once
   }
   /* istanbul ignore if */
-  if (modifiers && modifiers.passive) {
+  if (modifiers.passive) {
     delete modifiers.passive;
     name = '&' + name; // mark the event as passive
   }
+
+  // normalize click.right and click.middle since they don't actually fire
+  // this is technically browser-specific, but at least for now browsers are
+  // the only target envs that have right/middle clicks.
+  if (name === 'click') {
+    if (modifiers.right) {
+      name = 'contextmenu';
+      delete modifiers.right;
+    } else if (modifiers.middle) {
+      name = 'mouseup';
+    }
+  }
+
   var events;
-  if (modifiers && modifiers.native) {
+  if (modifiers.native) {
     delete modifiers.native;
     events = el.nativeEvents || (el.nativeEvents = {});
   } else {
     events = el.events || (el.events = {});
   }
-  var newHandler = { value: value, modifiers: modifiers };
+
+  var newHandler = { value: value };
+  if (modifiers !== emptyObject) {
+    newHandler.modifiers = modifiers;
+  }
+
   var handlers = events[name];
   /* istanbul ignore if */
   if (Array.isArray(handlers)) {
@@ -2829,10 +2908,11 @@ var decodingMap = {
   '>': '>',
   '"': '"',
   '&': '&',
-  '
': '\n'
+  '
': '\n',
+  '	': '\t'
 };
 var encodedAttr = /&(?:lt|gt|quot|amp);/g;
-var encodedAttrWithNewLines = /&(?:lt|gt|quot|amp|#10);/g;
+var encodedAttrWithNewLines = /&(?:lt|gt|quot|amp|#10|#9);/g;
 
 // #5992
 var isIgnoreNewlineTag = makeMap('pre,textarea', true);
@@ -3023,12 +3103,12 @@ function parseHTML (html, options) {
         if (args[5] === '') { delete args[5]; }
       }
       var value = args[3] || args[4] || args[5] || '';
+      var shouldDecodeNewlines = tagName === 'a' && args[1] === 'href'
+        ? options.shouldDecodeNewlinesForHref
+        : options.shouldDecodeNewlines;
       attrs[i] = {
         name: args[1],
-        value: decodeAttr(
-          value,
-          options.shouldDecodeNewlines
-        )
+        value: decodeAttr(value, shouldDecodeNewlines)
       };
     }
 
@@ -3252,7 +3332,8 @@ function parseString (chr) {
 var onRE = /^@|^v-on:/;
 var dirRE = /^v-|^@|^:/;
 var forAliasRE = /(.*?)\s+(?:in|of)\s+(.*)/;
-var forIteratorRE = /\((\{[^}]*\}|[^,]*),([^,]*)(?:,([^,]*))?\)/;
+var forIteratorRE = /\((\{[^}]*\}|[^,{]*),([^,]*)(?:,([^,]*))?\)/;
+var stripParensRE = /^\(|\)$/g;
 
 var argRE = /:(.*)$/;
 var bindRE = /^:|^v-bind:/;
@@ -3337,6 +3418,7 @@ function parse (
     isUnaryTag: options.isUnaryTag,
     canBeLeftOpenTag: options.canBeLeftOpenTag,
     shouldDecodeNewlines: options.shouldDecodeNewlines,
+    shouldDecodeNewlinesForHref: options.shouldDecodeNewlinesForHref,
     shouldKeepComment: options.comments,
     start: function start (tag, attrs, unary) {
       // check namespace.
@@ -3592,7 +3674,7 @@ function processFor (el) {
         el.iterator2 = iteratorMatch[3].trim();
       }
     } else {
-      el.alias = alias;
+      el.alias = alias.replace(stripParensRE, '');
     }
   }
 }
@@ -3688,6 +3770,15 @@ function processSlot (el) {
       }
       el.slotScope = slotScope || getAndRemoveAttr(el, 'slot-scope');
     } else if ((slotScope = getAndRemoveAttr(el, 'slot-scope'))) {
+      /* istanbul ignore if */
+      if (process.env.NODE_ENV !== 'production' && el.attrsMap['v-for']) {
+        warn$1(
+          "Ambiguous combined usage of slot-scope and v-for on <" + (el.tag) + "> " +
+          "(v-for takes higher priority). Use a wrapper <template> for the " +
+          "scoped slot to make it clearer.",
+          true
+        );
+      }
       el.slotScope = slotScope;
     }
     var slotTarget = getBindingAttr(el, 'slot');
@@ -3695,7 +3786,7 @@ function processSlot (el) {
       el.slotTarget = slotTarget === '""' ? '"default"' : slotTarget;
       // preserve slot as an attribute for native shadow DOM compat
       // only for non-scoped slots.
-      if (!el.slotScope) {
+      if (el.tag !== 'template' && !el.slotScope) {
         addAttr(el, 'slot', slotTarget);
       }
     }
@@ -3784,6 +3875,13 @@ function processAttrs (el) {
         }
       }
       addAttr(el, name, JSON.stringify(value));
+      // #6887 firefox doesn't update muted state if set via attribute
+      // even immediately after element creation
+      if (!el.component &&
+          name === 'muted' &&
+          platformMustUseProp(el.tag, el.attrsMap.type, name)) {
+        addProp(el, name, 'true');
+      }
     }
   }
 }
@@ -3888,6 +3986,8 @@ function preTransformNode (el, options) {
       var typeBinding = getBindingAttr(el, 'type');
       var ifCondition = getAndRemoveAttr(el, 'v-if', true);
       var ifConditionExtra = ifCondition ? ("&&(" + ifCondition + ")") : "";
+      var hasElse = getAndRemoveAttr(el, 'v-else', true) != null;
+      var elseIfCondition = getAndRemoveAttr(el, 'v-else-if', true);
       // 1. checkbox
       var branch0 = cloneASTElement(el);
       // process for on the main node
@@ -3918,6 +4018,13 @@ function preTransformNode (el, options) {
         exp: ifCondition,
         block: branch2
       });
+
+      if (hasElse) {
+        branch0.else = true;
+      } else if (elseIfCondition) {
+        branch0.elseif = elseIfCondition;
+      }
+
       return branch0
     }
   }
@@ -3932,14 +4039,14 @@ function addRawAttr (el, name, value) {
   el.attrsList.push({ name: name, value: value });
 }
 
-var model = {
+var model$1 = {
   preTransformNode: preTransformNode
 };
 
 var modules$1 = [
   klass,
   style,
-  model
+  model$1
 ];
 
 /*  */
@@ -3951,7 +4058,7 @@ var warn$2;
 var RANGE_TOKEN = '__r';
 
 
-function model$1 (
+function model$2 (
   el,
   dir,
   _warn
@@ -4068,6 +4175,19 @@ function genDefaultModel (
   modifiers
 ) {
   var type = el.attrsMap.type;
+
+  // warn if v-bind:value conflicts with v-model
+  if (process.env.NODE_ENV !== 'production') {
+    var value$1 = el.attrsMap['v-bind:value'] || el.attrsMap[':value'];
+    if (value$1) {
+      var binding = el.attrsMap['v-bind:value'] ? 'v-bind:value' : ':value';
+      warn$2(
+        binding + "=\"" + value$1 + "\" conflicts with v-model on the same element " +
+        'because the latter already expands to a value binding internally'
+      );
+    }
+  }
+
   var ref = modifiers || {};
   var lazy = ref.lazy;
   var number = ref.number;
@@ -4116,7 +4236,7 @@ function html (el, dir) {
 }
 
 var directives = {
-  model: model$1,
+  model: model$2,
   text: text,
   html: html
 };
@@ -4179,18 +4299,7 @@ function genHandlers (
 ) {
   var res = isNative ? 'nativeOn:{' : 'on:{';
   for (var name in events) {
-    var handler = events[name];
-    // #5330: warn click.right, since right clicks do not actually fire click events.
-    if (process.env.NODE_ENV !== 'production' &&
-      name === 'click' &&
-      handler && handler.modifiers && handler.modifiers.right
-    ) {
-      warn(
-        "Use \"contextmenu\" instead of \"click.right\" since right clicks " +
-        "do not actually fire \"click\" events."
-      );
-    }
-    res += "\"" + name + "\":" + (genHandler(name, handler)) + ",";
+    res += "\"" + name + "\":" + (genHandler(name, events[name])) + ",";
   }
   return res.slice(0, -1) + '}'
 }
@@ -4357,10 +4466,10 @@ function genElement (el, state) {
 }
 
 // hoist static sub-trees out
-function genStatic (el, state) {
+function genStatic (el, state, once$$1) {
   el.staticProcessed = true;
   state.staticRenderFns.push(("with(this){return " + (genElement(el, state)) + "}"));
-  return ("_m(" + (state.staticRenderFns.length - 1) + (el.staticInFor ? ',true' : '') + ")")
+  return ("_m(" + (state.staticRenderFns.length - 1) + "," + (el.staticInFor ? 'true' : 'false') + "," + (once$$1 ? 'true' : 'false') + ")")
 }
 
 // v-once
@@ -4386,7 +4495,7 @@ function genOnce (el, state) {
     }
     return ("_o(" + (genElement(el, state)) + "," + (state.onceId++) + "," + key + ")")
   } else {
-    return genStatic(el, state)
+    return genStatic(el, state, true)
   }
 }
 
@@ -4750,6 +4859,10 @@ function applyModelTransform (el, state) {
       var dir = el.directives[i];
       if (dir.name === 'model') {
         state.directives.model(el, dir, state.warn);
+        // remove value for textarea as its converted to text
+        if (el.tag === 'textarea' && el.props) {
+          el.props = el.props.filter(function (p) { return p.name !== 'value'; });
+        }
         break
       }
     }
@@ -4897,7 +5010,7 @@ function walk (node, isRoot) {
     if (node.ifConditions) {
       for (var i$1 = 1, l$1 = node.ifConditions.length; i$1 < l$1; i$1++) {
         var block = node.ifConditions[i$1].block;
-        walk(block);
+        walk(block, isRoot);
         check(block);
       }
     }
@@ -4955,7 +5068,8 @@ function isUnOptimizableTree (node) {
   return (
     isBuiltInTag(node.tag) || // built-in (slot, component)
     !isPlatformReservedTag(node.tag) || // custom component
-    !!node.component // "is" component
+    !!node.component || // "is" component
+    isSelectWithModel(node) // <select v-model> requires runtime inspection
   )
 }
 
@@ -4969,6 +5083,17 @@ function hasCustomDirective (node) {
   )
 }
 
+// <select v-model> cannot be optimized because it requires a runtime check
+// to determine proper selected option
+function isSelectWithModel (node) {
+  return (
+    node.type === 1 &&
+    node.tag === 'select' &&
+    node.directives != null &&
+    node.directives.some(function (d) { return d.name === 'model'; })
+  )
+}
+
 /*  */
 
 // The SSR codegen is essentially extending the default codegen to handle
@@ -5142,6 +5267,9 @@ function childrenToSegments (el, state) {
   if ((binding = el.attrsMap['v-text'])) {
     return [{ type: INTERPOLATION, value: ("_s(" + binding + ")") }]
   }
+  if (el.tag === 'textarea' && (binding = el.attrsMap['v-model'])) {
+    return [{ type: INTERPOLATION, value: ("_s(" + binding + ")") }]
+  }
   return el.children
     ? nodesToSegments(el.children, state)
     : []
@@ -5208,9 +5336,6 @@ var unaryOperatorsRE = new RegExp('\\b' + (
   'delete,typeof,void'
 ).split(',').join('\\s*\\([^\\)]*\\)|\\b') + '\\s*\\([^\\)]*\\)');
 
-// check valid identifier for v-for
-var identRE = /[A-Za-z_$][\w$]*/;
-
 // strip strings in expressions
 var stripStringRE = /'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"|`(?:[^`\\]|\\.)*\$\{|\}(?:[^`\\]|\\.)*`|`(?:[^`\\]|\\.)*`/g;
 
@@ -5268,9 +5393,18 @@ function checkFor (node, text, errors) {
   checkIdentifier(node.iterator2, 'v-for iterator', text, errors);
 }
 
-function checkIdentifier (ident, type, text, errors) {
-  if (typeof ident === 'string' && !identRE.test(ident)) {
-    errors.push(("invalid " + type + " \"" + ident + "\" in expression: " + (text.trim())));
+function checkIdentifier (
+  ident,
+  type,
+  text,
+  errors
+) {
+  if (typeof ident === 'string') {
+    try {
+      new Function(("var " + ident + "=_"));
+    } catch (e) {
+      errors.push(("invalid " + type + " \"" + ident + "\" in expression: " + (text.trim())));
+    }
   }
 }
 
@@ -5698,6 +5832,43 @@ if (process.env.NODE_ENV !== 'production') {
 
 /*  */
 
+var seenObjects = new _Set();
+
+/**
+ * Recursively traverse an object to evoke all converted
+ * getters, so that every nested property inside the object
+ * is collected as a "deep" dependency.
+ */
+function traverse (val) {
+  _traverse(val, seenObjects);
+  seenObjects.clear();
+}
+
+function _traverse (val, seen) {
+  var i, keys;
+  var isA = Array.isArray(val);
+  if ((!isA && !isObject(val)) || Object.isFrozen(val)) {
+    return
+  }
+  if (val.__ob__) {
+    var depId = val.__ob__.dep.id;
+    if (seen.has(depId)) {
+      return
+    }
+    seen.add(depId);
+  }
+  if (isA) {
+    i = val.length;
+    while (i--) { _traverse(val[i], seen); }
+  } else {
+    keys = Object.keys(val);
+    i = keys.length;
+    while (i--) { _traverse(val[keys[i]], seen); }
+  }
+}
+
+/*  */
+
 var normalizeEvent = cached(function (name) {
   var passive = name.charAt(0) === '&';
   name = passive ? name.slice(1) : name;
@@ -5997,6 +6168,7 @@ function updateComponentListeners (
 ) {
   target = vm;
   updateListeners(listeners, oldListeners || {}, add, remove$1, vm);
+  target = undefined;
 }
 
 /*  */
@@ -6012,7 +6184,6 @@ function resolveSlots (
   if (!children) {
     return slots
   }
-  var defaultSlot = [];
   for (var i = 0, l = children.length; i < l; i++) {
     var child = children[i];
     var data = child.data;
@@ -6022,7 +6193,7 @@ function resolveSlots (
     }
     // named slots should only be respected if the vnode was rendered in the
     // same context.
-    if ((child.context === context || child.functionalContext === context) &&
+    if ((child.context === context || child.fnContext === context) &&
       data && data.slot != null
     ) {
       var name = child.data.slot;
@@ -6033,18 +6204,20 @@ function resolveSlots (
         slot.push(child);
       }
     } else {
-      defaultSlot.push(child);
+      (slots.default || (slots.default = [])).push(child);
     }
   }
-  // ignore whitespace
-  if (!defaultSlot.every(isWhitespace)) {
-    slots.default = defaultSlot;
+  // ignore slots that contains only whitespace
+  for (var name$1 in slots) {
+    if (slots[name$1].every(isWhitespace)) {
+      delete slots[name$1];
+    }
   }
   return slots
 }
 
 function isWhitespace (node) {
-  return node.isComment || node.text === ' '
+  return (node.isComment && !node.asyncFactory) || node.text === ' '
 }
 
 function resolveScopedSlots (
@@ -6340,9 +6513,13 @@ var Watcher = function Watcher (
   vm,
   expOrFn,
   cb,
-  options
+  options,
+  isRenderWatcher
 ) {
   this.vm = vm;
+  if (isRenderWatcher) {
+    vm._watcher = this;
+  }
   vm._watchers.push(this);
   // options
   if (options) {
@@ -6536,40 +6713,6 @@ Watcher.prototype.teardown = function teardown () {
   }
 };
 
-/**
- * Recursively traverse an object to evoke all converted
- * getters, so that every nested property inside the object
- * is collected as a "deep" dependency.
- */
-var seenObjects = new _Set();
-function traverse (val) {
-  seenObjects.clear();
-  _traverse(val, seenObjects);
-}
-
-function _traverse (val, seen) {
-  var i, keys;
-  var isA = Array.isArray(val);
-  if ((!isA && !isObject(val)) || !Object.isExtensible(val)) {
-    return
-  }
-  if (val.__ob__) {
-    var depId = val.__ob__.dep.id;
-    if (seen.has(depId)) {
-      return
-    }
-    seen.add(depId);
-  }
-  if (isA) {
-    i = val.length;
-    while (i--) { _traverse(val[i], seen); }
-  } else {
-    keys = Object.keys(val);
-    i = keys.length;
-    while (i--) { _traverse(val[keys[i]], seen); }
-  }
-}
-
 /*  */
 
 /*  */
@@ -6741,6 +6884,7 @@ function renderSlot (
   bindObject
 ) {
   var scopedSlotFn = this.$scopedSlots[name];
+  var nodes;
   if (scopedSlotFn) { // scoped slot
     props = props || {};
     if (bindObject) {
@@ -6752,19 +6896,28 @@ function renderSlot (
       }
       props = extend(extend({}, bindObject), props);
     }
-    return scopedSlotFn(props) || fallback
+    nodes = scopedSlotFn(props) || fallback;
   } else {
     var slotNodes = this.$slots[name];
     // warn duplicate slot usage
-    if (slotNodes && process.env.NODE_ENV !== 'production') {
-      slotNodes._rendered && warn(
-        "Duplicate presence of slot \"" + name + "\" found in the same render tree " +
-        "- this will likely cause render errors.",
-        this
-      );
+    if (slotNodes) {
+      if (process.env.NODE_ENV !== 'production' && slotNodes._rendered) {
+        warn(
+          "Duplicate presence of slot \"" + name + "\" found in the same render tree " +
+          "- this will likely cause render errors.",
+          this
+        );
+      }
       slotNodes._rendered = true;
     }
-    return slotNodes || fallback
+    nodes = slotNodes || fallback;
+  }
+
+  var target = props && props.slot;
+  if (target) {
+    return this.$createElement('template', { slot: target }, nodes)
+  } else {
+    return nodes
   }
 }
 
@@ -6863,12 +7016,19 @@ function bindObjectProps (
  */
 function renderStatic (
   index,
-  isInFor
+  isInFor,
+  isOnce
 ) {
-  // static trees can be rendered once and cached on the contructor options
-  // so every instance shares the same cached trees
+  // render fns generated by compiler < 2.5.4 does not provide v-once
+  // information to runtime so be conservative
+  var isOldVersion = arguments.length < 3;
+  // if a static tree is generated by v-once, it is cached on the instance;
+  // otherwise it is purely static and can be cached on the shared options
+  // across all instances.
   var renderFns = this.$options.staticRenderFns;
-  var cached = renderFns.cached || (renderFns.cached = []);
+  var cached = isOldVersion || isOnce
+    ? (this._staticTrees || (this._staticTrees = []))
+    : (renderFns.cached || (renderFns.cached = []));
   var tree = cached[index];
   // if has already-rendered static tree and not inside v-for,
   // we can reuse the same tree by doing a shallow clone.
@@ -7102,8 +7262,8 @@ function FunctionalRenderContext (
     this._c = function (a, b, c, d) {
       var vnode = createElement(contextVm, a, b, c, d, needNormalization);
       if (vnode) {
-        vnode.functionalScopeId = options._scopeId;
-        vnode.functionalContext = parent;
+        vnode.fnScopeId = options._scopeId;
+        vnode.fnContext = parent;
       }
       return vnode
     };
@@ -7144,8 +7304,8 @@ function createFunctionalComponent (
   var vnode = options.render.call(null, renderContext._c, renderContext);
 
   if (vnode instanceof VNode) {
-    vnode.functionalContext = contextVm;
-    vnode.functionalOptions = options;
+    vnode.fnContext = contextVm;
+    vnode.fnOptions = options;
     if (data.slot) {
       (vnode.data || (vnode.data = {})).slot = data.slot;
     }
@@ -7636,8 +7796,8 @@ function renderElement (el, isRoot, context) {
     el.data.attrs[SSR_ATTR] = 'true';
   }
 
-  if (el.functionalOptions) {
-    registerComponentForCache(el.functionalOptions, write);
+  if (el.fnOptions) {
+    registerComponentForCache(el.fnOptions, write);
   }
 
   var startTag = renderStartingTag(el, context);
@@ -8329,7 +8489,7 @@ function compileModule (files, basedir, runInNewContext) {
       : script.runInNewContext(sandbox);
     var m = { exports: {}};
     var r = function (file) {
-      file = path$2.join('.', file);
+      file = path$2.posix.join('.', file);
       if (files[file]) {
         return evaluateModule(file, sandbox, evaluatedFiles)
       } else if (basedir) {
diff --git a/packages/vue-server-renderer/package.json b/packages/vue-server-renderer/package.json
index b22297f..00e6f8c 100644
--- a/packages/vue-server-renderer/package.json
+++ b/packages/vue-server-renderer/package.json
@@ -1,6 +1,6 @@
 {
   "name": "vue-server-renderer",
-  "version": "2.5.2",
+  "version": "2.5.9",
   "description": "server renderer for Vue 2.0",
   "main": "index.js",
   "types": "types/index.d.ts",
diff --git a/packages/vue-server-renderer/types/index.d.ts b/packages/vue-server-renderer/types/index.d.ts
index e6c8d62..1c7e8bd 100644
--- a/packages/vue-server-renderer/types/index.d.ts
+++ b/packages/vue-server-renderer/types/index.d.ts
@@ -11,6 +11,7 @@ interface Renderer {
   renderToString(vm: Vue, callback: RenderCallback): void;
   renderToString(vm: Vue, context: object, callback: RenderCallback): void;
   renderToString(vm: Vue): Promise<string>;
+  renderToString(vm: Vue, context: object): Promise<string>;
 
   renderToStream(vm: Vue, context?: object): Readable;
 }
@@ -18,6 +19,8 @@ interface Renderer {
 interface BundleRenderer {
   renderToString(callback: RenderCallback): void;
   renderToString(context: object, callback: RenderCallback): void;
+  renderToString(): Promise<string>;
+  renderToString(context: object): Promise<string>;
 
   renderToStream(context?: object): Readable;
 }
diff --git a/packages/vue-template-compiler/browser.js b/packages/vue-template-compiler/browser.js
index 7b3a8f2..049f66d 100644
--- a/packages/vue-template-compiler/browser.js
+++ b/packages/vue-template-compiler/browser.js
@@ -52,6 +52,8 @@ function count (line, type) {
 
 /*  */
 
+var emptyObject = Object.freeze({});
+
 // these helpers produces better vm code in JS engines due to their
 // explicitness and function inlining
 
@@ -320,10 +322,11 @@ var decodingMap = {
   '>': '>',
   '"': '"',
   '&': '&',
-  '
': '\n'
+  '
': '\n',
+  '	': '\t'
 };
 var encodedAttr = /&(?:lt|gt|quot|amp);/g;
-var encodedAttrWithNewLines = /&(?:lt|gt|quot|amp|#10);/g;
+var encodedAttrWithNewLines = /&(?:lt|gt|quot|amp|#10|#9);/g;
 
 // #5992
 var isIgnoreNewlineTag = makeMap('pre,textarea', true);
@@ -514,12 +517,12 @@ function parseHTML (html, options) {
         if (args[5] === '') { delete args[5]; }
       }
       var value = args[3] || args[4] || args[5] || '';
+      var shouldDecodeNewlines = tagName === 'a' && args[1] === 'href'
+        ? options.shouldDecodeNewlinesForHref
+        : options.shouldDecodeNewlines;
       attrs[i] = {
         name: args[1],
-        value: decodeAttr(
-          value,
-          options.shouldDecodeNewlines
-        )
+        value: decodeAttr(value, shouldDecodeNewlines)
       };
     }
 
@@ -705,8 +708,6 @@ function parseComponent (
 
 /*  */
 
-var emptyObject = Object.freeze({});
-
 /**
  * Check if a string starts with $ or _
  */
@@ -726,17 +727,20 @@ function def (obj, key, val, enumerable) {
 
 /*  */
 
+
 // can we use __proto__?
 var hasProto = '__proto__' in {};
 
 // Browser environment sniffing
 var inBrowser = typeof window !== 'undefined';
+var inWeex = typeof WXEnvironment !== 'undefined' && !!WXEnvironment.platform;
+var weexPlatform = inWeex && WXEnvironment.platform.toLowerCase();
 var UA = inBrowser && window.navigator.userAgent.toLowerCase();
 var isIE = UA && /msie|trident/.test(UA);
 var isIE9 = UA && UA.indexOf('msie 9.0') > 0;
 var isEdge = UA && UA.indexOf('edge/') > 0;
-var isAndroid = UA && UA.indexOf('android') > 0;
-var isIOS = UA && /iphone|ipad|ipod|ios/.test(UA);
+var isAndroid = (UA && UA.indexOf('android') > 0) || (weexPlatform === 'android');
+var isIOS = (UA && /iphone|ipad|ipod|ios/.test(UA)) || (weexPlatform === 'ios');
 var isChrome = UA && /chrome\/\d+/.test(UA) && !isEdge;
 
 // Firefox has a "watch" function on Object.prototype...
@@ -1072,9 +1076,9 @@ var VNode = function VNode (
   this.elm = elm;
   this.ns = undefined;
   this.context = context;
-  this.functionalContext = undefined;
-  this.functionalOptions = undefined;
-  this.functionalScopeId = undefined;
+  this.fnContext = undefined;
+  this.fnOptions = undefined;
+  this.fnScopeId = undefined;
   this.key = data && data.key;
   this.componentOptions = componentOptions;
   this.componentInstance = undefined;
@@ -1328,7 +1332,7 @@ function set (target, key, val) {
     target.splice(key, 1, val);
     return val
   }
-  if (hasOwn(target, key)) {
+  if (key in target && !(key in Object.prototype)) {
     target[key] = val;
     return val
   }
@@ -1439,7 +1443,7 @@ function mergeDataOrFn (
         typeof parentVal === 'function' ? parentVal.call(this) : parentVal
       )
     }
-  } else if (parentVal || childVal) {
+  } else {
     return function mergedInstanceDataFn () {
       // instance merge
       var instanceData = typeof childVal === 'function'
@@ -1473,7 +1477,7 @@ strats.data = function (
 
       return parentVal
     }
-    return mergeDataOrFn.call(this, parentVal, childVal)
+    return mergeDataOrFn(parentVal, childVal)
   }
 
   return mergeDataOrFn(parentVal, childVal, vm)
@@ -1930,39 +1934,59 @@ function addHandler (
   important,
   warn
 ) {
+  modifiers = modifiers || emptyObject;
   // warn prevent and passive modifier
   /* istanbul ignore if */
   if (
     "development" !== 'production' && warn &&
-    modifiers && modifiers.prevent && modifiers.passive
+    modifiers.prevent && modifiers.passive
   ) {
     warn(
       'passive and prevent can\'t be used together. ' +
       'Passive handler can\'t prevent default event.'
     );
   }
+
   // check capture modifier
-  if (modifiers && modifiers.capture) {
+  if (modifiers.capture) {
     delete modifiers.capture;
     name = '!' + name; // mark the event as captured
   }
-  if (modifiers && modifiers.once) {
+  if (modifiers.once) {
     delete modifiers.once;
     name = '~' + name; // mark the event as once
   }
   /* istanbul ignore if */
-  if (modifiers && modifiers.passive) {
+  if (modifiers.passive) {
     delete modifiers.passive;
     name = '&' + name; // mark the event as passive
   }
+
+  // normalize click.right and click.middle since they don't actually fire
+  // this is technically browser-specific, but at least for now browsers are
+  // the only target envs that have right/middle clicks.
+  if (name === 'click') {
+    if (modifiers.right) {
+      name = 'contextmenu';
+      delete modifiers.right;
+    } else if (modifiers.middle) {
+      name = 'mouseup';
+    }
+  }
+
   var events;
-  if (modifiers && modifiers.native) {
+  if (modifiers.native) {
     delete modifiers.native;
     events = el.nativeEvents || (el.nativeEvents = {});
   } else {
     events = el.events || (el.events = {});
   }
-  var newHandler = { value: value, modifiers: modifiers };
+
+  var newHandler = { value: value };
+  if (modifiers !== emptyObject) {
+    newHandler.modifiers = modifiers;
+  }
+
   var handlers = events[name];
   /* istanbul ignore if */
   if (Array.isArray(handlers)) {
@@ -2636,7 +2660,8 @@ function parseString (chr) {
 var onRE = /^@|^v-on:/;
 var dirRE = /^v-|^@|^:/;
 var forAliasRE = /(.*?)\s+(?:in|of)\s+(.*)/;
-var forIteratorRE = /\((\{[^}]*\}|[^,]*),([^,]*)(?:,([^,]*))?\)/;
+var forIteratorRE = /\((\{[^}]*\}|[^,{]*),([^,]*)(?:,([^,]*))?\)/;
+var stripParensRE = /^\(|\)$/g;
 
 var argRE = /:(.*)$/;
 var bindRE = /^:|^v-bind:/;
@@ -2721,6 +2746,7 @@ function parse (
     isUnaryTag: options.isUnaryTag,
     canBeLeftOpenTag: options.canBeLeftOpenTag,
     shouldDecodeNewlines: options.shouldDecodeNewlines,
+    shouldDecodeNewlinesForHref: options.shouldDecodeNewlinesForHref,
     shouldKeepComment: options.comments,
     start: function start (tag, attrs, unary) {
       // check namespace.
@@ -2976,7 +3002,7 @@ function processFor (el) {
         el.iterator2 = iteratorMatch[3].trim();
       }
     } else {
-      el.alias = alias;
+      el.alias = alias.replace(stripParensRE, '');
     }
   }
 }
@@ -3072,6 +3098,15 @@ function processSlot (el) {
       }
       el.slotScope = slotScope || getAndRemoveAttr(el, 'slot-scope');
     } else if ((slotScope = getAndRemoveAttr(el, 'slot-scope'))) {
+      /* istanbul ignore if */
+      if ("development" !== 'production' && el.attrsMap['v-for']) {
+        warn$1(
+          "Ambiguous combined usage of slot-scope and v-for on <" + (el.tag) + "> " +
+          "(v-for takes higher priority). Use a wrapper <template> for the " +
+          "scoped slot to make it clearer.",
+          true
+        );
+      }
       el.slotScope = slotScope;
     }
     var slotTarget = getBindingAttr(el, 'slot');
@@ -3079,7 +3114,7 @@ function processSlot (el) {
       el.slotTarget = slotTarget === '""' ? '"default"' : slotTarget;
       // preserve slot as an attribute for native shadow DOM compat
       // only for non-scoped slots.
-      if (!el.slotScope) {
+      if (el.tag !== 'template' && !el.slotScope) {
         addAttr(el, 'slot', slotTarget);
       }
     }
@@ -3168,6 +3203,13 @@ function processAttrs (el) {
         }
       }
       addAttr(el, name, JSON.stringify(value));
+      // #6887 firefox doesn't update muted state if set via attribute
+      // even immediately after element creation
+      if (!el.component &&
+          name === 'muted' &&
+          platformMustUseProp(el.tag, el.attrsMap.type, name)) {
+        addProp(el, name, 'true');
+      }
     }
   }
 }
@@ -3272,6 +3314,8 @@ function preTransformNode (el, options) {
       var typeBinding = getBindingAttr(el, 'type');
       var ifCondition = getAndRemoveAttr(el, 'v-if', true);
       var ifConditionExtra = ifCondition ? ("&&(" + ifCondition + ")") : "";
+      var hasElse = getAndRemoveAttr(el, 'v-else', true) != null;
+      var elseIfCondition = getAndRemoveAttr(el, 'v-else-if', true);
       // 1. checkbox
       var branch0 = cloneASTElement(el);
       // process for on the main node
@@ -3302,6 +3346,13 @@ function preTransformNode (el, options) {
         exp: ifCondition,
         block: branch2
       });
+
+      if (hasElse) {
+        branch0.else = true;
+      } else if (elseIfCondition) {
+        branch0.elseif = elseIfCondition;
+      }
+
       return branch0
     }
   }
@@ -3452,6 +3503,19 @@ function genDefaultModel (
   modifiers
 ) {
   var type = el.attrsMap.type;
+
+  // warn if v-bind:value conflicts with v-model
+  {
+    var value$1 = el.attrsMap['v-bind:value'] || el.attrsMap[':value'];
+    if (value$1) {
+      var binding = el.attrsMap['v-bind:value'] ? 'v-bind:value' : ':value';
+      warn$2(
+        binding + "=\"" + value$1 + "\" conflicts with v-model on the same element " +
+        'because the latter already expands to a value binding internally'
+      );
+    }
+  }
+
   var ref = modifiers || {};
   var lazy = ref.lazy;
   var number = ref.number;
@@ -3690,18 +3754,7 @@ function genHandlers (
 ) {
   var res = isNative ? 'nativeOn:{' : 'on:{';
   for (var name in events) {
-    var handler = events[name];
-    // #5330: warn click.right, since right clicks do not actually fire click events.
-    if ("development" !== 'production' &&
-      name === 'click' &&
-      handler && handler.modifiers && handler.modifiers.right
-    ) {
-      warn(
-        "Use \"contextmenu\" instead of \"click.right\" since right clicks " +
-        "do not actually fire \"click\" events."
-      );
-    }
-    res += "\"" + name + "\":" + (genHandler(name, handler)) + ",";
+    res += "\"" + name + "\":" + (genHandler(name, events[name])) + ",";
   }
   return res.slice(0, -1) + '}'
 }
@@ -3868,10 +3921,10 @@ function genElement (el, state) {
 }
 
 // hoist static sub-trees out
-function genStatic (el, state) {
+function genStatic (el, state, once$$1) {
   el.staticProcessed = true;
   state.staticRenderFns.push(("with(this){return " + (genElement(el, state)) + "}"));
-  return ("_m(" + (state.staticRenderFns.length - 1) + (el.staticInFor ? ',true' : '') + ")")
+  return ("_m(" + (state.staticRenderFns.length - 1) + "," + (el.staticInFor ? 'true' : 'false') + "," + (once$$1 ? 'true' : 'false') + ")")
 }
 
 // v-once
@@ -3897,7 +3950,7 @@ function genOnce (el, state) {
     }
     return ("_o(" + (genElement(el, state)) + "," + (state.onceId++) + "," + key + ")")
   } else {
-    return genStatic(el, state)
+    return genStatic(el, state, true)
   }
 }
 
@@ -4264,9 +4317,6 @@ var unaryOperatorsRE = new RegExp('\\b' + (
   'delete,typeof,void'
 ).split(',').join('\\s*\\([^\\)]*\\)|\\b') + '\\s*\\([^\\)]*\\)');
 
-// check valid identifier for v-for
-var identRE = /[A-Za-z_$][\w$]*/;
-
 // strip strings in expressions
 var stripStringRE = /'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"|`(?:[^`\\]|\\.)*\$\{|\}(?:[^`\\]|\\.)*`|`(?:[^`\\]|\\.)*`/g;
 
@@ -4324,9 +4374,18 @@ function checkFor (node, text, errors) {
   checkIdentifier(node.iterator2, 'v-for iterator', text, errors);
 }
 
-function checkIdentifier (ident, type, text, errors) {
-  if (typeof ident === 'string' && !identRE.test(ident)) {
-    errors.push(("invalid " + type + " \"" + ident + "\" in expression: " + (text.trim())));
+function checkIdentifier (
+  ident,
+  type,
+  text,
+  errors
+) {
+  if (typeof ident === 'string') {
+    try {
+      new Function(("var " + ident + "=_"));
+    } catch (e) {
+      errors.push(("invalid " + type + " \"" + ident + "\" in expression: " + (text.trim())));
+    }
   }
 }
 
@@ -4584,6 +4643,10 @@ function applyModelTransform (el, state) {
       var dir = el.directives[i];
       if (dir.name === 'model') {
         state.directives.model(el, dir, state.warn);
+        // remove value for textarea as its converted to text
+        if (el.tag === 'textarea' && el.props) {
+          el.props = el.props.filter(function (p) { return p.name !== 'value'; });
+        }
         break
       }
     }
@@ -4731,7 +4794,7 @@ function walk (node, isRoot) {
     if (node.ifConditions) {
       for (var i$1 = 1, l$1 = node.ifConditions.length; i$1 < l$1; i$1++) {
         var block = node.ifConditions[i$1].block;
-        walk(block);
+        walk(block, isRoot);
         check(block);
       }
     }
@@ -4789,7 +4852,8 @@ function isUnOptimizableTree (node) {
   return (
     isBuiltInTag(node.tag) || // built-in (slot, component)
     !isPlatformReservedTag$1(node.tag) || // custom component
-    !!node.component // "is" component
+    !!node.component || // "is" component
+    isSelectWithModel(node) // <select v-model> requires runtime inspection
   )
 }
 
@@ -4803,6 +4867,17 @@ function hasCustomDirective (node) {
   )
 }
 
+// <select v-model> cannot be optimized because it requires a runtime check
+// to determine proper selected option
+function isSelectWithModel (node) {
+  return (
+    node.type === 1 &&
+    node.tag === 'select' &&
+    node.directives != null &&
+    node.directives.some(function (d) { return d.name === 'model'; })
+  )
+}
+
 /*  */
 
 // The SSR codegen is essentially extending the default codegen to handle
@@ -4976,6 +5051,9 @@ function childrenToSegments (el, state) {
   if ((binding = el.attrsMap['v-text'])) {
     return [{ type: INTERPOLATION, value: ("_s(" + binding + ")") }]
   }
+  if (el.tag === 'textarea' && (binding = el.attrsMap['v-model'])) {
+    return [{ type: INTERPOLATION, value: ("_s(" + binding + ")") }]
+  }
   return el.children
     ? nodesToSegments(el.children, state)
     : []
diff --git a/packages/vue-template-compiler/build.js b/packages/vue-template-compiler/build.js
index 78c3546..fe5290e 100644
--- a/packages/vue-template-compiler/build.js
+++ b/packages/vue-template-compiler/build.js
@@ -9,6 +9,8 @@ var he = _interopDefault(require('he'));
 
 /*  */
 
+var emptyObject = Object.freeze({});
+
 // these helpers produces better vm code in JS engines due to their
 // explicitness and function inlining
 
@@ -277,10 +279,11 @@ var decodingMap = {
   '>': '>',
   '"': '"',
   '&': '&',
-  '
': '\n'
+  '
': '\n',
+  '	': '\t'
 };
 var encodedAttr = /&(?:lt|gt|quot|amp);/g;
-var encodedAttrWithNewLines = /&(?:lt|gt|quot|amp|#10);/g;
+var encodedAttrWithNewLines = /&(?:lt|gt|quot|amp|#10|#9);/g;
 
 // #5992
 var isIgnoreNewlineTag = makeMap('pre,textarea', true);
@@ -471,12 +474,12 @@ function parseHTML (html, options) {
         if (args[5] === '') { delete args[5]; }
       }
       var value = args[3] || args[4] || args[5] || '';
+      var shouldDecodeNewlines = tagName === 'a' && args[1] === 'href'
+        ? options.shouldDecodeNewlinesForHref
+        : options.shouldDecodeNewlines;
       attrs[i] = {
         name: args[1],
-        value: decodeAttr(
-          value,
-          options.shouldDecodeNewlines
-        )
+        value: decodeAttr(value, shouldDecodeNewlines)
       };
     }
 
@@ -662,8 +665,6 @@ function parseComponent (
 
 /*  */
 
-var emptyObject = Object.freeze({});
-
 /**
  * Check if a string starts with $ or _
  */
@@ -683,17 +684,20 @@ function def (obj, key, val, enumerable) {
 
 /*  */
 
+
 // can we use __proto__?
 var hasProto = '__proto__' in {};
 
 // Browser environment sniffing
 var inBrowser = typeof window !== 'undefined';
+var inWeex = typeof WXEnvironment !== 'undefined' && !!WXEnvironment.platform;
+var weexPlatform = inWeex && WXEnvironment.platform.toLowerCase();
 var UA = inBrowser && window.navigator.userAgent.toLowerCase();
 var isIE = UA && /msie|trident/.test(UA);
 var isIE9 = UA && UA.indexOf('msie 9.0') > 0;
 var isEdge = UA && UA.indexOf('edge/') > 0;
-var isAndroid = UA && UA.indexOf('android') > 0;
-var isIOS = UA && /iphone|ipad|ipod|ios/.test(UA);
+var isAndroid = (UA && UA.indexOf('android') > 0) || (weexPlatform === 'android');
+var isIOS = (UA && /iphone|ipad|ipod|ios/.test(UA)) || (weexPlatform === 'ios');
 var isChrome = UA && /chrome\/\d+/.test(UA) && !isEdge;
 
 // Firefox has a "watch" function on Object.prototype...
@@ -1029,9 +1033,9 @@ var VNode = function VNode (
   this.elm = elm;
   this.ns = undefined;
   this.context = context;
-  this.functionalContext = undefined;
-  this.functionalOptions = undefined;
-  this.functionalScopeId = undefined;
+  this.fnContext = undefined;
+  this.fnOptions = undefined;
+  this.fnScopeId = undefined;
   this.key = data && data.key;
   this.componentOptions = componentOptions;
   this.componentInstance = undefined;
@@ -1285,7 +1289,7 @@ function set (target, key, val) {
     target.splice(key, 1, val);
     return val
   }
-  if (hasOwn(target, key)) {
+  if (key in target && !(key in Object.prototype)) {
     target[key] = val;
     return val
   }
@@ -1396,7 +1400,7 @@ function mergeDataOrFn (
         typeof parentVal === 'function' ? parentVal.call(this) : parentVal
       )
     }
-  } else if (parentVal || childVal) {
+  } else {
     return function mergedInstanceDataFn () {
       // instance merge
       var instanceData = typeof childVal === 'function'
@@ -1430,7 +1434,7 @@ strats.data = function (
 
       return parentVal
     }
-    return mergeDataOrFn.call(this, parentVal, childVal)
+    return mergeDataOrFn(parentVal, childVal)
   }
 
   return mergeDataOrFn(parentVal, childVal, vm)
@@ -1887,39 +1891,59 @@ function addHandler (
   important,
   warn
 ) {
+  modifiers = modifiers || emptyObject;
   // warn prevent and passive modifier
   /* istanbul ignore if */
   if (
     process.env.NODE_ENV !== 'production' && warn &&
-    modifiers && modifiers.prevent && modifiers.passive
+    modifiers.prevent && modifiers.passive
   ) {
     warn(
       'passive and prevent can\'t be used together. ' +
       'Passive handler can\'t prevent default event.'
     );
   }
+
   // check capture modifier
-  if (modifiers && modifiers.capture) {
+  if (modifiers.capture) {
     delete modifiers.capture;
     name = '!' + name; // mark the event as captured
   }
-  if (modifiers && modifiers.once) {
+  if (modifiers.once) {
     delete modifiers.once;
     name = '~' + name; // mark the event as once
   }
   /* istanbul ignore if */
-  if (modifiers && modifiers.passive) {
+  if (modifiers.passive) {
     delete modifiers.passive;
     name = '&' + name; // mark the event as passive
   }
+
+  // normalize click.right and click.middle since they don't actually fire
+  // this is technically browser-specific, but at least for now browsers are
+  // the only target envs that have right/middle clicks.
+  if (name === 'click') {
+    if (modifiers.right) {
+      name = 'contextmenu';
+      delete modifiers.right;
+    } else if (modifiers.middle) {
+      name = 'mouseup';
+    }
+  }
+
   var events;
-  if (modifiers && modifiers.native) {
+  if (modifiers.native) {
     delete modifiers.native;
     events = el.nativeEvents || (el.nativeEvents = {});
   } else {
     events = el.events || (el.events = {});
   }
-  var newHandler = { value: value, modifiers: modifiers };
+
+  var newHandler = { value: value };
+  if (modifiers !== emptyObject) {
+    newHandler.modifiers = modifiers;
+  }
+
   var handlers = events[name];
   /* istanbul ignore if */
   if (Array.isArray(handlers)) {
@@ -2238,7 +2262,8 @@ function parseString (chr) {
 var onRE = /^@|^v-on:/;
 var dirRE = /^v-|^@|^:/;
 var forAliasRE = /(.*?)\s+(?:in|of)\s+(.*)/;
-var forIteratorRE = /\((\{[^}]*\}|[^,]*),([^,]*)(?:,([^,]*))?\)/;
+var forIteratorRE = /\((\{[^}]*\}|[^,{]*),([^,]*)(?:,([^,]*))?\)/;
+var stripParensRE = /^\(|\)$/g;
 
 var argRE = /:(.*)$/;
 var bindRE = /^:|^v-bind:/;
@@ -2323,6 +2348,7 @@ function parse (
     isUnaryTag: options.isUnaryTag,
     canBeLeftOpenTag: options.canBeLeftOpenTag,
     shouldDecodeNewlines: options.shouldDecodeNewlines,
+    shouldDecodeNewlinesForHref: options.shouldDecodeNewlinesForHref,
     shouldKeepComment: options.comments,
     start: function start (tag, attrs, unary) {
       // check namespace.
@@ -2578,7 +2604,7 @@ function processFor (el) {
         el.iterator2 = iteratorMatch[3].trim();
       }
     } else {
-      el.alias = alias;
+      el.alias = alias.replace(stripParensRE, '');
     }
   }
 }
@@ -2674,6 +2700,15 @@ function processSlot (el) {
       }
       el.slotScope = slotScope || getAndRemoveAttr(el, 'slot-scope');
     } else if ((slotScope = getAndRemoveAttr(el, 'slot-scope'))) {
+      /* istanbul ignore if */
+      if (process.env.NODE_ENV !== 'production' && el.attrsMap['v-for']) {
+        warn$1(
+          "Ambiguous combined usage of slot-scope and v-for on <" + (el.tag) + "> " +
+          "(v-for takes higher priority). Use a wrapper <template> for the " +
+          "scoped slot to make it clearer.",
+          true
+        );
+      }
       el.slotScope = slotScope;
     }
     var slotTarget = getBindingAttr(el, 'slot');
@@ -2681,7 +2716,7 @@ function processSlot (el) {
       el.slotTarget = slotTarget === '""' ? '"default"' : slotTarget;
       // preserve slot as an attribute for native shadow DOM compat
       // only for non-scoped slots.
-      if (!el.slotScope) {
+      if (el.tag !== 'template' && !el.slotScope) {
         addAttr(el, 'slot', slotTarget);
       }
     }
@@ -2770,6 +2805,13 @@ function processAttrs (el) {
         }
       }
       addAttr(el, name, JSON.stringify(value));
+      // #6887 firefox doesn't update muted state if set via attribute
+      // even immediately after element creation
+      if (!el.component &&
+          name === 'muted' &&
+          platformMustUseProp(el.tag, el.attrsMap.type, name)) {
+        addProp(el, name, 'true');
+      }
     }
   }
 }
@@ -2874,6 +2916,8 @@ function preTransformNode (el, options) {
       var typeBinding = getBindingAttr(el, 'type');
       var ifCondition = getAndRemoveAttr(el, 'v-if', true);
       var ifConditionExtra = ifCondition ? ("&&(" + ifCondition + ")") : "";
+      var hasElse = getAndRemoveAttr(el, 'v-else', true) != null;
+      var elseIfCondition = getAndRemoveAttr(el, 'v-else-if', true);
       // 1. checkbox
       var branch0 = cloneASTElement(el);
       // process for on the main node
@@ -2904,6 +2948,13 @@ function preTransformNode (el, options) {
         exp: ifCondition,
         block: branch2
       });
+
+      if (hasElse) {
+        branch0.else = true;
+      } else if (elseIfCondition) {
+        branch0.elseif = elseIfCondition;
+      }
+
       return branch0
     }
   }
@@ -3054,6 +3105,19 @@ function genDefaultModel (
   modifiers
 ) {
   var type = el.attrsMap.type;
+
+  // warn if v-bind:value conflicts with v-model
+  if (process.env.NODE_ENV !== 'production') {
+    var value$1 = el.attrsMap['v-bind:value'] || el.attrsMap[':value'];
+    if (value$1) {
+      var binding = el.attrsMap['v-bind:value'] ? 'v-bind:value' : ':value';
+      warn$2(
+        binding + "=\"" + value$1 + "\" conflicts with v-model on the same element " +
+        'because the latter already expands to a value binding internally'
+      );
+    }
+  }
+
   var ref = modifiers || {};
   var lazy = ref.lazy;
   var number = ref.number;
@@ -3292,18 +3356,7 @@ function genHandlers (
 ) {
   var res = isNative ? 'nativeOn:{' : 'on:{';
   for (var name in events) {
-    var handler = events[name];
-    // #5330: warn click.right, since right clicks do not actually fire click events.
-    if (process.env.NODE_ENV !== 'production' &&
-      name === 'click' &&
-      handler && handler.modifiers && handler.modifiers.right
-    ) {
-      warn(
-        "Use \"contextmenu\" instead of \"click.right\" since right clicks " +
-        "do not actually fire \"click\" events."
-      );
-    }
-    res += "\"" + name + "\":" + (genHandler(name, handler)) + ",";
+    res += "\"" + name + "\":" + (genHandler(name, events[name])) + ",";
   }
   return res.slice(0, -1) + '}'
 }
@@ -3470,10 +3523,10 @@ function genElement (el, state) {
 }
 
 // hoist static sub-trees out
-function genStatic (el, state) {
+function genStatic (el, state, once$$1) {
   el.staticProcessed = true;
   state.staticRenderFns.push(("with(this){return " + (genElement(el, state)) + "}"));
-  return ("_m(" + (state.staticRenderFns.length - 1) + (el.staticInFor ? ',true' : '') + ")")
+  return ("_m(" + (state.staticRenderFns.length - 1) + "," + (el.staticInFor ? 'true' : 'false') + "," + (once$$1 ? 'true' : 'false') + ")")
 }
 
 // v-once
@@ -3499,7 +3552,7 @@ function genOnce (el, state) {
     }
     return ("_o(" + (genElement(el, state)) + "," + (state.onceId++) + "," + key + ")")
   } else {
-    return genStatic(el, state)
+    return genStatic(el, state, true)
   }
 }
 
@@ -3866,9 +3919,6 @@ var unaryOperatorsRE = new RegExp('\\b' + (
   'delete,typeof,void'
 ).split(',').join('\\s*\\([^\\)]*\\)|\\b') + '\\s*\\([^\\)]*\\)');
 
-// check valid identifier for v-for
-var identRE = /[A-Za-z_$][\w$]*/;
-
 // strip strings in expressions
 var stripStringRE = /'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"|`(?:[^`\\]|\\.)*\$\{|\}(?:[^`\\]|\\.)*`|`(?:[^`\\]|\\.)*`/g;
 
@@ -3926,9 +3976,18 @@ function checkFor (node, text, errors) {
   checkIdentifier(node.iterator2, 'v-for iterator', text, errors);
 }
 
-function checkIdentifier (ident, type, text, errors) {
-  if (typeof ident === 'string' && !identRE.test(ident)) {
-    errors.push(("invalid " + type + " \"" + ident + "\" in expression: " + (text.trim())));
+function checkIdentifier (
+  ident,
+  type,
+  text,
+  errors
+) {
+  if (typeof ident === 'string') {
+    try {
+      new Function(("var " + ident + "=_"));
+    } catch (e) {
+      errors.push(("invalid " + type + " \"" + ident + "\" in expression: " + (text.trim())));
+    }
   }
 }
 
@@ -4186,6 +4245,10 @@ function applyModelTransform (el, state) {
       var dir = el.directives[i];
       if (dir.name === 'model') {
         state.directives.model(el, dir, state.warn);
+        // remove value for textarea as its converted to text
+        if (el.tag === 'textarea' && el.props) {
+          el.props = el.props.filter(function (p) { return p.name !== 'value'; });
+        }
         break
       }
     }
@@ -4333,7 +4396,7 @@ function walk (node, isRoot) {
     if (node.ifConditions) {
       for (var i$1 = 1, l$1 = node.ifConditions.length; i$1 < l$1; i$1++) {
         var block = node.ifConditions[i$1].block;
-        walk(block);
+        walk(block, isRoot);
         check(block);
       }
     }
@@ -4391,7 +4454,8 @@ function isUnOptimizableTree (node) {
   return (
     isBuiltInTag(node.tag) || // built-in (slot, component)
     !isPlatformReservedTag$1(node.tag) || // custom component
-    !!node.component // "is" component
+    !!node.component || // "is" component
+    isSelectWithModel(node) // <select v-model> requires runtime inspection
   )
 }
 
@@ -4405,6 +4469,17 @@ function hasCustomDirective (node) {
   )
 }
 
+// <select v-model> cannot be optimized because it requires a runtime check
+// to determine proper selected option
+function isSelectWithModel (node) {
+  return (
+    node.type === 1 &&
+    node.tag === 'select' &&
+    node.directives != null &&
+    node.directives.some(function (d) { return d.name === 'model'; })
+  )
+}
+
 /*  */
 
 // The SSR codegen is essentially extending the default codegen to handle
@@ -4578,6 +4653,9 @@ function childrenToSegments (el, state) {
   if ((binding = el.attrsMap['v-text'])) {
     return [{ type: INTERPOLATION, value: ("_s(" + binding + ")") }]
   }
+  if (el.tag === 'textarea' && (binding = el.attrsMap['v-model'])) {
+    return [{ type: INTERPOLATION, value: ("_s(" + binding + ")") }]
+  }
   return el.children
     ? nodesToSegments(el.children, state)
     : []
diff --git a/packages/vue-template-compiler/package.json b/packages/vue-template-compiler/package.json
index 2006388..0d5da29 100644
--- a/packages/vue-template-compiler/package.json
+++ b/packages/vue-template-compiler/package.json
@@ -1,6 +1,6 @@
 {
   "name": "vue-template-compiler",
-  "version": "2.5.2",
+  "version": "2.5.9",
   "description": "template compiler for Vue 2.0",
   "main": "index.js",
   "unpkg": "browser.js",
diff --git a/packages/weex-template-compiler/build.js b/packages/weex-template-compiler/build.js
index 81f7721..ec042ce 100644
--- a/packages/weex-template-compiler/build.js
+++ b/packages/weex-template-compiler/build.js
@@ -8,6 +8,8 @@ var he = _interopDefault(require('he'));
 
 /*  */
 
+var emptyObject = Object.freeze({});
+
 // these helpers produces better vm code in JS engines due to their
 // explicitness and function inlining
 
@@ -276,10 +278,11 @@ var decodingMap = {
   '>': '>',
   '"': '"',
   '&': '&',
-  '
': '\n'
+  '
': '\n',
+  '	': '\t'
 };
 var encodedAttr = /&(?:lt|gt|quot|amp);/g;
-var encodedAttrWithNewLines = /&(?:lt|gt|quot|amp|#10);/g;
+var encodedAttrWithNewLines = /&(?:lt|gt|quot|amp|#10|#9);/g;
 
 // #5992
 var isIgnoreNewlineTag = makeMap('pre,textarea', true);
@@ -470,12 +473,12 @@ function parseHTML (html, options) {
         if (args[5] === '') { delete args[5]; }
       }
       var value = args[3] || args[4] || args[5] || '';
+      var shouldDecodeNewlines = tagName === 'a' && args[1] === 'href'
+        ? options.shouldDecodeNewlinesForHref
+        : options.shouldDecodeNewlines;
       attrs[i] = {
         name: args[1],
-        value: decodeAttr(
-          value,
-          options.shouldDecodeNewlines
-        )
+        value: decodeAttr(value, shouldDecodeNewlines)
       };
     }
 
@@ -653,6 +656,8 @@ var buildRegex = cached(function (delimiters) {
   return new RegExp(open + '((?:.|\\n)+?)' + close, 'g')
 });
 
+
+
 function parseText (
   text,
   delimiters
@@ -662,23 +667,30 @@ function parseText (
     return
   }
   var tokens = [];
+  var rawTokens = [];
   var lastIndex = tagRE.lastIndex = 0;
-  var match, index;
+  var match, index, tokenValue;
   while ((match = tagRE.exec(text))) {
     index = match.index;
     // push text token
     if (index > lastIndex) {
-      tokens.push(JSON.stringify(text.slice(lastIndex, index)));
+      rawTokens.push(tokenValue = text.slice(lastIndex, index));
+      tokens.push(JSON.stringify(tokenValue));
     }
     // tag token
     var exp = parseFilters(match[1].trim());
     tokens.push(("_s(" + exp + ")"));
+    rawTokens.push({ '@binding': exp });
     lastIndex = index + match[0].length;
   }
   if (lastIndex < text.length) {
-    tokens.push(JSON.stringify(text.slice(lastIndex)));
+    rawTokens.push(tokenValue = text.slice(lastIndex));
+    tokens.push(JSON.stringify(tokenValue));
+  }
+  return {
+    expression: tokens.join('+'),
+    tokens: rawTokens
   }
-  return tokens.join('+')
 }
 
 /*  */
@@ -831,267 +843,22 @@ function parseString (chr) {
   }
 }
 
-var ASSET_TYPES = [
-  'component',
-  'directive',
-  'filter'
-];
-
-var LIFECYCLE_HOOKS = [
-  'beforeCreate',
-  'created',
-  'beforeMount',
-  'mounted',
-  'beforeUpdate',
-  'updated',
-  'beforeDestroy',
-  'destroyed',
-  'activated',
-  'deactivated',
-  'errorCaptured'
-];
-
-/*  */
-
-var config = ({
-  /**
-   * Option merge strategies (used in core/util/options)
-   */
-  optionMergeStrategies: Object.create(null),
-
-  /**
-   * Whether to suppress warnings.
-   */
-  silent: false,
-
-  /**
-   * Show production mode tip message on boot?
-   */
-  productionTip: process.env.NODE_ENV !== 'production',
-
-  /**
-   * Whether to enable devtools
-   */
-  devtools: process.env.NODE_ENV !== 'production',
-
-  /**
-   * Whether to record perf
-   */
-  performance: false,
-
-  /**
-   * Error handler for watcher errors
-   */
-  errorHandler: null,
-
-  /**
-   * Warn handler for watcher warns
-   */
-  warnHandler: null,
-
-  /**
-   * Ignore certain custom elements
-   */
-  ignoredElements: [],
-
-  /**
-   * Custom user key aliases for v-on
-   */
-  keyCodes: Object.create(null),
-
-  /**
-   * Check if a tag is reserved so that it cannot be registered as a
-   * component. This is platform-dependent and may be overwritten.
-   */
-  isReservedTag: no,
-
-  /**
-   * Check if an attribute is reserved so that it cannot be used as a component
-   * prop. This is platform-dependent and may be overwritten.
-   */
-  isReservedAttr: no,
-
-  /**
-   * Check if a tag is an unknown element.
-   * Platform-dependent.
-   */
-  isUnknownElement: no,
-
-  /**
-   * Get the namespace of an element
-   */
-  getTagNamespace: noop,
-
-  /**
-   * Parse the real tag name for the specific platform.
-   */
-  parsePlatformTagName: identity,
-
-  /**
-   * Check if an attribute must be bound using property, e.g. value
-   * Platform-dependent.
-   */
-  mustUseProp: no,
-
-  /**
-   * Exposed for legacy reasons
-   */
-  _lifecycleHooks: LIFECYCLE_HOOKS
-});
-
-/*  */
-
-var warn$1 = noop;
-var tip = noop;
-var generateComponentTrace = (noop); // work around flow check
-var formatComponentName = (noop);
-
-if (process.env.NODE_ENV !== 'production') {
-  var hasConsole = typeof console !== 'undefined';
-  var classifyRE = /(?:^|[-_])(\w)/g;
-  var classify = function (str) { return str
-    .replace(classifyRE, function (c) { return c.toUpperCase(); })
-    .replace(/[-_]/g, ''); };
-
-  warn$1 = function (msg, vm) {
-    var trace = vm ? generateComponentTrace(vm) : '';
-
-    if (config.warnHandler) {
-      config.warnHandler.call(null, msg, vm, trace);
-    } else if (hasConsole && (!config.silent)) {
-      console.error(("[Vue warn]: " + msg + trace));
-    }
-  };
-
-  tip = function (msg, vm) {
-    if (hasConsole && (!config.silent)) {
-      console.warn("[Vue tip]: " + msg + (
-        vm ? generateComponentTrace(vm) : ''
-      ));
-    }
-  };
-
-  formatComponentName = function (vm, includeFile) {
-    if (vm.$root === vm) {
-      return '<Root>'
-    }
-    var options = typeof vm === 'function' && vm.cid != null
-      ? vm.options
-      : vm._isVue
-        ? vm.$options || vm.constructor.options
-        : vm || {};
-    var name = options.name || options._componentTag;
-    var file = options.__file;
-    if (!name && file) {
-      var match = file.match(/([^/\\]+)\.vue$/);
-      name = match && match[1];
-    }
-
-    return (
-      (name ? ("<" + (classify(name)) + ">") : "<Anonymous>") +
-      (file && includeFile !== false ? (" at " + file) : '')
-    )
-  };
-
-  var repeat = function (str, n) {
-    var res = '';
-    while (n) {
-      if (n % 2 === 1) { res += str; }
-      if (n > 1) { str += str; }
-      n >>= 1;
-    }
-    return res
-  };
-
-  generateComponentTrace = function (vm) {
-    if (vm._isVue && vm.$parent) {
-      var tree = [];
-      var currentRecursiveSequence = 0;
-      while (vm) {
-        if (tree.length > 0) {
-          var last = tree[tree.length - 1];
-          if (last.constructor === vm.constructor) {
-            currentRecursiveSequence++;
-            vm = vm.$parent;
-            continue
-          } else if (currentRecursiveSequence > 0) {
-            tree[tree.length - 1] = [last, currentRecursiveSequence];
-            currentRecursiveSequence = 0;
-          }
-        }
-        tree.push(vm);
-        vm = vm.$parent;
-      }
-      return '\n\nfound in\n\n' + tree
-        .map(function (vm, i) { return ("" + (i === 0 ? '---> ' : repeat(' ', 5 + i * 2)) + (Array.isArray(vm)
-            ? ((formatComponentName(vm[0])) + "... (" + (vm[1]) + " recursive calls)")
-            : formatComponentName(vm))); })
-        .join('\n')
-    } else {
-      return ("\n\n(found in " + (formatComponentName(vm)) + ")")
-    }
-  };
-}
-
 /*  */
 
-function handleError (err, vm, info) {
-  if (vm) {
-    var cur = vm;
-    while ((cur = cur.$parent)) {
-      var hooks = cur.$options.errorCaptured;
-      if (hooks) {
-        for (var i = 0; i < hooks.length; i++) {
-          try {
-            var capture = hooks[i].call(cur, err, vm, info) === false;
-            if (capture) { return }
-          } catch (e) {
-            globalHandleError(e, cur, 'errorCaptured hook');
-          }
-        }
-      }
-    }
-  }
-  globalHandleError(err, vm, info);
-}
-
-function globalHandleError (err, vm, info) {
-  if (config.errorHandler) {
-    try {
-      return config.errorHandler.call(null, err, vm, info)
-    } catch (e) {
-      logError(e, null, 'config.errorHandler');
-    }
-  }
-  logError(err, vm, info);
-}
-
-function logError (err, vm, info) {
-  if (process.env.NODE_ENV !== 'production') {
-    warn$1(("Error in " + info + ": \"" + (err.toString()) + "\""), vm);
-  }
-  /* istanbul ignore else */
-  if (inBrowser && typeof console !== 'undefined') {
-    console.error(err);
-  } else {
-    throw err
-  }
-}
-
-/*  */
-/* globals MessageChannel */
 
 // can we use __proto__?
 var hasProto = '__proto__' in {};
 
 // Browser environment sniffing
 var inBrowser = typeof window !== 'undefined';
+var inWeex = typeof WXEnvironment !== 'undefined' && !!WXEnvironment.platform;
+var weexPlatform = inWeex && WXEnvironment.platform.toLowerCase();
 var UA = inBrowser && window.navigator.userAgent.toLowerCase();
 var isIE = UA && /msie|trident/.test(UA);
 var isIE9 = UA && UA.indexOf('msie 9.0') > 0;
 var isEdge = UA && UA.indexOf('edge/') > 0;
-var isAndroid = UA && UA.indexOf('android') > 0;
-var isIOS = UA && /iphone|ipad|ipod|ios/.test(UA);
+var isAndroid = (UA && UA.indexOf('android') > 0) || (weexPlatform === 'android');
+var isIOS = (UA && /iphone|ipad|ipod|ios/.test(UA)) || (weexPlatform === 'ios');
 var isChrome = UA && /chrome\/\d+/.test(UA) && !isEdge;
 
 // Firefox has a "watch" function on Object.prototype...
@@ -1140,88 +907,6 @@ var hasSymbol =
   typeof Symbol !== 'undefined' && isNative(Symbol) &&
   typeof Reflect !== 'undefined' && isNative(Reflect.ownKeys);
 
-/**
- * Defer a task to execute it asynchronously.
- */
-var nextTick = (function () {
-  var callbacks = [];
-  var pending = false;
-  var timerFunc;
-
-  function nextTickHandler () {
-    pending = false;
-    var copies = callbacks.slice(0);
-    callbacks.length = 0;
-    for (var i = 0; i < copies.length; i++) {
-      copies[i]();
-    }
-  }
-
-  // An asynchronous deferring mechanism.
-  // In pre 2.4, we used to use microtasks (Promise/MutationObserver)
-  // but microtasks actually has too high a priority and fires in between
-  // supposedly sequential events (e.g. #4521, #6690) or even between
-  // bubbling of the same event (#6566). Technically setImmediate should be
-  // the ideal choice, but it's not available everywhere; and the only polyfill
-  // that consistently queues the callback after all DOM events triggered in the
-  // same loop is by using MessageChannel.
-  /* istanbul ignore if */
-  if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) {
-    timerFunc = function () {
-      setImmediate(nextTickHandler);
-    };
-  } else if (typeof MessageChannel !== 'undefined' && (
-    isNative(MessageChannel) ||
-    // PhantomJS
-    MessageChannel.toString() === '[object MessageChannelConstructor]'
-  )) {
-    var channel = new MessageChannel();
-    var port = channel.port2;
-    channel.port1.onmessage = nextTickHandler;
-    timerFunc = function () {
-      port.postMessage(1);
-    };
-  } else
-  /* istanbul ignore next */
-  if (typeof Promise !== 'undefined' && isNative(Promise)) {
-    // use microtask in non-DOM environments, e.g. Weex
-    var p = Promise.resolve();
-    timerFunc = function () {
-      p.then(nextTickHandler);
-    };
-  } else {
-    // fallback to setTimeout
-    timerFunc = function () {
-      setTimeout(nextTickHandler, 0);
-    };
-  }
-
-  return function queueNextTick (cb, ctx) {
-    var _resolve;
-    callbacks.push(function () {
-      if (cb) {
-        try {
-          cb.call(ctx);
-        } catch (e) {
-          handleError(e, ctx, 'nextTick');
-        }
-      } else if (_resolve) {
-        _resolve(ctx);
-      }
-    });
-    if (!pending) {
-      pending = true;
-      timerFunc();
-    }
-    // $flow-disable-line
-    if (!cb && typeof Promise !== 'undefined') {
-      return new Promise(function (resolve, reject) {
-        _resolve = resolve;
-      })
-    }
-  }
-})();
-
 var _Set;
 /* istanbul ignore if */ // $flow-disable-line
 if (typeof Set !== 'undefined' && isNative(Set)) {
@@ -1289,39 +974,59 @@ function addHandler (
   important,
   warn
 ) {
+  modifiers = modifiers || emptyObject;
   // warn prevent and passive modifier
   /* istanbul ignore if */
   if (
     process.env.NODE_ENV !== 'production' && warn &&
-    modifiers && modifiers.prevent && modifiers.passive
+    modifiers.prevent && modifiers.passive
   ) {
     warn(
       'passive and prevent can\'t be used together. ' +
       'Passive handler can\'t prevent default event.'
     );
   }
+
   // check capture modifier
-  if (modifiers && modifiers.capture) {
+  if (modifiers.capture) {
     delete modifiers.capture;
     name = '!' + name; // mark the event as captured
   }
-  if (modifiers && modifiers.once) {
+  if (modifiers.once) {
     delete modifiers.once;
     name = '~' + name; // mark the event as once
   }
   /* istanbul ignore if */
-  if (modifiers && modifiers.passive) {
+  if (modifiers.passive) {
     delete modifiers.passive;
     name = '&' + name; // mark the event as passive
   }
+
+  // normalize click.right and click.middle since they don't actually fire
+  // this is technically browser-specific, but at least for now browsers are
+  // the only target envs that have right/middle clicks.
+  if (name === 'click') {
+    if (modifiers.right) {
+      name = 'contextmenu';
+      delete modifiers.right;
+    } else if (modifiers.middle) {
+      name = 'mouseup';
+    }
+  }
+
   var events;
-  if (modifiers && modifiers.native) {
+  if (modifiers.native) {
     delete modifiers.native;
     events = el.nativeEvents || (el.nativeEvents = {});
   } else {
     events = el.events || (el.events = {});
   }
-  var newHandler = { value: value, modifiers: modifiers };
+
+  var newHandler = { value: value };
+  if (modifiers !== emptyObject) {
+    newHandler.modifiers = modifiers;
+  }
+
   var handlers = events[name];
   /* istanbul ignore if */
   if (Array.isArray(handlers)) {
@@ -1450,7 +1155,7 @@ function parse (
     }
   }
 
-  function endPre (element) {
+  function closeElement (element) {
     // check pre state
     if (element.pre) {
       inVPre = false;
@@ -1458,6 +1163,10 @@ function parse (
     if (platformIsPreTag(element.tag)) {
       inPre = false;
     }
+    // apply post-transforms
+    for (var i = 0; i < postTransforms.length; i++) {
+      postTransforms[i](element, options);
+    }
   }
 
   parseHTML(template, {
@@ -1466,6 +1175,7 @@ function parse (
     isUnaryTag: options.isUnaryTag,
     canBeLeftOpenTag: options.canBeLeftOpenTag,
     shouldDecodeNewlines: options.shouldDecodeNewlines,
+    shouldDecodeNewlinesForHref: options.shouldDecodeNewlinesForHref,
     shouldKeepComment: options.comments,
     start: function start (tag, attrs, unary) {
       // check namespace.
@@ -1569,11 +1279,7 @@ function parse (
         currentParent = element;
         stack.push(element);
       } else {
-        endPre(element);
-      }
-      // apply post-transforms
-      for (var i$1 = 0; i$1 < postTransforms.length; i$1++) {
-        postTransforms[i$1](element, options);
+        closeElement(element);
       }
     },
 
@@ -1587,7 +1293,7 @@ function parse (
       // pop stack
       stack.length -= 1;
       currentParent = stack[stack.length - 1];
-      endPre(element);
+      closeElement(element);
     },
 
     chars: function chars (text) {
@@ -1619,11 +1325,12 @@ function parse (
         // only preserve whitespace if its not right after a starting tag
         : preserveWhitespace && children.length ? ' ' : '';
       if (text) {
-        var expression;
-        if (!inVPre && text !== ' ' && (expression = parseText(text, delimiters))) {
+        var res;
+        if (!inVPre && text !== ' ' && (res = parseText(text, delimiters))) {
           children.push({
             type: 2,
-            expression: expression,
+            expression: res.expression,
+            tokens: res.tokens,
             text: text
           });
         } else if (text !== ' ' || !children.length || children[children.length - 1].text !== ' ') {
@@ -1817,6 +1524,15 @@ function processSlot (el) {
       }
       el.slotScope = slotScope || getAndRemoveAttr(el, 'slot-scope');
     } else if ((slotScope = getAndRemoveAttr(el, 'slot-scope'))) {
+      /* istanbul ignore if */
+      if (process.env.NODE_ENV !== 'production' && el.attrsMap['v-for']) {
+        warn(
+          "Ambiguous combined usage of slot-scope and v-for on <" + (el.tag) + "> " +
+          "(v-for takes higher priority). Use a wrapper <template> for the " +
+          "scoped slot to make it clearer.",
+          true
+        );
+      }
       el.slotScope = slotScope;
     }
     var slotTarget = getBindingAttr(el, 'slot');
@@ -1824,7 +1540,7 @@ function processSlot (el) {
       el.slotTarget = slotTarget === '""' ? '"default"' : slotTarget;
       // preserve slot as an attribute for native shadow DOM compat
       // only for non-scoped slots.
-      if (!el.slotScope) {
+      if (el.tag !== 'template' && !el.slotScope) {
         addAttr(el, 'slot', slotTarget);
       }
     }
@@ -1902,8 +1618,8 @@ function processAttrs (el) {
     } else {
       // literal attribute
       if (process.env.NODE_ENV !== 'production') {
-        var expression = parseText(value, delimiters);
-        if (expression) {
+        var res = parseText(value, delimiters);
+        if (res) {
           warn(
             name + "=\"" + value + "\": " +
             'Interpolation inside attributes has been removed. ' +
@@ -1913,6 +1629,13 @@ function processAttrs (el) {
         }
       }
       addAttr(el, name, JSON.stringify(value));
+      // #6887 firefox doesn't update muted state if set via attribute
+      // even immediately after element creation
+      if (!el.component &&
+          name === 'muted' &&
+          platformMustUseProp(el.tag, el.attrsMap.type, name)) {
+        addProp(el, name, 'true');
+      }
     }
   }
 }
@@ -2168,22 +1891,28 @@ function genHandlers (
 ) {
   var res = isNative ? 'nativeOn:{' : 'on:{';
   for (var name in events) {
-    var handler = events[name];
-    // #5330: warn click.right, since right clicks do not actually fire click events.
-    if (process.env.NODE_ENV !== 'production' &&
-      name === 'click' &&
-      handler && handler.modifiers && handler.modifiers.right
-    ) {
-      warn(
-        "Use \"contextmenu\" instead of \"click.right\" since right clicks " +
-        "do not actually fire \"click\" events."
-      );
-    }
-    res += "\"" + name + "\":" + (genHandler(name, handler)) + ",";
+    res += "\"" + name + "\":" + (genHandler(name, events[name])) + ",";
   }
   return res.slice(0, -1) + '}'
 }
 
+// Generate handler code with binding params on Weex
+function genWeexHandler (params, handlerCode) {
+  var innerHandlerCode = handlerCode;
+  var exps = params.filter(function (exp) { return simplePathRE.test(exp) && exp !== '$event'; });
+  var bindings = exps.map(function (exp) { return ({ '@binding': exp }); });
+  var args = exps.map(function (exp, i) {
+    var key = "$_" + (i + 1);
+    innerHandlerCode = innerHandlerCode.replace(exp, key);
+    return key
+  });
+  args.push('$event');
+  return '{\n' +
+    "handler:function(" + (args.join(',')) + "){" + innerHandlerCode + "},\n" +
+    "params:" + (JSON.stringify(bindings)) + "\n" +
+    '}'
+}
+
 function genHandler (
   name,
   handler
@@ -2200,9 +1929,13 @@ function genHandler (
   var isFunctionExpression = fnExpRE.test(handler.value);
 
   if (!handler.modifiers) {
-    return isMethodPath || isFunctionExpression
-      ? handler.value
-      : ("function($event){" + (handler.value) + "}") // inline statement
+    if (isMethodPath || isFunctionExpression) {
+      return handler.value
+    }
+    if (true && handler.params) {
+      return genWeexHandler(handler.params, handler.value)
+    }
+    return ("function($event){" + (handler.value) + "}") // inline statement
   } else {
     var code = '';
     var genModifierCode = '';
@@ -2238,47 +1971,250 @@ function genHandler (
       : isFunctionExpression
         ? ("(" + (handler.value) + ")($event)")
         : handler.value;
+    if (true && handler.params) {
+      return genWeexHandler(handler.params, code + handlerCode)
+    }
     return ("function($event){" + code + handlerCode + "}")
   }
 }
 
-function genKeyFilter (keys) {
-  return ("if(!('button' in $event)&&" + (keys.map(genFilterCode).join('&&')) + ")return null;")
-}
+function genKeyFilter (keys) {
+  return ("if(!('button' in $event)&&" + (keys.map(genFilterCode).join('&&')) + ")return null;")
+}
+
+function genFilterCode (key) {
+  var keyVal = parseInt(key, 10);
+  if (keyVal) {
+    return ("$event.keyCode!==" + keyVal)
+  }
+  var code = keyCodes[key];
+  return (
+    "_k($event.keyCode," +
+    (JSON.stringify(key)) + "," +
+    (JSON.stringify(code)) + "," +
+    "$event.key)"
+  )
+}
+
+/*  */
+
+/**
+ * Check if a string starts with $ or _
+ */
+
+
+/**
+ * Define a property.
+ */
+function def (obj, key, val, enumerable) {
+  Object.defineProperty(obj, key, {
+    value: val,
+    enumerable: !!enumerable,
+    writable: true,
+    configurable: true
+  });
+}
+
+var ASSET_TYPES = [
+  'component',
+  'directive',
+  'filter'
+];
+
+var LIFECYCLE_HOOKS = [
+  'beforeCreate',
+  'created',
+  'beforeMount',
+  'mounted',
+  'beforeUpdate',
+  'updated',
+  'beforeDestroy',
+  'destroyed',
+  'activated',
+  'deactivated',
+  'errorCaptured'
+];
+
+/*  */
+
+var config = ({
+  /**
+   * Option merge strategies (used in core/util/options)
+   */
+  optionMergeStrategies: Object.create(null),
+
+  /**
+   * Whether to suppress warnings.
+   */
+  silent: false,
+
+  /**
+   * Show production mode tip message on boot?
+   */
+  productionTip: process.env.NODE_ENV !== 'production',
+
+  /**
+   * Whether to enable devtools
+   */
+  devtools: process.env.NODE_ENV !== 'production',
+
+  /**
+   * Whether to record perf
+   */
+  performance: false,
+
+  /**
+   * Error handler for watcher errors
+   */
+  errorHandler: null,
+
+  /**
+   * Warn handler for watcher warns
+   */
+  warnHandler: null,
+
+  /**
+   * Ignore certain custom elements
+   */
+  ignoredElements: [],
+
+  /**
+   * Custom user key aliases for v-on
+   */
+  keyCodes: Object.create(null),
+
+  /**
+   * Check if a tag is reserved so that it cannot be registered as a
+   * component. This is platform-dependent and may be overwritten.
+   */
+  isReservedTag: no,
+
+  /**
+   * Check if an attribute is reserved so that it cannot be used as a component
+   * prop. This is platform-dependent and may be overwritten.
+   */
+  isReservedAttr: no,
+
+  /**
+   * Check if a tag is an unknown element.
+   * Platform-dependent.
+   */
+  isUnknownElement: no,
+
+  /**
+   * Get the namespace of an element
+   */
+  getTagNamespace: noop,
 
-function genFilterCode (key) {
-  var keyVal = parseInt(key, 10);
-  if (keyVal) {
-    return ("$event.keyCode!==" + keyVal)
-  }
-  var code = keyCodes[key];
-  return (
-    "_k($event.keyCode," +
-    (JSON.stringify(key)) + "," +
-    (JSON.stringify(code)) + "," +
-    "$event.key)"
-  )
-}
+  /**
+   * Parse the real tag name for the specific platform.
+   */
+  parsePlatformTagName: identity,
+
+  /**
+   * Check if an attribute must be bound using property, e.g. value
+   * Platform-dependent.
+   */
+  mustUseProp: no,
+
+  /**
+   * Exposed for legacy reasons
+   */
+  _lifecycleHooks: LIFECYCLE_HOOKS
+});
 
 /*  */
 
-var emptyObject = Object.freeze({});
+var warn$1 = noop;
+var tip = noop;
+var generateComponentTrace = (noop); // work around flow check
+var formatComponentName = (noop);
 
-/**
- * Check if a string starts with $ or _
- */
+if (process.env.NODE_ENV !== 'production') {
+  var hasConsole = typeof console !== 'undefined';
+  var classifyRE = /(?:^|[-_])(\w)/g;
+  var classify = function (str) { return str
+    .replace(classifyRE, function (c) { return c.toUpperCase(); })
+    .replace(/[-_]/g, ''); };
 
+  warn$1 = function (msg, vm) {
+    var trace = vm ? generateComponentTrace(vm) : '';
 
-/**
- * Define a property.
- */
-function def (obj, key, val, enumerable) {
-  Object.defineProperty(obj, key, {
-    value: val,
-    enumerable: !!enumerable,
-    writable: true,
-    configurable: true
-  });
+    if (config.warnHandler) {
+      config.warnHandler.call(null, msg, vm, trace);
+    } else if (hasConsole && (!config.silent)) {
+      console.error(("[Vue warn]: " + msg + trace));
+    }
+  };
+
+  tip = function (msg, vm) {
+    if (hasConsole && (!config.silent)) {
+      console.warn("[Vue tip]: " + msg + (
+        vm ? generateComponentTrace(vm) : ''
+      ));
+    }
+  };
+
+  formatComponentName = function (vm, includeFile) {
+    if (vm.$root === vm) {
+      return '<Root>'
+    }
+    var options = typeof vm === 'function' && vm.cid != null
+      ? vm.options
+      : vm._isVue
+        ? vm.$options || vm.constructor.options
+        : vm || {};
+    var name = options.name || options._componentTag;
+    var file = options.__file;
+    if (!name && file) {
+      var match = file.match(/([^/\\]+)\.vue$/);
+      name = match && match[1];
+    }
+
+    return (
+      (name ? ("<" + (classify(name)) + ">") : "<Anonymous>") +
+      (file && includeFile !== false ? (" at " + file) : '')
+    )
+  };
+
+  var repeat = function (str, n) {
+    var res = '';
+    while (n) {
+      if (n % 2 === 1) { res += str; }
+      if (n > 1) { str += str; }
+      n >>= 1;
+    }
+    return res
+  };
+
+  generateComponentTrace = function (vm) {
+    if (vm._isVue && vm.$parent) {
+      var tree = [];
+      var currentRecursiveSequence = 0;
+      while (vm) {
+        if (tree.length > 0) {
+          var last = tree[tree.length - 1];
+          if (last.constructor === vm.constructor) {
+            currentRecursiveSequence++;
+            vm = vm.$parent;
+            continue
+          } else if (currentRecursiveSequence > 0) {
+            tree[tree.length - 1] = [last, currentRecursiveSequence];
+            currentRecursiveSequence = 0;
+          }
+        }
+        tree.push(vm);
+        vm = vm.$parent;
+      }
+      return '\n\nfound in\n\n' + tree
+        .map(function (vm, i) { return ("" + (i === 0 ? '---> ' : repeat(' ', 5 + i * 2)) + (Array.isArray(vm)
+            ? ((formatComponentName(vm[0])) + "... (" + (vm[1]) + " recursive calls)")
+            : formatComponentName(vm))); })
+        .join('\n')
+    } else {
+      return ("\n\n(found in " + (formatComponentName(vm)) + ")")
+    }
+  };
 }
 
 /*  */
@@ -2341,9 +2277,9 @@ var VNode = function VNode (
   this.elm = elm;
   this.ns = undefined;
   this.context = context;
-  this.functionalContext = undefined;
-  this.functionalOptions = undefined;
-  this.functionalScopeId = undefined;
+  this.fnContext = undefined;
+  this.fnOptions = undefined;
+  this.fnScopeId = undefined;
   this.key = data && data.key;
   this.componentOptions = componentOptions;
   this.componentInstance = undefined;
@@ -2597,7 +2533,7 @@ function set (target, key, val) {
     target.splice(key, 1, val);
     return val
   }
-  if (hasOwn(target, key)) {
+  if (key in target && !(key in Object.prototype)) {
     target[key] = val;
     return val
   }
@@ -2708,7 +2644,7 @@ function mergeDataOrFn (
         typeof parentVal === 'function' ? parentVal.call(this) : parentVal
       )
     }
-  } else if (parentVal || childVal) {
+  } else {
     return function mergedInstanceDataFn () {
       // instance merge
       var instanceData = typeof childVal === 'function'
@@ -2742,7 +2678,7 @@ strats.data = function (
 
       return parentVal
     }
-    return mergeDataOrFn.call(this, parentVal, childVal)
+    return mergeDataOrFn(parentVal, childVal)
   }
 
   return mergeDataOrFn(parentVal, childVal, vm)
@@ -2889,6 +2825,54 @@ function assertObjectType (name, value, vm) {
 /*  */
 
 /*  */
+/* globals MessageChannel */
+
+var callbacks = [];
+function flushCallbacks () {
+  var copies = callbacks.slice(0);
+  callbacks.length = 0;
+  for (var i = 0; i < copies.length; i++) {
+    copies[i]();
+  }
+}
+
+// Determine (macro) Task defer implementation.
+// Technically setImmediate should be the ideal choice, but it's only available
+// in IE. The only polyfill that consistently queues the callback after all DOM
+// events triggered in the same loop is by using MessageChannel.
+/* istanbul ignore if */
+if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) {
+  
+} else if (typeof MessageChannel !== 'undefined' && (
+  isNative(MessageChannel) ||
+  // PhantomJS
+  MessageChannel.toString() === '[object MessageChannelConstructor]'
+)) {
+  var channel = new MessageChannel();
+  channel.port1.onmessage = flushCallbacks;
+  
+} else {
+  /* istanbul ignore next */
+  
+}
+
+// Determine MicroTask defer implementation.
+/* istanbul ignore next, $flow-disable-line */
+if (typeof Promise !== 'undefined' && isNative(Promise)) {
+  
+} else {
+  // fallback to macro
+  
+}
+
+/**
+ * Wrap a function so that if any code inside triggers state change,
+ * the changes are queued using a Task instead of a MicroTask.
+ */
+
+/*  */
+
+/*  */
 
 function on (el, dir) {
   if (process.env.NODE_ENV !== 'production' && dir.modifiers) {
@@ -2974,10 +2958,10 @@ function genElement (el, state) {
 }
 
 // hoist static sub-trees out
-function genStatic (el, state) {
+function genStatic (el, state, once$$1) {
   el.staticProcessed = true;
   state.staticRenderFns.push(("with(this){return " + (genElement(el, state)) + "}"));
-  return ("_m(" + (state.staticRenderFns.length - 1) + (el.staticInFor ? ',true' : '') + ")")
+  return ("_m(" + (state.staticRenderFns.length - 1) + "," + (el.staticInFor ? 'true' : 'false') + "," + (once$$1 ? 'true' : 'false') + ")")
 }
 
 // v-once
@@ -3003,7 +2987,7 @@ function genOnce (el, state) {
     }
     return ("_o(" + (genElement(el, state)) + "," + (state.onceId++) + "," + key + ")")
   } else {
-    return genStatic(el, state)
+    return genStatic(el, state, true)
   }
 }
 
@@ -3343,11 +3327,18 @@ function genProps (props) {
   var res = '';
   for (var i = 0; i < props.length; i++) {
     var prop = props[i];
-    res += "\"" + (prop.name) + "\":" + (transformSpecialNewlines(prop.value)) + ",";
+    res += "\"" + (prop.name) + "\":" + (generateValue(prop.value)) + ",";
   }
   return res.slice(0, -1)
 }
 
+function generateValue (value) {
+  if (typeof value === 'string') {
+    return transformSpecialNewlines(value)
+  }
+  return JSON.stringify(value)
+}
+
 // #3895, #4268
 function transformSpecialNewlines (text) {
   return text
@@ -3370,9 +3361,6 @@ var unaryOperatorsRE = new RegExp('\\b' + (
   'delete,typeof,void'
 ).split(',').join('\\s*\\([^\\)]*\\)|\\b') + '\\s*\\([^\\)]*\\)');
 
-// check valid identifier for v-for
-var identRE = /[A-Za-z_$][\w$]*/;
-
 // strip strings in expressions
 var stripStringRE = /'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"|`(?:[^`\\]|\\.)*\$\{|\}(?:[^`\\]|\\.)*`|`(?:[^`\\]|\\.)*`/g;
 
@@ -3430,9 +3418,18 @@ function checkFor (node, text, errors) {
   checkIdentifier(node.iterator2, 'v-for iterator', text, errors);
 }
 
-function checkIdentifier (ident, type, text, errors) {
-  if (typeof ident === 'string' && !identRE.test(ident)) {
-    errors.push(("invalid " + type + " \"" + ident + "\" in expression: " + (text.trim())));
+function checkIdentifier (
+  ident,
+  type,
+  text,
+  errors
+) {
+  if (typeof ident === 'string') {
+    try {
+      new Function(("var " + ident + "=_"));
+    } catch (e) {
+      errors.push(("invalid " + type + " \"" + ident + "\" in expression: " + (text.trim())));
+    }
   }
 }
 
@@ -3671,7 +3668,7 @@ function parseStaticClass (staticClass, options) {
       var result = parseText(name, options.delimiters);
       if (result) {
         dynamic = true;
-        return result
+        return result.expression
       }
       return JSON.stringify(name)
     });
@@ -3743,7 +3740,7 @@ function parseStaticStyle (staticStyle, options) {
       var dynamicValue = parseText(value, options.delimiters);
       if (dynamicValue) {
         dynamic = true;
-        return key + ':' + dynamicValue
+        return key + ':' + dynamicValue.expression
       }
       return key + ':' + JSON.stringify(value)
     }).filter(function (result) { return result; });
@@ -3813,7 +3810,200 @@ var append = {
   genData: genData$3
 };
 
+/*  */
+
+function genText$1 (node) {
+  var value = node.type === 3
+    ? node.text
+    : node.type === 2
+      ? node.tokens.length === 1
+        ? node.tokens[0]
+        : node.tokens
+      : '';
+  return JSON.stringify(value)
+}
+
+function postTransformText (el, options) {
+  // weex <text> can only contain text, so the parser
+  // always generates a single child.
+  if (el.children.length) {
+    addAttr(el, 'value', genText$1(el.children[0]));
+    el.children = [];
+    el.plain = false;
+  }
+}
+
+/*  */
+
+function parseAttrName (name) {
+  return camelize(name.replace(bindRE, ''))
+}
+
+function preTransformVBind (el, options) {
+  for (var attr in el.attrsMap) {
+    if (bindRE.test(attr)) {
+      var name = parseAttrName(attr);
+      var value = {
+        '@binding': getAndRemoveAttr(el, attr)
+      };
+      delete el.attrsMap[attr];
+      el.attrsMap[name] = value;
+      el.attrsList.push({ name: name, value: value });
+      // addAttr(el, name, value)
+      // el.hasBindings = false
+    }
+  }
+}
+
+/*  */
+
+function hasConditionDirective (el) {
+  for (var attr in el.attrsMap) {
+    if (/^v\-if|v\-else|v\-else\-if$/.test(attr)) {
+      return true
+    }
+  }
+  return false
+}
+
+function getPrevMatch (el) {
+  if (el.parent && el.parent.children) {
+    var prev = el.parent.children[el.parent.children.length - 1];
+    return prev.attrsMap['[[match]]']
+  }
+}
+
+function preTransformVIf (el, options) {
+  if (hasConditionDirective(el)) {
+    var exp;
+    var ifExp = getAndRemoveAttr(el, 'v-if', true /* remove from attrsMap */);
+    var elseExp = getAndRemoveAttr(el, 'v-else', true);
+    var elseifExp = getAndRemoveAttr(el, 'v-else-if', true);
+    if (ifExp) {
+      exp = ifExp;
+    } else {
+      var prevMatch = getPrevMatch(el);
+      if (prevMatch) {
+        exp = elseifExp
+          ? ("!(" + prevMatch + ") && (" + elseifExp + ")") // v-else-if
+          : ("!(" + prevMatch + ")"); // v-else
+      } else if (process.env.NODE_ENV !== 'production' && options.warn) {
+        options.warn(
+          "v-" + (elseifExp ? ('else-if="' + elseifExp + '"') : 'else') + " " +
+          "used on element <" + (el.tag) + "> without corresponding v-if."
+        );
+        return
+      }
+    }
+    el.attrsMap['[[match]]'] = exp;
+    el.attrsList.push({ name: '[[match]]', value: exp });
+  }
+}
+
+/*  */
+
+function preTransformVFor (el, options) {
+  var exp = getAndRemoveAttr(el, 'v-for');
+  if (!exp) {
+    return
+  }
+  var inMatch = exp.match(forAliasRE);
+  if (inMatch) {
+    var alias = inMatch[1].trim();
+    var desc = {
+      '@expression': inMatch[2].trim(),
+      '@alias': alias
+    };
+    var iteratorMatch = alias.match(forIteratorRE);
+    if (iteratorMatch) {
+      desc['@alias'] = iteratorMatch[1].trim();
+      desc['@index'] = iteratorMatch[2].trim();
+      if (iteratorMatch[3]) {
+        desc['@key'] = iteratorMatch[2].trim();
+        desc['@index'] = iteratorMatch[3].trim();
+      }
+    }
+    delete el.attrsMap['v-for'];
+    el.attrsMap['[[repeat]]'] = desc;
+    el.attrsList.push({ name: '[[repeat]]', value: desc });
+  } else if (process.env.NODE_ENV !== 'production' && options.warn) {
+    options.warn(("Invalid v-for expression: " + exp));
+  }
+}
+
+/*  */
+
+var inlineStatementRE = /^\s*([A-Za-z_$0-9\['\."\]]+)*\s*\(\s*(([A-Za-z_$0-9\['\."\]]+)?(\s*,\s*([A-Za-z_$0-9\['\."\]]+))*)\s*\)$/;
+
+function parseHandlerParams (handler) {
+  var res = inlineStatementRE.exec(handler.value);
+  if (res && res[2]) {
+    handler.params = res[2].split(/\s*,\s*/);
+  }
+}
+
+function postTransformVOn (el, options) {
+  var events = el.events;
+  if (!events) {
+    return
+  }
+  for (var name in events) {
+    var handler = events[name];
+    if (Array.isArray(handler)) {
+      handler.map(function (fn) { return parseHandlerParams(fn); });
+    } else {
+      parseHandlerParams(handler);
+    }
+  }
+}
+
+/*  */
+
+var currentRecycleList = null;
+
+function shouldCompile (el, options) {
+  return options.recyclable ||
+    (currentRecycleList && el !== currentRecycleList)
+}
+
+function preTransformNode$1 (el, options) {
+  if (el.tag === 'recycle-list') {
+    currentRecycleList = el;
+  }
+  if (shouldCompile(el, options)) {
+    preTransformVBind(el, options);
+    preTransformVIf(el, options); // also v-else-if and v-else
+    preTransformVFor(el, options);
+  }
+}
+
+function transformNode$3 (el, options) {
+  if (shouldCompile(el, options)) {
+    // do nothing yet
+  }
+}
+
+function postTransformNode (el, options) {
+  if (shouldCompile(el, options)) {
+    // <text>: transform children text into value attr
+    if (el.tag === 'text') {
+      postTransformText(el, options);
+    }
+    postTransformVOn(el, options);
+  }
+  if (el === currentRecycleList) {
+    currentRecycleList = null;
+  }
+}
+
+var recycleList = {
+  preTransformNode: preTransformNode$1,
+  transformNode: transformNode$3,
+  postTransformNode: postTransformNode
+};
+
 var modules = [
+  recycleList,
   klass,
   style,
   props,
@@ -3879,7 +4069,7 @@ var canBeLeftOpenTag$1 = makeMap(
 );
 
 var isRuntimeComponent = makeMap(
-  'richtext,trisition,trisition-group',
+  'richtext,transition,transition-group',
   true
 );
 
@@ -3902,10 +4092,31 @@ var baseOptions = {
   isReservedTag: isReservedTag,
   getTagNamespace: getTagNamespace,
   preserveWhitespace: false,
+  recyclable: false,
   staticKeys: genStaticKeys(modules)
 };
 
-var ref = createCompiler(baseOptions);
-var compile = ref.compile;
+var compiler = createCompiler(baseOptions);
+
+function compile (
+  template,
+  options
+) {
+  var generateAltRender = false;
+  if (options && options.recyclable === true) {
+    generateAltRender = true;
+    options.recyclable = false;
+  }
+  var result = compiler.compile(template, options);
+
+  // generate @render function for <recycle-list>
+  if (options && generateAltRender) {
+    options.recyclable = true;
+    var ref = compiler.compile(template, options);
+    var render = ref.render;
+    result['@render'] = render;
+  }
+  return result
+}
 
 exports.compile = compile;
diff --git a/packages/weex-vue-framework/factory.js b/packages/weex-vue-framework/factory.js
index 266cba3..858e217 100644
--- a/packages/weex-vue-framework/factory.js
+++ b/packages/weex-vue-framework/factory.js
@@ -4,6 +4,8 @@ module.exports = function weexFactory (exports, document) {
 
 /*  */
 
+var emptyObject = Object.freeze({});
+
 // these helpers produces better vm code in JS engines due to their
 // explicitness and function inlining
 function isUndef (v) {
@@ -417,8 +419,6 @@ var config = ({
 
 /*  */
 
-var emptyObject = Object.freeze({});
-
 /**
  * Check if a string starts with $ or _
  */
@@ -459,6 +459,95 @@ function parsePath (path) {
 
 /*  */
 
+
+// can we use __proto__?
+var hasProto = '__proto__' in {};
+
+// Browser environment sniffing
+var inBrowser = typeof window !== 'undefined';
+var inWeex = typeof WXEnvironment !== 'undefined' && !!WXEnvironment.platform;
+var weexPlatform = inWeex && WXEnvironment.platform.toLowerCase();
+var UA = inBrowser && window.navigator.userAgent.toLowerCase();
+var isIE = UA && /msie|trident/.test(UA);
+var isIE9 = UA && UA.indexOf('msie 9.0') > 0;
+var isEdge = UA && UA.indexOf('edge/') > 0;
+var isAndroid = (UA && UA.indexOf('android') > 0) || (weexPlatform === 'android');
+var isIOS = (UA && /iphone|ipad|ipod|ios/.test(UA)) || (weexPlatform === 'ios');
+var isChrome = UA && /chrome\/\d+/.test(UA) && !isEdge;
+
+// Firefox has a "watch" function on Object.prototype...
+var nativeWatch = ({}).watch;
+
+
+if (inBrowser) {
+  try {
+    var opts = {};
+    Object.defineProperty(opts, 'passive', ({
+      get: function get () {
+        /* istanbul ignore next */
+        
+      }
+    })); // https://github.com/facebook/flow/issues/285
+    window.addEventListener('test-passive', null, opts);
+  } catch (e) {}
+}
+
+// this needs to be lazy-evaled because vue may be required before
+// vue-server-renderer can set VUE_ENV
+var _isServer;
+var isServerRendering = function () {
+  if (_isServer === undefined) {
+    /* istanbul ignore if */
+    if (!inBrowser && typeof global !== 'undefined') {
+      // detect presence of vue-server-renderer and avoid
+      // Webpack shimming the process
+      _isServer = global['process'].env.VUE_ENV === 'server';
+    } else {
+      _isServer = false;
+    }
+  }
+  return _isServer
+};
+
+// detect devtools
+var devtools = inBrowser && window.__VUE_DEVTOOLS_GLOBAL_HOOK__;
+
+/* istanbul ignore next */
+function isNative (Ctor) {
+  return typeof Ctor === 'function' && /native code/.test(Ctor.toString())
+}
+
+var hasSymbol =
+  typeof Symbol !== 'undefined' && isNative(Symbol) &&
+  typeof Reflect !== 'undefined' && isNative(Reflect.ownKeys);
+
+var _Set;
+/* istanbul ignore if */ // $flow-disable-line
+if (typeof Set !== 'undefined' && isNative(Set)) {
+  // use native Set when available.
+  _Set = Set;
+} else {
+  // a non-standard Set polyfill that only works with primitive keys.
+  _Set = (function () {
+    function Set () {
+      this.set = Object.create(null);
+    }
+    Set.prototype.has = function has (key) {
+      return this.set[key] === true
+    };
+    Set.prototype.add = function add (key) {
+      this.set[key] = true;
+    };
+    Set.prototype.clear = function clear () {
+      this.set = Object.create(null);
+    };
+
+    return Set;
+  }());
+}
+
+/*  */
+
 var warn = noop;
 var tip = noop;
 var generateComponentTrace = (noop); // work around flow check
@@ -553,220 +642,6 @@ if (process.env.NODE_ENV !== 'production') {
 
 /*  */
 
-function handleError (err, vm, info) {
-  if (vm) {
-    var cur = vm;
-    while ((cur = cur.$parent)) {
-      var hooks = cur.$options.errorCaptured;
-      if (hooks) {
-        for (var i = 0; i < hooks.length; i++) {
-          try {
-            var capture = hooks[i].call(cur, err, vm, info) === false;
-            if (capture) { return }
-          } catch (e) {
-            globalHandleError(e, cur, 'errorCaptured hook');
-          }
-        }
-      }
-    }
-  }
-  globalHandleError(err, vm, info);
-}
-
-function globalHandleError (err, vm, info) {
-  if (config.errorHandler) {
-    try {
-      return config.errorHandler.call(null, err, vm, info)
-    } catch (e) {
-      logError(e, null, 'config.errorHandler');
-    }
-  }
-  logError(err, vm, info);
-}
-
-function logError (err, vm, info) {
-  if (process.env.NODE_ENV !== 'production') {
-    warn(("Error in " + info + ": \"" + (err.toString()) + "\""), vm);
-  }
-  /* istanbul ignore else */
-  if (inBrowser && typeof console !== 'undefined') {
-    console.error(err);
-  } else {
-    throw err
-  }
-}
-
-/*  */
-/* globals MessageChannel */
-
-// can we use __proto__?
-var hasProto = '__proto__' in {};
-
-// Browser environment sniffing
-var inBrowser = typeof window !== 'undefined';
-var UA = inBrowser && window.navigator.userAgent.toLowerCase();
-var isIE = UA && /msie|trident/.test(UA);
-var isIE9 = UA && UA.indexOf('msie 9.0') > 0;
-var isEdge = UA && UA.indexOf('edge/') > 0;
-var isAndroid = UA && UA.indexOf('android') > 0;
-var isIOS = UA && /iphone|ipad|ipod|ios/.test(UA);
-var isChrome = UA && /chrome\/\d+/.test(UA) && !isEdge;
-
-// Firefox has a "watch" function on Object.prototype...
-var nativeWatch = ({}).watch;
-
-
-if (inBrowser) {
-  try {
-    var opts = {};
-    Object.defineProperty(opts, 'passive', ({
-      get: function get () {
-        /* istanbul ignore next */
-        
-      }
-    })); // https://github.com/facebook/flow/issues/285
-    window.addEventListener('test-passive', null, opts);
-  } catch (e) {}
-}
-
-// this needs to be lazy-evaled because vue may be required before
-// vue-server-renderer can set VUE_ENV
-var _isServer;
-var isServerRendering = function () {
-  if (_isServer === undefined) {
-    /* istanbul ignore if */
-    if (!inBrowser && typeof global !== 'undefined') {
-      // detect presence of vue-server-renderer and avoid
-      // Webpack shimming the process
-      _isServer = global['process'].env.VUE_ENV === 'server';
-    } else {
-      _isServer = false;
-    }
-  }
-  return _isServer
-};
-
-// detect devtools
-var devtools = inBrowser && window.__VUE_DEVTOOLS_GLOBAL_HOOK__;
-
-/* istanbul ignore next */
-function isNative (Ctor) {
-  return typeof Ctor === 'function' && /native code/.test(Ctor.toString())
-}
-
-var hasSymbol =
-  typeof Symbol !== 'undefined' && isNative(Symbol) &&
-  typeof Reflect !== 'undefined' && isNative(Reflect.ownKeys);
-
-/**
- * Defer a task to execute it asynchronously.
- */
-var nextTick = (function () {
-  var callbacks = [];
-  var pending = false;
-  var timerFunc;
-
-  function nextTickHandler () {
-    pending = false;
-    var copies = callbacks.slice(0);
-    callbacks.length = 0;
-    for (var i = 0; i < copies.length; i++) {
-      copies[i]();
-    }
-  }
-
-  // An asynchronous deferring mechanism.
-  // In pre 2.4, we used to use microtasks (Promise/MutationObserver)
-  // but microtasks actually has too high a priority and fires in between
-  // supposedly sequential events (e.g. #4521, #6690) or even between
-  // bubbling of the same event (#6566). Technically setImmediate should be
-  // the ideal choice, but it's not available everywhere; and the only polyfill
-  // that consistently queues the callback after all DOM events triggered in the
-  // same loop is by using MessageChannel.
-  /* istanbul ignore if */
-  if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) {
-    timerFunc = function () {
-      setImmediate(nextTickHandler);
-    };
-  } else if (typeof MessageChannel !== 'undefined' && (
-    isNative(MessageChannel) ||
-    // PhantomJS
-    MessageChannel.toString() === '[object MessageChannelConstructor]'
-  )) {
-    var channel = new MessageChannel();
-    var port = channel.port2;
-    channel.port1.onmessage = nextTickHandler;
-    timerFunc = function () {
-      port.postMessage(1);
-    };
-  } else
-  /* istanbul ignore next */
-  if (typeof Promise !== 'undefined' && isNative(Promise)) {
-    // use microtask in non-DOM environments, e.g. Weex
-    var p = Promise.resolve();
-    timerFunc = function () {
-      p.then(nextTickHandler);
-    };
-  } else {
-    // fallback to setTimeout
-    timerFunc = function () {
-      setTimeout(nextTickHandler, 0);
-    };
-  }
-
-  return function queueNextTick (cb, ctx) {
-    var _resolve;
-    callbacks.push(function () {
-      if (cb) {
-        try {
-          cb.call(ctx);
-        } catch (e) {
-          handleError(e, ctx, 'nextTick');
-        }
-      } else if (_resolve) {
-        _resolve(ctx);
-      }
-    });
-    if (!pending) {
-      pending = true;
-      timerFunc();
-    }
-    // $flow-disable-line
-    if (!cb && typeof Promise !== 'undefined') {
-      return new Promise(function (resolve, reject) {
-        _resolve = resolve;
-      })
-    }
-  }
-})();
-
-var _Set;
-/* istanbul ignore if */ // $flow-disable-line
-if (typeof Set !== 'undefined' && isNative(Set)) {
-  // use native Set when available.
-  _Set = Set;
-} else {
-  // a non-standard Set polyfill that only works with primitive keys.
-  _Set = (function () {
-    function Set () {
-      this.set = Object.create(null);
-    }
-    Set.prototype.has = function has (key) {
-      return this.set[key] === true
-    };
-    Set.prototype.add = function add (key) {
-      this.set[key] = true;
-    };
-    Set.prototype.clear = function clear () {
-      this.set = Object.create(null);
-    };
-
-    return Set;
-  }());
-}
-
-/*  */
-
 
 var uid$1 = 0;
 
@@ -835,9 +710,9 @@ var VNode = function VNode (
   this.elm = elm;
   this.ns = undefined;
   this.context = context;
-  this.functionalContext = undefined;
-  this.functionalOptions = undefined;
-  this.functionalScopeId = undefined;
+  this.fnContext = undefined;
+  this.fnOptions = undefined;
+  this.fnScopeId = undefined;
   this.key = data && data.key;
   this.componentOptions = componentOptions;
   this.componentInstance = undefined;
@@ -881,6 +756,7 @@ function createTextVNode (val) {
 // multiple renders, cloning them avoids errors when DOM manipulations rely
 // on their elm reference.
 function cloneVNode (vnode, deep) {
+  var componentOptions = vnode.componentOptions;
   var cloned = new VNode(
     vnode.tag,
     vnode.data,
@@ -888,16 +764,24 @@ function cloneVNode (vnode, deep) {
     vnode.text,
     vnode.elm,
     vnode.context,
-    vnode.componentOptions,
+    componentOptions,
     vnode.asyncFactory
   );
   cloned.ns = vnode.ns;
   cloned.isStatic = vnode.isStatic;
   cloned.key = vnode.key;
   cloned.isComment = vnode.isComment;
+  cloned.fnContext = vnode.fnContext;
+  cloned.fnOptions = vnode.fnOptions;
+  cloned.fnScopeId = vnode.fnScopeId;
   cloned.isCloned = true;
-  if (deep && vnode.children) {
-    cloned.children = cloneVNodes(vnode.children);
+  if (deep) {
+    if (vnode.children) {
+      cloned.children = cloneVNodes(vnode.children, true);
+    }
+    if (componentOptions && componentOptions.children) {
+      componentOptions.children = cloneVNodes(componentOptions.children, true);
+    }
   }
   return cloned
 }
@@ -1130,7 +1014,7 @@ function set (target, key, val) {
     target.splice(key, 1, val);
     return val
   }
-  if (hasOwn(target, key)) {
+  if (key in target && !(key in Object.prototype)) {
     target[key] = val;
     return val
   }
@@ -1262,7 +1146,7 @@ function mergeDataOrFn (
         typeof parentVal === 'function' ? parentVal.call(this) : parentVal
       )
     }
-  } else if (parentVal || childVal) {
+  } else {
     return function mergedInstanceDataFn () {
       // instance merge
       var instanceData = typeof childVal === 'function'
@@ -1296,7 +1180,7 @@ strats.data = function (
 
       return parentVal
     }
-    return mergeDataOrFn.call(this, parentVal, childVal)
+    return mergeDataOrFn(parentVal, childVal)
   }
 
   return mergeDataOrFn(parentVal, childVal, vm)
@@ -1770,6 +1654,158 @@ function isType (type, fn) {
 
 /*  */
 
+function handleError (err, vm, info) {
+  if (vm) {
+    var cur = vm;
+    while ((cur = cur.$parent)) {
+      var hooks = cur.$options.errorCaptured;
+      if (hooks) {
+        for (var i = 0; i < hooks.length; i++) {
+          try {
+            var capture = hooks[i].call(cur, err, vm, info) === false;
+            if (capture) { return }
+          } catch (e) {
+            globalHandleError(e, cur, 'errorCaptured hook');
+          }
+        }
+      }
+    }
+  }
+  globalHandleError(err, vm, info);
+}
+
+function globalHandleError (err, vm, info) {
+  if (config.errorHandler) {
+    try {
+      return config.errorHandler.call(null, err, vm, info)
+    } catch (e) {
+      logError(e, null, 'config.errorHandler');
+    }
+  }
+  logError(err, vm, info);
+}
+
+function logError (err, vm, info) {
+  if (process.env.NODE_ENV !== 'production') {
+    warn(("Error in " + info + ": \"" + (err.toString()) + "\""), vm);
+  }
+  /* istanbul ignore else */
+  if ((inBrowser || inWeex) && typeof console !== 'undefined') {
+    console.error(err);
+  } else {
+    throw err
+  }
+}
+
+/*  */
+/* globals MessageChannel */
+
+var callbacks = [];
+var pending = false;
+
+function flushCallbacks () {
+  pending = false;
+  var copies = callbacks.slice(0);
+  callbacks.length = 0;
+  for (var i = 0; i < copies.length; i++) {
+    copies[i]();
+  }
+}
+
+// Here we have async deferring wrappers using both micro and macro tasks.
+// In < 2.4 we used micro tasks everywhere, but there are some scenarios where
+// micro tasks have too high a priority and fires in between supposedly
+// sequential events (e.g. #4521, #6690) or even between bubbling of the same
+// event (#6566). However, using macro tasks everywhere also has subtle problems
+// when state is changed right before repaint (e.g. #6813, out-in transitions).
+// Here we use micro task by default, but expose a way to force macro task when
+// needed (e.g. in event handlers attached by v-on).
+var microTimerFunc;
+var macroTimerFunc;
+var useMacroTask = false;
+
+// Determine (macro) Task defer implementation.
+// Technically setImmediate should be the ideal choice, but it's only available
+// in IE. The only polyfill that consistently queues the callback after all DOM
+// events triggered in the same loop is by using MessageChannel.
+/* istanbul ignore if */
+if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) {
+  macroTimerFunc = function () {
+    setImmediate(flushCallbacks);
+  };
+} else if (typeof MessageChannel !== 'undefined' && (
+  isNative(MessageChannel) ||
+  // PhantomJS
+  MessageChannel.toString() === '[object MessageChannelConstructor]'
+)) {
+  var channel = new MessageChannel();
+  var port = channel.port2;
+  channel.port1.onmessage = flushCallbacks;
+  macroTimerFunc = function () {
+    port.postMessage(1);
+  };
+} else {
+  /* istanbul ignore next */
+  macroTimerFunc = function () {
+    setTimeout(flushCallbacks, 0);
+  };
+}
+
+// Determine MicroTask defer implementation.
+/* istanbul ignore next, $flow-disable-line */
+if (typeof Promise !== 'undefined' && isNative(Promise)) {
+  var p = Promise.resolve();
+  microTimerFunc = function () {
+    p.then(flushCallbacks);
+    // in problematic UIWebViews, Promise.then doesn't completely break, but
+    // it can get stuck in a weird state where callbacks are pushed into the
+    // microtask queue but the queue isn't being flushed, until the browser
+    // needs to do some other work, e.g. handle a timer. Therefore we can
+    // "force" the microtask queue to be flushed by adding an empty timer.
+    if (isIOS) { setTimeout(noop); }
+  };
+} else {
+  // fallback to macro
+  microTimerFunc = macroTimerFunc;
+}
+
+/**
+ * Wrap a function so that if any code inside triggers state change,
+ * the changes are queued using a Task instead of a MicroTask.
+ */
+
+
+function nextTick (cb, ctx) {
+  var _resolve;
+  callbacks.push(function () {
+    if (cb) {
+      try {
+        cb.call(ctx);
+      } catch (e) {
+        handleError(e, ctx, 'nextTick');
+      }
+    } else if (_resolve) {
+      _resolve(ctx);
+    }
+  });
+  if (!pending) {
+    pending = true;
+    if (useMacroTask) {
+      macroTimerFunc();
+    } else {
+      microTimerFunc();
+    }
+  }
+  // $flow-disable-line
+  if (!cb && typeof Promise !== 'undefined') {
+    return new Promise(function (resolve) {
+      _resolve = resolve;
+    })
+  }
+}
+
+/*  */
+
 /* not type checking this file because flow doesn't play well with Proxy */
 
 var initProxy;
@@ -1846,6 +1882,43 @@ if (process.env.NODE_ENV !== 'production') {
   };
 }
 
+/*  */
+
+var seenObjects = new _Set();
+
+/**
+ * Recursively traverse an object to evoke all converted
+ * getters, so that every nested property inside the object
+ * is collected as a "deep" dependency.
+ */
+function traverse (val) {
+  _traverse(val, seenObjects);
+  seenObjects.clear();
+}
+
+function _traverse (val, seen) {
+  var i, keys;
+  var isA = Array.isArray(val);
+  if ((!isA && !isObject(val)) || Object.isFrozen(val)) {
+    return
+  }
+  if (val.__ob__) {
+    var depId = val.__ob__.dep.id;
+    if (seen.has(depId)) {
+      return
+    }
+    seen.add(depId);
+  }
+  if (isA) {
+    i = val.length;
+    while (i--) { _traverse(val[i], seen); }
+  } else {
+    keys = Object.keys(val);
+    i = keys.length;
+    while (i--) { _traverse(val[keys[i]], seen); }
+  }
+}
+
 var mark;
 var measure;
 
@@ -1912,11 +1985,15 @@ function updateListeners (
   remove$$1,
   vm
 ) {
-  var name, cur, old, event;
+  var name, def, cur, old, event;
   for (name in on) {
-    cur = on[name];
+    def = cur = on[name];
     old = oldOn[name];
     event = normalizeEvent(name);
+    if (true && isPlainObject(def)) {
+      cur = def.handler;
+      event.params = def.params;
+    }
     if (isUndef(cur)) {
       process.env.NODE_ENV !== 'production' && warn(
         "Invalid handler for event \"" + (event.name) + "\": got " + String(cur),
@@ -1926,7 +2003,7 @@ function updateListeners (
       if (isUndef(cur.fns)) {
         cur = on[name] = createFnInvoker(cur);
       }
-      add(event.name, cur, event.once, event.capture, event.passive);
+      add(event.name, cur, event.once, event.capture, event.passive, event.params);
     } else if (cur !== old) {
       old.fns = cur;
       on[name] = old;
@@ -1943,6 +2020,9 @@ function updateListeners (
 /*  */
 
 function mergeVNodeHook (def, hookKey, hook) {
+  if (def instanceof VNode) {
+    def = def.data.hook || (def.data.hook = {});
+  }
   var invoker;
   var oldHook = def[hookKey];
 
@@ -2310,6 +2390,7 @@ function updateComponentListeners (
 ) {
   target = vm;
   updateListeners(listeners, oldListeners || {}, add, remove$1, vm);
+  target = undefined;
 }
 
 function eventsMixin (Vue) {
@@ -2365,7 +2446,7 @@ function eventsMixin (Vue) {
     if (!cbs) {
       return vm
     }
-    if (arguments.length === 1) {
+    if (!fn) {
       vm._events[event] = null;
       return vm
     }
@@ -2427,7 +2508,6 @@ function resolveSlots (
   if (!children) {
     return slots
   }
-  var defaultSlot = [];
   for (var i = 0, l = children.length; i < l; i++) {
     var child = children[i];
     var data = child.data;
@@ -2437,7 +2517,7 @@ function resolveSlots (
     }
     // named slots should only be respected if the vnode was rendered in the
     // same context.
-    if ((child.context === context || child.functionalContext === context) &&
+    if ((child.context === context || child.fnContext === context) &&
       data && data.slot != null
     ) {
       var name = child.data.slot;
@@ -2448,18 +2528,20 @@ function resolveSlots (
         slot.push(child);
       }
     } else {
-      defaultSlot.push(child);
+      (slots.default || (slots.default = [])).push(child);
     }
   }
-  // ignore whitespace
-  if (!defaultSlot.every(isWhitespace)) {
-    slots.default = defaultSlot;
+  // ignore slots that contains only whitespace
+  for (var name$1 in slots) {
+    if (slots[name$1].every(isWhitespace)) {
+      delete slots[name$1];
+    }
   }
   return slots
 }
 
 function isWhitespace (node) {
-  return node.isComment || node.text === ' '
+  return (node.isComment && !node.asyncFactory) || node.text === ' '
 }
 
 function resolveScopedSlots (
@@ -2655,7 +2737,10 @@ function mountComponent (
     };
   }
 
-  vm._watcher = new Watcher(vm, updateComponent, noop);
+  // we set this to vm._watcher inside the watcher's constructor
+  // since the watcher's initial patch may call $forceUpdate (e.g. inside child
+  // component's mounted hook), which relies on vm._watcher being already defined
+  new Watcher(vm, updateComponent, noop, null, true /* isRenderWatcher */);
   hydrating = false;
 
   // manually mounted instance, call mounted on self
@@ -2942,9 +3027,13 @@ var Watcher = function Watcher (
   vm,
   expOrFn,
   cb,
-  options
+  options,
+  isRenderWatcher
 ) {
   this.vm = vm;
+  if (isRenderWatcher) {
+    vm._watcher = this;
+  }
   vm._watchers.push(this);
   // options
   if (options) {
@@ -3138,40 +3227,6 @@ Watcher.prototype.teardown = function teardown () {
   }
 };
 
-/**
- * Recursively traverse an object to evoke all converted
- * getters, so that every nested property inside the object
- * is collected as a "deep" dependency.
- */
-var seenObjects = new _Set();
-function traverse (val) {
-  seenObjects.clear();
-  _traverse(val, seenObjects);
-}
-
-function _traverse (val, seen) {
-  var i, keys;
-  var isA = Array.isArray(val);
-  if ((!isA && !isObject(val)) || !Object.isExtensible(val)) {
-    return
-  }
-  if (val.__ob__) {
-    var depId = val.__ob__.dep.id;
-    if (seen.has(depId)) {
-      return
-    }
-    seen.add(depId);
-  }
-  if (isA) {
-    i = val.length;
-    while (i--) { _traverse(val[i], seen); }
-  } else {
-    keys = Object.keys(val);
-    i = keys.length;
-    while (i--) { _traverse(val[keys[i]], seen); }
-  }
-}
-
 /*  */
 
 var sharedPropertyDefinition = {
@@ -3617,6 +3672,7 @@ function renderSlot (
   bindObject
 ) {
   var scopedSlotFn = this.$scopedSlots[name];
+  var nodes;
   if (scopedSlotFn) { // scoped slot
     props = props || {};
     if (bindObject) {
@@ -3628,19 +3684,28 @@ function renderSlot (
       }
       props = extend(extend({}, bindObject), props);
     }
-    return scopedSlotFn(props) || fallback
+    nodes = scopedSlotFn(props) || fallback;
   } else {
     var slotNodes = this.$slots[name];
     // warn duplicate slot usage
-    if (slotNodes && process.env.NODE_ENV !== 'production') {
-      slotNodes._rendered && warn(
-        "Duplicate presence of slot \"" + name + "\" found in the same render tree " +
-        "- this will likely cause render errors.",
-        this
-      );
+    if (slotNodes) {
+      if (process.env.NODE_ENV !== 'production' && slotNodes._rendered) {
+        warn(
+          "Duplicate presence of slot \"" + name + "\" found in the same render tree " +
+          "- this will likely cause render errors.",
+          this
+        );
+      }
       slotNodes._rendered = true;
     }
-    return slotNodes || fallback
+    nodes = slotNodes || fallback;
+  }
+
+  var target = props && props.slot;
+  if (target) {
+    return this.$createElement('template', { slot: target }, nodes)
+  } else {
+    return nodes
   }
 }
 
@@ -3739,12 +3804,19 @@ function bindObjectProps (
  */
 function renderStatic (
   index,
-  isInFor
+  isInFor,
+  isOnce
 ) {
-  // static trees can be rendered once and cached on the contructor options
-  // so every instance shares the same cached trees
+  // render fns generated by compiler < 2.5.4 does not provide v-once
+  // information to runtime so be conservative
+  var isOldVersion = arguments.length < 3;
+  // if a static tree is generated by v-once, it is cached on the instance;
+  // otherwise it is purely static and can be cached on the shared options
+  // across all instances.
   var renderFns = this.$options.staticRenderFns;
-  var cached = renderFns.cached || (renderFns.cached = []);
+  var cached = isOldVersion || isOnce
+    ? (this._staticTrees || (this._staticTrees = []))
+    : (renderFns.cached || (renderFns.cached = []));
   var tree = cached[index];
   // if has already-rendered static tree and not inside v-for,
   // we can reuse the same tree by doing a shallow clone.
@@ -3872,8 +3944,8 @@ function FunctionalRenderContext (
     this._c = function (a, b, c, d) {
       var vnode = createElement(contextVm, a, b, c, d, needNormalization);
       if (vnode) {
-        vnode.functionalScopeId = options._scopeId;
-        vnode.functionalContext = parent;
+        vnode.fnScopeId = options._scopeId;
+        vnode.fnContext = parent;
       }
       return vnode
     };
@@ -3914,8 +3986,8 @@ function createFunctionalComponent (
   var vnode = options.render.call(null, renderContext._c, renderContext);
 
   if (vnode instanceof VNode) {
-    vnode.functionalContext = contextVm;
-    vnode.functionalOptions = options;
+    vnode.fnContext = contextVm;
+    vnode.fnOptions = options;
     if (data.slot) {
       (vnode.data || (vnode.data = {})).slot = data.slot;
     }
@@ -4050,6 +4122,21 @@ function createComponent (
 
   data = data || {};
 
+  // recycle-list optimized render function for extracting cell-slot
+  // template. This is essentially inline expanding instead of creating
+  // an actual instance.
+  // https://github.com/Hanks10100/weex-native-directive/tree/master/component
+  if (true && data.attrs && data.attrs['@isInRecycleList']) {
+    var altRender = Ctor.options['@render'];
+    if (altRender) {
+      return altRender.call(
+        context,
+        context.$createElement,
+        data.attrs
+      )
+    }
+  }
+
   // resolve constructor options in case global mixins are applied after
   // component constructor creation
   resolveConstructorOptions(Ctor);
@@ -4212,11 +4299,13 @@ function _createElement (
   if (process.env.NODE_ENV !== 'production' &&
     isDef(data) && isDef(data.key) && !isPrimitive(data.key)
   ) {
-    warn(
-      'Avoid using non-primitive value as key, ' +
-      'use string/number value instead.',
-      context
-    );
+    if (!true || !('@binding' in data.key)) {
+      warn(
+        'Avoid using non-primitive value as key, ' +
+        'use string/number value instead.',
+        context
+      );
+    }
   }
   // support single function children as default scoped slot
   if (Array.isArray(children) &&
@@ -4286,6 +4375,7 @@ function applyNS (vnode, ns, force) {
 
 function initRender (vm) {
   vm._vnode = null; // the root of the child tree
+  vm._staticTrees = null; // v-once cached trees
   var options = vm.$options;
   var parentVnode = vm.$vnode = options._parentVnode; // the placeholder node in parent tree
   var renderContext = parentVnode && parentVnode.context;
@@ -4337,7 +4427,9 @@ function renderMixin (Vue) {
       // last render. They need to be cloned to ensure "freshness" for this render.
       for (var key in vm.$slots) {
         var slot = vm.$slots[key];
-        if (slot._rendered) {
+        // _rendered is a flag added by renderSlot, but may not be present
+        // if the slot is passed from manually written render functions
+        if (slot._rendered || (slot[0] && slot[0].elm)) {
           vm.$slots[key] = cloneVNodes(slot, true /* deep */);
         }
       }
@@ -4747,7 +4839,7 @@ function pruneCacheEntry (
   current
 ) {
   var cached$$1 = cache[key];
-  if (cached$$1 && cached$$1 !== current) {
+  if (cached$$1 && (!current || cached$$1.tag !== current.tag)) {
     cached$$1.componentInstance.$destroy();
   }
   cache[key] = null;
@@ -4789,21 +4881,27 @@ var KeepAlive = {
   },
 
   render: function render () {
-    var vnode = getFirstComponentChild(this.$slots.default);
+    var slot = this.$slots.default;
+    var vnode = getFirstComponentChild(slot);
     var componentOptions = vnode && vnode.componentOptions;
     if (componentOptions) {
       // check pattern
       var name = getComponentName(componentOptions);
-      if (name && (
-        (this.include && !matches(this.include, name)) ||
-        (this.exclude && matches(this.exclude, name))
-      )) {
+      var ref = this;
+      var include = ref.include;
+      var exclude = ref.exclude;
+      if (
+        // not included
+        (include && (!name || !matches(include, name))) ||
+        // excluded
+        (exclude && name && matches(exclude, name))
+      ) {
         return vnode
       }
 
-      var ref = this;
-      var cache = ref.cache;
-      var keys = ref.keys;
+      var ref$1 = this;
+      var cache = ref$1.cache;
+      var keys = ref$1.keys;
       var key = vnode.key == null
         // same constructor may get registered as different local components
         // so cid alone is not enough (#3269)
@@ -4825,7 +4923,7 @@ var KeepAlive = {
 
       vnode.data.keepAlive = true;
     }
-    return vnode
+    return vnode || (slot && slot[0])
   }
 };
 
@@ -4892,7 +4990,7 @@ Object.defineProperty(Vue$2.prototype, '$ssrContext', {
   }
 });
 
-Vue$2.version = '2.5.0';
+Vue$2.version = '2.5.8';
 
 var latestNodeId = 1;
 
@@ -5171,7 +5269,23 @@ function createPatchFunction (backend) {
     }
   }
 
-  var inPre = 0;
+  function isUnknownElement$$1 (vnode, inVPre) {
+    return (
+      !inVPre &&
+      !vnode.ns &&
+      !(
+        config.ignoredElements.length &&
+        config.ignoredElements.some(function (ignore) {
+          return isRegExp(ignore)
+            ? ignore.test(vnode.tag)
+            : ignore === vnode.tag
+        })
+      ) &&
+      config.isUnknownElement(vnode.tag)
+    )
+  }
+
+  var creatingElmInVPre = 0;
   function createElm (vnode, insertedVnodeQueue, parentElm, refElm, nested) {
     vnode.isRootInsert = !nested; // for transition enter check
     if (createComponent(vnode, insertedVnodeQueue, parentElm, refElm)) {
@@ -5184,21 +5298,9 @@ function createPatchFunction (backend) {
     if (isDef(tag)) {
       if (process.env.NODE_ENV !== 'production') {
         if (data && data.pre) {
-          inPre++;
+          creatingElmInVPre++;
         }
-        if (
-          !inPre &&
-          !vnode.ns &&
-          !(
-            config.ignoredElements.length &&
-            config.ignoredElements.some(function (ignore) {
-              return isRegExp(ignore)
-                ? ignore.test(tag)
-                : ignore === tag
-            })
-          ) &&
-          config.isUnknownElement(tag)
-        ) {
+        if (isUnknownElement$$1(vnode, creatingElmInVPre)) {
           warn(
             'Unknown custom element: <' + tag + '> - did you ' +
             'register the component correctly? For recursive components, ' +
@@ -5234,7 +5336,7 @@ function createPatchFunction (backend) {
       }
 
       if (process.env.NODE_ENV !== 'production' && data && data.pre) {
-        inPre--;
+        creatingElmInVPre--;
       }
     } else if (isTrue(vnode.isComment)) {
       vnode.elm = nodeOps.createComment(vnode.text);
@@ -5351,7 +5453,7 @@ function createPatchFunction (backend) {
   // of going through the normal attribute patching process.
   function setScope (vnode) {
     var i;
-    if (isDef(i = vnode.functionalScopeId)) {
+    if (isDef(i = vnode.fnScopeId)) {
       nodeOps.setAttribute(vnode.elm, i, '');
     } else {
       var ancestor = vnode;
@@ -5365,7 +5467,7 @@ function createPatchFunction (backend) {
     // for slot content they should also get the scopeId from the host instance.
     if (isDef(i = activeInstance) &&
       i !== vnode.context &&
-      i !== vnode.functionalContext &&
+      i !== vnode.fnContext &&
       isDef(i = i.$options._scopeId)
     ) {
       nodeOps.setAttribute(vnode.elm, i, '');
@@ -5589,27 +5691,32 @@ function createPatchFunction (backend) {
     }
   }
 
-  var bailed = false;
+  var hydrationBailed = false;
   // list of modules that can skip create hook during hydration because they
   // are already rendered on the client or has no need for initialization
-  var isRenderedModule = makeMap('attrs,style,class,staticClass,staticStyle,key');
+  // Note: style is excluded because it relies on initial clone for future
+  // deep updates (#7063).
+  var isRenderedModule = makeMap('attrs,class,staticClass,staticStyle,key');
 
   // Note: this is a browser-only function so we can assume elms are DOM nodes.
-  function hydrate (elm, vnode, insertedVnodeQueue) {
+  function hydrate (elm, vnode, insertedVnodeQueue, inVPre) {
+    var i;
+    var tag = vnode.tag;
+    var data = vnode.data;
+    var children = vnode.children;
+    inVPre = inVPre || (data && data.pre);
+    vnode.elm = elm;
+
     if (isTrue(vnode.isComment) && isDef(vnode.asyncFactory)) {
-      vnode.elm = elm;
       vnode.isAsyncPlaceholder = true;
       return true
     }
+    // assert node match
     if (process.env.NODE_ENV !== 'production') {
-      if (!assertNodeMatch(elm, vnode)) {
+      if (!assertNodeMatch(elm, vnode, inVPre)) {
         return false
       }
     }
-    vnode.elm = elm;
-    var tag = vnode.tag;
-    var data = vnode.data;
-    var children = vnode.children;
     if (isDef(data)) {
       if (isDef(i = data.hook) && isDef(i = i.init)) { i(vnode, true /* hydrating */); }
       if (isDef(i = vnode.componentInstance)) {
@@ -5630,9 +5737,9 @@ function createPatchFunction (backend) {
               /* istanbul ignore if */
               if (process.env.NODE_ENV !== 'production' &&
                 typeof console !== 'undefined' &&
-                !bailed
+                !hydrationBailed
               ) {
-                bailed = true;
+                hydrationBailed = true;
                 console.warn('Parent: ', elm);
                 console.warn('server innerHTML: ', i);
                 console.warn('client innerHTML: ', elm.innerHTML);
@@ -5644,7 +5751,7 @@ function createPatchFunction (backend) {
             var childrenMatch = true;
             var childNode = elm.firstChild;
             for (var i$1 = 0; i$1 < children.length; i$1++) {
-              if (!childNode || !hydrate(childNode, children[i$1], insertedVnodeQueue)) {
+              if (!childNode || !hydrate(childNode, children[i$1], insertedVnodeQueue, inVPre)) {
                 childrenMatch = false;
                 break
               }
@@ -5656,9 +5763,9 @@ function createPatchFunction (backend) {
               /* istanbul ignore if */
               if (process.env.NODE_ENV !== 'production' &&
                 typeof console !== 'undefined' &&
-                !bailed
+                !hydrationBailed
               ) {
-                bailed = true;
+                hydrationBailed = true;
                 console.warn('Parent: ', elm);
                 console.warn('Mismatching childNodes vs. VNodes: ', elm.childNodes, children);
               }
@@ -5668,12 +5775,18 @@ function createPatchFunction (backend) {
         }
       }
       if (isDef(data)) {
+        var fullInvoke = false;
         for (var key in data) {
           if (!isRenderedModule(key)) {
+            fullInvoke = true;
             invokeCreateHooks(vnode, insertedVnodeQueue);
             break
           }
         }
+        if (!fullInvoke && data['class']) {
+          // ensure collecting deps for deep class bindings for future updates
+          traverse(data['class']);
+        }
       }
     } else if (elm.data !== vnode.text) {
       elm.data = vnode.text;
@@ -5681,10 +5794,10 @@ function createPatchFunction (backend) {
     return true
   }
 
-  function assertNodeMatch (node, vnode) {
+  function assertNodeMatch (node, vnode, inVPre) {
     if (isDef(vnode.tag)) {
-      return (
-        vnode.tag.indexOf('vue-component') === 0 ||
+      return vnode.tag.indexOf('vue-component') === 0 || (
+        !isUnknownElement$$1(vnode, inVPre) &&
         vnode.tag.toLowerCase() === (node.tagName && node.tagName.toLowerCase())
       )
     } else {
@@ -5737,9 +5850,12 @@ function createPatchFunction (backend) {
           // create an empty node and replace it
           oldVnode = emptyNodeAt(oldVnode);
         }
+
         // replacing existing element
         var oldElm = oldVnode.elm;
         var parentElm$1 = nodeOps.parentNode(oldElm);
+
+        // create new node
         createElm(
           vnode,
           insertedVnodeQueue,
@@ -5750,9 +5866,8 @@ function createPatchFunction (backend) {
           nodeOps.nextSibling(oldElm)
         );
 
+        // update parent placeholder node element, recursively
         if (isDef(vnode.parent)) {
-          // component root element replaced.
-          // update parent placeholder node element, recursively
           var ancestor = vnode.parent;
           var patchable = isPatchable(vnode);
           while (ancestor) {
@@ -5781,6 +5896,7 @@ function createPatchFunction (backend) {
           }
         }
 
+        // destroy old node
         if (isDef(parentElm$1)) {
           removeVnodes(parentElm$1, [oldVnode], 0, 0);
         } else if (isDef(oldVnode.tag)) {
@@ -5846,14 +5962,14 @@ function _update (oldVnode, vnode) {
       }
     };
     if (isCreate) {
-      mergeVNodeHook(vnode.data.hook || (vnode.data.hook = {}), 'insert', callInsert);
+      mergeVNodeHook(vnode, 'insert', callInsert);
     } else {
       callInsert();
     }
   }
 
   if (dirsWithPostpatch.length) {
-    mergeVNodeHook(vnode.data.hook || (vnode.data.hook = {}), 'postpatch', function () {
+    mergeVNodeHook(vnode, 'postpatch', function () {
       for (var i = 0; i < dirsWithPostpatch.length; i++) {
         callHook$1(dirsWithPostpatch[i], 'componentUpdated', vnode, oldVnode);
       }
@@ -5927,18 +6043,27 @@ function updateAttrs (oldVnode, vnode) {
     attrs = vnode.data.attrs = extend({}, attrs);
   }
 
+  var supportBatchUpdate = typeof elm.setAttrs === 'function';
+  var batchedAttrs = {};
   for (key in attrs) {
     cur = attrs[key];
     old = oldAttrs[key];
     if (old !== cur) {
-      elm.setAttr(key, cur);
+      supportBatchUpdate
+        ? (batchedAttrs[key] = cur)
+        : elm.setAttr(key, cur);
     }
   }
   for (key in oldAttrs) {
     if (attrs[key] == null) {
-      elm.setAttr(key);
+      supportBatchUpdate
+        ? (batchedAttrs[key] = undefined)
+        : elm.setAttr(key);
     }
   }
+  if (supportBatchUpdate) {
+    elm.setAttrs(batchedAttrs);
+  }
 }
 
 var attrs = {
@@ -5982,8 +6107,12 @@ function updateClass (oldVnode, vnode) {
   }
 
   var style = getStyle(oldClassList, classList, ctx);
-  for (var key in style) {
-    el.setStyle(key, style[key]);
+  if (typeof el.setStyles === 'function') {
+    el.setStyles(style);
+  } else {
+    for (var key in style) {
+      el.setStyle(key, style[key]);
+    }
   }
 }
 
@@ -6020,7 +6149,9 @@ function add$1 (
   event,
   handler,
   once,
-  capture
+  capture,
+  passive,
+  params
 ) {
   if (capture) {
     console.log('Weex do not support event in bubble phase.');
@@ -6038,7 +6169,7 @@ function add$1 (
       }
     };
   }
-  target$1.addEvent(event, handler);
+  target$1.addEvent(event, handler, params);
 }
 
 function remove$2 (
@@ -6058,6 +6189,7 @@ function updateDOMListeners (oldVnode, vnode) {
   var oldOn = oldVnode.data.on || {};
   target$1 = vnode.elm;
   updateListeners(on, oldOn, add$1, remove$2, vnode.context);
+  target$1 = undefined;
 }
 
 var events = {
@@ -6076,11 +6208,18 @@ function createStyle (oldVnode, vnode) {
   }
   var elm = vnode.elm;
   var staticStyle = vnode.data.staticStyle;
+  var supportBatchUpdate = typeof elm.setStyles === 'function';
+  var batchedStyles = {};
   for (var name in staticStyle) {
     if (staticStyle[name]) {
-      elm.setStyle(normalize(name), staticStyle[name]);
+      supportBatchUpdate
+        ? (batchedStyles[normalize(name)] = staticStyle[name])
+        : elm.setStyle(normalize(name), staticStyle[name]);
     }
   }
+  if (supportBatchUpdate) {
+    elm.setStyles(batchedStyles);
+  }
   updateStyle(oldVnode, vnode);
 }
 
@@ -6106,14 +6245,23 @@ function updateStyle (oldVnode, vnode) {
     style = vnode.data.style = extend({}, style);
   }
 
+  var supportBatchUpdate = typeof elm.setStyles === 'function';
+  var batchedStyles = {};
   for (name in oldStyle) {
     if (!style[name]) {
-      elm.setStyle(normalize(name), '');
+      supportBatchUpdate
+        ? (batchedStyles[normalize(name)] = '')
+        : elm.setStyle(normalize(name), '');
     }
   }
   for (name in style) {
     cur = style[name];
-    elm.setStyle(normalize(name), cur);
+    supportBatchUpdate
+      ? (batchedStyles[normalize(name)] = cur)
+      : elm.setStyle(normalize(name), cur);
+  }
+  if (supportBatchUpdate) {
+    elm.setStyles(batchedStyles);
   }
 }
 
@@ -6302,8 +6450,12 @@ function enter (_, vnode) {
   beforeEnterHook && beforeEnterHook(el);
 
   if (startState) {
-    for (var key in startState) {
-      el.setStyle(key, startState[key]);
+    if (typeof el.setStyles === 'function') {
+      el.setStyles(startState);
+    } else {
+      for (var key in startState) {
+        el.setStyle(key, startState[key]);
+      }
     }
   }
 
@@ -6469,6 +6621,8 @@ var patch = createPatchFunction({
 var platformDirectives = {
 };
 
+/*  */
+
 function getVNodeType (vnode) {
   if (!vnode.tag) {
     return ''
@@ -6477,29 +6631,20 @@ function getVNodeType (vnode) {
 }
 
 function isSimpleSpan (vnode) {
-  return vnode.children && vnode.children.length === 1 && !vnode.children[0].tag
-}
-
-var cssLengthRE = /^([+-]?[0-9]+(\.[0-9]+)?)(px|em|ex|%|in|cm|mm|pt|pc)$/i;
-function trimCSSUnit (prop) {
-  var res = String(prop).match(cssLengthRE);
-  if (res) {
-    return Number(res[1])
-  }
-  return prop
+  return vnode.children &&
+    vnode.children.length === 1 &&
+    !vnode.children[0].tag
 }
 
 function parseStyle (vnode) {
   if (!vnode || !vnode.data) {
     return
   }
-
   var ref = vnode.data;
   var staticStyle = ref.staticStyle;
   var staticClass = ref.staticClass;
   if (vnode.data.style || vnode.data.class || staticStyle || staticClass) {
     var styles = Object.assign({}, staticStyle, vnode.data.style);
-
     var cssMap = vnode.context.$options.style || {};
     var classList = [].concat(staticClass, vnode.data.class);
     classList.forEach(function (name) {
@@ -6507,10 +6652,6 @@ function parseStyle (vnode) {
         Object.assign(styles, cssMap[name]);
       }
     });
-
-    for (var key in styles) {
-      styles[key] = trimCSSUnit(styles[key]);
-    }
     return styles
   }
 }
@@ -6538,7 +6679,6 @@ function convertVNodeChildren (children) {
           props.events = vnode.data.on;
         }
       }
-
       if (type === 'span' && isSimpleSpan(vnode)) {
         props.attr = props.attr || {};
         props.attr.value = vnode.children[0].text.trim();
@@ -6556,7 +6696,6 @@ function convertVNodeChildren (children) {
 
 var Richtext = {
   name: 'richtext',
-  // abstract: true,
   render: function render (h) {
     return h('weex:richtext', {
       on: this._events,
@@ -6645,7 +6784,7 @@ var Transition$1 = {
   render: function render (h) {
     var this$1 = this;
 
-    var children = this.$options._renderChildren;
+    var children = this.$slots.default;
     if (!children) {
       return
     }
@@ -6724,7 +6863,9 @@ var Transition$1 = {
       oldChild &&
       oldChild.data &&
       !isSameChild(child, oldChild) &&
-      !isAsyncPlaceholder(oldChild)
+      !isAsyncPlaceholder(oldChild) &&
+      // #6687 component root is a comment node
+      !(oldChild.componentInstance && oldChild.componentInstance._vnode.isComment)
     ) {
       // replace old child transition data with fresh one
       // important for dynamic transitions!
@@ -6928,7 +7069,7 @@ var canBeLeftOpenTag = makeMap(
 );
 
 var isRuntimeComponent = makeMap(
-  'richtext,trisition,trisition-group',
+  'richtext,transition,transition-group',
   true
 );
 
diff --git a/packages/weex-vue-framework/index.js b/packages/weex-vue-framework/index.js
index acd095e..04b1efa 100644
--- a/packages/weex-vue-framework/index.js
+++ b/packages/weex-vue-framework/index.js
@@ -125,59 +125,6 @@ function getRoot (instanceId) {
   return instance.app.$el.toJSON()
 }
 
-var jsHandlers = {
-  fireEvent: function (id) {
-    var args = [], len = arguments.length - 1;
-    while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ];
-
-    return fireEvent.apply(void 0, [ instances[id] ].concat( args ))
-  },
-  callback: function (id) {
-    var args = [], len = arguments.length - 1;
-    while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ];
-
-    return callback.apply(void 0, [ instances[id] ].concat( args ))
-  }
-};
-
-function fireEvent (instance, nodeId, type, e, domChanges) {
-  var el = instance.document.getRef(nodeId);
-  if (el) {
-    return instance.document.fireEvent(el, type, e, domChanges)
-  }
-  return new Error(("invalid element reference \"" + nodeId + "\""))
-}
-
-function callback (instance, callbackId, data, ifKeepAlive) {
-  var result = instance.document.taskCenter.callback(callbackId, data, ifKeepAlive);
-  instance.document.taskCenter.send('dom', { action: 'updateFinish' }, []);
-  return result
-}
-
-/**
- * Accept calls from native (event or callback).
- *
- * @param  {string} id
- * @param  {array} tasks list with `method` and `args`
- */
-function receiveTasks (id, tasks) {
-  var instance = instances[id];
-  if (instance && Array.isArray(tasks)) {
-    var results = [];
-    tasks.forEach(function (task) {
-      var handler = jsHandlers[task.method];
-      var args = [].concat( task.args );
-      /* istanbul ignore else */
-      if (typeof handler === 'function') {
-        args.unshift(id);
-        results.push(handler.apply(void 0, args));
-      }
-    });
-    return results
-  }
-  return new Error(("invalid instance id \"" + id + "\" or tasks"))
-}
-
 /**
  * Create a fresh instance of Vue for each Weex instance.
  */
@@ -309,4 +256,3 @@ exports.createInstance = createInstance;
 exports.destroyInstance = destroyInstance;
 exports.refreshInstance = refreshInstance;
 exports.getRoot = getRoot;
-exports.receiveTasks = receiveTasks;
diff --git a/src/compiler/codegen/events.js b/src/compiler/codegen/events.js
index b15d931..7bfe5ec 100644
--- a/src/compiler/codegen/events.js
+++ b/src/compiler/codegen/events.js
@@ -41,18 +41,7 @@ export function genHandlers (
 ): string {
   let res = isNative ? 'nativeOn:{' : 'on:{'
   for (const name in events) {
-    const handler = events[name]
-    // #5330: warn click.right, since right clicks do not actually fire click events.
-    if (process.env.NODE_ENV !== 'production' &&
-      name === 'click' &&
-      handler && handler.modifiers && handler.modifiers.right
-    ) {
-      warn(
-        `Use "contextmenu" instead of "click.right" since right clicks ` +
-        `do not actually fire "click" events.`
-      )
-    }
-    res += `"${name}":${genHandler(name, handler)},`
+    res += `"${name}":${genHandler(name, events[name])},`
   }
   return res.slice(0, -1) + '}'
 }
diff --git a/src/compiler/codegen/index.js b/src/compiler/codegen/index.js
index 17b31e5..7b8a182 100644
--- a/src/compiler/codegen/index.js
+++ b/src/compiler/codegen/index.js
@@ -86,10 +86,16 @@ export function genElement (el: ASTElement, state: CodegenState): string {
 }
 
 // hoist static sub-trees out
-function genStatic (el: ASTElement, state: CodegenState): string {
+function genStatic (el: ASTElement, state: CodegenState, once: ?boolean): string {
   el.staticProcessed = true
   state.staticRenderFns.push(`with(this){return ${genElement(el, state)}}`)
-  return `_m(${state.staticRenderFns.length - 1}${el.staticInFor ? ',true' : ''})`
+  return `_m(${
+    state.staticRenderFns.length - 1
+  },${
+    el.staticInFor ? 'true' : 'false'
+  },${
+    once ? 'true' : 'false'
+  })`
 }
 
 // v-once
@@ -115,7 +121,7 @@ function genOnce (el: ASTElement, state: CodegenState): string {
     }
     return `_o(${genElement(el, state)},${state.onceId++},${key})`
   } else {
-    return genStatic(el, state)
+    return genStatic(el, state, true)
   }
 }
 
diff --git a/src/compiler/error-detector.js b/src/compiler/error-detector.js
index 6321f4f..e729c49 100644
--- a/src/compiler/error-detector.js
+++ b/src/compiler/error-detector.js
@@ -15,9 +15,6 @@ const unaryOperatorsRE = new RegExp('\\b' + (
   'delete,typeof,void'
 ).split(',').join('\\s*\\([^\\)]*\\)|\\b') + '\\s*\\([^\\)]*\\)')
 
-// check valid identifier for v-for
-const identRE = /[A-Za-z_$][\w$]*/
-
 // strip strings in expressions
 const stripStringRE = /'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"|`(?:[^`\\]|\\.)*\$\{|\}(?:[^`\\]|\\.)*`|`(?:[^`\\]|\\.)*`/g
 
@@ -75,9 +72,18 @@ function checkFor (node: ASTElement, text: string, errors: Array<string>) {
   checkIdentifier(node.iterator2, 'v-for iterator', text, errors)
 }
 
-function checkIdentifier (ident: ?string, type: string, text: string, errors: Array<string>) {
-  if (typeof ident === 'string' && !identRE.test(ident)) {
-    errors.push(`invalid ${type} "${ident}" in expression: ${text.trim()}`)
+function checkIdentifier (
+  ident: ?string,
+  type: string,
+  text: string,
+  errors: Array<string>
+) {
+  if (typeof ident === 'string') {
+    try {
+      new Function(`var ${ident}=_`)
+    } catch (e) {
+      errors.push(`invalid ${type} "${ident}" in expression: ${text.trim()}`)
+    }
   }
 }
 
diff --git a/src/compiler/helpers.js b/src/compiler/helpers.js
index 5c844bd..1349fa3 100644
--- a/src/compiler/helpers.js
+++ b/src/compiler/helpers.js
@@ -1,5 +1,6 @@
 /* @flow */
 
+import { emptyObject } from 'shared/util'
 import { parseFilters } from './parser/filter-parser'
 
 export function baseWarn (msg: string) {
@@ -42,39 +43,59 @@ export function addHandler (
   important?: boolean,
   warn?: Function
 ) {
+  modifiers = modifiers || emptyObject
   // warn prevent and passive modifier
   /* istanbul ignore if */
   if (
     process.env.NODE_ENV !== 'production' && warn &&
-    modifiers && modifiers.prevent && modifiers.passive
+    modifiers.prevent && modifiers.passive
   ) {
     warn(
       'passive and prevent can\'t be used together. ' +
       'Passive handler can\'t prevent default event.'
     )
   }
+
   // check capture modifier
-  if (modifiers && modifiers.capture) {
+  if (modifiers.capture) {
     delete modifiers.capture
     name = '!' + name // mark the event as captured
   }
-  if (modifiers && modifiers.once) {
+  if (modifiers.once) {
     delete modifiers.once
     name = '~' + name // mark the event as once
   }
   /* istanbul ignore if */
-  if (modifiers && modifiers.passive) {
+  if (modifiers.passive) {
     delete modifiers.passive
     name = '&' + name // mark the event as passive
   }
+
+  // normalize click.right and click.middle since they don't actually fire
+  // this is technically browser-specific, but at least for now browsers are
+  // the only target envs that have right/middle clicks.
+  if (name === 'click') {
+    if (modifiers.right) {
+      name = 'contextmenu'
+      delete modifiers.right
+    } else if (modifiers.middle) {
+      name = 'mouseup'
+    }
+  }
+
   let events
-  if (modifiers && modifiers.native) {
+  if (modifiers.native) {
     delete modifiers.native
     events = el.nativeEvents || (el.nativeEvents = {})
   } else {
     events = el.events || (el.events = {})
   }
-  const newHandler = { value, modifiers }
+
+  const newHandler: any = { value }
+  if (modifiers !== emptyObject) {
+    newHandler.modifiers = modifiers
+  }
+
   const handlers = events[name]
   /* istanbul ignore if */
   if (Array.isArray(handlers)) {
diff --git a/src/compiler/parser/html-parser.js b/src/compiler/parser/html-parser.js
index f9f78d5..86955e0 100644
--- a/src/compiler/parser/html-parser.js
+++ b/src/compiler/parser/html-parser.js
@@ -39,10 +39,11 @@ const decodingMap = {
   '>': '>',
   '"': '"',
   '&': '&',
-  '
': '\n'
+  '
': '\n',
+  '	': '\t'
 }
 const encodedAttr = /&(?:lt|gt|quot|amp);/g
-const encodedAttrWithNewLines = /&(?:lt|gt|quot|amp|#10);/g
+const encodedAttrWithNewLines = /&(?:lt|gt|quot|amp|#10|#9);/g
 
 // #5992
 const isIgnoreNewlineTag = makeMap('pre,textarea', true)
@@ -233,12 +234,12 @@ export function parseHTML (html, options) {
         if (args[5] === '') { delete args[5] }
       }
       const value = args[3] || args[4] || args[5] || ''
+      const shouldDecodeNewlines = tagName === 'a' && args[1] === 'href'
+        ? options.shouldDecodeNewlinesForHref
+        : options.shouldDecodeNewlines
       attrs[i] = {
         name: args[1],
-        value: decodeAttr(
-          value,
-          options.shouldDecodeNewlines
-        )
+        value: decodeAttr(value, shouldDecodeNewlines)
       }
     }
 
diff --git a/src/compiler/parser/index.js b/src/compiler/parser/index.js
index ceedce7..e971524 100644
--- a/src/compiler/parser/index.js
+++ b/src/compiler/parser/index.js
@@ -22,7 +22,8 @@ import {
 export const onRE = /^@|^v-on:/
 export const dirRE = /^v-|^@|^:/
 export const forAliasRE = /(.*?)\s+(?:in|of)\s+(.*)/
-export const forIteratorRE = /\((\{[^}]*\}|[^,]*),([^,]*)(?:,([^,]*))?\)/
+export const forIteratorRE = /\((\{[^}]*\}|[^,{]*),([^,]*)(?:,([^,]*))?\)/
+const stripParensRE = /^\(|\)$/g
 
 const argRE = /:(.*)$/
 const bindRE = /^:|^v-bind:/
@@ -107,6 +108,7 @@ export function parse (
     isUnaryTag: options.isUnaryTag,
     canBeLeftOpenTag: options.canBeLeftOpenTag,
     shouldDecodeNewlines: options.shouldDecodeNewlines,
+    shouldDecodeNewlinesForHref: options.shouldDecodeNewlinesForHref,
     shouldKeepComment: options.comments,
     start (tag, attrs, unary) {
       // check namespace.
@@ -363,7 +365,7 @@ export function processFor (el: ASTElement) {
         el.iterator2 = iteratorMatch[3].trim()
       }
     } else {
-      el.alias = alias
+      el.alias = alias.replace(stripParensRE, '')
     }
   }
 }
@@ -459,6 +461,15 @@ function processSlot (el) {
       }
       el.slotScope = slotScope || getAndRemoveAttr(el, 'slot-scope')
     } else if ((slotScope = getAndRemoveAttr(el, 'slot-scope'))) {
+      /* istanbul ignore if */
+      if (process.env.NODE_ENV !== 'production' && el.attrsMap['v-for']) {
+        warn(
+          `Ambiguous combined usage of slot-scope and v-for on <${el.tag}> ` +
+          `(v-for takes higher priority). Use a wrapper <template> for the ` +
+          `scoped slot to make it clearer.`,
+          true
+        )
+      }
       el.slotScope = slotScope
     }
     const slotTarget = getBindingAttr(el, 'slot')
@@ -466,7 +477,7 @@ function processSlot (el) {
       el.slotTarget = slotTarget === '""' ? '"default"' : slotTarget
       // preserve slot as an attribute for native shadow DOM compat
       // only for non-scoped slots.
-      if (!el.slotScope) {
+      if (el.tag !== 'template' && !el.slotScope) {
         addAttr(el, 'slot', slotTarget)
       }
     }
@@ -555,6 +566,13 @@ function processAttrs (el) {
         }
       }
       addAttr(el, name, JSON.stringify(value))
+      // #6887 firefox doesn't update muted state if set via attribute
+      // even immediately after element creation
+      if (!el.component &&
+          name === 'muted' &&
+          platformMustUseProp(el.tag, el.attrsMap.type, name)) {
+        addProp(el, name, 'true')
+      }
     }
   }
 }
diff --git a/src/core/components/keep-alive.js b/src/core/components/keep-alive.js
index 3f6e7af..53dd264 100644
--- a/src/core/components/keep-alive.js
+++ b/src/core/components/keep-alive.js
@@ -41,7 +41,7 @@ function pruneCacheEntry (
   current?: VNode
 ) {
   const cached = cache[key]
-  if (cached && cached !== current) {
+  if (cached && (!current || cached.tag !== current.tag)) {
     cached.componentInstance.$destroy()
   }
   cache[key] = null
@@ -81,15 +81,19 @@ export default {
   },
 
   render () {
-    const vnode: VNode = getFirstComponentChild(this.$slots.default)
+    const slot = this.$slots.default
+    const vnode: VNode = getFirstComponentChild(slot)
     const componentOptions: ?VNodeComponentOptions = vnode && vnode.componentOptions
     if (componentOptions) {
       // check pattern
       const name: ?string = getComponentName(componentOptions)
-      if (name && (
-        (this.include && !matches(this.include, name)) ||
-        (this.exclude && matches(this.exclude, name))
-      )) {
+      const { include, exclude } = this
+      if (
+        // not included
+        (include && (!name || !matches(include, name))) ||
+        // excluded
+        (exclude && name && matches(exclude, name))
+      ) {
         return vnode
       }
 
@@ -115,6 +119,6 @@ export default {
 
       vnode.data.keepAlive = true
     }
-    return vnode
+    return vnode || (slot && slot[0])
   }
 }
diff --git a/src/core/instance/events.js b/src/core/instance/events.js
index 7908041..5877999 100644
--- a/src/core/instance/events.js
+++ b/src/core/instance/events.js
@@ -19,7 +19,7 @@ export function initEvents (vm: Component) {
   }
 }
 
-let target: Component
+let target: any
 
 function add (event, fn, once) {
   if (once) {
@@ -40,6 +40,7 @@ export function updateComponentListeners (
 ) {
   target = vm
   updateListeners(listeners, oldListeners || {}, add, remove, vm)
+  target = undefined
 }
 
 export function eventsMixin (Vue: Class<Component>) {
@@ -91,7 +92,7 @@ export function eventsMixin (Vue: Class<Component>) {
     if (!cbs) {
       return vm
     }
-    if (arguments.length === 1) {
+    if (!fn) {
       vm._events[event] = null
       return vm
     }
diff --git a/src/core/instance/lifecycle.js b/src/core/instance/lifecycle.js
index db7bf28..9280de9 100644
--- a/src/core/instance/lifecycle.js
+++ b/src/core/instance/lifecycle.js
@@ -193,7 +193,10 @@ export function mountComponent (
     }
   }
 
-  vm._watcher = new Watcher(vm, updateComponent, noop)
+  // we set this to vm._watcher inside the watcher's constructor
+  // since the watcher's initial patch may call $forceUpdate (e.g. inside child
+  // component's mounted hook), which relies on vm._watcher being already defined
+  new Watcher(vm, updateComponent, noop, null, true /* isRenderWatcher */)
   hydrating = false
 
   // manually mounted instance, call mounted on self
diff --git a/src/core/instance/render-helpers/render-slot.js b/src/core/instance/render-helpers/render-slot.js
index 1a194c5..a58daa7 100644
--- a/src/core/instance/render-helpers/render-slot.js
+++ b/src/core/instance/render-helpers/render-slot.js
@@ -12,6 +12,7 @@ export function renderSlot (
   bindObject: ?Object
 ): ?Array<VNode> {
   const scopedSlotFn = this.$scopedSlots[name]
+  let nodes
   if (scopedSlotFn) { // scoped slot
     props = props || {}
     if (bindObject) {
@@ -23,18 +24,27 @@ export function renderSlot (
       }
       props = extend(extend({}, bindObject), props)
     }
-    return scopedSlotFn(props) || fallback
+    nodes = scopedSlotFn(props) || fallback
   } else {
     const slotNodes = this.$slots[name]
     // warn duplicate slot usage
-    if (slotNodes && process.env.NODE_ENV !== 'production') {
-      slotNodes._rendered && warn(
-        `Duplicate presence of slot "${name}" found in the same render tree ` +
-        `- this will likely cause render errors.`,
-        this
-      )
+    if (slotNodes) {
+      if (process.env.NODE_ENV !== 'production' && slotNodes._rendered) {
+        warn(
+          `Duplicate presence of slot "${name}" found in the same render tree ` +
+          `- this will likely cause render errors.`,
+          this
+        )
+      }
       slotNodes._rendered = true
     }
-    return slotNodes || fallback
+    nodes = slotNodes || fallback
+  }
+
+  const target = props && props.slot
+  if (target) {
+    return this.$createElement('template', { slot: target }, nodes)
+  } else {
+    return nodes
   }
 }
diff --git a/src/core/instance/render-helpers/render-static.js b/src/core/instance/render-helpers/render-static.js
index 02f424d..d80311e 100644
--- a/src/core/instance/render-helpers/render-static.js
+++ b/src/core/instance/render-helpers/render-static.js
@@ -7,12 +7,19 @@ import { cloneVNode, cloneVNodes } from 'core/vdom/vnode'
  */
 export function renderStatic (
   index: number,
-  isInFor?: boolean
+  isInFor: boolean,
+  isOnce: boolean
 ): VNode | Array<VNode> {
-  // static trees can be rendered once and cached on the contructor options
-  // so every instance shares the same cached trees
+  // render fns generated by compiler < 2.5.4 does not provide v-once
+  // information to runtime so be conservative
+  const isOldVersion = arguments.length < 3
+  // if a static tree is generated by v-once, it is cached on the instance;
+  // otherwise it is purely static and can be cached on the shared options
+  // across all instances.
   const renderFns = this.$options.staticRenderFns
-  const cached = renderFns.cached || (renderFns.cached = [])
+  const cached = isOldVersion || isOnce
+    ? (this._staticTrees || (this._staticTrees = []))
+    : (renderFns.cached || (renderFns.cached = []))
   let tree = cached[index]
   // if has already-rendered static tree and not inside v-for,
   // we can reuse the same tree by doing a shallow clone.
diff --git a/src/core/instance/render-helpers/resolve-slots.js b/src/core/instance/render-helpers/resolve-slots.js
index 26ed51d..0065e3c 100644
--- a/src/core/instance/render-helpers/resolve-slots.js
+++ b/src/core/instance/render-helpers/resolve-slots.js
@@ -11,7 +11,6 @@ export function resolveSlots (
   if (!children) {
     return slots
   }
-  const defaultSlot = []
   for (let i = 0, l = children.length; i < l; i++) {
     const child = children[i]
     const data = child.data
@@ -21,7 +20,7 @@ export function resolveSlots (
     }
     // named slots should only be respected if the vnode was rendered in the
     // same context.
-    if ((child.context === context || child.functionalContext === context) &&
+    if ((child.context === context || child.fnContext === context) &&
       data && data.slot != null
     ) {
       const name = child.data.slot
@@ -32,18 +31,20 @@ export function resolveSlots (
         slot.push(child)
       }
     } else {
-      defaultSlot.push(child)
+      (slots.default || (slots.default = [])).push(child)
     }
   }
-  // ignore whitespace
-  if (!defaultSlot.every(isWhitespace)) {
-    slots.default = defaultSlot
+  // ignore slots that contains only whitespace
+  for (const name in slots) {
+    if (slots[name].every(isWhitespace)) {
+      delete slots[name]
+    }
   }
   return slots
 }
 
 function isWhitespace (node: VNode): boolean {
-  return node.isComment || node.text === ' '
+  return (node.isComment && !node.asyncFactory) || node.text === ' '
 }
 
 export function resolveScopedSlots (
diff --git a/src/core/instance/render.js b/src/core/instance/render.js
index 5b7df25..391e124 100644
--- a/src/core/instance/render.js
+++ b/src/core/instance/render.js
@@ -17,6 +17,7 @@ import { isUpdatingChildComponent } from './lifecycle'
 
 export function initRender (vm: Component) {
   vm._vnode = null // the root of the child tree
+  vm._staticTrees = null // v-once cached trees
   const options = vm.$options
   const parentVnode = vm.$vnode = options._parentVnode // the placeholder node in parent tree
   const renderContext = parentVnode && parentVnode.context
@@ -66,7 +67,9 @@ export function renderMixin (Vue: Class<Component>) {
       // last render. They need to be cloned to ensure "freshness" for this render.
       for (const key in vm.$slots) {
         const slot = vm.$slots[key]
-        if (slot._rendered) {
+        // _rendered is a flag added by renderSlot, but may not be present
+        // if the slot is passed from manually written render functions
+        if (slot._rendered || (slot[0] && slot[0].elm)) {
           vm.$slots[key] = cloneVNodes(slot, true /* deep */)
         }
       }
diff --git a/src/core/observer/index.js b/src/core/observer/index.js
index 11de2d8..86a21f9 100644
--- a/src/core/observer/index.js
+++ b/src/core/observer/index.js
@@ -196,7 +196,7 @@ export function set (target: Array<any> | Object, key: any, val: any): any {
     target.splice(key, 1, val)
     return val
   }
-  if (hasOwn(target, key)) {
+  if (key in target && !(key in Object.prototype)) {
     target[key] = val
     return val
   }
diff --git a/src/core/observer/traverse.js b/src/core/observer/traverse.js
new file mode 100644
index 0000000..37c71e9
--- /dev/null
+++ b/src/core/observer/traverse.js
@@ -0,0 +1,39 @@
+/* @flow */
+
+import { _Set as Set, isObject } from '../util/index'
+import type { SimpleSet } from '../util/index'
+
+const seenObjects = new Set()
+
+/**
+ * Recursively traverse an object to evoke all converted
+ * getters, so that every nested property inside the object
+ * is collected as a "deep" dependency.
+ */
+export function traverse (val: any) {
+  _traverse(val, seenObjects)
+  seenObjects.clear()
+}
+
+function _traverse (val: any, seen: SimpleSet) {
+  let i, keys
+  const isA = Array.isArray(val)
+  if ((!isA && !isObject(val)) || Object.isFrozen(val)) {
+    return
+  }
+  if (val.__ob__) {
+    const depId = val.__ob__.dep.id
+    if (seen.has(depId)) {
+      return
+    }
+    seen.add(depId)
+  }
+  if (isA) {
+    i = val.length
+    while (i--) _traverse(val[i], seen)
+  } else {
+    keys = Object.keys(val)
+    i = keys.length
+    while (i--) _traverse(val[keys[i]], seen)
+  }
+}
diff --git a/src/core/observer/watcher.js b/src/core/observer/watcher.js
index 4025314..48a2e61 100644
--- a/src/core/observer/watcher.js
+++ b/src/core/observer/watcher.js
@@ -1,8 +1,5 @@
 /* @flow */
 
-import { queueWatcher } from './scheduler'
-import Dep, { pushTarget, popTarget } from './dep'
-
 import {
   warn,
   remove,
@@ -12,7 +9,11 @@ import {
   handleError
 } from '../util/index'
 
-import type { ISet } from '../util/index'
+import { traverse } from './traverse'
+import { queueWatcher } from './scheduler'
+import Dep, { pushTarget, popTarget } from './dep'
+
+import type { SimpleSet } from '../util/index'
 
 let uid = 0
 
@@ -34,8 +35,8 @@ export default class Watcher {
   active: boolean;
   deps: Array<Dep>;
   newDeps: Array<Dep>;
-  depIds: ISet;
-  newDepIds: ISet;
+  depIds: SimpleSet;
+  newDepIds: SimpleSet;
   getter: Function;
   value: any;
 
@@ -43,9 +44,13 @@ export default class Watcher {
     vm: Component,
     expOrFn: string | Function,
     cb: Function,
-    options?: Object
+    options?: ?Object,
+    isRenderWatcher?: boolean
   ) {
     this.vm = vm
+    if (isRenderWatcher) {
+      vm._watcher = this
+    }
     vm._watchers.push(this)
     // options
     if (options) {
@@ -233,37 +238,3 @@ export default class Watcher {
     }
   }
 }
-
-/**
- * Recursively traverse an object to evoke all converted
- * getters, so that every nested property inside the object
- * is collected as a "deep" dependency.
- */
-const seenObjects = new Set()
-function traverse (val: any) {
-  seenObjects.clear()
-  _traverse(val, seenObjects)
-}
-
-function _traverse (val: any, seen: ISet) {
-  let i, keys
-  const isA = Array.isArray(val)
-  if ((!isA && !isObject(val)) || !Object.isExtensible(val)) {
-    return
-  }
-  if (val.__ob__) {
-    const depId = val.__ob__.dep.id
-    if (seen.has(depId)) {
-      return
-    }
-    seen.add(depId)
-  }
-  if (isA) {
-    i = val.length
-    while (i--) _traverse(val[i], seen)
-  } else {
-    keys = Object.keys(val)
-    i = keys.length
-    while (i--) _traverse(val[keys[i]], seen)
-  }
-}
diff --git a/src/core/util/env.js b/src/core/util/env.js
index 3076795..c2e80df 100644
--- a/src/core/util/env.js
+++ b/src/core/util/env.js
@@ -1,16 +1,19 @@
 /* @flow */
+declare var WXEnvironment: any;
 
 // can we use __proto__?
 export const hasProto = '__proto__' in {}
 
 // Browser environment sniffing
 export const inBrowser = typeof window !== 'undefined'
+export const inWeex = typeof WXEnvironment !== 'undefined' && !!WXEnvironment.platform
+export const weexPlatform = inWeex && WXEnvironment.platform.toLowerCase()
 export const UA = inBrowser && window.navigator.userAgent.toLowerCase()
 export const isIE = UA && /msie|trident/.test(UA)
 export const isIE9 = UA && UA.indexOf('msie 9.0') > 0
 export const isEdge = UA && UA.indexOf('edge/') > 0
-export const isAndroid = UA && UA.indexOf('android') > 0
-export const isIOS = UA && /iphone|ipad|ipod|ios/.test(UA)
+export const isAndroid = (UA && UA.indexOf('android') > 0) || (weexPlatform === 'android')
+export const isIOS = (UA && /iphone|ipad|ipod|ios/.test(UA)) || (weexPlatform === 'ios')
 export const isChrome = UA && /chrome\/\d+/.test(UA) && !isEdge
 
 // Firefox has a "watch" function on Object.prototype...
@@ -66,7 +69,7 @@ if (typeof Set !== 'undefined' && isNative(Set)) {
   _Set = Set
 } else {
   // a non-standard Set polyfill that only works with primitive keys.
-  _Set = class Set implements ISet {
+  _Set = class Set implements SimpleSet {
     set: Object;
     constructor () {
       this.set = Object.create(null)
@@ -83,11 +86,11 @@ if (typeof Set !== 'undefined' && isNative(Set)) {
   }
 }
 
-interface ISet {
+interface SimpleSet {
   has(key: string | number): boolean;
   add(key: string | number): mixed;
   clear(): void;
 }
 
 export { _Set }
-export type { ISet }
+export type { SimpleSet }
diff --git a/src/core/util/error.js b/src/core/util/error.js
index abf5b6a..b7d05a6 100644
--- a/src/core/util/error.js
+++ b/src/core/util/error.js
@@ -2,7 +2,7 @@
 
 import config from '../config'
 import { warn } from './debug'
-import { inBrowser } from './env'
+import { inBrowser, inWeex } from './env'
 
 export function handleError (err: Error, vm: any, info: string) {
   if (vm) {
@@ -40,7 +40,7 @@ function logError (err, vm, info) {
     warn(`Error in ${info}: "${err.toString()}"`, vm)
   }
   /* istanbul ignore else */
-  if (inBrowser && typeof console !== 'undefined') {
+  if ((inBrowser || inWeex) && typeof console !== 'undefined') {
     console.error(err)
   } else {
     throw err
diff --git a/src/core/util/lang.js b/src/core/util/lang.js
index 3be32d1..96b8219 100644
--- a/src/core/util/lang.js
+++ b/src/core/util/lang.js
@@ -1,7 +1,5 @@
 /* @flow */
 
-export const emptyObject = Object.freeze({})
-
 /**
  * Check if a string starts with $ or _
  */
diff --git a/src/core/util/options.js b/src/core/util/options.js
index 3be38b8..ad36bb9 100644
--- a/src/core/util/options.js
+++ b/src/core/util/options.js
@@ -89,7 +89,7 @@ export function mergeDataOrFn (
         typeof parentVal === 'function' ? parentVal.call(this) : parentVal
       )
     }
-  } else if (parentVal || childVal) {
+  } else {
     return function mergedInstanceDataFn () {
       // instance merge
       const instanceData = typeof childVal === 'function'
@@ -123,7 +123,7 @@ strats.data = function (
 
       return parentVal
     }
-    return mergeDataOrFn.call(this, parentVal, childVal)
+    return mergeDataOrFn(parentVal, childVal)
   }
 
   return mergeDataOrFn(parentVal, childVal, vm)
diff --git a/src/core/vdom/create-functional-component.js b/src/core/vdom/create-functional-component.js
index d749ab9..ff00f24 100644
--- a/src/core/vdom/create-functional-component.js
+++ b/src/core/vdom/create-functional-component.js
@@ -49,8 +49,8 @@ function FunctionalRenderContext (
     this._c = (a, b, c, d) => {
       const vnode: ?VNode = createElement(contextVm, a, b, c, d, needNormalization)
       if (vnode) {
-        vnode.functionalScopeId = options._scopeId
-        vnode.functionalContext = parent
+        vnode.fnScopeId = options._scopeId
+        vnode.fnContext = parent
       }
       return vnode
     }
@@ -91,8 +91,8 @@ export function createFunctionalComponent (
   const vnode = options.render.call(null, renderContext._c, renderContext)
 
   if (vnode instanceof VNode) {
-    vnode.functionalContext = contextVm
-    vnode.functionalOptions = options
+    vnode.fnContext = contextVm
+    vnode.fnOptions = options
     if (data.slot) {
       (vnode.data || (vnode.data = {})).slot = data.slot
     }
diff --git a/src/core/vdom/helpers/merge-hook.js b/src/core/vdom/helpers/merge-hook.js
index 2312d92..0bb96e8 100644
--- a/src/core/vdom/helpers/merge-hook.js
+++ b/src/core/vdom/helpers/merge-hook.js
@@ -1,9 +1,13 @@
 /* @flow */
 
+import VNode from '../vnode'
 import { createFnInvoker } from './update-listeners'
 import { remove, isDef, isUndef, isTrue } from 'shared/util'
 
 export function mergeVNodeHook (def: Object, hookKey: string, hook: Function) {
+  if (def instanceof VNode) {
+    def = def.data.hook || (def.data.hook = {})
+  }
   let invoker
   const oldHook = def[hookKey]
 
diff --git a/src/core/vdom/modules/directives.js b/src/core/vdom/modules/directives.js
index db35c35..42e33f9 100644
--- a/src/core/vdom/modules/directives.js
+++ b/src/core/vdom/modules/directives.js
@@ -54,14 +54,14 @@ function _update (oldVnode, vnode) {
       }
     }
     if (isCreate) {
-      mergeVNodeHook(vnode.data.hook || (vnode.data.hook = {}), 'insert', callInsert)
+      mergeVNodeHook(vnode, 'insert', callInsert)
     } else {
       callInsert()
     }
   }
 
   if (dirsWithPostpatch.length) {
-    mergeVNodeHook(vnode.data.hook || (vnode.data.hook = {}), 'postpatch', () => {
+    mergeVNodeHook(vnode, 'postpatch', () => {
       for (let i = 0; i < dirsWithPostpatch.length; i++) {
         callHook(dirsWithPostpatch[i], 'componentUpdated', vnode, oldVnode)
       }
diff --git a/src/core/vdom/patch.js b/src/core/vdom/patch.js
index f06a1fe..368eb41 100644
--- a/src/core/vdom/patch.js
+++ b/src/core/vdom/patch.js
@@ -14,6 +14,7 @@ import VNode from './vnode'
 import config from '../config'
 import { SSR_ATTR } from 'shared/constants'
 import { registerRef } from './modules/ref'
+import { traverse } from '../observer/traverse'
 import { activeInstance } from '../instance/lifecycle'
 import { isTextInputType } from 'web/util/element'
 
@@ -103,7 +104,23 @@ export function createPatchFunction (backend) {
     }
   }
 
-  let inPre = 0
+  function isUnknownElement (vnode, inVPre) {
+    return (
+      !inVPre &&
+      !vnode.ns &&
+      !(
+        config.ignoredElements.length &&
+        config.ignoredElements.some(ignore => {
+          return isRegExp(ignore)
+            ? ignore.test(vnode.tag)
+            : ignore === vnode.tag
+        })
+      ) &&
+      config.isUnknownElement(vnode.tag)
+    )
+  }
+
+  let creatingElmInVPre = 0
   function createElm (vnode, insertedVnodeQueue, parentElm, refElm, nested) {
     vnode.isRootInsert = !nested // for transition enter check
     if (createComponent(vnode, insertedVnodeQueue, parentElm, refElm)) {
@@ -116,21 +133,9 @@ export function createPatchFunction (backend) {
     if (isDef(tag)) {
       if (process.env.NODE_ENV !== 'production') {
         if (data && data.pre) {
-          inPre++
+          creatingElmInVPre++
         }
-        if (
-          !inPre &&
-          !vnode.ns &&
-          !(
-            config.ignoredElements.length &&
-            config.ignoredElements.some(ignore => {
-              return isRegExp(ignore)
-                ? ignore.test(tag)
-                : ignore === tag
-            })
-          ) &&
-          config.isUnknownElement(tag)
-        ) {
+        if (isUnknownElement(vnode, creatingElmInVPre)) {
           warn(
             'Unknown custom element: <' + tag + '> - did you ' +
             'register the component correctly? For recursive components, ' +
@@ -172,7 +177,7 @@ export function createPatchFunction (backend) {
       }
 
       if (process.env.NODE_ENV !== 'production' && data && data.pre) {
-        inPre--
+        creatingElmInVPre--
       }
     } else if (isTrue(vnode.isComment)) {
       vnode.elm = nodeOps.createComment(vnode.text)
@@ -289,7 +294,7 @@ export function createPatchFunction (backend) {
   // of going through the normal attribute patching process.
   function setScope (vnode) {
     let i
-    if (isDef(i = vnode.functionalScopeId)) {
+    if (isDef(i = vnode.fnScopeId)) {
       nodeOps.setAttribute(vnode.elm, i, '')
     } else {
       let ancestor = vnode
@@ -303,7 +308,7 @@ export function createPatchFunction (backend) {
     // for slot content they should also get the scopeId from the host instance.
     if (isDef(i = activeInstance) &&
       i !== vnode.context &&
-      i !== vnode.functionalContext &&
+      i !== vnode.fnContext &&
       isDef(i = i.$options._scopeId)
     ) {
       nodeOps.setAttribute(vnode.elm, i, '')
@@ -527,25 +532,30 @@ export function createPatchFunction (backend) {
     }
   }
 
-  let bailed = false
+  let hydrationBailed = false
   // list of modules that can skip create hook during hydration because they
   // are already rendered on the client or has no need for initialization
-  const isRenderedModule = makeMap('attrs,style,class,staticClass,staticStyle,key')
+  // Note: style is excluded because it relies on initial clone for future
+  // deep updates (#7063).
+  const isRenderedModule = makeMap('attrs,class,staticClass,staticStyle,key')
 
   // Note: this is a browser-only function so we can assume elms are DOM nodes.
-  function hydrate (elm, vnode, insertedVnodeQueue) {
+  function hydrate (elm, vnode, insertedVnodeQueue, inVPre) {
+    let i
+    const { tag, data, children } = vnode
+    inVPre = inVPre || (data && data.pre)
+    vnode.elm = elm
+
     if (isTrue(vnode.isComment) && isDef(vnode.asyncFactory)) {
-      vnode.elm = elm
       vnode.isAsyncPlaceholder = true
       return true
     }
+    // assert node match
     if (process.env.NODE_ENV !== 'production') {
-      if (!assertNodeMatch(elm, vnode)) {
+      if (!assertNodeMatch(elm, vnode, inVPre)) {
         return false
       }
     }
-    vnode.elm = elm
-    const { tag, data, children } = vnode
     if (isDef(data)) {
       if (isDef(i = data.hook) && isDef(i = i.init)) i(vnode, true /* hydrating */)
       if (isDef(i = vnode.componentInstance)) {
@@ -566,9 +576,9 @@ export function createPatchFunction (backend) {
               /* istanbul ignore if */
               if (process.env.NODE_ENV !== 'production' &&
                 typeof console !== 'undefined' &&
-                !bailed
+                !hydrationBailed
               ) {
-                bailed = true
+                hydrationBailed = true
                 console.warn('Parent: ', elm)
                 console.warn('server innerHTML: ', i)
                 console.warn('client innerHTML: ', elm.innerHTML)
@@ -580,7 +590,7 @@ export function createPatchFunction (backend) {
             let childrenMatch = true
             let childNode = elm.firstChild
             for (let i = 0; i < children.length; i++) {
-              if (!childNode || !hydrate(childNode, children[i], insertedVnodeQueue)) {
+              if (!childNode || !hydrate(childNode, children[i], insertedVnodeQueue, inVPre)) {
                 childrenMatch = false
                 break
               }
@@ -592,9 +602,9 @@ export function createPatchFunction (backend) {
               /* istanbul ignore if */
               if (process.env.NODE_ENV !== 'production' &&
                 typeof console !== 'undefined' &&
-                !bailed
+                !hydrationBailed
               ) {
-                bailed = true
+                hydrationBailed = true
                 console.warn('Parent: ', elm)
                 console.warn('Mismatching childNodes vs. VNodes: ', elm.childNodes, children)
               }
@@ -604,12 +614,18 @@ export function createPatchFunction (backend) {
         }
       }
       if (isDef(data)) {
+        let fullInvoke = false
         for (const key in data) {
           if (!isRenderedModule(key)) {
+            fullInvoke = true
             invokeCreateHooks(vnode, insertedVnodeQueue)
             break
           }
         }
+        if (!fullInvoke && data['class']) {
+          // ensure collecting deps for deep class bindings for future updates
+          traverse(data['class'])
+        }
       }
     } else if (elm.data !== vnode.text) {
       elm.data = vnode.text
@@ -617,10 +633,10 @@ export function createPatchFunction (backend) {
     return true
   }
 
-  function assertNodeMatch (node, vnode) {
+  function assertNodeMatch (node, vnode, inVPre) {
     if (isDef(vnode.tag)) {
-      return (
-        vnode.tag.indexOf('vue-component') === 0 ||
+      return vnode.tag.indexOf('vue-component') === 0 || (
+        !isUnknownElement(vnode, inVPre) &&
         vnode.tag.toLowerCase() === (node.tagName && node.tagName.toLowerCase())
       )
     } else {
@@ -673,9 +689,12 @@ export function createPatchFunction (backend) {
           // create an empty node and replace it
           oldVnode = emptyNodeAt(oldVnode)
         }
+
         // replacing existing element
         const oldElm = oldVnode.elm
         const parentElm = nodeOps.parentNode(oldElm)
+
+        // create new node
         createElm(
           vnode,
           insertedVnodeQueue,
@@ -686,9 +705,8 @@ export function createPatchFunction (backend) {
           nodeOps.nextSibling(oldElm)
         )
 
+        // update parent placeholder node element, recursively
         if (isDef(vnode.parent)) {
-          // component root element replaced.
-          // update parent placeholder node element, recursively
           let ancestor = vnode.parent
           const patchable = isPatchable(vnode)
           while (ancestor) {
@@ -717,6 +735,7 @@ export function createPatchFunction (backend) {
           }
         }
 
+        // destroy old node
         if (isDef(parentElm)) {
           removeVnodes(parentElm, [oldVnode], 0, 0)
         } else if (isDef(oldVnode.tag)) {
diff --git a/src/core/vdom/vnode.js b/src/core/vdom/vnode.js
index a34330d..838f9f1 100644
--- a/src/core/vdom/vnode.js
+++ b/src/core/vdom/vnode.js
@@ -24,9 +24,9 @@ export default class VNode {
   asyncMeta: Object | void;
   isAsyncPlaceholder: boolean;
   ssrContext: Object | void;
-  functionalContext: Component | void; // real context vm for functional nodes
-  functionalOptions: ?ComponentOptions; // for SSR caching
-  functionalScopeId: ?string; // functioanl scope id support
+  fnContext: Component | void; // real context vm for functional nodes
+  fnOptions: ?ComponentOptions; // for SSR caching
+  fnScopeId: ?string; // functioanl scope id support
 
   constructor (
     tag?: string,
@@ -45,9 +45,9 @@ export default class VNode {
     this.elm = elm
     this.ns = undefined
     this.context = context
-    this.functionalContext = undefined
-    this.functionalOptions = undefined
-    this.functionalScopeId = undefined
+    this.fnContext = undefined
+    this.fnOptions = undefined
+    this.fnScopeId = undefined
     this.key = data && data.key
     this.componentOptions = componentOptions
     this.componentInstance = undefined
@@ -86,6 +86,7 @@ export function createTextVNode (val: string | number) {
 // multiple renders, cloning them avoids errors when DOM manipulations rely
 // on their elm reference.
 export function cloneVNode (vnode: VNode, deep?: boolean): VNode {
+  const componentOptions = vnode.componentOptions
   const cloned = new VNode(
     vnode.tag,
     vnode.data,
@@ -93,16 +94,24 @@ export function cloneVNode (vnode: VNode, deep?: boolean): VNode {
     vnode.text,
     vnode.elm,
     vnode.context,
-    vnode.componentOptions,
+    componentOptions,
     vnode.asyncFactory
   )
   cloned.ns = vnode.ns
   cloned.isStatic = vnode.isStatic
   cloned.key = vnode.key
   cloned.isComment = vnode.isComment
+  cloned.fnContext = vnode.fnContext
+  cloned.fnOptions = vnode.fnOptions
+  cloned.fnScopeId = vnode.fnScopeId
   cloned.isCloned = true
-  if (deep && vnode.children) {
-    cloned.children = cloneVNodes(vnode.children)
+  if (deep) {
+    if (vnode.children) {
+      cloned.children = cloneVNodes(vnode.children, true)
+    }
+    if (componentOptions && componentOptions.children) {
+      componentOptions.children = cloneVNodes(componentOptions.children, true)
+    }
   }
   return cloned
 }
diff --git a/src/platforms/web/compiler/directives/model.js b/src/platforms/web/compiler/directives/model.js
index 98d4259..81c4777 100644
--- a/src/platforms/web/compiler/directives/model.js
+++ b/src/platforms/web/compiler/directives/model.js
@@ -128,6 +128,19 @@ function genDefaultModel (
   modifiers: ?ASTModifiers
 ): ?boolean {
   const type = el.attrsMap.type
+
+  // warn if v-bind:value conflicts with v-model
+  if (process.env.NODE_ENV !== 'production') {
+    const value = el.attrsMap['v-bind:value'] || el.attrsMap[':value']
+    if (value) {
+      const binding = el.attrsMap['v-bind:value'] ? 'v-bind:value' : ':value'
+      warn(
+        `${binding}="${value}" conflicts with v-model on the same element ` +
+        'because the latter already expands to a value binding internally'
+      )
+    }
+  }
+
   const { lazy, number, trim } = modifiers || {}
   const needCompositionGuard = !lazy && type !== 'range'
   const event = lazy
diff --git a/src/platforms/web/compiler/modules/model.js b/src/platforms/web/compiler/modules/model.js
index 61657d1..5e882d7 100644
--- a/src/platforms/web/compiler/modules/model.js
+++ b/src/platforms/web/compiler/modules/model.js
@@ -29,6 +29,8 @@ function preTransformNode (el: ASTElement, options: CompilerOptions) {
       const typeBinding: any = getBindingAttr(el, 'type')
       const ifCondition = getAndRemoveAttr(el, 'v-if', true)
       const ifConditionExtra = ifCondition ? `&&(${ifCondition})` : ``
+      const hasElse = getAndRemoveAttr(el, 'v-else', true) != null
+      const elseIfCondition = getAndRemoveAttr(el, 'v-else-if', true)
       // 1. checkbox
       const branch0 = cloneASTElement(el)
       // process for on the main node
@@ -59,6 +61,13 @@ function preTransformNode (el: ASTElement, options: CompilerOptions) {
         exp: ifCondition,
         block: branch2
       })
+
+      if (hasElse) {
+        branch0.else = true
+      } else if (elseIfCondition) {
+        branch0.elseif = elseIfCondition
+      }
+
       return branch0
     }
   }
diff --git a/src/platforms/web/entry-runtime-with-compiler.js b/src/platforms/web/entry-runtime-with-compiler.js
index 5ca67b6..1ebc102 100644
--- a/src/platforms/web/entry-runtime-with-compiler.js
+++ b/src/platforms/web/entry-runtime-with-compiler.js
@@ -6,8 +6,8 @@ import { mark, measure } from 'core/util/perf'
 
 import Vue from './runtime/index'
 import { query } from './util/index'
-import { shouldDecodeNewlines } from './util/compat'
 import { compileToFunctions } from './compiler/index'
+import { shouldDecodeNewlines, shouldDecodeNewlinesForHref } from './util/compat'
 
 const idToTemplate = cached(id => {
   const el = query(id)
@@ -64,6 +64,7 @@ Vue.prototype.$mount = function (
 
       const { render, staticRenderFns } = compileToFunctions(template, {
         shouldDecodeNewlines,
+        shouldDecodeNewlinesForHref,
         delimiters: options.delimiters,
         comments: options.comments
       }, this)
diff --git a/src/platforms/web/runtime/components/transition.js b/src/platforms/web/runtime/components/transition.js
index 857c88f..6111d8c 100644
--- a/src/platforms/web/runtime/components/transition.js
+++ b/src/platforms/web/runtime/components/transition.js
@@ -82,7 +82,7 @@ export default {
   abstract: true,
 
   render (h: Function) {
-    let children: ?Array<VNode> = this.$options._renderChildren
+    let children: any = this.$slots.default
     if (!children) {
       return
     }
@@ -161,7 +161,9 @@ export default {
       oldChild &&
       oldChild.data &&
       !isSameChild(child, oldChild) &&
-      !isAsyncPlaceholder(oldChild)
+      !isAsyncPlaceholder(oldChild) &&
+      // #6687 component root is a comment node
+      !(oldChild.componentInstance && oldChild.componentInstance._vnode.isComment)
     ) {
       // replace old child transition data with fresh one
       // important for dynamic transitions!
diff --git a/src/platforms/web/runtime/directives/model.js b/src/platforms/web/runtime/directives/model.js
index 8923981..c3b669f 100644
--- a/src/platforms/web/runtime/directives/model.js
+++ b/src/platforms/web/runtime/directives/model.js
@@ -5,6 +5,7 @@
 
 import { isTextInputType } from 'web/util/element'
 import { looseEqual, looseIndexOf } from 'shared/util'
+import { mergeVNodeHook } from 'core/vdom/helpers/index'
 import { warn, isAndroid, isIE9, isIE, isEdge } from 'core/util/index'
 
 /* istanbul ignore if */
@@ -18,10 +19,17 @@ if (isIE9) {
   })
 }
 
-export default {
-  inserted (el, binding, vnode) {
+const directive = {
+  inserted (el, binding, vnode, oldVnode) {
     if (vnode.tag === 'select') {
-      setSelected(el, binding, vnode.context)
+      // #6903
+      if (oldVnode.elm && !oldVnode.elm._vOptions) {
+        mergeVNodeHook(vnode, 'postpatch', () => {
+          directive.componentUpdated(el, binding, vnode)
+        })
+      } else {
+        setSelected(el, binding, vnode.context)
+      }
       el._vOptions = [].map.call(el.options, getValue)
     } else if (vnode.tag === 'textarea' || isTextInputType(el.type)) {
       el._vModifiers = binding.modifiers
@@ -42,6 +50,7 @@ export default {
       }
     }
   },
+
   componentUpdated (el, binding, vnode) {
     if (vnode.tag === 'select') {
       setSelected(el, binding, vnode.context)
@@ -136,3 +145,5 @@ function trigger (el, type) {
   e.initEvent(type, true, true)
   el.dispatchEvent(e)
 }
+
+export default directive
diff --git a/src/platforms/web/runtime/modules/attrs.js b/src/platforms/web/runtime/modules/attrs.js
index 317316d..0034d35 100644
--- a/src/platforms/web/runtime/modules/attrs.js
+++ b/src/platforms/web/runtime/modules/attrs.js
@@ -1,6 +1,6 @@
 /* @flow */
 
-import { isIE9, isEdge } from 'core/util/env'
+import { isIE, isIE9, isEdge } from 'core/util/env'
 
 import {
   extend,
@@ -44,7 +44,7 @@ function updateAttrs (oldVnode: VNodeWithData, vnode: VNodeWithData) {
   // #4391: in IE9, setting type can reset value for input[type=radio]
   // #6666: IE/Edge forces progress value down to 1 before setting a max
   /* istanbul ignore if */
-  if ((isIE9 || isEdge) && attrs.value !== oldAttrs.value) {
+  if ((isIE || isEdge) && attrs.value !== oldAttrs.value) {
     setAttr(elm, 'value', attrs.value)
   }
   for (key in oldAttrs) {
@@ -84,6 +84,23 @@ function setAttr (el: Element, key: string, value: any) {
     if (isFalsyAttrValue(value)) {
       el.removeAttribute(key)
     } else {
+      // #7138: IE10 & 11 fires input event when setting placeholder on
+      // <textarea>... block the first input event and remove the blocker
+      // immediately.
+      /* istanbul ignore if */
+      if (
+        isIE && !isIE9 &&
+        el.tagName === 'TEXTAREA' &&
+        key === 'placeholder' && !el.__ieph
+      ) {
+        const blocker = e => {
+          e.stopImmediatePropagation()
+          el.removeEventListener('input', blocker)
+        }
+        el.addEventListener('input', blocker)
+        // $flow-disable-line
+        el.__ieph = true /* IE placeholder patched */
+      }
       el.setAttribute(key, value)
     }
   }
diff --git a/src/platforms/web/runtime/modules/events.js b/src/platforms/web/runtime/modules/events.js
index 103dfe0..1e71b66 100644
--- a/src/platforms/web/runtime/modules/events.js
+++ b/src/platforms/web/runtime/modules/events.js
@@ -26,7 +26,7 @@ function normalizeEvents (on) {
   }
 }
 
-let target: HTMLElement
+let target: any
 
 function createOnceHandler (handler, event, capture) {
   const _target = target // save current target element in closure
@@ -78,6 +78,7 @@ function updateDOMListeners (oldVnode: VNodeWithData, vnode: VNodeWithData) {
   target = vnode.elm
   normalizeEvents(on)
   updateListeners(on, oldOn, add, remove, vnode.context)
+  target = undefined
 }
 
 export default {
diff --git a/src/platforms/web/runtime/modules/transition.js b/src/platforms/web/runtime/modules/transition.js
index 94acb90..0d099c9 100644
--- a/src/platforms/web/runtime/modules/transition.js
+++ b/src/platforms/web/runtime/modules/transition.js
@@ -130,7 +130,7 @@ export function enter (vnode: VNodeWithData, toggleDisplay: ?() => void) {
 
   if (!vnode.data.show) {
     // remove pending leave element on enter by injecting an insert hook
-    mergeVNodeHook(vnode.data.hook || (vnode.data.hook = {}), 'insert', () => {
+    mergeVNodeHook(vnode, 'insert', () => {
       const parent = el.parentNode
       const pendingNode = parent && parent._pending && parent._pending[vnode.key]
       if (pendingNode &&
@@ -181,12 +181,12 @@ export function leave (vnode: VNodeWithData, rm: Function) {
   }
 
   const data = resolveTransition(vnode.data.transition)
-  if (isUndef(data)) {
+  if (isUndef(data) || el.nodeType !== 1) {
     return rm()
   }
 
   /* istanbul ignore if */
-  if (isDef(el._leaveCb) || el.nodeType !== 1) {
+  if (isDef(el._leaveCb)) {
     return
   }
 
diff --git a/src/platforms/web/server/directives/index.js b/src/platforms/web/server/directives/index.js
index 89c2eee..fd7fce0 100644
--- a/src/platforms/web/server/directives/index.js
+++ b/src/platforms/web/server/directives/index.js
@@ -1,5 +1,7 @@
 import show from './show'
+import model from './model'
 
 export default {
-  show
+  show,
+  model
 }
diff --git a/src/platforms/web/server/directives/model.js b/src/platforms/web/server/directives/model.js
new file mode 100644
index 0000000..7962d6c
--- /dev/null
+++ b/src/platforms/web/server/directives/model.js
@@ -0,0 +1,44 @@
+/* @flow */
+
+import { looseEqual, looseIndexOf } from 'shared/util'
+
+// this is only applied for <select v-model> because it is the only edge case
+// that must be done at runtime instead of compile time.
+export default function model (node: VNodeWithData, dir: VNodeDirective) {
+  if (!node.children) return
+  const value = dir.value
+  const isMultiple = node.data.attrs && node.data.attrs.multiple
+  for (let i = 0, l = node.children.length; i < l; i++) {
+    const option = node.children[i]
+    if (option.tag === 'option') {
+      if (isMultiple) {
+        const selected =
+          Array.isArray(value) &&
+          (looseIndexOf(value, getValue(option)) > -1)
+        if (selected) {
+          setSelected(option)
+        }
+      } else {
+        if (looseEqual(value, getValue(option))) {
+          setSelected(option)
+          return
+        }
+      }
+    }
+  }
+}
+
+function getValue (option) {
+  const data = option.data || {}
+  return (
+    (data.attrs && data.attrs.value) ||
+    (data.domProps && data.domProps.value) ||
+    (option.children && option.children[0] && option.children[0].text)
+  )
+}
+
+function setSelected (option) {
+  const data = option.data || (option.data = {})
+  const attrs = data.attrs || (data.attrs = {})
+  attrs.selected = ''
+}
diff --git a/src/platforms/web/server/modules/dom-props.js b/src/platforms/web/server/modules/dom-props.js
index 98a0daf..57c18ee 100644
--- a/src/platforms/web/server/modules/dom-props.js
+++ b/src/platforms/web/server/modules/dom-props.js
@@ -27,7 +27,10 @@ export default function renderDOMProps (node: VNodeWithData): string {
       setText(node, props[key], true)
     } else if (key === 'textContent') {
       setText(node, props[key], false)
+    } else if (key === 'value' && node.tag === 'textarea') {
+      setText(node, props[key], false)
     } else {
+      // $flow-disable-line (WTF?)
       const attr = propsToAttrMap[key] || key.toLowerCase()
       if (isRenderableAttr(attr) &&
         // avoid rendering double-bound props/attrs twice
diff --git a/src/platforms/web/util/compat.js b/src/platforms/web/util/compat.js
index 144d68a..d95759c 100644
--- a/src/platforms/web/util/compat.js
+++ b/src/platforms/web/util/compat.js
@@ -3,12 +3,14 @@
 import { inBrowser } from 'core/util/index'
 
 // check whether current browser encodes a char inside attribute values
-function shouldDecode (content: string, encoded: string): boolean {
-  const div = document.createElement('div')
-  div.innerHTML = `<div a="${content}"/>`
-  return div.innerHTML.indexOf(encoded) > 0
+let div
+function getShouldDecode (href: boolean): boolean {
+  div = div || document.createElement('div')
+  div.innerHTML = href ? `<a href="\n"/>` : `<div a="\n"/>`
+  return div.innerHTML.indexOf('
') > 0
 }
 
-// #3663
-// IE encodes newlines inside attribute values while other browsers don't
-export const shouldDecodeNewlines = inBrowser ? shouldDecode('\n', '
') : false
+// #3663: IE encodes newlines inside attribute values while other browsers don't
+export const shouldDecodeNewlines = inBrowser ? getShouldDecode(false) : false
+// #6828: chrome encodes content in a[href]
+export const shouldDecodeNewlinesForHref = inBrowser ? getShouldDecode(true) : false
diff --git a/src/platforms/weex/runtime/components/richtext.js b/src/platforms/weex/runtime/components/richtext.js
index dc2b0d5..a9164c7 100644
--- a/src/platforms/weex/runtime/components/richtext.js
+++ b/src/platforms/weex/runtime/components/richtext.js
@@ -1,32 +1,25 @@
-function getVNodeType (vnode) {
+/* @flow */
+
+function getVNodeType (vnode: VNode): string {
   if (!vnode.tag) {
     return ''
   }
   return vnode.tag.replace(/vue\-component\-(\d+\-)?/, '')
 }
 
-function isSimpleSpan (vnode) {
-  return vnode.children && vnode.children.length === 1 && !vnode.children[0].tag
+function isSimpleSpan (vnode: VNode): boolean {
+  return vnode.children &&
+    vnode.children.length === 1 &&
+    !vnode.children[0].tag
 }
 
-const cssLengthRE = /^([+-]?[0-9]+(\.[0-9]+)?)(px|em|ex|%|in|cm|mm|pt|pc)$/i
-function trimCSSUnit (prop) {
-  const res = String(prop).match(cssLengthRE)
-  if (res) {
-    return Number(res[1])
-  }
-  return prop
-}
-
-function parseStyle (vnode) {
+function parseStyle (vnode: VNode): Object | void {
   if (!vnode || !vnode.data) {
     return
   }
-
   const { staticStyle, staticClass } = vnode.data
   if (vnode.data.style || vnode.data.class || staticStyle || staticClass) {
     const styles = Object.assign({}, staticStyle, vnode.data.style)
-
     const cssMap = vnode.context.$options.style || {}
     const classList = [].concat(staticClass, vnode.data.class)
     classList.forEach(name => {
@@ -34,22 +27,18 @@ function parseStyle (vnode) {
         Object.assign(styles, cssMap[name])
       }
     })
-
-    for (const key in styles) {
-      styles[key] = trimCSSUnit(styles[key])
-    }
     return styles
   }
 }
 
-function convertVNodeChildren (children) {
+function convertVNodeChildren (children: Array<VNode>): Array<VNode> | void {
   if (!children.length) {
     return
   }
 
   return children.map(vnode => {
-    const type = getVNodeType(vnode)
-    const props = { type }
+    const type: string = getVNodeType(vnode)
+    const props: Object = { type }
 
     // convert raw text node
     if (!type) {
@@ -65,7 +54,6 @@ function convertVNodeChildren (children) {
           props.events = vnode.data.on
         }
       }
-
       if (type === 'span' && isSimpleSpan(vnode)) {
         props.attr = props.attr || {}
         props.attr.value = vnode.children[0].text.trim()
@@ -83,8 +71,7 @@ function convertVNodeChildren (children) {
 
 export default {
   name: 'richtext',
-  // abstract: true,
-  render (h) {
+  render (h: Function) {
     return h('weex:richtext', {
       on: this._events,
       attrs: {
diff --git a/src/platforms/weex/runtime/modules/attrs.js b/src/platforms/weex/runtime/modules/attrs.js
index 39d532d..1b6185c 100755
--- a/src/platforms/weex/runtime/modules/attrs.js
+++ b/src/platforms/weex/runtime/modules/attrs.js
@@ -15,18 +15,27 @@ function updateAttrs (oldVnode: VNodeWithData, vnode: VNodeWithData) {
     attrs = vnode.data.attrs = extend({}, attrs)
   }
 
+  const supportBatchUpdate = typeof elm.setAttrs === 'function'
+  const batchedAttrs = {}
   for (key in attrs) {
     cur = attrs[key]
     old = oldAttrs[key]
     if (old !== cur) {
-      elm.setAttr(key, cur)
+      supportBatchUpdate
+        ? (batchedAttrs[key] = cur)
+        : elm.setAttr(key, cur)
     }
   }
   for (key in oldAttrs) {
     if (attrs[key] == null) {
-      elm.setAttr(key)
+      supportBatchUpdate
+        ? (batchedAttrs[key] = undefined)
+        : elm.setAttr(key)
     }
   }
+  if (supportBatchUpdate) {
+    elm.setAttrs(batchedAttrs)
+  }
 }
 
 export default {
diff --git a/src/platforms/weex/runtime/modules/class.js b/src/platforms/weex/runtime/modules/class.js
index b1e3b18..8d9d51e 100755
--- a/src/platforms/weex/runtime/modules/class.js
+++ b/src/platforms/weex/runtime/modules/class.js
@@ -36,8 +36,12 @@ function updateClass (oldVnode: VNodeWithData, vnode: VNodeWithData) {
   }
 
   const style = getStyle(oldClassList, classList, ctx)
-  for (const key in style) {
-    el.setStyle(key, style[key])
+  if (typeof el.setStyles === 'function') {
+    el.setStyles(style)
+  } else {
+    for (const key in style) {
+      el.setStyle(key, style[key])
+    }
   }
 }
 
diff --git a/src/platforms/weex/runtime/modules/events.js b/src/platforms/weex/runtime/modules/events.js
index 824f08e..11b7edc 100755
--- a/src/platforms/weex/runtime/modules/events.js
+++ b/src/platforms/weex/runtime/modules/events.js
@@ -46,6 +46,7 @@ function updateDOMListeners (oldVnode: VNodeWithData, vnode: VNodeWithData) {
   const oldOn = oldVnode.data.on || {}
   target = vnode.elm
   updateListeners(on, oldOn, add, remove, vnode.context)
+  target = undefined
 }
 
 export default {
diff --git a/src/platforms/weex/runtime/modules/style.js b/src/platforms/weex/runtime/modules/style.js
index 9c60fd1..bdabd17 100755
--- a/src/platforms/weex/runtime/modules/style.js
+++ b/src/platforms/weex/runtime/modules/style.js
@@ -11,11 +11,18 @@ function createStyle (oldVnode: VNodeWithData, vnode: VNodeWithData) {
   }
   const elm = vnode.elm
   const staticStyle = vnode.data.staticStyle
+  const supportBatchUpdate = typeof elm.setStyles === 'function'
+  const batchedStyles = {}
   for (const name in staticStyle) {
     if (staticStyle[name]) {
-      elm.setStyle(normalize(name), staticStyle[name])
+      supportBatchUpdate
+        ? (batchedStyles[normalize(name)] = staticStyle[name])
+        : elm.setStyle(normalize(name), staticStyle[name])
     }
   }
+  if (supportBatchUpdate) {
+    elm.setStyles(batchedStyles)
+  }
   updateStyle(oldVnode, vnode)
 }
 
@@ -41,14 +48,23 @@ function updateStyle (oldVnode: VNodeWithData, vnode: VNodeWithData) {
     style = vnode.data.style = extend({}, style)
   }
 
+  const supportBatchUpdate = typeof elm.setStyles === 'function'
+  const batchedStyles = {}
   for (name in oldStyle) {
     if (!style[name]) {
-      elm.setStyle(normalize(name), '')
+      supportBatchUpdate
+        ? (batchedStyles[normalize(name)] = '')
+        : elm.setStyle(normalize(name), '')
     }
   }
   for (name in style) {
     cur = style[name]
-    elm.setStyle(normalize(name), cur)
+    supportBatchUpdate
+      ? (batchedStyles[normalize(name)] = cur)
+      : elm.setStyle(normalize(name), cur)
+  }
+  if (supportBatchUpdate) {
+    elm.setStyles(batchedStyles)
   }
 }
 
diff --git a/src/platforms/weex/runtime/modules/transition.js b/src/platforms/weex/runtime/modules/transition.js
index 86e3f6d..e474c2b 100644
--- a/src/platforms/weex/runtime/modules/transition.js
+++ b/src/platforms/weex/runtime/modules/transition.js
@@ -119,8 +119,12 @@ function enter (_, vnode) {
   beforeEnterHook && beforeEnterHook(el)
 
   if (startState) {
-    for (const key in startState) {
-      el.setStyle(key, startState[key])
+    if (typeof el.setStyles === 'function') {
+      el.setStyles(startState)
+    } else {
+      for (const key in startState) {
+        el.setStyle(key, startState[key])
+      }
     }
   }
 
diff --git a/src/server/bundle-renderer/create-bundle-runner.js b/src/server/bundle-renderer/create-bundle-runner.js
index a0e1d28..16c33c4 100644
--- a/src/server/bundle-renderer/create-bundle-runner.js
+++ b/src/server/bundle-renderer/create-bundle-runner.js
@@ -51,7 +51,7 @@ function compileModule (files, basedir, runInNewContext) {
       : script.runInNewContext(sandbox)
     const m = { exports: {}}
     const r = file => {
-      file = path.join('.', file)
+      file = path.posix.join('.', file)
       if (files[file]) {
         return evaluateModule(file, sandbox, evaluatedFiles)
       } else if (basedir) {
diff --git a/src/server/optimizing-compiler/codegen.js b/src/server/optimizing-compiler/codegen.js
index dfc4477..26097c0 100644
--- a/src/server/optimizing-compiler/codegen.js
+++ b/src/server/optimizing-compiler/codegen.js
@@ -205,6 +205,9 @@ function childrenToSegments (el, state): Array<StringSegment> {
   if ((binding = el.attrsMap['v-text'])) {
     return [{ type: INTERPOLATION, value: `_s(${binding})` }]
   }
+  if (el.tag === 'textarea' && (binding = el.attrsMap['v-model'])) {
+    return [{ type: INTERPOLATION, value: `_s(${binding})` }]
+  }
   return el.children
     ? nodesToSegments(el.children, state)
     : []
diff --git a/src/server/optimizing-compiler/modules.js b/src/server/optimizing-compiler/modules.js
index e01f5ed..41b1af1 100644
--- a/src/server/optimizing-compiler/modules.js
+++ b/src/server/optimizing-compiler/modules.js
@@ -31,6 +31,10 @@ export function applyModelTransform (el: ASTElement, state: CodegenState) {
       const dir = el.directives[i]
       if (dir.name === 'model') {
         state.directives.model(el, dir, state.warn)
+        // remove value for textarea as its converted to text
+        if (el.tag === 'textarea' && el.props) {
+          el.props = el.props.filter(p => p.name !== 'value')
+        }
         break
       }
     }
diff --git a/src/server/optimizing-compiler/optimizer.js b/src/server/optimizing-compiler/optimizer.js
index 82ac880..d24acc5 100644
--- a/src/server/optimizing-compiler/optimizer.js
+++ b/src/server/optimizing-compiler/optimizer.js
@@ -55,7 +55,7 @@ function walk (node: ASTNode, isRoot?: boolean) {
     if (node.ifConditions) {
       for (let i = 1, l = node.ifConditions.length; i < l; i++) {
         const block = node.ifConditions[i].block
-        walk(block)
+        walk(block, isRoot)
         check(block)
       }
     }
@@ -113,7 +113,8 @@ function isUnOptimizableTree (node: ASTNode): boolean {
   return (
     isBuiltInTag(node.tag) || // built-in (slot, component)
     !isPlatformReservedTag(node.tag) || // custom component
-    !!node.component // "is" component
+    !!node.component || // "is" component
+    isSelectWithModel(node) // <select v-model> requires runtime inspection
   )
 }
 
@@ -126,3 +127,14 @@ function hasCustomDirective (node: ASTNode): ?boolean {
     node.directives.some(d => !isBuiltInDir(d.name))
   )
 }
+
+// <select v-model> cannot be optimized because it requires a runtime check
+// to determine proper selected option
+function isSelectWithModel (node: ASTNode): boolean {
+  return (
+    node.type === 1 &&
+    node.tag === 'select' &&
+    node.directives != null &&
+    node.directives.some(d => d.name === 'model')
+  )
+}
diff --git a/src/server/render.js b/src/server/render.js
index 0ca49f7..0400aa7 100644
--- a/src/server/render.js
+++ b/src/server/render.js
@@ -252,8 +252,8 @@ function renderElement (el, isRoot, context) {
     el.data.attrs[SSR_ATTR] = 'true'
   }
 
-  if (el.functionalOptions) {
-    registerComponentForCache(el.functionalOptions, write)
+  if (el.fnOptions) {
+    registerComponentForCache(el.fnOptions, write)
   }
 
   const startTag = renderStartingTag(el, context)
diff --git a/src/shared/util.js b/src/shared/util.js
index 353b982..fe1c025 100644
--- a/src/shared/util.js
+++ b/src/shared/util.js
@@ -1,5 +1,7 @@
 /* @flow */
 
+export const emptyObject = Object.freeze({})
+
 // these helpers produces better vm code in JS engines due to their
 // explicitness and function inlining
 export function isUndef (v: any): boolean %checks {
diff --git a/test/ssr/ssr-string.spec.js b/test/ssr/ssr-string.spec.js
index 7e07ad1..3e8470f 100644
--- a/test/ssr/ssr-string.spec.js
+++ b/test/ssr/ssr-string.spec.js
@@ -989,6 +989,129 @@ describe('SSR: renderToString', () => {
       done()
     })
   })
+
+  // #6907
+  it('should not optimize root if conditions', done => {
+    renderVmWithOptions({
+      data: { foo: 123 },
+      template: `<input :type="'text'" v-model="foo">`
+    }, res => {
+      expect(res).toBe(`<input type="text" data-server-rendered="true" value="123">`)
+      done()
+    })
+  })
+
+  it('render muted properly', done => {
+    renderVmWithOptions({
+      template: '<video muted></video>'
+    }, result => {
+      expect(result).toContain('<video muted="muted" data-server-rendered="true"></video>')
+      done()
+    })
+  })
+
+  it('render v-model with textarea', done => {
+    renderVmWithOptions({
+      data: { foo: 'bar' },
+      template: '<div><textarea v-model="foo"></textarea></div>'
+    }, result => {
+      expect(result).toContain('<textarea>bar</textarea>')
+      done()
+    })
+  })
+
+  it('render v-model with textarea (non-optimized)', done => {
+    renderVmWithOptions({
+      render (h) {
+        return h('textarea', {
+          domProps: {
+            value: 'foo'
+          }
+        })
+      }
+    }, result => {
+      expect(result).toContain('<textarea data-server-rendered="true">foo</textarea>')
+      done()
+    })
+  })
+
+  it('render v-model with <select> (value binding)', done => {
+    renderVmWithOptions({
+      data: {
+        selected: 2,
+        options: [
+          { id: 1, label: 'one' },
+          { id: 2, label: 'two' }
+        ]
+      },
+      template: `
+      <div>
+        <select v-model="selected">
+          <option v-for="o in options" :value="o.id">{{ o.label }}</option>
+        </select>
+      </div>
+      `
+    }, result => {
+      expect(result).toContain(
+        '<select>' +
+          '<option value="1">one</option>' +
+          '<option selected="selected" value="2">two</option>' +
+        '</select>'
+      )
+      done()
+    })
+  })
+
+  it('render v-model with <select> (static value)', done => {
+    renderVmWithOptions({
+      data: {
+        selected: 2
+      },
+      template: `
+      <div>
+        <select v-model="selected">
+          <option value="1">one</option>
+          <option value="2">two</option>
+        </select>
+      </div>
+      `
+    }, result => {
+      expect(result).toContain(
+        '<select>' +
+          '<option value="1">one</option> ' +
+          '<option value="2" selected="selected">two</option>' +
+        '</select>'
+      )
+      done()
+    })
+  })
+
+  it('render v-model with <select> (text as value)', done => {
+    renderVmWithOptions({
+      data: {
+        selected: 2,
+        options: [
+          { id: 1, label: 'one' },
+          { id: 2, label: 'two' }
+        ]
+      },
+      template: `
+      <div>
+        <select v-model="selected">
+          <option v-for="o in options">{{ o.id }}</option>
+        </select>
+      </div>
+      `
+    }, result => {
+      expect(result).toContain(
+        '<select>' +
+          '<option>1</option>' +
+          '<option selected="selected">2</option>' +
+        '</select>'
+      )
+      done()
+    })
+  })
 })
 
 function renderVmWithOptions (options, cb) {
diff --git a/test/unit/features/component/component-async.spec.js b/test/unit/features/component/component-async.spec.js
index a63b8c0..889cb71 100644
--- a/test/unit/features/component/component-async.spec.js
+++ b/test/unit/features/component/component-async.spec.js
@@ -342,5 +342,34 @@ describe('Component async', () => {
         done()
       }, 50)
     })
+
+    // #7107
+    it(`should work when resolving sync in sibling component's mounted hook`, done => {
+      let resolveTwo
+
+      const vm = new Vue({
+        template: `<div><one/> <two/></div>`,
+        components: {
+          one: {
+            template: `<div>one</div>`,
+            mounted () {
+              resolveTwo()
+            }
+          },
+          two: resolve => {
+            resolveTwo = () => {
+              resolve({
+                template: `<div>two</div>`
+              })
+            }
+          }
+        }
+      }).$mount()
+
+      expect(vm.$el.textContent).toBe('one ')
+      waitForUpdate(() => {
+        expect(vm.$el.textContent).toBe('one two')
+      }).then(done)
+    })
   })
 })
diff --git a/test/unit/features/component/component-keep-alive.spec.js b/test/unit/features/component/component-keep-alive.spec.js
index d6dad4e..b89fbdc 100644
--- a/test/unit/features/component/component-keep-alive.spec.js
+++ b/test/unit/features/component/component-keep-alive.spec.js
@@ -477,6 +477,213 @@ describe('Component keep-alive', () => {
     }).then(done)
   })
 
+  it('max', done => {
+    const spyA = jasmine.createSpy()
+    const spyB = jasmine.createSpy()
+    const spyC = jasmine.createSpy()
+    const spyAD = jasmine.createSpy()
+    const spyBD = jasmine.createSpy()
+    const spyCD = jasmine.createSpy()
+
+    function assertCount (calls) {
+      expect([
+        spyA.calls.count(),
+        spyAD.calls.count(),
+        spyB.calls.count(),
+        spyBD.calls.count(),
+        spyC.calls.count(),
+        spyCD.calls.count()
+      ]).toEqual(calls)
+    }
+
+    const vm = new Vue({
+      template: `
+        <keep-alive max="2">
+          <component :is="n"></component>
+        </keep-alive>
+      `,
+      data: {
+        n: 'aa'
+      },
+      components: {
+        aa: {
+          template: '<div>a</div>',
+          created: spyA,
+          destroyed: spyAD
+        },
+        bb: {
+          template: '<div>bbb</div>',
+          created: spyB,
+          destroyed: spyBD
+        },
+        cc: {
+          template: '<div>ccc</div>',
+          created: spyC,
+          destroyed: spyCD
+        }
+      }
+    }).$mount()
+
+    assertCount([1, 0, 0, 0, 0, 0])
+    vm.n = 'bb'
+    waitForUpdate(() => {
+      assertCount([1, 0, 1, 0, 0, 0])
+      vm.n = 'cc'
+    }).then(() => {
+      // should prune A because max cache reached
+      assertCount([1, 1, 1, 0, 1, 0])
+      vm.n = 'bb'
+    }).then(() => {
+      // B should be reused, and made latest
+      assertCount([1, 1, 1, 0, 1, 0])
+      vm.n = 'aa'
+    }).then(() => {
+      // C should be pruned because B was used last so C is the oldest cached
+      assertCount([2, 1, 1, 0, 1, 1])
+    }).then(done)
+  })
+
+  it('should warn unknown component inside', () => {
+    new Vue({
+      template: `<keep-alive><foo/></keep-alive>`
+    }).$mount()
+    expect(`Unknown custom element: <foo>`).toHaveBeenWarned()
+  })
+
+  // #6938
+  it('should not cache anonymous component when include is specified', done => {
+    const Foo = {
+      name: 'foo',
+      template: `<div>foo</div>`,
+      created: jasmine.createSpy('foo')
+    }
+
+    const Bar = {
+      template: `<div>bar</div>`,
+      created: jasmine.createSpy('bar')
+    }
+
+    const Child = {
+      functional: true,
+      render (h, ctx) {
+        return h(ctx.props.view ? Foo : Bar)
+      }
+    }
+
+    const vm = new Vue({
+      template: `
+        <keep-alive include="foo">
+          <child :view="view"></child>
+        </keep-alive>
+      `,
+      data: {
+        view: true
+      },
+      components: { Child }
+    }).$mount()
+
+    function assert (foo, bar) {
+      expect(Foo.created.calls.count()).toBe(foo)
+      expect(Bar.created.calls.count()).toBe(bar)
+    }
+
+    expect(vm.$el.textContent).toBe('foo')
+    assert(1, 0)
+    vm.view = false
+    waitForUpdate(() => {
+      expect(vm.$el.textContent).toBe('bar')
+      assert(1, 1)
+      vm.view = true
+    }).then(() => {
+      expect(vm.$el.textContent).toBe('foo')
+      assert(1, 1)
+      vm.view = false
+    }).then(() => {
+      expect(vm.$el.textContent).toBe('bar')
+      assert(1, 2)
+    }).then(done)
+  })
+
+  it('should cache anonymous components if include is not specified', done => {
+    const Foo = {
+      template: `<div>foo</div>`,
+      created: jasmine.createSpy('foo')
+    }
+
+    const Bar = {
+      template: `<div>bar</div>`,
+      created: jasmine.createSpy('bar')
+    }
+
+    const Child = {
+      functional: true,
+      render (h, ctx) {
+        return h(ctx.props.view ? Foo : Bar)
+      }
+    }
+
+    const vm = new Vue({
+      template: `
+        <keep-alive>
+          <child :view="view"></child>
+        </keep-alive>
+      `,
+      data: {
+        view: true
+      },
+      components: { Child }
+    }).$mount()
+
+    function assert (foo, bar) {
+      expect(Foo.created.calls.count()).toBe(foo)
+      expect(Bar.created.calls.count()).toBe(bar)
+    }
+
+    expect(vm.$el.textContent).toBe('foo')
+    assert(1, 0)
+    vm.view = false
+    waitForUpdate(() => {
+      expect(vm.$el.textContent).toBe('bar')
+      assert(1, 1)
+      vm.view = true
+    }).then(() => {
+      expect(vm.$el.textContent).toBe('foo')
+      assert(1, 1)
+      vm.view = false
+    }).then(() => {
+      expect(vm.$el.textContent).toBe('bar')
+      assert(1, 1)
+    }).then(done)
+  })
+
+  // #7105
+  it('should not destroy active instance when pruning cache', done => {
+    const Foo = {
+      template: `<div>foo</div>`,
+      destroyed: jasmine.createSpy('destroyed')
+    }
+    const vm = new Vue({
+      template: `
+        <div>
+          <keep-alive :include="include">
+            <foo/>
+          </keep-alive>
+        </div>
+      `,
+      data: {
+        include: ['foo']
+      },
+      components: { Foo }
+    }).$mount()
+    // condition: a render where a previous component is reused
+    vm.include = ['foo']
+    waitForUpdate(() => {
+      vm.include = ['']
+    }).then(() => {
+      expect(Foo.destroyed).not.toHaveBeenCalled()
+    }).then(done)
+  })
+
   if (!isIE9) {
     it('with transition-mode out-in', done => {
       let next
@@ -946,71 +1153,5 @@ describe('Component keep-alive', () => {
         }).then(done)
       }
     })
-
-    it('max', done => {
-      const spyA = jasmine.createSpy()
-      const spyB = jasmine.createSpy()
-      const spyC = jasmine.createSpy()
-      const spyAD = jasmine.createSpy()
-      const spyBD = jasmine.createSpy()
-      const spyCD = jasmine.createSpy()
-
-      function assertCount (calls) {
-        expect([
-          spyA.calls.count(),
-          spyAD.calls.count(),
-          spyB.calls.count(),
-          spyBD.calls.count(),
-          spyC.calls.count(),
-          spyCD.calls.count()
-        ]).toEqual(calls)
-      }
-
-      const vm = new Vue({
-        template: `
-          <keep-alive max="2">
-            <component :is="n"></component>
-          </keep-alive>
-        `,
-        data: {
-          n: 'aa'
-        },
-        components: {
-          aa: {
-            template: '<div>a</div>',
-            created: spyA,
-            destroyed: spyAD
-          },
-          bb: {
-            template: '<div>bbb</div>',
-            created: spyB,
-            destroyed: spyBD
-          },
-          cc: {
-            template: '<div>ccc</div>',
-            created: spyC,
-            destroyed: spyCD
-          }
-        }
-      }).$mount()
-
-      assertCount([1, 0, 0, 0, 0, 0])
-      vm.n = 'bb'
-      waitForUpdate(() => {
-        assertCount([1, 0, 1, 0, 0, 0])
-        vm.n = 'cc'
-      }).then(() => {
-        // should prune A because max cache reached
-        assertCount([1, 1, 1, 0, 1, 0])
-        vm.n = 'bb'
-      }).then(() => {
-        // B should be reused, and made latest
-        assertCount([1, 1, 1, 0, 1, 0])
-        vm.n = 'aa'
-      }).then(() => {
-        // C should be pruned because B was used last so C is the oldest cached
-        assertCount([2, 1, 1, 0, 1, 1])
-      }).then(done)
-    })
   }
 })
diff --git a/test/unit/features/component/component-slot.spec.js b/test/unit/features/component/component-slot.spec.js
index 66e70da..28d6555 100644
--- a/test/unit/features/component/component-slot.spec.js
+++ b/test/unit/features/component/component-slot.spec.js
@@ -686,6 +686,7 @@ describe('Component slot', () => {
     expect(vm.$el.innerHTML).toBe('<div>default<span>foo</span></div>')
   })
 
+  // #6372, #6915
   it('should handle nested components in slots properly', done => {
     const TestComponent = {
       template: `
@@ -706,7 +707,10 @@ describe('Component slot', () => {
           <test-component ref="test">
             <div>
               <foo/>
-            </div><bar/>
+            </div>
+            <bar>
+              <foo/>
+            </bar>
           </test-component>
         </div>
       `,
@@ -716,16 +720,16 @@ describe('Component slot', () => {
           template: `<div>foo</div>`
         },
         bar: {
-          template: `<div>bar</div>`
+          template: `<div>bar<slot/></div>`
         }
       }
     }).$mount()
 
-    expect(vm.$el.innerHTML).toBe(`<b><div><div>foo</div></div><div>bar</div></b>`)
+    expect(vm.$el.innerHTML).toBe(`<b><div><div>foo</div></div> <div>bar<div>foo</div></div></b>`)
 
     vm.$refs.test.toggleEl = false
     waitForUpdate(() => {
-      expect(vm.$el.innerHTML).toBe(`<i><div><div>foo</div></div><div>bar</div></i>`)
+      expect(vm.$el.innerHTML).toBe(`<i><div><div>foo</div></div> <div>bar<div>foo</div></div></i>`)
     }).then(done)
   })
 
@@ -739,4 +743,85 @@ describe('Component slot', () => {
     }).$mount()
     expect(vm.$el.children[0].getAttribute('slot')).toBe('foo')
   })
+
+  it('passing a slot down as named slot', () => {
+    const Bar = {
+      template: `<div class="bar"><slot name="foo"/></div>`
+    }
+
+    const Foo = {
+      components: { Bar },
+      template: `<div class="foo"><bar><slot slot="foo"/></bar></div>`
+    }
+
+    const vm = new Vue({
+      components: { Foo },
+      template: `<div><foo>hello</foo></div>`
+    }).$mount()
+
+    expect(vm.$el.innerHTML).toBe('<div class="foo"><div class="bar">hello</div></div>')
+  })
+
+  it('fallback content for named template slot', () => {
+    const Bar = {
+      template: `<div class="bar"><slot name="foo">fallback</slot></div>`
+    }
+
+    const Foo = {
+      components: { Bar },
+      template: `<div class="foo"><bar><template slot="foo"/><slot/></template></bar></div>`
+    }
+
+    const vm = new Vue({
+      components: { Foo },
+      template: `<div><foo></foo></div>`
+    }).$mount()
+
+    expect(vm.$el.innerHTML).toBe('<div class="foo"><div class="bar">fallback</div></div>')
+  })
+
+  // #7106
+  it('should not lose functional slot across renders', done => {
+    const One = {
+      data: () => ({
+        foo: true
+      }),
+      render (h) {
+        this.foo
+        return h('div', this.$slots.slot)
+      }
+    }
+
+    const Two = {
+      render (h) {
+        return h('span', this.$slots.slot)
+      }
+    }
+
+    const Three = {
+      functional: true,
+      render: (h, { children }) => h('span', children)
+    }
+
+    const vm = new Vue({
+      template: `
+        <div>
+          <one ref="one">
+            <two slot="slot">
+              <three slot="slot">hello</three>
+            </two>
+          </one>
+        </div>
+      `,
+      components: { One, Two, Three }
+    }).$mount()
+
+    expect(vm.$el.textContent).toBe('hello')
+    // trigger re-render of <one>
+    vm.$refs.one.foo = false
+    waitForUpdate(() => {
+      // should still be there
+      expect(vm.$el.textContent).toBe('hello')
+    }).then(done)
+  })
 })
diff --git a/test/unit/features/directives/for.spec.js b/test/unit/features/directives/for.spec.js
index db92426..9f778b9 100644
--- a/test/unit/features/directives/for.spec.js
+++ b/test/unit/features/directives/for.spec.js
@@ -446,7 +446,7 @@ describe('Directive v-for', () => {
     }).then(done)
   })
 
-  it('strings', done => {
+  it('should work with strings', done => {
     const vm = new Vue({
       data: {
         text: 'foo'
@@ -463,4 +463,21 @@ describe('Directive v-for', () => {
       expect(vm.$el.textContent).toMatch('f.o.o.b.a.r.')
     }).then(done)
   })
+
+  const supportsDestructuring = (() => {
+    try {
+      new Function('var { foo } = bar')
+      return true
+    } catch (e) {}
+  })()
+
+  if (supportsDestructuring) {
+    it('should support destructuring syntax in alias position', () => {
+      const vm = new Vue({
+        data: { list: [{ foo: 'hi', bar: 'ho' }] },
+        template: '<div><div v-for="({ foo, bar }, i) in list">{{ foo }} {{ bar }} {{ i }}</div></div>'
+      }).$mount()
+      expect(vm.$el.textContent).toBe('hi ho 0')
+    })
+  }
 })
diff --git a/test/unit/features/directives/model-dynamic.spec.js b/test/unit/features/directives/model-dynamic.spec.js
index eb193f1..a5c18fe 100644
--- a/test/unit/features/directives/model-dynamic.spec.js
+++ b/test/unit/features/directives/model-dynamic.spec.js
@@ -40,6 +40,48 @@ describe('Directive v-model dynamic input type', () => {
     assertInputWorks(vm, chain).then(done)
   })
 
+  it('with v-else', done => {
+    const data = {
+      ok: true,
+      type: null,
+      test: 'b'
+    }
+    const vm = new Vue({
+      data,
+      template: `<div v-if="ok">haha</div><input v-else :type="type" v-model="test">`
+    }).$mount()
+    document.body.appendChild(vm.$el)
+    expect(vm.$el.textContent).toBe('haha')
+
+    vm.ok = false
+    assertInputWorks(vm).then(done)
+  })
+
+  it('with v-else-if', done => {
+    const vm = new Vue({
+      data: {
+        foo: true,
+        bar: false,
+        type: null,
+        test: 'b'
+      },
+      template: `<div v-if="foo">text</div><input v-else-if="bar" :type="type" v-model="test">`
+    }).$mount()
+    document.body.appendChild(vm.$el)
+
+    const chain = waitForUpdate(() => {
+      expect(vm.$el.textContent).toBe('text')
+    }).then(() => {
+      vm.foo = false
+    }).then(() => {
+      expect(vm._vnode.isComment).toBe(true)
+    }).then(() => {
+      vm.bar = true
+    })
+
+    assertInputWorks(vm, chain).then(done)
+  })
+
   it('with v-for', done => {
     const vm = new Vue({
       data: {
diff --git a/test/unit/features/directives/model-select.spec.js b/test/unit/features/directives/model-select.spec.js
index 7c265d2..c961224 100644
--- a/test/unit/features/directives/model-select.spec.js
+++ b/test/unit/features/directives/model-select.spec.js
@@ -546,4 +546,46 @@ describe('Directive v-model select', () => {
       expect(spy).not.toHaveBeenCalled()
     }).then(done)
   })
+
+  // #6903
+  describe('should correctly handle v-model when the vnodes are the same', () => {
+    function makeInstance (foo) {
+      return new Vue({
+        data: {
+          foo: foo,
+          options: ['b', 'c', 'd'],
+          value: 'c'
+        },
+        template:
+          '<div>' +
+            '<select v-if="foo" data-attr>' +
+              '<option selected>a</option>' +
+            '</select>' +
+            '<select v-else v-model="value">' +
+              '<option v-for="option in options" :value="option">{{ option }}</option>' +
+            '</select>' +
+          '</div>'
+      }).$mount()
+    }
+
+    it('register v-model', done => {
+      const vm = makeInstance(true)
+
+      expect(vm.$el.firstChild.selectedIndex).toBe(0)
+      vm.foo = false
+      waitForUpdate(() => {
+        expect(vm.$el.firstChild.selectedIndex).toBe(1)
+      }).then(done)
+    })
+
+    it('remove v-model', done => {
+      const vm = makeInstance(false)
+
+      expect(vm.$el.firstChild.selectedIndex).toBe(1)
+      vm.foo = true
+      waitForUpdate(() => {
+        expect(vm.$el.firstChild.selectedIndex).toBe(0)
+      }).then(done)
+    })
+  })
 })
diff --git a/test/unit/features/directives/model-text.spec.js b/test/unit/features/directives/model-text.spec.js
index 7e29135..7aae24b 100644
--- a/test/unit/features/directives/model-text.spec.js
+++ b/test/unit/features/directives/model-text.spec.js
@@ -1,5 +1,5 @@
 import Vue from 'vue'
-import { isIE9, isAndroid } from 'core/util/env'
+import { isIE9, isIE, isAndroid } from 'core/util/env'
 
 describe('Directive v-model text', () => {
   it('should update value both ways', done => {
@@ -250,6 +250,47 @@ describe('Directive v-model text', () => {
     expect('You are binding v-model directly to a v-for iteration alias').toHaveBeenWarned()
   })
 
+  it('warn if v-model and v-bind:value conflict', () => {
+    new Vue({
+      data: {
+        test: 'foo'
+      },
+      template: '<input type="text" v-model="test" v-bind:value="test">'
+    }).$mount()
+    expect('v-bind:value="test" conflicts with v-model').toHaveBeenWarned()
+  })
+
+  it('warn if v-model and :value conflict', () => {
+    new Vue({
+      data: {
+        test: 'foo'
+      },
+      template: '<input type="text" v-model="test" :value="test">'
+    }).$mount()
+    expect(':value="test" conflicts with v-model').toHaveBeenWarned()
+  })
+
+  it('should not warn on radio, checkbox, or custom component', () => {
+    new Vue({
+      data: { test: '' },
+      components: {
+        foo: {
+          props: ['model', 'value'],
+          model: { prop: 'model', event: 'change' },
+          template: `<div/>`
+        }
+      },
+      template: `
+        <div>
+          <input type="checkbox" v-model="test" :value="test">
+          <input type="radio" v-model="test" :value="test">
+          <foo v-model="test" :value="test"/>
+        </div>
+      `
+    }).$mount()
+    expect('conflicts with v-model').not.toHaveBeenWarned()
+  })
+
   if (!isAndroid) {
     it('does not trigger extra input events with single compositionend', () => {
       const spy = jasmine.createSpy()
@@ -371,4 +412,21 @@ describe('Directive v-model text', () => {
       }).then(done)
     })
   }
+
+  // #7138
+  if (isIE && !isIE9) {
+    it('should not fire input on initial render of textarea with placeholder in IE10/11', done => {
+      const el = document.createElement('div')
+      document.body.appendChild(el)
+      const vm = new Vue({
+        el,
+        data: { foo: null },
+        template: `<textarea v-model="foo" placeholder="bar"></textarea>`
+      })
+      setTimeout(() => {
+        expect(vm.foo).toBe(null)
+        done()
+      }, 17)
+    })
+  }
 })
diff --git a/test/unit/features/directives/on.spec.js b/test/unit/features/directives/on.spec.js
index a32bcaa..4ef3c69 100644
--- a/test/unit/features/directives/on.spec.js
+++ b/test/unit/features/directives/on.spec.js
@@ -693,13 +693,27 @@ describe('Directive v-on', () => {
     expect(prevented).toBe(true)
   })
 
-  it('should warn click.right', () => {
-    new Vue({
+  it('should transform click.right to contextmenu', () => {
+    const spy = jasmine.createSpy('click.right')
+    const vm = new Vue({
       template: `<div @click.right="foo"></div>`,
-      methods: { foo () {} }
+      methods: { foo: spy }
     }).$mount()
 
-    expect(`Use "contextmenu" instead`).toHaveBeenWarned()
+    triggerEvent(vm.$el, 'contextmenu')
+    expect(spy).toHaveBeenCalled()
+  })
+
+  it('should transform click.middle to mouseup', () => {
+    const spy = jasmine.createSpy('click.middle')
+    const vm = new Vue({
+      template: `<div @click.middle="foo"></div>`,
+      methods: { foo: spy }
+    }).$mount()
+    triggerEvent(vm.$el, 'mouseup', e => { e.button = 0 })
+    expect(spy).not.toHaveBeenCalled()
+    triggerEvent(vm.$el, 'mouseup', e => { e.button = 1 })
+    expect(spy).toHaveBeenCalled()
   })
 
   it('object syntax (no argument)', () => {
diff --git a/test/unit/features/directives/once.spec.js b/test/unit/features/directives/once.spec.js
index cdfdb01..eca8be0 100644
--- a/test/unit/features/directives/once.spec.js
+++ b/test/unit/features/directives/once.spec.js
@@ -335,6 +335,28 @@ describe('Directive v-once', () => {
       vm.ok = false // teardown component with v-once
     }).then(done) // should not throw
   })
+
+  // #6826
+  it('should render different component instances properly', done => {
+    const vm = new Vue({
+      components: {
+        foo: {
+          props: ['name'],
+          template: '<div v-once>{{ name }}</div>'
+        }
+      },
+      template: `
+        <div>
+          <foo name="a" v-once></foo>
+          <foo name="b" v-once></foo>
+        </div>
+      `
+    }).$mount()
+    waitForUpdate(() => {
+      expect(vm.$el.children[0].innerHTML).toBe('a')
+      expect(vm.$el.children[1].innerHTML).toBe('b')
+    }).then(done)
+  })
 })
 
 function expectTextContent (vm, text) {
diff --git a/test/unit/features/global-api/set-delete.spec.js b/test/unit/features/global-api/set-delete.spec.js
index d758422..d1c7f3d 100644
--- a/test/unit/features/global-api/set-delete.spec.js
+++ b/test/unit/features/global-api/set-delete.spec.js
@@ -80,6 +80,32 @@ describe('Global API: set/delete', () => {
         expect(vm.$el.innerHTML).toBe('<p>D</p><p>B</p><p>C</p>')
       }).then(done)
     })
+
+    // #6845
+    it('should not overwrite properties on prototype chain', () => {
+      class Model {
+        constructor () {
+          this._bar = null
+        }
+        get bar () {
+          return this._bar
+        }
+        set bar (newvalue) {
+          this._bar = newvalue
+        }
+      }
+
+      const vm = new Vue({
+        data: {
+          data: new Model()
+        }
+      })
+
+      Vue.set(vm.data, 'bar', 123)
+      expect(vm.data.bar).toBe(123)
+      expect(vm.data.hasOwnProperty('bar')).toBe(false)
+      expect(vm.data._bar).toBe(123)
+    })
   })
 
   describe('Vue.delete', () => {
diff --git a/test/unit/features/instance/methods-events.spec.js b/test/unit/features/instance/methods-events.spec.js
index be15007..8883457 100644
--- a/test/unit/features/instance/methods-events.spec.js
+++ b/test/unit/features/instance/methods-events.spec.js
@@ -41,6 +41,13 @@ describe('Instance methods events', () => {
     expect(spy.calls.count()).toBe(1)
   })
 
+  it('$off multi event without callback', () => {
+    vm.$on(['test1', 'test2'], spy)
+    vm.$off(['test1', 'test2'])
+    vm.$emit('test1')
+    expect(spy).not.toHaveBeenCalled()
+  })
+
   it('$once', () => {
     vm.$once('test', spy)
     vm.$emit('test', 1, 2, 3)
diff --git a/test/unit/features/transition/transition.spec.js b/test/unit/features/transition/transition.spec.js
index 1f2f214..5e4dcc7 100644
--- a/test/unit/features/transition/transition.spec.js
+++ b/test/unit/features/transition/transition.spec.js
@@ -1081,5 +1081,47 @@ if (!isIE9) {
         }).then(done)
       })
     })
+
+    // #6687
+    it('transition on child components with empty root node', done => {
+      const vm = new Vue({
+        template: `
+          <div>
+            <transition mode="out-in">
+              <component class="test" :is="view"></component>
+            </transition>
+          </div>
+        `,
+        data: { view: 'one' },
+        components: {
+          'one': {
+            template: '<div v-if="false">one</div>'
+          },
+          'two': {
+            template: '<div>two</div>'
+          }
+        }
+      }).$mount(el)
+
+      // should not apply transition on initial render by default
+      expect(vm.$el.innerHTML).toBe('<!---->')
+      vm.view = 'two'
+      waitForUpdate(() => {
+        expect(vm.$el.innerHTML).toBe('<div class="test v-enter v-enter-active">two</div>')
+      }).thenWaitFor(nextFrame).then(() => {
+        expect(vm.$el.children[0].className).toBe('test v-enter-active v-enter-to')
+      }).thenWaitFor(duration + buffer).then(() => {
+        expect(vm.$el.children[0].className).toBe('test')
+        vm.view = 'one'
+      }).then(() => {
+        // incoming comment node is appended instantly because it doesn't have
+        // data and therefore doesn't go through the transition module.
+        expect(vm.$el.innerHTML).toBe('<div class="test v-leave v-leave-active">two</div><!---->')
+      }).thenWaitFor(nextFrame).then(() => {
+        expect(vm.$el.children[0].className).toBe('test v-leave-active v-leave-to')
+      }).thenWaitFor(duration + buffer).then(() => {
+        expect(vm.$el.innerHTML).toBe('<!---->')
+      }).then(done)
+    })
   })
 }
diff --git a/test/unit/karma.base.config.js b/test/unit/karma.base.config.js
index 6860030..24b4a6a 100644
--- a/test/unit/karma.base.config.js
+++ b/test/unit/karma.base.config.js
@@ -19,7 +19,7 @@ var webpackConfig = {
       __WEEX__: false,
       'process.env': {
         NODE_ENV: '"development"',
-        TRANSITION_DURATION: 50,
+        TRANSITION_DURATION: process.env.CI ? 100 : 50,
         TRANSITION_BUFFER: 10
       }
     })
diff --git a/test/unit/modules/compiler/codegen.spec.js b/test/unit/modules/compiler/codegen.spec.js
index d8b6c7e..5e04266 100644
--- a/test/unit/modules/compiler/codegen.spec.js
+++ b/test/unit/modules/compiler/codegen.spec.js
@@ -478,7 +478,7 @@ describe('codegen', () => {
     // have "inline-template'"
     assertCodegen(
       '<my-component inline-template><p><span>hello world</span></p></my-component>',
-      `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")])])}}]}})}`
+      `with(this){return _c('my-component',{inlineTemplate:{render:function(){with(this){return _m(0,false,false)}},staticRenderFns:[function(){with(this){return _c('p',[_c('span',[_v("hello world")])])}}]}})}`
     )
     // "have inline-template attrs, but not having exactly one child element
     assertCodegen(
@@ -498,7 +498,7 @@ describe('codegen', () => {
   it('generate static trees inside v-for', () => {
     assertCodegen(
       `<div><div v-for="i in 10"><p><span></span></p></div></div>`,
-      `with(this){return _c('div',_l((10),function(i){return _c('div',[_m(0,true)])}))}`,
+      `with(this){return _c('div',_l((10),function(i){return _c('div',[_m(0,true,false)])}))}`,
       [`with(this){return _c('p',[_c('span')])}`]
     )
   })
diff --git a/test/unit/modules/compiler/parser.spec.js b/test/unit/modules/compiler/parser.spec.js
index c2bb6c2..4957da1 100644
--- a/test/unit/modules/compiler/parser.spec.js
+++ b/test/unit/modules/compiler/parser.spec.js
@@ -283,6 +283,45 @@ describe('parser', () => {
     expect(liAst.key).toBe('item.uid')
   })
 
+  it('v-for directive destructuring', () => {
+    let ast = parse('<ul><li v-for="{ foo } in items"></li></ul>', baseOptions)
+    let liAst = ast.children[0]
+    expect(liAst.for).toBe('items')
+    expect(liAst.alias).toBe('{ foo }')
+
+    // with paren
+    ast = parse('<ul><li v-for="({ foo }) in items"></li></ul>', baseOptions)
+    liAst = ast.children[0]
+    expect(liAst.for).toBe('items')
+    expect(liAst.alias).toBe('{ foo }')
+
+    // multi-var destructuring
+    ast = parse('<ul><li v-for="{ foo, bar, baz } in items"></li></ul>', baseOptions)
+    liAst = ast.children[0]
+    expect(liAst.for).toBe('items')
+    expect(liAst.alias).toBe('{ foo, bar, baz }')
+
+    // multi-var destructuring with paren
+    ast = parse('<ul><li v-for="({ foo, bar, baz }) in items"></li></ul>', baseOptions)
+    liAst = ast.children[0]
+    expect(liAst.for).toBe('items')
+    expect(liAst.alias).toBe('{ foo, bar, baz }')
+
+    // with index
+    ast = parse('<ul><li v-for="({ foo }, i) in items"></li></ul>', baseOptions)
+    liAst = ast.children[0]
+    expect(liAst.for).toBe('items')
+    expect(liAst.alias).toBe('{ foo }')
+    expect(liAst.iterator1).toBe('i')
+
+    // multi-var destructuring with index
+    ast = parse('<ul><li v-for="({ foo, bar, baz }, i) in items"></li></ul>', baseOptions)
+    liAst = ast.children[0]
+    expect(liAst.for).toBe('items')
+    expect(liAst.alias).toBe('{ foo, bar, baz }')
+    expect(liAst.iterator1).toBe('i')
+  })
+
   it('v-for directive invalid syntax', () => {
     parse('<ul><li v-for="item into items"></li></ul>', baseOptions)
     expect('Invalid v-for expression').toHaveBeenWarned()
@@ -395,6 +434,15 @@ describe('parser', () => {
     expect(ast.props[0].value).toBe('msg')
   })
 
+  // #6887
+  it('special case static attribute that must be props', () => {
+    const ast = parse('<video muted></video>', baseOptions)
+    expect(ast.attrs[0].name).toBe('muted')
+    expect(ast.attrs[0].value).toBe('""')
+    expect(ast.props[0].name).toBe('muted')
+    expect(ast.props[0].value).toBe('true')
+  })
+
   it('attribute with v-on', () => {
     const ast = parse('<input type="text" name="field1" :value="msg" @input="onInput">', baseOptions)
     expect(ast.events.input.value).toBe('onInput')
diff --git a/test/unit/modules/vdom/patch/edge-cases.spec.js b/test/unit/modules/vdom/patch/edge-cases.spec.js
index 7e14053..8793da2 100644
--- a/test/unit/modules/vdom/patch/edge-cases.spec.js
+++ b/test/unit/modules/vdom/patch/edge-cases.spec.js
@@ -246,4 +246,25 @@ describe('vdom patch: edge cases', () => {
     vm.$el.children[0].click()
     expect(spy).toHaveBeenCalled()
   })
+
+  // #7041
+  it('transition children with only deep bindings should be patched on update', done => {
+    const vm = new Vue({
+      template: `
+      <div>
+        <transition>
+          <div :style="style"></div>
+        </transition>
+      </div>
+      `,
+      data: () => ({
+        style: { color: 'red' }
+      })
+    }).$mount()
+    expect(vm.$el.children[0].style.color).toBe('red')
+    vm.style.color = 'green'
+    waitForUpdate(() => {
+      expect(vm.$el.children[0].style.color).toBe('green')
+    }).then(done)
+  })
 })
diff --git a/test/unit/modules/vdom/patch/hydration.spec.js b/test/unit/modules/vdom/patch/hydration.spec.js
index 42fb337..930ad47 100644
--- a/test/unit/modules/vdom/patch/hydration.spec.js
+++ b/test/unit/modules/vdom/patch/hydration.spec.js
@@ -150,6 +150,17 @@ describe('vdom patch: hydration', () => {
     expect('not matching server-rendered content').toHaveBeenWarned()
   })
 
+  it('should warn failed hydration when component is not properly registered', () => {
+    const dom = createMockSSRDOM('<div><foo></foo></div>')
+
+    new Vue({
+      template: '<div><foo></foo></div>'
+    }).$mount(dom)
+
+    expect('not matching server-rendered content').toHaveBeenWarned()
+    expect('Unknown custom element: <foo>').toHaveBeenWarned()
+  })
+
   it('should overwrite textNodes in the correct position but with mismatching text without warning', () => {
     const dom = createMockSSRDOM('<div><span>foo</span></div>')
 
@@ -342,4 +353,39 @@ describe('vdom patch: hydration', () => {
     }).$mount(dom)
     expect('not matching server-rendered content').not.toHaveBeenWarned()
   })
+
+  // #7063
+  it('should properly initialize dynamic style bindings for future updates', done => {
+    const dom = createMockSSRDOM('<div style="padding-left:0px"></div>')
+
+    const vm = new Vue({
+      data: {
+        style: { paddingLeft: '0px' }
+      },
+      template: `<div><div :style="style"></div></div>`
+    }).$mount(dom)
+
+    // should update
+    vm.style.paddingLeft = '100px'
+    waitForUpdate(() => {
+      expect(dom.children[0].style.paddingLeft).toBe('100px')
+    }).then(done)
+  })
+
+  it('should properly initialize dynamic class bindings for future updates', done => {
+    const dom = createMockSSRDOM('<div class="foo bar"></div>')
+
+    const vm = new Vue({
+      data: {
+        cls: [{ foo: true }, 'bar']
+      },
+      template: `<div><div :class="cls"></div></div>`
+    }).$mount(dom)
+
+    // should update
+    vm.cls[0].foo = false
+    waitForUpdate(() => {
+      expect(dom.children[0].className).toBe('bar')
+    }).then(done)
+  })
 })
diff --git a/test/weex/cases/cases.spec.js b/test/weex/cases/cases.spec.js
new file mode 100644
index 0000000..291600d
--- /dev/null
+++ b/test/weex/cases/cases.spec.js
@@ -0,0 +1,72 @@
+import fs from 'fs'
+import path from 'path'
+import {
+  compileVue,
+  createInstance,
+  getRoot,
+  getEvents,
+  fireEvent
+} from '../helpers'
+
+function readFile (filename) {
+  return fs.readFileSync(path.resolve(__dirname, filename), 'utf8')
+}
+
+function readObject (filename) {
+  return (new Function(`return ${readFile(filename)}`))()
+}
+
+// Create one-off render test case
+function createRenderTestCase (name) {
+  const source = readFile(`${name}.vue`)
+  const target = readObject(`${name}.vdom.js`)
+  return done => {
+    compileVue(source).then(code => {
+      const id = String(Date.now() * Math.random())
+      const instance = createInstance(id, code)
+      setTimeout(() => {
+        expect(getRoot(instance)).toEqual(target)
+        done()
+      }, 50)
+    }).catch(err => {
+      expect(err).toBe(null)
+      done()
+    })
+  }
+}
+
+// Create event test case, will trigger the first bind event
+function createEventTestCase (name) {
+  const source = readFile(`${name}.vue`)
+  const before = readObject(`${name}.before.vdom.js`)
+  const after = readObject(`${name}.after.vdom.js`)
+  return done => {
+    compileVue(source).then(code => {
+      const id = String(Date.now() * Math.random())
+      const instance = createInstance(id, code)
+      setTimeout(() => {
+        expect(getRoot(instance)).toEqual(before)
+        const event = getEvents(instance)[0]
+        fireEvent(instance, event.ref, event.type, {})
+        setTimeout(() => {
+          expect(getRoot(instance)).toEqual(after)
+          done()
+        }, 50)
+      }, 50)
+    }).catch(err => {
+      expect(err).toBe(null)
+      done()
+    })
+  }
+}
+
+describe('Usage', () => {
+  describe('render', () => {
+    it('sample', createRenderTestCase('render/sample'))
+  })
+
+  describe('event', () => {
+    it('click', createEventTestCase('event/click'))
+  })
+})
+
diff --git a/test/weex/cases/event/click.after.vdom.js b/test/weex/cases/event/click.after.vdom.js
new file mode 100644
index 0000000..eab1a36
--- /dev/null
+++ b/test/weex/cases/event/click.after.vdom.js
@@ -0,0 +1,10 @@
+({
+  type: 'div',
+  event: ['click'],
+  children: [{
+    type: 'text',
+    attr: {
+      value: '43'
+    }
+  }]
+})
diff --git a/test/weex/cases/event/click.before.vdom.js b/test/weex/cases/event/click.before.vdom.js
new file mode 100644
index 0000000..de278b3
--- /dev/null
+++ b/test/weex/cases/event/click.before.vdom.js
@@ -0,0 +1,10 @@
+({
+  type: 'div',
+  event: ['click'],
+  children: [{
+    type: 'text',
+    attr: {
+      value: '42'
+    }
+  }]
+})
diff --git a/test/weex/cases/event/click.vue b/test/weex/cases/event/click.vue
new file mode 100644
index 0000000..508782c
--- /dev/null
+++ b/test/weex/cases/event/click.vue
@@ -0,0 +1,20 @@
+<template>
+  <div @click="inc">
+    <text>{{count}}</text>
+  </div>
+</template>
+
+<script>
+  module.exports = {
+    data () {
+      return {
+        count: 42
+      }
+    },
+    methods: {
+      inc () {
+        this.count++
+      }
+    }
+  }
+</script>
diff --git a/test/weex/cases/render/sample.vdom.js b/test/weex/cases/render/sample.vdom.js
new file mode 100644
index 0000000..6e213a5
--- /dev/null
+++ b/test/weex/cases/render/sample.vdom.js
@@ -0,0 +1,17 @@
+({
+  type: 'div',
+  style: {
+    justifyContent: 'center'
+  },
+  children: [{
+    type: 'text',
+    attr: {
+      value: 'Yo'
+    },
+    style: {
+      color: '#41B883',
+      fontSize: '233px',
+      textAlign: 'center'
+    }
+  }]
+})
diff --git a/test/weex/cases/render/sample.vue b/test/weex/cases/render/sample.vue
new file mode 100644
index 0000000..0251b3d
--- /dev/null
+++ b/test/weex/cases/render/sample.vue
@@ -0,0 +1,23 @@
+<template>
+  <div style="justify-content:center">
+    <text class="freestyle">{{string}}</text>
+  </div>
+</template>
+
+<style scoped>
+  .freestyle {
+    color: #41B883;
+    font-size: 233px;
+    text-align: center;
+  }
+</style>
+
+<script>
+  module.exports = {
+    data () {
+      return {
+        string: 'Yo'
+      }
+    }
+  }
+</script>
diff --git a/test/weex/compiler/compile.spec.js b/test/weex/compiler/compile.spec.js
index 7a717f1..cd69c74 100644
--- a/test/weex/compiler/compile.spec.js
+++ b/test/weex/compiler/compile.spec.js
@@ -32,12 +32,12 @@ describe('compile basic', () => {
 
   it('should compile unary tag', () => {
     const inputCase = compile(`<div><input><text>abc</text></div>`)
-    expect(inputCase.render).toMatch(strToRegExp(`return _m(0)`))
+    expect(inputCase.render).toMatch(strToRegExp(`return _m(0,false,false)`))
     expect(inputCase.staticRenderFns).toMatch(strToRegExp(`_c('div',[_c('input'),_c('text',[_v("abc")])])`))
     expect(inputCase.errors).toEqual([])
 
     const imageCase = compile(`<div><image src="path"><text>abc</text></div>`)
-    expect(imageCase.render).toMatch(strToRegExp(`return _m(0)`))
+    expect(imageCase.render).toMatch(strToRegExp(`return _m(0,false,false)`))
     expect(imageCase.staticRenderFns).toMatch(strToRegExp(`_c('div',[_c('image',{attrs:{"src":"path"}}),_c('text',[_v("abc")])])`))
     expect(imageCase.errors).toEqual([])
 
@@ -54,7 +54,7 @@ describe('compile basic', () => {
         </div>
       </div>
     `)
-    expect(complexCase.render).toMatch(strToRegExp(`return _m(0)`))
+    expect(complexCase.render).toMatch(strToRegExp(`return _m(0,false,false)`))
     expect(complexCase.staticRenderFns).toMatch(strToRegExp(`_c('image',{attrs:{"src":"path"}}),_c('image'),_c('div'`))
     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")])]`))
     expect(complexCase.errors).toEqual([])
diff --git a/test/weex/helpers/index.js b/test/weex/helpers/index.js
index ca4b343..653ded3 100644
--- a/test/weex/helpers/index.js
+++ b/test/weex/helpers/index.js
@@ -1,6 +1,11 @@
 import * as Vue from '../../../packages/weex-vue-framework'
 import { compile } from '../../../packages/weex-template-compiler'
 import WeexRuntime from 'weex-js-runtime'
+import styler from 'weex-styler'
+
+const styleRE = /<\s*style\s*\w*>([^(<\/)]*)<\/\s*style\s*>/g
+const scriptRE = /<\s*script.*>([^]*)<\/\s*script\s*>/
+const templateRE = /<\s*template\s*>([^]*)<\/\s*template\s*>/
 
 console.debug = () => {}
 
@@ -10,6 +15,10 @@ export function strToRegExp (str) {
   return new RegExp(str.replace(matchOperatorsRe, '\\$&'))
 }
 
+function parseStatic (fns) {
+  return '[' + fns.map(fn => `function () { ${fn} }`).join(',') + ']'
+}
+
 export function compileAndStringify (template) {
   const { render, staticRenderFns } = compile(template)
   return {
@@ -18,8 +27,48 @@ export function compileAndStringify (template) {
   }
 }
 
-function parseStatic (fns) {
-  return '[' + fns.map(fn => `function () { ${fn} }`).join(',') + ']'
+/**
+ * Compile *.vue file into js code
+ * @param {string} source raw text of *.vue file
+ * @param {string} componentName whether compile to a component
+ */
+export function compileVue (source, componentName) {
+  return new Promise((resolve, reject) => {
+    if (!templateRE.test(source)) {
+      return reject('No Template!')
+    }
+    const scriptMatch = scriptRE.exec(source)
+    const script = scriptMatch ? scriptMatch[1] : ''
+    const { render, staticRenderFns } = compile(templateRE.exec(source)[1])
+
+    const generateCode = styles => (`
+      var test_case = Object.assign({
+        style: ${JSON.stringify(styles)},
+        render: function () { ${render} },
+        staticRenderFns: ${parseStatic(staticRenderFns)},
+      }, (function(){
+        var module = { exports: {} };
+        ${script};
+        return module.exports;
+      })());
+    ` + (componentName
+        ? `Vue.component('${componentName}', test_case);\n`
+        : `test_case.el = 'body';new Vue(test_case);`)
+    )
+
+    let cssText = ''
+    let styleMatch = null
+    while ((styleMatch = styleRE.exec(source))) {
+      cssText += `\n${styleMatch[1]}\n`
+    }
+    styler.parse(cssText, (error, result) => {
+      if (error) {
+        return reject(error)
+      }
+      resolve(generateCode(result.jsonStyle))
+    })
+    resolve(generateCode({}))
+  })
 }
 
 function isObject (object) {
@@ -47,6 +96,24 @@ export function getRoot (instance) {
   return omitUseless(instance.document.body.toJSON())
 }
 
+// Get all binding events in the instance
+export function getEvents (instance) {
+  const events = []
+  const recordEvent = node => {
+    if (!node) { return }
+    if (Array.isArray(node.event)) {
+      node.event.forEach(type => {
+        events.push({ ref: node.ref, type })
+      })
+    }
+    if (Array.isArray(node.children)) {
+      node.children.forEach(recordEvent)
+    }
+  }
+  recordEvent(instance.document.body.toJSON())
+  return events
+}
+
 export function fireEvent (instance, ref, type, event = {}) {
   const el = instance.document.getRef(ref)
   if (el) {
diff --git a/test/weex/runtime/components/richtext.spec.js b/test/weex/runtime/components/richtext.spec.js
index e6190b7..f1c21ca 100644
--- a/test/weex/runtime/components/richtext.spec.js
+++ b/test/weex/runtime/components/richtext.spec.js
@@ -199,7 +199,7 @@ describe('richtext component', () => {
         attr: {
           value: [{
             type: 'image',
-            style: { width: 150, height: 150 },
+            style: { width: '150px', height: '150px' },
             attr: { src: 'path/to/profile.png' }
           }]
         }
@@ -293,11 +293,11 @@ describe('richtext component', () => {
         attr: {
           value: [{
             type: 'span',
-            style: { fontSize: 16, color: '#FF6600' },
+            style: { fontSize: '16px', color: '#FF6600' },
             attr: { value: 'ABCD' }
           }, {
             type: 'image',
-            style: { width: 33.33, height: 66.67 },
+            style: { width: '33.33px', height: '66.67px' },
             attr: { src: 'path/to/A.png' }
           }]
         }
@@ -471,7 +471,7 @@ describe('richtext component', () => {
         attr: {
           value: [{
             type: 'span',
-            style: { fontSize: 32, color: '#F6F660' },
+            style: { fontSize: '32px', color: '#F6F660' },
             attr: { value: 'ABCD' }
           }, {
             type: 'span',
@@ -543,7 +543,7 @@ describe('richtext component', () => {
         attr: {
           value: [{
             type: 'span',
-            style: { fontSize: 24, color: '#ABCDEF' },
+            style: { fontSize: '24px', color: '#ABCDEF' },
             attr: { value: 'ABCD' }
           }, {
             type: 'span',
diff --git a/types/index.d.ts b/types/index.d.ts
index da58517..720180d 100644
--- a/types/index.d.ts
+++ b/types/index.d.ts
@@ -3,7 +3,8 @@ import { Vue } from "./vue";
 export default Vue;
 
 export {
-  CreateElement
+  CreateElement,
+  VueConstructor
 } from "./vue";
 
 export {
diff --git a/types/options.d.ts b/types/options.d.ts
index c4d822f..8401a93 100644
--- a/types/options.d.ts
+++ b/types/options.d.ts
@@ -9,8 +9,7 @@ type Constructor = {
 export type Component<Data=DefaultData<Vue>, Methods=DefaultMethods<Vue>, Computed=DefaultComputed, Props=DefaultProps> =
   | typeof Vue
   | FunctionalComponentOptions<Props>
-  | ThisTypedComponentOptionsWithArrayProps<Vue, Data, Methods, Computed, keyof Props>
-  | ThisTypedComponentOptionsWithRecordProps<Vue, Data, Methods, Computed, Props>;
+  | ComponentOptions<Vue, Data, Methods, Computed, Props>
 
 interface EsModuleComponent {
   default: Component
@@ -59,12 +58,12 @@ export interface ComponentOptions<
   PropsDef=PropsDefinition<DefaultProps>> {
   data?: Data;
   props?: PropsDef;
-  propsData?: Object;
+  propsData?: object;
   computed?: Accessors<Computed>;
   methods?: Methods;
   watch?: Record<string, WatchOptionsWithHandler<any> | WatchHandler<any> | string>;
 
-  el?: Element | String;
+  el?: Element | string;
   template?: string;
   render?(createElement: CreateElement): VNode;
   renderError?: (h: () => VNode, err: Error) => VNode;
@@ -84,10 +83,10 @@ export interface ComponentOptions<
 
   directives?: { [key: string]: DirectiveFunction | DirectiveOptions };
   components?: { [key: string]: Component<any, any, any, any> | AsyncComponent<any, any, any, any> };
-  transitions?: { [key: string]: Object };
+  transitions?: { [key: string]: object };
   filters?: { [key: string]: Function };
 
-  provide?: Object | (() => Object);
+  provide?: object | (() => object);
   inject?: InjectOptions;
 
   model?: {
diff --git a/types/test/options-test.ts b/types/test/options-test.ts
index e7cd8ba..e1edff3 100644
--- a/types/test/options-test.ts
+++ b/types/test/options-test.ts
@@ -196,7 +196,7 @@ Vue.component('component', {
       bind() {},
       inserted() {},
       update() {},
-      componentMounted() {},
+      componentUpdated() {},
       unbind() {}
     },
     b(el, binding, vnode, oldVnode) {
@@ -310,7 +310,10 @@ Vue.component("async-component", ((resolve, reject) => {
     resolve(Vue.component("component"));
   }, 0);
   return new Promise((resolve) => {
-    resolve({ functional: true });
+    resolve({
+      functional: true,
+      render(h: CreateElement) { return h('div') }
+    });
   })
 }));
 
diff --git a/types/test/ssr-test.ts b/types/test/ssr-test.ts
index a9377a4..ed6409a 100644
--- a/types/test/ssr-test.ts
+++ b/types/test/ssr-test.ts
@@ -46,6 +46,14 @@ renderer.renderToString(app)
     throw err;
   });
 
+renderer.renderToString(app, context)
+  .then(html => {
+    const res: string = html;
+  })
+  .catch(err => {
+    throw err;
+  });
+
 renderer.renderToStream(app, context).on('data', chunk => {
   const html = chunk.toString();
 });
@@ -95,6 +103,14 @@ bundleRenderer.renderToString(context, (err, html) => {
   const res: string = html;
 });
 
+bundleRenderer.renderToString().then(html => {
+  const res: string = html;
+});
+
+bundleRenderer.renderToString(context).then(html => {
+  const res: string = html;
+});
+
 bundleRenderer.renderToStream(context).on('data', chunk => {
   const html = chunk.toString();
 });
diff --git a/types/test/tsconfig.json b/types/test/tsconfig.json
index 784de82..15809b5 100644
--- a/types/test/tsconfig.json
+++ b/types/test/tsconfig.json
@@ -7,7 +7,11 @@
     ],
     "module": "commonjs",
     "strict": true,
-    "noEmit": true
+    "noEmit": true,
+    "baseUrl": ".",
+    "paths": {
+      "vue": ["../index.d.ts"]
+    }
   },
   "files": [
     "../index.d.ts",
diff --git a/types/vnode.d.ts b/types/vnode.d.ts
index ae72065..2fd2ef1 100644
--- a/types/vnode.d.ts
+++ b/types/vnode.d.ts
@@ -27,8 +27,8 @@ export interface VNode {
 
 export interface VNodeComponentOptions {
   Ctor: typeof Vue;
-  propsData?: Object;
-  listeners?: Object;
+  propsData?: object;
+  listeners?: object;
   children?: VNodeChildren;
   tag?: string;
 }
@@ -42,14 +42,14 @@ export interface VNodeData {
   staticClass?: string;
   class?: any;
   staticStyle?: { [key: string]: any };
-  style?: Object[] | Object;
+  style?: object[] | object;
   props?: { [key: string]: any };
   attrs?: { [key: string]: any };
   domProps?: { [key: string]: any };
   hook?: { [key: string]: Function };
   on?: { [key: string]: Function | Function[] };
   nativeOn?: { [key: string]: Function | Function[] };
-  transition?: Object;
+  transition?: object;
   show?: boolean;
   inlineTemplate?: {
     render: Function;
diff --git a/types/vue.d.ts b/types/vue.d.ts
index 0672226..e143145 100644
--- a/types/vue.d.ts
+++ b/types/vue.d.ts
@@ -16,13 +16,13 @@ import { VNode, VNodeData, VNodeChildren, ScopedSlot } from "./vnode";
 import { PluginFunction, PluginObject } from "./plugin";
 
 export interface CreateElement {
-  (tag?: string | Component<any, any, any, any> | AsyncComponent<any, any, any, any>, children?: VNodeChildren): VNode;
-  (tag?: string | Component<any, any, any, any> | AsyncComponent<any, any, any, any>, data?: VNodeData, children?: VNodeChildren): VNode;
+  (tag?: string | Component<any, any, any, any> | AsyncComponent<any, any, any, any> | (() => Component), children?: VNodeChildren): VNode;
+  (tag?: string | Component<any, any, any, any> | AsyncComponent<any, any, any, any> | (() => Component), data?: VNodeData, children?: VNodeChildren): VNode;
 }
 
 export interface Vue {
   readonly $el: HTMLElement;
-  readonly $options: ComponentOptions<this>;
+  readonly $options: ComponentOptions<Vue>;
   readonly $parent: Vue;
   readonly $root: Vue;
   readonly $children: Vue[];
@@ -37,7 +37,7 @@ export interface Vue {
   readonly $attrs: Record<string, string>;
   readonly $listeners: Record<string, Function | Function[]>;
 
-  $mount(elementOrSelector?: Element | String, hydrating?: boolean): this;
+  $mount(elementOrSelector?: Element | string, hydrating?: boolean): this;
   $forceUpdate(): void;
   $destroy(): void;
   $set: typeof Vue.set;
@@ -61,7 +61,7 @@ export interface Vue {
   $createElement: CreateElement;
 }
 
-export type CombinedVueInstance<Instance extends Vue, Data, Methods, Computed, Props> = Instance & Data & Methods & Computed & Props;
+export type CombinedVueInstance<Instance extends Vue, Data, Methods, Computed, Props> =  Data & Methods & Computed & Props & Instance;
 export type ExtendedVue<Instance extends Vue, Data, Methods, Computed, Props> = VueConstructor<CombinedVueInstance<Instance, Data, Methods, Computed, Props> & Vue>;
 
 export interface VueConstructor<V extends Vue = Vue> {
@@ -72,15 +72,15 @@ export interface VueConstructor<V extends Vue = Vue> {
 
   extend<PropNames extends string = never>(definition: FunctionalComponentOptions<Record<PropNames, any>, PropNames[]>): ExtendedVue<V, {}, {}, {}, Record<PropNames, any>>;
   extend<Props>(definition: FunctionalComponentOptions<Props, RecordPropsDefinition<Props>>): ExtendedVue<V, {}, {}, {}, Props>;
-  extend<Data, Methods, Computed, PropNames extends string>(options?: ThisTypedComponentOptionsWithArrayProps<V, Data, Methods, Computed, PropNames>): ExtendedVue<V, Data, Methods, Computed, Record<PropNames, any>>;
+  extend<Data, Methods, Computed, PropNames extends string = never>(options?: ThisTypedComponentOptionsWithArrayProps<V, Data, Methods, Computed, PropNames>): ExtendedVue<V, Data, Methods, Computed, Record<PropNames, any>>;
   extend<Data, Methods, Computed, Props>(options?: ThisTypedComponentOptionsWithRecordProps<V, Data, Methods, Computed, Props>): ExtendedVue<V, Data, Methods, Computed, Props>;
   extend(options?: ComponentOptions<V>): ExtendedVue<V, {}, {}, {}, {}>;
 
   nextTick(callback: () => void, context?: any[]): void;
   nextTick(): Promise<void>
-  set<T>(object: Object, key: string, value: T): T;
+  set<T>(object: object, key: string, value: T): T;
   set<T>(array: T[], key: number, value: T): T;
-  delete(object: Object, key: string): void;
+  delete(object: object, key: string): void;
   delete<T>(array: T[], key: number): void;
 
   directive(
@@ -94,7 +94,7 @@ export interface VueConstructor<V extends Vue = Vue> {
   component<Data, Methods, Computed, Props>(id: string, definition: AsyncComponent<Data, Methods, Computed, Props>): ExtendedVue<V, Data, Methods, Computed, Props>;
   component<PropNames extends string>(id: string, definition: FunctionalComponentOptions<Record<PropNames, any>, PropNames[]>): ExtendedVue<V, {}, {}, {}, Record<PropNames, any>>;
   component<Props>(id: string, definition: FunctionalComponentOptions<Props, RecordPropsDefinition<Props>>): ExtendedVue<V, {}, {}, {}, Props>;
-  component<Data, Methods, Computed, PropNames extends string>(id: string, definition?: ThisTypedComponentOptionsWithArrayProps<V, Data, Methods, Computed, PropNames>): ExtendedVue<V, Data, Methods, Computed, Record<PropNames, any>>;
+  component<Data, Methods, Computed, PropNames extends string = never>(id: string, definition?: ThisTypedComponentOptionsWithArrayProps<V, Data, Methods, Computed, PropNames>): ExtendedVue<V, Data, Methods, Computed, Record<PropNames, any>>;
   component<Data, Methods, Computed, Props>(id: string, definition?: ThisTypedComponentOptionsWithRecordProps<V, Data, Methods, Computed, Props>): ExtendedVue<V, Data, Methods, Computed, Props>;
   component(id: string, definition?: ComponentOptions<V>): ExtendedVue<V, {}, {}, {}, {}>;
 

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/vue.js.git



More information about the Pkg-javascript-commits mailing list