|
1 | 1 | /* @flow */ |
2 | 2 |
|
3 | 3 | import { isUnaryTag } from './util' |
4 | | -import { warn, tip } from 'core/util/debug' |
5 | | -import { detectErrors } from 'compiler/error-detector' |
6 | | -import { compile as baseCompile } from 'compiler/index' |
7 | | -import { extend, genStaticKeys, noop } from 'shared/util' |
8 | | -import { isReservedTag, mustUseProp, getTagNamespace, isPreTag } from '../util/index' |
| 4 | +import { genStaticKeys } from 'shared/util' |
| 5 | +import { createCompiler } from 'compiler/index' |
9 | 6 |
|
10 | 7 | import modules from './modules/index' |
11 | 8 | import directives from './directives/index' |
12 | 9 |
|
13 | | -const cache: { [key: string]: CompiledFunctionResult } = Object.create(null) |
| 10 | +import { |
| 11 | + isPreTag, |
| 12 | + mustUseProp, |
| 13 | + isReservedTag, |
| 14 | + getTagNamespace |
| 15 | +} from '../util/index' |
14 | 16 |
|
15 | 17 | export const baseOptions: CompilerOptions = { |
16 | 18 | expectHTML: true, |
17 | 19 | modules, |
18 | | - staticKeys: genStaticKeys(modules), |
19 | 20 | directives, |
20 | | - isReservedTag, |
| 21 | + isPreTag, |
21 | 22 | isUnaryTag, |
22 | 23 | mustUseProp, |
| 24 | + isReservedTag, |
23 | 25 | getTagNamespace, |
24 | | - isPreTag |
25 | | -} |
26 | | - |
27 | | -export function compile ( |
28 | | - template: string, |
29 | | - options?: CompilerOptions |
30 | | -): CompiledResult { |
31 | | - const finalOptions = Object.create(baseOptions) |
32 | | - const errors = [] |
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 | | - } |
55 | | - } |
56 | | - } |
57 | | - |
58 | | - const compiled = baseCompile(template, finalOptions) |
59 | | - if (process.env.NODE_ENV !== 'production') { |
60 | | - errors.push.apply(errors, detectErrors(compiled.ast)) |
61 | | - } |
62 | | - compiled.errors = errors |
63 | | - compiled.tips = tips |
64 | | - return compiled |
65 | | -} |
66 | | - |
67 | | -export function compileToFunctions ( |
68 | | - template: string, |
69 | | - options?: CompilerOptions, |
70 | | - vm?: Component |
71 | | -): CompiledFunctionResult { |
72 | | - options = extend({}, options) |
73 | | - |
74 | | - /* istanbul ignore if */ |
75 | | - if (process.env.NODE_ENV !== 'production') { |
76 | | - // detect possible CSP restriction |
77 | | - try { |
78 | | - new Function('return 1') |
79 | | - } catch (e) { |
80 | | - if (e.toString().match(/unsafe-eval|CSP/)) { |
81 | | - warn( |
82 | | - 'It seems you are using the standalone build of Vue.js in an ' + |
83 | | - 'environment with Content Security Policy that prohibits unsafe-eval. ' + |
84 | | - 'The template compiler cannot work in this environment. Consider ' + |
85 | | - 'relaxing the policy to allow unsafe-eval or pre-compiling your ' + |
86 | | - 'templates into render functions.' |
87 | | - ) |
88 | | - } |
89 | | - } |
90 | | - } |
91 | | - |
92 | | - // check cache |
93 | | - const key = options.delimiters |
94 | | - ? String(options.delimiters) + template |
95 | | - : template |
96 | | - if (cache[key]) { |
97 | | - return cache[key] |
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 |
118 | | - const res = {} |
119 | | - const fnGenErrors = [] |
120 | | - res.render = makeFunction(compiled.render, fnGenErrors) |
121 | | - const l = compiled.staticRenderFns.length |
122 | | - res.staticRenderFns = new Array(l) |
123 | | - for (let i = 0; i < l; i++) { |
124 | | - res.staticRenderFns[i] = makeFunction(compiled.staticRenderFns[i], fnGenErrors) |
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 */ |
131 | | - if (process.env.NODE_ENV !== 'production') { |
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'), |
136 | | - vm |
137 | | - ) |
138 | | - } |
139 | | - } |
140 | | - |
141 | | - return (cache[key] = res) |
| 26 | + staticKeys: genStaticKeys(modules) |
142 | 27 | } |
143 | 28 |
|
144 | | -function makeFunction (code, errors) { |
145 | | - try { |
146 | | - return new Function(code) |
147 | | - } catch (err) { |
148 | | - errors.push({ err, code }) |
149 | | - return noop |
150 | | - } |
151 | | -} |
| 29 | +const { compile, compileToFunctions } = createCompiler(baseOptions) |
| 30 | +export { compile, compileToFunctions } |
0 commit comments