diff --git a/README.md b/README.md index 4994eca..6cc91fb 100644 --- a/README.md +++ b/README.md @@ -113,6 +113,7 @@ params: - escape {boolean} default `true`, default escape variable to html encode, you can set false to close it. - unescape {object} define the object, which key do not need escape. For example, set unescape equal `{control: true}`, so `$control.html` will not escape. +- env {string} when env equal `development` will throw error when null values are used #### parse diff --git a/src/compile/references.js b/src/compile/references.js index c717ed0..0f75cfb 100644 --- a/src/compile/references.js +++ b/src/compile/references.js @@ -124,9 +124,13 @@ module.exports = function(Velocity, utils) { if (local.isLocaled) ret = local['value']; - if (ast.path && ret !== undefined) { + if (ast.path) { - utils.some(ast.path, function(property) { + utils.some(ast.path, function(property, i, len) { + + if (ret === undefined) { + this._throw(ast, property); + } // 第三个参数,返回后面的参数ast ret = this.getAttributes(property, ret, ast); @@ -294,11 +298,31 @@ module.exports = function(Velocity, utils) { } } else { + this._throw(ast, property, 'TypeError'); ret = undefined; } } return ret; + }, + + _throw: function(ast, property, errorName) { + if (this.config.env !== 'development') { + return; + } + + var text = Velocity.Helper.getRefText(ast); + var pos = ast.pos; + var propertyName = property.type === 'index' ? property.id.value : property.id; + var errorMsg = 'get property ' + propertyName + ' of undefined'; + if (errorName === 'TypeError') { + errorMsg = propertyName + ' is not method'; + } + + errorMsg += '\n at L/N ' + text + ' ' + pos.first_line + ':' + pos.first_column; + var e = new Error(errorMsg); + e.name = errorName || 'ReferenceError'; + throw e; } }) diff --git a/tests/compile.js b/tests/compile.js index a0e5163..74f9823 100644 --- a/tests/compile.js +++ b/tests/compile.js @@ -186,6 +186,53 @@ describe('Compile', function() { ret = compile.render(context) assert.equal('<i>', ret) }) + + describe('env', function() { + it('should throw on property when parent is null', function() { + var vm = '$foo.bar'; + var compile = new Compile(parse(vm), { env: 'development' }) + function foo() { + compile.render() + }; + foo.should.throw(/get property bar of undefined/); + }); + + it('should throw on index when parent is null', function() { + var vm = '$foo[1]'; + var compile = new Compile(parse(vm), { env: 'development' }) + function foo() { + compile.render() + }; + foo.should.throw(/get property 1 of undefined/); + }); + + it('should throw on function when parent is null', function() { + var vm = '$foo.xx()'; + var compile = new Compile(parse(vm), { env: 'development' }) + function foo() { + compile.render() + }; + foo.should.throw(/get property xx of undefined/); + }); + + it('should throw when mult level', function() { + var vm = '$foo.bar.xx.bar1'; + var compile = new Compile(parse(vm), { env: 'development' }) + function foo() { + compile.render({ foo: { bar: {} }}); + }; + foo.should.throw(/get property bar1 of undefined/); + }); + + it('not function', function() { + var vm = '$foo.bar.xx()'; + var compile = new Compile(parse(vm), { env: 'development' }) + function foo() { + return compile.render({ foo: { bar: {} }}); + }; + foo.should.throw(/xx is not method/); + }); + }); })