1
1
/* @flow */
2
2
3
3
import { isUnaryTag } from './util'
4
- import { warn } from 'core/util/debug'
4
+ import { warn , tip } from 'core/util/debug'
5
5
import { detectErrors } from 'compiler/error-detector'
6
6
import { compile as baseCompile } from 'compiler/index'
7
7
import { extend , genStaticKeys , noop } from 'shared/util'
@@ -24,43 +24,43 @@ export const baseOptions: CompilerOptions = {
24
24
isPreTag
25
25
}
26
26
27
- function compileWithOptions (
28
- template : string ,
29
- options ?: CompilerOptions
30
- ) : CompiledResult {
31
- options = options
32
- ? extend ( extend ( { } , baseOptions ) , options )
33
- : baseOptions
34
- return baseCompile ( template , options )
35
- }
36
-
37
27
export function compile (
38
28
template : string ,
39
29
options ?: CompilerOptions
40
30
) : CompiledResult {
41
- options = options || { }
31
+ const finalOptions = Object . create ( baseOptions )
42
32
const errors = [ ]
43
- // allow injecting modules/directives
44
- const baseModules = baseOptions . modules || [ ]
45
- const modules = options . modules
46
- ? baseModules . concat ( options . modules )
47
- : baseModules
48
- const directives = options . directives
49
- ? extend ( extend ( { } , baseOptions . directives ) , options . directives )
50
- : baseOptions . directives
51
- const compiled = compileWithOptions ( template , {
52
- modules,
53
- directives,
54
- preserveWhitespace : options . preserveWhitespace ,
55
- warn : msg => {
56
- errors . push ( msg )
33
+ const tips = [ ]
34
+ finalOptions . warn = ( msg , tip ) => {
35
+ ( tip ? tips : errors ) . push ( msg )
36
+ }
37
+
38
+ if ( options ) {
39
+ // merge custom modules
40
+ if ( options . modules ) {
41
+ finalOptions . modules = ( baseOptions . modules || [ ] ) . concat ( options . modules )
42
+ }
43
+ // merge custom directives
44
+ if ( options . directives ) {
45
+ finalOptions . directives = extend (
46
+ Object . create ( baseOptions . directives ) ,
47
+ options . directives
48
+ )
49
+ }
50
+ // copy other options
51
+ for ( const key in options ) {
52
+ if ( key !== 'modules' && key !== 'directives' ) {
53
+ finalOptions [ key ] = options [ key ]
54
+ }
57
55
}
58
- } )
56
+ }
57
+
58
+ const compiled = baseCompile ( template , finalOptions )
59
59
if ( process . env . NODE_ENV !== 'production ') {
60
- compiled . errors = errors . concat ( detectErrors ( compiled . ast ) )
61
- } else {
62
- compiled . errors = errors
60
+ errors . push . apply ( errors , detectErrors ( compiled . ast ) )
63
61
}
62
+ compiled . errors = errors
63
+ compiled . tips = tips
64
64
return compiled
65
65
}
66
66
@@ -70,20 +70,15 @@ export function compileToFunctions (
70
70
vm ?: Component
71
71
) : CompiledFunctionResult {
72
72
options = extend ( { } , options )
73
- const _warn = options . warn || warn
74
- const errors = [ ]
73
+
75
74
/* istanbul ignore if */
76
75
if ( process . env . NODE_ENV !== 'production' ) {
77
- options . warn = msg => {
78
- errors . push ( msg )
79
- }
80
-
81
76
// detect possible CSP restriction
82
77
try {
83
78
new Function ( 'return 1' )
84
79
} catch ( e ) {
85
80
if ( e . toString ( ) . match ( / u n s a f e - e v a l | C S P / ) ) {
86
- _warn (
81
+ warn (
87
82
'It seems you are using the standalone build of Vue.js in an ' +
88
83
'environment with Content Security Policy that prohibits unsafe-eval. ' +
89
84
'The template compiler cannot work in this environment. Consider ' +
@@ -93,41 +88,64 @@ export function compileToFunctions (
93
88
}
94
89
}
95
90
}
91
+
92
+ // check cache
96
93
const key = options . delimiters
97
94
? String ( options . delimiters ) + template
98
95
: template
99
96
if ( cache [ key ] ) {
100
97
return cache [ key ]
101
98
}
99
+
100
+ // compile
101
+ const compiled = compile ( template , options )
102
+
103
+ // check compilation errors/tips
104
+ if ( process . env . NODE_ENV !== 'production' ) {
105
+ if ( compiled . errors && compiled . errors . length ) {
106
+ warn (
107
+ `Error compiling template:\n\n${ template } \n\n` +
108
+ compiled . errors . map ( e => `- ${ e } ` ) . join ( '\n' ) + '\n' ,
109
+ vm
110
+ )
111
+ }
112
+ if ( compiled . tips && compiled . tips . length ) {
113
+ compiled . tips . forEach ( msg => tip ( msg , vm ) )
114
+ }
115
+ }
116
+
117
+ // turn code into functions
102
118
const res = { }
103
- const compiled = compileWithOptions ( template , options )
104
- res . render = makeFunction ( compiled . render )
119
+ const fnGenErrors = [ ]
120
+ res . render = makeFunction ( compiled . render , fnGenErrors )
105
121
const l = compiled . staticRenderFns . length
106
122
res . staticRenderFns = new Array ( l )
107
123
for ( let i = 0 ; i < l ; i ++ ) {
108
- res . staticRenderFns [ i ] = makeFunction ( compiled . staticRenderFns [ i ] )
124
+ res . staticRenderFns [ i ] = makeFunction ( compiled . staticRenderFns [ i ] , fnGenErrors )
109
125
}
126
+
127
+ // check function generation errors.
128
+ // this should only happen if there is a bug in the compiler itself.
129
+ // mostly for codegen development use
130
+ /* istanbul ignore if */
110
131
if ( process . env . NODE_ENV !== 'production' ) {
111
- if (
112
- errors . length ||
113
- res . render === noop ||
114
- res . staticRenderFns . some ( fn => fn === noop )
115
- ) {
116
- const allErrors = errors . concat ( detectErrors ( compiled . ast ) )
117
- _warn (
118
- `Error compiling template:\n\n${ template } \n\n` +
119
- ( allErrors . length ? allErrors . map ( e => `- ${ e } ` ) . join ( '\n' ) + '\n' : '' ) ,
132
+ if ( ( ! compiled . errors || ! compiled . errors . length ) && fnGenErrors . length ) {
133
+ warn (
134
+ `Failed to generate render function:\n\n` +
135
+ fnGenErrors . map ( ( { err, code } ) => `${ err . toString ( ) } in\n\n${ code } \n` ) . join ( '\n' ) ,
120
136
vm
121
137
)
122
138
}
123
139
}
140
+
124
141
return ( cache [ key ] = res )
125
142
}
126
143
127
- function makeFunction ( code ) {
144
+ function makeFunction ( code , errors ) {
128
145
try {
129
146
return new Function ( code )
130
- } catch ( e ) {
147
+ } catch ( err ) {
148
+ errors . push ( { err, code } )
131
149
return noop
132
150
}
133
151
}
0 commit comments