[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