diff --git a/src/parsers/directive.js b/src/parsers/directive.js index b565f3a8008..ab8c81e9d83 100644 --- a/src/parsers/directive.js +++ b/src/parsers/directive.js @@ -1,8 +1,9 @@ import { toNumber, stripQuotes } from '../util/index' import Cache from '../cache' +import { warn } from '../util/index' const cache = new Cache(1000) -const filterTokenRE = /[^\s'"]+|'[^']*'|"[^"]*"/g +const filterTokenRE = /(\[.*\])|[^\s'"]+|'[^']*'|"[^"]*"/g const reservedArgRE = /^in$|^-?\d+/ /** @@ -25,7 +26,39 @@ function pushFilter () { var tokens = exp.match(filterTokenRE) filter.name = tokens[0] if (tokens.length > 1) { - filter.args = tokens.slice(1).map(processFilterArg) + tokens.slice(1).map(function (token) { + if (filter.args === undefined) { + filter.args = [] + } + + if (token[0] === '[') { + try { + /* eslint-disable no-eval */ + window.eval(token).map(function (arg) { + /* eslint-disable no-eval */ + filter.args.push(processFilterArg(JSON.stringify(arg).replace(/"/g, ''))) + }) + } catch (e) { + if (process.env.NODE_ENV !== 'production') { + /* istanbul ignore if */ + if (e.toString().match(/unsafe-eval|CSP/)) { + warn( + 'It seems you are using the default build of Vue.js in an environment ' + + 'with Content Security Policy that prohibits unsafe-eval. ' + + 'Use the CSP-compliant build instead: ' + + 'http://vuejs.org/guide/installation.html#CSP-compliant-build' + ) + } else { + warn( + 'Invalid filter argument: ' + token + ) + } + } + } + } else { + filter.args.push(processFilterArg(token)) + } + }) } } if (filter) { diff --git a/test/unit/specs/parsers/directive_spec.js b/test/unit/specs/parsers/directive_spec.js index 982207c1482..03c5e08067c 100644 --- a/test/unit/specs/parsers/directive_spec.js +++ b/test/unit/specs/parsers/directive_spec.js @@ -77,6 +77,30 @@ describe('Directive Parser', function () { expect(res.filters[0].args).toBeUndefined() }) + it('object literal with mixed spaces', function () { + var res1 = parse('t | f [{u: true}]') + var res2 = parse('t | f [{u : true}]') + var res3 = parse('t | f [{ u: true }]') + var res4 = parse('t | f [{u: true }]') + var res5 = parse('t | f [{ u:true}]') + + expect(res1.filters[0].args[0].value).toBe('{u:true}') + expect(res2.filters[0].args[0].value).toBe('{u:true}') + expect(res3.filters[0].args[0].value).toBe('{u:true}') + expect(res4.filters[0].args[0].value).toBe('{u:true}') + expect(res5.filters[0].args[0].value).toBe('{u:true}') + + var res6 = parse('t | f1 [[1, 2, 3], { a: 1 }, { u : true, b: [1, 2] }] | f2 \'abc\'') + expect(res6.filters[0].args[0].value).toBe('[1,2,3]') + expect(res6.filters[0].args[1].value).toBe('{a:1}') + expect(res6.filters[0].args[2].value).toBe('{u:true,b:[1,2]}') + expect(res6.filters[1].args[0].value).toBe('abc') + + // Try out broken filter + parse('t | f1 [[1, 2, 3],') + expect('Invalid filter argument: [[1, 2, 3]').toHaveBeenWarned() + }) + it('escape string', function () { var res = parse("'a\\'b' | test") expect(res.expression).toBe("'a\\'b'")