From 03fa3cf21018f1d9474c9f212431dc444fd0be2b Mon Sep 17 00:00:00 2001 From: zigomir Date: Sat, 2 Jul 2016 18:57:19 -0700 Subject: [PATCH 1/3] Allow whitespaces inside object literal. --- src/parsers/directive.js | 2 +- test/unit/specs/parsers/directive_spec.js | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/parsers/directive.js b/src/parsers/directive.js index b565f3a8008..7c66fed5b84 100644 --- a/src/parsers/directive.js +++ b/src/parsers/directive.js @@ -2,7 +2,7 @@ import { toNumber, stripQuotes } from '../util/index' import Cache from '../cache' const cache = new Cache(1000) -const filterTokenRE = /[^\s'"]+|'[^']*'|"[^"]*"/g +const filterTokenRE = /(({.*})|([^\s'"]+|'[^']*'|"[^"]*"))/g const reservedArgRE = /^in$|^-?\d+/ /** diff --git a/test/unit/specs/parsers/directive_spec.js b/test/unit/specs/parsers/directive_spec.js index 982207c1482..7ccb6448d73 100644 --- a/test/unit/specs/parsers/directive_spec.js +++ b/test/unit/specs/parsers/directive_spec.js @@ -77,6 +77,20 @@ 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}') + }) + it('escape string', function () { var res = parse("'a\\'b' | test") expect(res.expression).toBe("'a\\'b'") From 0925e3449cfb0f663d0d72294883668dfde86c11 Mon Sep 17 00:00:00 2001 From: zigomir Date: Sun, 10 Jul 2016 21:26:05 -0700 Subject: [PATCH 2/3] Special syntax for multiple filter params - wrap it in []. --- src/parsers/directive.js | 18 ++++++++++++++-- test/unit/specs/parsers/directive_spec.js | 26 ++++++++++++++--------- 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/src/parsers/directive.js b/src/parsers/directive.js index 7c66fed5b84..7c60dc205a8 100644 --- a/src/parsers/directive.js +++ b/src/parsers/directive.js @@ -2,7 +2,7 @@ import { toNumber, stripQuotes } from '../util/index' import Cache from '../cache' const cache = new Cache(1000) -const filterTokenRE = /(({.*})|([^\s'"]+|'[^']*'|"[^"]*"))/g +const filterTokenRE = /(\[.*\])|[^\s'"]+|'[^']*'|"[^"]*"/g const reservedArgRE = /^in$|^-?\d+/ /** @@ -25,7 +25,21 @@ 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] === '[') { + /* eslint-disable no-eval */ + window.eval(token).map(function (arg) { + /* eslint-disable no-eval */ + filter.args.push(processFilterArg(JSON.stringify(arg).replace(/"/g, ''))) + }) + } 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 7ccb6448d73..da0dc878a36 100644 --- a/test/unit/specs/parsers/directive_spec.js +++ b/test/unit/specs/parsers/directive_spec.js @@ -78,17 +78,23 @@ describe('Directive Parser', function () { }) 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}') + 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}') + 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') }) it('escape string', function () { From 3d7673284e738cfb219d3c63645e9614342d2ff3 Mon Sep 17 00:00:00 2001 From: zigomir Date: Sun, 10 Jul 2016 23:06:25 -0700 Subject: [PATCH 3/3] CSP warn. --- src/parsers/directive.js | 29 +++++++++++++++++++---- test/unit/specs/parsers/directive_spec.js | 4 ++++ 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/src/parsers/directive.js b/src/parsers/directive.js index 7c60dc205a8..ab8c81e9d83 100644 --- a/src/parsers/directive.js +++ b/src/parsers/directive.js @@ -1,5 +1,6 @@ import { toNumber, stripQuotes } from '../util/index' import Cache from '../cache' +import { warn } from '../util/index' const cache = new Cache(1000) const filterTokenRE = /(\[.*\])|[^\s'"]+|'[^']*'|"[^"]*"/g @@ -31,11 +32,29 @@ function pushFilter () { } if (token[0] === '[') { - /* eslint-disable no-eval */ - window.eval(token).map(function (arg) { - /* eslint-disable no-eval */ - filter.args.push(processFilterArg(JSON.stringify(arg).replace(/"/g, ''))) - }) + 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)) } diff --git a/test/unit/specs/parsers/directive_spec.js b/test/unit/specs/parsers/directive_spec.js index da0dc878a36..03c5e08067c 100644 --- a/test/unit/specs/parsers/directive_spec.js +++ b/test/unit/specs/parsers/directive_spec.js @@ -95,6 +95,10 @@ describe('Directive Parser', function () { 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 () {