Repository: jshint/jshint
Pull request #2386 (2015-05-14 16:56:40)

[[FIX]] Do not accept empty values for directives
Previously, when an directive was specified without a value, JSHint
would interpret this as the empty string and apply linting rules
accordingly. The empty string is never a valid value for any directive,
so the generated warnings were not appropriate.

If a directive is specified without a value, trigger an explicit error
describing the invalid configuration.

Resolves gh-2261

coveralls: 
[![Coverage Status](https://coveralls.io/builds/2564558/badge)](https://coveralls.io/builds/2564558)

Coverage increased (+0.01%) to 96.57% when pulling **fca531c689916fd105f424a6bb1059dd8261d588 on jugglinmike:2261-empty-directives** into **2ea9cb0f636cf005d48e53cc69b29175818f4ddf on jshint:master**.

coveralls: 
[![Coverage Status](https://coveralls.io/builds/2752296/badge)](https://coveralls.io/builds/2752296)

Coverage increased (+0.01%) to 96.57% when pulling **8e4307d9571964fc65a3ee381c7b6d57f72b3dee on jugglinmike:2261-empty-directives** into **2ea9cb0f636cf005d48e53cc69b29175818f4ddf on jshint:master**.


Patch:
diff --git a/src/jshint.js b/src/jshint.js
index d75cedfc..c843a65a 100644
--- a/src/jshint.js
+++ b/src/jshint.js
@@ -489,11 +489,20 @@ var JSHINT = (function() {
     var body = nt.body.split(",").map(function(s) { return s.trim(); });
     var predef = {};
     if (nt.type === "globals") {
-      body.forEach(function(g) {
+      body.forEach(function(g, idx) {
         g = g.split(":");
         var key = (g[0] || "").trim();
         var val = (g[1] || "").trim();
 
+        if (key === "-" || !key.length) {
+          // Ignore trailing comma
+          if (idx > 0 && idx === body.length - 1) {
+            return;
+          }
+          error("E002", nt);
+          return;
+        }
+
         if (key.charAt(0) === "-") {
           key = key.slice(1);
           val = false;
@@ -515,7 +524,16 @@ var JSHINT = (function() {
     }
 
     if (nt.type === "exported") {
-      body.forEach(function(e) {
+      body.forEach(function(e, idx) {
+        if (!e.length) {
+          // Ignore trailing comma
+          if (idx > 0 && idx === body.length - 1) {
+            return;
+          }
+          error("E002", nt);
+          return;
+        }
+
         exported[e] = true;
       });
     }


Test patch:
diff --git a/tests/unit/parser.js b/tests/unit/parser.js
index 05e5ae7b..4e602cda 100644
--- a/tests/unit/parser.js
+++ b/tests/unit/parser.js
@@ -213,6 +213,47 @@ exports.options = function (test) {
   test.done();
 };
 
+exports.emptyDirectives = function (test) {
+  TestRun(test)
+    .addError(1, "Bad option value.")
+    .test('/* global */');
+
+  TestRun(test)
+    .addError(1, "Bad option value.")
+    .test('/* global : */');
+
+  TestRun(test)
+    .addError(1, "Bad option value.")
+    .test('/* global -: */');
+
+  TestRun(test)
+    .test('/* global foo, bar, baz, */');
+
+  TestRun(test)
+    .addError(1, "Bad option value.")
+    .test('/* globals */');
+
+  TestRun(test)
+    .addError(1, "Bad option value.")
+    .test('/* globals : */');
+
+  TestRun(test)
+    .addError(1, "Bad option value.")
+    .test('/* globals -: */');
+
+  TestRun(test)
+    .test('/* globals foo, bar, baz, */');
+
+  TestRun(test)
+    .addError(1, "Bad option value.")
+    .test('/* exported */');
+
+  TestRun(test)
+    .test('/* exported foo, bar, baz, */');
+
+  test.done();
+};
+
 exports["jshint option comments single line"] = function (test) {
   var src = fs.readFileSync(__dirname + "/fixtures/gh1768-1.js", "utf8");