Explorar el Código

allow quoted arguments in diretives

Evan You hace 11 años
padre
commit
8602b3545d
Se han modificado 4 ficheros con 65 adiciones y 22 borrados
  1. 36 0
      benchmarks/dir.js
  2. 1 1
      benchmarks/expression.js
  3. 13 5
      src/parse/directive.js
  4. 15 16
      test/unit/specs/directive_parser_spec.js

+ 36 - 0
benchmarks/dir.js

@@ -0,0 +1,36 @@
+console.log('\nDirective Parser\n')
+
+var Cache = require('../src/cache')
+var parse = require('../src/parse/directive').parse
+
+Cache.prototype.get = Cache.prototype.put = function () {}
+
+function bench (id, fn) {
+  var s = Date.now()
+  var max = i = 100000
+  while (i--) {
+    fn()
+  }
+  var used = Date.now() - s
+  var ops = Math.round(16 / (used / max))
+  console.log(id + ': ' + ops + ' ops/frame')
+}
+
+
+var side
+
+bench('simple path', function () {
+  side = parse('a.b.c')
+})
+
+bench('filters', function () {
+  side = parse('a.b.c | a | b | c')
+})
+
+bench('multi', function () {
+  side = parse('abc:ddd, bcd:eee, fsef:fff')
+})
+
+bench('complex exp', function () {
+  side = parse('test:a.b + { c: d} + "abced{fsefesf}ede"')
+})

+ 1 - 1
benchmarks/expression.js

@@ -31,5 +31,5 @@ bench('simple exp', function () {
 })
 
 bench('complex exp', function () {
-  side = parse('a.b + c')
+  side = parse('a.b + { c: d} + "abced{fsefesf}ede"')
 })

+ 13 - 5
src/parse/directive.js

@@ -1,7 +1,7 @@
 var Cache = require('../cache')
 var cache = new Cache(1000)
-var ARG_RE = /^[\w\$-]+$/
-var FILTER_TOKEN_RE = /[^\s'"]+|'[^']+'|"[^"]+"/g
+var argRE = /^[\w\$-]+$|^'[^']*'$|^"[^"]*"$/
+var filterTokenRE = /[^\s'"]+|'[^']+'|"[^"]+"/g
 
 /**
  * Parser state
@@ -20,6 +20,7 @@ var dirs
 var dir
 var lastFilterIndex
 var arg
+var argC
 
 /**
  * Push a directive object into the result Array
@@ -46,7 +47,7 @@ function pushFilter () {
   var filter
   if (exp) {
     filter = {}
-    var tokens = exp.match(FILTER_TOKEN_RE)
+    var tokens = exp.match(filterTokenRE)
     filter.name = tokens[0]
     filter.args = tokens.length > 1 ? tokens.slice(1) : null
   }
@@ -107,9 +108,16 @@ exports.parse = function (s) {
     } else if (c === ':' && !dir.expression && !dir.arg) {
       // argument
       arg = str.slice(begin, i).trim()
-      if (ARG_RE.test(arg)) {
+      // test for valid argument here
+      // since we may have caught stuff like first half of
+      // an object literal or a ternary expression.
+      if (argRE.test(arg)) {
         argIndex = i + 1
-        dir.arg = arg
+        argC = arg.charAt(0)
+        // strip quotes
+        dir.arg = argC === '"' || argC === "'"
+          ? arg.slice(1, -1)
+          : arg
       }
     } else if (c === '|' && str.charAt(i + 1) !== '|' && str.charAt(i - 1) !== '|') {
       if (dir.expression === undefined) {

+ 15 - 16
test/unit/specs/directive_parser_spec.js

@@ -2,14 +2,14 @@ var parse = require('../../../src/parse/directive').parse
 
 describe('Directive Parser', function () {
 
-  it('exp', function () {
+  it('simple', function () {
     var res = parse('exp')
     expect(res.length).toBe(1)
     expect(res[0].expression).toBe('exp')
     expect(res[0].raw).toBe('exp')
   })
 
-  it('arg:exp', function () {
+  it('with arg', function () {
     var res = parse('arg:exp')
     expect(res.length).toBe(1)
     expect(res[0].expression).toBe('exp')
@@ -17,8 +17,7 @@ describe('Directive Parser', function () {
     expect(res[0].raw).toBe('arg:exp')
   })
 
-  // filters
-  it('arg : exp | abc de | bcd', function () {
+  it('with filters', function () {
     var res = parse(' arg : exp | abc de | bcd')
     expect(res.length).toBe(1)
     expect(res[0].expression).toBe('exp')
@@ -32,8 +31,7 @@ describe('Directive Parser', function () {
     expect(res[0].filters[1].args).toBeNull()
   })
 
-  // double pipe
-  it('a || b | c', function () {
+  it('double pipe', function () {
     var res = parse('a || b | c')
     expect(res.length).toBe(1)
     expect(res[0].expression).toBe('a || b')
@@ -43,16 +41,14 @@ describe('Directive Parser', function () {
     expect(res[0].filters[0].args).toBeNull()
   })
 
-  // single quote + boolean
-  it('a ? \'b\' : c', function () {
+  it('single quote + boolean', function () {
     var res = parse('a ? \'b\' : c')
     expect(res.length).toBe(1)
     expect(res[0].expression).toBe('a ? \'b\' : c')
     expect(res[0].filters).toBeUndefined()
   })
 
-  // double quote + boolean
-  it('"a:b:c||d|e|f" || d ? a : b', function () {
+  it('double quote + boolean', function () {
     var res = parse('"a:b:c||d|e|f" || d ? a : b')
     expect(res.length).toBe(1)
     expect(res[0].expression).toBe('"a:b:c||d|e|f" || d ? a : b')
@@ -60,8 +56,7 @@ describe('Directive Parser', function () {
     expect(res[0].arg).toBeUndefined()
   })
 
-  // multiple simple clause
-  it('a, b, c', function () {
+  it('multiple simple clauses', function () {
     var res = parse('a, b, c')
     expect(res.length).toBe(3)
     expect(res[0].expression).toBe('a')
@@ -69,8 +64,7 @@ describe('Directive Parser', function () {
     expect(res[2].expression).toBe('c')
   })
 
-  // multiple complex clause
-  it('a:b | c | j, d:e | f | k l, g:h | i', function () {
+  it('multiple complex clauses', function () {
     var res = parse('a:b | c | j, d:e | f | k l, g:h | i')
     expect(res.length).toBe(3)
 
@@ -98,8 +92,7 @@ describe('Directive Parser', function () {
     expect(res[2].filters[0].args).toBeNull()
   })
 
-  // super complex
-  it('click:test(c.indexOf(d,f),"e,f"), input: d || [e,f], ok:{a:1,b:2}', function () {
+  it('nexted function calls + array/object literals', function () {
     var res = parse('click:test(c.indexOf(d,f),"e,f"), input: d || [e,f], ok:{a:1,b:2}')
     expect(res.length).toBe(3)
     expect(res[0].arg).toBe('click')
@@ -111,6 +104,12 @@ describe('Directive Parser', function () {
     expect(res[2].expression).toBe('{a:1,b:2}')
   })
 
+  it('quoted arguments', function () {
+    var res = parse('"xlink:href":a?"fsef":ff')
+    expect(res.length).toBe(1)
+    expect(res[0].arg).toBe('xlink:href')
+  })
+
   it('cache', function () {
     var res1 = parse('a || b | c')
     var res2 = parse('a || b | c')