Skip to content

Commit 30784b5

Browse files
author
Evan You
committed
expressions
- add functional test case for sd-on expression handlers - invalid inline expressions: the error will be captured and warning thrown - add unit test case for invalid inline expressions - utils.warn() now always gets thrown by default - add `silent` config option to suppress warnings
1 parent f87f603 commit 30784b5

File tree

8 files changed

+64
-10
lines changed

8 files changed

+64
-10
lines changed

src/compiler.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -425,8 +425,8 @@ CompilerProto.createBinding = function (key, isExp, isFn) {
425425
// a complex expression binding
426426
// we need to generate an anonymous computed property for it
427427
var result = ExpParser.parse(key)
428-
if (result) {
429-
log(' created anonymous binding: ' + key)
428+
if (result.getter) {
429+
log(' created expression binding: ' + key)
430430
binding.value = isFn
431431
? result.getter
432432
: { $get: result.getter }
@@ -443,8 +443,6 @@ CompilerProto.createBinding = function (key, isExp, isFn) {
443443
}
444444
}
445445
}
446-
} else {
447-
utils.warn(' invalid expression: ' + key)
448446
}
449447
} else {
450448
log(' created binding: ' + key)

src/config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ module.exports = {
22

33
prefix : 'sd',
44
debug : false,
5+
silent : false,
56
attrs : {}
67

78
}

src/exp-parser.js

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
var utils = require('./utils')
2+
13
// Variable extraction scooped from https://github.com/RubyLouvre/avalon
24

35
var KEYWORDS =
@@ -44,6 +46,22 @@ function getPaths (code, vars) {
4446
return code.match(pathRE)
4547
}
4648

49+
/**
50+
* Create a function from a string...
51+
* this looks like evil magic but since all variables are limited
52+
* to the VM's scope it's actually properly sandboxed
53+
*/
54+
function makeGetter (exp, raw) {
55+
/* jshint evil: true */
56+
var fn
57+
try {
58+
fn = new Function(exp)
59+
} catch (e) {
60+
utils.warn('Invalid expression: ' + raw)
61+
}
62+
return fn
63+
}
64+
4765
module.exports = {
4866

4967
/**
@@ -52,12 +70,11 @@ module.exports = {
5270
* created as bindings.
5371
*/
5472
parse: function (exp) {
55-
/* jshint evil: true */
5673
// extract variable names
5774
var vars = getVariables(exp)
5875
if (!vars.length) {
5976
return {
60-
getter: new Function('return ' + exp)
77+
getter: makeGetter('return ' + exp, exp)
6178
}
6279
}
6380
var args = [],
@@ -79,7 +96,7 @@ module.exports = {
7996
}
8097
args = 'var ' + args.join(',') + ';return ' + exp
8198
return {
82-
getter: new Function(args),
99+
getter: makeGetter(args, exp),
83100
paths: getPaths(exp, Object.keys(hash))
84101
}
85102
}

src/utils.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,10 +161,10 @@ var utils = module.exports = {
161161
},
162162

163163
/**
164-
* warn for debugging
164+
* warnings, thrown in all cases
165165
*/
166166
warn: function() {
167-
if (config.debug && console) {
167+
if (!config.silent && console) {
168168
console.warn(join.call(arguments, ' '))
169169
}
170170
}

test/functional/fixtures/expression.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,14 @@
1010
<div id="normal">
1111
<p sd-text="one + ' ' + two.three + '!'"></p>
1212
<input id="one" sd-model="one" name="one"> <input id="two" sd-model="two.three" name="two">
13+
<button sd-on="click: this.one = 'clicked'">click</button>
1314
</div>
1415
<div id="lazy">
1516
<p sd-text="one + ' ' + two.three + '!'"></p>
1617
<form id="form">
1718
<input sd-model="one" name="three"> <input sd-model="two.three" name="four">
1819
</form>
20+
<button sd-on="click: two.three = 'clicked'">click</button>
1921
</div>
2022
<script>
2123
var normal = new Seed({

test/functional/specs/expression.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* global normal */
22

3-
casper.test.begin('Expression', 12, function (test) {
3+
casper.test.begin('Expression', 16, function (test) {
44

55
casper
66
.start('./fixtures/expression.html', function () {
@@ -37,6 +37,16 @@ casper.test.begin('Expression', 12, function (test) {
3737
this.sendKeys('#one', 'Bye')
3838
test.assertSelectorHasText('#normal p', 'Bye Casper!')
3939

40+
// sd-on with expression
41+
this.click('#normal button')
42+
test.assertField('one', 'clicked')
43+
test.assertSelectorHasText('#normal p', 'clicked Casper!')
44+
45+
// sd-on with expression
46+
this.click('#lazy button')
47+
test.assertField('four', 'clicked')
48+
test.assertSelectorHasText('#lazy p', 'three clicked!')
49+
4050
})
4151
.run(function () {
4252
test.done()

test/unit/runner.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
var Seed = require('seed'),
2121
assert = chai.assert
2222

23+
Seed.config({silent:true})
24+
2325
function mock (id, html, attrs) {
2426
var el = document.createElement('div')
2527
el.id = id

test/unit/specs/exp-parser.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,12 @@ describe('UNIT: Expression Parser', function () {
5252
}
5353
},
5454
expectedValue: 'write tests : nope'
55+
},
56+
{
57+
// expression with no scope variables
58+
exp: "'a' + 'b'",
59+
vm: {},
60+
expectedValue: 'ab'
5561
}
5662
]
5763

@@ -69,6 +75,7 @@ describe('UNIT: Expression Parser', function () {
6975
vm.$get = function (key) { return this[key] }
7076

7177
it('should get correct args', function () {
78+
if (!vars.length) return
7279
assert.strictEqual(result.paths.length, vars.length)
7380
for (var i = 0; i < vars.length; i++) {
7481
assert.strictEqual(vars[i], result.paths[i])
@@ -83,4 +90,21 @@ describe('UNIT: Expression Parser', function () {
8390
})
8491
}
8592

93+
// extra case for invalid expressions
94+
describe('invalid expression', function () {
95+
96+
it('should capture the error and warn', function () {
97+
var utils = require('seed/src/utils'),
98+
oldWarn = utils.warn,
99+
warned = false
100+
utils.warn = function () {
101+
warned = true
102+
}
103+
ExpParser.parse('a + "fsef')
104+
assert.ok(warned)
105+
utils.warn = oldWarn
106+
})
107+
108+
})
109+
86110
})

0 commit comments

Comments
 (0)