Ver código fonte

make function compilation reusable

Evan You 9 anos atrás
pai
commit
303780acd2

+ 1 - 1
src/compiler/codegen/index.js

@@ -49,7 +49,7 @@ export function generate (
   }
 }
 
-function genElement (el: ASTElement, state: CodegenState): string {
+export function genElement (el: ASTElement, state: CodegenState): string {
   if (el.staticRoot && !el.staticProcessed) {
     return genStatic(el, state)
   } else if (el.once && !el.onceProcessed) {

+ 3 - 93
src/compiler/index.js

@@ -1,11 +1,11 @@
 /* @flow */
 
+import { extend } from 'shared/util'
 import { parse } from './parser/index'
 import { optimize } from './optimizer'
 import { generate } from './codegen/index'
 import { detectErrors } from './error-detector'
-import { extend, noop } from 'shared/util'
-import { warn, tip } from 'core/util/debug'
+import { createCompileToFunctionFn } from './to-function'
 
 function baseCompile (
   template: string,
@@ -21,20 +21,7 @@ function baseCompile (
   }
 }
 
-function makeFunction (code, errors) {
-  try {
-    return new Function(code)
-  } catch (err) {
-    errors.push({ err, code })
-    return noop
-  }
-}
-
 export function createCompiler (baseOptions: CompilerOptions) {
-  const functionCompileCache: {
-    [key: string]: CompiledFunctionResult;
-  } = Object.create(null)
-
   function compile (
     template: string,
     options?: CompilerOptions
@@ -75,85 +62,8 @@ export function createCompiler (baseOptions: CompilerOptions) {
     return compiled
   }
 
-  function compileToFunctions (
-    template: string,
-    options?: CompilerOptions,
-    vm?: Component
-  ): CompiledFunctionResult {
-    options = options || {}
-
-    /* istanbul ignore if */
-    if (process.env.NODE_ENV !== 'production') {
-      // detect possible CSP restriction
-      try {
-        new Function('return 1')
-      } catch (e) {
-        if (e.toString().match(/unsafe-eval|CSP/)) {
-          warn(
-            'It seems you are using the standalone build of Vue.js in an ' +
-            'environment with Content Security Policy that prohibits unsafe-eval. ' +
-            'The template compiler cannot work in this environment. Consider ' +
-            'relaxing the policy to allow unsafe-eval or pre-compiling your ' +
-            'templates into render functions.'
-          )
-        }
-      }
-    }
-
-    // check cache
-    const key = options.delimiters
-      ? String(options.delimiters) + template
-      : template
-    if (functionCompileCache[key]) {
-      return functionCompileCache[key]
-    }
-
-    // compile
-    const compiled = compile(template, options)
-
-    // check compilation errors/tips
-    if (process.env.NODE_ENV !== 'production') {
-      if (compiled.errors && compiled.errors.length) {
-        warn(
-          `Error compiling template:\n\n${template}\n\n` +
-          compiled.errors.map(e => `- ${e}`).join('\n') + '\n',
-          vm
-        )
-      }
-      if (compiled.tips && compiled.tips.length) {
-        compiled.tips.forEach(msg => tip(msg, vm))
-      }
-    }
-
-    // turn code into functions
-    const res = {}
-    const fnGenErrors = []
-    res.render = makeFunction(compiled.render, fnGenErrors)
-    const l = compiled.staticRenderFns.length
-    res.staticRenderFns = new Array(l)
-    for (let i = 0; i < l; i++) {
-      res.staticRenderFns[i] = makeFunction(compiled.staticRenderFns[i], fnGenErrors)
-    }
-
-    // check function generation errors.
-    // this should only happen if there is a bug in the compiler itself.
-    // mostly for codegen development use
-    /* istanbul ignore if */
-    if (process.env.NODE_ENV !== 'production') {
-      if ((!compiled.errors || !compiled.errors.length) && fnGenErrors.length) {
-        warn(
-          `Failed to generate render function:\n\n` +
-          fnGenErrors.map(({ err, code }) => `${err.toString()} in\n\n${code}\n`).join('\n'),
-          vm
-        )
-      }
-    }
-
-    return (functionCompileCache[key] = res)
-  }
-
   return {
     compile,
-    compileToFunctions
+    compileToFunctions: createCompileToFunctionFn(compile)
   }
 }

+ 96 - 0
src/compiler/to-function.js

@@ -0,0 +1,96 @@
+/* @flow */
+
+import { noop } from 'shared/util'
+import { warn, tip } from 'core/util/debug'
+
+function createFunction (code, errors) {
+  try {
+    return new Function(code)
+  } catch (err) {
+    errors.push({ err, code })
+    return noop
+  }
+}
+
+export function createCompileToFunctionFn (compile: Function): Function {
+  const cache: {
+    [key: string]: CompiledFunctionResult;
+  } = Object.create(null)
+
+  return function compileToFunctions (
+    template: string,
+    options?: CompilerOptions,
+    vm?: Component
+  ): CompiledFunctionResult {
+    options = options || {}
+
+    /* istanbul ignore if */
+    if (process.env.NODE_ENV !== 'production') {
+      // detect possible CSP restriction
+      try {
+        new Function('return 1')
+      } catch (e) {
+        if (e.toString().match(/unsafe-eval|CSP/)) {
+          warn(
+            'It seems you are using the standalone build of Vue.js in an ' +
+            'environment with Content Security Policy that prohibits unsafe-eval. ' +
+            'The template compiler cannot work in this environment. Consider ' +
+            'relaxing the policy to allow unsafe-eval or pre-compiling your ' +
+            'templates into render functions.'
+          )
+        }
+      }
+    }
+
+    // check cache
+    const key = options.delimiters
+      ? String(options.delimiters) + template
+      : template
+    if (cache[key]) {
+      return cache[key]
+    }
+
+    // compile
+    const compiled = compile(template, options)
+
+    // check compilation errors/tips
+    if (process.env.NODE_ENV !== 'production') {
+      if (compiled.errors && compiled.errors.length) {
+        warn(
+          `Error compiling template:\n\n${template}\n\n` +
+          compiled.errors.map(e => `- ${e}`).join('\n') + '\n',
+          vm
+        )
+      }
+      if (compiled.tips && compiled.tips.length) {
+        compiled.tips.forEach(msg => tip(msg, vm))
+      }
+    }
+
+    // turn code into functions
+    const res = {}
+    const fnGenErrors = []
+    res.render = createFunction(compiled.render, fnGenErrors)
+    const l = compiled.staticRenderFns.length
+    res.staticRenderFns = new Array(l)
+    for (let i = 0; i < l; i++) {
+      res.staticRenderFns[i] = createFunction(compiled.staticRenderFns[i], fnGenErrors)
+    }
+
+    // check function generation errors.
+    // this should only happen if there is a bug in the compiler itself.
+    // mostly for codegen development use
+    /* istanbul ignore if */
+    if (process.env.NODE_ENV !== 'production') {
+      if ((!compiled.errors || !compiled.errors.length) && fnGenErrors.length) {
+        warn(
+          `Failed to generate render function:\n\n` +
+          fnGenErrors.map(({ err, code }) => `${err.toString()} in\n\n${code}\n`).join('\n'),
+          vm
+        )
+      }
+    }
+
+    return (cache[key] = res)
+  }
+}

+ 2 - 25
src/platforms/web/compiler/index.js

@@ -1,31 +1,8 @@
 /* @flow */
 
-import { isUnaryTag, canBeLeftOpenTag } from './util'
-import { genStaticKeys } from 'shared/util'
+import { baseOptions } from './options'
 import { createCompiler } from 'compiler/index'
 
-import modules from './modules/index'
-import directives from './directives/index'
-
-import {
-  isPreTag,
-  mustUseProp,
-  isReservedTag,
-  getTagNamespace
-} from '../util/index'
-
-export const baseOptions: CompilerOptions = {
-  expectHTML: true,
-  modules,
-  directives,
-  isPreTag,
-  isUnaryTag,
-  mustUseProp,
-  canBeLeftOpenTag,
-  isReservedTag,
-  getTagNamespace,
-  staticKeys: genStaticKeys(modules)
-}
-
 const { compile, compileToFunctions } = createCompiler(baseOptions)
+
 export { compile, compileToFunctions }

+ 26 - 0
src/platforms/web/compiler/options.js

@@ -0,0 +1,26 @@
+/* @flow */
+
+import {
+  isPreTag,
+  mustUseProp,
+  isReservedTag,
+  getTagNamespace
+} from '../util/index'
+
+import modules from './modules/index'
+import directives from './directives/index'
+import { genStaticKeys } from 'shared/util'
+import { isUnaryTag, canBeLeftOpenTag } from './util'
+
+export const baseOptions: CompilerOptions = {
+  expectHTML: true,
+  modules,
+  directives,
+  isPreTag,
+  isUnaryTag,
+  mustUseProp,
+  canBeLeftOpenTag,
+  isReservedTag,
+  getTagNamespace,
+  staticKeys: genStaticKeys(modules)
+}

+ 1 - 1
test/unit/modules/compiler/codegen.spec.js

@@ -3,7 +3,7 @@ import { optimize } from 'compiler/optimizer'
 import { generate } from 'compiler/codegen'
 import { isObject } from 'shared/util'
 import { isReservedTag } from 'web/util/index'
-import { baseOptions } from 'web/compiler/index'
+import { baseOptions } from 'web/compiler/options'
 
 function assertCodegen (template, generatedCode, ...args) {
   let staticRenderFnCodes = []

+ 1 - 1
test/unit/modules/compiler/optimizer.spec.js

@@ -1,6 +1,6 @@
 import { parse } from 'compiler/parser/index'
 import { optimize } from 'compiler/optimizer'
-import { baseOptions } from 'web/compiler/index'
+import { baseOptions } from 'web/compiler/options'
 
 describe('optimizer', () => {
   it('simple', () => {

+ 1 - 1
test/unit/modules/compiler/parser.spec.js

@@ -1,6 +1,6 @@
 import { parse } from 'compiler/parser/index'
 import { extend } from 'shared/util'
-import { baseOptions } from 'web/compiler/index'
+import { baseOptions } from 'web/compiler/options'
 import { isIE, isEdge } from 'core/util/env'
 
 describe('parser', () => {