From bd62ddf8461eedd0c31f7f67b9f5ca0a6f6d04c5 Mon Sep 17 00:00:00 2001 From: David Majda Date: Thu, 1 Sep 2016 14:59:44 +0200 Subject: [PATCH] Use "[]" & "[^]" for empty character classes, not "(?!)" & "[\\S\\s]" See #441. --- lib/compiler/passes/generate-bytecode.js | 62 ++++++++----------- .../compiler/passes/generate-bytecode.spec.js | 26 ++------ 2 files changed, 29 insertions(+), 59 deletions(-) diff --git a/lib/compiler/passes/generate-bytecode.js b/lib/compiler/passes/generate-bytecode.js index b0c1c8f..934df96 100644 --- a/lib/compiler/passes/generate-bytecode.js +++ b/lib/compiler/passes/generate-bytecode.js @@ -569,43 +569,31 @@ function generateBytecode(ast) { }, "class": function(node) { - var regexp, parts, regexpIndex, expectedIndex; - - if (node.parts.length > 0) { - regexp = '/^[' - + (node.inverted ? '^' : '') - + node.parts.map(function(part) { - return Array.isArray(part) - ? js.regexpClassEscape(part[0]) - + '-' - + js.regexpClassEscape(part[1]) - : js.regexpClassEscape(part); - }).join('') - + ']/' + (node.ignoreCase ? 'i' : ''); - } else { - /* - * IE considers regexps /[]/ and /[^]/ as syntactically invalid, so we - * translate them into equivalents it can handle. - */ - regexp = node.inverted ? '/^[\\S\\s]/' : '/^(?!)/'; - } - - parts = '[' - + node.parts.map(function(part) { - return Array.isArray(part) - ? '["' + js.stringEscape(part[0]) + '", "' + js.stringEscape(part[1]) + '"]' - : '"' + js.stringEscape(part) + '"'; - }).join(', ') - + ']'; - - regexpIndex = addConst(regexp); - expectedIndex = addConst( - 'peg$classExpectation(' - + parts + ', ' - + node.inverted + ', ' - + node.ignoreCase - + ')' - ); + var regexp = '/^[' + + (node.inverted ? '^' : '') + + node.parts.map(function(part) { + return Array.isArray(part) + ? js.regexpClassEscape(part[0]) + + '-' + + js.regexpClassEscape(part[1]) + : js.regexpClassEscape(part); + }).join('') + + ']/' + (node.ignoreCase ? 'i' : ''), + parts = '[' + + node.parts.map(function(part) { + return Array.isArray(part) + ? '["' + js.stringEscape(part[0]) + '", "' + js.stringEscape(part[1]) + '"]' + : '"' + js.stringEscape(part) + '"'; + }).join(', ') + + ']', + regexpIndex = addConst(regexp), + expectedIndex = addConst( + 'peg$classExpectation(' + + parts + ', ' + + node.inverted + ', ' + + node.ignoreCase + + ')' + ); return buildCondition( [op.MATCH_REGEXP, regexpIndex], diff --git a/spec/unit/compiler/passes/generate-bytecode.spec.js b/spec/unit/compiler/passes/generate-bytecode.spec.js index f49eebb..5bfc1ba 100644 --- a/spec/unit/compiler/passes/generate-bytecode.spec.js +++ b/spec/unit/compiler/passes/generate-bytecode.spec.js @@ -594,7 +594,7 @@ describe("compiler pass |generateBytecode|", function() { ])); }); - describe("non-empty non-inverted case-sensitive", function() { + describe("non-inverted case-sensitive", function() { it("defines correct constants", function() { expect(pass).toChangeAST('start = [a]', constsDetails([ '/^[a]/', @@ -603,7 +603,7 @@ describe("compiler pass |generateBytecode|", function() { }); }); - describe("non-empty inverted case-sensitive", function() { + describe("inverted case-sensitive", function() { it("defines correct constants", function() { expect(pass).toChangeAST('start = [^a]', constsDetails([ '/^[^a]/', @@ -612,7 +612,7 @@ describe("compiler pass |generateBytecode|", function() { }); }); - describe("non-empty non-inverted case-insensitive", function() { + describe("non-inverted case-insensitive", function() { it("defines correct constants", function() { expect(pass).toChangeAST('start = [a]i', constsDetails([ '/^[a]/i', @@ -621,7 +621,7 @@ describe("compiler pass |generateBytecode|", function() { }); }); - describe("non-empty complex", function() { + describe("complex", function() { it("defines correct constants", function() { expect(pass).toChangeAST('start = [ab-def-hij-l]', constsDetails([ '/^[ab-def-hij-l]/', @@ -629,24 +629,6 @@ describe("compiler pass |generateBytecode|", function() { ])); }); }); - - describe("empty non-inverted", function() { - it("defines correct constants", function() { - expect(pass).toChangeAST('start = []', constsDetails([ - '/^(?!)/', - 'peg$classExpectation([], false, false)' - ])); - }); - }); - - describe("empty inverted", function() { - it("defines correct constants", function() { - expect(pass).toChangeAST('start = [^]', constsDetails([ - '/^[\\S\\s]/', - 'peg$classExpectation([], true, false)' - ])); - }); - }); }); describe("for any", function() {