diff --git a/packages/weex-vue-framework/factory.js b/packages/weex-vue-framework/factory.js
index 8bcfb675ba9..fb30d12bbbd 100644
--- a/packages/weex-vue-framework/factory.js
+++ b/packages/weex-vue-framework/factory.js
@@ -5797,7 +5797,7 @@ function createPatchFunction (backend) {
}
}
- function removeVnodes (parentElm, vnodes, startIdx, endIdx) {
+ function removeVnodes (vnodes, startIdx, endIdx) {
for (; startIdx <= endIdx; ++startIdx) {
var ch = vnodes[startIdx];
if (isDef(ch)) {
@@ -5908,7 +5908,7 @@ function createPatchFunction (backend) {
refElm = isUndef(newCh[newEndIdx + 1]) ? null : newCh[newEndIdx + 1].elm;
addVnodes(parentElm, refElm, newCh, newStartIdx, newEndIdx, insertedVnodeQueue);
} else if (newStartIdx > newEndIdx) {
- removeVnodes(parentElm, oldCh, oldStartIdx, oldEndIdx);
+ removeVnodes(oldCh, oldStartIdx, oldEndIdx);
}
}
@@ -5985,7 +5985,7 @@ function createPatchFunction (backend) {
if (isDef(oldVnode.text)) { nodeOps.setTextContent(elm, ''); }
addVnodes(elm, null, ch, 0, ch.length - 1, insertedVnodeQueue);
} else if (isDef(oldCh)) {
- removeVnodes(elm, oldCh, 0, oldCh.length - 1);
+ removeVnodes(oldCh, 0, oldCh.length - 1);
} else if (isDef(oldVnode.text)) {
nodeOps.setTextContent(elm, '');
}
@@ -6216,7 +6216,7 @@ function createPatchFunction (backend) {
// destroy old node
if (isDef(parentElm$1)) {
- removeVnodes(parentElm$1, [oldVnode], 0, 0);
+ removeVnodes([oldVnode], 0, 0);
} else if (isDef(oldVnode.tag)) {
invokeDestroyHook(oldVnode);
}
diff --git a/src/compiler/error-detector.js b/src/compiler/error-detector.js
index 22c3b75d3aa..9893aa4a47a 100644
--- a/src/compiler/error-detector.js
+++ b/src/compiler/error-detector.js
@@ -36,6 +36,8 @@ function checkNode (node: ASTNode, warn: Function) {
const range = node.rawAttrsMap[name]
if (name === 'v-for') {
checkFor(node, `v-for="${value}"`, warn, range)
+ } else if (name === 'v-slot' || name[0] === '#') {
+ checkFunctionParameterExpression(value, `${name}="${value}"`, warn, range)
} else if (onRE.test(name)) {
checkEvent(value, `${name}="${value}"`, warn, range)
} else {
@@ -111,3 +113,16 @@ function checkExpression (exp: string, text: string, warn: Function, range?: Ran
}
}
}
+
+function checkFunctionParameterExpression (exp: string, text: string, warn: Function, range?: Range) {
+ try {
+ new Function(exp, '')
+ } catch (e) {
+ warn(
+ `invalid function parameter expression: ${e.message} in\n\n` +
+ ` ${exp}\n\n` +
+ ` Raw expression: ${text.trim()}\n`,
+ range
+ )
+ }
+}
diff --git a/src/compiler/parser/index.js b/src/compiler/parser/index.js
index fb258752179..cdeb257eda4 100644
--- a/src/compiler/parser/index.js
+++ b/src/compiler/parser/index.js
@@ -23,8 +23,8 @@ import {
export const onRE = /^@|^v-on:/
export const dirRE = process.env.VBIND_PROP_SHORTHAND
- ? /^v-|^@|^:|^\./
- : /^v-|^@|^:/
+ ? /^v-|^@|^:|^\.|^#/
+ : /^v-|^@|^:|^#/
export const forAliasRE = /([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/
export const forIteratorRE = /,([^,\}\]]*)(?:,([^,\}\]]*))?$/
const stripParensRE = /^\(|\)$/g
diff --git a/src/core/util/env.js b/src/core/util/env.js
index eff1d21dc75..820bacdb405 100644
--- a/src/core/util/env.js
+++ b/src/core/util/env.js
@@ -87,11 +87,10 @@ if (typeof Set !== 'undefined' && isNative(Set)) {
}
}
-interface SimpleSet {
+export interface SimpleSet {
has(key: string | number): boolean;
add(key: string | number): mixed;
clear(): void;
}
export { _Set }
-export type { SimpleSet }
diff --git a/src/core/vdom/create-element.js b/src/core/vdom/create-element.js
index 46027084b51..ba36e15b12d 100644
--- a/src/core/vdom/create-element.js
+++ b/src/core/vdom/create-element.js
@@ -98,6 +98,12 @@ export function _createElement (
ns = (context.$vnode && context.$vnode.ns) || config.getTagNamespace(tag)
if (config.isReservedTag(tag)) {
// platform built-in elements
+ if (process.env.NODE_ENV !== 'production' && isDef(data) && isDef(data.nativeOn)) {
+ warn(
+ `The .native modifier for v-on is only valid on components but it was used on <${tag}>.`,
+ context
+ )
+ }
vnode = new VNode(
config.parsePlatformTagName(tag), data, children,
undefined, undefined, context
diff --git a/src/core/vdom/patch.js b/src/core/vdom/patch.js
index 9746bb794f8..95a4db47298 100644
--- a/src/core/vdom/patch.js
+++ b/src/core/vdom/patch.js
@@ -16,6 +16,7 @@ import { SSR_ATTR } from 'shared/constants'
import { registerRef } from './modules/ref'
import { traverse } from '../observer/traverse'
import { activeInstance } from '../instance/lifecycle'
+import { inBrowser } from '../util/index';
import { isTextInputType } from 'web/util/element'
import {
@@ -32,6 +33,8 @@ export const emptyNode = new VNode('', {}, [])
const hooks = ['create', 'activate', 'update', 'remove', 'destroy']
+const customElements = inBrowser ? window.customElements : undefined
+
function sameVnode (a, b) {
return (
a.key === b.key && (
@@ -106,6 +109,7 @@ export function createPatchFunction (backend) {
function isUnknownElement (vnode, inVPre) {
return (
+ !(customElements && customElements.get(vnode.tag)) &&
!inVPre &&
!vnode.ns &&
!(
@@ -358,7 +362,7 @@ export function createPatchFunction (backend) {
}
}
- function removeVnodes (parentElm, vnodes, startIdx, endIdx) {
+ function removeVnodes (vnodes, startIdx, endIdx) {
for (; startIdx <= endIdx; ++startIdx) {
const ch = vnodes[startIdx]
if (isDef(ch)) {
@@ -469,7 +473,7 @@ export function createPatchFunction (backend) {
refElm = isUndef(newCh[newEndIdx + 1]) ? null : newCh[newEndIdx + 1].elm
addVnodes(parentElm, refElm, newCh, newStartIdx, newEndIdx, insertedVnodeQueue)
} else if (newStartIdx > newEndIdx) {
- removeVnodes(parentElm, oldCh, oldStartIdx, oldEndIdx)
+ removeVnodes(oldCh, oldStartIdx, oldEndIdx)
}
}
@@ -561,7 +565,7 @@ export function createPatchFunction (backend) {
if (isDef(oldVnode.text)) nodeOps.setTextContent(elm, '')
addVnodes(elm, null, ch, 0, ch.length - 1, insertedVnodeQueue)
} else if (isDef(oldCh)) {
- removeVnodes(elm, oldCh, 0, oldCh.length - 1)
+ removeVnodes(oldCh, 0, oldCh.length - 1)
} else if (isDef(oldVnode.text)) {
nodeOps.setTextContent(elm, '')
}
@@ -790,7 +794,7 @@ export function createPatchFunction (backend) {
// destroy old node
if (isDef(parentElm)) {
- removeVnodes(parentElm, [oldVnode], 0, 0)
+ removeVnodes([oldVnode], 0, 0)
} else if (isDef(oldVnode.tag)) {
invokeDestroyHook(oldVnode)
}
diff --git a/test/e2e/nightwatch.config.js b/test/e2e/nightwatch.config.js
index 2004f92b45b..8ec592494fe 100644
--- a/test/e2e/nightwatch.config.js
+++ b/test/e2e/nightwatch.config.js
@@ -50,7 +50,8 @@ module.exports = {
'desiredCapabilities': {
'browserName': 'phantomjs',
'javascriptEnabled': true,
- 'acceptSslCerts': true
+ 'acceptSslCerts': true,
+ 'phantomjs.binary.path': require('phantomjs-prebuilt').path
}
}
}
diff --git a/test/unit/features/component/component-scoped-slot.spec.js b/test/unit/features/component/component-scoped-slot.spec.js
index f8a0f11b7fa..28369814f48 100644
--- a/test/unit/features/component/component-scoped-slot.spec.js
+++ b/test/unit/features/component/component-scoped-slot.spec.js
@@ -759,6 +759,22 @@ describe('Component scoped slot', () => {
}).$mount()
expect(`Unexpected mixed usage of different slot syntaxes`).toHaveBeenWarned()
})
+
+ it('should warn invalid parameter expression', () => {
+ new Vue({
+ template: ``,
+ components: { Foo }
+ }).$mount();
+ expect('invalid function parameter expression').toHaveBeenWarned()
+ })
+
+ it('should allow destructuring props with default value', () => {
+ new Vue({
+ template: ``,
+ components: { Foo }
+ }).$mount();
+ expect('invalid function parameter expression').not.toHaveBeenWarned()
+ })
}
// run tests for both full syntax and shorthand
diff --git a/test/unit/features/directives/on.spec.js b/test/unit/features/directives/on.spec.js
index a97ddaa8947..b7801a82f22 100644
--- a/test/unit/features/directives/on.spec.js
+++ b/test/unit/features/directives/on.spec.js
@@ -460,6 +460,20 @@ describe('Directive v-on', () => {
expect(spy).toHaveBeenCalled()
})
+ it('should throw a warning if native modifier is used on native HTML element', () => {
+ vm = new Vue({
+ el,
+ template: `
+
+ `,
+ methods: { foo: spy },
+ })
+
+ triggerEvent(vm.$el, 'click')
+ expect(`The .native modifier for v-on is only valid on components but it was used on