Skip to content

introduce a warning with misusage binding in dev mode #4084

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions src/compiler/parser/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,9 @@ function processAttrs (el) {
name = name.replace(modifierRE, '')
}
if (bindRE.test(name)) { // v-bind
if (process.env.NODE_ENV !== 'production') {
checkVBindingVal(rawName, value)
}
name = name.replace(bindRE, '')
if (modifiers && modifiers.prop) {
isProp = true
Expand All @@ -382,6 +385,9 @@ function processAttrs (el) {
addHandler(el, name, value, modifiers)
} else { // normal directives
name = name.replace(dirRE, '')
if (process.env.NODE_ENV !== 'production' && name === 'bind') {
checkVBindingVal(rawName, value)
}
// parse arg
const argMatch = name.match(argRE)
if (argMatch && (arg = argMatch[1])) {
Expand Down Expand Up @@ -410,6 +416,31 @@ function processAttrs (el) {
}
}

function checkVBindingVal (name: string, value: string): void {
let func

// there may be template error, leave it to the compiler detectErrors
try {
func = new Function(`(${value})`)
} catch (ex) {
return
}

try {
func()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While being a savvy technique, this is also very very dangerous. It will introduce code execution, especially if expression is passed from user input or database.

Copy link
Member Author

@defcc defcc Nov 2, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

En, this is just a check in dev mode. If the expression passed down is plain js code like 'alert(1)', it'll be warned.

<component :val="alert(1)"></component>

} catch (ex) {
return
}
// if v-bind value is literal, the evaluation causes no error, we should introduce a warning.
warn(
`${name}="${value}": ` +
`You are using v-bind with literal. ` +
`To get better performance, ` +
`if is an object/array literal, save the literal in data/computed property, use like <component :ids="list"> instead of <component :ids="[1,2,3]">; ` +
`otherwise use like <component ids="1"> instead of <component :ids="1">`
)
}

function checkInFor (el: ASTElement): boolean {
let parent = el
while (parent) {
Expand Down
5 changes: 5 additions & 0 deletions test/unit/modules/compiler/parser.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,11 @@ describe('parser', () => {
expect(ast.props[0].value).toBe('msg')
})

it('warn v-bind with literal', () => {
parse('<my-component :value="{}"></my-component>', baseOptions)
expect('You are using v-bind with literal').toHaveBeenWarned()
})

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')
Expand Down