Evan You преди 12 години
родител
ревизия
656c0157f5
променени са 10 файла, в които са добавени 34 реда и са изтрити 75 реда
  1. 4 33
      src/compiler.js
  2. 2 2
      src/directives/html.js
  3. 1 1
      src/directives/index.js
  4. 1 1
      src/directives/model.js
  5. 6 1
      src/text-parser.js
  6. 9 13
      src/utils.js
  7. 1 1
      test/unit/specs/compiler.js
  8. 2 6
      test/unit/specs/directives.js
  9. 1 1
      test/unit/specs/text-parser.js
  10. 7 16
      test/unit/specs/utils.js

+ 4 - 33
src/compiler.js

@@ -17,8 +17,6 @@ var Emitter     = require('./emitter'),
     def         = utils.defProtected,
     hasOwn      = ({}).hasOwnProperty,
 
-    SINGLE_VAR_RE = /^[\w\.$]+$/,
-
     // hooks to register
     hooks = [
         'created', 'ready',
@@ -776,39 +774,12 @@ CompilerProto.addDelegator = function (event) {
  *  includes bindings. It accepts additional raw data
  *  because we need to dynamically resolve v-component
  *  before a childVM is even compiled...
- *  TODO: make it less of a hack.
  */
 CompilerProto.eval = function (exp, data) {
-    var tokens = TextParser.parse(exp)
-    if (!tokens) { // no bindings
-        return exp
-    } else {
-        var token,
-            i = -1,
-            l = tokens.length,
-            res = '',
-            dataVal
-        while (++i < l) {
-            token = tokens[i]
-            if (token.key) {
-                if (SINGLE_VAR_RE.test(token.key)) {
-                    dataVal = data && utils.get(data, token.key)
-                    res += utils.toText(
-                        dataVal === undefined
-                            ? utils.get(this.data, token.key)
-                            : dataVal
-                    )
-                } else {
-                    res += utils.toText(
-                        ExpParser.eval(token.key, this, data)
-                    )
-                }
-            } else {
-                res += token
-            }
-        }
-        return res
-    }
+    var parsed = TextParser.parseAttr(exp)
+    return parsed
+        ? ExpParser.eval(parsed, this, data)
+        : exp
 }
 
 /**

+ 2 - 2
src/directives/html.js

@@ -1,4 +1,4 @@
-var toText = require('../utils').toText,
+var guard = require('../utils').guard,
     slice = [].slice
 
 module.exports = {
@@ -14,7 +14,7 @@ module.exports = {
     },
 
     update: function (value) {
-        value = toText(value)
+        value = guard(value)
         if (this.holder) {
             this.swap(value)
         } else {

+ 1 - 1
src/directives/index.js

@@ -28,7 +28,7 @@ module.exports = {
                 : 'textContent'
         },
         update: function (value) {
-            this.el[this.attr] = utils.toText(value)
+            this.el[this.attr] = utils.guard(value)
         }
     },
 

+ 1 - 1
src/directives/model.js

@@ -140,7 +140,7 @@ module.exports = {
         } else if (el.type === 'checkbox') { // checkbox
             el.checked = !!value
         } else {
-            el[this.attr] = utils.toText(value)
+            el[this.attr] = utils.guard(value)
         }
     },
 

+ 6 - 1
src/text-parser.js

@@ -27,10 +27,15 @@ function parse (text) {
 function parseAttr (attr) {
     var tokens = parse(attr)
     if (!tokens) return null
+    if (tokens.length === 1) return tokens[0].key
     var res = [], token
     for (var i = 0, l = tokens.length; i < l; i++) {
         token = tokens[i]
-        res.push(token.key || ('"' + token + '"'))
+        res.push(
+            token.key
+                ? ('(' + token.key + ')')
+                : ('"' + token + '"')
+        )
     }
     return res.join('+')
 }

+ 9 - 13
src/utils.js

@@ -88,19 +88,15 @@ var utils = module.exports = {
     },
 
     /**
-     *  Make sure only strings, booleans, numbers and
-     *  objects are output to html. otherwise, ouput empty string.
-     */
-    toText: function (value) {
-        /* jshint eqeqeq: false */
-        var type = typeof value
-        return (type === 'string' ||
-            type === 'boolean' ||
-            (type === 'number' && value == value)) // deal with NaN
-                ? value
-                : type === 'object' && value !== null
-                    ? JSON.stringify(value)
-                    : ''
+     *  Make sure null and undefined output empty string
+     */
+    guard: function (value) {
+        /* jshint eqeqeq: false, eqnull: true */
+        return value == null
+            ? ''
+            : (typeof value == 'object')
+                ? JSON.stringify(value)
+                : value
     },
 
     /**

+ 1 - 1
test/unit/specs/compiler.js

@@ -20,7 +20,7 @@ describe('Compiler', function () {
 
         it('should accept additional data', function () {
             var res = v.$compiler.eval('{{c.d}}', { c: { d: 3 } })
-            assert.strictEqual(res, '3')
+            assert.strictEqual(res, 3)
             res = v.$compiler.eval('{{c.d === 3 ? "a" : "b"}}', { c: { d: 3 } })
             assert.strictEqual(res, 'a')
         })

+ 2 - 6
test/unit/specs/directives.js

@@ -70,13 +70,11 @@ describe('Directives', function () {
             assert.strictEqual(dir.el.textContent, '{"foo":"bar"}')
         })
 
-        it('should be empty with other stuff', function () {
+        it('should be empty with null & undefined', function () {
             dir.update(null)
             assert.strictEqual(dir.el.textContent, '')
             dir.update(undefined)
             assert.strictEqual(dir.el.textContent, '')
-            dir.update(function () {})
-            assert.strictEqual(dir.el.textContent, '')
         })
     })
 
@@ -106,13 +104,11 @@ describe('Directives', function () {
             assert.strictEqual(dir.el.textContent, '{"foo":"bar"}')
         })
 
-        it('should be empty with other stuff', function () {
+        it('should be empty with with null & undefined', function () {
             dir.update(null)
             assert.strictEqual(dir.el.innerHTML, '')
             dir.update(undefined)
             assert.strictEqual(dir.el.innerHTML, '')
-            dir.update(function () {})
-            assert.strictEqual(dir.el.innerHTML, '')
         })
 
         it('should swap html if el is a comment placeholder', function () {

+ 1 - 1
test/unit/specs/text-parser.js

@@ -64,7 +64,7 @@ describe('Text Parser', function () {
         it('should return Directive.parse friendly expression', function () {
             assert.strictEqual(TextParser.parseAttr('{{msg}}'), 'msg')
             assert.strictEqual(TextParser.parseAttr('{{msg + "123"}}'), 'msg + "123"')
-            assert.strictEqual(TextParser.parseAttr('ha {{msg + "123"}} ho'), '"ha "+msg + "123"+" ho"')
+            assert.strictEqual(TextParser.parseAttr('ha {{msg + "123"}} ho'), '"ha "+(msg + "123")+" ho"')
         })
 
     })

+ 7 - 16
test/unit/specs/utils.js

@@ -128,25 +128,16 @@ describe('Utils', function () {
 
     })
 
-    describe('toText', function () {
-
-        var txt = utils.toText
-
-        it('should do nothing for strings, numbers and booleans', function () {
-            assert.strictEqual(txt('hihi'), 'hihi')
-            assert.strictEqual(txt(123), 123)
-            assert.strictEqual(txt(true), true)
-            assert.strictEqual(txt(false), false)
-        })
+    describe('guard', function () {
         
-        it('should output empty string if value is not string or number', function () {
-            assert.strictEqual(txt(undefined), '')
-            assert.strictEqual(txt(null), '')
-            assert.strictEqual(txt(NaN), '')
+        it('should output empty string if value is null or undefined', function () {
+            assert.strictEqual(utils.guard(undefined), '')
+            assert.strictEqual(utils.guard(null), '')
         })
 
-        it('should stringify value if is object', function () {
-            assert.strictEqual(txt({foo:"bar"}), '{"foo":"bar"}')
+        it('should output stringified data if value is object', function () {
+            assert.strictEqual(utils.guard({a:1}), '{"a":1}')
+            assert.strictEqual(utils.guard([1,2,3]), '[1,2,3]')
         })
 
     })