Skip to content

Commit

Permalink
[[FEAT]] Implement ES2019 RegExp "dotall"
Browse files Browse the repository at this point in the history
Introduce a new warning to alert users of RegExp literals that include
the new flag without using the "dot" atom.
  • Loading branch information
jugglinmike authored and rwaldron committed Jan 29, 2019
1 parent 962dced commit 457d732
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 12 deletions.
41 changes: 34 additions & 7 deletions src/lex.js
Original file line number Diff line number Diff line change
Expand Up @@ -1328,16 +1328,17 @@ Lexer.prototype = {
var char = this.peek();
var value = char;
var body = "";
var flags = [];
var groupReferences = [];
var allFlags = "";
var es5Flags = "";
var malformed = false;
var isCharSet = false;
var isCharSetRange = false;
var isGroup = false;
var isQuantifiable = false;
var hasInvalidQuantifier = false;
var escapedChars = "";
var hasUFlag = function() { return flags.indexOf("u") > -1; };
var hasUFlag = function() { return allFlags.indexOf("u") > -1; };
var escapeSequence;
var groupCount = 0;
var terminated, malformedDesc;
Expand Down Expand Up @@ -1648,7 +1649,7 @@ Lexer.prototype = {

while (index < length) {
char = this.peek(index);
if (!/[gimyu]/.test(char)) {
if (!/[gimyus]/.test(char)) {
break;
}
if (char === "y") {
Expand Down Expand Up @@ -1706,18 +1707,38 @@ Lexer.prototype = {
}

body = translateUFlag(body);
} else if (char === "s") {
if (!state.inES9()) {
this.triggerAsync(
"warning",
{
code: "W119",
line: this.line,
character: this.char,
data: [ "DotAll RegExp flag", "9" ]
},
checks,
function() { return true; }
);
}
if (value.indexOf("s") > -1) {
malformedDesc = "Duplicate RegExp flag";
}
} else {
es5Flags += char;
}

if (flags.indexOf(char) > -1) {
if (allFlags.indexOf(char) > -1) {
malformedDesc = "Duplicate RegExp flag";
}
flags.push(char);
allFlags += char;

value += char;
allFlags += char;
index += 1;
}

if (flags.indexOf("u") === -1) {
if (allFlags.indexOf("u") === -1) {
this.triggerAsync("warning", {
code: "W147",
line: this.line,
Expand All @@ -1728,7 +1749,7 @@ Lexer.prototype = {
// Check regular expression for correctness.

try {
new RegExp(body);
new RegExp(body, es5Flags);
} catch (err) {
/**
* Because JSHint relies on the current engine's RegExp parser to
Expand All @@ -1746,6 +1767,12 @@ Lexer.prototype = {
character: this.char,
data: [ malformedDesc ]
});
} else if (allFlags.indexOf("s") > -1 && !reg.regexpDot.test(body)) {
this.trigger("warning", {
code: "W148",
line: this.line,
character: this.char
});
}

return {
Expand Down
3 changes: 2 additions & 1 deletion src/messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,8 @@ var warnings = {
W144: "'{a}' is a non-standard language feature. Enable it using the '{b}' unstable option.",
W145: "Superfluous 'case' clause.",
W146: "Unnecessary `await` expression.",
W147: "Regular expressions should include the 'u' flag."
W147: "Regular expressions should include the 'u' flag.",
W148: "Unnecessary RegExp 's' flag."
};

var info = {
Expand Down
3 changes: 3 additions & 0 deletions src/reg.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,6 @@ exports.regexpSyntaxChars = /[\^$\\.*+?()[\]{}|]/;
exports.regexpQuantifiers = /[*+?{]/;

exports.regexpCharClasses = /[dDsSwW]/;

// Identifies the "dot" atom in regular expressions
exports.regexpDot = /(^|[^\\])(\\\\)*\./;
4 changes: 0 additions & 4 deletions tests/test262/expectations.txt
Original file line number Diff line number Diff line change
Expand Up @@ -883,10 +883,6 @@ test/built-ins/RegExp/named-groups/unicode-references.js(default)
test/built-ins/RegExp/named-groups/unicode-references.js(strict mode)
test/built-ins/RegExp/named-groups/unicode-property-names.js(default)
test/built-ins/RegExp/named-groups/unicode-property-names.js(strict mode)
test/built-ins/RegExp/prototype/dotAll/this-val-regexp.js(default)
test/built-ins/RegExp/prototype/dotAll/this-val-regexp.js(strict mode)
test/built-ins/RegExp/prototype/flags/s.js(default)
test/built-ins/RegExp/prototype/flags/s.js(strict mode)
test/built-ins/RegExp/property-escapes/character-class.js(default)
test/built-ins/RegExp/property-escapes/character-class.js(strict mode)
test/built-ins/RegExp/property-escapes/grammar-extensions.js(default)
Expand Down
51 changes: 51 additions & 0 deletions tests/unit/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -787,6 +787,57 @@ exports.regexp.yFlag = function (test) {
test.done();
};

exports.regexp.dotAll = function (test) {
TestRun(test, "flag presence - disallowed in editions prior to 2018")
.addError(1, 6, "'DotAll RegExp flag' is only available in ES9 (use 'esversion: 9').")
.addError(2, 6, "'DotAll RegExp flag' is only available in ES9 (use 'esversion: 9').")
.addError(3, 6, "'DotAll RegExp flag' is only available in ES9 (use 'esversion: 9').")
.test([
"void /./s;",
"void /./gs;",
"void /./sg;"
], { esversion: 8 });

TestRun(test, "flag presence - allowed in 2018")
.test([
"void /./s;",
"void /./gs;",
"void /./sg;"
], { esversion: 9 });

TestRun(test, "duplicate flag")
.addError(1, 6, "Invalid regular expression.")
.addError(2, 6, "Invalid regular expression.")
.test([
"void /./ss;",
"void /./sgs;"
], { esversion: 9 });

TestRun(test, "missing dot")
.addError(1, 6, "Unnecessary RegExp 's' flag.")
.addError(2, 6, "Unnecessary RegExp 's' flag.")
.addError(3, 6, "Unnecessary RegExp 's' flag.")
.addError(4, 6, "Unnecessary RegExp 's' flag.")
.addError(5, 6, "Unnecessary RegExp 's' flag.")
.test([
"void /dotall flag without dot/s;",
"void /literal period \\./s;",
"void /\\. literal period/s;",
"void /literal period \\\\\\./s;",
"void /\\\\\\. literal period/s;"
], { esversion: 9 });

TestRun(test, "dot following escape")
.test([
"void /RegExp dot \\\\./s;",
"void /\\\\. RegExp dot/s;",
"void /RegExp dot \\\\\\\\\./s;",
"void /\\\\\\\\\. RegExp dot/s;"
], { esversion: 9 });

test.done();
};

exports.regexp.regressions = function (test) {
// GH-536
TestRun(test).test("str /= 5;", {es3: true}, { str: true });
Expand Down

0 comments on commit 457d732

Please sign in to comment.