Skip to content

Commit

Permalink
[[FIX]] Allow empty export and trailing comma
Browse files Browse the repository at this point in the history
Now JSHint correctly parses this code:
  export { a, };
  export {};
but warns `Empty export.` at line 2

This commit fixes #2567
  • Loading branch information
nicolo-ribaudo authored and jugglinmike committed Sep 10, 2017
1 parent 07bb596 commit 631327e
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 22 deletions.
22 changes: 12 additions & 10 deletions src/jshint.js
Original file line number Diff line number Diff line change
Expand Up @@ -3412,7 +3412,7 @@ var JSHINT = (function() {
advance("[");
}
if (checkPunctuator(state.tokens.next, "]")) {
warning("W137", state.tokens.curr);
warning("W137", state.tokens.curr, "destructuring");
}
var element_after_rest = false;
while (!checkPunctuator(state.tokens.next, "]")) {
Expand Down Expand Up @@ -3444,7 +3444,7 @@ var JSHINT = (function() {
advance("{");
}
if (checkPunctuator(state.tokens.next, "}")) {
warning("W137", state.tokens.curr);
warning("W137", state.tokens.curr, "destructuring");
}
while (!checkPunctuator(state.tokens.next, "}")) {
assignmentProperty();
Expand Down Expand Up @@ -4634,6 +4634,10 @@ var JSHINT = (function() {
} else {
// ImportClause :: NamedImports
advance("{");
// Breaking change
// if (checkPunctuator(state.tokens.next, "}")) {
// warning("W137", state.tokens.next, "import");
// }
for (;;) {
if (state.tokens.next.value === "}") {
advance("}");
Expand Down Expand Up @@ -4731,8 +4735,11 @@ var JSHINT = (function() {
if (state.tokens.next.value === "{") {
// ExportDeclaration :: export ExportClause
advance("{");
if (checkPunctuator(state.tokens.next, "}")) {
warning("W137", state.tokens.next, "export");
}
var exportedTokens = [];
for (;;) {
while (!checkPunctuator(state.tokens.next, "}")) {
if (!state.tokens.next.identifier) {
error("E030", state.tokens.next, state.tokens.next.value);
}
Expand All @@ -4748,16 +4755,11 @@ var JSHINT = (function() {
advance();
}

if (state.tokens.next.value === ",") {
if (!checkPunctuator(state.tokens.next, "}")) {
advance(",");
} else if (state.tokens.next.value === "}") {
advance("}");
break;
} else {
error("E024", state.tokens.next, state.tokens.next.value);
break;
}
}
advance("}");
if (state.tokens.next.value === "from") {
// ExportDeclaration :: export ExportClause FromClause
advance("from");
Expand Down
2 changes: 1 addition & 1 deletion src/messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ var warnings = {
W134: "The '{a}' option is only available when linting ECMAScript {b} code.",
W135: "{a} may not be supported by non-browser environments.",
W136: "'{a}' must be in function scope.",
W137: "Empty destructuring.",
W137: "Empty {a}.",
W138: "Regular parameters should not come after default parameters.",
W139: "Function expressions should not be used as the second operand to instanceof.",
W140: "Missing comma."
Expand Down
10 changes: 4 additions & 6 deletions tests/test262/expectations.txt
Original file line number Diff line number Diff line change
Expand Up @@ -410,12 +410,7 @@ language/module-code/early-dup-export-id.js
language/module-code/early-export-global.js
language/module-code/early-export-unresolvable.js
language/module-code/early-super.js
language/module-code/eval-rqstd-once.js
language/module-code/eval-rqstd-order.js
language/module-code/eval-self-once.js
language/module-code/instn-iee-trlng-comma.js
language/module-code/instn-named-id-name.js
language/module-code/instn-once.js
language/module-code/instn-resolve-empty-import.js
language/module-code/instn-resolve-err-reference.js
language/module-code/instn-resolve-err-syntax.js
Expand All @@ -433,7 +428,6 @@ language/module-code/parse-err-invoke-anon-fun-decl.js
language/module-code/parse-err-invoke-anon-gen-decl.js
language/module-code/parse-err-reference.js
language/module-code/parse-err-return.js
language/module-code/parse-export-empty.js
language/expressions/async-arrow-function/arrow-returns-promise.js
language/expressions/async-function/expression-returns-promise.js
language/expressions/async-function/syntax-expression-is-PrimaryExpression.js
Expand Down Expand Up @@ -4619,3 +4613,7 @@ language/statements/class/meth-static-dflt-params-ref-self.js
language/statements/class/meth-static-dflt-params-trailing-comma.js
language/statements/class/meth-static-params-trailing-comma-multiple.js
language/statements/class/meth-static-params-trailing-comma-single.js

# JSHint currently makes no attempt to resolve module references, so it is
# incapable of detecting early errors across modules.
language/module-code/instn-resolve-empty-export.js
14 changes: 9 additions & 5 deletions tests/unit/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -827,11 +827,12 @@ exports.testES6Modules = function (test) {
[60, 13, "'ember2' has already been declared."]
];

var testRun = TestRun(test);
var testRun = TestRun(test)
.addError(74, 9, "Empty export.");
importConstErrors.forEach(function(error) { testRun.addError.apply(testRun, error); });
testRun.test(src, {esnext: true});

testRun = TestRun(test)
testRun
.addError(3, 1, "'import' is only available in ES6 (use 'esversion: 6').")
.addError(4, 1, "'import' is only available in ES6 (use 'esversion: 6').")
.addError(5, 1, "'import' is only available in ES6 (use 'esversion: 6').")
Expand Down Expand Up @@ -862,9 +863,12 @@ exports.testES6Modules = function (test) {
.addError(65, 1, "'import' is only available in ES6 (use 'esversion: 6').")
.addError(67, 1, "'export' is only available in ES6 (use 'esversion: 6').")
.addError(67, 16, "'function*' is only available in ES6 (use 'esversion: 6').")
.addError(67, 26, "'yield' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).");
importConstErrors.forEach(function(error) { testRun.addError.apply(testRun, error); });
testRun.test(src, {});
.addError(67, 26, "'yield' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).")
.addError(70, 1, "'export' is only available in ES6 (use 'esversion: 6').")
.addError(71, 1, "'import' is only available in ES6 (use 'esversion: 6').")
.addError(74, 1, "'export' is only available in ES6 (use 'esversion: 6').")
.addError(75, 1, "'import' is only available in ES6 (use 'esversion: 6').")
.test(src);

var src2 = [
"var a = {",
Expand Down
8 changes: 8 additions & 0 deletions tests/unit/fixtures/es6-import-export.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,11 @@ if (newImport) {
import newImport from 'newImport';

export function* gen() { yield 1; }

// Trailing comma
export { a, };
import { x, } from "source";

// Empty
export {};
import {} from "source";

0 comments on commit 631327e

Please sign in to comment.