Skip to content

Commit 38ee967

Browse files
committed
improve warnings
1 parent 0e8e40a commit 38ee967

File tree

26 files changed

+120
-130
lines changed

26 files changed

+120
-130
lines changed

src/batcher.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,12 @@ function runBatcherQueue (queue) {
6666
if (process.env.NODE_ENV !== 'production' && has[id] != null) {
6767
circular[id] = (circular[id] || 0) + 1
6868
if (circular[id] > config._maxUpdateCount) {
69-
queue.splice(has[id], 1)
7069
warn(
7170
'You may have an infinite update loop for watcher ' +
72-
'with expression: ' + watcher.expression
71+
'with expression "' + watcher.expression + '"',
72+
watcher.vm
7373
)
74+
break
7475
}
7576
}
7677
}

src/compiler/compile-props.js

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,11 @@ const settablePathRE = /^[A-Za-z_$][\w$]*(\.[A-Za-z_$][\w$]*|\[[^\[\]]+\])*$/
3131
*
3232
* @param {Element|DocumentFragment} el
3333
* @param {Array} propOptions
34+
* @param {Vue} vm
3435
* @return {Function} propsLinkFn
3536
*/
3637

37-
export function compileProps (el, propOptions) {
38+
export function compileProps (el, propOptions, vm) {
3839
var props = []
3940
var names = Object.keys(propOptions)
4041
var i = names.length
@@ -44,7 +45,7 @@ export function compileProps (el, propOptions) {
4445
options = propOptions[name] || empty
4546

4647
if (process.env.NODE_ENV !== 'production' && name === '$data') {
47-
warn('Do not use $data as prop.')
48+
warn('Do not use $data as prop.', vm)
4849
continue
4950
}
5051

@@ -55,7 +56,8 @@ export function compileProps (el, propOptions) {
5556
if (!identRE.test(path)) {
5657
process.env.NODE_ENV !== 'production' && warn(
5758
'Invalid prop key: "' + name + '". Prop keys ' +
58-
'must be valid identifiers.'
59+
'must be valid identifiers.',
60+
vm
5961
)
6062
continue
6163
}
@@ -98,7 +100,8 @@ export function compileProps (el, propOptions) {
98100
prop.mode = propBindingModes.ONE_WAY
99101
warn(
100102
'Cannot bind two-way prop with non-settable ' +
101-
'parent path: ' + value
103+
'parent path: ' + value,
104+
vm
102105
)
103106
}
104107
}
@@ -111,7 +114,8 @@ export function compileProps (el, propOptions) {
111114
prop.mode !== propBindingModes.TWO_WAY
112115
) {
113116
warn(
114-
'Prop "' + name + '" expects a two-way binding type.'
117+
'Prop "' + name + '" expects a two-way binding type.',
118+
vm
115119
)
116120
}
117121
} else if ((value = getAttr(el, attr)) !== null) {
@@ -133,11 +137,12 @@ export function compileProps (el, propOptions) {
133137
warn(
134138
'Possible usage error for prop `' + lowerCaseName + '` - ' +
135139
'did you mean `' + attr + '`? HTML is case-insensitive, remember to use ' +
136-
'kebab-case for props in templates.'
140+
'kebab-case for props in templates.',
141+
vm
137142
)
138143
} else if (options.required) {
139144
// warn missing required
140-
warn('Missing required prop: ' + name)
145+
warn('Missing required prop: ' + name, vm)
141146
}
142147
}
143148
// push prop
@@ -222,7 +227,7 @@ export function initProp (vm, prop, value) {
222227
const key = prop.path
223228
value = coerceProp(prop, value)
224229
if (value === undefined) {
225-
value = getPropDefaultValue(vm, prop.options)
230+
value = getPropDefaultValue(vm, prop)
226231
}
227232
if (!assertProp(prop, value, vm)) {
228233
value = undefined
@@ -234,12 +239,13 @@ export function initProp (vm, prop, value) {
234239
* Get the default value of a prop.
235240
*
236241
* @param {Vue} vm
237-
* @param {Object} options
242+
* @param {Object} prop
238243
* @return {*}
239244
*/
240245

241-
function getPropDefaultValue (vm, options) {
246+
function getPropDefaultValue (vm, prop) {
242247
// no default, return undefined
248+
const options = prop.options
243249
if (!hasOwn(options, 'default')) {
244250
// absent boolean value defaults to false
245251
return options.type === Boolean
@@ -250,9 +256,10 @@ function getPropDefaultValue (vm, options) {
250256
// warn against non-factory defaults for Object & Array
251257
if (isObject(def)) {
252258
process.env.NODE_ENV !== 'production' && warn(
253-
'Object/Array as default prop values will be shared ' +
254-
'across multiple instances. Use a factory function ' +
255-
'to return the default value instead.'
259+
'Invalid default value for prop "' + prop.name + '": ' +
260+
'Props with type Object/Array must use a factory function ' +
261+
'to return the default value.',
262+
vm
256263
)
257264
}
258265
// call factory function for non-Function types
@@ -308,10 +315,10 @@ export function assertProp (prop, value, vm) {
308315
if (!valid) {
309316
if (process.env.NODE_ENV !== 'production') {
310317
warn(
311-
'Invalid prop: type check failed for prop "' + prop.name + '"' +
312-
(vm.$options.name ? ' on component <' + hyphenate(vm.$options.name) + '>.' : '.') +
318+
'Invalid prop: type check failed for prop "' + prop.name + '".' +
313319
' Expected ' + formatType(expectedType) +
314-
', got ' + formatValue(value) + '.'
320+
', got ' + formatValue(value) + '.',
321+
vm
315322
)
316323
}
317324
return false
@@ -320,8 +327,8 @@ export function assertProp (prop, value, vm) {
320327
if (validator) {
321328
if (!validator(value)) {
322329
process.env.NODE_ENV !== 'production' && warn(
323-
'Invalid prop: custom validator check failed for prop "' + prop.name + '"' +
324-
(vm.$options.name ? ' on component <' + hyphenate(vm.$options.name) + '>.' : '.')
330+
'Invalid prop: custom validator check failed for prop "' + prop.name + '".',
331+
vm
325332
)
326333
return false
327334
}

src/compiler/compile.js

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import {
1414
checkComponentAttr,
1515
findRef,
1616
defineReactive,
17-
assertAsset,
1817
getAttr
1918
} from '../util/index'
2019

@@ -181,7 +180,7 @@ function teardownDirs (vm, dirs, destroying) {
181180
*/
182181

183182
export function compileAndLinkProps (vm, el, props, scope) {
184-
var propsLinkFn = compileProps(el, props)
183+
var propsLinkFn = compileProps(el, props, vm)
185184
var propDirs = linkAndCapture(function () {
186185
propsLinkFn(vm, scope)
187186
}, vm)
@@ -691,7 +690,8 @@ function compileDirectives (attrs, options) {
691690
})) {
692691
warn(
693692
'class="' + rawValue + '": Do not mix mustache interpolation ' +
694-
'and v-bind for "class" on the same element. Use one or the other.'
693+
'and v-bind for "class" on the same element. Use one or the other.',
694+
options
695695
)
696696
}
697697
}
@@ -730,12 +730,7 @@ function compileDirectives (attrs, options) {
730730
continue
731731
}
732732

733-
dirDef = resolveAsset(options, 'directives', dirName)
734-
735-
if (process.env.NODE_ENV !== 'production') {
736-
assertAsset(dirDef, 'directive', dirName)
737-
}
738-
733+
dirDef = resolveAsset(options, 'directives', dirName, true)
739734
if (dirDef) {
740735
pushDir(dirName, dirDef)
741736
}

src/compiler/resolve-slots.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export function resolveSlots (vm, content) {
3131
}
3232
/* eslint-enable no-cond-assign */
3333
if (process.env.NODE_ENV !== 'production' && getBindAttr(el, 'slot')) {
34-
warn('The "slot" attribute must be static.')
34+
warn('The "slot" attribute must be static.', vm.$parent)
3535
}
3636
}
3737
for (name in contents) {

src/directives/element/partial.js

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ import { PARTIAL } from '../priorities'
44
import {
55
createAnchor,
66
replace,
7-
resolveAsset,
8-
assertAsset
7+
resolveAsset
98
} from '../../util/index'
109

1110
export default {
@@ -31,10 +30,7 @@ export default {
3130
},
3231

3332
insert (id) {
34-
var partial = resolveAsset(this.vm.$options, 'partials', id)
35-
if (process.env.NODE_ENV !== 'production') {
36-
assertAsset(partial, 'partial', id)
37-
}
33+
var partial = resolveAsset(this.vm.$options, 'partials', id, true)
3834
if (partial) {
3935
this.factory = new FragmentFactory(this.vm, partial)
4036
vIf.insert.call(this)

src/directives/internal/component.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,8 @@ export default {
239239
child._isFragment) {
240240
warn(
241241
'Transitions will not work on a fragment instance. ' +
242-
'Template: ' + child.$options.template
242+
'Template: ' + child.$options.template,
243+
child
243244
)
244245
}
245246
return child

src/directives/public/bind.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ export default {
5252
process.env.NODE_ENV !== 'production' && warn(
5353
attr + '="' + descriptor.raw + '": ' +
5454
'attribute interpolation is not allowed in Vue.js ' +
55-
'directives and special attributes.'
55+
'directives and special attributes.',
56+
this.vm
5657
)
5758
this.el.removeAttribute(attr)
5859
this.invalid = true
@@ -65,7 +66,8 @@ export default {
6566
if (attr === 'src') {
6667
warn(
6768
raw + 'interpolation in "src" attribute will cause ' +
68-
'a 404 request. Use v-bind:src instead.'
69+
'a 404 request. Use v-bind:src instead.',
70+
this.vm
6971
)
7072
}
7173

@@ -74,7 +76,8 @@ export default {
7476
warn(
7577
raw + 'interpolation in "style" attribute will cause ' +
7678
'the attribute to be discarded in Internet Explorer. ' +
77-
'Use v-bind:style instead.'
79+
'Use v-bind:style instead.',
80+
this.vm
7881
)
7982
}
8083
}

src/directives/public/for.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,9 @@ const vFor = {
4848

4949
if (!this.alias) {
5050
process.env.NODE_ENV !== 'production' && warn(
51-
'Alias is required in v-for.'
51+
'Invalid v-for expression "' + this.descriptor.raw + '": ' +
52+
'alias is required.',
53+
this.vm
5254
)
5355
return
5456
}
@@ -637,7 +639,8 @@ if (process.env.NODE_ENV !== 'production') {
637639
warn(
638640
'Duplicate value found in v-for="' + this.descriptor.raw + '": ' +
639641
JSON.stringify(value) + '. Use track-by="$index" if ' +
640-
'you are expecting duplicate values.'
642+
'you are expecting duplicate values.',
643+
this.vm
641644
)
642645
}
643646
}

src/directives/public/if.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ export default {
2828
} else {
2929
process.env.NODE_ENV !== 'production' && warn(
3030
'v-if="' + this.expression + '" cannot be ' +
31-
'used on an instance root element.'
31+
'used on an instance root element.',
32+
this.vm
3233
)
3334
this.invalid = true
3435
}

src/directives/public/model/index.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,9 @@ export default {
3636
if (this.hasRead && !this.hasWrite) {
3737
process.env.NODE_ENV !== 'production' && warn(
3838
'It seems you are using a read-only filter with ' +
39-
'v-model. You might want to use a two-way filter ' +
40-
'to ensure correct behavior.'
39+
'v-model="' + this.descriptor.raw + '". ' +
40+
'You might want to use a two-way filter to ensure correct behavior.',
41+
this.vm
4142
)
4243
}
4344
var el = this.el
@@ -51,7 +52,8 @@ export default {
5152
handler = handlers.text
5253
} else {
5354
process.env.NODE_ENV !== 'production' && warn(
54-
'v-model does not support element type: ' + tag
55+
'v-model does not support element type: ' + tag,
56+
this.vm
5557
)
5658
return
5759
}

src/directives/public/on.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,8 @@ export default {
9494
process.env.NODE_ENV !== 'production' && warn(
9595
'v-on:' + this.arg + '="' +
9696
this.expression + '" expects a function value, ' +
97-
'got ' + handler
97+
'got ' + handler,
98+
this.vm
9899
)
99100
return
100101
}

src/directives/public/ref.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ export default {
44
bind () {
55
process.env.NODE_ENV !== 'production' && warn(
66
'v-ref:' + this.arg + ' must be used on a child ' +
7-
'component. Found on <' + this.el.tagName.toLowerCase() + '>.'
7+
'component. Found on <' + this.el.tagName.toLowerCase() + '>.',
8+
this.vm
89
)
910
}
1011
}

src/instance/api/lifecycle.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ export default function (Vue) {
1515
Vue.prototype.$mount = function (el) {
1616
if (this._isCompiled) {
1717
process.env.NODE_ENV !== 'production' && warn(
18-
'$mount() should be called only once.'
18+
'$mount() should be called only once.',
19+
this
1920
)
2021
return
2122
}

src/instance/internal/events.js

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,9 @@ export default function (Vue) {
4242
vm.$on(name.replace(eventRE), handler)
4343
} else if (process.env.NODE_ENV !== 'production') {
4444
warn(
45-
'v-on:' + name + '="' + attrs[i].value + '"' + (
46-
vm.$options.name
47-
? ' on component <' + vm.$options.name + '>'
48-
: ''
49-
) + ' expects a function value, got ' + handler
45+
'v-on:' + name + '="' + attrs[i].value + '" ' +
46+
'expects a function value, got ' + handler,
47+
vm
5048
)
5149
}
5250
}
@@ -99,7 +97,8 @@ export default function (Vue) {
9997
process.env.NODE_ENV !== 'production' && warn(
10098
'Unknown method: "' + handler + '" when ' +
10199
'registering callback for ' + action +
102-
': "' + key + '".'
100+
': "' + key + '".',
101+
vm
103102
)
104103
}
105104
} else if (handler && type === 'object') {

src/instance/internal/misc.js

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import {
22
resolveAsset,
3-
assertAsset,
43
isPlainObject,
54
warn
65
} from '../../util/index'
@@ -23,10 +22,7 @@ export default function (Vue) {
2322
var filter, fn, args, arg, offset, i, l, j, k
2423
for (i = 0, l = filters.length; i < l; i++) {
2524
filter = filters[write ? l - i - 1 : i]
26-
fn = resolveAsset(this.$options, 'filters', filter.name)
27-
if (process.env.NODE_ENV !== 'production') {
28-
assertAsset(fn, 'filter', filter.name)
29-
}
25+
fn = resolveAsset(this.$options, 'filters', filter.name, true)
3026
if (!fn) continue
3127
fn = write ? fn.write : (fn.read || fn)
3228
if (typeof fn !== 'function') continue
@@ -61,10 +57,7 @@ export default function (Vue) {
6157
if (typeof value === 'function') {
6258
factory = value
6359
} else {
64-
factory = resolveAsset(this.$options, 'components', value)
65-
if (process.env.NODE_ENV !== 'production') {
66-
assertAsset(factory, 'component', value)
67-
}
60+
factory = resolveAsset(this.$options, 'components', value, true)
6861
}
6962
if (!factory) {
7063
return

0 commit comments

Comments
 (0)