Skip to content

Commit

Permalink
[[FIX]] Restrict IdentifierNames in ES5 code
Browse files Browse the repository at this point in the history
  • Loading branch information
jugglinmike committed May 27, 2018
1 parent f2ce8fe commit 5995a9f
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 4 deletions.
1 change: 1 addition & 0 deletions data/es5-identifier-names.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 30 additions & 0 deletions scripts/generate-identifier-data.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,18 @@ var ID_Start = get('Binary_Property/ID_Start');
var ID_Continue = get('Binary_Property/ID_Continue');
var Other_ID_Start = get('Binary_Property/Other_ID_Start');

// Get the Unicode categories needed to construct the ES5 regex.
var Lu = get('General_Category/Uppercase_Letter');
var Ll = get('General_Category/Lowercase_Letter');
var Lt = get('General_Category/Titlecase_Letter');
var Lm = get('General_Category/Modifier_Letter');
var Lo = get('General_Category/Other_Letter');
var Nl = get('General_Category/Letter_Number');
var Mn = get('General_Category/Nonspacing_Mark');
var Mc = get('General_Category/Spacing_Mark');
var Nd = get('General_Category/Decimal_Number');
var Pc = get('General_Category/Connector_Punctuation');

var generateData = function() { // ES 5.1
// http://mathiasbynens.be/notes/javascript-identifiers#valid-identifier-names
var identifierStart = regenerate(ID_Start)
Expand All @@ -40,6 +52,20 @@ var generateData = function() { // ES 5.1
};
};

// Adapted from https://gist.github.com/mathiasbynens/6334847
var generateES5Regex = function() { // ES 5.1
// https://mathiasbynens.be/notes/javascript-identifiers#valid-identifier-names
var identifierStart = regenerate('$', '_')
.add(Lu, Ll, Lt, Lm, Lo, Nl)
.removeRange(0x010000, 0x10FFFF); // Remove astral symbols.
var identifierPart = identifierStart.clone()
.add('\u200C', '\u200D', Mn, Mc, Nd, Pc)
.removeRange(0x010000, 0x10FFFF); // Remove astral symbols.

return '/^(?:' + identifierStart.toString() + ')' +
'(?:' + identifierPart.toString() + ')*$/';
};

var fs = require('fs');
var writeFile = function(fileName, data) {
fs.writeFileSync(
Expand All @@ -57,3 +83,7 @@ var writeFile = function(fileName, data) {
var result = generateData();
writeFile('./data/non-ascii-identifier-start.js', result.nonAsciiIdentifierStart);
writeFile('./data/non-ascii-identifier-part-only.js', result.nonAsciiIdentifierPart);
fs.writeFileSync(
'./data/es5-identifier-names.js',
'module.exports = ' + generateES5Regex() + ';'
);
30 changes: 26 additions & 4 deletions src/lex.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ var asciiIdentifierStartTable = unicodeData.asciiIdentifierStartTable;
var asciiIdentifierPartTable = unicodeData.asciiIdentifierPartTable;
var nonAsciiIdentifierStartTable = require("../data/non-ascii-identifier-start.js");
var nonAsciiIdentifierPartTable = require("../data/non-ascii-identifier-part-only.js");
// Loading of this module is deferred as an optimization for ES2015 input
var es5IdentifierNames;

// Some of these token types are from JavaScript Parser API
// while others are specific to JSHint parser.
Expand Down Expand Up @@ -582,10 +584,10 @@ Lexer.prototype = {
* Extract a JavaScript identifier out of the next sequence of
* characters or return 'null' if its not possible.
*/
scanIdentifier: function() {
scanIdentifier: function(checks) {
var id = "";
var index = 0;
var char;
var char, value;

function isNonAsciiIdentifierStart(code) {
return nonAsciiIdentifierStartTable.indexOf(code) > -1;
Expand Down Expand Up @@ -695,9 +697,29 @@ Lexer.prototype = {
id += char;
}

value = removeEscapeSequences(id)

if (!state.inES6(true)) {
es5IdentifierNames = require("../data/es5-identifier-names.js");

if (!es5IdentifierNames.test(value)) {
this.triggerAsync(
"warning",
{
code: "W119",
line: this.line,
character: this.char,
data: ["unicode 8", "6"]
},
checks,
function() { return true; }
);
}
}

return {
type: Token.Identifier,
value: removeEscapeSequences(id),
value: value,
text: id,
tokenLength: id.length
};
Expand Down Expand Up @@ -1531,7 +1553,7 @@ Lexer.prototype = {
this.scanRegExp(checks) ||
this.scanPunctuator() ||
this.scanKeyword() ||
this.scanIdentifier() ||
this.scanIdentifier(checks) ||
this.scanNumericLiteral(checks);

if (match) {
Expand Down
4 changes: 4 additions & 0 deletions tests/unit/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -8366,6 +8366,10 @@ exports["regression test for GH-3230"] = function (test) {
};

exports.unicode8 = function (test) {
TestRun(test)
.addError(1, 5, "'unicode 8' is only available in ES6 (use 'esversion: 6').")
.test("var Ϳ;", {esversion: 5});

TestRun(test)
.test("var Ϳ;", {esversion: 6});

Expand Down

0 comments on commit 5995a9f

Please sign in to comment.