Преглед изворни кода

refine ast nodes with disjoint union type

Evan You пре 10 година
родитељ
комит
3573ffff1f

+ 15 - 5
flow/compiler.js

@@ -28,17 +28,15 @@ declare type ASTDirective = {
   modifiers: ?{ [key: string]: true }
 }
 
-declare type ASTText = {
-  text?: string,
-  expression?: string
-}
+declare type ASTNode = ASTElement | ASTText | ASTExpression
 
 declare type ASTElement = {
+  type: 1,
   tag: string,
   attrsList: Array<{ name: string, value: string }>,
   attrsMap: { [key: string]: string | null },
   parent: ASTElement | void,
-  children: Array<any>, // for flexibility
+  children: Array<ASTNode>,
 
   static?: boolean,
   staticRoot?: true,
@@ -83,3 +81,15 @@ declare type ASTElement = {
   forbidden?: true,
   once?: true
 }
+
+declare type ASTExpression = {
+  type: 2,
+  expression: string,
+  static?: boolean
+}
+
+declare type ASTText = {
+  type: 3,
+  text: string,
+  static?: boolean
+}

+ 14 - 12
src/compiler/codegen.js

@@ -159,18 +159,20 @@ function genData (el: ASTElement): string {
   }
   // inline-template
   if (el.inlineTemplate) {
+    const ast = el.children[0]
     if (process.env.NODE_ENV !== 'production' && (
-      el.children.length > 1 || !el.children[0].tag
+      el.children.length > 1 || ast.type !== 1
     )) {
       warn('Inline-template components must have exactly one child element.')
     }
-    const ast: ASTElement = el.children[0]
-    const inlineRenderFns = generate(ast, currentOptions)
-    data += `inlineTemplate:{render:function(){${
-      inlineRenderFns.render
-    }},staticRenderFns:[${
-      inlineRenderFns.staticRenderFns.map(code => `function(){${code}}`).join(',')
-    }]}`
+    if (ast.type === 1) {
+      const inlineRenderFns = generate(ast, currentOptions)
+      data += `inlineTemplate:{render:function(){${
+        inlineRenderFns.render
+      }},staticRenderFns:[${
+        inlineRenderFns.staticRenderFns.map(code => `function(){${code}}`).join(',')
+      }]}`
+    }
   }
   return data.replace(/,$/, '') + '}'
 }
@@ -216,16 +218,16 @@ function genChildren (el: ASTElement, asThunk?: boolean): string {
     : code
 }
 
-function genNode (node) {
-  if (node.tag) {
+function genNode (node: ASTNode) {
+  if (node.type === 1) {
     return genElement(node)
   } else {
     return genText(node)
   }
 }
 
-function genText (text: ASTText): string {
-  return text.expression
+function genText (text: ASTText | ASTExpression): string {
+  return text.type === 2
     ? `(${text.expression})`
     : '__t__(' + JSON.stringify(text.text) + ')'
 }

+ 12 - 7
src/compiler/optimizer.js

@@ -26,7 +26,7 @@ export function optimize (root: ?ASTElement, options: CompilerOptions) {
 
 function markStatic (node) {
   node.static = isStatic(node)
-  if (node.children) {
+  if (node.type === 1) {
     for (let i = 0, l = node.children.length; i < l; i++) {
       const child = node.children[i]
       markStatic(child)
@@ -38,7 +38,7 @@ function markStatic (node) {
 }
 
 function markStaticRoots (node) {
-  if (node.tag && (node.once || node.static)) {
+  if (node.type === 1 && (node.once || node.static)) {
     node.staticRoot = true
     return
   }
@@ -54,12 +54,17 @@ const isStaticKey = makeMap(
   'staticAttrs,staticClass'
 )
 
-function isStatic (node) {
-  return !!(node.text || node.pre || (
-    !node.expression && // not text with interpolation
+function isStatic (node: ASTNode): boolean {
+  if (node.type === 2) { // expression
+    return false
+  }
+  if (node.type === 3) { // text
+    return true
+  }
+  return !!(node.pre || (
     !node.if && !node.for && // not v-if or v-for or v-else
-    (!node.tag || isPlatformReservedTag(node.tag)) && // not a component
-    !(node.tag && isBuiltInTag(node.tag)) && // not a built-in
+    isPlatformReservedTag(node.tag) && // not a component
+    !isBuiltInTag(node.tag) && // not a built-in
     (node.plain || Object.keys(node).every(isStaticKey)) // no dynamic bindings
   ))
 }

+ 6 - 3
src/compiler/parser/index.js

@@ -63,6 +63,7 @@ export function parse (
 
       tag = tag.toLowerCase()
       const element: ASTElement = {
+        type: 1,
         tag,
         attrsList: attrs,
         attrsMap: makeAttrsMap(attrs),
@@ -138,7 +139,9 @@ export function parse (
       // remove trailing whitespace
       const element = stack[stack.length - 1]
       const lastNode = element.children[element.children.length - 1]
-      if (lastNode && lastNode.text === ' ') element.children.pop()
+      if (lastNode && lastNode.type === 3 && lastNode.text === ' ') {
+        element.children.pop()
+      }
       // pop stack
       stack.length -= 1
       currentParent = stack[stack.length - 1]
@@ -167,9 +170,9 @@ export function parse (
       if (text) {
         let expression
         if (!inPre && text !== ' ' && (expression = parseText(text, delimiters))) {
-          currentParent.children.push({ expression })
+          currentParent.children.push({ type: 2, expression })
         } else {
-          currentParent.children.push({ text })
+          currentParent.children.push({ type: 3, text })
         }
       }
     }

+ 1 - 1
src/platforms/web/compiler/directives/model.js

@@ -80,7 +80,7 @@ const getSelectedValueCode =
 function patchChildOptions (el, fn) {
   for (let i = 0; i < el.children.length; i++) {
     const c = el.children[i]
-    if (c.tag === 'option') {
+    if (c.type === 1 && c.tag === 'option') {
       addProp(c, 'selected', fn(getBindingAttr(c, 'value')))
     }
   }