How to use addError method in Cucumber-gherkin

Best JavaScript code snippet using cucumber-gherkin

parser.js

Source:parser.js Github

copy

Full Screen

...10  var code = [11    "var a\u000a = 'Here is a unsafe character';",12  ];13  TestRun(test)14    .addError(1, "This character may get silently deleted by one or more browsers.")15    .test(code, {es3: true});16  test.done();17};18exports.other = function (test) {19  var code = [20    "\\",21    "!",22  ];23  TestRun(test)24    .addError(1, "Unexpected '\\'.")25    .addError(2, "Unexpected early end of program.")26    .addError(2, "Expected an identifier and instead saw '(end)'.")27    .addError(2, "Unrecoverable syntax error. (100% scanned).")28    .test(code, {es3: true});29  // GH-81830  TestRun(test)31    .addError(1, "Expected an identifier and instead saw ')'.")32    .addError(1, "Unrecoverable syntax error. (100% scanned).")33    .test("if (product < ) {}", {es3: true});34  test.done();35};36exports.confusingOps = function (test) {37  var code = [38    "var a = 3 - -3;",39    "var b = 3 + +3;",40    "a = a - --a;",41    "a = b + ++b;",42    "a = a-- - 3;", // this is not confusing?!43    "a = a++ + 3;", // this is not confusing?!44  ];45  var run = TestRun(test)46    .addError(1, "Confusing minuses.")47    .addError(2, "Confusing plusses.")48    .addError(3, "Confusing minuses.")49    .addError(4, "Confusing plusses.");50  run.test(code, {es3: true});51  run.test(code, {}); // es552  run.test(code, {esnext: true});53  run.test(code, {moz: true});54  test.done();55};56exports.division = function (test) {57  var run;58  var code = [59    'var a=4,b=4,i=2;',60    'a/=b+2;',61    'a/=b/2;',62    'a/=b/i;',63    '/*jshint expr:true*/',64    '/=b/i;' // valid standalone RegExp expression65  ];66  run = TestRun(test);67  run.test(code);68  test.done();69};70exports.plusplus = function (test) {71  var run;72  var code = [73    "var a = ++[2];",74    "var b = --(2);",75  ];76  run = TestRun(test)77    .addError(1, "Unexpected use of '++'.")78    .addError(2, "Unexpected use of '--'.");79  run.test(code, { plusplus: true, es3: true });80  run.test(code, { plusplus: true }); // es581  run.test(code, { plusplus: true, esnext: true });82  run.test(code, { plusplus: true, moz: true });83  run = TestRun(test)84    .addError(2, "Bad operand.");85  run.test(code, { plusplus: false, es3: true });86  run.test(code, { plusplus: false }); // es587  run.test(code, { plusplus: false, esnext: true });88  run.test(code, { plusplus: false, moz: true });89  test.done();90};91exports.assignment = function (test) {92  var code = [93    "function test() {",94    "arguments.length = 2;",95    "arguments[0] = 3;",96    "}",97    "function test2() {",98    "\"use strict\";",99    "arguments.length = 2;",100    "arguments[0] = 3;",101    "}",102    "a() = 2;",103  ];104  var run = TestRun(test)105    .addError(2, "Bad assignment.")106    .addError(3, "Bad assignment.")107    .addError(10, "Bad assignment.")108    .addError(10, "Expected an assignment or function call and instead saw an expression.")109    .addError(10, "Missing semicolon.");110  run.test(code, { plusplus: true, es3: true });111  run.test(code, { plusplus: true }); // es5112  run.test(code, { plusplus: true, esnext: true });113  run.test(code, { plusplus: true, moz: true });114  test.done();115};116exports.relations = function (test) {117  var code = [118    "var a = 2 === NaN;",119    "var b = NaN == 2;",120    "var c = !2 < 3;",121    "var c = 2 < !3;",122    "var d = (!'x' in obj);",123    "var e = (!a === b);",124    "var f = (a === !'hi');",125    "var g = (!2 === 1);",126    "var h = (![1, 2, 3] === []);",127  ];128  var run = TestRun(test)129    .addError(1, "Use the isNaN function to compare with NaN.")130    .addError(2, "Use the isNaN function to compare with NaN.")131    .addError(3, "Confusing use of '!'.", {character : 9})132    .addError(4, "Confusing use of '!'.", {character : 13})133    .addError(5, "Confusing use of '!'.", {character : 10})134    .addError(6, "Confusing use of '!'.", {character : 10})135    .addError(7, "Confusing use of '!'.", {character : 16})136    .addError(8, "Confusing use of '!'.", {character : 10})137    .addError(9, "Confusing use of '!'.", {character : 10});138  run.test(code, {es3: true});139  run.test(code, {}); // es5140  run.test(code, {esnext: true});141  run.test(code, {moz: true});142  test.done();143};144exports.options = function (test) {145  var code = [146    "/*member a*/",147    "/*members b*/",148    "var x; x.a.b.c();",149    "/*jshint ++ */",150    "/*jslint indent: 0 */",151    "/*jslint indent: -2 */",152    "/*jslint indent: 100.4 */",153    "/*jslint maxlen: 200.4 */",154    "/*jslint maxerr: 300.4 */",155    "/*jslint maxerr: 0 */",156    "/*jslint maxerr: 20 */",157    "/*member c:true */",158    "/*jshint d:no */",159    "/*global xxx*/",160    "xxx = 2;",161  ];162  var run = TestRun(test)163    .addError(3, "Unexpected /*member 'c'.")164    .addError(4, "Bad option: '++'.")165    .addError(5, "Expected a small integer or 'false' and instead saw '0'.")166    .addError(6, "Expected a small integer or 'false' and instead saw '-2'.")167    .addError(7, "Expected a small integer or 'false' and instead saw '100.4'.")168    .addError(8, "Expected a small integer or 'false' and instead saw '200.4'.")169    .addError(9, "Expected a small integer or 'false' and instead saw '300.4'.")170    .addError(10, "Expected a small integer or 'false' and instead saw '0'.")171    .addError(13, "Bad option: 'd'.")172    .addError(15, "Read only.");173  run.test(code, {es3: true});174  run.test(code, {}); // es5175  run.test(code, {esnext: true});176  run.test(code, {moz: true});177  TestRun(test).test(fs.readFileSync(__dirname + "/fixtures/gh988.js", "utf8"));178  test.done();179};180exports["jshint option comments single line"] = function (test) {181  var src = fs.readFileSync(__dirname + "/fixtures/gh1768-1.js", "utf8");182  TestRun(test).test(src);183  test.done();184};185exports["jshint option comments single line, leading and trailing space"] = function (test) {186  var src = fs.readFileSync(__dirname + "/fixtures/gh1768-2.js", "utf8");187  TestRun(test).test(src);188  test.done();189};190exports["jshint option comments multi line"] = function (test) {191  var src = fs.readFileSync(__dirname + "/fixtures/gh1768-3.js", "utf8");192  TestRun(test).test(src);193  test.done();194};195exports["jshint option comments multi line, leading and trailing space"] = function (test) {196  var src = fs.readFileSync(__dirname + "/fixtures/gh1768-4.js", "utf8");197  TestRun(test)198    .addError(4, "'foo' is not defined.")199    .test(src);200  test.done();201};202exports["jshint option comments multi line/option"] = function (test) {203  var src = fs.readFileSync(__dirname + "/fixtures/gh1768-5.js", "utf8");204  TestRun(test)205    .addError(3, "'foo' is not defined.")206    .test(src);207  test.done();208};209exports["jshint option comments multi line/option, leading and trailing space"] = function (test) {210  var src = fs.readFileSync(__dirname + "/fixtures/gh1768-6.js", "utf8");211  TestRun(test)212    .addError(4, "'foo' is not defined.")213    .test(src);214  test.done();215};216exports.shebang = function (test) {217  var code = [218    "#!test",219    "var a = 'xxx';",220    "#!test"221  ];222  var run = TestRun(test)223    .addError(3, "Expected an identifier and instead saw '#'.")224    .addError(3, "Expected an operator and instead saw '!'.")225    .addError(3, "Expected an assignment or function call and instead saw an expression.")226    .addError(3, "Missing semicolon.");227  run.test(code, {es3: true});228  run.test(code, {}); // es5229  run.test(code, {esnext: true});230  run.test(code, {moz: true});231  test.done();232};233exports.shebangImpliesNode = function (test) {234  var code = [235    "#!usr/bin/env node",236    "require('module');",237  ];238  TestRun(test).test(code);239  test.done();240};241exports.numbers = function (test) {242  /*jshint maxlen: 300*/243  var code = [244    "var a = 10e307;",245    "var b = 10e308;",246    "var c = 0.03 + 0.3 + 3.0 + 30.00;",247    "var d = 03;",248    "var e = .3;",249    "var f = 0xAAg;",250    "var g = 0033;",251    "var h = 3.;",252    "var i = 3.7.toString();",253    "var j = 1e-10;" // GH-821254  ];255  TestRun(test)256    .addError(2, "Bad number '10e308'.")257    .addError(5, "A leading decimal point can be confused with a dot: '.3'.")258    .addError(6, "Unexpected '0'.")259    .addError(7, "Expected an identifier and instead saw 'var'.")260    .addError(7, "Missing semicolon.")261    .addError(7, "Don't use extra leading zeros '0033'.")262    .addError(8, "A trailing decimal point can be confused with a dot: '3.'.")263    .addError(9, "A dot following a number can be confused with a decimal point.")264    .test(code, {es3: true});265  // Octals are prohibited in strict mode.266  TestRun(test)267    .addError(3, "Octal literals are not allowed in strict mode.")268    .test([269      "(function () {",270      "'use strict';",271      "return 045;",272      "}());"273    ]);274  // GitHub #751 - an expression containing a number with a leading decimal point should be parsed in its entirety275  TestRun(test)276    .addError(1, "A leading decimal point can be confused with a dot: '.3'.")277    .addError(2, "A leading decimal point can be confused with a dot: '.3'.")278    .test([279      "var a = .3 + 1;",280      "var b = 1 + .3;",281    ]);282  test.done();283};284exports.comments = function (test) {285  var code = [286    "/*",287    "/* nested */",288    "*/",289    "/* unclosed ..",290  ];291  var run = TestRun(test)292    .addError(3, "Unbegun comment.")293    .addError(4, "Unclosed comment.");294  run.test(code, {es3: true});295  run.test(code, {}); // es5296  run.test(code, {esnext: true});297  run.test(code, {moz: true});298  var src = "/* this is a comment /* with nested slash-start */";299  TestRun(test).test(src);300  TestRun(test).test(fs.readFileSync(__dirname + "/fixtures/gruntComment.js", "utf8"));301  test.done();302};303exports.regexp = function (test) {304  var code = [305    "var a1 = /\\\x1f/;",306    "var a2 = /[\\\x1f]/;",307    "var b1 = /\\</;", // only \< is unexpected?!308    "var b2 = /[\\<]/;", // only \< is unexpected?!309    "var c = /(?(a)b)/;",310    "var d = /)[--aa-b-cde-]/;",311    "var e = /[]/;",312    "var f = /[^]/;",313    "var g = /[a^[]/;",314    // FIXME: Firefox doesn't handle [a-\\s] well.315    // See https://bugzilla.mozilla.org/show_bug.cgi?id=813249316    "", // "var h = /[a-\\s-\\w-\\d\\x10-\\x20--]/;",317    "var i = /[/-a1-/]/;",318    "var j = /[a-<<-3]./;",319    "var k = /]}/;",320    "var l = /?(*)(+)({)/;",321    "var m = /a{b}b{2,c}c{3,2}d{4,?}x{30,40}/;",322    "var n = /a??b+?c*?d{3,4}? a?b+c*d{3,4}/;",323    "var o = /a\\/*  [a-^-22-]/;",324    "var p = /(?:(?=a|(?!b)))/;",325    "var q = /=;/;",326    "var r = /(/;",327    "var s = /(((/;",328    "var t = /x/* 2;",329    "var u = /x/;",330    "var v = /dsdg;",331    "var w = v + /s/;",332    "var x = w - /s/;",333    "var y = typeof /[a-z]/;" // GH-657334  ];335  var run = TestRun(test)336    .addError(1, "This character may get silently deleted by one or more browsers.")337    .addError(1, "Unexpected control character in regular expression.")338    .addError(2, "This character may get silently deleted by one or more browsers.")339    .addError(2, "Unexpected control character in regular expression.")340    .addError(3, "Unexpected escaped character '<' in regular expression.")341    .addError(4, "Unexpected escaped character '<' in regular expression.")342    .addError(5, "Invalid regular expression.")343    .addError(6, "Invalid regular expression.")344    .addError(11, "Invalid regular expression.")345    .addError(12, "Invalid regular expression.")346    .addError(14, "Invalid regular expression.")347    .addError(15, "Invalid regular expression.")348    .addError(17, "Invalid regular expression.")349    .addError(20, "Invalid regular expression.")350    .addError(21, "Invalid regular expression.")351    .addError(24, "Unclosed regular expression.")352    .addError(24, "Unrecoverable syntax error. (88% scanned).");353  run.test(code, {es3: true});354  run.test(code, {}); // es5355  run.test(code, {esnext: true});356  run.test(code, {moz: true});357  // Pre Regular Expression Punctuation358  //  (See: token method, create function in lex.js)359  //360  // "."361  TestRun(test)362    .addError(1, "A trailing decimal point can be confused with a dot: '10.'.")363    .test("var y = 10. / 1;", {es3: true});364  TestRun(test)365    .addError(1, "A trailing decimal point can be confused with a dot: '10.'.")366    .test("var y = 10. / 1;", {}); // es5367  TestRun(test)368    .addError(1, "A trailing decimal point can be confused with a dot: '10.'.")369    .test("var y = 10. / 1;", {esnext: true});370  TestRun(test)371    .addError(1, "A trailing decimal point can be confused with a dot: '10.'.")372    .test("var y = 10. / 1;", {moz: true});373  // ")"374  TestRun(test).test("var y = Math.sqrt(16) / 180;", {es3: true});375  TestRun(test).test("var y = Math.sqrt(16) / 180;", {}); // es5376  TestRun(test).test("var y = Math.sqrt(16) / 180;", {esnext: true});377  TestRun(test).test("var y = Math.sqrt(16) / 180;", {moz: true});378  // "~"379  TestRun(test).test("var y = Math.sqrt(16) / 180;", {es3: true});380  TestRun(test).test("var y = Math.sqrt(16) / 180;", {}); // es5381  TestRun(test).test("var y = Math.sqrt(16) / 180;", {esnext: true});382  TestRun(test).test("var y = Math.sqrt(16) / 180;", {moz: true});383  // "]" (GH-803)384  TestRun(test).test("var x = [1]; var y = x[0] / 180;", {es3: true});385  TestRun(test).test("var x = [1]; var y = x[0] / 180;", {}); // es5386  TestRun(test).test("var x = [1]; var y = x[0] / 180;", {esnext: true});387  TestRun(test).test("var x = [1]; var y = x[0] / 180;", {moz: true});388  // "++" (GH-1787)389  TestRun(test).test("var a = 1; var b = a++ / 10;", {es3: true});390  TestRun(test).test("var a = 1; var b = a++ / 10;", {}); // es5391  TestRun(test).test("var a = 1; var b = a++ / 10;", {esnext: true});392  TestRun(test).test("var a = 1; var b = a++ / 10;", {moz: true});393  // "--" (GH-1787)394  TestRun(test).test("var a = 1; var b = a-- / 10;", {es3: true});395  TestRun(test).test("var a = 1; var b = a-- / 10;", {}); // es5396  TestRun(test).test("var a = 1; var b = a-- / 10;", {esnext: true});397  TestRun(test).test("var a = 1; var b = a-- / 10;", {moz: true});398  test.done();399};400exports.testRegexRegressions = function (test) {401  // GH-536402  TestRun(test).test("str /= 5;", {es3: true}, { str: true });403  TestRun(test).test("str /= 5;", {}, { str: true }); // es5404  TestRun(test).test("str /= 5;", {esnext: true}, { str: true });405  TestRun(test).test("str /= 5;", {moz: true}, { str: true });406  TestRun(test).test("str = str.replace(/=/g, '');",  {es3: true}, { str: true });407  TestRun(test).test("str = str.replace(/=/g, '');", {}, { str: true }); // es5408  TestRun(test).test("str = str.replace(/=/g, '');", {esnext: true}, { str: true });409  TestRun(test).test("str = str.replace(/=/g, '');", {moz: true}, { str: true });410  TestRun(test).test("str = str.replace(/=abc/g, '');", {es3: true}, { str: true });411  TestRun(test).test("str = str.replace(/=abc/g, '');", {}, { str: true }); // es5412  TestRun(test).test("str = str.replace(/=abc/g, '');", {esnext: true}, { str: true });413  TestRun(test).test("str = str.replace(/=abc/g, '');", {moz: true}, { str: true });414  // GH-538415  TestRun(test).test("var exp = /function(.*){/gi;", {es3: true});416  TestRun(test).test("var exp = /function(.*){/gi;", {}); // es5417  TestRun(test).test("var exp = /function(.*){/gi;", {esnext: true});418  TestRun(test).test("var exp = /function(.*){/gi;", {moz: true});419  test.done();420};421exports.strings = function (test) {422  var code = [423    "var a = '\u0012\\r';",424    "var b = \'\\g\';",425    "var c = '\\u0022\\u0070\\u005C';",426    "var e = '\\x6b..\\x6e';",427    "var f = 'ax"428  ];429  var run = TestRun(test)430    .addError(1, "Control character in string: <non-printable>.", {character: 10})431    .addError(1, "This character may get silently deleted by one or more browsers.")432    .addError(2, "Bad or unnecessary escaping.")433    .addError(5, "Unclosed string.")434    .addError(5, "Missing semicolon.");435  run.test(code, {es3: true});436  run.test(code, {}); // es5437  run.test(code, {esnext: true});438  run.test(code, {moz: true});439  test.done();440};441exports.ownProperty = function (test) {442  var code = [443    "var obj = { hasOwnProperty: false };",444    "obj.hasOwnProperty = true;",445    "obj['hasOwnProperty'] = true;",446    "function test() { var hasOwnProperty = {}.hasOwnProperty; }"447  ];448  var run = TestRun(test)449    .addError(1, "'hasOwnProperty' is a really bad name.")450    .addError(2, "'hasOwnProperty' is a really bad name.")451    .addError(3, "'hasOwnProperty' is a really bad name.")452    .addError(3, "['hasOwnProperty'] is better written in dot notation.");453  run.test(code, {es3: true});454  run.test(code, {}); // es5455  run.test(code, {esnext: true});456  run.test(code, {moz: true});457  test.done();458};459exports.jsonMode = function (test) {460  var code = [461    '{',462    '  a: 2,',463    '  \'b\': "hallo\\"\\v\\x12\\\'world",',464    '  "c\\"\\v\\x12": \'4\',',465    '  "d": "4\\',466    '  ",',467    '  "e": 0x332,',468    '  "x": 0',469    '}',470  ];471  var run = TestRun(test)472    .addError(2, "Expected a string and instead saw a.")473    .addError(3, "Strings must use doublequote.")474    .addError(3, "Avoid \\v.")475    .addError(3, "Avoid \\x-.")476    .addError(3, "Avoid \\'.")477    .addError(4, "Avoid \\v.")478    .addError(4, "Avoid \\x-.")479    .addError(4, "Strings must use doublequote.")480    .addError(5, "Avoid EOL escaping.")481    .addError(7, "Avoid 0x-.");482  run.test(code, {multistr: true, es3: true});483  run.test(code, {multistr: true}); // es5484  run.test(code, {multistr: true, esnext: true});485  run.test(code, {multistr: true, moz: true});486  test.done();487};488exports.comma = function (test) {489  var src = fs.readFileSync(__dirname + "/fixtures/comma.js", "utf8");490  TestRun(test)491    .addError(2, "Expected an assignment or function call and instead saw an expression.")492    .addError(15, "Expected an assignment or function call and instead saw an expression.")493    .addError(15, "Missing semicolon.")494    .addError(20, "Expected an assignment or function call and instead saw an expression.")495    .addError(30, "Expected an assignment or function call and instead saw an expression.")496    .addError(35, "Expected an assignment or function call and instead saw an expression.")497    .addError(35, "Missing semicolon.")498    .addError(36, "Unexpected 'if'.")499    .addError(43, "Expected an assignment or function call and instead saw an expression.")500    .addError(43, "Missing semicolon.")501    .addError(44, "Unexpected '}'.")502    .test(src, {es3: true});503  // Regression test (GH-56)504  TestRun(test)505    .addError(4, "Expected an assignment or function call and instead saw an expression.")506    .test(fs.readFileSync(__dirname + "/fixtures/gh56.js", "utf8"));507  // Regression test (GH-363)508  TestRun(test)509    .addError(1, "Extra comma. (it breaks older versions of IE)")510    .test("var f = [1,];", {es3: true});511  test.done();512};513exports.withStatement = function (test) {514  var src = fs.readFileSync(__dirname + "/fixtures/with.js", "utf8");515  var run;516  run = TestRun(test)517    .addError(5, "Don't use 'with'.")518    .addError(13, "'with' is not allowed in strict mode.");519  run.test(src, {es3: true});520  run.test(src); // es5521  run.test(src, {esnext: true});522  run.test(src, {moz: true});523  run = TestRun(test)524    .addError(13, "'with' is not allowed in strict mode.");525  run.test(src, {withstmt: true, es3: true});526  run.test(src, {withstmt: true}); // es5527  run.test(src, {withstmt: true, esnext: true});528  run.test(src, {withstmt: true, moz: true});529  test.done();530};531exports.blocks = function (test) {532  var src = fs.readFileSync(__dirname + "/fixtures/blocks.js", "utf8");533  var run = TestRun(test)534    .addError(29, "Unmatched \'{\'.")535    .addError(31, "Unmatched \'{\'.");536  run.test(src, {es3: true});537  run.test(src, {}); // es5538  run.test(src, {esnext: true});539  run.test(src, {moz: true});540  test.done();541};542exports.functionCharacterLocation = function (test) {543  var i;544  var src = fs.readFileSync(__dirname + "/fixtures/nestedFunctions.js", "utf8");545  var locations = JSON.parse(546    fs.readFileSync(547      __dirname + "/fixtures/nestedFunctions-locations.js", "utf8"548    )549  );550  JSHINT(src);551  var report = JSHINT.data().functions;552  test.equal(locations.length, report.length);553  for (i = 0; i < locations.length; i += 1) {554    test.equal(locations[i].name, report[i].name);555    test.equal(locations[i].line, report[i].line);556    test.equal(locations[i].character, report[i].character);557    test.equal(locations[i].last, report[i].last);558    test.equal(locations[i].lastcharacter, report[i].lastcharacter);559  }560  test.done();561};562exports.exported = function (test) {563  var src = fs.readFileSync(__dirname + "/fixtures/exported.js", "utf8");564  var run = TestRun(test)565    .addError(5, "'unused' is defined but never used.")566    .addError(6, "'isDog' is defined but never used.")567    .addError(13, "'unusedDeclaration' is defined but never used.")568    .addError(14, "'unusedExpression' is defined but never used.")569    .addError(17, "'cannotBeExported' is defined but never used.");570  run.test(src, {es3: true, unused: true });571  run.test(src, {unused: true }); // es5572  run.test(src, {esnext: true, unused: true });573  run.test(src, {moz: true, unused: true });574  run = TestRun(test)575    .addError(1, "'unused' is defined but never used.")576    .test("var unused = 1; var used = 2;", {exported: ["used"], unused: true});577  test.done();578};579exports.testIdentifiers = function (test) {580  var src = fs.readFileSync(__dirname + "/fixtures/identifiers.js", "utf8");581  TestRun(test).test(src, {es3: true});582  var run = TestRun(test)583    .addError(1, "'ascii' is defined but never used.")584    .addError(2, "'num1' is defined but never used.")585    .addError(3, "'lifé' is defined but never used.")586    .addError(4, "'π' is defined but never used.")587    .addError(5, "'привет' is defined but never used.")588    .addError(6, "'\\u1d44' is defined but never used.")589    .addError(7, "'encoded\\u1d44' is defined but never used.")590    .addError(8, "'\\uFF38' is defined but never used.")591    .addError(9, "'\\uFF58' is defined but never used.")592    .addError(10, "'\\u1FBC' is defined but never used.")593    .addError(11, "'\\uFF70' is defined but never used.")594    .addError(12, "'\\u4DB3' is defined but never used.")595    .addError(13, "'\\u97CA' is defined but never used.")596    .addError(14, "'\\uD7A1' is defined but never used.")597    .addError(15, "'\\uFFDA' is defined but never used.")598    .addError(16, "'\\uA6ED' is defined but never used.")599    .addError(17, "'\\u0024' is defined but never used.")600    .addError(18, "'\\u005F' is defined but never used.")601    .addError(19, "'\\u0024\\uFF38' is defined but never used.")602    .addError(20, "'\\u0024\\uFF58' is defined but never used.")603    .addError(21, "'\\u0024\\u1FBC' is defined but never used.")604    .addError(22, "'\\u0024\\uFF70' is defined but never used.")605    .addError(23, "'\\u0024\\u4DB3' is defined but never used.")606    .addError(24, "'\\u0024\\u97CA' is defined but never used.")607    .addError(25, "'\\u0024\\uD7A1' is defined but never used.")608    .addError(26, "'\\u0024\\uFFDA' is defined but never used.")609    .addError(27, "'\\u0024\\uA6ED' is defined but never used.")610    .addError(28, "'\\u0024\\uFE24' is defined but never used.")611    .addError(29, "'\\u0024\\uABE9' is defined but never used.")612    .addError(30, "'\\u0024\\uFF17' is defined but never used.")613    .addError(31, "'\\u0024\\uFE4E' is defined but never used.")614    .addError(32, "'\\u0024\\u200C' is defined but never used.")615    .addError(33, "'\\u0024\\u200D' is defined but never used.")616    .addError(34, "'\\u0024\\u0024' is defined but never used.")617    .addError(35, "'\\u0024\\u005F' is defined but never used.");618  run.test(src, {es3: true, unused: true });619  run.test(src, {unused: true }); // es5620  run.test(src, {esnext: true, unused: true });621  run.test(src, {moz: true, unused: true });622  test.done();623};624exports["regression for GH-878"] = function (test) {625  var src = fs.readFileSync(__dirname + "/fixtures/gh878.js", "utf8");626  TestRun(test).test(src, {es3: true});627  test.done();628};629exports["regression for GH-910"] = function (test) {630  var src = "(function () { if (true) { foo.bar + } })();";631  TestRun(test)632    .addError(1, "Expected an identifier and instead saw '}'.")633    .addError(1, "Expected an assignment or function call and instead saw an expression.")634    .addError(1, "Missing semicolon.")635    .addError(1, "Expected an identifier and instead saw ')'.")636    .addError(1, "Expected an operator and instead saw '('.")637    .addError(1, "Unmatched '{'.")638    .addError(1, "Unmatched '('.")639    .addError(1, "Expected an assignment or function call and instead saw an expression.")640    .addError(1, "Missing semicolon.")641    .test(src, { es3: true, nonew: true });642  test.done();643};644exports.testHtml = function (test) {645  var html = "<html><body>Hello World</body></html>";646  TestRun(test)647    .addError(1, "Expected an identifier and instead saw '<'.")648    .addError(1, "Expected an assignment or function call and instead saw an expression.")649    .addError(1, "Missing semicolon.")650    .addError(1, "Expected an identifier and instead saw '<'.")651    .addError(1, "Unrecoverable syntax error. (100% scanned).")652    .test(html, {});653  test.done();654};655exports["test: destructuring var in function scope"] = function (test) {656  var code = [657    "function foobar() {",658    "  var [ a, b, c ] = [ 1, 2, 3 ];",659    "  var [ a ] = [ 1 ];",660    "  var [ a ] = [ z ];",661    "  var [ h, w ] = [ 'hello', 'world' ]; ",662    "  var [ o ] = [ { o : 1 } ];",663    "  var [ a, [ [ [ b ], c ], d ] ] = [ 1, [ [ [ 2 ], 3], 4 ] ];",664    "  var { foo : bar } = { foo : 1 };",665    "  var [ a, { foo : bar } ] = [ 2, { foo : 1 } ];",666    "  var [ 1 ] = [ a ];",667    "  var [ a, b; c ] = [ 1, 2, 3 ];",668    "  var [ a, b, c ] = [ 1, 2; 3 ];",669    "}"670  ];671  TestRun(test)672    .addError(1,  "'foobar' is defined but never used.")673    .addError(3,  "'a' is already defined.")674    .addError(4,  "'a' is already defined.")675    .addError(7,  "'a' is already defined.")676    .addError(7,  "'b' is already defined.")677    .addError(7,  "'c' is already defined.")678    .addError(9,  "'a' is already defined.")679    .addError(9,  "'bar' is already defined.")680    .addError(10,  "Expected an identifier and instead saw '1'.")681    .addError(10,  "Expected ',' and instead saw '1'.")682    .addError(10,  "Expected an identifier and instead saw ']'.")683    .addError(11, "Expected ',' and instead saw ';'.")684    .addError(11, "'a' is already defined.")685    .addError(11, "'b' is already defined.")686    .addError(11, "'c' is already defined.")687    .addError(12, "'a' is already defined.")688    .addError(12, "'b' is already defined.")689    .addError(12, "'c' is already defined.")690    .addError(12, "Expected ']' to match '[' from line 12 and instead saw ';'.")691    .addError(12, "Missing semicolon.")692    .addError(12, "Expected an assignment or function call and instead saw an expression.")693    .addError(12, "Missing semicolon.")694    .addError(12, "Expected an identifier and instead saw ']'.")695    .addError(12, "Expected an assignment or function call and instead saw an expression.")696    .addError(4,  "'z' is not defined.")697    .addError(12, "'a' is defined but never used.")698    .addError(12, "'b' is defined but never used.")699    .addError(12, "'c' is defined but never used.")700    .addError(5,  "'h' is defined but never used.")701    .addError(5,  "'w' is defined but never used.")702    .addError(6,  "'o' is defined but never used.")703    .addError(7,  "'d' is defined but never used.")704    .addError(9,  "'bar' is defined but never used.")705    .test(code, {esnext: true, unused: true, undef: true});706  test.done();707};708exports["test: destructuring var as moz"] = function (test) {709  var code = [710    "var [ a, b, c ] = [ 1, 2, 3 ];",711    "var [ a ] = [ 1 ];",712    "var [ a ] = [ z ];",713    "var [ h, w ] = [ 'hello', 'world' ]; ",714    "var [ o ] = [ { o : 1 } ];",715    "var [ a, [ [ [ b ], c ], d ] ] = [ 1, [ [ [ 2 ], 3], 4 ] ];",716    "var { foo : bar } = { foo : 1 };",717    "var [ a, { foo : bar } ] = [ 2, { foo : 1 } ];",718  ];719  TestRun(test)720    .addError(3,  "'z' is not defined.")721    .addError(8,  "'a' is defined but never used.")722    .addError(6,  "'b' is defined but never used.")723    .addError(6,  "'c' is defined but never used.")724    .addError(4,  "'h' is defined but never used.")725    .addError(4,  "'w' is defined but never used.")726    .addError(5,  "'o' is defined but never used.")727    .addError(6,  "'d' is defined but never used.")728    .addError(8,  "'bar' is defined but never used.")729    .test(code, {moz: true, unused: true, undef: true});730  test.done();731};732exports["test: destructuring var as esnext"] = function (test) {733  var code = [734    "var [ a, b, c ] = [ 1, 2, 3 ];",735    "var [ a ] = [ 1 ];",736    "var [ a ] = [ z ];",737    "var [ h, w ] = [ 'hello', 'world' ]; ",738    "var [ o ] = [ { o : 1 } ];",739    "var [ a, [ [ [ b ], c ], d ] ] = [ 1, [ [ [ 2 ], 3], 4 ] ];",740    "var { foo : bar } = { foo : 1 };",741    "var [ a, { foo : bar } ] = [ 2, { foo : 1 } ];",742  ];743  TestRun(test)744    .addError(3,  "'z' is not defined.")745    .addError(8,  "'a' is defined but never used.")746    .addError(6,  "'b' is defined but never used.")747    .addError(6,  "'c' is defined but never used.")748    .addError(4,  "'h' is defined but never used.")749    .addError(4,  "'w' is defined but never used.")750    .addError(5,  "'o' is defined but never used.")751    .addError(6,  "'d' is defined but never used.")752    .addError(8,  "'bar' is defined but never used.")753    .test(code, {esnext: true, unused: true, undef: true});754  test.done();755};756exports["test: destructuring var as es5"] = function (test) {757  var code = [758    "var [ a, b, c ] = [ 1, 2, 3 ];",759    "var [ a ] = [ 1 ];",760    "var [ a ] = [ z ];",761    "var [ h, w ] = [ 'hello', 'world' ]; ",762    "var [ o ] = [ { o : 1 } ];",763    "var [ a, [ [ [ b ], c ], d ] ] = [ 1, [ [ [ 2 ], 3], 4 ] ];",764    "var { foo : bar } = { foo : 1 };",765    "var [ a, { foo : bar } ] = [ 2, { foo : 1 } ];",766  ];767  TestRun(test)768    .addError(1, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")769    .addError(2, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")770    .addError(3, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")771    .addError(4, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")772    .addError(5, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")773    .addError(6, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")774    .addError(6, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")775    .addError(6, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")776    .addError(7, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")777    .addError(8, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")778    .addError(8, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")779    .addError(3,  "'z' is not defined.")780    .addError(8,  "'a' is defined but never used.")781    .addError(6,  "'b' is defined but never used.")782    .addError(6,  "'c' is defined but never used.")783    .addError(4,  "'h' is defined but never used.")784    .addError(4,  "'w' is defined but never used.")785    .addError(5,  "'o' is defined but never used.")786    .addError(6,  "'d' is defined but never used.")787    .addError(8,  "'bar' is defined but never used.")788    .test(code, {unused: true, undef: true}); // es5789  test.done();790};791exports["test: destructuring var as legacy JS"] = function (test) {792  var code = [793    "var [ a, b, c ] = [ 1, 2, 3 ];",794    "var [ a ] = [ 1 ];",795    "var [ a ] = [ z ];",796    "var [ h, w ] = [ 'hello', 'world' ]; ",797    "var [ o ] = [ { o : 1 } ];",798    "var [ a, [ [ [ b ], c ], d ] ] = [ 1, [ [ [ 2 ], 3], 4 ] ];",799    "var { foo : bar } = { foo : 1 };",800    "var [ a, { foo : bar } ] = [ 2, { foo : 1 } ];",801  ];802  TestRun(test)803    .addError(1, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")804    .addError(2, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")805    .addError(3, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")806    .addError(4, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")807    .addError(5, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")808    .addError(6, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")809    .addError(6, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")810    .addError(6, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")811    .addError(7, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")812    .addError(8, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")813    .addError(8, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")814    .addError(3,  "'z' is not defined.")815    .addError(8,  "'a' is defined but never used.")816    .addError(6,  "'b' is defined but never used.")817    .addError(6,  "'c' is defined but never used.")818    .addError(4,  "'h' is defined but never used.")819    .addError(4,  "'w' is defined but never used.")820    .addError(5,  "'o' is defined but never used.")821    .addError(6,  "'d' is defined but never used.")822    .addError(8,  "'bar' is defined but never used.")823    .test(code, {es3: true, unused: true, undef: true});824  test.done();825};826exports["test: destructuring var errors"] = function (test) {827  var code = [828    "var [ a, b, c ] = [ 1, 2, 3 ];",829    "var [ a ] = [ 1 ];",830    "var [ a ] = [ z ];",831    "var [ h, w ] = [ 'hello', 'world' ]; ",832    "var [ o ] = [ { o : 1 } ];",833    "var [ a, [ [ [ b ], c ], d ] ] = [ 1, [ [ [ 2 ], 3], 4 ] ];",834    "var { foo : bar } = { foo : 1 };",835    "var [ a, { foo : bar } ] = [ 2, { foo : 1 } ];",836    "var [ 1 ] = [ a ];",837    "var [ a, b; c ] = [ 1, 2, 3 ];",838    "var [ a, b, c ] = [ 1, 2; 3 ];"839  ];840  TestRun(test)841    .addError(9,  "Expected an identifier and instead saw '1'.")842    .addError(9,  "Expected ',' and instead saw '1'.")843    .addError(9,  "Expected an identifier and instead saw ']'.")844    .addError(10, "Expected ',' and instead saw ';'.")845    .addError(11, "Expected ']' to match '[' from line 11 and instead saw ';'.")846    .addError(11, "Missing semicolon.")847    .addError(11, "Expected an assignment or function call and instead saw an expression.")848    .addError(11, "Missing semicolon.")849    .addError(11, "Expected an identifier and instead saw ']'.")850    .addError(11, "Expected an assignment or function call and instead saw an expression.")851    .addError(3,  "'z' is not defined.")852    .addError(11, "'a' is defined but never used.")853    .addError(11, "'b' is defined but never used.")854    .addError(11, "'c' is defined but never used.")855    .addError(4,  "'h' is defined but never used.")856    .addError(4,  "'w' is defined but never used.")857    .addError(5,  "'o' is defined but never used.")858    .addError(6,  "'d' is defined but never used.")859    .addError(8,  "'bar' is defined but never used.")860    .test(code, {esnext: true, unused: true, undef: true});861  test.done();862};863exports["test: destructuring const as moz"] = function (test) {864  var code = [865    "const [ a, b, c ] = [ 1, 2, 3 ];",866    "const [ d ] = [ 1 ];",867    "const [ e ] = [ z ];",868    "const [ hel, wor ] = [ 'hello', 'world' ]; ",869    "const [ o ] = [ { o : 1 } ];",870    "const [ f, [ [ [ g ], h ], i ] ] = [ 1, [ [ [ 2 ], 3], 4 ] ];",871    "const { foo : bar } = { foo : 1 };",872    "const [ j, { foo : foobar } ] = [ 2, { foo : 1 } ];",873    "const [ aa, bb ] = yield func();"874  ];875  TestRun(test)876    .addError(1, "'a' is defined but never used.")877    .addError(1, "'b' is defined but never used.")878    .addError(1, "'c' is defined but never used.")879    .addError(2, "'d' is defined but never used.")880    .addError(3, "'e' is defined but never used.")881    .addError(4, "'hel' is defined but never used.")882    .addError(4, "'wor' is defined but never used.")883    .addError(5, "'o' is defined but never used.")884    .addError(6, "'f' is defined but never used.")885    .addError(6, "'g' is defined but never used.")886    .addError(6, "'h' is defined but never used.")887    .addError(6, "'i' is defined but never used.")888    .addError(7, "'bar' is defined but never used.")889    .addError(8, "'j' is defined but never used.")890    .addError(8, "'foobar' is defined but never used.")891    .addError(9, "'aa' is defined but never used.")892    .addError(9, "'bb' is defined but never used.")893    .addError(3, "'z' is not defined.")894    .addError(9, "'func' is not defined.")895    .test(code, {moz: true, unused: true, undef: true});896  test.done();897};898exports["test: destructuring const as esnext"] = function (test) {899  var code = [900    "const [ a, b, c ] = [ 1, 2, 3 ];",901    "const [ d ] = [ 1 ];",902    "const [ e ] = [ z ];",903    "const [ hel, wor ] = [ 'hello', 'world' ]; ",904    "const [ o ] = [ { o : 1 } ];",905    "const [ f, [ [ [ g ], h ], i ] ] = [ 1, [ [ [ 2 ], 3], 4 ] ];",906    "const { foo : bar } = { foo : 1 };",907    "const [ j, { foo : foobar } ] = [ 2, { foo : 1 } ];",908  ];909  TestRun(test)910    .addError(1, "'a' is defined but never used.")911    .addError(1, "'b' is defined but never used.")912    .addError(1, "'c' is defined but never used.")913    .addError(2, "'d' is defined but never used.")914    .addError(3, "'e' is defined but never used.")915    .addError(4, "'hel' is defined but never used.")916    .addError(4, "'wor' is defined but never used.")917    .addError(5, "'o' is defined but never used.")918    .addError(6, "'f' is defined but never used.")919    .addError(6, "'g' is defined but never used.")920    .addError(6, "'h' is defined but never used.")921    .addError(6, "'i' is defined but never used.")922    .addError(7, "'bar' is defined but never used.")923    .addError(8, "'j' is defined but never used.")924    .addError(8, "'foobar' is defined but never used.")925    .addError(3, "'z' is not defined.")926    .test(code, {esnext: true, unused: true, undef: true});927  test.done();928};929exports["test: destructuring const as es5"] = function (test) {930  var code = [931    "const [ a, b, c ] = [ 1, 2, 3 ];",932    "const [ d ] = [ 1 ];",933    "const [ e ] = [ z ];",934    "const [ hel, wor ] = [ 'hello', 'world' ]; ",935    "const [ o ] = [ { o : 1 } ];",936    "const [ f, [ [ [ g ], h ], i ] ] = [ 1, [ [ [ 2 ], 3], 4 ] ];",937    "const { foo : bar } = { foo : 1 };",938    "const [ j, { foo : foobar } ] = [ 2, { foo : 1 } ];",939  ];940  TestRun(test)941    .addError(1, "'const' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")942    .addError(1, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")943    .addError(2, "'const' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")944    .addError(2, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")945    .addError(3, "'const' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")946    .addError(3, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")947    .addError(4, "'const' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")948    .addError(4, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")949    .addError(5, "'const' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")950    .addError(5, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")951    .addError(6, "'const' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")952    .addError(6, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")953    .addError(6, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")954    .addError(7, "'const' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")955    .addError(7, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")956    .addError(8, "'const' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")957    .addError(8, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")958    .addError(8, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")959    .addError(1, "'a' is defined but never used.")960    .addError(1, "'b' is defined but never used.")961    .addError(1, "'c' is defined but never used.")962    .addError(2, "'d' is defined but never used.")963    .addError(3, "'e' is defined but never used.")964    .addError(4, "'hel' is defined but never used.")965    .addError(4, "'wor' is defined but never used.")966    .addError(5, "'o' is defined but never used.")967    .addError(6, "'f' is defined but never used.")968    .addError(6, "'g' is defined but never used.")969    .addError(6, "'h' is defined but never used.")970    .addError(6, "'i' is defined but never used.")971    .addError(7, "'bar' is defined but never used.")972    .addError(8, "'j' is defined but never used.")973    .addError(8, "'foobar' is defined but never used.")974    .addError(3, "'z' is not defined.")975    .test(code, {unused: true, undef: true}); // es5976  test.done();977};978exports["test: destructuring const as legacy JS"] = function (test) {979  var code = [980    "const [ a, b, c ] = [ 1, 2, 3 ];",981    "const [ d ] = [ 1 ];",982    "const [ e ] = [ z ];",983    "const [ hel, wor ] = [ 'hello', 'world' ]; ",984    "const [ o ] = [ { o : 1 } ];",985    "const [ f, [ [ [ g ], h ], i ] ] = [ 1, [ [ [ 2 ], 3], 4 ] ];",986    "const { foo : bar } = { foo : 1 };",987    "const [ j, { foo : foobar } ] = [ 2, { foo : 1 } ];",988  ];989  TestRun(test)990    .addError(1, "'const' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")991    .addError(1, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")992    .addError(2, "'const' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")993    .addError(2, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")994    .addError(3, "'const' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")995    .addError(3, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")996    .addError(4, "'const' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")997    .addError(4, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")998    .addError(5, "'const' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")999    .addError(5, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1000    .addError(6, "'const' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1001    .addError(6, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1002    .addError(6, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1003    .addError(7, "'const' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1004    .addError(7, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1005    .addError(8, "'const' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1006    .addError(8, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1007    .addError(8, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1008    .addError(1, "'a' is defined but never used.")1009    .addError(1, "'b' is defined but never used.")1010    .addError(1, "'c' is defined but never used.")1011    .addError(2, "'d' is defined but never used.")1012    .addError(3, "'e' is defined but never used.")1013    .addError(4, "'hel' is defined but never used.")1014    .addError(4, "'wor' is defined but never used.")1015    .addError(5, "'o' is defined but never used.")1016    .addError(6, "'f' is defined but never used.")1017    .addError(6, "'g' is defined but never used.")1018    .addError(6, "'h' is defined but never used.")1019    .addError(6, "'i' is defined but never used.")1020    .addError(7, "'bar' is defined but never used.")1021    .addError(8, "'j' is defined but never used.")1022    .addError(8, "'foobar' is defined but never used.")1023    .addError(3, "'z' is not defined.")1024    .test(code, {es3: true, unused: true, undef: true});1025  test.done();1026};1027exports["test: destructuring const errors"] = function (test) {1028  var code = [1029    "const [ a, b, c ] = [ 1, 2, 3 ];",1030    "const [ a, b, c ] = [ 1, 2, 3 ];",1031    "const [ 1 ] = [ a ];",1032    "const [ k, l; m ] = [ 1, 2, 3 ];",1033    "const [ n, o, p ] = [ 1, 2; 3 ];"1034  ];1035  TestRun(test)1036    .addError(2, "'b' is defined but never used.")1037    .addError(2, "'c' is defined but never used.")1038    .addError(4, "'k' is defined but never used.")1039    .addError(4, "'l' is defined but never used.")1040    .addError(4, "'m' is defined but never used.")1041    .addError(5, "'n' is defined but never used.")1042    .addError(5, "'o' is defined but never used.")1043    .addError(5, "'p' is defined but never used.")1044    .addError(2, "const 'a' has already been declared.")1045    .addError(2, "const 'b' has already been declared.")1046    .addError(2, "const 'c' has already been declared.")1047    .addError(3, "Expected an identifier and instead saw '1'.")1048    .addError(3, "Expected ',' and instead saw '1'.")1049    .addError(3, "Expected an identifier and instead saw ']'.")1050    .addError(4, "Expected ',' and instead saw ';'.")1051    .addError(5, "Expected ']' to match '[' from line 5 and instead saw ';'.")1052    .addError(5, "Missing semicolon.")1053    .addError(5, "Expected an assignment or function call and instead saw an expression.")1054    .addError(5, "Missing semicolon.")1055    .addError(5, "Expected an identifier and instead saw ']'.")1056    .addError(5, "Expected an assignment or function call and instead saw an expression.")1057    .addError(5, "Missing semicolon.")1058    .test(code, {es3: true, esnext: true, unused: true, undef: true});1059  test.done();1060};1061exports["test: destructuring globals as moz"] = function (test) {1062  var code = [1063    "var a, b, c, d, h, w, o;",1064    "[ a, b, c ] = [ 1, 2, 3 ];",1065    "[ a ] = [ 1 ];",1066    "[ a ] = [ z ];",1067    "[ h, w ] = [ 'hello', 'world' ]; ",1068    "[ o ] = [ { o : 1 } ];",1069    "[ a, [ [ [ b ], c ], d ] ] = [ 1, [ [ [ 2 ], 3], 4 ] ];",1070    "[ a, { foo : b } ] = [ 2, { foo : 1 } ];",1071  ];1072  TestRun(test)1073    .addError(4,  "'z' is not defined.")1074    .test(code, {moz: true, unused: true, undef: true});1075  test.done();1076};1077exports["test: destructuring globals as esnext"] = function (test) {1078  var code = [1079    "var a, b, c, d, h, w, o;",1080    "[ a, b, c ] = [ 1, 2, 3 ];",1081    "[ a ] = [ 1 ];",1082    "[ a ] = [ z ];",1083    "[ h, w ] = [ 'hello', 'world' ]; ",1084    "[ o ] = [ { o : 1 } ];",1085    "[ a, [ [ [ b ], c ], d ] ] = [ 1, [ [ [ 2 ], 3], 4 ] ];",1086    "[ a, { foo : b } ] = [ 2, { foo : 1 } ];",1087  ];1088  TestRun(test)1089    .addError(4,  "'z' is not defined.")1090    .test(code, {esnext: true, unused: true, undef: true});1091  test.done();1092};1093exports["test: destructuring globals as es5"] = function (test) {1094  var code = [1095    "var a, b, c, d, h, w, o;",1096    "[ a, b, c ] = [ 1, 2, 3 ];",1097    "[ a ] = [ 1 ];",1098    "[ a ] = [ z ];",1099    "[ h, w ] = [ 'hello', 'world' ]; ",1100    "[ o ] = [ { o : 1 } ];",1101    "[ a, [ [ [ b ], c ], d ] ] = [ 1, [ [ [ 2 ], 3], 4 ] ];",1102    "[ a, { foo : b } ] = [ 2, { foo : 1 } ];",1103  ];1104  TestRun(test)1105    .addError(4,  "'z' is not defined.")1106    .addError(2, "'destructuring assignment' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1107    .addError(3, "'destructuring assignment' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1108    .addError(4, "'destructuring assignment' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1109    .addError(5, "'destructuring assignment' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1110    .addError(6, "'destructuring assignment' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1111    .addError(7, "'destructuring assignment' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1112    .addError(8, "'destructuring assignment' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1113    .test(code, {unused: true, undef: true}); // es51114  test.done();1115};1116exports["test: destructuring globals as legacy JS"] = function (test) {1117  var code = [1118    "var a, b, c, d, h, w, o;",1119    "[ a, b, c ] = [ 1, 2, 3 ];",1120    "[ a ] = [ 1 ];",1121    "[ a ] = [ z ];",1122    "[ h, w ] = [ 'hello', 'world' ]; ",1123    "[ o ] = [ { o : 1 } ];",1124    "[ a, [ [ [ b ], c ], d ] ] = [ 1, [ [ [ 2 ], 3], 4 ] ];",1125    "[ a, { foo : b } ] = [ 2, { foo : 1 } ];",1126  ];1127  TestRun(test)1128    .addError(4,  "'z' is not defined.")1129    .addError(2, "'destructuring assignment' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1130    .addError(3, "'destructuring assignment' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1131    .addError(4, "'destructuring assignment' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1132    .addError(5, "'destructuring assignment' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1133    .addError(6, "'destructuring assignment' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1134    .addError(7, "'destructuring assignment' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1135    .addError(8, "'destructuring assignment' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1136    .test(code, {es3: true, unused: true, undef: true});1137  test.done();1138};1139exports["test: destructuring globals with syntax error"] = function (test) {1140  var code = [1141    "var a, b, c;",1142    "[ a ] = [ z ];",1143    "[ 1 ] = [ a ];",1144    "[ a, b; c ] = [ 1, 2, 3 ];",1145    "[ a, b, c ] = [ 1, 2; 3 ];"1146  ];1147  TestRun(test)1148    .addError(4, "Expected ']' to match '[' from line 4 and instead saw ';'.")1149    .addError(4, "Expected an assignment or function call and instead saw an expression.")1150    .addError(4, "Missing semicolon.")1151    .addError(4, "Expected an assignment or function call and instead saw an expression.")1152    .addError(4, "Missing semicolon.")1153    .addError(4, "Expected an identifier and instead saw ']'.")1154    .addError(4, "Expected an operator and instead saw '='.")1155    .addError(4, "Expected an operator and instead saw '['.")1156    .addError(4, "Expected an assignment or function call and instead saw an expression.")1157    .addError(4, "Missing semicolon.")1158    .addError(4, "Expected an assignment or function call and instead saw an expression.")1159    .addError(4, "Expected an assignment or function call and instead saw an expression.")1160    .addError(4, "Missing semicolon.")1161    .addError(4, "Expected an identifier and instead saw ']'.")1162    .addError(4, "Expected an assignment or function call and instead saw an expression.")1163    .addError(5, "Expected ']' to match '[' from line 5 and instead saw ';'.")1164    .addError(5, "Missing semicolon.")1165    .addError(5, "Expected an assignment or function call and instead saw an expression.")1166    .addError(5, "Missing semicolon.")1167    .addError(5, "Expected an identifier and instead saw ']'.")1168    .addError(5, "Expected an assignment or function call and instead saw an expression.")1169    .addError(2,  "'z' is not defined.")1170    .test(code, {esnext: true, unused: true, undef: true});1171  test.done();1172};1173exports["test: destructuring assign of empty values as moz"] = function (test) {1174  var code = [1175    "var [ a ] = [ 1, 2 ];",1176    "var [ c, d ] = [ 1 ];",1177    "var [ e, , f ] = [ 3, , 4 ];"1178  ];1179  TestRun(test)1180    .addError(1, "'a' is defined but never used.")1181    .addError(2, "'c' is defined but never used.")1182    .addError(2, "'d' is defined but never used.")1183    .addError(3, "'e' is defined but never used.")1184    .addError(3, "'f' is defined but never used.")1185    .test(code, {moz: true, unused: true, undef: true, laxcomma: true});1186  test.done();1187};1188exports["test: destructuring assign of empty values as esnext"] = function (test) {1189  var code = [1190    "var [ a ] = [ 1, 2 ];",1191    "var [ c, d ] = [ 1 ];",1192    "var [ e, , f ] = [ 3, , 4 ];"1193  ];1194  TestRun(test)1195    .addError(1, "'a' is defined but never used.")1196    .addError(2, "'c' is defined but never used.")1197    .addError(2, "'d' is defined but never used.")1198    .addError(3, "'e' is defined but never used.")1199    .addError(3, "'f' is defined but never used.")1200    .test(code, {esnext: true, unused: true, undef: true});1201  test.done();1202};1203exports["test: destructuring assign of empty values as es5"] = function (test) {1204  var code = [1205    "var [ a ] = [ 1, 2 ];",1206    "var [ c, d ] = [ 1 ];",1207    "var [ e, , f ] = [ 3, , 4 ];"1208  ];1209  TestRun(test)1210    .addError(1, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1211    .addError(1, "'a' is defined but never used.")1212    .addError(2, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1213    .addError(2, "'c' is defined but never used.")1214    .addError(2, "'d' is defined but never used.")1215    .addError(3, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1216    .addError(3, "'e' is defined but never used.")1217    .addError(3, "'f' is defined but never used.")1218    .test(code, {unused: true, undef: true}); // es51219  test.done();1220};1221exports["test: destructuring assign of empty values as JS legacy"] = function (test) {1222  var code = [1223    "var [ a ] = [ 1, 2 ];",1224    "var [ c, d ] = [ 1 ];",1225    "var [ e, , f ] = [ 3, , 4 ];"1226  ];1227  TestRun(test)1228    .addError(1, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1229    .addError(1, "'a' is defined but never used.")1230    .addError(2, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1231    .addError(2, "'c' is defined but never used.")1232    .addError(2, "'d' is defined but never used.")1233    .addError(3, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1234    .addError(3, "'e' is defined but never used.")1235    .addError(3, "'f' is defined but never used.")1236    .addError(3, "Extra comma. (it breaks older versions of IE)")1237    .test(code, {es3: true, unused: true, undef: true});1238  test.done();1239};1240exports["test: array element assignment inside array"] = function (test) {1241  var code = [1242    "var a1 = {};",1243    "var a2 = [function f() {a1[0] = 1;}];",1244  ];1245  TestRun(test)1246    .test(code);1247  test.done();1248};1249exports["test: let statement as moz"] = function (test) {1250  var code = [1251    "let x = 1;",1252    "{",1253    "  let y = 3 ;",1254    "  {",1255    "    let z = 2;",1256    "    print(x + ' ' + y + ' ' + z);",1257    "  }",1258    "  print(x + ' ' + y);",1259    "}",1260    "print(x);"1261  ];1262  TestRun(test)1263    .test(code, {moz: true, unused: true, undef: true, predef: ["print"]});1264  test.done();1265};1266exports["test: let statement as esnext"] = function (test) {1267  var code = [1268    "let x = 1;",1269    "{",1270    "  let y = 3 ;",1271    "  {",1272    "    let z = 2;",1273    "    print(x + ' ' + y + ' ' + z);",1274    "  }",1275    "  print(x + ' ' + y);",1276    "}",1277    "print(x);"1278  ];1279  TestRun(test)1280    .test(code, {esnext: true, unused: true, undef: true, predef: ["print"]});1281  test.done();1282};1283exports["test: let statement as es5"] = function (test) {1284  var code = [1285    "let x = 1;",1286    "{",1287    "  let y = 3 ;",1288    "  {",1289    "    let z = 2;",1290    "    print(x + ' ' + y + ' ' + z);",1291    "  }",1292    "  print(x + ' ' + y);",1293    "}",1294    "print(x);"1295  ];1296  TestRun(test)1297    .addError(1, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1298    .addError(3, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1299    .addError(5, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1300    .test(code, {unused: true, undef: true, predef: ["print"]}); // es51301  test.done();1302};1303exports["test: let statement as legacy JS"] = function (test) {1304  var code = [1305    "let x = 1;",1306    "{",1307    "  let y = 3 ;",1308    "  {",1309    "    let z = 2;",1310    "    print(x + ' ' + y + ' ' + z);",1311    "  }",1312    "  print(x + ' ' + y);",1313    "}",1314    "print(x);"1315  ];1316  TestRun(test)1317    .addError(1, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1318    .addError(3, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1319    .addError(5, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1320    .test(code, {es3: true, unused: true, undef: true, predef: ["print"]});1321  test.done();1322};1323exports["test: let statement out of scope as moz"] = function (test) {1324  var code = [1325    "let x = 1;",1326    "{",1327    "  let y = 3 ;",1328    "  {",1329    "    let z = 2;",1330    "  }",1331    "  print(z);",1332    "}",1333    "print(y);",1334  ];1335  TestRun(test)1336    .addError(1, "'x' is defined but never used.")1337    .addError(5, "'z' is defined but never used.")1338    .addError(3, "'y' is defined but never used.")1339    .addError(7, "'z' is not defined.")1340    .addError(9, "'y' is not defined.")1341    .test(code, {moz: true, unused: true, undef: true, predef: ["print"]});1342  test.done();1343};1344exports["test: let statement out of scope as esnext"] = function (test) {1345  var code = [1346    "let x = 1;",1347    "{",1348    "  let y = 3 ;",1349    "  {",1350    "    let z = 2;",1351    "  }",1352    "  print(z);",1353    "}",1354    "print(y);",1355  ];1356  TestRun(test)1357    .addError(1, "'x' is defined but never used.")1358    .addError(5, "'z' is defined but never used.")1359    .addError(3, "'y' is defined but never used.")1360    .addError(7, "'z' is not defined.")1361    .addError(9, "'y' is not defined.")1362    .test(code, {esnext: true, unused: true, undef: true, predef: ["print"]});1363  test.done();1364};1365exports["test: let statement out of scope as es5"] = function (test) {1366  var code = [1367    "let x = 1;",1368    "{",1369    "  let y = 3 ;",1370    "  {",1371    "    let z = 2;",1372    "  }",1373    "  print(z);",1374    "}",1375    "print(y);",1376  ];1377  TestRun(test)1378    .addError(1, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1379    .addError(3, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1380    .addError(5, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1381    .addError(1, "'x' is defined but never used.")1382    .addError(5, "'z' is defined but never used.")1383    .addError(3, "'y' is defined but never used.")1384    .addError(7, "'z' is not defined.")1385    .addError(9, "'y' is not defined.")1386    .test(code, {unused: true, undef: true, predef: ["print"]}); // es51387  test.done();1388};1389exports["test: let statement out of scope as legacy JS"] = function (test) {1390  var code = [1391    "let x = 1;",1392    "{",1393    "  let y = 3 ;",1394    "  {",1395    "    let z = 2;",1396    "  }",1397    "  print(z);",1398    "}",1399    "print(y);",1400  ];1401  TestRun(test)1402    .addError(1, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1403    .addError(3, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1404    .addError(5, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1405    .addError(1, "'x' is defined but never used.")1406    .addError(5, "'z' is defined but never used.")1407    .addError(3, "'y' is defined but never used.")1408    .addError(7, "'z' is not defined.")1409    .addError(9, "'y' is not defined.")1410    .test(code, {es3: true, unused: true, undef: true, predef: ["print"]});1411  test.done();1412};1413exports["test: let statement in functions as moz"] = function (test) {1414  var code = [1415    "let x = 1;",1416    "function foo() {",1417    "  let y = 3 ;",1418    "  function bar() {",1419    "    let z = 2;",1420    "    print(x);",1421    "    print(z);",1422    "  }",1423    "  print(y);",1424    "  bar();",1425    "}",1426    "foo();"1427  ];1428  TestRun(test)1429    .test(code, {moz: true, unused: true, undef: true, predef: ["print"]});1430  test.done();1431};1432exports["test: let statement in functions as esnext"] = function (test) {1433  var code = [1434    "let x = 1;",1435    "function foo() {",1436    "  let y = 3 ;",1437    "  function bar() {",1438    "    let z = 2;",1439    "    print(x);",1440    "    print(z);",1441    "  }",1442    "  print(y);",1443    "  bar();",1444    "}",1445    "foo();"1446  ];1447  TestRun(test)1448    .test(code, {esnext: true, unused: true, undef: true, predef: ["print"]});1449  test.done();1450};1451exports["test: let statement in functions as es5"] = function (test) {1452  var code = [1453    "let x = 1;",1454    "function foo() {",1455    "  let y = 3 ;",1456    "  function bar() {",1457    "    let z = 2;",1458    "    print(x);",1459    "    print(z);",1460    "  }",1461    "  print(y);",1462    "  bar();",1463    "}",1464    "foo();"1465  ];1466  TestRun(test)1467    .addError(1, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1468    .addError(3, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1469    .addError(5, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1470    .test(code, {unused: true, undef: true, predef: ["print"]}); // es51471  test.done();1472};1473exports["test: let statement in functions as legacy JS"] = function (test) {1474  var code = [1475    "let x = 1;",1476    "function foo() {",1477    "  let y = 3 ;",1478    "  function bar() {",1479    "    let z = 2;",1480    "    print(x);",1481    "    print(z);",1482    "  }",1483    "  print(y);",1484    "  bar();",1485    "}",1486    "foo();"1487  ];1488  TestRun(test)1489    .addError(1, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1490    .addError(3, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1491    .addError(5, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1492    .test(code, {es3: true, unused: true, undef: true, predef: ["print"]});1493  test.done();1494};1495exports["test: let statement not in scope as moz"] = function (test) {1496  var code = [1497    "let x = 1;",1498    "function foo() {",1499    "  let y = 3 ;",1500    "  let bar = function () {",1501    "    print(x);",1502    "    let z = 2;",1503    "  };",1504    "  print(z);",1505    "}",1506    "print(y);",1507    "bar();",1508    "foo();",1509  ];1510  TestRun(test)1511    .addError(6, "'z' is defined but never used.")1512    .addError(3, "'y' is defined but never used.")1513    .addError(4, "'bar' is defined but never used.")1514    .addError(8, "'z' is not defined.")1515    .addError(10, "'y' is not defined.")1516    .addError(11, "'bar' is not defined.")1517    .test(code, {moz: true, unused: true, undef: true, predef: ["print"]});1518  test.done();1519};1520exports["test: let statement not in scope as esnext"] = function (test) {1521  var code = [1522    "let x = 1;",1523    "function foo() {",1524    "  let y = 3 ;",1525    "  let bar = function () {",1526    "    print(x);",1527    "    let z = 2;",1528    "  };",1529    "  print(z);",1530    "}",1531    "print(y);",1532    "bar();",1533    "foo();",1534  ];1535  TestRun(test)1536    .addError(6, "'z' is defined but never used.")1537    .addError(3, "'y' is defined but never used.")1538    .addError(4, "'bar' is defined but never used.")1539    .addError(8, "'z' is not defined.")1540    .addError(10, "'y' is not defined.")1541    .addError(11, "'bar' is not defined.")1542    .test(code, {esnext: true, unused: true, undef: true, predef: ["print"]});1543  test.done();1544};1545exports["test: let statement not in scope as es5"] = function (test) {1546  var code = [1547    "let x = 1;",1548    "function foo() {",1549    "  let y = 3 ;",1550    "  let bar = function () {",1551    "    print(x);",1552    "    let z = 2;",1553    "  };",1554    "  print(z);",1555    "}",1556    "print(y);",1557    "bar();",1558    "foo();",1559  ];1560  TestRun(test)1561    .addError(1, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1562    .addError(3, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1563    .addError(4, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1564    .addError(6, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1565    .addError(6, "'z' is defined but never used.")1566    .addError(3, "'y' is defined but never used.")1567    .addError(4, "'bar' is defined but never used.")1568    .addError(8, "'z' is not defined.")1569    .addError(10, "'y' is not defined.")1570    .addError(11, "'bar' is not defined.")1571    .test(code, {unused: true, undef: true, predef: ["print"]}); // es51572  test.done();1573};1574exports["test: let statement not in scope as legacy JS"] = function (test) {1575  var code = [1576    "let x = 1;",1577    "function foo() {",1578    "  let y = 3 ;",1579    "  let bar = function () {",1580    "    print(x);",1581    "    let z = 2;",1582    "  };",1583    "  print(z);",1584    "}",1585    "print(y);",1586    "bar();",1587    "foo();",1588  ];1589  TestRun(test)1590    .addError(1, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1591    .addError(3, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1592    .addError(4, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1593    .addError(6, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1594    .addError(6, "'z' is defined but never used.")1595    .addError(3, "'y' is defined but never used.")1596    .addError(4, "'bar' is defined but never used.")1597    .addError(8, "'z' is not defined.")1598    .addError(10, "'y' is not defined.")1599    .addError(11, "'bar' is not defined.")1600    .test(code, {es3: true, unused: true, undef: true, predef: ["print"]});1601  test.done();1602};1603exports["test: let statement in for loop as moz"] = function (test) {1604  var code = [1605    "var obj={foo: 'bar', bar: 'foo'};",1606    "for ( let [n, v] in Iterator(obj) ) {",1607    "  print('Name: ' + n + ', Value: ' + v);",1608    "}",1609    "for (let i in [1, 2, 3, 4]) {",1610    "  print(i);",1611    "}",1612    "for (let i in [1, 2, 3, 4]) {",1613    "  print(i);",1614    "}",1615    "for (let i = 0; i<15; ++i) {",1616    "  print(i);",1617    "}",1618    "for (let i=i ; i < 10 ; i++ ) {",1619    "print(i);",1620    "}"1621  ];1622  TestRun(test)1623    .test(code, {moz: true, unused: true, undef: true, predef: ["print", "Iterator"]});1624  test.done();1625};1626exports["test: let statement in for loop as esnext"] = function (test) {1627  var code = [1628    "var obj={foo: 'bar', bar: 'foo'};",1629    "for ( let [n, v] in Iterator(obj) ) {",1630    "  print('Name: ' + n + ', Value: ' + v);",1631    "}",1632    "for (let i in [1, 2, 3, 4]) {",1633    "  print(i);",1634    "}",1635    "for (let i in [1, 2, 3, 4]) {",1636    "  print(i);",1637    "}",1638    "for (let i = 0; i<15; ++i) {",1639    "  print(i);",1640    "}",1641    "for (let i=i ; i < 10 ; i++ ) {",1642    "print(i);",1643    "}"1644  ];1645  TestRun(test)1646    .test(code, {esnext: true, unused: true, undef: true, predef: ["print", "Iterator"]});1647  test.done();1648};1649exports["test: let statement in for loop as es5"] = function (test) {1650  var code = [1651    "var obj={foo: 'bar', bar: 'foo'};",1652    "for ( let [n, v] in Iterator(obj) ) {",1653    "  print('Name: ' + n + ', Value: ' + v);",1654    "}",1655    "for (let i in [1, 2, 3, 4]) {",1656    "  print(i);",1657    "}",1658    "for (let i in [1, 2, 3, 4]) {",1659    "  print(i);",1660    "}",1661    "for (let i = 0; i<15; ++i) {",1662    "  print(i);",1663    "}",1664    "for (let i=i ; i < 10 ; i++ ) {",1665    "print(i);",1666    "}"1667  ];1668  TestRun(test)1669    .addError(2, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1670    .addError(2, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1671    .addError(5, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1672    .addError(8, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1673    .addError(11, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1674    .addError(14, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1675    .test(code, {unused: true, undef: true, predef: ["print", "Iterator"]}); // es51676  test.done();1677};1678exports["test: let statement in for loop as legacy JS"] = function (test) {1679  var code = [1680    "var obj={foo: 'bar', bar: 'foo'};",1681    "for ( let [n, v] in Iterator(obj) ) {",1682    "  print('Name: ' + n + ', Value: ' + v);",1683    "}",1684    "for (let i in [1, 2, 3, 4]) {",1685    "  print(i);",1686    "}",1687    "for (let i in [1, 2, 3, 4]) {",1688    "  print(i);",1689    "}",1690    "for (let i = 0; i<15; ++i) {",1691    "  print(i);",1692    "}",1693    "for (let i=i ; i < 10 ; i++ ) {",1694    "print(i);",1695    "}"1696  ];1697  TestRun(test)1698    .addError(2, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1699    .addError(2, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1700    .addError(5, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1701    .addError(8, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1702    .addError(11, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1703    .addError(14, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1704    .test(code, {es3: true, unused: true, undef: true, predef: ["print", "Iterator"]});1705  test.done();1706};1707exports["test: let statement in destructured for loop as moz"] = function (test) {1708  // example taken from https://developer.mozilla.org/en-US/docs/JavaScript/New_in_JavaScript/1.71709  var code = [1710    "var people = [",1711    "{",1712    "  name: 'Mike Smith',",1713    "  family: {",1714    "  mother: 'Jane Smith',",1715    "  father: 'Harry Smith',",1716    "  sister: 'Samantha Smith'",1717    "  },",1718    "  age: 35",1719    "},",1720    "{",1721    "  name: 'Tom Jones',",1722    "  family: {",1723    "  mother: 'Norah Jones',",1724    "  father: 'Richard Jones',",1725    "  brother: 'Howard Jones'",1726    "  },",1727    "  age: 25",1728    "}",1729    "];",1730    "for (let {name: n, family: { father: f } } in people) {",1731    "print('Name: ' + n + ', Father: ' + f);",1732    "}"1733  ];1734  TestRun(test)1735    .test(code, {moz: true, unused: true,1736           undef: true, predef: ["print"]});1737  test.done();1738};1739exports["test: let statement in destructured for loop as esnext"] = function (test) {1740  // example taken from https://developer.mozilla.org/en-US/docs/JavaScript/New_in_JavaScript/1.71741  var code = [1742    "var people = [",1743    "{",1744    "  name: 'Mike Smith',",1745    "  family: {",1746    "  mother: 'Jane Smith',",1747    "  father: 'Harry Smith',",1748    "  sister: 'Samantha Smith'",1749    "  },",1750    "  age: 35",1751    "},",1752    "{",1753    "  name: 'Tom Jones',",1754    "  family: {",1755    "  mother: 'Norah Jones',",1756    "  father: 'Richard Jones',",1757    "  brother: 'Howard Jones'",1758    "  },",1759    "  age: 25",1760    "}",1761    "];",1762    "for (let {name: n, family: { father: f } } in people) {",1763    "print('Name: ' + n + ', Father: ' + f);",1764    "}"1765  ];1766  TestRun(test)1767    .test(code, {esnext: true, unused: true,1768           undef: true, predef: ["print"]});1769  test.done();1770};1771exports["test: let statement in destructured for loop as es5"] = function (test) {1772  // example taken from https://developer.mozilla.org/en-US/docs/JavaScript/New_in_JavaScript/1.71773  var code = [1774    "var people = [",1775    "{",1776    "  name: 'Mike Smith',",1777    "  family: {",1778    "  mother: 'Jane Smith',",1779    "  father: 'Harry Smith',",1780    "  sister: 'Samantha Smith'",1781    "  },",1782    "  age: 35",1783    "},",1784    "{",1785    "  name: 'Tom Jones',",1786    "  family: {",1787    "  mother: 'Norah Jones',",1788    "  father: 'Richard Jones',",1789    "  brother: 'Howard Jones'",1790    "  },",1791    "  age: 25",1792    "}",1793    "];",1794    "for (let {name: n, family: { father: f } } in people) {",1795    "print('Name: ' + n + ', Father: ' + f);",1796    "}"1797  ];1798  TestRun(test)1799    .addError(21, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1800    .addError(21, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1801    .test(code, {unused: true, undef: true, predef: ["print"]}); // es51802  test.done();1803};1804exports["test: let statement in destructured for loop as legacy JS"] = function (test) {1805  // example taken from https://developer.mozilla.org/en-US/docs/JavaScript/New_in_JavaScript/1.71806  var code = [1807    "var people = [",1808    "{",1809    "  name: 'Mike Smith',",1810    "  family: {",1811    "  mother: 'Jane Smith',",1812    "  father: 'Harry Smith',",1813    "  sister: 'Samantha Smith'",1814    "  },",1815    "  age: 35",1816    "},",1817    "{",1818    "  name: 'Tom Jones',",1819    "  family: {",1820    "  mother: 'Norah Jones',",1821    "  father: 'Richard Jones',",1822    "  brother: 'Howard Jones'",1823    "  },",1824    "  age: 25",1825    "}",1826    "];",1827    "for (let {name: n, family: { father: f } } in people) {",1828    "print('Name: ' + n + ', Father: ' + f);",1829    "}"1830  ];1831  TestRun(test)1832    .addError(21, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1833    .addError(21, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1834    .test(code, {es3: true, unused: true, undef: true, predef: ["print"]});1835  test.done();1836};1837exports["test: let statement (as seen in jetpack)"] = function (test) {1838  // Example taken from jetpack/addons sdk library from Mozilla project1839  var code = [1840    "const { Cc, Ci } = require('chrome');",1841    "// add a text/unicode flavor (html converted to plain text)",1842    "let (str = Cc['@mozilla.org/supports-string;1'].",1843    "            createInstance(Ci.nsISupportsString),",1844    "    converter = Cc['@mozilla.org/feed-textconstruct;1'].",1845    "                createInstance(Ci.nsIFeedTextConstruct))",1846    "{",1847    "converter.type = 'html';",1848    "converter.text = options.data;",1849    "str.data = converter.plainText();",1850    "xferable.addDataFlavor('text/unicode');",1851    "xferable.setTransferData('text/unicode', str, str.data.length * 2);",1852    "}"1853  ];1854  TestRun(test)1855    .test(code, {moz: true, unused: true, undef: true,1856           predef: ["require", "xferable", "options"]});1857  test.done();1858};1859exports["test: let statement (as seen in jetpack) as esnext"] = function (test) {1860  // Example taken from jetpack/addons sdk library from Mozilla project1861  var code = [1862    "const { Cc, Ci } = require('chrome');",1863    "// add a text/unicode flavor (html converted to plain text)",1864    "let (str = Cc['@mozilla.org/supports-string;1'].",1865    "            createInstance(Ci.nsISupportsString),",1866    "    converter = Cc['@mozilla.org/feed-textconstruct;1'].",1867    "                createInstance(Ci.nsIFeedTextConstruct))",1868    "{",1869    "converter.type = 'html';",1870    "converter.text = options.data;",1871    "str.data = converter.plainText();",1872    "xferable.addDataFlavor('text/unicode');",1873    "xferable.setTransferData('text/unicode', str, str.data.length * 2);",1874    "}"1875  ];1876  TestRun(test)1877    .addError(3, "'let block' is only available in Mozilla JavaScript extensions (use moz option).")1878    .test(code, {esnext: true, unused: true, undef: true,1879           predef: ["require", "xferable", "options"]});1880  test.done();1881};1882exports["test: let statement (as seen in jetpack) as es5"] = function (test) {1883  // Example taken from jetpack/addons sdk library from Mozilla project1884  var code = [1885    "const { Cc, Ci } = require('chrome');",1886    "// add a text/unicode flavor (html converted to plain text)",1887    "let (str = Cc['@mozilla.org/supports-string;1'].",1888    "            createInstance(Ci.nsISupportsString),",1889    "    converter = Cc['@mozilla.org/feed-textconstruct;1'].",1890    "                createInstance(Ci.nsIFeedTextConstruct))",1891    "{",1892    "converter.type = 'html';",1893    "converter.text = options.data;",1894    "str.data = converter.plainText();",1895    "xferable.addDataFlavor('text/unicode');",1896    "xferable.setTransferData('text/unicode', str, str.data.length * 2);",1897    "}"1898  ];1899  TestRun(test)1900    .addError(1, "'const' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1901    .addError(1, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1902    .addError(3, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1903    .addError(3, "'let block' is only available in Mozilla JavaScript extensions (use moz option).")1904    .test(code, {unused: true, undef: true,1905           predef: ["require", "xferable", "options"]}); // es51906  test.done();1907};1908exports["test: let statement (as seen in jetpack) as legacy JS"] = function (test) {1909  // Example taken from jetpack/addons sdk library from Mozilla project1910  var code = [1911    "const { Cc, Ci } = require('chrome');",1912    "// add a text/unicode flavor (html converted to plain text)",1913    "let (str = Cc['@mozilla.org/supports-string;1'].",1914    "            createInstance(Ci.nsISupportsString),",1915    "    converter = Cc['@mozilla.org/feed-textconstruct;1'].",1916    "                createInstance(Ci.nsIFeedTextConstruct))",1917    "{",1918    "converter.type = 'html';",1919    "converter.text = options.data;",1920    "str.data = converter.plainText();",1921    "xferable.addDataFlavor('text/unicode');",1922    "xferable.setTransferData('text/unicode', str, str.data.length * 2);",1923    "}"1924  ];1925  TestRun(test)1926    .addError(1, "'const' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1927    .addError(1, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1928    .addError(3, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1929    .addError(3, "'let block' is only available in Mozilla JavaScript extensions (use moz option).")1930    .test(code, {es3: true, unused: true, undef: true,1931           predef: ["require", "xferable", "options"]});1932  test.done();1933};1934exports["test: let block and let expression"] = function (test) {1935  // Example taken from jetpack/addons sdk library from Mozilla project1936  var code = [1937    "let (x=1, y=2, z=3)",1938    "{",1939    "  let(t=4) print(x, y, z, t);",1940    "  print(let(u=4) u,x);",1941    "}"1942  ];1943  TestRun(test)1944    .test(code, {moz: true, unused: true, undef: true, predef: ["print"]});1945  test.done();1946};1947exports["test: let block and let expression as esnext"] = function (test) {1948  // Example taken from jetpack/addons sdk library from Mozilla project1949  var code = [1950    "let (x=1, y=2, z=3)",1951    "{",1952    "  let(t=4) print(x, y, z, t);",1953    "  print(let(u=4) u,x);",1954    "}"1955  ];1956  TestRun(test)1957    .addError(1, "'let block' is only available in Mozilla JavaScript extensions (use moz option).")1958    .addError(3, "'let block' is only available in Mozilla JavaScript extensions (use moz option).")1959    .addError(4, "'let expressions' is only available in Mozilla JavaScript extensions " +1960      "(use moz option).")1961    .test(code, {esnext: true, unused: true, undef: true, predef: ["print"]});1962  test.done();1963};1964exports["test: let block and let expression as es5"] = function (test) {1965  // Example taken from jetpack/addons sdk library from Mozilla project1966  var code = [1967    "let (x=1, y=2, z=3)",1968    "{",1969    "  let(t=4) print(x, y, z, t);",1970    "  print(let(u=4) u,x);",1971    "}"1972  ];1973  TestRun(test)1974    .addError(1, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1975    .addError(1, "'let block' is only available in Mozilla JavaScript extensions (use moz option).")1976    .addError(3, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1977    .addError(3, "'let block' is only available in Mozilla JavaScript extensions (use moz option).")1978    .addError(4, "'let expressions' is only available in Mozilla JavaScript extensions " +1979      "(use moz option).")1980    .addError(4, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1981    .test(code, {unused: true, undef: true, predef: ["print"]}); // es51982  test.done();1983};1984exports["test: let block and let expression as legacy JS"] = function (test) {1985  // Example taken from jetpack/addons sdk library from Mozilla project1986  var code = [1987    "let (x=1, y=2, z=3)",1988    "{",1989    "  let(t=4) print(x, y, z, t);",1990    "  print(let(u=4) u,x);",1991    "}"1992  ];1993  TestRun(test)1994    .addError(1, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1995    .addError(1, "'let block' is only available in Mozilla JavaScript extensions (use moz option).")1996    .addError(3, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")1997    .addError(3, "'let block' is only available in Mozilla JavaScript extensions (use moz option).")1998    .addError(4, "'let expressions' is only available in Mozilla JavaScript extensions " +1999      "(use moz option).")2000    .addError(4, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")2001    .test(code, {es3: true, unused: true, undef: true, predef: ["print"]});2002  test.done();2003};2004exports["make sure let variables are not treated as globals"] = function (test) {2005  // This is a regression test for GH-13622006  var code = [2007    "function sup() {",2008      "if (true) {",2009        "let closed = 1;",2010        "closed = 2;",2011      "}",2012      "if (true) {",2013        "if (true) {",2014          "let closed = 1;",2015          "closed = 2;",2016        "}",2017      "}",2018    "}"2019  ];2020  TestRun(test).test(code, { esnext: true, browser: true });2021  test.done();2022};2023exports["make sure var variables can shadow let variables"] = function (test) {2024  // This is a regression test for GH-13942025  var code = [2026    "let a = 1;",2027    "let b = 2;",2028    "var c = 3;",2029    "function sup(a) {",2030      "var b = 4;",2031      "let c = 5;",2032      "let d = 6;",2033      "if (false) {",2034        "var d = 7;",2035      "}",2036      "return b + c + a + d;",2037    "}",2038    "sup();"2039  ];2040  TestRun(test)2041    .addError(1, "'a' is defined but never used.")2042    .addError(2, "'b' is defined but never used.")2043    .addError(3, "'c' is defined but never used.")2044    .addError(7, "'d' is defined but never used.")2045    .test(code, { esnext: true, unused: true, undef: true, funcscope: true });2046  test.done();2047};2048exports["test destructuring function as moz"] = function (test) {2049  // Example from https://developer.mozilla.org/en-US/docs/JavaScript/New_in_JavaScript/1.72050  var code = [2051    "function userId({id}) {",2052    "  return id;",2053    "}",2054    "function whois({displayName: displayName, fullName: {firstName: name}}) {",2055    "  print(displayName + ' is ' + name);",2056    "}",2057    "var user = {id: 42, displayName: 'jdoe', fullName: {firstName: 'John', lastName: 'Doe'}};",2058    "print('userId: ' + userId(user));",2059    "whois(user);"2060  ];2061  TestRun(test)2062    .test(code, {moz: true, unused: true, undef: true, predef: ["print"]});2063  test.done();2064};2065exports["test destructuring function as esnext"] = function (test) {2066  // Example from https://developer.mozilla.org/en-US/docs/JavaScript/New_in_JavaScript/1.72067  var code = [2068    "function userId({id}) {",2069    "  return id;",2070    "}",2071    "function whois({displayName: displayName, fullName: {firstName: name}}) {",2072    "  print(displayName + ' is ' + name);",2073    "}",2074    "var user = {id: 42, displayName: 'jdoe', fullName: {firstName: 'John', lastName: 'Doe'}};",2075    "print('userId: ' + userId(user));",2076    "whois(user);"2077  ];2078  TestRun(test)2079    .test(code, {esnext: true, unused: true, undef: true, predef: ["print"]});2080  test.done();2081};2082exports["test destructuring function as es5"] = function (test) {2083  // Example from https://developer.mozilla.org/en-US/docs/JavaScript/New_in_JavaScript/1.72084  var code = [2085    "function userId({id}) {",2086    "  return id;",2087    "}",2088    "function whois({displayName: displayName, fullName: {firstName: name}}) {",2089    "  print(displayName + ' is ' + name);",2090    "}",2091    "var user = {id: 42, displayName: 'jdoe', fullName: {firstName: 'John', lastName: 'Doe'}};",2092    "print('userId: ' + userId(user));",2093    "whois(user);"2094  ];2095  TestRun(test)2096    .addError(1, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")2097    .addError(4, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")2098    .addError(4, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")2099    .test(code, {unused: true, undef: true, predef: ["print"]}); // es52100  test.done();2101};2102exports["test destructuring function as legacy JS"] = function (test) {2103  // Example from https://developer.mozilla.org/en-US/docs/JavaScript/New_in_JavaScript/1.72104  var code = [2105    "function userId({id}) {",2106    "  return id;",2107    "}",2108    "function whois({displayName: displayName, fullName: {firstName: name}}) {",2109    "  print(displayName + ' is ' + name);",2110    "}",2111    "var user = {id: 42, displayName: 'jdoe', fullName: {firstName: 'John', lastName: 'Doe'}};",2112    "print('userId: ' + userId(user));",2113    "whois(user);"2114  ];2115  TestRun(test)2116    .addError(1, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")2117    .addError(4, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")2118    .addError(4, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")2119    .test(code, {es3: true, unused: true, undef: true, predef: ["print"]});2120  test.done();2121};2122exports["test: invalid for each"] = function (test) {2123  // example taken from https://developer.mozilla.org/en-US/docs/JavaScript/New_in_JavaScript/1.72124  var code = [2125    "for each (let i = 0; i<15; ++i) {",2126    "  print(i);",2127    "}"2128  ];2129  TestRun(test)2130    .addError(1, "Invalid for each loop.")2131    .test(code, {moz: true, unused: true, undef: true, predef: ["print"]});2132  test.done();2133};2134exports["test: invalid for each as esnext"] = function (test) {2135  // example taken from https://developer.mozilla.org/en-US/docs/JavaScript/New_in_JavaScript/1.72136  var code = [2137    "for each (let i = 0; i<15; ++i) {",2138    "  print(i);",2139    "}"2140  ];2141  TestRun(test)2142    .addError(1, "Invalid for each loop.")2143    .addError(1, "'for each' is only available in Mozilla JavaScript extensions (use moz option).")2144    .test(code, {esnext: true, unused: true, undef: true, predef: ["print"]});2145  test.done();2146};2147exports["test: invalid for each as ES5"] = function (test) {2148  // example taken from https://developer.mozilla.org/en-US/docs/JavaScript/New_in_JavaScript/1.72149  var code = [2150    "for each (let i = 0; i<15; ++i) {",2151    "  print(i);",2152    "}"2153  ];2154  TestRun(test)2155    .addError(1, "Invalid for each loop.")2156    .addError(1, "'for each' is only available in Mozilla JavaScript extensions (use moz option).")2157    .addError(1, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")2158    .test(code, {unused: true, undef: true, predef: ["print"]}); // es52159  test.done();2160};2161exports["test: invalid for each as legacy JS"] = function (test) {2162  // example taken from https://developer.mozilla.org/en-US/docs/JavaScript/New_in_JavaScript/1.72163  var code = [2164    "for each (let i = 0; i<15; ++i) {",2165    "  print(i);",2166    "}"2167  ];2168  TestRun(test)2169    .addError(1, "Invalid for each loop.")2170    .addError(1, "'for each' is only available in Mozilla JavaScript extensions (use moz option).")2171    .addError(1, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")2172    .test(code, {es3: true, unused: true, undef: true, predef: ["print"]});2173  test.done();2174};2175exports["test: esnext generator"] = function (test) {2176  // example taken from https://developer.mozilla.org/en-US/docs/JavaScript/New_in_JavaScript/1.72177  var code = [2178    "function* fib() {",2179    "  var i = 0, j = 1;",2180    "  while (true) {",2181    "    yield i;",2182    "    [i, j] = [j, i + j];",2183    "  }",2184    "}",2185    "var g = fib();",2186    "for (var i = 0; i < 10; i++)",2187    "  print(g.next());"2188  ];2189  TestRun(test)2190    .test(code, {esnext: true, unused: true, undef: true, predef: ["print"]});2191  test.done();2192};2193exports["test: esnext generator as moz extension"] = function (test) {2194  // example taken from https://developer.mozilla.org/en-US/docs/JavaScript/New_in_JavaScript/1.72195  var code = [2196    "function* fib() {",2197    "  var i = 0, j = 1;",2198    "  while (true) {",2199    "    yield i;",2200    "    [i, j] = [j, i + j];",2201    "  }",2202    "}",2203    "var g = fib();",2204    "for (var i = 0; i < 10; i++)",2205    "  print(g.next());"2206  ];2207  TestRun(test)2208    .addError(1, "'function*' is only available in ES6 (use esnext option).")2209    .test(code, {moz: true, unused: true, undef: true, predef: ["print"]});2210  test.done();2211};2212exports["test: esnext generator as es5"] = function (test) {2213  // example taken from https://developer.mozilla.org/en-US/docs/JavaScript/New_in_JavaScript/1.72214  var code = [2215    "function* fib() {",2216    "  var i = 0, j = 1;",2217    "  while (true) {",2218    "    yield i;",2219    "    [i, j] = [j, i + j];",2220    "  }",2221    "}",2222    "var g = fib();",2223    "for (var i = 0; i < 10; i++)",2224    "  print(g.next());"2225  ];2226  TestRun(test)2227    .addError(1, "'function*' is only available in ES6 (use esnext option).")2228    .addError(4, "'yield' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")2229    .addError(5, "'destructuring assignment' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")2230    .test(code, {unused: true, undef: true, predef: ["print"]}); // es52231  test.done();2232};2233exports["test: esnext generator as legacy JS"] = function (test) {2234  // example taken from https://developer.mozilla.org/en-US/docs/JavaScript/New_in_JavaScript/1.72235  var code = [2236    "function* fib() {",2237    "  var i = 0, j = 1;",2238    "  while (true) {",2239    "    yield i;",2240    "    [i, j] = [j, i + j];",2241    "  }",2242    "}",2243    "var g = fib();",2244    "for (var i = 0; i < 10; i++)",2245    "  print(g.next());"2246  ];2247  TestRun(test)2248    .addError(1, "'function*' is only available in ES6 (use esnext option).")2249    .addError(4, "'yield' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")2250    .addError(5, "'destructuring assignment' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")2251    .test(code, {es3: true, unused: true, undef: true, predef: ["print"]});2252  test.done();2253};2254exports["test: esnext generator without yield"] = function (test) {2255  // example taken from https://developer.mozilla.org/en-US/docs/JavaScript/New_in_JavaScript/1.72256  var code = [2257    "function* fib() {",2258    "  var i = 0, j = 1;",2259    "  while (true) {",2260    "    [i, j] = [j, i + j];",2261    "    return i;",2262    "  }",2263    "}",2264    "var g = fib();",2265    "for (let i = 0; i < 10; i++)",2266    "  print(g.next());"2267  ];2268  TestRun(test)2269    .addError(7, "A generator function shall contain a yield statement.")2270    .test(code, {esnext: true, unused: true, undef: true, predef: ["print"]});2271  test.done();2272};2273exports["test: esnext generator without yield and check turned off"] = function (test) {2274  var code = [2275    "function* emptyGenerator() {}",2276    "emptyGenerator();"2277  ];2278  TestRun(test)2279    .test(code, {esnext: true, noyield: true, unused: true, undef: true, predef: ["print"]});2280  test.done();2281};2282exports["test: mozilla generator"] = function (test) {2283  // example taken from https://developer.mozilla.org/en-US/docs/JavaScript/New_in_JavaScript/1.72284  var code = [2285    "function fib() {",2286    "  var i = 0, j = 1;",2287    "  while (true) {",2288    "    yield i;",2289    "    [i, j] = [j, i + j];",2290    "  }",2291    "}",2292    "var g = fib();",2293    "for (let i = 0; i < 10; i++)",2294    "  print(g.next());"2295  ];2296  TestRun(test)2297    .test(code, {moz: true, unused: true, undef: true, predef: ["print", "Iterator"]});2298  test.done();2299};2300exports["test: mozilla generator as esnext"] = function (test) {2301  // example taken from https://developer.mozilla.org/en-US/docs/JavaScript/New_in_JavaScript/1.72302  var code = [2303    "function fib() {",2304    "  var i = 0, j = 1;",2305    "  while (true) {",2306    "    yield i;",2307    "    [i, j] = [j, i + j];",2308    "  }",2309    "}",2310    "var g = fib();",2311    "for (let i = 0; i < 10; i++)",2312    "  print(g.next());"2313  ];2314  TestRun(test)2315    .addError(4,2316     "A yield statement shall be within a generator function (with syntax: `function*`)")2317    .test(code, {esnext: true, unused: true, undef: true, predef: ["print", "Iterator"]});2318  test.done();2319};2320exports["test: yield statement within try-catch"] = function (test) {2321  // see issue: https://github.com/jshint/jshint/issues/15052322  var code = [2323    "function* fib() {",2324    "  try {",2325    "    yield 1;",2326    "  } catch (err) {",2327    "    yield err;",2328    "  }",2329    "}",2330    "var g = fib();",2331    "for (let i = 0; i < 10; i++)",2332    "  print(g.next());"2333  ];2334  TestRun(test)2335    .test(code, {esnext: true, unused: true, undef: true, predef: ["print", "Iterator"]});2336  test.done();2337};2338exports["test: mozilla generator as es5"] = function (test) {2339  // example taken from https://developer.mozilla.org/en-US/docs/JavaScript/New_in_JavaScript/1.72340  var code = [2341    "function fib() {",2342    "  var i = 0, j = 1;",2343    "  while (true) {",2344    "    yield i;",2345    "    [i, j] = [j, i + j];",2346    "  }",2347    "}",2348    "var g = fib();",2349    "for (let i = 0; i < 10; i++)",2350    "  print(g.next());"2351  ];2352  TestRun(test)2353    .addError(4, "'yield' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")2354    .addError(5, "'destructuring assignment' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")2355    .addError(9, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")2356    .test(code, {unused: true, undef: true, predef: ["print", "Iterator"]}); // es52357  test.done();2358};2359exports["test: mozilla generator as legacy JS"] = function (test) {2360  // example taken from https://developer.mozilla.org/en-US/docs/JavaScript/New_in_JavaScript/1.72361  var code = [2362    "function fib() {",2363    "  var i = 0, j = 1;",2364    "  while (true) {",2365    "    yield i;",2366    "    [i, j] = [j, i + j];",2367    "  }",2368    "}",2369    "var g = fib();",2370    "for (let i = 0; i < 10; i++)",2371    "  print(g.next());"2372  ];2373  TestRun(test)2374    .addError(4, "'yield' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")2375    .addError(5, "'destructuring assignment' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")2376    .addError(9, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")2377    .test(code, {es3: true, unused: true, undef: true, predef: ["print", "Iterator"]});2378  test.done();2379};2380exports["test: array comprehension"] = function (test) {2381  // example taken from https://developer.mozilla.org/en-US/docs/JavaScript/New_in_JavaScript/1.72382  var code = [2383    "function *range(begin, end) {",2384    "  for (let i = begin; i < end; ++i) {",2385    "    yield i;",2386    "  }",2387    "}",2388    "var ten_squares = [for (i of range(0, 10)) i * i];",2389    "var evens = [for (i of range(0, 21)) if (i % 2 === 0) i];",2390    "print('squares:', ten_squares);",2391    "print('evens:', evens);"2392  ];2393  TestRun(test)2394    .test(code, {esnext: true, unused: true, undef: true, predef: ["print"]});2395  test.done();2396};2397exports["test: moz-style array comprehension"] = function (test) {2398  // example taken from https://developer.mozilla.org/en-US/docs/JavaScript/New_in_JavaScript/1.72399  var code = [2400    "function range(begin, end) {",2401    "  for (let i = begin; i < end; ++i) {",2402    "    yield i;",2403    "  }",2404    "}",2405    "var ten_squares = [i * i for each (i in range(0, 10))];",2406    "var evens = [i for each (i in range(0, 21)) if (i % 2 === 0)];",2407    "print('squares:', ten_squares);",2408    "print('evens:', evens);"2409  ];2410  TestRun(test)2411    .test(code, {moz: true, unused: true, undef: true, predef: ["print"]});2412  test.done();2413};2414exports["test: array comprehension with for..of"] = function (test) {2415  // example adapted from https://developer.mozilla.org/en-US/docs/JavaScript/New_in_JavaScript/1.72416  var code = [2417    "function *range(begin, end) {",2418    "  for (let i = begin; i < end; ++i) {",2419    "    yield i;",2420    "  }",2421    "}",2422    "var ten_squares = [for (i of range(0, 10)) i * i];",2423    "var evens = [for (i of range(0, 21)) if (i % 2 === 0) i];",2424    "print('squares:', ten_squares);",2425    "print('evens:', evens);"2426  ];2427  TestRun(test)2428    .test(code, {esnext: true, unused: true, undef: true, predef: ["print"]});2429  test.done();2430};2431exports["test: moz-style array comprehension with for..of"] = function (test) {2432  // example adapted from https://developer.mozilla.org/en-US/docs/JavaScript/New_in_JavaScript/1.72433  var code = [2434    "function range(begin, end) {",2435    "  for (let i = begin; i < end; ++i) {",2436    "    yield i;",2437    "  }",2438    "}",2439    "var ten_squares = [i * i for (i of range(0, 10))];",2440    "var evens = [i for (i of range(0, 21)) if (i % 2 === 0)];",2441    "print('squares:', ten_squares);",2442    "print('evens:', evens);"2443  ];2444  TestRun(test)2445    .test(code, {moz: true, unused: true, undef: true, predef: ["print"]});2446  test.done();2447};2448exports["test: array comprehension with unused variables"] = function (test) {2449  var code = [2450    "var ret = [for (i of unknown) i];",2451    "print('ret:', ret);",2452  ];2453  TestRun(test)2454    .addError(1, "'unknown' is not defined.")2455    .test(code, {esnext: true, unused: true, undef: true, predef: ["print"]});2456  test.done();2457};2458exports["test: moz-style array comprehension with unused variables"] = function (test) {2459  var code = [2460    "var ret = [i for (i of unknown)];",2461    "print('ret:', ret);",2462  ];2463  TestRun(test)2464    .addError(1, "'unknown' is not defined.")2465    .test(code, {moz: true, unused: true, undef: true, predef: ["print"]});2466  test.done();2467};2468exports["test: moz-style array comprehension as esnext"] = function (test) {2469  // example taken from https://developer.mozilla.org/en-US/docs/JavaScript/New_in_JavaScript/1.72470  var code = [2471    "function range(begin, end) {",2472    "  for (let i = begin; i < end; ++i) {",2473    "    yield i;",2474    "  }",2475    "}",2476    "var ten_squares = [i * i for each (i in range(0, 10))];",2477    "var evens = [i for each (i in range(0, 21)) if (i % 2 === 0)];",2478    "print('squares:', ten_squares);",2479    "print('evens:', evens);"2480  ];2481  TestRun(test)2482    .addError(3, "A yield statement shall be within a generator function (with syntax: " +2483      "`function*`)")2484    .addError(6, "Expected 'for' and instead saw 'i'.")2485    .addError(6, "'for each' is only available in Mozilla JavaScript extensions (use moz option).")2486    .addError(7, "Expected 'for' and instead saw 'i'.")2487    .addError(7, "'for each' is only available in Mozilla JavaScript extensions (use moz option).")2488    .test(code, {esnext: true, unused: true, undef: true, predef: ["print"]});2489  test.done();2490};2491exports["test: array comprehension as es5"] = function (test) {2492  // example taken from https://developer.mozilla.org/en-US/docs/JavaScript/New_in_JavaScript/1.72493  var code = [2494    "function *range(begin, end) {",2495    "  for (let i = begin; i < end; ++i) {",2496    "    yield i;",2497    "  }",2498    "}",2499    "var ten_squares = [for (i of range(0, 10)) i * i];",2500    "var evens = [for (i of range(0, 21)) if (i % 2 === 0) i];",2501    "print('squares:', ten_squares);",2502    "print('evens:', evens);"2503  ];2504  TestRun(test)2505    .addError(1, "'function*' is only available in ES6 (use esnext option).")2506    .addError(2, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")2507    .addError(3, "'yield' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")2508    .addError(6, "'array comprehension' is only available in ES6 " +2509      "(use esnext option).")2510    .addError(7, "'array comprehension' is only available in ES6 " +2511      "(use esnext option).")2512    .test(code, {unused: true, undef: true, predef: ["print"]}); // es52513  test.done();2514};2515exports["test: moz-style array comprehension as es5"] = function (test) {2516  // example taken from https://developer.mozilla.org/en-US/docs/JavaScript/New_in_JavaScript/1.72517  var code = [2518    "function range(begin, end) {",2519    "  for (let i = begin; i < end; ++i) {",2520    "    yield i;",2521    "  }",2522    "}",2523    "var ten_squares = [i * i for each (i in range(0, 10))];",2524    "var evens = [i for each (i in range(0, 21)) if (i % 2 === 0)];",2525    "print('squares:', ten_squares);",2526    "print('evens:', evens);"2527  ];2528  TestRun(test)2529    .addError(2, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")2530    .addError(3, "'yield' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")2531    .addError(6, "'array comprehension' is only available in ES6 " +2532      "(use esnext option).")2533    .addError(6, "Expected 'for' and instead saw 'i'.")2534    .addError(6, "'for each' is only available in Mozilla JavaScript extensions (use moz option).")2535    .addError(7, "'array comprehension' is only available in ES6 " +2536      "(use esnext option).")2537    .addError(7, "Expected 'for' and instead saw 'i'.")2538    .addError(7, "'for each' is only available in Mozilla JavaScript extensions (use moz option).")2539    .test(code, {unused: true, undef: true, predef: ["print"]}); // es52540  test.done();2541};2542exports["test: array comprehension as legacy JS"] = function (test) {2543  // example taken from https://developer.mozilla.org/en-US/docs/JavaScript/New_in_JavaScript/1.72544  var code = [2545    "function range(begin, end) {",2546    "  for (let i = begin; i < end; ++i) {",2547    "    yield i;",2548    "  }",2549    "}",2550    "var ten_squares = [for (i of range(0, 10)) i * i];",2551    "var evens = [for (i of range(0, 21)) if (i % 2 === 0) i];",2552    "print('squares:', ten_squares);",2553    "print('evens:', evens);"2554  ];2555  TestRun(test)2556    .addError(2, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")2557    .addError(3, "'yield' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")2558    .addError(6, "'array comprehension' is only available in ES6 " +2559      "(use esnext option).")2560    .addError(7, "'array comprehension' is only available in ES6 " +2561      "(use esnext option).")2562    .test(code, {es3: true, unused: true, undef: true, predef: ["print"]});2563  test.done();2564};2565exports["test: moz-style array comprehension as legacy JS"] = function (test) {2566  // example taken from https://developer.mozilla.org/en-US/docs/JavaScript/New_in_JavaScript/1.72567  var code = [2568    "function range(begin, end) {",2569    "  for (let i = begin; i < end; ++i) {",2570    "    yield i;",2571    "  }",2572    "}",2573    "var ten_squares = [i * i for each (i in range(0, 10))];",2574    "var evens = [i for each (i in range(0, 21)) if (i % 2 === 0)];",2575    "print('squares:', ten_squares);",2576    "print('evens:', evens);"2577  ];2578  TestRun(test)2579    .addError(2, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")2580    .addError(3, "'yield' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")2581    .addError(6, "'array comprehension' is only available in ES6 " +2582      "(use esnext option).")2583    .addError(6, "Expected 'for' and instead saw 'i'.")2584    .addError(6, "'for each' is only available in Mozilla JavaScript extensions (use moz option).")2585    .addError(7, "'array comprehension' is only available in ES6 " +2586      "(use esnext option).")2587    .addError(7, "Expected 'for' and instead saw 'i'.")2588    .addError(7, "'for each' is only available in Mozilla JavaScript extensions (use moz option).")2589    .test(code, {es3: true, unused: true, undef: true, predef: ["print"]});2590  test.done();2591};2592exports['test: array comprehension with dest array at global scope'] = function (test) {2593  var code = [2594    "[for ([i, j] of [[0,0], [1,1], [2,2]]) [i, j] ];",2595    "var destarray_comparray_1 = [for ([i, j] of [[0,0], [1,1], [2,2]]) [i, [j, j] ]];",2596    "var destarray_comparray_2 = [for ([i, j] of [[0,0], [1,1], [2,2]]) [i, {i: [i, j]} ]];",2597  ];2598  TestRun(test)2599    .test(code, {esnext: true, undef: true, predef: ["print"]});2600  test.done();2601};2602exports['test: moz-style array comprehension with dest array at global scope'] = function (test) {2603  var code = [2604    "[ [i, j] for each ([i, j] in [[0,0], [1,1], [2,2]])];",2605    "var destarray_comparray_1 = [ [i, [j, j] ] for each ([i, j] in [[0,0], [1,1], [2,2]])];",2606    "var destarray_comparray_2 = [ [i, {i: [i, j]} ] for each ([i, j] in [[0,0], [1,1], [2,2]])];",2607  ];2608  TestRun(test)2609    .test(code, {moz: true, undef: true, predef: ["print"]});2610  test.done();2611};2612exports['test: moz-style array comprehension with dest array at global scope as esnext'] = function (test) {2613  var code = [2614    "[ [i, j] for each ([i, j] in [[0,0], [1,1], [2,2]])];",2615    "var destarray_comparray_1 = [ [i, [j, j] ] for each ([i, j] in [[0,0], [1,1], [2,2]])];",2616    "var destarray_comparray_2 = [ [i, {i: [i, j]} ] for each ([i, j] in [[0,0], [1,1], [2,2]])];",2617  ];2618  TestRun(test)2619    .addError(1, "Expected 'for' and instead saw '['.")2620    .addError(1, "'for each' is only available in Mozilla JavaScript extensions (use moz option).")2621    .addError(2, "Expected 'for' and instead saw '['.")2622    .addError(2, "'for each' is only available in Mozilla JavaScript extensions (use moz option).")2623    .addError(3, "Expected 'for' and instead saw '['.")2624    .addError(3, "'for each' is only available in Mozilla JavaScript extensions (use moz option).")2625    .test(code, {esnext: true, undef: true, predef: ["print"]});2626  test.done();2627};2628exports['test: array comprehension with dest array at global scope as es5'] = function (test) {2629  var code = [2630    "[for ([i, j] of [[0,0], [1,1], [2,2]]) [i, j] ];",2631    "var destarray_comparray_1 = [for ([i, j] of [[0,0], [1,1], [2,2]]) [i, [j, j] ] ];",2632    "var destarray_comparray_2 = [for ([i, j] of [[0,0], [1,1], [2,2]]) [i, {i: [i, j]} ] ];",2633  ];2634  TestRun(test)2635    .addError(1, "'array comprehension' is only available in ES6 " +2636      "(use esnext option).")2637    .addError(2, "'array comprehension' is only available in ES6 " +2638      "(use esnext option).")2639    .addError(3, "'array comprehension' is only available in ES6 " +2640      "(use esnext option).")2641    .test(code, {undef: true, predef: ["print"]}); // es52642  test.done();2643};2644exports['test: moz-style array comprehension with dest array at global scope as es5'] = function (test) {2645  var code = [2646    "[ [i, j] for each ([i, j] in [[0,0], [1,1], [2,2]])];",2647    "var destarray_comparray_1 = [ [i, [j, j] ] for each ([i, j] in [[0,0], [1,1], [2,2]])];",2648    "var destarray_comparray_2 = [ [i, {i: [i, j]} ] for each ([i, j] in [[0,0], [1,1], [2,2]])];",2649  ];2650  TestRun(test)2651    .addError(1, "'array comprehension' is only available in ES6 " +2652      "(use esnext option).")2653    .addError(1, "Expected 'for' and instead saw '['.")2654    .addError(1, "'for each' is only available in Mozilla JavaScript extensions (use moz option).")2655    .addError(2, "'array comprehension' is only available in ES6 " +2656      "(use esnext option).")2657    .addError(2, "Expected 'for' and instead saw '['.")2658    .addError(2, "'for each' is only available in Mozilla JavaScript extensions (use moz option).")2659    .addError(3, "'array comprehension' is only available in ES6 " +2660      "(use esnext option).")2661    .addError(3, "Expected 'for' and instead saw '['.")2662    .addError(3, "'for each' is only available in Mozilla JavaScript extensions (use moz option).")2663    .test(code, {undef: true, predef: ["print"]}); // es52664  test.done();2665};2666exports['test: array comprehension with dest array at global scope as JS legacy'] = function (test) {2667  var code = [2668    "[for ([i, j] of [[0,0], [1,1], [2,2]]) [i, j] ];",2669    "var destarray_comparray_1 = [for ([i, j] of [[0,0], [1,1], [2,2]]) [i, [j, j] ] ];",2670    "var destarray_comparray_2 = [for ([i, j] of [[0,0], [1,1], [2,2]]) [i, {i: [i, j]} ] ];",2671  ];2672  TestRun(test)2673    .addError(1, "'array comprehension' is only available in ES6 " +2674      "(use esnext option).")2675    .addError(2, "'array comprehension' is only available in ES6 " +2676      "(use esnext option).")2677    .addError(3, "'array comprehension' is only available in ES6 " +2678      "(use esnext option).")2679    .test(code, {es3: true, undef: true, predef: ["print"]});2680  test.done();2681};2682exports['test: moz-style array comprehension with dest array at global scope as JS legacy'] = function (test) {2683  var code = [2684    "[ [i, j] for each ([i, j] in [[0,0], [1,1], [2,2]])];",2685    "var destarray_comparray_1 = [ [i, [j, j] ] for each ([i, j] in [[0,0], [1,1], [2,2]])];",2686    "var destarray_comparray_2 = [ [i, {i: [i, j]} ] for each ([i, j] in [[0,0], [1,1], [2,2]])];",2687  ];2688  TestRun(test)2689    .addError(1, "'array comprehension' is only available in ES6 " +2690      "(use esnext option).")2691    .addError(1, "Expected 'for' and instead saw '['.")2692    .addError(1, "'for each' is only available in Mozilla JavaScript extensions (use moz option).")2693    .addError(2, "'array comprehension' is only available in ES6 " +2694      "(use esnext option).")2695    .addError(2, "Expected 'for' and instead saw '['.")2696    .addError(2, "'for each' is only available in Mozilla JavaScript extensions (use moz option).")2697    .addError(3, "'array comprehension' is only available in ES6 " +2698      "(use esnext option).")2699    .addError(3, "Expected 'for' and instead saw '['.")2700    .addError(3, "'for each' is only available in Mozilla JavaScript extensions (use moz option).")2701    .test(code, {es3: true, undef: true, predef: ["print"]});2702  test.done();2703};2704exports["test: array comprehension imbrication with dest array"] = function (test) {2705  var code = [2706    "[for ([i, j] of [for ([a, b] of [[2,2], [3,4]]) [a, b] ]) [i, j] ];"2707  ];2708  TestRun(test)2709    .test(code, {esnext: true, undef: true, predef: ["print"]});2710  test.done();2711};2712exports["test: moz-style array comprehension imbrication with dest array"] = function (test) {2713  var code = [2714    "[ [i, j] for ([i, j] in [[a, b] for each ([a, b] in [[2,2], [3,4]])]) ];"2715  ];2716  TestRun(test)2717    .test(code, {moz: true, undef: true, predef: ["print"]});2718  test.done();2719};2720exports["test: moz-style array comprehension imbrication with dest array using for..of"] = function (test) {2721  var code = [2722    "[ [i, j] for ([i, j] of [[a, b] for ([a, b] of [[2,2], [3,4]])]) ];"2723  ];2724  TestRun(test)2725    .test(code, {moz: true, undef: true, predef: ["print"]});2726  test.done();2727};2728exports["test: moz-style array comprehension imbrication with dest array as esnext"] = function (test) {2729  var code = [2730    "[ [i, j] for each ([i, j] in [[a, b] for each ([a, b] in [[2,2], [3,4]])]) ];"2731  ];2732  TestRun(test)2733    .addError(1, "Expected 'for' and instead saw '['.")2734    .addError(1, "'for each' is only available in Mozilla JavaScript extensions (use moz option).")2735    .test(code, {esnext: true, undef: true, predef: ["print"]});2736  test.done();2737};2738exports["test: array comprehension imbrication with dest array as es5"] = function (test) {2739  var code = [2740    "[for ([i, j] of [for ([a, b] of [[2,2], [3,4]]) [a, b] ]) [i, j] ];"2741  ];2742  TestRun(test)2743    .addError(1, "'array comprehension' is only available in ES6 " +2744      "(use esnext option).")2745    .addError(1, "'array comprehension' is only available in ES6 " +2746      "(use esnext option).")2747    .test(code, {undef: true, predef: ["print"]}); // es52748  test.done();2749};2750exports["test: moz-style array comprehension imbrication with dest array as es5"] = function (test) {2751  var code = [2752    "[for ([i, j] of [for ([a, b] of [[2,2], [3,4]]) [a, b] ]) [i, j] ];"2753  ];2754  TestRun(test)2755    .addError(1, "'array comprehension' is only available in ES6 " +2756      "(use esnext option).")2757    .addError(1, "'array comprehension' is only available in ES6 " +2758      "(use esnext option).")2759    .test(code, {undef: true, predef: ["print"]}); // es52760  test.done();2761};2762exports["test: array comprehension imbrication with dest array as legacy JS"] = function (test) {2763  var code = [2764    "[ [i, j] for each ([i, j] in [[a, b] for each ([a, b] in [[2,2], [3,4]])]) ];"2765  ];2766  TestRun(test)2767    .addError(1, "'array comprehension' is only available in ES6 " +2768      "(use esnext option).")2769    .addError(1, "'array comprehension' is only available in ES6 " +2770      "(use esnext option).")2771    .addError(1, "Expected 'for' and instead saw '['.")2772    .addError(1, "Expected 'for' and instead saw '['.")2773    .addError(1, "'for each' is only available in Mozilla JavaScript extensions (use moz option).")2774    .test(code, {es3: true, undef: true, predef: ["print"]});2775  test.done();2776};2777exports["test: moz-style array comprehension imbrication with dest array as legacy JS"] = function (test) {2778  var code = [2779    "[ [i, j] for each ([i, j] in [[a, b] for each ([a, b] in [[2,2], [3,4]])]) ];"2780  ];2781  TestRun(test)2782    .addError(1, "'array comprehension' is only available in ES6 " +2783      "(use esnext option).")2784    .addError(1, "'array comprehension' is only available in ES6 " +2785      "(use esnext option).")2786    .addError(1, "Expected 'for' and instead saw '['.")2787    .addError(1, "Expected 'for' and instead saw '['.")2788    .addError(1, "'for each' is only available in Mozilla JavaScript extensions (use moz option).")2789    .test(code, {es3: true, undef: true, predef: ["print"]});2790  test.done();2791};2792exports["test: no false positive array comprehension"] = function (test) {2793  var code = [2794    "var foo = []; for (let i in [1,2,3]) { print(i); }"2795  ];2796  TestRun(test)2797    .test(code, {moz: true, undef: true, predef: ["print"]});2798  test.done();2799};2800exports["try catch filters"] = function (test) {2801  var code = [2802    "try {",2803    "  throw {name: 'foo', message: 'bar'};",2804    "}",2805    "catch (e if e.name === 'foo') {",2806    "  print (e.message);",2807    "}"2808  ];2809  TestRun(test)2810    .test(code, {moz: true, undef: true, predef: ["print"]});2811  test.done();2812};2813exports["try catch filters as esnext"] = function (test) {2814  var code = [2815    "try {",2816    "  throw {name: 'foo', message: 'bar'};",2817    "}",2818    "catch (e if e.name === 'foo') {",2819    "  print (e.message);",2820    "}"2821  ];2822  TestRun(test)2823    .addError(4, "'catch filter' is only available in Mozilla JavaScript extensions " +2824      "(use moz option).")2825    .test(code, {esnext: true, undef: true, predef: ["print"]});2826  test.done();2827};2828exports["try catch filters as es5"] = function (test) {2829  var code = [2830    "try {",2831    "  throw {name: 'foo', message: 'bar'};",2832    "}",2833    "catch (e if e.name === 'foo') {",2834    "  print (e.message);",2835    "}"2836  ];2837  TestRun(test)2838    .addError(4, "'catch filter' is only available in Mozilla JavaScript extensions " +2839      "(use moz option).")2840    .test(code, {undef: true, predef: ["print"]}); // es52841  test.done();2842};2843exports["try catch filters as legacy JS"] = function (test) {2844  var code = [2845    "try {",2846    "  throw {name: 'foo', message: 'bar'};",2847    "}",2848    "catch (e if e.name === 'foo') {",2849    "  print (e.message);",2850    "}"2851  ];2852  TestRun(test)2853    .addError(4, "'catch filter' is only available in Mozilla JavaScript extensions " +2854      "(use moz option).")2855    .test(code, {es3: true, undef: true, predef: ["print"]});2856  test.done();2857};2858exports["test: function closure expression"] = function (test) {2859  var code = [2860    "let (arr = [1,2,3]) {",2861    "  arr.every(function (o) o instanceof Object);",2862    "}"2863  ];2864  TestRun(test)2865    .test(code, {es3: true, moz: true, undef: true});2866  test.done();2867};2868exports["test: function closure expression as esnext"] = function (test) {2869  var code = [2870    "var arr = [1,2,3];",2871    "arr.every(function (o) o instanceof Object);",2872  ];2873  TestRun(test)2874    .addError(2, "'function closure expressions' is only available in Mozilla JavaScript " +2875      "extensions (use moz option).")2876    .test(code, {esnext: true, undef: true});2877  test.done();2878};2879exports["test: function closure expression as es5"] = function (test) {2880  var code = [2881    "var arr = [1,2,3];",2882    "arr.every(function (o) o instanceof Object);",2883  ];2884  TestRun(test)2885    .addError(2, "'function closure expressions' is only available in Mozilla JavaScript " +2886      "extensions (use moz option).")2887    .test(code, {undef: true}); // es52888  test.done();2889};2890exports["test: function closure expression as legacy JS"] = function (test) {2891  var code = [2892    "var arr = [1,2,3];",2893    "arr.every(function (o) o instanceof Object);",2894  ];2895  TestRun(test)2896    .addError(2, "'function closure expressions' is only available in Mozilla JavaScript " +2897      "extensions (use moz option).")2898    .test(code, {es3: true, undef: true});2899  test.done();2900};2901exports["test: for of as esnext"] = function (test) {2902  var code = [2903    "for (let x of [1,2,3,4]) {",2904    "    print(x);",2905    "}",2906    "for (let x of [1,2,3,4]) print(x);"2907  ];2908  TestRun(test)2909    .test(code, {esnext: true, undef: true, predef: ["print"]});2910  test.done();2911};2912exports["test: for of as es5"] = function (test) {2913  var code = [2914    "for (let x of [1,2,3,4]) {",2915    "    print(x);",2916    "}",2917    "for (let x of [1,2,3,4]) print(x);"2918  ];2919  TestRun(test)2920    .addError(1, "'for of' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")2921    .addError(1, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")2922    .addError(4, "'for of' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")2923    .addError(4, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")2924    .test(code, {undef: true, predef: ["print"]}); // es52925  test.done();2926};2927exports["test: for of as legacy JS"] = function (test) {2928  var code = [2929    "for (let x of [1,2,3,4]) {",2930    "    print(x);",2931    "}",2932    "for (let x of [1,2,3,4]) print(x);"2933  ];2934  TestRun(test)2935    .addError(1, "'for of' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")2936    .addError(1, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")2937    .addError(4, "'for of' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")2938    .addError(4, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")2939    .test(code, {undef: true, predef: ["print"]}); // es52940  test.done();2941};2942exports["test: try multi-catch for moz extensions"] = function (test) {2943  var code = [2944    "try {",2945    "    print('X');",2946    "} catch (err) {",2947    "    print(err);",2948    "} catch (err) {",2949    "    print(err);",2950    "} finally {",2951    "    print('Z');",2952    "}"2953  ];2954  TestRun(test)2955    .test(code, {moz: true, undef: true, predef: ["print"]});2956  test.done();2957};2958exports["test: try multi-catch as esnext"] = function (test) {2959  var code = [2960    "try {",2961    "    print('X');",2962    "} catch (err) {",2963    "    print(err);",2964    "} catch (err) {",2965    "    print(err);",2966    "} finally {",2967    "    print('Z');",2968    "}"2969  ];2970  TestRun(test)2971    .addError(5, "'multiple catch blocks' is only available in Mozilla JavaScript extensions " +2972      "(use moz option).")2973    .test(code, {esnext: true, undef: true, predef: ["print"]});2974  test.done();2975};2976exports["test: try multi-catch as es5"] = function (test) {2977  var code = [2978    "try {",2979    "    print('X');",2980    "} catch (err) {",2981    "    print(err);",2982    "} catch (err) {",2983    "    print(err);",2984    "} finally {",2985    "    print('Z');",2986    "}"2987  ];2988  TestRun(test)2989    .addError(5, "'multiple catch blocks' is only available in Mozilla JavaScript extensions " +2990      "(use moz option).")2991    .test(code, {undef: true, predef: ["print"]}); // es52992  test.done();2993};2994exports["test: try multi-catch as legacy JS"] = function (test) {2995  var code = [2996    "try {",2997    "    print('X');",2998    "} catch (err) {",2999    "    print(err);",3000    "} catch (err) {",3001    "    print(err);",3002    "} finally {",3003    "    print('Z');",3004    "}"3005  ];3006  TestRun(test)3007    .addError(5, "'multiple catch blocks' is only available in Mozilla JavaScript extensions " +3008      "(use moz option).")3009    .test(code, {es3: true, undef: true, predef: ["print"]});3010  test.done();3011};3012exports["test: no let not directly within a block"] = function (test) {3013  var code = [3014    "if (true) let x = 1;",3015    "function foo() {",3016    "   if (true)",3017    "       let x = 1;",3018    "}",3019    "if (true) let (x = 1) print(x);",3020    "for (let x = 0; x < 42; ++x) let a = 1;",3021    "for (let x in [1, 2, 3, 4] ) let a = 1;",3022    "for (let x of [1, 2, 3, 4] ) let a = 1;",3023    "while (true) let a = 1;",3024    "if (false) let a = 1; else if (true) let a = 1; else let a = 2;"3025  ];3026  TestRun(test)3027    .addError(1, "Let declaration not directly within block.")3028    .addError(4, "Let declaration not directly within block.")3029    .addError(7, "Let declaration not directly within block.")3030    .addError(8, "Let declaration not directly within block.")3031    .addError(9, "Let declaration not directly within block.")3032    .addError(10, "Let declaration not directly within block.")3033    .addError(11, "Let declaration not directly within block.")3034    .addError(11, "Let declaration not directly within block.")3035    .addError(11, "Let declaration not directly within block.")3036    .test(code, {moz: true, predef: ["print"]});3037  test.done();3038};3039exports["regression test for crash from GH-964"] = function (test) {3040  var code = [3041    "function test(a, b) {",3042    "  return a[b] || a[b] = new A();",3043    "}"3044  ];3045  TestRun(test)3046    .addError(2, "Bad assignment.")3047    .addError(2, "Expected an operator and instead saw 'new'.")3048    .addError(2, "Missing semicolon.")3049    .test(code);3050  test.done();3051};3052exports["automatic comma insertion GH-950"] = function (test) {3053  var code = [3054    "var a = b",3055    "instanceof c;",3056    "var a = { b: 'X' }",3057    "delete a.b",3058    "var y = true",3059    "           && true && false;",3060    "function test() {",3061    "  return",3062    "      { a: 1 }",3063    "}",3064  ];3065  var run = TestRun(test)3066    .addError(2, "Bad line breaking before 'instanceof'.")3067    .addError(6, "Bad line breaking before '&&'.")3068    .addError(8, "Line breaking error 'return'.")3069    .addError(9, "Label 'a' on 1 statement.")3070    .addError(9, "Expected an assignment or function call and instead saw an expression.");3071  run.test(code, {es3: true, asi: true});3072  run.test(code, {asi: true}); // es53073  run.test(code, {esnext: true, asi: true});3074  run.test(code, {moz: true, asi: true});3075  run = TestRun(test)3076    .addError(2, "Bad line breaking before 'instanceof'.")3077    .addError(3, "Missing semicolon.")3078    .addError(4, "Missing semicolon.")3079    .addError(6, "Bad line breaking before '&&'.")3080    .addError(8, "Line breaking error 'return'.")3081    .addError(8, "Missing semicolon.")3082    .addError(9, "Label 'a' on 1 statement.")3083    .addError(9, "Expected an assignment or function call and instead saw an expression.")3084    .addError(9, "Missing semicolon.");3085  run.test(code, {es3: true, asi: false});3086  run.test(code, {asi: false}); // es53087  run.test(code, {esnext: true, asi: false});3088  run.test(code, {moz: true, asi: false});3089  test.done();3090};3091exports["fat arrows support"] = function (test) {3092  var code = [3093    "let empty = () => {};",3094    "let identity = x => x;",3095    "let square = x => x * x;",3096    "let key_maker = val => ({key: val});",3097    "let odds = evens.map(v => v + 1);",3098    "let fives = []; nats.forEach(v => { if (v % 5 === 0) fives.push(v); });",3099    "let block = (x,y, { z: t }) => {",3100    "  print(x,y,z);",3101    "  print(j, t);",3102    "};",3103    // using lexical this3104    "const obj = {",3105    "  method: function () {",3106    "    return () => this;",3107    "  }",3108    "};",3109    "let retnObj = () => ({});",3110    "let assgnRetnObj = (() => ({}))();",3111    "let retnObjLong = () => { return {}; };",3112    "let assgnRetnObjLong = (() => { return {}; })();",3113    "let objFns = {",3114    "  retnObj: () => ({}),",3115    "  assgnRetnObj: (() => ({}))(),",3116    "  retnObjLong: () => { return {}; },",3117    "  assgnRetnObjLong: (() => { return {}; })()",3118    "};"3119  ];3120  var run = TestRun(test)3121    .addError(5, "'evens' is not defined.")3122    .addError(6, "'nats' is not defined.")3123    .addError(8, "'print' is not defined.")3124    .addError(9, "'print' is not defined.")3125    .addError(9, "'j' is not defined.")3126    .addError(8, "'z' is not defined.");3127  run.test(code, { undef: true, esnext: true });3128  run = TestRun(test)3129    .addError(1, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3130    .addError(2, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3131    .addError(3, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3132    .addError(4, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3133    .addError(5, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3134    .addError(5, "'evens' is not defined.")3135    .addError(6, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3136    .addError(6, "'nats' is not defined.")3137    .addError(7, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3138    .addError(8, "'print' is not defined.")3139    .addError(8, "'z' is not defined.")3140    .addError(9, "'print' is not defined.")3141    .addError(9, "'j' is not defined.")3142    .addError(13, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3143    .addError(16, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3144    .addError(17, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3145    .addError(17, "Bad invocation.")3146    .addError(18, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3147    .addError(19, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3148    .addError(19, "Bad invocation.")3149    .addError(21, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3150    .addError(22, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3151    .addError(22, "Bad invocation.")3152    .addError(23, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3153    .addError(24, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3154    .addError(24, "Bad invocation.");3155  run.test(code, { undef: true, moz: true });3156  run = TestRun(test)3157    .addError(1, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3158    .addError(1, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3159    .addError(2, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3160    .addError(2, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3161    .addError(3, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3162    .addError(3, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3163    .addError(4, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3164    .addError(4, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3165    .addError(5, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3166    .addError(5, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3167    .addError(6, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3168    .addError(6, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3169    .addError(7, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3170    .addError(7, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3171    .addError(7, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3172    .addError(11, "'const' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3173    .addError(13, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3174    .addError(16, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3175    .addError(16, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3176    .addError(17, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3177    .addError(17, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3178    .addError(17, "Bad invocation.")3179    .addError(18, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3180    .addError(18, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3181    .addError(19, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3182    .addError(19, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3183    .addError(19, "Bad invocation.")3184    .addError(20, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3185    .addError(21, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3186    .addError(22, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3187    .addError(22, "Bad invocation.")3188    .addError(23, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3189    .addError(24, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3190    .addError(24, "Bad invocation.");3191  run.test(code); // es53192  run.test(code, {es3: true});3193  test.done();3194};3195exports["concise methods support"] = function (test) {3196  var code = [3197    "var foobar = {",3198    "  foo () {",3199    "    return 'foo';",3200    "  },",3201    "  *bar () {",3202    "    yield 'bar';",3203    "  }",3204    "};"3205  ];3206  var run = TestRun(test);3207  run.test(code, {esnext: true});3208  run.test(code, {moz: true});3209  run = TestRun(test)3210    .addError(2, "'concise methods' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3211    .addError(5, "'generator functions' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3212    .addError(5, "'concise methods' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3213    .addError(6, "'yield' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).");3214  run.test(code); // es53215  run.test(code, {es3: true});3216  test.done();3217};3218exports["concise methods support for 'get' and 'set' function names"] = function (test) {3219  var code = [3220    "var a = [1, 2, 3, 4, 5];",3221    "var strange = {",3222    "  get (i) {",3223    "    return a[i];",3224    "  },",3225    "  set () {",3226    "    a.forEach(function(v, i, l) { l[i] = v++; });",3227    "  }",3228    "};"3229  ];3230  TestRun(test).test(code, {esnext: true});3231  test.done();3232};3233exports["concise methods support for 'get' without 'set'"] = function (test) {3234  var code = [3235    "var a = [1, 2, 3, 4, 5];",3236    "var strange = {",3237    "  get () {",3238    "    return a;",3239    "  }",3240    "};"3241  ];3242  TestRun(test).test(code, {esnext: true});3243  test.done();3244};3245exports["concise methods support for 'set' without 'get'"] = function (test) {3246  var code = [3247    "var a = [1, 2, 3, 4, 5];",3248    "var strange = {",3249    "  set (v) {",3250    "    a = v;",3251    "  }",3252    "};"3253  ];3254  TestRun(test).test(code, {esnext: true});3255  test.done();3256};3257exports["object short notation: basic"] = function (test) {3258  var code = [3259    "var foo = 42;",3260    "var bar = {foo};",3261    "var baz = {foo, bar};"3262  ];3263  TestRun(test).test(code, {esnext: true});3264  TestRun(test)3265    .addError(2, "'object short notation' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3266    .addError(3, "'object short notation' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3267    .test(code);3268  test.done();3269};3270exports["object short notation: mixed"] = function (test) {3271  var code = [3272    "var b = 1, c = 2;",3273    "var o1 = {a: 1, b, c};",3274    "var o2 = {b, a: 1, c};"3275  ].join("\n");3276  TestRun(test).test(code, { esnext: true });3277  TestRun(test)3278    .addError(2, "'object short notation' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3279    .addError(2, "'object short notation' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3280    .addError(3, "'object short notation' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3281    .addError(3, "'object short notation' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3282  .test(code);3283  test.done();3284};3285exports["spread & rest operator support"] = function (test) {3286  var code = [3287    // spread operator3288    "function foo(a, b, c) {",3289    "  console.log(a, b, c); ",3290    "}",3291    "var args = [ 0, 1, 2 ];",3292    "foo(...args);",3293    // spread operator3294    "let initial = [ 1, 2, 3, 4, 5 ];",3295    "let extended = [ ...initial, 6, 7, 8, 9 ];",3296    // rest operator3297    "(function foo(i, j, ...args) {",3298    "  return args;",3299    "}());",3300    // rest operator on a fat arrow function3301    "let bar = (...args) => args;"3302  ];3303  var run = TestRun(test);3304  run.test(code, {esnext: true});3305  run = TestRun(test)3306    .addError(11, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3307    .addError(5, "'spread/rest operator' is only available in ES6 (use esnext option).")3308    .addError(7, "'spread/rest operator' is only available in ES6 (use esnext option).")3309    .addError(8, "'spread/rest operator' is only available in ES6 (use esnext option).")3310    .addError(11, "'spread/rest operator' is only available in ES6 (use esnext option).");3311  run.test(code, {moz: true});3312  run = TestRun(test)3313    .addError(5, "'spread/rest operator' is only available in ES6 (use esnext option).")3314    .addError(6, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3315    .addError(7, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3316    .addError(7, "'spread/rest operator' is only available in ES6 (use esnext option).")3317    .addError(8, "'spread/rest operator' is only available in ES6 (use esnext option).")3318    .addError(11, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3319    .addError(11, "'spread/rest operator' is only available in ES6 (use esnext option).")3320    .addError(11, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).");3321  run.test(code);3322  test.done();3323};3324exports["parameter destructuring with rest"] = function (test) {3325  var code = [3326    // 13327    // parameter destructuring with rest operator, solo3328    "let b = ([...args]) => args;",3329    // 23330    // ...in function expression3331    "let c = function([...args]) { return args; };",3332    // 33333    // ...in function declaration3334    "function d([...args]) { return args; }",3335    // 43336    // default destructuring with rest operator, with leading param3337    "let e = ([first, ...args]) => args;",3338    // 53339    // ...in function expression3340    "let f = function([first, ...args]) { return args; };",3341    // 63342    // ...in function declaration3343    "function g([first, ...args]) { return args; }",3344    // 73345    // Just rest3346    "let h = (...args) => args;",3347    // 83348    // ...in function expression3349    "let i = function(...args) { return args; };",3350    // 93351    // ...in function declaration3352    "function j(...args) { return args; }"3353  ];3354  var run = TestRun(test);3355  run.test(code, {esnext: true});3356  run = TestRun(test)3357    .addError(1, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3358    .addError(1, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3359    .addError(4, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3360    .addError(7, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3361    .addError(7, "'spread/rest operator' is only available in ES6 (use esnext option).")3362    .addError(1, "'spread/rest operator' is only available in ES6 (use esnext option).")3363    .addError(1, "'spread/rest operator' is only available in ES6 (use esnext option).")3364    .addError(2, "'spread/rest operator' is only available in ES6 (use esnext option).")3365    .addError(2, "'spread/rest operator' is only available in ES6 (use esnext option).")3366    .addError(3, "'spread/rest operator' is only available in ES6 (use esnext option).")3367    .addError(3, "'spread/rest operator' is only available in ES6 (use esnext option).")3368    .addError(4, "'spread/rest operator' is only available in ES6 (use esnext option).")3369    .addError(4, "'spread/rest operator' is only available in ES6 (use esnext option).")3370    .addError(5, "'spread/rest operator' is only available in ES6 (use esnext option).")3371    .addError(5, "'spread/rest operator' is only available in ES6 (use esnext option).")3372    .addError(6, "'spread/rest operator' is only available in ES6 (use esnext option).")3373    .addError(6, "'spread/rest operator' is only available in ES6 (use esnext option).")3374    .addError(8, "'spread/rest operator' is only available in ES6 (use esnext option).")3375    .addError(9, "'spread/rest operator' is only available in ES6 (use esnext option).");3376  run.test(code, {moz: true});3377  run = TestRun(test)3378    .addError(1, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3379    .addError(1, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3380    .addError(1, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3381    .addError(1, "'spread/rest operator' is only available in ES6 (use esnext option).")3382    .addError(2, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3383    .addError(2, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3384    .addError(2, "'spread/rest operator' is only available in ES6 (use esnext option).")3385    .addError(3, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3386    .addError(3, "'spread/rest operator' is only available in ES6 (use esnext option).")3387    .addError(4, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3388    .addError(4, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3389    .addError(4, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3390    .addError(4, "'spread/rest operator' is only available in ES6 (use esnext option).")3391    .addError(5, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3392    .addError(5, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3393    .addError(5, "'spread/rest operator' is only available in ES6 (use esnext option).")3394    .addError(6, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3395    .addError(6, "'spread/rest operator' is only available in ES6 (use esnext option).")3396    .addError(7, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3397    .addError(7, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3398    .addError(7, "'spread/rest operator' is only available in ES6 (use esnext option).")3399    .addError(8, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3400    .addError(8, "'spread/rest operator' is only available in ES6 (use esnext option).")3401    .addError(9, "'spread/rest operator' is only available in ES6 (use esnext option).");3402  run.test(code);3403  test.done();3404};3405exports["test for GH-1010"] = function (test) {3406  var code = [3407    "var x = 20, y, z; if(x < 30) y=7, z=2; else y=5;"3408  ];3409  var run = TestRun(test);3410  run.test(code, {expr: true, es3: true});3411  run.test(code, {expr: true}); // es53412  run.test(code, {expr: true, esnext: true});3413  run.test(code, {expr: true, moz: true});3414  test.done();3415};3416exports.classes = function (test) {3417  var cdecl = "// cdecl";3418  var cexpr = "// cexpr";3419  var cdeclAssn = "// cdeclAssn";3420  var cexprAssn = "// cexprAssn";3421  var code = [3422    "var Bar;",3423    // class declarations3424    cdecl,3425    "class Foo0 {}",3426    "class Foo1 extends Bar {}",3427    "class protected {",3428    "  constructor(package) {}",3429    "}",3430    "class Foo3 extends interface {",3431    "  constructor() {}",3432    "}",3433    "class Foo4 extends Bar {",3434    "  constructor() {",3435    "    super();",3436    "  }",3437    "}",3438    "class Foo5 {",3439    "  constructor() {",3440    "  }",3441    "  static create() {",3442    "  }",3443    "}",3444    "class Foo6 extends Bar {",3445    "  constructor() {",3446    "    super();",3447    "  }",3448    "  static create() {",3449    "  }",3450    "}",3451    // class expressions3452    cexpr,3453    "var Foo7 = class {};",3454    "let Foo8 = class extends Bar {};",3455    "var static = class protected {",3456    "  constructor(package) {}",3457    "};",3458    "var Foo10 = class extends interface {",3459    "  constructor() {}",3460    "};",3461    "var Foo11 = class extends Bar {",3462    "  constructor() {",3463    "    super();",3464    "  }",3465    "};",3466    "var Foo12 = class {",3467    "  constructor() {",3468    "  }",3469    "  static create() {",3470    "  }",3471    "};",3472    "let Foo13 = class extends Bar {",3473    "  constructor() {",3474    "    super();",3475    "  }",3476    "  static create() {",3477    "  }",3478    "};",3479    // mark these as used3480    "void (Foo1, Foo3, Foo4, Foo5, Foo6);",3481    "void (Foo8, Foo10, Foo11, Foo12, Foo13);",3482    // class declarations: extends AssignmentExpression3483    cdeclAssn,3484    "class Foo14 extends Bar[42] {}",3485    "class Foo15 extends { a: function() { return 42; } } {}",3486    "class Foo16 extends class Foo15 extends Bar {} {}",3487    "class Foo17 extends Foo15 = class Foo16 extends Bar {} {}",3488    "class Foo18 extends function () {} {}",3489    "class Foo19 extends class extends function () {} {} {}",3490    "class Foo20 extends Foo18 = class extends Foo17 = function () {} {} {}",3491    // class expressions: extends AssignmentExpression3492    cexprAssn,3493    "let Foo21 = class extends Bar[42] {};",3494    "let Foo22 = class extends { a() { return 42; } } {};",3495    "let Foo23 = class extends class Foo15 extends Bar {} {};",3496    "let Foo24 = class extends Foo15 = class Foo16 extends Bar {} {};",3497    "let Foo25 = class extends function () {} {};",3498    "let Foo26 = class extends class extends function () {} {} {};",3499    "let Foo27 = class extends Foo18 = class extends Foo17 = function () {} {} {};",3500    // mark these as used3501    "void (Foo14, Foo15, Foo16, Foo17, Foo18, Foo19, Foo20);",3502    "void (Foo21, Foo22, Foo23, Foo24, Foo25, Foo26, Foo27);"3503  ];3504  cdecl = code.indexOf(cdecl) + 1;3505  cexpr = code.indexOf(cexpr) + 1;3506  cdeclAssn = code.indexOf(cdeclAssn) + 1;3507  cexprAssn = code.indexOf(cexprAssn) + 1;3508  var run = TestRun(test)3509    .addError(cdecl + 4, "Expected an identifier and instead saw 'package' (a reserved word).")3510    .addError(cexpr + 4, "Expected an identifier and instead saw 'package' (a reserved word).");3511  run.test(code, {esnext: true});3512  run.test(code, {moz: true});3513  run3514    .addError(cdecl + 1, "'Foo0' is defined but never used.")3515    .addError(cdecl + 3, "Expected an identifier and instead saw 'protected' (a reserved word).")3516    .addError(cdecl + 3, "'protected' is defined but never used.")3517    .addError(cdecl + 4, "'package' is defined but never used.");3518  run3519    .addError(cexpr + 1, "'Foo7' is defined but never used.")3520    .addError(cexpr + 3, "Expected an identifier and instead saw 'static' (a reserved word).")3521    .addError(cexpr + 3, "'static' is defined but never used.")3522    .addError(cexpr + 3, "Expected an identifier and instead saw 'protected' (a reserved word).")3523    .addError(cexpr + 4, "'package' is defined but never used.");3524  code[0] = "'use strict';" + code[0];3525  run.test(code, {unused: true, globalstrict: true, esnext: true});3526  run.test(code, {unused: true, globalstrict: true, moz: true});3527  test.done();3528};3529exports["class and method naming"] = function (test) {3530  var code = [3531    "class eval {}",3532    "class arguments {}",3533    "class C {",3534    "  get constructor() {}",3535    "  set constructor(x) {}",3536    "  prototype() {}",3537    "}"3538  ];3539  var run = TestRun(test)3540    .addError(1, "Expected an identifier and instead saw 'eval' (a reserved word).")3541    .addError(2, "Expected an identifier and instead saw 'arguments' (a reserved word).")3542    .addError(4, "A class getter method cannot be named 'constructor'.")3543    .addError(5, "A class setter method cannot be named 'constructor'.")3544    .addError(7, "A class method cannot be named 'prototype'.");3545  run.test(code, {esnext: true});3546  test.done();3547};3548exports["test for GH-1018"] = function (test) {3549  var code = [3550    "if (a = 42) {}",3551    "else if (a = 42) {}",3552    "while (a = 42) {}",3553    "for (a = 42; a = 42; a += 42) {}",3554    "do {} while (a = 42);",3555    "switch (a = 42) {}"3556  ];3557  var run = TestRun(test);3558  run.test(code, {boss: true});3559  for (var i = 0; i < code.length; i++) {3560    run.addError(i + 1, "Expected a conditional expression and instead saw an assignment.");3561  }3562  run.test(code);3563  test.done();3564};3565exports["test warnings for assignments in conditionals"] = function (test) {3566  var code = [3567    "if (a = b) { }",3568    "if ((a = b)) { }",3569    "if (a = b, a) { }",3570    "if (a = b, b = c) { }",3571    "if ((a = b, b = c)) { }",3572    "if (a = b, (b = c)) { }"3573  ];3574  var run = TestRun(test)3575    .addError(1, "Expected a conditional expression and instead saw an assignment.")3576    .addError(4, "Expected a conditional expression and instead saw an assignment.");3577  run.test(code); // es53578  test.done();3579};3580exports["test for GH-1089"] = function (test) {3581  var code = [3582    "function foo() {",3583    "    'use strict';",3584    "    Object.defineProperty(foo, 'property', {",3585    "        get: function() foo,",3586    "        set: function(value) {},",3587    "        enumerable: true",3588    "    });",3589    "}",3590    "foo;"3591  ];3592  var run = TestRun(test)3593    .addError(9, "Expected an assignment or function call and instead saw an expression.");3594  run.test(code, {moz: true});3595  run3596    .addError(4, "'function closure expressions' is only available in Mozilla JavaScript " +3597        "extensions (use moz option).");3598  run.test(code);3599  test.done();3600};3601exports["test for GH-1103"] = function (test) {3602  var code = [ "var ohnoes = 42;" ];3603  var run = TestRun(test);3604  var patch = true;3605  JSHINT.addModule(function (linter) {3606    if (!patch) {3607      return;3608    }3609    patch = false;3610    var ohnoes = "oh noes";3611    Array.prototype.ohnoes = function () {3612      linter.warn("E024", { line: 1, char: 1, data: [ ohnoes += "!" ] });3613    };3614  });3615  run.test(code);3616  test.done();3617  delete Array.prototype.ohnoes;3618};3619exports["test for GH-1105"] = function (test) {3620  var code = [3621    "while (true) {",3622    "    if (true) { break }",3623    "}"3624  ];3625  var run = TestRun(test)3626    .addError(2, "Missing semicolon.");3627  run.test(code);3628  test.done();3629};3630exports["test for crash with invalid condition"] = function (test) {3631  var code = [3632    "do {} while ();",3633    "do {} while (,);",3634    "do {} while (a,);",3635    "do {} while (,b);",3636    "do {} while (());",3637    "do {} while ((,));",3638    "do {} while ((a,));",3639    "do {} while ((,b));"3640  ];3641  // As long as jshint doesn't crash, it doesn't matter what these errors3642  // are. Feel free to adjust these if they don't match the output.3643  var run = TestRun(test)3644    .addError(1, "Expected an identifier and instead saw ')'.")3645    .addError(1, "Expected ')' to match '(' from line 1 and instead saw ';'.")3646    .addError(2, "Expected an identifier and instead saw ','.")3647    .addError(3, "Unexpected ')'.")3648    .addError(4, "Expected an identifier and instead saw ','.")3649    .addError(4, "Expected ')' to match '(' from line 4 and instead saw 'b'.")3650    .addError(4, "Expected an identifier and instead saw ')'.")3651    .addError(6, "Expected an identifier and instead saw ','.")3652    .addError(7, "Unexpected ')'.")3653    .addError(7, "Expected an identifier and instead saw ')'.")3654    .addError(7, "Expected ')' to match '(' from line 7 and instead saw ';'.")3655    .addError(8, "Expected an identifier and instead saw ','.")3656    .addError(8, "Expected ')' to match '(' from line 8 and instead saw 'b'.")3657    .addError(8, "Expected an identifier and instead saw ')'.");3658  run.test(code, {asi: true, expr: true});3659  test.done();3660};3661exports["test 'yield' in compound expressions."] = function (test) {3662  var code = fs.readFileSync(path.join(__dirname, "./fixtures/yield-expressions.js"), "utf8");3663  var run = TestRun(test)3664    .addError(22, "Did you mean to return a conditional instead of an assignment?")3665    .addError(31, "Did you mean to return a conditional instead of an assignment?");3666  run.test(code, {maxerr: 1000, expr: true, esnext: true});3667  // These are line-column pairs for the Mozilla paren errors.3668  var needparen = [3669    // comma3670    [ 5,  5], [ 6,  8], [ 7,  5], [11,  5], [12,  8], [13,  5],3671    // yield in yield3672    [18, 11], [19, 17], [19, 11], [20, 11], [20,  5], [21, 11], [21,  5], [21, 26], [22, 22],3673    [23, 22], [23, 11], [27, 11], [28, 17], [28, 11], [29, 11], [29,  5], [30, 11], [30,  5],3674    [30, 24], [31, 22], [32, 11], [32, 20],3675    // infix3676    [51, 10], [53, 10], [54, 16], [57, 10], [58,  5], [59, 10], [60,  5], [60, 14],3677    // prefix3678    [64,  6], [65,  7], [66,  6], [67,  7], [70,  6], [71,  7],3679    // ternary3680    [77,  5], [78,  5], [78, 13], [79,  5], [79, 13], [79, 41], [82,  5], [83,  5], [83, 13],3681    [84,  5], [84, 13], [84, 37]3682  ];3683  needparen.forEach(function (lc) {3684    run.addError(lc[0], "Mozilla requires the yield expression to be parenthesized here.",3685                 {character: lc[1]});3686  });3687  run3688    .addError(1, "'function*' is only available in ES6 (use esnext option).")3689    .addError(74, "'function*' is only available in ES6 (use esnext option).");3690  run.test(code, {maxerr: 1000, expr: true, moz: true});3691  test.done();3692};3693exports["test for GH-387"] = function (test) {3694  var code = [3695    "var foo = a",3696    "delete foo.a;"3697  ];3698  var run = TestRun(test)3699    .addError(1, "Missing semicolon.");3700  run.test(code); // es53701  test.done();3702};3703exports["test for line breaks with 'yield'"] = function (test) {3704  var code = [3705    "function* F() {",3706    "    a = b + (yield",3707    "    c",3708    "    );",3709    "    d = yield",3710    "    + e;",3711    "    f = (yield",3712    "    , g);",3713    "    h = yield",3714    "    ? i : j;",3715    "    k = l ? yield",3716    "    : m;",3717    "    n = o ? p : yield",3718    "    + r;",3719    "}"3720  ];3721  var run = TestRun(test)3722    .addError(3, "Bad line breaking before 'c'.")3723    .addError(6, "Bad line breaking before '+'.")3724    .addError(8, "Comma warnings can be turned off with 'laxcomma'.")3725    .addError(7, "Bad line breaking before ','.")3726    .addError(10, "Bad line breaking before '?'.")3727    .addError(14, "Bad line breaking before '+'.");3728  run.test(code, {esnext: true});3729  // Mozilla assumes the statement has ended if there is a line break3730  // following a `yield`. This naturally causes havoc with the subsequent3731  // parse.3732  //3733  // Note: there is one exception to the line-breaking rule:3734  // ```js3735  // a ? yield3736  // : b;3737  // ```3738  run = TestRun(test)3739    .addError(1, "'function*' is only available in ES6 (use esnext option).")3740    .addError(3, "Expected ')' to match '(' from line 2 and instead saw 'c'.")3741    .addError(4, "Expected an identifier and instead saw ')'.")3742    .addError(4, "Expected an assignment or function call and instead saw an expression.")3743    .addError(6, "Expected an assignment or function call and instead saw an expression.")3744    .addError(8, "Comma warnings can be turned off with 'laxcomma'.")3745    .addError(7, "Bad line breaking before ','.")3746    .addError(10, "Expected an identifier and instead saw '?'.")3747    .addError(10, "Expected an assignment or function call and instead saw an expression.")3748    .addError(10, "Label 'i' on j statement.")3749    .addError(10, "Expected an assignment or function call and instead saw an expression.")3750    .addError(14, "Expected an assignment or function call and instead saw an expression.");3751  run.test(code, {moz: true, asi: true});3752  run3753    .addError(2, "Line breaking error 'yield'.")3754    .addError(3, "Missing semicolon.")3755    .addError(5, "Line breaking error 'yield'.")3756    .addError(5, "Missing semicolon.")3757    .addError(7, "Line breaking error 'yield'.")3758    .addError(9, "Line breaking error 'yield'.")3759    .addError(9, "Missing semicolon.")3760    .addError(10, "Missing semicolon.")3761    .addError(11, "Line breaking error 'yield'.")3762    .addError(13, "Line breaking error 'yield'.")3763    .addError(13, "Missing semicolon.");3764  run.test(code, {moz: true});3765  test.done();3766};3767exports["regression for GH-1227"] = function (test) {3768  var src = fs.readFileSync(__dirname + "/fixtures/gh1227.js", "utf8");3769  TestRun(test)3770    .addError(14, "Unreachable 'return' after 'return'.")3771    .test(src);3772  test.done();3773};3774exports["test for 'break' in switch case + curly braces"] = function (test) {3775  var code = [3776    "switch (foo) {",3777    "  case 1: { break; }",3778    "  case 2: { return; }",3779    "  case 3: { throw 'Error'; }",3780    "  case 11: {",3781    "    while (true) {",3782    "      break;",3783    "    }",3784    "  }",3785    "  default: break;",3786    "}"3787  ];3788  // No error for case 1, 2, 3.3789  var run = TestRun(test)3790    .addError(9, "Expected a 'break' statement before 'default'.")3791    .test(code);3792  test.done();3793};3794exports["test for 'break' in switch case in loop + curly braces"] = function (test) {3795  var code = [3796    "while (true) {",3797    "  switch (foo) {",3798    "    case 1: { break; }",3799    "    case 2: { return; }",3800    "    case 3: { throw 'Error'; }",3801    "    case 4: { continue; }",3802    "    case 11: {",3803    "      while (true) {",3804    "        break;",3805    "      }",3806    "    }",3807    "    default: break;",3808    "  }",3809    "}"3810  ];3811  // No error for case 1, 2, 3, 4.3812  var run = TestRun(test)3813    .addError(11, "Expected a 'break' statement before 'default'.")3814    .test(code);3815  test.done();3816};3817exports["allow expression with a comma in switch case condition"] = function (test) {3818  var code = [3819    "switch (false) {",3820    "  case x = 1, y = x: { break; }",3821    "}"3822  ]3823  var run = TestRun(test).test(code);3824  test.done();3825};3826exports["/*jshint ignore */ should be a good option and only accept start, end or line as values"] = function (test) {3827  var code = [3828    "/*jshint ignore:start*/",3829    "/*jshint ignore:end*/",3830    "/*jshint ignore:line*/",3831    "/*jshint ignore:badvalue*/"3832  ];3833  TestRun(test)3834    .addError(4, "Bad option value.")3835    .test(code);3836  test.done();3837};3838exports["/*jshint ignore */ should allow the linter to skip blocked-out lines to continue finding errors in the rest of the code"] = function (test) {3839  var code = fs.readFileSync(__dirname + "/fixtures/gh826.js", "utf8");3840  TestRun(test)3841    .addError(33, "Use '===' to compare with '0'.")3842    .test(code);3843  test.done();3844};3845exports["/*jshint ignore */ should be detected even with leading and/or trailing whitespace"] = function (test) {3846  var code = [3847    "  /*jshint ignore:start */",     // leading whitespace3848    "   if (true) { alert('sup') }", // should be ignored3849    "  /*jshint ignore:end */  ",     // leading and trailing whitespace3850    "   if (true) { alert('sup') }", // should not be ignored3851    "  /*jshint ignore:start */   ",  // leading and trailing whitespace3852    "   if (true) { alert('sup') }", // should be ignored3853    "  /*jshint ignore:end */   "     // leading and trailing whitespace3854  ];3855  TestRun(test)3856    .addError(4, "Missing semicolon.")3857    .test(code);3858  test.done();3859};3860exports["should be able to ignore a single line with a trailing comment: // jshint:ignore"] = function (test) {3861  var code = fs.readFileSync(__dirname + "/fixtures/gh870.js", "utf8");3862  TestRun(test).test(code, { unused: true });3863  test.done();3864};3865exports["regression test for GH-1431"] = function (test) {3866  // The code is invalid but it should not crash JSHint.3867  TestRun(test)3868    .addError(1, "Use '!==' to compare with 'null'.")3869    .addError(1, "Expected ';' and instead saw ')'.")3870    .addError(1, "Expected ')' and instead saw ';'.")3871    .addError(1, "Expected an identifier and instead saw ';'.")3872    .addError(1, "Expected ')' to match '(' from line 1 and instead saw 'i'.")3873    .addError(1, "Expected an identifier and instead saw ')'.")3874    .test("for (i=0; (arr[i])!=null); i++);");3875  test.done();3876};3877exports["jshint ignore:start/end should be detected using single line comments"] = function (test) {3878  var code = [3879    "// jshint ignore:start",3880    "var a;",3881    "// jshint ignore:end",3882    "var b;"3883  ];3884  TestRun(test)3885    .addError(4, "'b' is defined but never used.")3886    .test(code, { unused: true });3887  test.done();3888};3889exports["test destructuring function parameters as es5"] = function (test) {3890  var src = fs.readFileSync(__dirname + "/fixtures/destparam.js", "utf8");3891  TestRun(test)3892    .addError(4, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3893    .addError(4, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3894    .addError(5, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3895    .addError(5, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3896    .addError(6, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3897    .addError(6, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3898    .addError(6, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3899    .addError(7, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3900    .addError(7, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3901    .addError(7, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3902    .addError(7, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3903    .addError(10, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3904    .addError(10, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3905    .addError(11, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3906    .addError(11, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3907    .addError(14, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3908    .addError(14, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3909    .addError(15, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3910    .addError(15, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3911    .addError(16, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3912    .addError(16, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3913    .addError(16, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3914    .addError(17, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3915    .addError(17, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3916    .addError(18, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3917    .addError(18, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3918    .addError(21, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3919    .addError(21, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3920    .addError(21, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3921    .addError(22, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3922    .addError(22, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3923    .addError(22, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3924    .addError(23, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3925    .addError(23, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3926    .addError(23, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3927    .addError(24, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3928    .addError(24, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3929    .addError(24, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3930    .addError(27, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3931    .addError(27, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3932    .addError(27, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3933    .addError(28, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3934    .addError(28, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3935    .addError(28, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3936    .addError(29, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3937    .addError(29, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3938    .addError(29, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3939    .addError(30, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3940    .addError(30, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3941    .addError(30, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3942    .addError(31, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3943    .addError(31, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3944    .addError(31, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3945  .test(src, {unused: true, undef: true, maxerr: 100});3946  test.done();3947};3948exports["test destructuring function parameters as legacy JS"] = function (test) {3949  var src = fs.readFileSync(__dirname + "/fixtures/destparam.js", "utf8");3950  TestRun(test)3951    .addError(4, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3952    .addError(4, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3953    .addError(5, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3954    .addError(5, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3955    .addError(6, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3956    .addError(6, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3957    .addError(6, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3958    .addError(7, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3959    .addError(7, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3960    .addError(7, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3961    .addError(7, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3962    .addError(10, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3963    .addError(10, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3964    .addError(11, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3965    .addError(11, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3966    .addError(14, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3967    .addError(14, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3968    .addError(15, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3969    .addError(15, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3970    .addError(16, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3971    .addError(16, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3972    .addError(16, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3973    .addError(17, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3974    .addError(17, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3975    .addError(18, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3976    .addError(18, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3977    .addError(21, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3978    .addError(21, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3979    .addError(21, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3980    .addError(22, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3981    .addError(22, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3982    .addError(22, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3983    .addError(23, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3984    .addError(23, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3985    .addError(23, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3986    .addError(24, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3987    .addError(24, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3988    .addError(24, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3989    .addError(27, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3990    .addError(27, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3991    .addError(27, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3992    .addError(28, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3993    .addError(28, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3994    .addError(28, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3995    .addError(29, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3996    .addError(29, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3997    .addError(29, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")3998    .addError(30, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")3999    .addError(30, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")4000    .addError(30, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")4001    .addError(31, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")4002    .addError(31, "'destructuring expression' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")4003    .addError(31, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")4004    .test(src, {es3: true, unused: true, undef: true, maxerr: 100});4005  test.done();4006};4007exports["test for parentheses in odd-numbered token"] = function (test) {4008  var code = [4009    "let f, b;",4010    "let a = x => ({ f: f(x) });",4011    "b = x => x;"4012  ];4013  TestRun(test)4014    .test(code, {esnext: true});4015  test.done();4016};4017exports["regression crash from GH-1573"] = function (test) {4018  TestRun(test)4019    .addError(1, "Expected an identifier and instead saw 'var'.")4020    .addError(1, "Expected ']' to match '[' from line 1 and instead saw 'foo'.")4021    .addError(1, "Expected an identifier and instead saw ']'.")4022    .addError(1, "Expected an assignment or function call and instead saw an expression.")4023    .addError(1, "Missing semicolon.")4024    .test("[var foo = 1;]");4025  test.done();4026};4027exports["make sure we don't throw errors on removed options"] = function (test) {4028  TestRun(test).test("a();", { nomen: true, onevar: true, passfail: true, white: true });4029  test.done();4030};4031exports["'for of' shouldn't be subject to 'for in' rules"] = function (test) {4032  TestRun(test)4033    .test("for (let x of [1, 2, 3]) { console.log(x); }", { forin: true, esnext: true });4034  test.done();4035};4036exports["Ignore strings containing braces within array literal declarations"] = function (test) {4037  TestRun(test).test("var a = [ '[' ];");...

Full Screen

Full Screen

options.js

Source:options.js Github

copy

Full Screen

...21exports.shadow = function (test) {22  var src = fs.readFileSync(__dirname + "/fixtures/redef.js", "utf8");23  // Do not tolerate variable shadowing by default24  TestRun(test)25    .addError(5, "'a' is already defined.")26    .addError(10, "'foo' is already defined.")27    .test(src, {es3: true});28  TestRun(test)29    .addError(5, "'a' is already defined.")30    .addError(10, "'foo' is already defined.")31    .test(src, {es3: true, shadow: false });32  TestRun(test)33    .addError(5, "'a' is already defined.")34    .addError(10, "'foo' is already defined.")35    .test(src, {es3: true, shadow: "inner" });36  // Allow variable shadowing when shadow is true37  TestRun(test)38    .test(src, { es3: true, shadow: true });39  test.done();40};41/**42 * Option `scopeshadow` allows you to re-define variables later in inner scopes.43 *44 *  E.g.:45 *    var a = 1;46 *    function foo() {47 *        var a = 2;48 *    }49 */50exports.scopeshadow = function (test) {51  var src = fs.readFileSync(__dirname + "/fixtures/scope-redef.js", "utf8");52  // Do not tolarate inner scope variable shadowing by default53  TestRun(test)54    .addError(5, "'a' is already defined in outer scope.")55    .addError(12, "'b' is already defined in outer scope.")56    .addError(20, "'bar' is already defined in outer scope.")57    .addError(26, "'foo' is already defined.")58    .test(src, { es3: true, shadow: "outer" });59  test.done();60}61/**62 * Option `latedef` allows you to prohibit the use of variable before their63 * definitions.64 *65 * E.g.:66 *   fn(); // fn will be defined later in code67 *   function fn() {};68 *69 * Since JavaScript has function-scope only, you can define variables and70 * functions wherever you want. But if you want to be more strict, use71 * this option.72 */73exports.latedef = function (test) {74  var src  = fs.readFileSync(__dirname + '/fixtures/latedef.js', 'utf8'),75    src1 = fs.readFileSync(__dirname + '/fixtures/redef.js', 'utf8');76  // By default, tolerate the use of variable before its definition77  TestRun(test)78    .test(src, {es3: true});79  // However, JSHint must complain if variable is actually missing80  TestRun(test)81    .addError(1, "'fn' is not defined.")82    .test('fn();', { es3: true, undef: true });83  // And it also must complain about the redefinition (see option `shadow`)84  TestRun(test)85    .addError(5, "'a' is already defined.")86    .addError(10, "'foo' is already defined.")87    .test(src1, { es3: true });88  // When latedef is true, JSHint must not tolerate the use before definition89  TestRun(test)90    .addError(10, "'vr' was used before it was defined.")91    .test(src, { es3: true, latedef: "nofunc" });92  // When latedef_func is true, JSHint must not tolerate the use before definition for functions93  TestRun(test)94    .addError(2, "'fn' was used before it was defined.")95    .addError(6, "'fn1' was used before it was defined.")96    .addError(10, "'vr' was used before it was defined.")97    .addError(18, "Inner functions should be listed at the top of the outer function.")98    .test(src, { es3: true, latedef: true });99  test.done();100};101exports.notypeof = function (test) {102  var src = fs.readFileSync(__dirname + '/fixtures/typeofcomp.js', 'utf8');103  TestRun(test)104    .addError(1, "Invalid typeof value 'funtion'")105    .addError(2, "Invalid typeof value 'double'")106    .addError(3, "Invalid typeof value 'bool'")107    .addError(4, "Invalid typeof value 'obj'")108    .test(src);109  TestRun(test)110    .test(src, { notypeof: true });111  test.done();112}113exports['combination of latedef and undef'] = function (test) {114  var src = fixture('latedefundef.js');115  // Assures that when `undef` is set to true, it'll report undefined variables116  // and late definitions won't be reported as `latedef` is set to false.117  TestRun(test)118    .addError(29, "'hello' is not defined.")119    .addError(35, "'world' is not defined.")120    .test(src, { es3: true, latedef: false, undef: true });121  // When we suppress `latedef` and `undef` then we get no warnings.122  TestRun(test)123    .test(src, { es3: true, latedef: false, undef: false });124  // If we warn on `latedef` but supress `undef` we only get the125  // late definition warnings.126  TestRun(test)127    .addError(5, "'func2' was used before it was defined.")128    .addError(12, "'foo' was used before it was defined.")129    .addError(18, "'fn1' was used before it was defined.")130    .addError(26, "'baz' was used before it was defined.")131    .addError(34, "'fn' was used before it was defined.")132    .addError(41, "'q' was used before it was defined.")133    .addError(46, "'h' was used before it was defined.")134    .test(src, { es3: true, latedef: true, undef: false });135  // But we get all the functions warning if we disable latedef func136  TestRun(test)137    .addError(41, "'q' was used before it was defined.")138    .addError(46, "'h' was used before it was defined.")139    .test(src, { es3: true, latedef: "nofunc", undef: false });140  // If we warn on both options we get all the warnings.141  TestRun(test)142    .addError(5, "'func2' was used before it was defined.")143    .addError(12, "'foo' was used before it was defined.")144    .addError(18, "'fn1' was used before it was defined.")145    .addError(26, "'baz' was used before it was defined.")146    .addError(29, "'hello' is not defined.")147    .addError(34, "'fn' was used before it was defined.")148    .addError(35, "'world' is not defined.")149    .addError(41, "'q' was used before it was defined.")150    .addError(46, "'h' was used before it was defined.")151    .test(src, { es3: true, latedef: true, undef: true });152  // If we remove latedef_func, we don't get the functions warning153  TestRun(test)154    .addError(29, "'hello' is not defined.")155    .addError(35, "'world' is not defined.")156    .addError(41, "'q' was used before it was defined.")157    .addError(46, "'h' was used before it was defined.")158    .test(src, { es3: true, latedef: "nofunc", undef: true });159  test.done();160};161exports.undefwstrict = function (test) {162  var src = fs.readFileSync(__dirname + '/fixtures/undefstrict.js', 'utf8');163  TestRun(test).test(src, { es3: true, undef: false });164  test.done();165};166// Regression test for GH-431167exports["implied and unused should respect hoisting"] = function (test) {168  var src = fs.readFileSync(__dirname + '/fixtures/gh431.js', 'utf8');169  TestRun(test)170    .addError(14, "'fun4' is not defined.")171    .test(src, { undef: true }); // es5172  JSHINT.flag = true;173  JSHINT(src, { undef: true });174  var report = JSHINT.data();175  test.equal(report.implieds.length, 1);176  test.equal(report.implieds[0].name, 'fun4');177  test.deepEqual(report.implieds[0].line, [14]);178  test.equal(report.unused.length, 3);179  test.done();180};181/**182 * The `proto` and `iterator` options allow you to prohibit the use of the183 * special `__proto__` and `__iterator__` properties, respectively.184 */185exports.testProtoAndIterator = function (test) {186  var source = fs.readFileSync(__dirname + '/fixtures/protoiterator.js', 'utf8');187  var json = '{"__proto__": true, "__iterator__": false, "_identifier": null, "property": 123}';188  // JSHint should not allow the `__proto__` and189  // `__iterator__` properties by default190  TestRun(test)191    .addError(7, "The '__proto__' property is deprecated.")192    .addError(8, "The '__proto__' property is deprecated.")193    .addError(10, "The '__proto__' property is deprecated.")194    .addError(27, "'__iterator__' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")195    .addError(33, "The '__proto__' property is deprecated.")196    .addError(37, "The '__proto__' property is deprecated.")197    .test(source, {es3: true});198  TestRun(test)199    .addError(1, "The '__proto__' key may produce unexpected results.")200    .addError(1, "The '__iterator__' key may produce unexpected results.")201    .test(json, {es3: true});202  // Should not report any errors when proto and iterator203  // options are on204  TestRun("source").test(source, { es3: true, proto: true, iterator: true });205  TestRun("json").test(json, { es3: true, proto: true, iterator: true });206  test.done();207};208/**209 * The `camelcase` option allows you to enforce use of the camel case convention.210 */211exports.testCamelcase = function (test) {212  var source = fs.readFileSync(__dirname + '/fixtures/camelcase.js', 'utf8');213  // By default, tolerate arbitrary identifiers214  TestRun(test)215    .test(source, {es3: true});216  // Require identifiers in camel case if camelcase is true217  TestRun(test)218    .addError(5, "Identifier 'Foo_bar' is not in camel case.")219    .addError(5, "Identifier 'test_me' is not in camel case.")220    .addError(6, "Identifier 'test_me' is not in camel case.")221    .addError(6, "Identifier 'test_me' is not in camel case.")222    .addError(13, "Identifier 'test_1' is not in camel case.")223    .test(source, { es3: true, camelcase: true });224  test.done();225};226/**227 * Option `curly` allows you to enforce the use of curly braces around228 * control blocks. JavaScript allows one-line blocks to go without curly229 * braces but some people like to always use curly bracse. This option is230 * for them.231 *232 * E.g.:233 *   if (cond) return;234 *     vs.235 *   if (cond) { return; }236 */237exports.curly = function (test) {238  var src  = fs.readFileSync(__dirname + '/fixtures/curly.js', 'utf8'),239    src1 = fs.readFileSync(__dirname + '/fixtures/curly2.js', 'utf8');240  // By default, tolerate one-line blocks since they are valid JavaScript241  TestRun(test).test(src, {es3: true});242  TestRun(test).test(src1, {es3: true});243  // Require all blocks to be wrapped with curly braces if curly is true244  TestRun(test)245    .addError(2, "Expected '{' and instead saw 'return'.")246    .addError(5, "Expected '{' and instead saw 'doSomething'.")247    .addError(8, "Expected '{' and instead saw 'doSomething'.")248    .addError(11, "Expected '{' and instead saw 'doSomething'.")249    .test(src, { es3: true, curly: true });250  TestRun(test).test(src1, { es3: true, curly: true });251  test.done();252};253/** Option `noempty` prohibits the use of empty blocks. */254exports.noempty = function (test) {255  var code = 'for (;;) {}';256  // By default, tolerate empty blocks since they are valid JavaScript257  TestRun(test).test(code, { es3: true });258  // Do not tolerate, when noempty is true259  TestRun(test)260    .addError(1, 'Empty block.')261    .test(code, { es3: true, noempty: true });262  test.done();263};264/**265 * Option `noarg` prohibits the use of arguments.callee and arguments.caller.266 * JSHint allows them by default but you have to know what you are doing since:267 *  - They are not supported by all JavaScript implementations268 *  - They might prevent an interpreter from doing some optimization tricks269 *  - They are prohibited in the strict mode270 */271exports.noarg = function (test) {272  var src = fs.readFileSync(__dirname + '/fixtures/noarg.js', 'utf8');273  // By default, tolerate both arguments.callee and arguments.caller274  TestRun(test).test(src, { es3: true });275  // Do not tolerate both .callee and .caller when noarg is true276  TestRun(test)277    .addError(2, 'Avoid arguments.callee.')278    .addError(6, 'Avoid arguments.caller.')279    .test(src, { es3: true, noarg: true });280  test.done();281};282/** Option `nonew` prohibits the use of constructors for side-effects */283exports.nonew = function (test) {284  var code  = "new Thing();",285    code1 = "var obj = new Thing();";286  TestRun(test).test(code, { es3: true });287  TestRun(test).test(code1, { es3: true });288  TestRun(test)289    .addError(1, "Do not use 'new' for side effects.", {290      character: 1291    })292    .test(code, { es3: true, nonew: true });293  test.done();294};295exports.shelljs = function (test) {296  var src = fs.readFileSync(__dirname + '/fixtures/shelljs.js', 'utf8');297  TestRun(test, 1)298    .addError(1, "'target' is not defined.")299    .addError(3, "'echo' is not defined.")300    .addError(4, "'exit' is not defined.")301    .addError(5, "'cd' is not defined.")302    .addError(6, "'pwd' is not defined.")303    .addError(7, "'ls' is not defined.")304    .addError(8, "'find' is not defined.")305    .addError(9, "'cp' is not defined.")306    .addError(10, "'rm' is not defined.")307    .addError(11, "'mv' is not defined.")308    .addError(12, "'mkdir' is not defined.")309    .addError(13, "'test' is not defined.")310    .addError(14, "'cat' is not defined.")311    .addError(15, "'sed' is not defined.")312    .addError(16, "'grep' is not defined.")313    .addError(17, "'which' is not defined.")314    .addError(18, "'dirs' is not defined.")315    .addError(19, "'pushd' is not defined.")316    .addError(20, "'popd' is not defined.")317    .addError(21, "'env' is not defined.")318    .addError(22, "'exec' is not defined.")319    .addError(23, "'chmod' is not defined.")320    .addError(24, "'config' is not defined.")321    .addError(25, "'error' is not defined.")322    .addError(26, "'tempdir' is not defined.")323    .addError(29, "'require' is not defined.")324    .addError(30, "'module' is not defined.")325    .addError(31, "'process' is not defined.")326    .test(src, { undef: true });327  TestRun(test, 2)328    .test(src, { undef: true, shelljs: true });329  test.done();330};331// Option `asi` allows you to use automatic-semicolon insertion332exports.asi = function (test) {333  var src = fs.readFileSync(__dirname + '/fixtures/asi.js', 'utf8');334  TestRun(test, 1)335    .addError(2, "Missing semicolon.")336    .addError(4, "Missing semicolon.")337    .addError(5, "Missing semicolon.")338    .addError(9, "Line breaking error 'continue'.")339    .addError(9, "Missing semicolon.")340    .addError(10, "Missing semicolon.")341    .addError(11, "Line breaking error 'break'.")342    .addError(11, "Missing semicolon.")343    .addError(12, "Missing semicolon.")344    .addError(16, "Missing semicolon.")345    .addError(17, "Missing semicolon.")346    .addError(19, "Line breaking error 'break'.")347    .addError(19, "Missing semicolon.")348    .addError(21, "Line breaking error 'break'.")349    .addError(21, "Missing semicolon.")350    .addError(25, "Missing semicolon.")351    .addError(26, "Missing semicolon.", { character: 10 })352    .addError(27, "Missing semicolon.", { character: 12 })353    .addError(28, "Missing semicolon.", { character: 12 })354    .test(src, { es3: true });355  TestRun(test, 2)356    .addError(2, "Missing semicolon.") // throw on "use strict", even option asi is used357    .test(src, { es3: true, asi: true });358  test.done();359};360// Option `asi` extended for safety -- warn in scenarios that would be unsafe when using asi.361exports.safeasi = function (test) {362  var src = fs.readFileSync(__dirname + '/fixtures/safeasi.js', 'utf8');363  TestRun(test, 1)364    // TOOD consider setting an option to suppress these errors so that365    // the tests don't become tightly interdependent366    .addError(10, "Bad line breaking before '/'.")367    .addError(10, "Expected an identifier and instead saw '.'.")368    .addError(10, "Expected an assignment or function call and instead saw an expression.")369    .addError(10, "Missing semicolon.")370    .addError(10, "Missing semicolon.")371    .addError(11, "Missing semicolon.")372    .addError(21, "Missing semicolon.")373    .test(src, {});374  TestRun(test, 2)375    .addError(5, "Bad line breaking before '('.")376    .addError(8, "Bad line breaking before '('.")377    .addError(10, "Bad line breaking before '/'.")378    .addError(10, "Bad line breaking before '/'.")379    .addError(10, "Expected an identifier and instead saw '.'.")380    .addError(10, "Expected an assignment or function call and instead saw an expression.")381    .test(src, { asi: true });382  test.done();383};384/** Option `lastsemic` allows you to skip the semicolon after last statement in a block,385  * if that statement is followed by the closing brace on the same line. */386exports.lastsemic = function (test) {387  var src = fs.readFileSync(__dirname + '/fixtures/lastsemic.js', 'utf8');388  // without lastsemic389  TestRun(test)390    .addError(2, "Missing semicolon.") // missing semicolon in the middle of a block391    .addError(4, "Missing semicolon.") // missing semicolon in a one-liner function392    .addError(5, "Missing semicolon.") // missing semicolon at the end of a block393    .test(src, {es3: true});394  // with lastsemic395  TestRun(test)396    .addError(2, "Missing semicolon.")397    .addError(5, "Missing semicolon.")398    .test(src, { es3: true, lastsemic: true });399  // this line is valid now: [1, 2, 3].forEach(function(i) { print(i) });400  // line 5 isn't, because the block doesn't close on the same line401  test.done();402};403/**404 * Option `expr` allows you to use ExpressionStatement as a Program code.405 *406 * Even though ExpressionStatement as a Program (i.e. without assingment407 * of its result) is a valid JavaScript, more often than not it is a typo.408 * That's why by default JSHint complains about it. But if you know what409 * are you doing, there is nothing wrong with it.410 */411exports.expr = function (test) {412  var exps = [413    "obj && obj.method && obj.method();",414    "myvar && func(myvar);",415    "1;",416    "true;",417    "+function (test) {};"418  ];419  for (var i = 0, exp; exp = exps[i]; i += 1) {420    TestRun(test)421      .addError(1, 'Expected an assignment or function call and instead saw an expression.')422      .test(exp, { es3: true });423  }424  for (i = 0, exp = null; exp = exps[i]; i += 1) {425    TestRun(test).test(exp, { es3: true, expr: true });426  }427  test.done();428};429// Option `undef` requires you to always define variables you use.430exports.undef = function (test) {431  var src = fs.readFileSync(__dirname + '/fixtures/undef.js', 'utf8');432  // Make sure there are no other errors433  TestRun(test).test(src, { es3: true });434  // Make sure it fails when undef is true435  TestRun(test)436    .addError(1, "'undef' is not defined.")437    .addError(5, "'undef' is not defined.")438    .addError(6, "'undef' is not defined.")439    .addError(8, "'undef' is not defined.")440    .addError(9, "'undef' is not defined.")441    .addError(13, "'localUndef' is not defined.")442    .addError(18, "'localUndef' is not defined.")443    .addError(19, "'localUndef' is not defined.")444    .addError(21, "'localUndef' is not defined.")445    .addError(22, "'localUndef' is not defined.")446    .test(src, { es3: true, undef: true });447  // Regression test for GH-668.448  src = fs.readFileSync(__dirname + "/fixtures/gh668.js", "utf8");449  test.ok(JSHINT(src, { undef: true }));450  test.ok(!JSHINT.data().implieds);451  test.ok(JSHINT(src));452  test.ok(!JSHINT.data().implieds);453  test.done();454};455exports.unused = function (test) {456  var src = fs.readFileSync(__dirname + '/fixtures/unused.js', 'utf8');457  TestRun(test).test(src, { esnext: true });458  var var_errors = [459    [1, "'a' is defined but never used."],460    [7, "'c' is defined but never used."],461    [15, "'foo' is defined but never used."],462    [20, "'bar' is defined but never used."],463    [22, "'i' is defined but never used."],464    [36, "'cc' is defined but never used."],465    [39, "'dd' is defined but never used."]466  ];467  var last_param_errors = [468    [6, "'f' is defined but never used."],469    [22, "'i' is defined but never used."],470    [28, "'a' is defined but never used."],471    [28, "'b' is defined but never used."],472    [28, "'c' is defined but never used."]473  ];474  var all_param_errors = [475    [15, "'err' is defined but never used."],476    [22, "'i' is defined but never used."],477    [28, "'a' is defined but never used."],478    [28, "'b' is defined but never used."],479    [28, "'c' is defined but never used."]480  ];481  var true_run = TestRun(test, {esnext: true});482  var_errors.concat(last_param_errors).forEach(function (e) {483    true_run.addError.apply(true_run, e);484  });485  true_run.test(src, { esnext: true, unused: true });486  test.ok(!JSHINT(src, { esnext: true, unused: true }));487  // Test checking all function params via unused="strict"488  var all_run = TestRun(test);489  var_errors.concat(last_param_errors, all_param_errors).forEach(function (e) {490    all_run.addError.apply(true_run, e);491  });492  all_run.test(src, { esnext: true, unused: "strict"});493  // Test checking everything except function params494  var vars_run = TestRun(test);495  var_errors.forEach(function (e) { vars_run.addError.apply(vars_run, e); });496  vars_run.test(src, { esnext: true, unused: "vars"});497  var unused = JSHINT.data().unused;498  test.equal(12, unused.length);499  test.ok(unused.some(function (err) { return err.line === 1 && err.character == 5 && err.name === "a"; }));500  test.ok(unused.some(function (err) { return err.line === 6 && err.character == 18 && err.name === "f"; }));501  test.ok(unused.some(function (err) { return err.line === 7 && err.character == 9 && err.name === "c"; }));502  test.ok(unused.some(function (err) { return err.line === 15 && err.character == 10 && err.name === "foo"; }));503  test.done();504};505// Regressions for "unused" getting overwritten via comment (GH-778)506exports['unused overrides'] = function (test) {507  var code;508  code = ['function foo(a) {', '/*jshint unused:false */', '}', 'foo();'];509  TestRun(test).test(code, {es3: true, unused: true});510  code = ['function foo(a, b, c) {', '/*jshint unused:vars */', 'var i = b;', '}', 'foo();'];511  TestRun(test)512    .addError(3, "'i' is defined but never used.")513    .test(code, {es3: true, unused: true});514  code = ['function foo(a, b, c) {', '/*jshint unused:true */', 'var i = b;', '}', 'foo();'];515  TestRun(test)516    .addError(1, "'c' is defined but never used.")517    .addError(3, "'i' is defined but never used.")518    .test(code, {es3: true, unused: "strict"});519  code = ['function foo(a, b, c) {', '/*jshint unused:strict */', 'var i = b;', '}', 'foo();'];520  TestRun(test)521    .addError(1, "'a' is defined but never used.")522    .addError(1, "'c' is defined but never used.")523    .addError(3, "'i' is defined but never used.")524    .test(code, {es3: true, unused: true});525  code = ['/*jshint unused:vars */', 'function foo(a, b) {}', 'foo();'];526  TestRun(test).test(code, {es3: true, unused: "strict"});527  code = ['/*jshint unused:vars */', 'function foo(a, b) {', 'var i = 3;', '}', 'foo();'];528  TestRun(test)529    .addError(3, "'i' is defined but never used.")530    .test(code, {es3: true, unused: "strict"});531  test.done();532};533// Regression test for `undef` to make sure that ...534exports['undef in a function scope'] = function (test) {535  var src = fixture('undef_func.js');536  // Make sure that the lint is clean with and without undef.537  TestRun(test).test(src, {es3: true});538  TestRun(test).test(src, {es3: true, undef: true });539  test.done();540};541/** Option `scripturl` allows the use of javascript-type URLs */542exports.scripturl = function (test) {543  var code = [544      "var foo = { 'count': 12, 'href': 'javascript:' };",545      "foo = 'javascript:' + 'xyz';"546    ],547    src = fs.readFileSync(__dirname + '/fixtures/scripturl.js', 'utf8');548  // Make sure there is an error549  TestRun(test)550    .addError(1, "Script URL.")551    .addError(2, "Script URL.") // 2 times?552    .addError(2, "JavaScript URL.")553    .test(code, {es3: true});554  // Make sure the error goes away when javascript URLs are tolerated555  TestRun(test).test(code, { es3: true, scripturl: true });556  // Make sure an error does not exist for labels that look like URLs (GH-1013)557  TestRun(test)558    .test(src, {es3: true});559  test.done();560};561/**562 * Option `forin` disallows the use of for in loops without hasOwnProperty.563 *564 * The for in statement is used to loop through the names of properties565 * of an object, including those inherited through the prototype chain.566 * The method hasOwnPropery is used to check if the property belongs to567 * an object or was inherited through the prototype chain.568 */569exports.forin = function (test) {570  var src = fs.readFileSync(__dirname + '/fixtures/forin.js', 'utf8');571  var msg = 'The body of a for in should be wrapped in an if statement to filter unwanted ' +572        'properties from the prototype.';573  // Make sure there are no other errors574  TestRun(test).test(src, {es3: true});575  // Make sure it fails when forin is true576  TestRun(test)577    .addError(15, msg)578    .addError(23, msg)579    .addError(37, msg)580    .addError(43, msg)581    .addError(73, msg)582    .test(src, { es3: true, forin: true });583  test.done();584};585/**586 * Option `loopfunc` allows you to use function expression in the loop.587 * E.g.:588 *   while (true) x = function (test) {};589 *590 * This is generally a bad idea since it is too easy to make a591 * closure-related mistake.592 */593exports.loopfunc = function (test) {594  var src = fs.readFileSync(__dirname + '/fixtures/loopfunc.js', 'utf8');595  // By default, not functions are allowed inside loops596  TestRun(test)597    .addError(2, "Don't make functions within a loop.")598    .addError(6, "Don't make functions within a loop.")599    .addError(10, "Function declarations should not be placed in blocks. Use a function " +600            "expression or move the statement to the top of the outer function.")601    .test(src, {es3: true});602  // When loopfunc is true, only function declaration should fail.603  // Expressions are okay.604  TestRun(test)605    .addError(10, "Function declarations should not be placed in blocks. Use a function " +606            "expression or move the statement to the top of the outer function.")607    .test(src, { es3: true, loopfunc: true });608  test.done();609};610/** Option `boss` unlocks some useful but unsafe features of JavaScript. */611exports.boss = function (test) {612  var src = fs.readFileSync(__dirname + '/fixtures/boss.js', 'utf8');613  // By default, warn about suspicious assignments614  TestRun(test)615    .addError(1, 'Expected a conditional expression and instead saw an assignment.')616    .addError(4, 'Expected a conditional expression and instead saw an assignment.')617    .addError(7, 'Expected a conditional expression and instead saw an assignment.')618    .addError(12, 'Expected a conditional expression and instead saw an assignment.')619    // GH-657620    .addError(14, 'Expected a conditional expression and instead saw an assignment.')621    .addError(17, 'Expected a conditional expression and instead saw an assignment.')622    .addError(20, 'Expected a conditional expression and instead saw an assignment.')623    .addError(25, 'Expected a conditional expression and instead saw an assignment.')624    // GH-670625    .addError(28, "Did you mean to return a conditional instead of an assignment?")626    .addError(32, "Did you mean to return a conditional instead of an assignment?")627    .test(src, {es3: true});628  // But if you are the boss, all is good629  TestRun(test).test(src, { es3: true, boss: true });630  test.done();631};632/**633 * Options `eqnull` allows you to use '== null' comparisons.634 * It is useful when you want to check if value is null _or_ undefined.635 */636exports.eqnull = function (test) {637  var code = [638    'if (e == null) doSomething();',639    'if (null == e) doSomething();',640    'if (e != null) doSomething();',641    'if (null != e) doSomething();',642  ];643  // By default, warn about `== null` comparison644  TestRun(test)645    .addError(1, "Use '===' to compare with 'null'.")646    .addError(2, "Use '===' to compare with 'null'.")647    .addError(3, "Use '!==' to compare with 'null'.")648    .addError(4, "Use '!==' to compare with 'null'.")649    .test(code, {es3: true});650  // But when `eqnull` is true, no questions asked651  TestRun(test).test(code, { es3: true, eqnull: true });652  // Make sure that `eqnull` has precedence over `eqeqeq`653  TestRun(test).test(code, { es3: true, eqeqeq: true, eqnull: true });654  test.done();655};656/**657 * Option `supernew` allows you to use operator `new` with anonymous functions658 * and objects without invocation.659 *660 * Ex.:661 *   new function (test) { ... };662 *   new Date;663 */664exports.supernew = function (test) {665  var src = fs.readFileSync(__dirname + '/fixtures/supernew.js', 'utf8');666  TestRun(test)667    .addError(1, "Weird construction. Is 'new' necessary?")668    .addError(9, "Missing '()' invoking a constructor.", { character: 1 })669    .addError(11, "Missing '()' invoking a constructor.", {670      character: 13671    })672    .test(src, {es3: true});673  TestRun(test).test(src, { es3: true, supernew: true });674  test.done();675};676/** Option `bitwise` disallows the use of bitwise operators. */677exports.bitwise = function (test) {678  var ops = [ '&', '|', '^', '<<', '>>', '>>>' ];679  var moreTests = [680    'var c = ~a;',681    'c &= 2;'682  ];683  // By default allow bitwise operators684  for (var i = 0, op; op = ops[i]; i += 1) {685    TestRun(test).test('var c = a ' + op + ' b;', {es3: true});686  }687  TestRun(test).test(moreTests, {es3: true});688  for (i = 0, op = null; op = ops[i]; i += 1) {689    TestRun(test)690      .addError(1, "Unexpected use of '" + op + "'.")691      .test('var c = a ' + op + ' b;', { es3: true, bitwise: true });692  }693  TestRun(test)694    .addError(1, "Unexpected '~'.")695    .addError(2, "Unexpected use of '&='.")696    .test(moreTests, { es3: true, bitwise: true });697  test.done();698};699/** Option `debug` allows the use of debugger statements. */700exports.debug = function (test) {701  var code = 'function test () { debugger; return true; }';702  // By default disallow debugger statements.703  TestRun(test)704    .addError(1, "Forgotten 'debugger' statement?")705    .test(code, {es3: true});706  // But allow them if debug is true.707  TestRun(test).test(code, { es3: true, debug: true });708  test.done();709};710/** `debugger` statements without semicolons are found on the correct line */711exports.debug = function (test) {712  var src = [713    "function test () {",714    "debugger",715    "return true; }"716  ];717  // Ensure we mark the correct line when finding debugger statements718  TestRun(test)719    .addError(2, "Forgotten 'debugger' statement?")720    .test(src, {es3: true, asi: true});721  test.done();722};723/** Option `eqeqeq` requires you to use === all the time. */724exports.eqeqeq = function (test) {725  var src = fs.readFileSync(__dirname + '/fixtures/eqeqeq.js', 'utf8');726  TestRun(test)727    .addError(8, "Use '===' to compare with 'null'.")728    .test(src, {es3: true});729  TestRun(test)730    .addError(2, "Expected '===' and instead saw '=='.")731    .addError(5, "Expected '!==' and instead saw '!='.")732    .addError(8, "Expected '===' and instead saw '=='.")733    .test(src, { es3: true, eqeqeq: true });734  test.done();735};736/** Option `evil` allows the use of eval. */737exports.evil = function (test) {738  var src = [739    "eval('hey();');",740    "document.write('');",741    "document.writeln('');",742    "window.execScript('xyz');",743    "new Function('xyz();');",744    "setTimeout('xyz();', 2);",745    "setInterval('xyz();', 2);",746    "var t = document['eval']('xyz');"747  ];748  TestRun(test)749    .addError(1, "eval can be harmful.")750    .addError(2, "document.write can be a form of eval.")751    .addError(3, "document.write can be a form of eval.")752    .addError(4, "eval can be harmful.")753    .addError(5, "The Function constructor is a form of eval.")754    .addError(6, "Implied eval. Consider passing a function instead of a string.")755    .addError(7, "Implied eval. Consider passing a function instead of a string.")756    .addError(8, "eval can be harmful.")757    .test(src, { es3: true, browser: true });758  TestRun(test).test(src, { es3: true, evil: true, browser: true });759  test.done();760};761/**762 * Option `immed` forces you to wrap immediate invocations in parens.763 *764 * Functions in JavaScript can be immediately invoce but that can confuse765 * readers of your code. To make it less confusing, wrap the invocations in766 * parens.767 *768 * E.g. (note the parens):769 *   var a = (function (test) {770 *     return 'a';771 *   }());772 *   console.log(a); // --> 'a'773 */774exports.immed = function (test) {775  var src = fs.readFileSync(__dirname + '/fixtures/immed.js', 'utf8');776  TestRun(test).test(src, {es3: true});777  TestRun(test)778    .addError(3, "Wrap an immediate function invocation in parens " +779           "to assist the reader in understanding that the expression " +780           "is the result of a function, and not the function itself.")781    .addError(13, "Wrapping non-IIFE function literals in parens is unnecessary.")782    .test(src, { es3: true, immed: true });783  // Regression for GH-900784  TestRun(test)785    .addError(1, "Expected an assignment or function call and instead saw an expression.")786    .addError(1, "Missing semicolon.")787    .addError(1, "Expected an identifier and instead saw ')'.")788    .addError(1, "Expected an assignment or function call and instead saw an expression.")789    .addError(1, "Unmatched '{'.")790    .addError(1, "Unmatched '('.")791    .addError(1, "Wrapping non-IIFE function literals in parens is unnecessary.")792    .addError(1, "Expected an assignment or function call and instead saw an expression.")793    .addError(1, "Missing semicolon.")794    .test("(function () { if (true) { }());", { es3: true, immed: true });795  test.done();796};797/** Option `plusplus` prohibits the use of increments/decrements. */798exports.plusplus = function (test) {799  var ops = [ '++', '--' ];800  for (var i = 0, op; op = ops[i]; i += 1) {801    TestRun(test).test('var i = j' + op + ';', {es3: true});802    TestRun(test).test('var i = ' + op + 'j;', {es3: true});803  }804  for (i = 0, op = null; op = ops[i]; i += 1) {805    TestRun(test)806      .addError(1, "Unexpected use of '" + op + "'.")807      .test('var i = j' + op + ';', { es3: true, plusplus: true });808    TestRun(test)809      .addError(1, "Unexpected use of '" + op + "'.")810      .test('var i = ' + op + 'j;', { es3: true, plusplus: true });811  }812  test.done();813};814/**815 * Option `newcap` requires constructors to be capitalized.816 *817 * Constructors are functions that are designed to be used with the `new` statement.818 * `new` creates a new object and binds it to the implied this parameter.819 * A constructor executed without new will have its this assigned to a global object,820 * leading to errors.821 *822 * Unfortunately, JavaScript gives us absolutely no way of telling if a function is a823 * constructor. There is a convention to capitalize all constructor names to prevent824 * those mistakes. This option enforces that convention.825 */826exports.newcap = function (test) {827  var src = fs.readFileSync(__dirname + '/fixtures/newcap.js', 'utf8');828  TestRun(test).test(src, {es3: true}); // By default, everything is fine829  // When newcap is true, enforce the conventions830  TestRun(test)831    .addError(1, 'A constructor name should start with an uppercase letter.')832    .addError(5, "Missing 'new' prefix when invoking a constructor.")833    .addError(10, "A constructor name should start with an uppercase letter.")834    .test(src, { es3: true, newcap: true });835  test.done();836};837/** Option `sub` allows all forms of subscription. */838exports.sub = function (test) {839  TestRun(test)840    .addError(1, "['prop'] is better written in dot notation.", {841      character: 17842    })843    .test("window.obj = obj['prop'];", {es3: true});844  TestRun(test).test("window.obj = obj['prop'];", { es3: true, sub: true });845  test.done();846};847/** Option `strict` requires you to use "use strict"; */848exports.strict = function (test) {849  var code  = "(function (test) { return; }());";850  var code1 = '(function (test) { "use strict"; return; }());';851  var src = fs.readFileSync(__dirname + '/fixtures/strict_violations.js', 'utf8');852  var src2 = fs.readFileSync(__dirname + '/fixtures/strict_incorrect.js', 'utf8');853  var src3 = fs.readFileSync(__dirname + '/fixtures/strict_newcap.js', 'utf8');854  TestRun(test).test(code, {es3: true});855  TestRun(test).test(code1, {es3: true});856  TestRun(test)857    .addError(1, 'Missing "use strict" statement.')858    .test(code, { es3: true, strict: true });859  TestRun(test).test(code1, { es3: true, strict: true });860  // Test for strict mode violations861  TestRun(test)862    .addError(4, 'Possible strict violation.')863    .addError(7, 'Strict violation.')864    .addError(8, 'Strict violation.')865    .test(src, { es3: true, strict: true });866  TestRun(test)867    .addError(4, 'Expected an assignment or function call and instead saw an expression.')868    .addError(9, 'Missing semicolon.')869    .addError(28, 'Expected an assignment or function call and instead saw an expression.')870    .addError(53, 'Expected an assignment or function call and instead saw an expression.')871    .test(src2, { es3: true, strict: false });872  TestRun(test)873    .addError(6, "Missing 'new' prefix when invoking a constructor.")874    .test(src3, {es3 : true});875  TestRun(test).test("var obj = Object({ foo: 'bar' });", { es3: true, strict: true });876  test.done();877};878/** Option `globalstrict` allows you to use global "use strict"; */879exports.globalstrict = function (test) {880  var code = [881    '"use strict";',882    'function hello() { return; }'883  ];884  TestRun(test)885    .addError(1, 'Use the function form of "use strict".')886    .test(code, { es3: true, strict: true });887  TestRun(test).test(code, { es3: true, globalstrict: true });888  // Check that globalstrict also enabled strict889  TestRun(test)890    .addError(1, 'Missing "use strict" statement.')891    .test(code[1], { es3: true, globalstrict: true });892  // Don't enforce "use strict"; if strict has been explicitly set to false893  TestRun(test).test(code[1], { es3: true, globalstrict: true, strict: false });894  // Check that we can detect missing "use strict"; statement for code that is895  // not inside a function896  code = [897    "var a = 1;",898    "a += 1;",899    "function func() {}"900  ];901  TestRun(test)902    .addError(1, 'Missing "use strict" statement.')903    .test(code, { globalstrict: true, strict: true });904  // globalscript does not prevent you from using only the function-mode905  // "use strict";906  code = '(function (test) { "use strict"; return; }());';907  TestRun(test).test(code, { globalstrict: true, strict: true });908  test.done();909};910/** Option `laxbreak` allows you to insert newlines before some operators. */911exports.laxbreak = function (test) {912  var src = fs.readFileSync(__dirname + '/fixtures/laxbreak.js', 'utf8');913  TestRun(test)914    .addError(2, "Bad line breaking before ','.")915    .addError(3, "Comma warnings can be turned off with 'laxcomma'.")916    .addError(12, "Bad line breaking before ','.")917    .test(src, { es3: true });918  var ops = [ '||', '&&', '*', '/', '%', '+', '-', '>=',919        '==', '===', '!=', '!==', '>', '<', '<=', 'instanceof' ];920  for (var i = 0, op, code; op = ops[i]; i += 1) {921    code = ['var a = b ', op + ' c;'];922    TestRun(test)923      .addError(2, "Bad line breaking before '" + op + "'.")924      .test(code, { es3: true });925    TestRun(test).test(code, { es3: true, laxbreak: true });926  }927  code = [ 'var a = b ', '? c : d;' ];928  TestRun(test)929    .addError(2, "Bad line breaking before '?'.")930    .test(code, { es3: true });931  TestRun(test).test(code, { es3: true, laxbreak: true });932  test.done();933};934exports.validthis = function (test) {935  var src = fs.readFileSync(__dirname + '/fixtures/strict_this.js', 'utf8');936  TestRun(test)937    .addError(8, "Possible strict violation.")938    .addError(9, "Possible strict violation.")939    .addError(11, "Possible strict violation.")940    .test(src, {es3: true});941  src = fs.readFileSync(__dirname + '/fixtures/strict_this2.js', 'utf8');942  TestRun(test).test(src, {es3: true});943  // Test for erroneus use of validthis944  var code = ['/*jshint validthis:true */', 'hello();'];945  TestRun(test)946    .addError(1, "Option 'validthis' can't be used in a global scope.")947    .test(code, {es3: true});948  code = ['function x() {', '/*jshint validthis:heya */', 'hello();', '}'];949  TestRun(test)950    .addError(2, "Bad option value.")951    .test(code, {es3: true});952  test.done();953};954/*955 * Test string relevant options956 *   multistr   allows multiline strings957 */958exports.strings = function (test) {959  var src = fs.readFileSync(__dirname + '/fixtures/strings.js', 'utf8');960  TestRun(test)961    .addError(9, "Unclosed string.")962    .addError(10, "Unclosed string.")963    .addError(15, "Unclosed string.")964    .addError(23, "Octal literals are not allowed in strict mode.")965    .test(src, { es3: true, multistr: true });966  TestRun(test)967    .addError(3, "Bad escaping of EOL. Use option multistr if needed.")968    .addError(4, "Bad escaping of EOL. Use option multistr if needed.")969    .addError(9, "Unclosed string.")970    .addError(10, "Unclosed string.")971    .addError(14, "Bad escaping of EOL. Use option multistr if needed.")972    .addError(15, "Unclosed string.")973    .addError(23, "Octal literals are not allowed in strict mode.")974    .test(src, { es3: true });975  test.done();976};977/*978 * Test the `quotmark` option979 *   quotmark   quotation mark or true (=ensure consistency)980 */981exports.quotes = function (test) {982  var src = fs.readFileSync(__dirname + '/fixtures/quotes.js', 'utf8');983  var src2 = fs.readFileSync(__dirname + '/fixtures/quotes2.js', 'utf8');984  TestRun(test)985    .test(src, { es3: true });986  TestRun(test)987    .addError(3, "Mixed double and single quotes.")988    .test(src, { es3: true, quotmark: true });989  TestRun(test)990    .addError(3, "Strings must use singlequote.")991    .test(src, { es3: true, quotmark: 'single' });992  TestRun(test)993    .addError(2, "Strings must use doublequote.")994    .test(src, { es3: true, quotmark: 'double' });995  // test multiple runs (must have the same result)996  var run = TestRun(test);997  run.addError(3, "Mixed double and single quotes.")998    .test(src, { es3: true, quotmark: true });999  run.addError(3, "Mixed double and single quotes.")1000    .test(src2, { es3: true, quotmark: true });1001  test.done();1002};1003// Test the `quotmark` option when defined as a JSHint comment.1004exports.quotesInline = function (test) {1005  TestRun(test)1006    .addError(6, "Strings must use doublequote.")1007    .addError(14, "Strings must use singlequote.")1008    .addError(21, "Mixed double and single quotes.")1009    .addError(32, "Bad option value.")1010    .test(fs.readFileSync(__dirname + "/fixtures/quotes3.js", "utf8"));1011  test.done();1012};1013// Test the `quotmark` option along with TemplateLiterals.1014exports.quotesAndTemplateLiterals = function (test) {1015  var src = fs.readFileSync(__dirname + '/fixtures/quotes4.js', 'utf8');1016  // Without esnext1017  TestRun(test)1018    .addError(2, "Unexpected '`'.")1019    .addError(2, "Unexpected early end of program.")1020    .addError(2, "Expected an identifier and instead saw '(end)'.")1021    .addError(2, "Missing semicolon.")1022    .test(src);1023  // With esnext1024  TestRun(test)1025    .test(src, {esnext: true});1026  // With esnext and single quotemark1027  TestRun(test)1028    .test(src, {esnext: true, quotmark: 'single'});1029  // With esnext and double quotemark1030  TestRun(test)1031    .addError(1, "Strings must use doublequote.")1032    .test(src, {esnext: true, quotmark: 'double'});1033  test.done();1034};1035exports.scope = function (test) {1036  var src = fs.readFileSync(__dirname + '/fixtures/scope.js', 'utf8');1037  TestRun(test, 1)1038    .addError(11, "'j' used out of scope.") // 3x1039    .addError(12, "'x' used out of scope.")1040    .addError(20, "'aa' used out of scope.")1041    .addError(27, "'bb' used out of scope.")1042    .addError(37, "'cc' is not defined.")1043    .addError(42, "'bb' is not defined.")1044    .addError(53, "'xx' used out of scope.")1045    .addError(54, "'yy' used out of scope.")1046    .test(src, {es3: true});1047  TestRun(test, 2)1048    .addError(37, "'cc' is not defined.")1049    .addError(42, "'bb' is not defined.")1050    .test(src, { es3: true, funcscope: true });1051  test.done();1052};1053/*1054 * Tests `esnext` and `moz` options.1055 *1056 * This test simply makes sure that options are recognizable1057 * and do not reset ES5 mode (see GH-1068)1058 *1059 */1060exports.esnext = function (test) {1061  var src = fs.readFileSync(__dirname + '/fixtures/const.js', 'utf8');1062  var code = [1063    'const myConst = true;',1064    'const foo = 9;',1065    'var myConst = function (test) { };',1066    'foo = "hello world";',1067    'var a = { get x() {} };'1068  ];1069  TestRun(test)1070    .addError(21, "const 'immutable4' is initialized to 'undefined'.")1071    .test(src, { esnext: true });1072  TestRun(test)1073    .addError(21, "const 'immutable4' is initialized to 'undefined'.")1074    .test(src, { moz: true });1075  TestRun(test)1076    .addError(3, "const 'myConst' has already been declared.")1077    .addError(4, "Attempting to override 'foo' which is a constant.")1078    .test(code, { esnext: true });1079  TestRun(test)1080    .addError(3, "const 'myConst' has already been declared.")1081    .addError(4, "Attempting to override 'foo' which is a constant.")1082    .test(code, { moz: true });1083  test.done();1084};1085/*1086 * Tests the `maxlen` option1087 */1088exports.maxlen = function (test) {1089  var src = fs.readFileSync(__dirname + '/fixtures/maxlen.js', 'utf8');1090  TestRun(test)1091    .addError(3, "Line is too long.")1092    .addError(4, "Line is too long.")1093    .addError(5, "Line is too long.")1094    .addError(6, "Line is too long.")1095    // line 7 and more are exceptions and won't trigger the error1096    .test(src, { es3: true, maxlen: 23 });1097  test.done();1098};1099/*1100 * Tests the `laxcomma` option1101 */1102exports.laxcomma = function (test) {1103  var src = fs.readFileSync(__dirname + '/fixtures/laxcomma.js', 'utf8');1104  // All errors.1105  TestRun(test)1106    .addError(1, "Bad line breaking before ','.")1107    .addError(2, "Comma warnings can be turned off with 'laxcomma'.")1108    .addError(2, "Bad line breaking before ','.")1109    .addError(6, "Bad line breaking before ','.")1110    .addError(10, "Bad line breaking before '&&'.")1111    .addError(15, "Bad line breaking before '?'.")1112    .test(src, {es3: true});1113  // Allows bad line breaking, but not on commas.1114  TestRun(test)1115    .addError(1, "Bad line breaking before ','.")1116    .addError(2, "Comma warnings can be turned off with 'laxcomma'.")1117    .addError(2, "Bad line breaking before ','.")1118    .addError(6, "Bad line breaking before ','.")1119    .test(src, {es3: true, laxbreak: true });1120  // Allows comma-first style but warns on bad line breaking1121  TestRun(test)1122    .addError(10, "Bad line breaking before '&&'.")1123    .addError(15, "Bad line breaking before '?'.")1124    .test(src, {es3: true, laxcomma: true });1125  // No errors if both laxbreak and laxcomma are turned on1126  TestRun(test).test(src, {es3: true, laxbreak: true, laxcomma: true });1127  test.done();1128};1129/*1130 * Tests the `browser` option1131 */1132exports.browser = function (test) {1133  var src = fs.readFileSync(__dirname + '/fixtures/browser.js', 'utf8');1134  TestRun(test)1135    .addError(2, "'atob' is not defined.")1136    .addError(3, "'btoa' is not defined.")1137    .addError(6, "'DOMParser' is not defined.")1138    .addError(10, "'XMLSerializer' is not defined.")1139    .addError(14, "'NodeFilter' is not defined.")1140    .addError(15, "'Node' is not defined.")1141    .addError(18, "'MutationObserver' is not defined.")1142    .addError(21, "'SVGElement' is not defined.")1143    .test(src, {es3: true, undef: true });1144  TestRun(test).test(src, {es3: true, browser: true, undef: true });1145  test.done();1146};1147exports.unnecessarysemicolon = function (test) {1148  var code = [1149    "function foo() {",1150    "    var a;;",1151    "}"1152  ];1153  TestRun(test)1154    .addError(2, "Unnecessary semicolon.")1155    .test(code, {es3: true});1156  test.done();1157};1158exports.blacklist = function (test) {1159  var src = fs.readFileSync(__dirname + '/fixtures/browser.js', 'utf8');1160  var code = [1161    '/*jshint browser: true */',1162    '/*global -event, bar, -btoa */',1163    'var a = event.hello();',1164    'var c = foo();',1165    'var b = btoa(1);',1166    'var d = bar();'1167  ];1168  // make sure everything is ok1169  TestRun(test).test(src, { es3: true, undef: true, browser: true });