• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

jshint / jshint / 2952

pending completion
2952

push

travis-ci

rwaldron
Coverage: add "istanbul ignore next" to lines that are not currently covered by tests

4476 of 4477 relevant lines covered (99.98%)

22871.69 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

99.97
/src/jshint.js
1
/*!
2
 * JSHint, by JSHint Community.
3
 *
4
 * This file (and this file only) is licensed under the same slightly modified
5
 * MIT license that JSLint is. It stops evil-doers everywhere:
6
 *
7
 *   Copyright (c) 2002 Douglas Crockford  (www.JSLint.com)
8
 *
9
 *   Permission is hereby granted, free of charge, to any person obtaining
10
 *   a copy of this software and associated documentation files (the "Software"),
11
 *   to deal in the Software without restriction, including without limitation
12
 *   the rights to use, copy, modify, merge, publish, distribute, sublicense,
13
 *   and/or sell copies of the Software, and to permit persons to whom
14
 *   the Software is furnished to do so, subject to the following conditions:
15
 *
16
 *   The above copyright notice and this permission notice shall be included
17
 *   in all copies or substantial portions of the Software.
18
 *
19
 *   The Software shall be used for Good, not Evil.
20
 *
21
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
 *   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
 *   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
 *   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
 *   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26
 *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27
 *   DEALINGS IN THE SOFTWARE.
28
 *
29
 */
30

31
/*jshint quotmark:double */
32
/*exported console */
33

34
var _            = require("lodash");
6✔
35
var events       = require("events");
6✔
36
var vars         = require("./vars.js");
6✔
37
var messages     = require("./messages.js");
6✔
38
var Lexer        = require("./lex.js").Lexer;
6✔
39
var reg          = require("./reg.js");
6✔
40
var state        = require("./state.js").state;
6✔
41
var style        = require("./style.js");
6✔
42
var options      = require("./options.js");
6✔
43
var scopeManager = require("./scope-manager.js");
6✔
44
var prodParams   = require("./prod-params.js");
6✔
45

46
// We need this module here because environments such as IE and Rhino
47
// don't necessarilly expose the 'console' API and browserify uses
48
// it to log things. It's a sad state of affair, really.
49
var console = require("console-browserify");
6✔
50

51
// We build the application inside a function so that we produce only a singleton
52
// variable. That function will be invoked immediately, and its return value is
53
// the JSHINT function itself.
54

55
var JSHINT = (function() {
6✔
56
  "use strict";
57

58
  var api, // Extension API
6✔
59

60
    // These are operators that should not be used with the ! operator.
61
    bang = {
62
      "<"  : true,
63
      "<=" : true,
64
      "==" : true,
65
      "===": true,
66
      "!==": true,
67
      "!=" : true,
68
      ">"  : true,
69
      ">=" : true,
70
      "+"  : true,
71
      "-"  : true,
72
      "*"  : true,
73
      "/"  : true,
74
      "%"  : true
75
    },
76

77
    declared, // Globals that were declared using /*global ... */ syntax.
78

79
    functions, // All of the functions
80

81
    inblock,
82
    indent,
83
    lookahead,
84
    lex,
85
    member,
86
    membersOnly,
87
    predefined,    // Global variables defined by option
88

89
    urls,
90

91
    extraModules = [],
92
    emitter = new events.EventEmitter();
93

94
  function checkOption(name, isStable, t) {
6✔
95
    var type, validNames;
14,070✔
96

97
    if (isStable) {
14,070✔
98
      type = "";
14,028✔
99
      validNames = options.validNames;
14,028✔
100
    } else {
101
      type = "unstable ";
42✔
102
      validNames = options.unstableNames;
42✔
103
    }
104

105
    name = name.trim();
14,070✔
106

107
    if (/^[+-]W\d{3}$/g.test(name)) {
14,070✔
108
      return true;
348✔
109
    }
110

111
    if (validNames.indexOf(name) === -1) {
13,722✔
112
      if (t.type !== "jslint" && !_.has(options.removed, name)) {
192✔
113
        error("E001", t, type, name);
144✔
114
        return false;
144✔
115
      }
116
    }
117

118
    return true;
13,578✔
119
  }
120

121
  function isString(obj) {
6✔
122
    return Object.prototype.toString.call(obj) === "[object String]";
9,660✔
123
  }
124

125
  function isIdentifier(tkn, value) {
6✔
126
    if (!tkn)
4,284✔
127
      return false;
72✔
128

129
    if (!tkn.identifier || tkn.value !== value)
4,212✔
130
      return false;
4,164✔
131

132
    return true;
48✔
133
  }
134

135
  /**
136
   * ES3 defined a set of "FutureReservedWords" in order "to allow for the
137
   * possibility of future adoption of [proposed] extensions."
138
   *
139
   * ES5 reduced the set of FutureReservedWords, in some cases by using them to
140
   * define new syntactic forms (e.g. `class` and `const`) and in other cases
141
   * by simply allowing their use as Identifiers (e.g. `int` and `goto`).
142
   * Separately, ES5 introduced new restrictions on certain tokens, but limited
143
   * the restriction to strict mode code (e.g. `let` and `yield`).
144
   *
145
   * This function determines if a given token describes a reserved word
146
   * according to the current state of the parser.
147
   *
148
   * @param {number} context - the parsing context; see `prod-params.js` for
149
   *                           more information
150
   * @param {Token} token
151
   */
152
  function isReserved(context, token) {
6✔
153
    if (!token.reserved) {
159,972✔
154
      return false;
115,182✔
155
    }
156
    var meta = token.meta;
44,790✔
157

158
    if (meta && meta.isFutureReservedWord) {
44,790✔
159
      if (state.inES5()) {
1,512✔
160
        // ES3 FutureReservedWord in an ES5 environment.
161
        if (!meta.es5) {
1,500✔
162
          return false;
396✔
163
        }
164

165
        if (token.isProperty) {
1,104✔
166
          return false;
12✔
167
        }
168
      }
169
    } else if (meta && meta.es5 && !state.inES5()) {
43,278✔
170
      return false;
210✔
171
    }
172

173
    // Some identifiers are reserved only within a strict mode environment.
174
    if (meta && meta.strictOnly && state.inES5()) {
44,172✔
175
      if (!state.option.strict && !state.isStrict()) {
4,014✔
176
        return false;
3,690✔
177
      }
178
    }
179

180
    if (token.id === "await" && (!(context & prodParams.async) && !state.option.module)) {
40,482✔
181
      return false;
942✔
182
    }
183

184
    return true;
39,540✔
185
  }
186

187
  function supplant(str, data) {
6✔
188
    return str.replace(/\{([^{}]*)\}/g, function(a, b) {
28,350✔
189
      var r = data[b];
32,622✔
190
      return typeof r === "string" || typeof r === "number" ? r : a;
32,622✔
191
    });
192
  }
193

194
  function combine(dest, src) {
6✔
195
    Object.keys(src).forEach(function(name) {
43,818✔
196
      if (_.has(JSHINT.blacklist, name)) return;
436,464✔
197
      dest[name] = src[name];
436,074✔
198
    });
199
  }
200

201
  function processenforceall() {
6✔
202
    if (state.option.enforceall) {
11,064✔
203
      for (var enforceopt in options.bool.enforcing) {
18✔
204
        if (state.option[enforceopt] === undefined &&
486✔
205
            !options.noenforceall[enforceopt]) {
206
          state.option[enforceopt] = true;
360✔
207
        }
208
      }
209
      for (var relaxopt in options.bool.relaxing) {
18✔
210
        if (state.option[relaxopt] === undefined) {
522✔
211
          state.option[relaxopt] = false;
456✔
212
        }
213
      }
214
    }
215
  }
216

217
  /**
218
   * Apply all linting options according to the status of the `state` object.
219
   */
220
  function applyOptions() {
6✔
221
    var badESOpt = null;
11,064✔
222
    processenforceall();
11,064✔
223

224
    /**
225
     * TODO: Remove in JSHint 3
226
     */
227
    badESOpt = state.inferEsVersion();
11,064✔
228
    if (badESOpt) {
11,064✔
229
      quit("E059", state.tokens.next, "esversion", badESOpt);
36✔
230
    }
231

232
    if (state.inES5()) {
11,028✔
233
      combine(predefined, vars.ecmaIdentifiers[5]);
8,586✔
234
    }
235

236
    if (state.inES6()) {
11,028✔
237
      combine(predefined, vars.ecmaIdentifiers[6]);
4,578✔
238
    }
239

240
    if (state.inES8()) {
11,028✔
241
      combine(predefined, vars.ecmaIdentifiers[8]);
618✔
242
    }
243

244
    /**
245
     * Use `in` to check for the presence of any explicitly-specified value for
246
     * `globalstrict` because both `true` and `false` should trigger an error.
247
     */
248
    if (state.option.strict === "global" && "globalstrict" in state.option) {
11,028✔
249
      quit("E059", state.tokens.next, "strict", "globalstrict");
36✔
250
    }
251

252
    if (state.option.module) {
10,992✔
253
      /**
254
       * TODO: Extend this restriction to *all* ES6-specific options.
255
       */
256
      if (!state.inES6()) {
180✔
257
        warning("W134", state.tokens.next, "module", 6);
12✔
258
      }
259
    }
260

261
    if (state.option.regexpu) {
10,992✔
262
      /**
263
       * TODO: Extend this restriction to *all* ES6-specific options.
264
       */
265
      if (!state.inES6()) {
24✔
266
        warning("W134", state.tokens.next, "regexpu", 6);
12✔
267
      }
268
    }
269

270
    if (state.option.couch) {
10,992✔
271
      combine(predefined, vars.couch);
6✔
272
    }
273

274
    if (state.option.qunit) {
10,992✔
275
      combine(predefined, vars.qunit);
6✔
276
    }
277

278
    if (state.option.rhino) {
10,992✔
279
      combine(predefined, vars.rhino);
6✔
280
    }
281

282
    if (state.option.shelljs) {
10,992✔
283
      combine(predefined, vars.shelljs);
6✔
284
      combine(predefined, vars.node);
6✔
285
    }
286
    if (state.option.typed) {
10,992✔
287
      combine(predefined, vars.typed);
6✔
288
    }
289

290
    if (state.option.phantom) {
10,992✔
291
      combine(predefined, vars.phantom);
48✔
292
    }
293

294
    if (state.option.prototypejs) {
10,992✔
295
      combine(predefined, vars.prototypejs);
6✔
296
    }
297

298
    if (state.option.node) {
10,992✔
299
      combine(predefined, vars.node);
156✔
300
      combine(predefined, vars.typed);
156✔
301
    }
302

303
    if (state.option.devel) {
10,992✔
304
      combine(predefined, vars.devel);
30✔
305
    }
306

307
    if (state.option.dojo) {
10,992✔
308
      combine(predefined, vars.dojo);
6✔
309
    }
310

311
    if (state.option.browser) {
10,992✔
312
      combine(predefined, vars.browser);
78✔
313
      combine(predefined, vars.typed);
78✔
314
    }
315

316
    if (state.option.browserify) {
10,992✔
317
      combine(predefined, vars.browser);
60✔
318
      combine(predefined, vars.typed);
60✔
319
      combine(predefined, vars.browserify);
60✔
320
    }
321

322
    if (state.option.nonstandard) {
10,992✔
323
      combine(predefined, vars.nonstandard);
6✔
324
    }
325

326
    if (state.option.jasmine) {
10,992✔
327
      combine(predefined, vars.jasmine);
6✔
328
    }
329

330
    if (state.option.jquery) {
10,992✔
331
      combine(predefined, vars.jquery);
6✔
332
    }
333

334
    if (state.option.mootools) {
10,992✔
335
      combine(predefined, vars.mootools);
6✔
336
    }
337

338
    if (state.option.worker) {
10,992✔
339
      combine(predefined, vars.worker);
6✔
340
    }
341

342
    if (state.option.wsh) {
10,992✔
343
      combine(predefined, vars.wsh);
6✔
344
    }
345

346
    if (state.option.yui) {
10,992✔
347
      combine(predefined, vars.yui);
6✔
348
    }
349

350
    if (state.option.mocha) {
10,992✔
351
      combine(predefined, vars.mocha);
6✔
352
    }
353
  }
354

355
  // Produce an error warning.
356
  function quit(code, token, a, b) {
6✔
357
    var percentage = Math.floor((token.line / state.lines.length) * 100);
606✔
358
    var message = messages.errors[code].desc;
606✔
359

360
    var exception = {
606✔
361
      name: "JSHintError",
362
      line: token.line,
363
      character: token.from,
364
      message: message + " (" + percentage + "% scanned).",
365
      raw: message,
366
      code: code,
367
      a: a,
368
      b: b
369
    };
370

371
    exception.reason = supplant(message, exception) + " (" + percentage +
606✔
372
      "% scanned).";
373

374
    throw exception;
606✔
375
  }
376

377
  function removeIgnoredMessages() {
6✔
378
    var ignored = state.ignoredLines;
27,768✔
379

380
    if (_.isEmpty(ignored)) return;
27,768✔
381
    JSHINT.errors = _.reject(JSHINT.errors, function(err) { return ignored[err.line] });
36✔
382
  }
383

384
  function warning(code, t, a, b, c, d) {
6✔
385
    var ch, l, w, msg;
27,954✔
386

387
    if (/^W\d{3}$/.test(code)) {
27,954✔
388
      if (state.ignored[code])
20,976✔
389
        return;
210✔
390

391
      msg = messages.warnings[code];
20,766✔
392
    } else if (/E\d{3}/.test(code)) {
6,978✔
393
      msg = messages.errors[code];
6,936✔
394
    } else if (/I\d{3}/.test(code)) {
42✔
395
      msg = messages.info[code];
42✔
396
    }
397

398
    t = t || state.tokens.next || {};
27,744✔
399
    if (t.id === "(end)") {  // `~
27,744✔
400
      t = state.tokens.curr;
222✔
401
    }
402

403
    l = t.line;
27,744✔
404
    ch = t.from;
27,744✔
405

406
    w = {
27,744✔
407
      id: "(error)",
408
      raw: msg.desc,
409
      code: msg.code,
410
      evidence: state.lines[l - 1] || "",
411
      line: l,
412
      character: ch,
413
      scope: JSHINT.scope,
414
      a: a,
415
      b: b,
416
      c: c,
417
      d: d
418
    };
419

420
    w.reason = supplant(msg.desc, w);
27,744✔
421
    JSHINT.errors.push(w);
27,744✔
422

423
    removeIgnoredMessages();
27,744✔
424

425
    if (JSHINT.errors.length >= state.option.maxerr)
27,744✔
426
      quit("E043", t);
30✔
427

428
    return w;
27,714✔
429
  }
430

431
  function warningAt(m, l, ch, a, b, c, d) {
6✔
432
    return warning(m, {
2,106✔
433
      line: l,
434
      from: ch
435
    }, a, b, c, d);
436
  }
437

438
  function error(m, t, a, b, c, d) {
6✔
439
    warning(m, t, a, b, c, d);
6,150✔
440
  }
441

442
  function errorAt(m, l, ch, a, b, c, d) {
6✔
443
    return error(m, {
876✔
444
      line: l,
445
      from: ch
446
    }, a, b, c, d);
447
  }
448

449
  // Tracking of "internal" scripts, like eval containing a static string
450
  function addEvalCode(elem, token) {
6✔
451
    JSHINT.internals.push({
36✔
452
      id: "(internal)",
453
      elem: elem,
454
      token: token,
455
      code: token.value.replace(/([^\\])(\\*)\2\\n/g, "$1\n")
456
    });
457
  }
458

459
  /**
460
   * Process an inline linting directive
461
   *
462
   * @param {Token} directiveToken - the directive-bearing comment token
463
   * @param {Token} previous - the token that preceeds the directive
464
   */
465
  function lintingDirective(directiveToken, previous) {
6✔
466
    var body = directiveToken.body.split(",")
1,998✔
467
      .map(function(s) { return s.trim(); });
2,484✔
468
    var predef = {};
1,998✔
469

470
    if (directiveToken.type === "falls through") {
1,998✔
471
      previous.caseFallsThrough = true;
42✔
472
      return;
42✔
473
    }
474

475
    if (directiveToken.type === "globals") {
1,956✔
476
      body.forEach(function(g, idx) {
282✔
477
        g = g.split(":");
402✔
478
        var key = g[0].trim();
402✔
479
        var val = (g[1] || "").trim();
402✔
480

481
        if (key === "-" || !key.length) {
402✔
482
          // Ignore trailing comma
483
          if (idx > 0 && idx === body.length - 1) {
54✔
484
            return;
18✔
485
          }
486
          error("E002", directiveToken);
36✔
487
          return;
36✔
488
        }
489

490
        if (key.charAt(0) === "-") {
348✔
491
          key = key.slice(1);
12✔
492
          val = false;
12✔
493

494
          JSHINT.blacklist[key] = key;
12✔
495
          delete predefined[key];
12✔
496
        } else {
497
          predef[key] = (val === "true");
336✔
498
        }
499
      });
500

501
      combine(predefined, predef);
282✔
502

503
      for (var key in predef) {
282✔
504
        if (_.has(predef, key)) {
1,182✔
505
          declared[key] = directiveToken;
336✔
506
        }
507
      }
508
    }
509

510
    if (directiveToken.type === "exported") {
1,956✔
511
      body.forEach(function(e, idx) {
168✔
512
        if (!e.length) {
306✔
513
          // Ignore trailing comma
514
          if (idx > 0 && idx === body.length - 1) {
12✔
515
            return;
6✔
516
          }
517
          error("E002", directiveToken);
6✔
518
          return;
6✔
519
        }
520

521
        state.funct["(scope)"].addExported(e);
294✔
522
      });
523
    }
524

525
    if (directiveToken.type === "members") {
1,956✔
526
      membersOnly = membersOnly || {};
84✔
527

528
      body.forEach(function(m) {
84✔
529
        var ch1 = m.charAt(0);
84✔
530
        var ch2 = m.charAt(m.length - 1);
84✔
531

532
        if (ch1 === ch2 && (ch1 === "\"" || ch1 === "'")) {
84✔
533
          m = m
6✔
534
            .substr(1, m.length - 2)
535
            .replace("\\\"", "\"");
536
        }
537

538
        membersOnly[m] = false;
84✔
539
      });
540
    }
541

542
    var numvals = [
1,956✔
543
      "maxstatements",
544
      "maxparams",
545
      "maxdepth",
546
      "maxcomplexity",
547
      "maxerr",
548
      "maxlen",
549
      "indent"
550
    ];
551

552
    if (directiveToken.type === "jshint" || directiveToken.type === "jslint" ||
1,956✔
553
      directiveToken.type === "jshint.unstable") {
554
      body.forEach(function(g) {
1,422✔
555
        g = g.split(":");
1,650✔
556
        var key = g[0].trim();
1,650✔
557
        var val = (g[1] || "").trim();
1,650✔
558

559
        if (!checkOption(key, directiveToken.type !== "jshint.unstable", directiveToken)) {
1,650✔
560
          return;
126✔
561
        }
562

563
        if (numvals.indexOf(key) >= 0) {
1,524✔
564
          // GH988 - numeric options can be disabled by setting them to `false`
565
          if (val !== "false") {
276✔
566
            val = +val;
234✔
567

568
            if (typeof val !== "number" || !isFinite(val) || val <= 0 || Math.floor(val) !== val) {
234✔
569
              error("E032", directiveToken, g[1].trim());
150✔
570
              return;
150✔
571
            }
572

573
            state.option[key] = val;
84✔
574
          } else {
575
            state.option[key] = key === "indent" ? 4 : false;
42✔
576
          }
577

578
          return;
126✔
579
        }
580

581
        if (key === "validthis") {
1,248✔
582
          // `validthis` is valid only within a function scope.
583

584
          if (state.funct["(global)"])
24✔
585
            return void error("E009");
6✔
586

587
          if (val !== "true" && val !== "false")
18✔
588
            return void error("E002", directiveToken);
6✔
589

590
          state.option.validthis = (val === "true");
12✔
591
          return;
12✔
592
        }
593

594
        if (key === "quotmark") {
1,224✔
595
          switch (val) {
30✔
596
          case "true":
597
          case "false":
598
            state.option.quotmark = (val === "true");
12✔
599
            break;
12✔
600
          case "double":
601
          case "single":
602
            state.option.quotmark = val;
12✔
603
            break;
12✔
604
          default:
605
            error("E002", directiveToken);
6✔
606
          }
607
          return;
30✔
608
        }
609

610
        if (key === "shadow") {
1,194✔
611
          switch (val) {
30✔
612
          case "true":
613
            state.option.shadow = true;
6✔
614
            break;
6✔
615
          case "outer":
616
            state.option.shadow = "outer";
6✔
617
            break;
6✔
618
          case "false":
619
          case "inner":
620
            state.option.shadow = "inner";
12✔
621
            break;
12✔
622
          default:
623
            error("E002", directiveToken);
6✔
624
          }
625
          return;
30✔
626
        }
627

628
        if (key === "unused") {
1,164✔
629
          switch (val) {
126✔
630
          case "true":
631
            state.option.unused = true;
60✔
632
            break;
60✔
633
          case "false":
634
            state.option.unused = false;
12✔
635
            break;
12✔
636
          case "vars":
637
          case "strict":
638
            state.option.unused = val;
42✔
639
            break;
42✔
640
          default:
641
            error("E002", directiveToken);
12✔
642
          }
643
          return;
126✔
644
        }
645

646
        if (key === "latedef") {
1,038✔
647
          switch (val) {
36✔
648
          case "true":
649
            state.option.latedef = true;
18✔
650
            break;
18✔
651
          case "false":
652
            state.option.latedef = false;
6✔
653
            break;
6✔
654
          case "nofunc":
655
            state.option.latedef = "nofunc";
6✔
656
            break;
6✔
657
          default:
658
            error("E002", directiveToken);
6✔
659
          }
660
          return;
36✔
661
        }
662

663
        if (key === "ignore") {
1,002✔
664
          switch (val) {
30✔
665
          case "line":
666
            state.ignoredLines[directiveToken.line] = true;
24✔
667
            removeIgnoredMessages();
24✔
668
            break;
24✔
669
          default:
670
            error("E002", directiveToken);
6✔
671
          }
672
          return;
30✔
673
        }
674

675
        if (key === "strict") {
972✔
676
          switch (val) {
48✔
677
          case "true":
678
            state.option.strict = true;
12✔
679
            break;
12✔
680
          case "false":
681
            state.option.strict = false;
6✔
682
            break;
6✔
683
          case "global":
684
          case "implied":
685
            state.option.strict = val;
24✔
686
            break;
24✔
687
          default:
688
            error("E002", directiveToken);
6✔
689
          }
690
          return;
48✔
691
        }
692

693
        if (key === "module") {
924✔
694
          /**
695
           * TODO: Extend this restriction to *all* "environmental" options.
696
           */
697
          if (!hasParsedCode(state.funct)) {
78✔
698
            error("E055", directiveToken, "module");
36✔
699
          }
700
        }
701

702
        if (key === "esversion") {
924✔
703
          switch (val) {
138✔
704
          case "3":
705
          case "5":
706
          case "6":
707
          case "7":
708
          case "8":
709
          case "9":
710
            state.option.moz = false;
96✔
711
            state.option.esversion = +val;
96✔
712
            break;
96✔
713
          case "2015":
714
          case "2016":
715
          case "2017":
716
          case "2018":
717
            state.option.moz = false;
24✔
718
            // Translate specification publication year to version number.
719
            state.option.esversion = +val - 2009;
24✔
720
            break;
24✔
721
          default:
722
            error("E002", directiveToken);
18✔
723
          }
724
          if (!hasParsedCode(state.funct)) {
138✔
725
            error("E055", directiveToken, "esversion");
6✔
726
          }
727
          return;
138✔
728
        }
729

730
        var match = /^([+-])(W\d{3})$/g.exec(key);
786✔
731
        if (match) {
786✔
732
          // ignore for -W..., unignore for +W...
733
          state.ignored[match[2]] = (match[1] === "-");
336✔
734
          return;
336✔
735
        }
736

737
        var tn;
450✔
738
        if (val === "true" || val === "false") {
450✔
739
          if (directiveToken.type === "jslint") {
444✔
740
            tn = options.renamed[key] || key;
30✔
741
            state.option[tn] = (val === "true");
30✔
742

743
            if (options.inverted[tn] !== undefined) {
30✔
744
              state.option[tn] = !state.option[tn];
18✔
745
            }
746
          } else if (directiveToken.type === "jshint.unstable") {
414✔
747
            /* istanbul ignore next */
748
            state.option.unstable[key] = (val === "true");
6✔
749
          } else {
750
            state.option[key] = (val === "true");
414✔
751
          }
752

753
          return;
444✔
754
        }
755

756
        error("E002", directiveToken);
6✔
757
      });
758

759
      applyOptions();
1,422✔
760
    }
761
  }
762

763
  /**
764
   * Return a token beyond the token available in `state.tokens.next`. If no
765
   * such token exists, return the "(end)" token. This function is used to
766
   * determine parsing strategies in cases where the value of the next token
767
   * does not provide sufficient information, as is the case with `for` loops,
768
   * e.g.:
769
   *
770
   *     for ( var i in ...
771
   *
772
   * versus:
773
   *
774
   *     for ( var i = ...
775
   *
776
   * @param {number} [p] - offset of desired token; defaults to 0
777
   *
778
   * @returns {token}
779
   */
780
  function peek(p) {
6✔
781
    var i = p || 0, j = lookahead.length, t;
302,724✔
782

783
    if (i < j) {
302,724✔
784
      return lookahead[i];
127,692✔
785
    }
786

787
    while (j <= i) {
175,032✔
788
      t = lex.token();
175,032✔
789

790
      // When the lexer is exhausted, this function should produce the "(end)"
791
      // token, even in cases where the requested token is beyond the end of
792
      // the input stream.
793
      if (!t) {
175,032✔
794
        // If the lookahead buffer is empty, the expected "(end)" token was
795
        // already emitted by the most recent invocation of `advance` and is
796
        // available as the next token.
797
        if (!lookahead.length) {
144✔
798
          return state.tokens.next;
42✔
799
        }
800

801
        return lookahead[j - 1];
102✔
802
      }
803

804
      lookahead[j] = t;
174,888✔
805
      j += 1;
174,888✔
806
    }
807

808
    return t;
174,888✔
809
  }
810

811
  function peekIgnoreEOL() {
6✔
812
    var i = 0;
9,048✔
813
    var t;
9,048✔
814
    do {
9,048✔
815
      t = peek(i++);
9,150✔
816
    } while (t.id === "(endline)");
817
    return t;
9,048✔
818
  }
819

820
  /**
821
   * Consume the next token.
822
   *
823
   * @param {string} [expected] - the expected value of the next token's `id`
824
   *                              property (in the case of punctuators) or
825
   *                              `value` property (in the case of identifiers
826
   *                              and literals); if unspecified, any token will
827
   *                              be accepted
828
   * @param {object} [relatedToken] - the token that informed the expected
829
   *                                  value, if any (for example: the opening
830
   *                                  brace when a closing brace is expected);
831
   *                                  used to produce more meaningful errors
832
   */
833
  function advance(expected, relatedToken) {
6✔
834
    var nextToken = state.tokens.next;
473,664✔
835

836
    if (expected && nextToken.id !== expected) {
473,664✔
837
      if (relatedToken) {
3,084✔
838
        if (nextToken.id === "(end)") {
150✔
839
          error("E019", relatedToken, relatedToken.id);
54✔
840
        } else {
841
          error("E020", nextToken, expected, relatedToken.id,
96✔
842
            relatedToken.line, nextToken.value);
843
        }
844
      } else if (nextToken.type !== "(identifier)" || nextToken.value !== expected) {
2,934✔
845
        error("E021", nextToken, expected, nextToken.value);
522✔
846
      }
847
    }
848

849
    state.tokens.prev = state.tokens.curr;
473,658✔
850
    state.tokens.curr = state.tokens.next;
473,658✔
851
    for (;;) {
473,658✔
852
      state.tokens.next = lookahead.shift() || lex.token();
562,392✔
853

854
      if (!state.tokens.next) { // No more tokens left, give up
562,350✔
855
        quit("E041", state.tokens.curr);
270✔
856
      }
857

858
      if (state.tokens.next.id === "(end)" || state.tokens.next.id === "(error)") {
562,080✔
859
        return;
9,390✔
860
      }
861

862
      if (state.tokens.next.check) {
552,690✔
863
        state.tokens.next.check();
550,692✔
864
      }
865

866
      if (state.tokens.next.isSpecial) {
552,690✔
867
        lintingDirective(state.tokens.next, state.tokens.curr);
1,998✔
868
      } else {
869
        if (state.tokens.next.id !== "(endline)") {
550,692✔
870
          break;
463,914✔
871
        }
872
      }
873
    }
874
  }
875

876
  /**
877
   * Determine whether a given token is an operator.
878
   *
879
   * @param {token} token
880
   *
881
   * @returns {boolean}
882
   */
883
  function isOperator(token) {
6✔
884
    return token.first || token.right || token.left || token.id === "yield" || token.id === "await";
1,212✔
885
  }
886

887
  function isEndOfExpr(context, curr, next) {
6✔
888
    if (arguments.length <= 1) {
38,934✔
889
      curr = state.tokens.curr;
37,818✔
890
      next = state.tokens.next;
37,818✔
891
    }
892

893
    if (next.id === "in" && context & prodParams.noin) {
38,934✔
894
      return true;
144✔
895
    }
896
    if (next.id === ";" || next.id === "}" || next.id === ":") {
38,790✔
897
      return true;
2,376✔
898
    }
899
    if (next.infix === curr.infix || curr.ltBoundary === "after" ||
36,414✔
900
      next.ltBoundary === "before") {
901
      return curr.line !== startLine(next);
3,672✔
902
    }
903
    return false;
32,742✔
904
  }
905

906
  /**
907
   * The `expression` function is the heart of JSHint's parsing behaior. It is
908
   * based on the Pratt parser, but it extends that model with a `fud` method.
909
   * Short for "first null denotation," it it similar to the `nud` ("null
910
   * denotation") function, but it is only used on the first token of a
911
   * statement. This simplifies usage in statement-oriented languages like
912
   * JavaScript.
913
   *
914
   * .nud  Null denotation
915
   * .fud  First null denotation
916
   * .led  Left denotation
917
   *  lbp  Left binding power
918
   *  rbp  Right binding power
919
   *
920
   * They are elements of the parsing method called Top Down Operator Precedence.
921
   *
922
   * In addition to parsing, this function applies a number of linting patterns.
923
   *
924
   * @param {number} context - the parsing context (a bitfield describing
925
   *                           conditions of the current parsing operation
926
   *                           which can influence how the next tokens are
927
   *                           interpreted); see `prod-params.js` for more
928
   *                           detail)
929
   * @param {number} rbp - the right-binding power of the token to be consumed
930
   */
931
  function expression(context, rbp) {
6✔
932
    var left, isArray = false, isObject = false;
148,302✔
933
    var initial = context & prodParams.initial;
148,302✔
934
    var curr;
148,302✔
935

936
    context &= ~prodParams.initial;
148,302✔
937

938
    state.nameStack.push();
148,302✔
939

940
    if (state.tokens.next.id === "(end)")
148,302✔
941
      error("E006", state.tokens.curr);
30✔
942

943
    advance();
148,302✔
944

945
    if (initial) {
148,260✔
946
      state.funct["(verb)"] = state.tokens.curr.value;
59,214✔
947
      state.tokens.curr.beginsStmt = true;
59,214✔
948
    }
949

950
    curr = state.tokens.curr;
148,260✔
951

952
    if (initial && curr.fud && (!curr.useFud || curr.useFud(context))) {
148,260✔
953
      left = state.tokens.curr.fud(context);
37,578✔
954
    } else {
955
      if (state.tokens.curr.nud) {
110,682✔
956
        left = state.tokens.curr.nud(context, rbp);
110,232✔
957
      } else {
958
        error("E030", state.tokens.curr, state.tokens.curr.id);
450✔
959
      }
960

961
      while (rbp < state.tokens.next.lbp && !isEndOfExpr(context)) {
110,592✔
962
        isArray = state.tokens.curr.value === "Array";
33,672✔
963
        isObject = state.tokens.curr.value === "Object";
33,672✔
964

965
        // #527, new Foo.Array(), Foo.Array(), new Foo.Object(), Foo.Object()
966
        // Line breaks in IfStatement heads exist to satisfy the checkJSHint
967
        // "Line too long." error.
968
        if (left && (left.value || (left.first && left.first.value))) {
33,672✔
969
          // If the left.value is not "new", or the left.first.value is a "."
970
          // then safely assume that this is not "new Array()" and possibly
971
          // not "new Object()"...
972
          if (left.value !== "new" ||
33,624✔
973
            (left.first && left.first.value && left.first.value === ".")) {
974
            isArray = false;
33,096✔
975
            // ...In the case of Object, if the left.value and state.tokens.curr.value
976
            // are not equal, then safely assume that this not "new Object()"
977
            if (left.value !== state.tokens.curr.value) {
33,096✔
978
              isObject = false;
9,780✔
979
            }
980
          }
981
        }
982

983
        advance();
33,672✔
984

985
        if (isArray && state.tokens.curr.id === "(" && state.tokens.next.id === ")") {
33,672✔
986
          warning("W009", state.tokens.curr);
6✔
987
        }
988

989
        if (isObject && state.tokens.curr.id === "(" && state.tokens.next.id === ")") {
33,672✔
990
          warning("W010", state.tokens.curr);
12✔
991
        }
992

993
        if (left && state.tokens.curr.led) {
33,672✔
994
          left = state.tokens.curr.led(context, left);
33,642✔
995
        } else {
996
          error("E033", state.tokens.curr, state.tokens.curr.id);
30✔
997
        }
998
      }
999
    }
1000

1001
    state.nameStack.pop();
147,906✔
1002

1003
    return left;
147,906✔
1004
  }
1005

1006

1007
  // Functions for conformance of style.
1008

1009
  function startLine(token) {
6✔
1010
    return token.startLine || token.line;
56,514✔
1011
  }
1012

1013
  function nobreaknonadjacent(left, right) {
6✔
1014
    if (!state.option.laxbreak && left.line !== startLine(right)) {
17,394✔
1015
      warning("W014", right, right.value);
270✔
1016
    }
1017
  }
1018

1019
  function nolinebreak(t) {
6✔
1020
    t = t;
2,688✔
1021
    if (t.line !== startLine(state.tokens.next)) {
2,688✔
1022
      warning("E022", t, t.value);
126✔
1023
    }
1024
  }
1025

1026
  function nobreakcomma(left, right) {
6✔
1027
    if (left.line !== startLine(right)) {
16,344✔
1028
      if (!state.option.laxcomma) {
108✔
1029
        if (parseComma.first) {
72✔
1030
          warning("I001");
42✔
1031
          parseComma.first = false;
42✔
1032
        }
1033
        warning("W014", left, right.value);
72✔
1034
      }
1035
    }
1036
  }
1037

1038
  function parseComma(opts) {
6✔
1039
    opts = opts || {};
16,344✔
1040

1041
    if (!opts.peek) {
16,344✔
1042
      nobreakcomma(state.tokens.curr, state.tokens.next);
15,894✔
1043
      advance(",");
15,894✔
1044
    } else {
1045
      nobreakcomma(state.tokens.prev, state.tokens.curr);
450✔
1046
    }
1047

1048
    if (state.tokens.next.identifier && !(opts.property && state.inES5())) {
16,344✔
1049
      // Keywords that cannot follow a comma operator.
1050
      switch (state.tokens.next.value) {
7,728✔
1051
      case "break":
1052
      case "case":
1053
      case "catch":
1054
      case "continue":
1055
      case "default":
1056
      case "do":
1057
      case "else":
1058
      case "finally":
1059
      case "for":
1060
      case "if":
1061
      case "in":
1062
      case "instanceof":
1063
      case "return":
1064
      case "switch":
1065
      case "throw":
1066
      case "try":
1067
      case "var":
1068
      case "let":
1069
      case "while":
1070
      case "with":
1071
        error("E024", state.tokens.next, state.tokens.next.value);
18✔
1072
        return false;
18✔
1073
      }
1074
    }
1075

1076
    if (state.tokens.next.type === "(punctuator)") {
16,326✔
1077
      switch (state.tokens.next.value) {
2,490✔
1078
      case "}":
1079
      case "]":
1080
      case ",":
1081
      case ")":
1082
        if (opts.allowTrailing) {
384✔
1083
          return true;
354✔
1084
        }
1085

1086
        error("E024", state.tokens.next, state.tokens.next.value);
30✔
1087
        return false;
30✔
1088
      }
1089
    }
1090
    return true;
15,942✔
1091
  }
1092

1093
  /**
1094
   * Factory function for creating "symbols"--objects that will be inherited by
1095
   * tokens. The objects created by this function are stored in a symbol table
1096
   * and set as the prototype of the tokens generated by the lexer.
1097
   *
1098
   * Note that this definition of "symbol" describes an implementation detail
1099
   * of JSHint and is not related to the ECMAScript value type introduced in
1100
   * ES2015.
1101
   *
1102
   * @param {string} s - the name of the token; for keywords (e.g. `void`) and
1103
   *                     delimiters (e.g.. `[`), this is the token's text
1104
   *                     representation; for literals (e.g. numbers) and other
1105
   *                     "special" tokens (e.g. the end-of-file marker) this is
1106
   *                     a parenthetical value
1107
   * @param {number} p - the left-binding power of the token as used by the
1108
   *                     Pratt parsing semantics
1109
   *
1110
   * @returns {object} - the object describing the JSHint symbol (provided to
1111
   *                     support cases where further refinement is necessary)
1112
   */
1113
  function symbol(s, p) {
6✔
1114
    var x = state.syntax[s];
804✔
1115
    if (!x || typeof x !== "object") {
804✔
1116
      state.syntax[s] = x = {
744✔
1117
        id: s,
1118
        lbp: p,
1119
        // Symbols that accept a right-hand side do so with a binding power
1120
        // that is commonly identical to their left-binding power. (This value
1121
        // is relevant when determining if the grouping operator is necessary
1122
        // to override the precedence of surrounding operators.) Because the
1123
        // exponentiation operator's left-binding power and right-binding power
1124
        // are distinct, the values must be encoded separately.
1125
        rbp: p,
1126
        value: s
1127
      };
1128
    }
1129
    return x;
804✔
1130
  }
1131

1132
  /**
1133
   * Convenience function for defining delimiter symbols.
1134
   *
1135
   * @param {string} s - the name of the symbol
1136
   *
1137
   * @returns {object} - the object describing the JSHint symbol (provided to
1138
   *                     support cases where further refinement is necessary)
1139
   */
1140
  function delim(s) {
6✔
1141
    var x = symbol(s, 0);
426✔
1142
    x.delim = true;
426✔
1143
    return x;
426✔
1144
  }
1145

1146
  /**
1147
   * Convenience function for defining statement-denoting symbols.
1148
   *
1149
   * @param {string} s - the name of the symbol
1150
   * @param {function} f - the first null denotation function for the symbol;
1151
   *                       see the `expression` function for more detail
1152
   *
1153
   * @returns {object} - the object describing the JSHint symbol (provided to
1154
   *                     support cases where further refinement is necessary)
1155
   */
1156
  function stmt(s, f) {
6✔
1157
    var x = delim(s);
114✔
1158
    x.identifier = x.reserved = true;
114✔
1159
    x.fud = f;
114✔
1160
    return x;
114✔
1161
  }
1162

1163
  /**
1164
   * Convenience function for defining block-statement-denoting symbols.
1165
   *
1166
   * A block-statement-denoting symbol is one like 'if' or 'for', which will be
1167
   * followed by a block and will not have to end with a semicolon.
1168
   *
1169
   * @param {string} s - the name of the symbol
1170
   * @param {function} - the first null denotation function for the symbol; see
1171
   *                     the `expression` function for more detail
1172
   *
1173
   * @returns {object} - the object describing the JSHint symbol (provided to
1174
   *                     support cases where further refinement is necessary)
1175
   */
1176
  function blockstmt(s, f) {
6✔
1177
    var x = stmt(s, f);
48✔
1178
    x.block = true;
48✔
1179
    return x;
48✔
1180
  }
1181
  /**
1182
   * Denote a given JSHint symbol as an identifier and a reserved keyword.
1183
   *
1184
   * @param {object} - a JSHint symbol value
1185
   *
1186
   * @returns {object} - the provided object
1187
   */
1188
  function reserveName(x) {
6✔
1189
    var c = x.id.charAt(0);
312✔
1190
    if ((c >= "a" && c <= "z") || (c >= "A" && c <= "Z")) {
312✔
1191
      x.identifier = x.reserved = true;
66✔
1192
    }
1193
    return x;
312✔
1194
  }
1195

1196
  /**
1197
   * Convenience function for defining "prefix" symbols--operators that accept
1198
   * expressions as a right-hand side.
1199
   *
1200
   * @param {string} s - the name of the symbol
1201
   * @param {function} [f] - the first null denotation function for the symbol;
1202
   *                         see the `expression` function for more detail
1203
   *
1204
   * @returns {object} - the object describing the JSHint symbol (provided to
1205
   *                     support cases where further refinement is necessary)
1206
   */
1207
  function prefix(s, f) {
6✔
1208
    var x = symbol(s, 150);
102✔
1209
    reserveName(x);
102✔
1210

1211
    x.nud = (typeof f === "function") ? f : function(context) {
102✔
1212
      this.arity = "unary";
4,020✔
1213
      this.right = expression(context, 150);
4,020✔
1214

1215
      if (this.id === "++" || this.id === "--") {
4,020✔
1216
        if (state.option.plusplus) {
558✔
1217
          warning("W016", this, this.id);
60✔
1218
        }
1219

1220
        if (this.right) {
558✔
1221
          checkLeftSideAssign(context, this.right, this);
552✔
1222
        }
1223
      }
1224

1225
      return this;
4,020✔
1226
    };
1227

1228
    return x;
102✔
1229
  }
1230

1231
  /**
1232
   * Convenience function for defining "type" symbols--those that describe
1233
   * literal values.
1234
   *
1235
   * @param {string} s - the name of the symbol
1236
   * @param {function} f - the first null denotation function for the symbol;
1237
   *                       see the `expression` function for more detail
1238
   *
1239
   * @returns {object} - the object describing the JSHint symbol (provided to
1240
   *                     support cases where further refinement is necessary)
1241
   */
1242
  function type(s, f) {
6✔
1243
    var x = delim(s);
234✔
1244
    x.type = s;
234✔
1245
    x.nud = f;
234✔
1246
    return x;
234✔
1247
  }
1248

1249
  /**
1250
   * Convenience function for defining JSHint symbols for reserved
1251
   * keywords--those that are restricted from use as bindings (and as property
1252
   * names in ECMAScript 3 environments).
1253
   *
1254
   * @param {string} s - the name of the symbol
1255
   * @param {function} func - the first null denotation function for the
1256
   *                          symbol; see the `expression` function for more
1257
   *                          detail
1258
   *
1259
   * @returns {object} - the object describing the JSHint symbol (provided to
1260
   *                     support cases where further refinement is necessary)
1261
   */
1262
  function reserve(name, func) {
6✔
1263
    var x = type(name, func);
60✔
1264
    x.identifier = true;
60✔
1265
    x.reserved = true;
60✔
1266
    return x;
60✔
1267
  }
1268

1269
  /**
1270
   * Convenience function for defining JSHint symbols for keywords that are
1271
   * only reserved in some circumstances.
1272
   *
1273
   * @param {string} name - the name of the symbol
1274
   * @param {object} [meta] - a collection of optional arguments
1275
   * @param {function} [meta.nud] -the null denotation function for the symbol;
1276
   *                   see the `expression` function for more detail
1277
   * @param {boolean} [meta.es5] - `true` if the identifier is reserved
1278
   *                               in ECMAScript 5 or later
1279
   * @param {boolean} [meta.strictOnly] - `true` if the identifier is only
1280
   *                                      reserved in strict mode code.
1281
   *
1282
   * @returns {object} - the object describing the JSHint symbol (provided to
1283
   *                     support cases where further refinement is necessary)
1284
   */
1285
  function FutureReservedWord(name, meta) {
6✔
1286
    var x = type(name, state.syntax["(identifier)"].nud);
156✔
1287

1288
    meta = meta || {};
156✔
1289
    meta.isFutureReservedWord = true;
156✔
1290

1291
    x.value = name;
156✔
1292
    x.identifier = true;
156✔
1293
    x.reserved = true;
156✔
1294
    x.meta = meta;
156✔
1295

1296
    return x;
156✔
1297
  }
1298

1299
  /**
1300
   * Convenience function for defining "infix" symbols--operators that require
1301
   * operands as both "land-hand side" and "right-hand side".
1302
   *
1303
   * @param {string} s - the name of the symbol
1304
   * @param {function} [f] - a function to be invoked that consumes the
1305
   *                         right-hand side of the operator
1306
   * @param {number} p - the left-binding power of the token as used by the
1307
   *                     Pratt parsing semantics
1308
   * @param {boolean} [w] - if `true`
1309
   *
1310
   * @returns {object} - the object describing the JSHint symbol (provided to
1311
   *                     support cases where further refinement is necessary)
1312
   */
1313
  function infix(s, f, p, w) {
6✔
1314
    var x = symbol(s, p);
174✔
1315
    reserveName(x);
174✔
1316
    x.infix = true;
174✔
1317
    x.led = function(context, left) {
174✔
1318
      if (!w) {
29,808✔
1319
        nobreaknonadjacent(state.tokens.prev, state.tokens.curr);
13,332✔
1320
      }
1321
      if ((s === "in" || s === "instanceof") && left.id === "!") {
29,808✔
1322
        warning("W018", left, "!");
48✔
1323
      }
1324
      if (typeof f === "function") {
29,808✔
1325
        return f(context, left, this);
28,590✔
1326
      } else {
1327
        this.left = left;
1,218✔
1328
        this.right = expression(context, p);
1,218✔
1329
        return this;
1,218✔
1330
      }
1331
    };
1332
    return x;
174✔
1333
  }
1334

1335
  /**
1336
   * Convenience function for defining the `=>` token as used in arrow
1337
   * functions.
1338
   *
1339
   * @param {string} s - the name of the symbol
1340
   *
1341
   * @returns {object} - the object describing the JSHint symbol (provided to
1342
   *                     support cases where further refinement is necessary)
1343
   */
1344
  function application(s) {
6✔
1345
    var x = symbol(s, 42);
6✔
1346

1347
    x.infix = true;
6✔
1348
    x.led = function(context, left) {
6✔
1349
      nobreaknonadjacent(state.tokens.prev, state.tokens.curr);
432✔
1350

1351
      this.left = left;
432✔
1352
      this.right = doFunction(context, { type: "arrow", loneArg: left });
432✔
1353
      return this;
432✔
1354
    };
1355
    return x;
6✔
1356
  }
1357

1358
  /**
1359
   * Convenience function for defining JSHint symbols for relation operators.
1360
   *
1361
   * @param {string} s - the name of the symbol
1362
   * @param {function} [f] - a function to be invoked to enforce any additional
1363
   *                         linting rules.
1364
   *
1365
   * @returns {object} - the object describing the JSHint symbol (provided to
1366
   *                     support cases where further refinement is necessary)
1367
   */
1368
  function relation(s, f) {
6✔
1369
    var x = symbol(s, 100);
48✔
1370

1371
    x.infix = true;
48✔
1372
    x.led = function(context, left) {
48✔
1373
      nobreaknonadjacent(state.tokens.prev, state.tokens.curr);
2,154✔
1374
      this.left = left;
2,154✔
1375
      var right = this.right = expression(context, 100);
2,154✔
1376

1377
      if (isIdentifier(left, "NaN") || isIdentifier(right, "NaN")) {
2,154✔
1378
        warning("W019", this);
48✔
1379
      } else if (f) {
2,106✔
1380
        f.apply(this, [context, left, right]);
1,116✔
1381
      }
1382

1383
      if (!left || !right) {
2,154✔
1384
        quit("E041", state.tokens.curr);
72✔
1385
      }
1386

1387
      if (left.id === "!") {
2,082✔
1388
        warning("W018", left, "!");
96✔
1389
      }
1390

1391
      if (right.id === "!") {
2,082✔
1392
        warning("W018", right, "!");
48✔
1393
      }
1394

1395
      return this;
2,082✔
1396
    };
1397
    return x;
48✔
1398
  }
1399

1400
  /**
1401
   * Determine if a given token marks the beginning of a UnaryExpression.
1402
   *
1403
   * @param {object} token
1404
   *
1405
   * @returns {boolean}
1406
   */
1407
  function beginsUnaryExpression(token) {
6✔
1408
    return token.arity === "unary" && token.id !== "++" && token.id !== "--";
1,614✔
1409
  }
1410

1411
  var typeofValues = {};
6✔
1412
  typeofValues.legacy = [
6✔
1413
    // E4X extended the `typeof` operator to return "xml" for the XML and
1414
    // XMLList types it introduced.
1415
    // Ref: 11.3.2 The typeof Operator
1416
    // http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-357.pdf
1417
    "xml",
1418
    // IE<9 reports "unknown" when the `typeof` operator is applied to an
1419
    // object existing across a COM+ bridge. In lieu of official documentation
1420
    // (which does not exist), see:
1421
    // http://robertnyman.com/2005/12/21/what-is-typeof-unknown/
1422
    "unknown"
1423
  ];
1424
  typeofValues.es3 = [
6✔
1425
    "undefined", "boolean", "number", "string", "function", "object",
1426
  ];
1427
  typeofValues.es3 = typeofValues.es3.concat(typeofValues.legacy);
6✔
1428
  typeofValues.es6 = typeofValues.es3.concat("symbol");
6✔
1429

1430
  /**
1431
   * Validate comparisons between the result of a `typeof` expression and a
1432
   * string literal.
1433
   *
1434
   * @param {token} [left] - one of the values being compared
1435
   * @param {token} [right] - the other value being compared
1436
   * @param {object} state - the global state object (see `state.js`)
1437
   *
1438
   * @returns {boolean} - `false` if the second token describes a `typeof`
1439
   *                       expression and the first token is a string literal
1440
   *                       whose value is never returned by that operator;
1441
   *                       `true` otherwise
1442
   */
1443
  function isTypoTypeof(left, right, state) {
6✔
1444
    var values;
2,106✔
1445

1446
    if (state.option.notypeof)
2,106✔
1447
      return false;
384✔
1448

1449
    if (!left || !right)
1,722✔
1450
      return false;
48✔
1451

1452
    values = state.inES6() ? typeofValues.es6 : typeofValues.es3;
1,674✔
1453

1454
    if (right.type === "(identifier)" && right.value === "typeof" && left.type === "(string)")
1,674✔
1455
      return !_.includes(values, left.value);
186✔
1456

1457
    return false;
1,488✔
1458
  }
1459

1460
  /**
1461
   * Determine if a given token describes the built-in `eval` function.
1462
   *
1463
   * @param {token} left
1464
   * @param {object} state - the global state object (see `state.js`)
1465
   *
1466
   * @returns {boolean}
1467
   */
1468
  function isGlobalEval(left, state) {
6✔
1469
    var isGlobal = false;
96✔
1470

1471
    // permit methods to refer to an "eval" key in their own context
1472
    if (left.type === "this" && state.funct["(context)"] === null) {
96✔
1473
      isGlobal = true;
12✔
1474
    }
1475
    // permit use of "eval" members of objects
1476
    else if (left.type === "(identifier)") {
84✔
1477
      if (state.option.node && left.value === "global") {
72✔
1478
        isGlobal = true;
12✔
1479
      }
1480

1481
      else if (state.option.browser && (left.value === "window" || left.value === "document")) {
60✔
1482
        isGlobal = true;
36✔
1483
      }
1484
    }
1485

1486
    return isGlobal;
96✔
1487
  }
1488

1489
  /**
1490
   * Determine if a given token describes a property of a built-in object.
1491
   *
1492
   * @param {token} left
1493
   *
1494
   * @returns {boolean}
1495
   */
1496
  function findNativePrototype(left) {
6✔
1497
    var natives = [
144✔
1498
      "Array", "ArrayBuffer", "Boolean", "Collator", "DataView", "Date",
1499
      "DateTimeFormat", "Error", "EvalError", "Float32Array", "Float64Array",
1500
      "Function", "Infinity", "Intl", "Int16Array", "Int32Array", "Int8Array",
1501
      "Iterator", "Number", "NumberFormat", "Object", "RangeError",
1502
      "ReferenceError", "RegExp", "StopIteration", "String", "SyntaxError",
1503
      "TypeError", "Uint16Array", "Uint32Array", "Uint8Array", "Uint8ClampedArray",
1504
      "URIError"
1505
    ];
1506

1507
    function walkPrototype(obj) {
6✔
1508
      if (typeof obj !== "object") return;
288✔
1509
      return obj.right === "prototype" ? obj : walkPrototype(obj.left);
180✔
1510
    }
1511

1512
    function walkNative(obj) {
6✔
1513
      while (!obj.identifier && typeof obj.left === "object")
36✔
1514
        obj = obj.left;
36✔
1515

1516
      if (obj.identifier && natives.indexOf(obj.value) >= 0 &&
36✔
1517
          state.funct["(scope)"].isPredefined(obj.value)) {
1518
        return obj.value;
18✔
1519
      }
1520
    }
1521

1522
    var prototype = walkPrototype(left);
144✔
1523
    if (prototype) return walkNative(prototype);
144✔
1524
  }
1525

1526
  /**
1527
   * Determine if the given token is a valid assignment target; emit errors
1528
   * and/or warnings as appropriate
1529
   *
1530
   * @param {number} context - the parsing context; see `prod-params.js` for
1531
   *                           more information
1532
   * @param {token} left - the left hand side of the assignment
1533
   * @param {token=} assignToken - the token for the assignment, used for
1534
   *                               reporting
1535
   * @param {object=} options - optional object
1536
   * @param {boolean} options.allowDestructuring - whether to allow
1537
   *                                               destructuring binding
1538
   *
1539
   * @returns {boolean} Whether the left hand side is OK
1540
   */
1541
  function checkLeftSideAssign(context, left, assignToken, options) {
6✔
1542

1543
    var allowDestructuring = options && options.allowDestructuring;
10,488✔
1544

1545
    assignToken = assignToken || left;
10,488✔
1546

1547
    if (state.option.freeze) {
10,488✔
1548
      var nativeObject = findNativePrototype(left);
144✔
1549
      if (nativeObject)
144✔
1550
        warning("W121", left, nativeObject);
18✔
1551
    }
1552
    if (checkPunctuator(left, "...")) {
10,488✔
1553
      /* istanbul ignore next */
1554
      left = left.right;
6✔
1555
    }
1556

1557
    if (left.identifier && !left.isMetaProperty) {
10,488✔
1558
      // The `reassign` method also calls `modify`, but we are specific in
1559
      // order to catch function re-assignment and globals re-assignment
1560
      state.funct["(scope)"].block.reassign(left.value, left);
8,004✔
1561
    }
1562

1563
    if (left.id === ".") {
10,488✔
1564
      if (!left.left || left.left.value === "arguments" && !state.isStrict()) {
966✔
1565
        warning("W143", assignToken);
54✔
1566
      }
1567

1568
      state.nameStack.set(state.tokens.prev);
966✔
1569
      return true;
966✔
1570
    } else if (left.id === "{" || left.id === "[") {
9,522✔
1571
      if (!allowDestructuring || !left.destructAssign) {
1,236✔
1572
        if (left.id === "{" || !left.left) {
378✔
1573
          warning("E031", assignToken);
132✔
1574
        } else if (left.left.value === "arguments" && !state.isStrict()) {
246✔
1575
          warning("W143", assignToken);
48✔
1576
        }
1577
      }
1578

1579
      if (left.id === "[") {
1,236✔
1580
        state.nameStack.set(left.right);
954✔
1581
      }
1582

1583
      return true;
1,236✔
1584
    } else if (left.identifier && !isReserved(context, left) && !left.isMetaProperty &&
8,286✔
1585
      left.value !== "eval" && left.value !== "arguments") {
1586
      if (state.funct["(scope)"].labeltype(left.value) === "exception") {
7,968✔
1587
        warning("W022", left);
24✔
1588
      }
1589
      state.nameStack.set(left);
7,968✔
1590
      return true;
7,968✔
1591
    }
1592

1593
    error("E031", assignToken);
318✔
1594

1595
    return false;
318✔
1596
  }
1597

1598
  /**
1599
   * Convenience function for defining JSHint symbols for assignment operators.
1600
   *
1601
   * @param {string} s - the name of the symbol
1602
   * @param {function} [f] - a function to be invoked that consumes the
1603
   *                         right-hand side of the operator (see the `infix`
1604
   *                         function)
1605
   * @param {number} p - the left-binding power of the token as used by the
1606
   *                     Pratt parsing semantics
1607
   *
1608
   * @returns {object} - the object describing the JSHint symbol (provided to
1609
   *                     support cases where further refinement is necessary)
1610
   */
1611
  function assignop(s, f, p) {
6✔
1612
    var x = infix(s, typeof f === "function" ? f : function(context, left, that) {
78✔
1613
      that.left = left;
6,762✔
1614

1615
      checkLeftSideAssign(context, left, that, { allowDestructuring: true });
6,762✔
1616

1617
      that.right = expression(context, 10);
6,762✔
1618

1619
      return that;
6,762✔
1620
    }, p);
1621

1622
    x.exps = true;
78✔
1623
    x.assign = true;
78✔
1624
    return x;
78✔
1625
  }
1626

1627
  /**
1628
   * Convenience function for defining JSHint symbols for bitwise operators.
1629
   *
1630
   * @param {string} s - the name of the symbol
1631
   * @param {function} [f] - the left denotation function for the symbol; see
1632
   *                         the `expression` function for more detail
1633
   * @param {number} p - the left-binding power of the token as used by the
1634
   *                     Pratt parsing semantics
1635
   *
1636
   * @returns {object} - the object describing the JSHint symbol (provided to
1637
   *                     support cases where further refinement is necessary)
1638
   */
1639
  function bitwise(s, f, p) {
6✔
1640
    var x = symbol(s, p);
36✔
1641
    reserveName(x);
36✔
1642
    x.infix = true;
36✔
1643
    x.led = (typeof f === "function") ? f : function(context, left) {
36✔
1644
      if (state.option.bitwise) {
102✔
1645
        warning("W016", this, this.id);
36✔
1646
      }
1647
      this.left = left;
102✔
1648
      this.right = expression(context, p);
102✔
1649
      return this;
102✔
1650
    };
1651
    return x;
36✔
1652
  }
1653

1654
  /**
1655
   * Convenience function for defining JSHint symbols for bitwise assignment
1656
   * operators. See the `assignop` function for more detail.
1657
   *
1658
   * @param {string} s - the name of the symbol
1659
   *
1660
   * @returns {object} - the object describing the JSHint symbol (provided to
1661
   *                     support cases where further refinement is necessary)
1662
   */
1663
  function bitwiseassignop(s) {
6✔
1664
    return assignop(s, function(context, left, that) {
36✔
1665
      if (state.option.bitwise) {
318✔
1666
        warning("W016", that, that.id);
36✔
1667
      }
1668

1669
      checkLeftSideAssign(context, left, that);
318✔
1670

1671
      that.right = expression(context, 10);
318✔
1672

1673
      return that;
318✔
1674
    }, 20);
1675
  }
1676

1677
  /**
1678
   * Convenience function for defining JSHint symbols for those operators which
1679
   * have a single operand that appears before them in the source code.
1680
   *
1681
   * @param {string} s - the name of the symbol
1682
   *
1683
   * @returns {object} - the object describing the JSHint symbol (provided to
1684
   *                     support cases where further refinement is necessary)
1685
   */
1686
  function suffix(s) {
6✔
1687
    var x = symbol(s, 150);
12✔
1688

1689
    x.led = function(context, left) {
12✔
1690
      // this = suffix e.g. "++" punctuator
1691
      // left = symbol operated e.g. "a" identifier or "a.b" punctuator
1692
      if (state.option.plusplus) {
996✔
1693
        warning("W016", this, this.id);
60✔
1694
      }
1695

1696
      checkLeftSideAssign(context, left, this);
996✔
1697

1698
      this.left = left;
996✔
1699
      return this;
996✔
1700
    };
1701
    return x;
12✔
1702
  }
1703

1704
  /**
1705
   * Retrieve the value of the current token if it is an identifier and
1706
   * optionally advance the parser.
1707
   *
1708
   * @param {number} context - the parsing context; see `prod-params.js` for
1709
   *                           more information
1710
   * @param {boolean} [prop] -`true` if this identifier is that of an object
1711
   *                           property
1712
   * @param {boolean} [preserve] - `true` if the token should not be consumed
1713
   *
1714
   * @returns {string|undefined} - the value of the identifier, if present
1715
   */
1716
  function optionalidentifier(context, prop, preserve) {
6✔
1717
    if (!state.tokens.next.identifier) {
52,986✔
1718
      return;
5,430✔
1719
    }
1720

1721
    if (!preserve) {
47,556✔
1722
      advance();
47,262✔
1723
    }
1724

1725
    var curr = state.tokens.curr;
47,556✔
1726
    var val  = state.tokens.curr.value;
47,556✔
1727

1728
    if (!isReserved(context, curr)) {
47,556✔
1729
      return val;
47,148✔
1730
    }
1731

1732
    if (prop) {
408✔
1733
      if (state.inES5()) {
180✔
1734
        return val;
138✔
1735
      }
1736
    }
1737

1738
    if (val === "undefined") {
270✔
1739
      /* istanbul ignore next */
1740
      return val;
6✔
1741
    }
1742

1743
    warning("W024", state.tokens.curr, state.tokens.curr.id);
270✔
1744
    return val;
270✔
1745
  }
1746

1747
  /**
1748
   * Consume the "..." token which designates "spread" and "rest" operations if
1749
   * it is present. If the operator is repeated, consume every repetition, and
1750
   * issue a single error describing the syntax error.
1751
   *
1752
   * @param {string} operation - either "spread" or "rest"
1753
   *
1754
   * @returns {boolean} a value describing whether or not any tokens were
1755
   *                    consumed in this way
1756
   */
1757
  function spreadrest(operation) {
6✔
1758
    if (!checkPunctuator(state.tokens.next, "...")) {
35,754✔
1759
      return false;
34,878✔
1760
    }
1761

1762
    if (!state.inES6(true)) {
876✔
1763
      warning("W119", state.tokens.next, operation + " operator", "6");
258✔
1764
    }
1765
    advance();
876✔
1766

1767
    if (checkPunctuator(state.tokens.next, "...")) {
876✔
1768
      warning("E024", state.tokens.next, "...");
60✔
1769
      while (checkPunctuator(state.tokens.next, "...")) {
60✔
1770
        advance();
60✔
1771
      }
1772
    }
1773

1774
    return true;
876✔
1775
  }
1776

1777
  /**
1778
   * Ensure that the current token is an identifier and retrieve its value.
1779
   *
1780
   * @param {number} context - the parsing context; see `prod-params.js` for
1781
   *                           more information
1782
   * @param {boolean} [prop] -`true` if this identifier is that of an object
1783
   *                           property
1784
   *
1785
   * @returns {string|undefined} - the value of the identifier, if present
1786
   */
1787
  function identifier(context, prop) {
6✔
1788
    var i = optionalidentifier(context, prop, false);
37,590✔
1789
    if (i) {
37,590✔
1790
      return i;
37,320✔
1791
    }
1792

1793
    error("E030", state.tokens.next, state.tokens.next.value);
270✔
1794

1795
    // The token should be consumed after a warning is issued so the parser
1796
    // can continue as though an identifier were found. The semicolon token
1797
    // should not be consumed in this way so that the parser interprets it as
1798
    // a statement delimeter;
1799
    if (state.tokens.next.id !== ";") {
270✔
1800
      advance();
252✔
1801
    }
1802
  }
1803

1804

1805
  /**
1806
   * Determine if the provided token may be evaluated and emit a linting
1807
   * warning if this is note the case.
1808
   *
1809
   * @param {token} controlToken
1810
   */
1811
  function reachable(controlToken) {
6✔
1812
    var i = 0, t;
4,386✔
1813
    if (state.tokens.next.id !== ";" || controlToken.inBracelessBlock) {
4,386✔
1814
      return;
234✔
1815
    }
1816
    for (;;) {
4,152✔
1817
      do {
6,402✔
1818
        t = peek(i);
6,420✔
1819
        i += 1;
6,420✔
1820
      } while (t.id !== "(end)" && t.id === "(comment)");
1821

1822
      if (t.reach) {
6,402✔
1823
        return;
4,104✔
1824
      }
1825
      if (t.id !== "(endline)") {
2,298✔
1826
        if (t.id === "function") {
48✔
1827
          if (state.option.latedef === true) {
18✔
1828
            warning("W026", t);
6✔
1829
          }
1830
          break;
18✔
1831
        }
1832

1833
        warning("W027", t, t.value, controlToken.value);
30✔
1834
        break;
30✔
1835
      }
1836
    }
1837
  }
1838

1839
  /**
1840
   * Consume the semicolon that delimits the statement currently being parsed,
1841
   * emitting relevant warnings/errors as appropriate.
1842
   *
1843
   * @param {token} stmt - token describing the statement under consideration
1844
   */
1845
  function parseFinalSemicolon(stmt) {
6✔
1846
    if (state.tokens.next.id !== ";") {
47,070✔
1847
      // don't complain about unclosed templates / strings
1848
      if (state.tokens.next.isUnclosed) return advance();
1,500✔
1849

1850
      var sameLine = startLine(state.tokens.next) === state.tokens.curr.line &&
1,482✔
1851
                     state.tokens.next.id !== "(end)";
1852
      var blockEnd = checkPunctuator(state.tokens.next, "}");
1,482✔
1853

1854
      if (sameLine && !blockEnd && !(stmt.id === "do" && state.inES6(true))) {
1,482✔
1855
        errorAt("E058", state.tokens.curr.line, state.tokens.curr.character);
324✔
1856
      } else if (!state.option.asi) {
1,158✔
1857

1858
        // If this is the last statement in a block that ends on the same line
1859
        // *and* option lastsemic is on, ignore the warning.  Otherwise, issue
1860
        // a warning about missing semicolon.
1861
        if (!(blockEnd && sameLine && state.option.lastsemic)) {
678✔
1862
          warningAt("W033", state.tokens.curr.line, state.tokens.curr.character);
672✔
1863
        }
1864
      }
1865
    } else {
1866
      advance(";");
45,570✔
1867
    }
1868
  }
1869

1870
  /**
1871
   * Consume a statement.
1872
   *
1873
   * @param {number} context - the parsing context; see `prod-params.js` for
1874
   *                           more information
1875
   *
1876
   * @returns {token} - the token describing the statement
1877
   */
1878
  function statement(context) {
6✔
1879
    var i = indent, r, t = state.tokens.next, hasOwnScope = false;
59,928✔
1880

1881
    context |= prodParams.initial;
59,928✔
1882

1883
    if (t.id === ";") {
59,928✔
1884
      advance(";");
114✔
1885
      return;
114✔
1886
    }
1887

1888
    // Is this a labelled statement?
1889
    var res = isReserved(context, t);
59,814✔
1890

1891
    // We're being more tolerant here: if someone uses
1892
    // a FutureReservedWord (that is not meant to start a statement)
1893
    // as a label, we warn but proceed anyway.
1894

1895
    if (res && t.meta && t.meta.isFutureReservedWord && !t.fud) {
59,814✔
1896
      warning("W024", t, t.id);
6✔
1897
      res = false;
6✔
1898
    }
1899

1900
    if (t.identifier && !res && peek().id === ":") {
59,814✔
1901
      advance();
804✔
1902
      advance(":");
804✔
1903

1904
      hasOwnScope = true;
804✔
1905
      state.funct["(scope)"].stack();
804✔
1906
      state.funct["(scope)"].block.addBreakLabel(t.value, { token: state.tokens.curr });
804✔
1907

1908
      if (!state.tokens.next.labelled && state.tokens.next.value !== "{") {
804✔
1909
        warning("W028", state.tokens.next, t.value, state.tokens.next.value);
66✔
1910
      }
1911

1912
      t = state.tokens.next;
804✔
1913
    }
1914

1915
    // Is it a lonely block?
1916

1917
    if (t.id === "{") {
59,814✔
1918
      // Is it a switch case block?
1919
      //
1920
      //  switch (foo) {
1921
      //    case bar: { <= here.
1922
      //      ...
1923
      //    }
1924
      //  }
1925
      var iscase = (state.funct["(verb)"] === "case" && state.tokens.curr.value === ":");
720✔
1926
      block(context, true, true, false, false, iscase);
720✔
1927

1928
      if (hasOwnScope) {
672✔
1929
        state.funct["(scope)"].unstack();
72✔
1930
      }
1931

1932
      return;
672✔
1933
    }
1934

1935
    // Parse the statement.
1936

1937
    r = expression(context, 0);
59,094✔
1938

1939
    if (r && !(r.identifier && r.value === "function") &&
58,776✔
1940
        !(r.type === "(punctuator)" && r.left &&
1941
          r.left.identifier && r.left.value === "function")) {
1942
      if (!state.isStrict() && state.stmtMissingStrict()) {
51,960✔
1943
        warning("E007");
114✔
1944
      }
1945
    }
1946

1947
    // Look for the final semicolon.
1948

1949
    if (!t.block) {
58,776✔
1950
      if (!state.option.expr && (!r || !r.exps)) {
46,026✔
1951
        warning("W030", state.tokens.curr);
978✔
1952
      } else if (state.option.nonew && r && r.left && r.id === "(" && r.left.id === "new") {
45,048✔
1953
        warning("W031", t);
6✔
1954
      }
1955
      parseFinalSemicolon(t);
46,026✔
1956
    }
1957

1958

1959
    // Restore the indentation.
1960

1961
    indent = i;
58,776✔
1962
    if (hasOwnScope) {
58,776✔
1963
      state.funct["(scope)"].unstack();
708✔
1964
    }
1965
    return r;
58,776✔
1966
  }
1967

1968
  /**
1969
   * Consume a series of statements until encountering either the end of the
1970
   * program or a token that interrupts control flow.
1971
   *
1972
   * @param {number} context - the parsing context; see `prod-params.js` for
1973
   *                           more information
1974
   *
1975
   * @returns {Array<token>} - the tokens consumed
1976
   */
1977
  function statements(context) {
6✔
1978
    var a = [], p;
23,046✔
1979

1980
    while (!state.tokens.next.reach && state.tokens.next.id !== "(end)") {
23,046✔
1981
      if (state.tokens.next.id === ";") {
58,194✔
1982
        p = peek();
96✔
1983

1984
        if (!p || (p.id !== "(" && p.id !== "[")) {
96✔
1985
          warning("W032");
72✔
1986
        }
1987

1988
        advance(";");
90✔
1989
      } else {
1990
        a.push(statement(context));
58,098✔
1991
      }
1992
    }
1993
    return a;
22,674✔
1994
  }
1995

1996

1997
  /**
1998
   * Parse any directives in a directive prologue.
1999
   */
2000
  function directives() {
6✔
2001
    var current = state.tokens.next;
17,964✔
2002
    while (state.tokens.next.id === "(string)") {
17,964✔
2003
      var next = peekIgnoreEOL();
1,116✔
2004
      if (!isEndOfExpr(0, current, next)) {
1,116✔
2005
        break;
72✔
2006
      }
2007
      current = next;
1,044✔
2008

2009
      advance();
1,044✔
2010
      var directive = state.tokens.curr.value;
1,044✔
2011
      if (state.directive[directive] ||
1,044✔
2012
          (directive === "use strict" && state.option.strict === "implied")) {
2013
        warning("W034", state.tokens.curr, directive);
156✔
2014
      }
2015

2016
      // From ECMAScript 2016:
2017
      //
2018
      // > 14.1.2 Static Semantics: Early Errors
2019
      // >
2020
      // > [...]
2021
      // > - It is a Syntax Error if ContainsUseStrict of FunctionBody is true
2022
      // >   and IsSimpleParameterList of FormalParameters is false.
2023
      if (directive === "use strict" && state.inES7() &&
1,044✔
2024
        !state.funct["(global)"] && state.funct["(hasSimpleParams)"] === false) {
2025
        error("E065", state.tokens.curr);
48✔
2026
      }
2027

2028
      // there's no directive negation, so always set to true
2029
      state.directive[directive] = true;
1,044✔
2030

2031
      parseFinalSemicolon(current);
1,044✔
2032
    }
2033

2034
    if (state.isStrict()) {
17,964✔
2035
      state.option.undef = true;
2,130✔
2036
    }
2037
  }
2038

2039
  /**
2040
   * Parses a single block. A block is a sequence of statements wrapped in
2041
   * braces.
2042
   *
2043
   * @param {number} context - parsing context
2044
   * @param {boolean} ordinary - `true` for everything but function bodies and
2045
   *                             try blocks
2046
   * @param {boolean} [stmt] - `true` if block can be a single statement (e.g.
2047
   *                           in if/for/while)
2048
   * @param {boolean} [isfunc] - `true` if block is a function body
2049
   * @param {boolean} [isfatarrow] - `true` if its a body of a fat arrow
2050
   *                                 function
2051
   * @param {boolean} [iscase] - `true` if block is a switch case block
2052
   *
2053
   * @returns {token} - the token describing the block
2054
   */
2055
  function block(context, ordinary, stmt, isfunc, isfatarrow, iscase) {
6✔
2056
    var a,
23,226✔
2057
      b = inblock,
2058
      old_indent = indent,
2059
      m,
2060
      t,
2061
      d;
2062

2063
    inblock = ordinary;
23,226✔
2064

2065
    t = state.tokens.next;
23,226✔
2066

2067
    var metrics = state.funct["(metrics)"];
23,226✔
2068
    metrics.nestedBlockDepth += 1;
23,226✔
2069
    metrics.verifyMaxNestedBlockDepthPerFunction();
23,226✔
2070

2071
    if (state.tokens.next.id === "{") {
23,226✔
2072
      advance("{");
20,472✔
2073

2074
      // create a new block scope
2075
      state.funct["(scope)"].stack();
20,472✔
2076

2077
      if (state.tokens.next.id !== "}") {
20,472✔
2078
        indent += state.option.indent;
13,374✔
2079
        while (!ordinary && state.tokens.next.from > indent) {
13,374✔
2080
          indent += state.option.indent;
14,814✔
2081
        }
2082

2083
        if (isfunc) {
13,374✔
2084
          m = {};
8,952✔
2085
          for (d in state.directive) {
8,952✔
2086
            m[d] = state.directive[d];
16,194✔
2087
          }
2088
          directives();
8,952✔
2089

2090
          state.funct["(isStrict)"] = state.isStrict();
8,952✔
2091

2092
          if (state.option.strict && state.funct["(context)"]["(global)"]) {
8,952✔
2093
            if (!m["use strict"] && !state.isStrict()) {
216✔
2094
              warning("E007");
54✔
2095
            }
2096
          }
2097
        }
2098

2099
        a = statements(context);
13,374✔
2100

2101
        metrics.statementCount += a.length;
13,326✔
2102

2103
        indent -= state.option.indent;
13,326✔
2104
      } else if (isfunc) {
7,098✔
2105
        // Ensure property is set for functions with empty bodies.
2106
        state.funct["(isStrict)"] = state.isStrict();
5,262✔
2107
      }
2108

2109
      advance("}", t);
20,424✔
2110

2111
      if (isfunc) {
20,388✔
2112
        state.funct["(scope)"].validateParams(isfatarrow);
14,184✔
2113
        if (m) {
14,184✔
2114
          state.directive = m;
8,922✔
2115
        }
2116
      }
2117

2118
      state.funct["(scope)"].unstack();
20,388✔
2119

2120
      indent = old_indent;
20,388✔
2121
    } else if (!ordinary) {
2,754✔
2122
      if (isfunc) {
972✔
2123
        state.funct["(scope)"].stack();
966✔
2124

2125
        if (stmt && !isfatarrow && !state.inMoz()) {
966✔
2126
          error("W118", state.tokens.curr, "function closure expressions");
24✔
2127
        }
2128

2129
        if (isfatarrow) {
966✔
2130
          state.funct["(scope)"].validateParams(true);
930✔
2131
        }
2132

2133
        var expr = expression(context, 10);
966✔
2134

2135
        if (state.option.noreturnawait && context & prodParams.async &&
966✔
2136
            expr.identifier && expr.value === "await") {
2137
          warning("W146", expr);
6✔
2138
        }
2139

2140
        if (state.option.strict && state.funct["(context)"]["(global)"]) {
966✔
2141
          if (!state.isStrict()) {
24✔
2142
            warning("E007");
24✔
2143
          }
2144
        }
2145

2146
        state.funct["(scope)"].unstack();
966✔
2147
      } else {
2148
        error("E021", state.tokens.next, "{", state.tokens.next.value);
6✔
2149
      }
2150
    } else {
2151

2152
      state.funct["(scope)"].stack();
1,782✔
2153

2154
      if (!stmt || state.option.curly) {
1,782✔
2155
        warning("W116", state.tokens.next, "{", state.tokens.next.value);
24✔
2156
      }
2157

2158
      // JSHint observes Annex B of the ECMAScript specification by default,
2159
      // where function declarations are permitted in the statement positions
2160
      // of IfStatements.
2161
      var supportsFnDecl = state.funct["(verb)"] === "if" ||
1,782✔
2162
        state.tokens.curr.id === "else";
2163

2164
      state.tokens.next.inBracelessBlock = true;
1,782✔
2165
      indent += state.option.indent;
1,782✔
2166
      // test indentation only if statement is in new line
2167
      a = [statement(context)];
1,782✔
2168
      indent -= state.option.indent;
1,782✔
2169

2170
      if (a[0] && a[0].declaration &&
1,782✔
2171
        !(supportsFnDecl && a[0].id === "function")) {
2172
        error("E048", a[0], a[0].id[0].toUpperCase() + a[0].id.slice(1));
162✔
2173
      }
2174

2175
      state.funct["(scope)"].unstack();
1,782✔
2176
    }
2177

2178
    // Don't clear and let it propagate out if it is "break", "return" or
2179
    // similar in switch case
2180
    switch (state.funct["(verb)"]) {
23,142✔
2181
    case "break":
2182
    case "continue":
2183
    case "return":
2184
    case "throw":
2185
      if (iscase) {
3,930✔
2186
        break;
48✔
2187
      }
2188

2189
      /* falls through */
2190
    default:
2191
      state.funct["(verb)"] = null;
23,094✔
2192
    }
2193

2194
    inblock = b;
23,142✔
2195
    if (ordinary && state.option.noempty && (!a || a.length === 0)) {
23,142✔
2196
      warning("W035", state.tokens.prev);
12✔
2197
    }
2198
    metrics.nestedBlockDepth -= 1;
23,142✔
2199
    return a;
23,142✔
2200
  }
2201

2202

2203
  /**
2204
   * Update the global state which tracks all statically-identifiable property
2205
   * names, and emit a warning if the `members` linting directive is in use and
2206
   * does not include the given name.
2207
   *
2208
   * @param {string} m - the property name
2209
   */
2210
  function countMember(m) {
6✔
2211
    if (membersOnly && typeof membersOnly[m] !== "boolean") {
8,748✔
2212
      warning("W036", state.tokens.curr, m);
24✔
2213
    }
2214
    if (typeof member[m] === "number") {
8,748✔
2215
      member[m] += 1;
3,060✔
2216
    } else {
2217
      member[m] = 1;
5,688✔
2218
    }
2219
  }
2220

2221
  // Build the syntax table by declaring the syntactic elements of the language.
2222

2223
  type("(number)", function() {
6✔
2224
    if (state.tokens.next.id === ".") {
22,506✔
2225
      warning("W005", this);
6✔
2226
    }
2227

2228
    return this;
22,506✔
2229
  });
2230

2231
  type("(string)", function() {
6✔
2232
    return this;
5,790✔
2233
  });
2234

2235
  state.syntax["(identifier)"] = {
6✔
2236
    type: "(identifier)",
2237
    lbp: 0,
2238
    identifier: true,
2239

2240
    nud: function(context) {
2241
      var v = this.value;
41,472✔
2242

2243
      // If this identifier is the lone parameter to a shorthand "fat arrow"
2244
      // function definition, i.e.
2245
      //
2246
      //     x => x;
2247
      //
2248
      // ...it should not be considered as a variable in the current scope. It
2249
      // will be added to the scope of the new function when the next token is
2250
      // parsed, so it can be safely ignored for now.
2251
      if (state.tokens.next.id === "=>") {
41,472✔
2252
        return this;
432✔
2253
      }
2254

2255
      if (isReserved(context, this)) {
41,040✔
2256
        warning("W024", this, v);
54✔
2257
      } else if (!state.funct["(comparray)"].check(v)) {
40,986✔
2258
        state.funct["(scope)"].block.use(v, state.tokens.curr);
39,348✔
2259
      }
2260
      return this;
41,040✔
2261
    },
2262

2263
    led: function() {
2264
      /* istanbul ignore next */
2265
      error("E033", state.tokens.next, state.tokens.next.value);
6✔
2266
    }
2267
  };
2268

2269
  var baseTemplateSyntax = {
6✔
2270
    identifier: false,
2271
    template: true,
2272
  };
2273
  state.syntax["(template)"] = _.extend({
6✔
2274
    lbp: 155,
2275
    type: "(template)",
2276
    nud: doTemplateLiteral,
2277
    led: doTemplateLiteral,
2278
    noSubst: false
2279
  }, baseTemplateSyntax);
2280

2281
  state.syntax["(template middle)"] = _.extend({
6✔
2282
    lbp: 0,
2283
    type: "(template middle)",
2284
    noSubst: false
2285
  }, baseTemplateSyntax);
2286

2287
  state.syntax["(template tail)"] = _.extend({
6✔
2288
    lbp: 0,
2289
    type: "(template tail)",
2290
    tail: true,
2291
    noSubst: false
2292
  }, baseTemplateSyntax);
2293

2294
  state.syntax["(no subst template)"] = _.extend({
6✔
2295
    lbp: 155,
2296
    type: "(template)",
2297
    nud: doTemplateLiteral,
2298
    led: doTemplateLiteral,
2299
    noSubst: true,
2300
    tail: true // mark as tail, since it's always the last component
2301
  }, baseTemplateSyntax);
2302

2303
  type("(regexp)", function() {
6✔
2304
    return this;
1,446✔
2305
  });
2306

2307
  // ECMAScript parser
2308

2309
  delim("(endline)");
6✔
2310
  (function(x) {
6✔
2311
    x.line = x.from = 0;
6✔
2312
  })(delim("(begin)"));
2313
  delim("(end)").reach = true;
6✔
2314
  delim("(error)").reach = true;
6✔
2315
  delim("}").reach = true;
6✔
2316
  delim(")");
6✔
2317
  delim("]");
6✔
2318
  delim("\"").reach = true;
6✔
2319
  delim("'").reach = true;
6✔
2320
  delim(";");
6✔
2321
  delim(":").reach = true;
6✔
2322
  delim("#");
6✔
2323

2324
  reserve("else");
6✔
2325
  reserve("case").reach = true;
6✔
2326
  reserve("catch");
6✔
2327
  reserve("default").reach = true;
6✔
2328
  reserve("finally");
6✔
2329
  reserve("true", function() { return this; });
2,088✔
2330
  reserve("false", function() { return this; });
630✔
2331
  reserve("null", function() { return this; });
906✔
2332
  reserve("this", function() {
6✔
2333
    if (state.isStrict() && !isMethod() &&
606✔
2334
        !state.option.validthis && ((state.funct["(statement)"] &&
2335
        state.funct["(name)"].charAt(0) > "Z") || state.funct["(global)"])) {
2336
      warning("W040", this);
60✔
2337
    }
2338

2339
    return this;
606✔
2340
  });
2341
  reserve("super", function() {
6✔
2342
    superNud.call(state.tokens.curr, this);
252✔
2343

2344
    return this;
252✔
2345
  });
2346

2347
  assignop("=", "assign", 20);
6✔
2348
  assignop("+=", "assignadd", 20);
6✔
2349
  assignop("-=", "assignsub", 20);
6✔
2350
  assignop("*=", "assignmult", 20);
6✔
2351
  assignop("/=", "assigndiv", 20).nud = function() {
6✔
2352
    /* istanbul ignore next */
2353
    error("E014");
6✔
2354
  };
2355
  assignop("%=", "assignmod", 20);
6✔
2356
  assignop("**=", function(context, left, that) {
6✔
2357
    if (!state.inES7()) {
84✔
2358
      warning("W119", that, "Exponentiation operator", "7");
48✔
2359
    }
2360

2361
    that.left = left;
84✔
2362

2363
    checkLeftSideAssign(context, left, that);
84✔
2364

2365
    that.right = expression(context, 10);
84✔
2366

2367
    return that;
84✔
2368
  }, 20);
2369

2370
  bitwiseassignop("&=");
6✔
2371
  bitwiseassignop("|=");
6✔
2372
  bitwiseassignop("^=");
6✔
2373
  bitwiseassignop("<<=");
6✔
2374
  bitwiseassignop(">>=");
6✔
2375
  bitwiseassignop(">>>=");
6✔
2376
  infix(",", function(context, left, that) {
6✔
2377
    var expr;
450✔
2378
    that.exprs = [left];
450✔
2379

2380
    if (state.option.nocomma) {
450✔
2381
      warning("W127");
6✔
2382
    }
2383

2384
    if (!parseComma({ peek: true })) {
450✔
2385
      return that;
30✔
2386
    }
2387
    while (true) {
420✔
2388
      if (!(expr = expression(context, 10))) {
486✔
2389
        /* istanbul ignore next */
2390
        break;
6✔
2391
      }
2392
      that.exprs.push(expr);
486✔
2393
      if (state.tokens.next.value !== "," || !parseComma()) {
486✔
2394
        break;
420✔
2395
      }
2396
    }
2397
    return that;
420✔
2398
  }, 10, true);
2399

2400
  infix("?", function(context, left, that) {
6✔
2401
    increaseComplexityCount();
414✔
2402
    that.left = left;
414✔
2403
    that.right = expression(context & ~prodParams.noin, 10);
414✔
2404
    advance(":");
414✔
2405
    expression(context, 10);
414✔
2406
    return that;
414✔
2407
  }, 30);
2408

2409
  var orPrecendence = 40;
6✔
2410
  infix("||", function(context, left, that) {
6✔
2411
    increaseComplexityCount();
390✔
2412
    that.left = left;
390✔
2413
    that.right = expression(context, orPrecendence);
390✔
2414
    return that;
390✔
2415
  }, orPrecendence);
2416
  infix("&&", "and", 50);
6✔
2417
  // The Exponentiation operator, introduced in ECMAScript 2016
2418
  //
2419
  // ExponentiationExpression[Yield] :
2420
  //   UnaryExpression[?Yield]
2421
  //   UpdateExpression[?Yield] ** ExponentiationExpression[?Yield]
2422
  infix("**", function(context, left, that) {
6✔
2423
    if (!state.inES7()) {
570✔
2424
      warning("W119", that, "Exponentiation operator", "7");
24✔
2425
    }
2426

2427
    // Disallow UnaryExpressions which are not wrapped in parenthesis
2428
    if (!left.paren && beginsUnaryExpression(left)) {
570✔
2429
      error("E024", that, "**");
42✔
2430
    }
2431

2432
    that.left = left;
570✔
2433
    that.right = expression(context, that.rbp);
570✔
2434
    return that;
570✔
2435
  }, 150);
2436
  state.syntax["**"].rbp = 140;
6✔
2437
  bitwise("|", "bitor", 70);
6✔
2438
  bitwise("^", "bitxor", 80);
6✔
2439
  bitwise("&", "bitand", 90);
6✔
2440
  relation("==", function(context, left, right) {
6✔
2441
    var eqnull = state.option.eqnull &&
156✔
2442
      ((left && left.value) === "null" || (right && right.value) === "null");
2443

2444
    switch (true) {
156✔
2445
      case !eqnull && state.option.eqeqeq:
2446
        this.from = this.character;
30✔
2447
        warning("W116", this, "===", "==");
30✔
2448
        break;
30✔
2449
      case isTypoTypeof(right, left, state):
2450
        /* istanbul ignore next */
2451
        warning("W122", this, right.value);
6✔
2452
        /* istanbul ignore next */
2453
        break;
6✔
2454
      case isTypoTypeof(left, right, state):
2455
        warning("W122", this, left.value);
12✔
2456
        break;
12✔
2457
    }
2458

2459
    return this;
156✔
2460
  });
2461
  relation("===", function(context, left, right) {
6✔
2462
    if (isTypoTypeof(right, left, state)) {
774✔
2463
      warning("W122", this, right.value);
18✔
2464
    } else if (isTypoTypeof(left, right, state)) {
756✔
2465
      /* istanbul ignore next */
2466
      warning("W122", this, left.value);
6✔
2467
    }
2468
    return this;
774✔
2469
  });
2470
  relation("!=", function(context, left, right) {
6✔
2471
    var eqnull = state.option.eqnull &&
120✔
2472
        ((left && left.value) === "null" || (right && right.value) === "null");
2473

2474
    if (!eqnull && state.option.eqeqeq) {
120✔
2475
      this.from = this.character;
18✔
2476
      warning("W116", this, "!==", "!=");
18✔
2477
    } else if (isTypoTypeof(right, left, state)) {
102✔
2478
      /* istanbul ignore next */
2479
      warning("W122", this, right.value);
6✔
2480
    } else if (isTypoTypeof(left, right, state)) {
102✔
2481
      warning("W122", this, left.value);
12✔
2482
    }
2483
    return this;
120✔
2484
  });
2485
  relation("!==", function(context, left, right) {
6✔
2486
    if (isTypoTypeof(right, left, state)) {
66✔
2487
      warning("W122", this, right.value);
12✔
2488
    } else if (isTypoTypeof(left, right, state)) {
54✔
2489
      /* istanbul ignore next */
2490
      warning("W122", this, left.value);
6✔
2491
    }
2492
    return this;
66✔
2493
  });
2494
  relation("<");
6✔
2495
  relation(">");
6✔
2496
  relation("<=");
6✔
2497
  relation(">=");
6✔
2498
  bitwise("<<", "shiftleft", 120);
6✔
2499
  bitwise(">>", "shiftright", 120);
6✔
2500
  bitwise(">>>", "shiftrightunsigned", 120);
6✔
2501
  infix("in", "in", 120);
6✔
2502
  infix("instanceof", function(context, left, token) {
6✔
2503
    var right;
306✔
2504
    var scope = state.funct["(scope)"];
306✔
2505
    token.left = left;
306✔
2506
    token.right = right = expression(context, 120);
306✔
2507

2508
    // This condition reflects a syntax error which will be reported by the
2509
    // `expression` function.
2510
    if (!right) {
306✔
2511
      return token;
6✔
2512
    }
2513

2514
    if (right.id === "(number)" ||
300✔
2515
        right.id === "(string)" ||
2516
        right.value === "null" ||
2517
        (right.value === "undefined" && !scope.has("undefined")) ||
2518
        right.arity === "unary" ||
2519
        right.id === "{" ||
2520
        (right.id === "[" && !right.right) ||
2521
        right.id === "(regexp)" ||
2522
        (right.id === "(template)" && !right.tag)) {
2523
      error("E060");
66✔
2524
    }
2525

2526
    if (right.id === "function") {
300✔
2527
      warning("W139");
12✔
2528
    }
2529

2530
    return token;
300✔
2531
  }, 120);
2532
  infix("+", function(context, left, that) {
6✔
2533
    var next = state.tokens.next;
2,988✔
2534
    var right;
2,988✔
2535
    that.left = left;
2,988✔
2536
    that.right = right = expression(context, 130);
2,988✔
2537

2538
    if (left && right && left.id === "(string)" && right.id === "(string)") {
2,988✔
2539
      left.value += right.value;
36✔
2540
      left.character = right.character;
36✔
2541
      if (!state.option.scripturl && reg.javascriptURL.test(left.value)) {
36✔
2542
        warning("W050", left);
6✔
2543
      }
2544
      return left;
36✔
2545
    }
2546

2547
    if (next.id === "+" || next.id === "++") {
2,952✔
2548
      warning("W007", that.right);
48✔
2549
    }
2550

2551
    return that;
2,952✔
2552
  }, 130);
2553
  prefix("+", function(context) {
6✔
2554
    var next = state.tokens.next;
168✔
2555
    this.arity = "unary";
168✔
2556
    this.right = expression(context, 150);
168✔
2557

2558
    if (next.id === "+" || next.id === "++") {
168✔
2559
      warning("W007", this.right);
12✔
2560
    }
2561

2562
    return this;
168✔
2563
  });
2564
  infix("-", function(context, left, that) {
6✔
2565
    var next = state.tokens.next;
282✔
2566
    that.left = left;
282✔
2567
    that.right = expression(context, 130);
282✔
2568

2569
    if (next.id === "-" || next.id === "--") {
282✔
2570
      warning("W006", that.right);
48✔
2571
    }
2572

2573
    return that;
282✔
2574
  }, 130);
2575
  prefix("-", function(context) {
6✔
2576
    var next = state.tokens.next;
138✔
2577
    this.arity = "unary";
138✔
2578
    this.right = expression(context, 150);
138✔
2579

2580
    if (next.id === "-" || next.id === "--") {
138✔
2581
      warning("W006", this.right);
12✔
2582
    }
2583

2584
    return this;
138✔
2585
  });
2586
  infix("*", "mult", 140);
6✔
2587
  infix("/", "div", 140);
6✔
2588
  infix("%", "mod", 140);
6✔
2589

2590
  suffix("++");
6✔
2591
  prefix("++", "preinc");
6✔
2592
  state.syntax["++"].exps = true;
6✔
2593
  state.syntax["++"].ltBoundary = "before";
6✔
2594

2595
  suffix("--");
6✔
2596
  prefix("--", "predec");
6✔
2597
  state.syntax["--"].exps = true;
6✔
2598
  state.syntax["--"].ltBoundary = "before";
6✔
2599

2600
  prefix("delete", function(context) {
6✔
2601
    this.arity = "unary";
162✔
2602
    var p = expression(context, 150);
162✔
2603
    if (!p) {
162✔
2604
      return this;
6✔
2605
    }
2606

2607
    if (p.id !== "." && p.id !== "[") {
156✔
2608
      warning("W051");
36✔
2609
    }
2610
    this.first = p;
156✔
2611

2612
    // The `delete` operator accepts unresolvable references when not in strict
2613
    // mode, so the operand may be undefined.
2614
    if (p.identifier && !state.isStrict()) {
156✔
2615
      p.forgiveUndef = true;
6✔
2616
    }
2617
    return this;
156✔
2618
  }).exps = true;
2619

2620
  prefix("~", function(context) {
6✔
2621
    if (state.option.bitwise) {
90✔
2622
      warning("W016", this, "~");
6✔
2623
    }
2624
    this.arity = "unary";
90✔
2625
    this.right = expression(context, 150);
90✔
2626
    return this;
90✔
2627
  });
2628

2629
  infix("...");
6✔
2630

2631
  prefix("!", function(context) {
6✔
2632
    this.arity = "unary";
588✔
2633
    this.right = expression(context, 150);
588✔
2634

2635
    if (!this.right) { // '!' followed by nothing? Give up.
582✔
2636
      /* istanbul ignore next */
2637
      quit("E041", this);
6✔
2638
    }
2639

2640
    if (bang[this.right.id] === true) {
582✔
2641
      /* istanbul ignore next */
2642
      warning("W018", this, "!");
6✔
2643
    }
2644
    return this;
582✔
2645
  });
2646

2647
  prefix("typeof", function(context) {
6✔
2648
    this.arity = "unary";
648✔
2649
    var p = expression(context, 150);
648✔
2650
    this.first = this.right = p;
648✔
2651

2652
    if (!p) { // 'typeof' followed by nothing? Give up.
648✔
2653
      quit("E041", this);
6✔
2654
    }
2655

2656
    // The `typeof` operator accepts unresolvable references, so the operand
2657
    // may be undefined.
2658
    if (p.identifier) {
642✔
2659
      p.forgiveUndef = true;
498✔
2660
    }
2661
    return this;
642✔
2662
  });
2663
  prefix("new", function(context) {
6✔
2664
    var mp = metaProperty(context, "target", function() {
798✔
2665
      if (!state.inES6(true)) {
198✔
2666
        warning("W119", state.tokens.prev, "new.target", "6");
6✔
2667
      }
2668
      var inFunction, c = state.funct;
198✔
2669
      while (c) {
198✔
2670
        inFunction = !c["(global)"];
270✔
2671
        if (!c["(arrow)"]) { break; }
270✔
2672
        c = c["(context)"];
72✔
2673
      }
2674
      if (!inFunction) {
198✔
2675
        warning("W136", state.tokens.prev, "new.target");
54✔
2676
      }
2677
    });
2678
    if (mp) { return mp; }
798✔
2679

2680
    var c = expression(context, 155), i;
594✔
2681
    if (c && c.id !== "function") {
594✔
2682
      if (c.identifier) {
582✔
2683
        switch (c.value) {
546✔
2684
        case "Number":
2685
        case "String":
2686
        case "Boolean":
2687
        case "Math":
2688
        case "JSON":
2689
          warning("W053", state.tokens.prev, c.value);
6✔
2690
          break;
6✔
2691
        case "Symbol":
2692
          if (state.inES6()) {
6✔
2693
            warning("W053", state.tokens.prev, c.value);
6✔
2694
          }
2695
          break;
6✔
2696
        case "Function":
2697
          if (!state.option.evil) {
12✔
2698
            warning("W054");
6✔
2699
          }
2700
          break;
12✔
2701
        case "Date":
2702
        case "RegExp":
2703
        case "this":
2704
          break;
18✔
2705
        default:
2706
          i = c.value.substr(0, 1);
504✔
2707
          if (state.option.newcap && (i < "A" || i > "Z") &&
504✔
2708
            !state.funct["(scope)"].isPredefined(c.value)) {
2709
            warning("W055", state.tokens.curr);
18✔
2710
          }
2711
        }
2712
      } else {
2713
        if (c.id !== "." && c.id !== "[" && c.id !== "(") {
36✔
2714
          /* istanbul ignore next */
2715
          warning("W056", state.tokens.curr);
6✔
2716
        }
2717
      }
2718
    } else {
2719
      if (!state.option.supernew)
12✔
2720
        warning("W057", this);
6✔
2721
    }
2722
    if (state.tokens.next.id !== "(" && !state.option.supernew) {
594✔
2723
      warning("W058", state.tokens.curr, state.tokens.curr.value);
30✔
2724
    }
2725
    this.first = this.right = c;
594✔
2726
    return this;
594✔
2727
  });
2728
  state.syntax["new"].exps = true;
6✔
2729

2730

2731
  // Class statement
2732
  blockstmt("class", function(context) {
6✔
2733
    var className, classNameToken;
786✔
2734
    var inexport = context & prodParams.export;
786✔
2735

2736
    if (!state.inES6()) {
786✔
2737
      warning("W104", state.tokens.curr, "class", "6");
36✔
2738
    }
2739
    state.inClassBody = true;
786✔
2740

2741
    // Class Declaration: 'class <Classname>'
2742
    if (state.tokens.next.identifier && state.tokens.next.value !== "extends") {
786✔
2743
      classNameToken = state.tokens.next;
786✔
2744
      className = classNameToken.value;
786✔
2745
      identifier(context);
786✔
2746
      // unintialized, so that the 'extends' clause is parsed while the class is in TDZ
2747
      state.funct["(scope)"].addlabel(className, {
786✔
2748
        type: "class",
2749
        initialized: false,
2750
        token: classNameToken
2751
      });
2752
    }
2753

2754
    // Class Declaration: 'class <Classname> extends <Superclass>'
2755
    if (state.tokens.next.value === "extends") {
786✔
2756
      advance("extends");
312✔
2757
      expression(context, 0);
312✔
2758
    }
2759

2760
    if (classNameToken) {
786✔
2761
      this.name = className;
786✔
2762
      state.funct["(scope)"].initialize(className);
786✔
2763
      if (inexport) {
786✔
2764
        state.funct["(scope)"].setExported(className, classNameToken);
84✔
2765
      }
2766
    }
2767
    state.funct["(scope)"].stack();
786✔
2768
    classBody(this, context);
786✔
2769
    return this;
774✔
2770
  }).exps = true;
2771

2772
  /*
2773
    Class expression
2774

2775
    The Block- and Expression- handling for "class" are almost identical, except for the ordering of steps.
2776
    In an expression:, the name should not be saved into the calling scope, but is still accessible inside the definition, so we open a new scope first, then save the name. We also mark it as used.
2777
  */
2778
  prefix("class", function(context) {
6✔
2779
    var className, classNameToken;
858✔
2780

2781
    if (!state.inES6()) {
858✔
2782
      warning("W104", state.tokens.curr, "class", "6");
6✔
2783
    }
2784
    state.inClassBody = true;
858✔
2785

2786
    // Class Declaration: 'class <Classname>'
2787
    if (state.tokens.next.identifier && state.tokens.next.value !== "extends") {
858✔
2788
      classNameToken = state.tokens.next;
204✔
2789
      className = classNameToken.value;
204✔
2790
      identifier(context);
204✔
2791
    }
2792

2793
    // Class Declaration: 'class <Classname> extends <Superclass>'
2794
    if (state.tokens.next.value === "extends") {
858✔
2795
      advance("extends");
492✔
2796
      expression(context, 0);
492✔
2797
    }
2798

2799
    state.funct["(scope)"].stack();
858✔
2800
    if (classNameToken) {
858✔
2801
      this.name = className;
204✔
2802
      state.funct["(scope)"].addlabel(className, {
204✔
2803
        type: "class",
2804
        initialized: true,
2805
        token: classNameToken
2806
      });
2807
      state.funct["(scope)"].block.use(className, classNameToken);
204✔
2808
    }
2809

2810
    classBody(this, context);
858✔
2811
    return this;
858✔
2812
  });
2813

2814
  function classBody(classToken, context) {
6✔
2815
    var props = Object.create(null);
1,644✔
2816
    var name, accessorType, token, isStatic, inGenerator, hasConstructor;
1,644✔
2817

2818
    if (state.tokens.next.value === "{") {
1,644✔
2819
      advance("{");
1,644✔
2820
    } else {
2821
      /* istanbul ignore next */
2822
      warning("W116", state.tokens.curr, "identifier", state.tokens.next.type); //?
6✔
2823
      /* istanbul ignore next */
2824
      advance();
6✔
2825
    }
2826

2827
    while (state.tokens.next.value !== "}") {
1,644✔
2828
      isStatic = false;
1,566✔
2829
      inGenerator = false;
1,566✔
2830
      context &= ~prodParams.preAsync;
1,566✔
2831

2832
      if (state.tokens.next.value === "static") {
1,566✔
2833
        isStatic = true;
390✔
2834
        advance();
390✔
2835
      }
2836

2837
      if (state.tokens.next.value === "async") {
1,566✔
2838
        if (!checkPunctuator(peek(), "(")) {
114✔
2839
          context |= prodParams.preAsync;
114✔
2840
          advance();
114✔
2841

2842
          nolinebreak(state.tokens.curr);
114✔
2843

2844
          if (checkPunctuator(state.tokens.next, "*")) {
114✔
2845
            inGenerator = true;
36✔
2846
            advance("*");
36✔
2847

2848
            if (!state.inES9()) {
36✔
2849
              warning("W119", state.tokens.next, "async generators", "9");
6✔
2850
            }
2851
          }
2852

2853
          if (!state.inES8()) {
114✔
2854
            warning("W119", state.tokens.curr, "async functions", "8");
18✔
2855
          }
2856
        }
2857
      }
2858

2859
      if (state.tokens.next.value === "*") {
1,566✔
2860
        inGenerator = true;
150✔
2861
        advance();
150✔
2862
      }
2863

2864
      token = state.tokens.next;
1,566✔
2865

2866
      if ((token.value === "set" || token.value === "get") && !checkPunctuator(peek(), "(")) {
1,566✔
2867
        if (inGenerator) {
282✔
2868
          /* istanbul ignore next */
2869
          error("E024", token, token.value);
6✔
2870
        }
2871
        accessorType = token.value;
282✔
2872
        advance();
282✔
2873
        token = state.tokens.next;
282✔
2874

2875
        if (!isStatic && token.value === "constructor") {
282✔
2876
          error("E049", token, "class " + accessorType + "ter method", token.value);
12✔
2877
        } else if (isStatic && token.value === "prototype") {
270✔
2878
          error("E049", token, "static class " + accessorType + "ter method", token.value);
6✔
2879
        }
2880
      } else {
2881
        accessorType = null;
1,284✔
2882
      }
2883

2884
      switch (token.value) {
1,566✔
2885
        case ";":
2886
          warning("W032", token);
30✔
2887
          advance();
30✔
2888
          break;
30✔
2889
        case "constructor":
2890
          if (isStatic) {
432✔
2891
            // treat like a regular method -- static methods can be called 'constructor'
2892
            name = propertyName(context);
18✔
2893
            saveProperty(props, name, token, true, isStatic);
18✔
2894
            doMethod(classToken, context, name, inGenerator);
18✔
2895
          } else {
2896
            if (inGenerator || context & prodParams.preAsync) {
414✔
2897
              error("E024", token, token.value);
12✔
2898
            } else if (hasConstructor) {
402✔
2899
              /* istanbul ignore next */
2900
              error("E024", token, token.value);
6✔
2901
            } else {
2902
              hasConstructor = !accessorType && !isStatic;
402✔
2903
            }
2904
            advance();
414✔
2905
            doMethod(classToken, context, state.nameStack.infer());
414✔
2906
          }
2907
          break;
426✔
2908
        case "[":
2909
          name = computedPropertyName(context);
126✔
2910
          doMethod(classToken, context, name, inGenerator);
126✔
2911
          // We don't check names (via calling saveProperty()) of computed expressions like ["Symbol.iterator"]()
2912
          break;
126✔
2913
        default:
2914
          name = propertyName(context);
978✔
2915
          if (name === undefined) {
978✔
2916
            error("E024", token, token.value);
6✔
2917
            advance();
6✔
2918
            break;
6✔
2919
          }
2920

2921
          if (accessorType) {
972✔
2922
            saveAccessor(accessorType, props, name, token, true, isStatic);
252✔
2923
            name = state.nameStack.infer();
252✔
2924
          } else {
2925
            if (isStatic && name === "prototype") {
720✔
2926
              error("E049", token, "static class method", name);
6✔
2927
            }
2928

2929
            saveProperty(props, name, token, true, isStatic);
720✔
2930
          }
2931

2932
          doMethod(classToken, context, name, inGenerator);
972✔
2933
          break;
966✔
2934
      }
2935
    }
2936
    advance("}");
1,632✔
2937
    checkProperties(props);
1,632✔
2938

2939
    state.inClassBody = false;
1,632✔
2940
    state.funct["(scope)"].unstack();
1,632✔
2941
  }
2942

2943
  function doMethod(classToken, context, name, generator) {
6✔
2944
    if (generator) {
1,530✔
2945
      if (!state.inES6()) {
180✔
2946
        warning("W119", state.tokens.curr, "function*", "6");
12✔
2947
      }
2948
    }
2949

2950
    if (state.tokens.next.value !== "(") {
1,530✔
2951
      error("E054", state.tokens.next, state.tokens.next.value);
48✔
2952
      advance();
48✔
2953
      if (state.tokens.next.value === "{") {
42✔
2954
        // manually cheating the test "invalidClasses", which asserts this particular behavior when a class is misdefined.
2955
        advance();
6✔
2956
        if (state.tokens.next.value === "}") {
6✔
2957
          warning("W116", state.tokens.next, "(", state.tokens.next.value);
6✔
2958
          advance();
6✔
2959
          identifier(context);
6✔
2960
          advance();
6✔
2961
        }
2962
        /* istanbul ignore next */
2963
        return;
6✔
2964
      } else {
2965
        while (state.tokens.next.value !== "(") {
36✔
2966
          advance();
18✔
2967
        }
2968
      }
2969
    }
2970

2971
    doFunction(context, { name: name,
1,518✔
2972
        type: generator ? "generator" : null,
2973
        isMethod: true,
2974
        statement: classToken });
2975
  }
2976

2977
  prefix("void").exps = true;
6✔
2978

2979
  infix(".", function(context, left, that) {
6✔
2980
    var m = identifier(context, true);
4,116✔
2981

2982
    if (typeof m === "string") {
4,116✔
2983
      countMember(m);
4,116✔
2984
    }
2985

2986
    that.left = left;
4,116✔
2987
    that.right = m;
4,116✔
2988

2989
    if (m && m === "hasOwnProperty" && state.tokens.next.value === "=") {
4,116✔
2990
      warning("W001");
30✔
2991
    }
2992

2993
    if (left && left.value === "arguments" && (m === "callee" || m === "caller")) {
4,116✔
2994
      if (state.option.noarg)
48✔
2995
        warning("W059", left, m);
12✔
2996
      else if (state.isStrict())
36✔
2997
        error("E008");
24✔
2998
    } else if (!state.option.evil && left && left.value === "document" &&
4,068✔
2999
        (m === "write" || m === "writeln")) {
3000
      warning("W060", left);
12✔
3001
    }
3002

3003
    if (!state.option.evil && (m === "eval" || m === "execScript")) {
4,116✔
3004
      if (isGlobalEval(left, state)) {
60✔
3005
        warning("W061");
36✔
3006
      }
3007
    }
3008

3009
    return that;
4,116✔
3010
  }, 160, true);
3011

3012
  infix("(", function(context, left, that) {
6✔
3013
    if (state.option.immed && left && !left.immed && left.id === "function") {
11,172✔
3014
      warning("W062");
6✔
3015
    }
3016

3017
    if (state.option.asi && checkPunctuators(state.tokens.prev, [")", "]"]) &&
11,172✔
3018
      state.tokens.prev.line !== startLine(state.tokens.curr)) {
3019
      warning("W014", state.tokens.curr, state.tokens.curr.id);
18✔
3020
    }
3021

3022
    var n = 0;
11,172✔
3023
    var p = [];
11,172✔
3024

3025
    if (left) {
11,172✔
3026
      if (left.type === "(identifier)") {
11,172✔
3027
        if (left.value.match(/^[A-Z]([A-Z0-9_$]*[a-z][A-Za-z0-9_$]*)?$/)) {
8,598✔
3028
          if ("Array Number String Boolean Date Object Error Symbol".indexOf(left.value) === -1) {
210✔
3029
            if (left.value === "Math") {
66✔
3030
              /* istanbul ignore next */
3031
              warning("W063", left);
6✔
3032
            } else if (state.option.newcap) {
66✔
3033
              warning("W064", left);
6✔
3034
            }
3035
          }
3036
        }
3037
      }
3038
    }
3039

3040
    if (state.tokens.next.id !== ")") {
11,172✔
3041
      for (;;) {
4,968✔
3042
        spreadrest("spread");
6,240✔
3043

3044
        p[p.length] = expression(context, 10);
6,240✔
3045
        n += 1;
6,228✔
3046
        if (state.tokens.next.id !== ",") {
6,228✔
3047
          break;
4,932✔
3048
        }
3049
        parseComma({ allowTrailing: true });
1,296✔
3050

3051
        if (state.tokens.next.id === ")") {
1,296✔
3052
          if (!state.inES8()) {
24✔
3053
            warning("W119", state.tokens.curr, "Trailing comma in arguments lists", "8");
6✔
3054
          }
3055

3056
          break;
24✔
3057
        }
3058
      }
3059
    }
3060

3061
    advance(")");
11,160✔
3062

3063
    if (typeof left === "object") {
11,160✔
3064
      if (!state.inES5() && left.value === "parseInt" && n === 1) {
11,160✔
3065
        warning("W065", state.tokens.curr);
6✔
3066
      }
3067
      if (!state.option.evil) {
11,160✔
3068
        if (left.value === "eval" || left.value === "Function" ||
11,094✔
3069
            left.value === "execScript") {
3070
          warning("W061", left);
72✔
3071

3072
          // This conditional expression was initially implemented with a typo
3073
          // which prevented the branch's execution in all cases. While
3074
          // enabling the code will produce behavior that is consistent with
3075
          // the other forms of code evaluation that follow, such a change is
3076
          // also technically incompatable with prior versions of JSHint (due
3077
          // to the fact that the behavior was never formally documented). This
3078
          // branch should be enabled as part of a major release.
3079
          //if (p[0] && p[0].id === "(string)") {
3080
          //  addEvalCode(left, p[0]);
3081
          //}
3082
        } else if (p[0] && p[0].id === "(string)" &&
11,022✔
3083
             (left.value === "setTimeout" ||
3084
            left.value === "setInterval")) {
3085
          warning("W066", left);
24✔
3086
          addEvalCode(left, p[0]);
24✔
3087

3088
        // window.setTimeout/setInterval
3089
        } else if (p[0] && p[0].id === "(string)" &&
10,998✔
3090
             left.value === "." &&
3091
             left.left.value === "window" &&
3092
             (left.right === "setTimeout" ||
3093
            left.right === "setInterval")) {
3094
          warning("W066", left);
12✔
3095
          addEvalCode(left, p[0]);
12✔
3096
        }
3097
      }
3098
      if (!left.identifier && left.id !== "." && left.id !== "[" && left.id !== "=>" &&
11,154✔
3099
          left.id !== "(" && left.id !== "&&" && left.id !== "||" && left.id !== "?" &&
3100
          left.id !== "async" && !(state.inES6() && left["(name)"])) {
3101
        warning("W067", that);
6✔
3102
      }
3103
    }
3104

3105
    that.left = left;
11,154✔
3106
    return that;
11,154✔
3107
  }, 155, true).exps = true;
3108

3109
  function peekThroughParens(parens) {
6✔
3110
    var pn = state.tokens.next;
7,200✔
3111
    var i = -1;
7,200✔
3112
    var pn1;
7,200✔
3113

3114
    do {
7,200✔
3115
      if (pn.value === "(") {
81,318✔
3116
        parens += 1;
6,846✔
3117
      } else if (pn.value === ")") {
74,472✔
3118
        parens -= 1;
13,710✔
3119
      }
3120

3121
      i += 1;
81,318✔
3122
      pn1 = pn;
81,318✔
3123
      pn = peek(i);
81,318✔
3124
    } while (!(parens === 0 && pn1.value === ")") && pn.type !== "(end)");
3125

3126
    return pn;
7,200✔
3127
  }
3128

3129
  prefix("(", function(context, rbp) {
6✔
3130
    var ret, triggerFnExpr, first, last;
6,888✔
3131
    var opening = state.tokens.curr;
6,888✔
3132
    var preceeding = state.tokens.prev;
6,888✔
3133
    var isNecessary = !state.option.singleGroups;
6,888✔
3134
    var pn = peekThroughParens(1);
6,888✔
3135

3136
    if (state.tokens.next.id === "function") {
6,888✔
3137
      triggerFnExpr = state.tokens.next.immed = true;
1,800✔
3138
    }
3139

3140
    // If the balanced grouping operator is followed by a "fat arrow", the
3141
    // current token marks the beginning of a "fat arrow" function and parsing
3142
    // should proceed accordingly.
3143
    if (pn.value === "=>") {
6,888✔
3144
      pn.funct = doFunction(context, { type: "arrow", parsedOpening: true });
1,782✔
3145
      return pn;
1,782✔
3146
    }
3147

3148
    var exprs = [];
5,106✔
3149

3150
    if (state.tokens.next.id !== ")") {
5,106✔
3151
      for (;;) {
5,088✔
3152
        exprs.push(expression(context, 10));
5,832✔
3153

3154
        if (state.tokens.next.id !== ",") {
5,802✔
3155
          break;
5,058✔
3156
        }
3157

3158
        if (state.option.nocomma) {
744✔
3159
          warning("W127");
6✔
3160
        }
3161

3162
        parseComma();
744✔
3163
      }
3164
    }
3165

3166
    advance(")", this);
5,076✔
3167
    if (state.option.immed && exprs[0] && exprs[0].id === "function") {
5,076✔
3168
      if (state.tokens.next.id !== "(" &&
36✔
3169
        state.tokens.next.id !== "." && state.tokens.next.id !== "[") {
3170
        warning("W068", this);
6✔
3171
      }
3172
    }
3173

3174
    if (!exprs.length) {
5,076✔
3175
      return;
18✔
3176
    }
3177
    if (exprs.length > 1) {
5,058✔
3178
      ret = Object.create(state.syntax[","]);
264✔
3179
      ret.exprs = exprs;
264✔
3180

3181
      first = exprs[0];
264✔
3182
      last = exprs[exprs.length - 1];
264✔
3183
    } else {
3184
      ret = first = last = exprs[0];
4,794✔
3185

3186
      if (!isNecessary) {
4,794✔
3187
        isNecessary =
1,530✔
3188
          // Used to distinguish from an ExpressionStatement which may not
3189
          // begin with the `{` and `function` tokens
3190
          (opening.beginsStmt && (ret.id === "{" || triggerFnExpr)) ||
3191
          // Used to signal that a function expression is being supplied to
3192
          // some other operator.
3193
          (triggerFnExpr &&
3194
            // For parenthesis wrapping a function expression to be considered
3195
            // necessary, the grouping operator should be the left-hand-side of
3196
            // some other operator--either within the parenthesis or directly
3197
            // following them.
3198
            (!isEndOfExpr() || state.tokens.prev.id !== "}")) ||
3199
          // Used to demarcate an arrow function as the left-hand side of some
3200
          // operator.
3201
          (ret.id === "=>" && !isEndOfExpr()) ||
3202
          // Used as the return value of a single-statement arrow function
3203
          (ret.id === "{" && preceeding.id === "=>") ||
3204
          // Used to cover a unary expression as the left-hand side of the
3205
          // exponentiation operator
3206
          (beginsUnaryExpression(ret) && state.tokens.next.id === "**") ||
3207
          // Used to delineate an integer number literal from a dereferencing
3208
          // punctuator (otherwise interpreted as a decimal point)
3209
          (ret.type === "(number)" &&
3210
            checkPunctuator(pn, ".") && /^\d+$/.test(ret.value)) ||
3211
          // Used to wrap object destructuring assignment
3212
          (opening.beginsStmt && ret.id === "=" && ret.left.id === "{");
3213
      }
3214
    }
3215

3216
    if (ret) {
5,058✔
3217
      // The operator may be necessary to override the default binding power of
3218
      // neighboring operators (whenever there is an operator in use within the
3219
      // first expression *or* the current group contains multiple expressions)
3220
      if (!isNecessary && (isOperator(first) || ret.exprs)) {
5,046✔
3221
        isNecessary =
1,044✔
3222
          (rbp > first.lbp) ||
3223
          (rbp > 0 && rbp === first.lbp) ||
3224
          (!isEndOfExpr() && last.rbp < state.tokens.next.lbp);
3225
      }
3226

3227
      if (!isNecessary) {
5,046✔
3228
        warning("W126", opening);
738✔
3229
      }
3230

3231
      ret.paren = true;
5,046✔
3232
    }
3233

3234
    return ret;
5,058✔
3235
  });
3236

3237
  application("=>");
6✔
3238

3239
  infix("[", function(context, left, that) {
6✔
3240
    var e, s, canUseDot;
738✔
3241

3242
    if (state.option.asi && checkPunctuators(state.tokens.prev, [")", "]"]) &&
738✔
3243
      state.tokens.prev.line !== startLine(state.tokens.curr)) {
3244
      warning("W014", state.tokens.curr, state.tokens.curr.id);
6✔
3245
    }
3246

3247
    e = expression(context & ~prodParams.noin, 10);
738✔
3248

3249
    if (e && e.type === "(string)") {
738✔
3250
      if (!state.option.evil && (e.value === "eval" || e.value === "execScript")) {
234✔
3251
        if (isGlobalEval(left, state)) {
36✔
3252
          warning("W061");
24✔
3253
        }
3254
      }
3255

3256
      countMember(e.value);
234✔
3257
      if (!state.option.sub && reg.identifier.test(e.value)) {
234✔
3258
        s = state.syntax[e.value];
156✔
3259

3260
        if (s) {
156✔
3261
          canUseDot = !isReserved(context, s);
36✔
3262
        } else {
3263
          // This branch exists to preserve legacy behavior with version 2.9.5
3264
          // and earlier. In those releases, `eval` and `arguments` were
3265
          // incorrectly interpreted as reserved keywords, so Member
3266
          // Expressions such as `object["eval"]` did not trigger warning W069.
3267
          //
3268
          // TODO: Remove in JSHint 3
3269
          canUseDot = e.value !== "eval" && e.value !== "arguments";
120✔
3270
        }
3271

3272
        if (canUseDot) {
156✔
3273
          warning("W069", state.tokens.prev, e.value);
102✔
3274
        }
3275
      }
3276
    }
3277
    advance("]", that);
738✔
3278

3279
    if (e && e.value === "hasOwnProperty" && state.tokens.next.value === "=") {
738✔
3280
      warning("W001");
24✔
3281
    }
3282

3283
    that.left = left;
738✔
3284
    that.right = e;
738✔
3285
    return that;
738✔
3286
  }, 160, true);
3287

3288
  function comprehensiveArrayExpression(context) {
6✔
3289
    var res = {};
402✔
3290
    res.exps = true;
402✔
3291
    state.funct["(comparray)"].stack();
402✔
3292

3293
    // Handle reversed for expressions, used in spidermonkey
3294
    var reversed = false;
402✔
3295
    if (state.tokens.next.value !== "for") {
402✔
3296
      reversed = true;
210✔
3297
      if (!state.inMoz()) {
210✔
3298
        warning("W116", state.tokens.next, "for", state.tokens.next.value);
126✔
3299
      }
3300
      state.funct["(comparray)"].setState("use");
210✔
3301
      res.right = expression(context, 10);
210✔
3302
    }
3303

3304
    advance("for");
402✔
3305
    if (state.tokens.next.value === "each") {
402✔
3306
      advance("each");
174✔
3307
      if (!state.inMoz()) {
174✔
3308
        warning("W118", state.tokens.curr, "for each");
126✔
3309
      }
3310
    }
3311
    advance("(");
402✔
3312
    state.funct["(comparray)"].setState("define");
402✔
3313
    res.left = expression(context, 130);
402✔
3314
    if (_.includes(["in", "of"], state.tokens.next.value)) {
402✔
3315
      advance();
402✔
3316
    } else {
3317
      /* istanbul ignore next */
3318
      error("E045", state.tokens.curr);
6✔
3319
    }
3320
    state.funct["(comparray)"].setState("generate");
402✔
3321
    expression(context, 10);
402✔
3322

3323
    advance(")");
402✔
3324
    if (state.tokens.next.value === "if") {
402✔
3325
      advance("if");
66✔
3326
      advance("(");
66✔
3327
      state.funct["(comparray)"].setState("filter");
66✔
3328
      expression(context, 10);
66✔
3329
      advance(")");
66✔
3330
    }
3331

3332
    if (!reversed) {
402✔
3333
      state.funct["(comparray)"].setState("use");
192✔
3334
      res.right = expression(context, 10);
192✔
3335
    }
3336

3337
    advance("]");
402✔
3338
    state.funct["(comparray)"].unstack();
402✔
3339
    return res;
402✔
3340
  }
3341

3342
  prefix("[", function(context) {
6✔
3343
    var blocktype = lookupBlockType();
7,038✔
3344
    if (blocktype.isCompArray) {
7,038✔
3345
      if (!state.option.esnext && !state.inMoz()) {
402✔
3346
        warning("W118", state.tokens.curr, "array comprehension");
186✔
3347
      }
3348
      return comprehensiveArrayExpression(context);
402✔
3349
    } else if (blocktype.isDestAssign) {
6,636✔
3350
      this.destructAssign = destructuringPattern(context, {
594✔
3351
          openingParsed: true,
3352
          assignment: true
3353
        });
3354
      return this;
594✔
3355
    }
3356
    var b = state.tokens.curr.line !== startLine(state.tokens.next);
6,042✔
3357
    this.first = [];
6,042✔
3358
    if (b) {
6,042✔
3359
      indent += state.option.indent;
84✔
3360
      if (state.tokens.next.from === indent + state.option.indent) {
84✔
3361
        /* istanbul ignore next */
3362
        indent += state.option.indent;
6✔
3363
      }
3364
    }
3365
    while (state.tokens.next.id !== "(end)") {
6,042✔
3366
      while (state.tokens.next.id === ",") {
15,102✔
3367
        if (!state.option.elision) {
222✔
3368
          if (!state.inES5()) {
96✔
3369
            // Maintain compat with old options --- ES5 mode without
3370
            // elision=true will warn once per comma
3371
            warning("W070");
72✔
3372
          } else {
3373
            warning("W128");
24✔
3374
            do {
24✔
3375
              advance(",");
42✔
3376
            } while (state.tokens.next.id === ",");
3377
            continue;
24✔
3378
          }
3379
        }
3380
        advance(",");
198✔
3381
      }
3382

3383
      if (state.tokens.next.id === "]") {
15,102✔
3384
        break;
624✔
3385
      }
3386

3387
      spreadrest("spread");
14,478✔
3388

3389
      this.first.push(expression(context, 10));
14,478✔
3390
      if (state.tokens.next.id === ",") {
14,478✔
3391
        parseComma({ allowTrailing: true });
9,096✔
3392
        if (state.tokens.next.id === "]" && !state.inES5()) {
9,096✔
3393
          warning("W070", state.tokens.curr);
36✔
3394
          break;
36✔
3395
        }
3396
      } else {
3397
        if (state.option.trailingcomma && state.inES5()) {
5,382✔
3398
          warningAt("W140", state.tokens.curr.line, state.tokens.curr.character);
24✔
3399
        }
3400
        break;
5,382✔
3401
      }
3402
    }
3403
    if (b) {
6,042✔
3404
      indent -= state.option.indent;
84✔
3405
    }
3406
    advance("]", this);
6,042✔
3407
    return this;
6,042✔
3408
  });
3409

3410

3411
  function isMethod() {
6✔
3412
    return !!state.funct["(method)"];
174✔
3413
  }
3414

3415
  function propertyName(context, preserveOrToken) {
6✔
3416
    var id;
5,136✔
3417
    var preserve = true;
5,136✔
3418
    if (typeof preserveOrToken === "object") {
5,136✔
3419
      /* istanbul ignore next */
3420
      id = preserveOrToken;
6✔
3421
    } else {
3422
      preserve = preserveOrToken;
5,136✔
3423
      id = optionalidentifier(context, true, preserve);
5,136✔
3424
    }
3425

3426
    if (!id) {
5,136✔
3427
      if (state.tokens.next.id === "(string)") {
204✔
3428
        id = state.tokens.next.value;
84✔
3429
        if (!preserve) {
84✔
3430
          advance();
84✔
3431
        }
3432
      } else if (state.tokens.next.id === "(number)") {
120✔
3433
        id = state.tokens.next.value.toString();
30✔
3434
        if (!preserve) {
30✔
3435
          advance();
30✔
3436
        }
3437
      }
3438
    } else if (typeof id === "object") {
4,932✔
3439
      /* istanbul ignore next */
3440
      if (id.id === "(string)" || id.id === "(identifier)") id = id.value;
6✔
3441
      /* istanbul ignore next */
3442
      else if (id.id === "(number)") id = id.value.toString();
6✔
3443
    }
3444

3445
    if (id === "hasOwnProperty") {
5,136✔
3446
      warning("W001");
48✔
3447
    }
3448

3449
    return id;
5,136✔
3450
  }
3451

3452
  /**
3453
   * @param {Number} context The parsing context
3454
   * @param {Object} [options]
3455
   * @param {token} [options.loneArg] The argument to the function in cases
3456
   *                                  where it was defined using the
3457
   *                                  single-argument shorthand.
3458
   * @param {bool} [options.parsedOpening] Whether the opening parenthesis has
3459
   *                                       already been parsed.
3460
   *
3461
   * @returns {{ arity: number, params: Array.<string>, isSimple: boolean }}
3462
   */
3463
  function functionparams(context, options) {
6✔
3464
    var next;
15,210✔
3465
    var paramsIds = [];
15,210✔
3466
    var ident;
15,210✔
3467
    var tokens = [];
15,210✔
3468
    var t;
15,210✔
3469
    var pastDefault = false;
15,210✔
3470
    var pastRest = false;
15,210✔
3471
    var arity = 0;
15,210✔
3472
    var loneArg = options && options.loneArg;
15,210✔
3473
    var hasDestructuring = false;
15,210✔
3474

3475
    if (loneArg && loneArg.identifier === true) {
15,210✔
3476
      state.funct["(scope)"].addParam(loneArg.value, loneArg);
432✔
3477
      return { arity: 1, params: [ loneArg.value ], isSimple: true };
432✔
3478
    }
3479

3480
    next = state.tokens.next;
14,778✔
3481

3482
    if (!options || !options.parsedOpening) {
14,778✔
3483
      advance("(");
12,996✔
3484
    }
3485

3486
    if (state.tokens.next.id === ")") {
14,772✔
3487
      advance(")");
11,184✔
3488
      return;
11,184✔
3489
    }
3490

3491
    function addParam(addParamArgs) {
6✔
3492
      state.funct["(scope)"].addParam.apply(state.funct["(scope)"], addParamArgs);
5,670✔
3493
    }
3494

3495
    for (;;) {
3,588✔
3496
      arity++;
5,112✔
3497
      // are added to the param scope
3498
      var currentParams = [];
5,112✔
3499

3500
      if (_.includes(["{", "["], state.tokens.next.id)) {
5,112✔
3501
        hasDestructuring = true;
930✔
3502
        tokens = destructuringPattern(context);
930✔
3503
        for (t in tokens) {
924✔
3504
          t = tokens[t];
4,332✔
3505
          if (t.id) {
4,332✔
3506
            paramsIds.push(t.id);
1,512✔
3507
            currentParams.push([t.id, t.token]);
1,512✔
3508
          }
3509
        }
3510
      } else {
3511
        pastRest = spreadrest("rest");
4,182✔
3512
        ident = identifier(context);
4,182✔
3513

3514
        if (ident) {
4,182✔
3515
          paramsIds.push(ident);
4,158✔
3516
          currentParams.push([ident, state.tokens.curr]);
4,158✔
3517
        } else {
3518
          // Skip invalid parameter.
3519
          while (!checkPunctuators(state.tokens.next, [",", ")"])) advance();
42✔
3520
        }
3521
      }
3522

3523
      // It is valid to have a regular argument after a default argument
3524
      // since undefined can be used for missing parameters. Still warn as it is
3525
      // a possible code smell.
3526
      if (pastDefault) {
5,088✔
3527
        if (state.tokens.next.id !== "=") {
174✔
3528
          error("W138", state.tokens.curr);
18✔
3529
        }
3530
      }
3531
      if (state.tokens.next.id === "=") {
5,088✔
3532
        if (!state.inES6()) {
648✔
3533
          warning("W119", state.tokens.next, "default parameters", "6");
78✔
3534
        }
3535

3536
        if (pastRest) {
648✔
3537
          error("E062", state.tokens.next);
6✔
3538
        }
3539

3540
        advance("=");
648✔
3541
        pastDefault = true;
648✔
3542
        expression(context, 10);
648✔
3543
      }
3544

3545
      // now we have evaluated the default expression, add the variable to the param scope
3546
      currentParams.forEach(addParam);
5,088✔
3547
      if (state.tokens.next.id === ",") {
5,088✔
3548
        if (pastRest) {
1,548✔
3549
          warning("W131", state.tokens.next);
12✔
3550
        }
3551
        parseComma({ allowTrailing: true });
1,548✔
3552
      }
3553

3554
      if (state.tokens.next.id === ")") {
5,088✔
3555
        if (state.tokens.curr.id === "," && !state.inES8()) {
3,564✔
3556
          warning("W119", state.tokens.curr, "Trailing comma in function parameters", "8");
18✔
3557
        }
3558

3559
        advance(")", next);
3,564✔
3560
        return {
3,564✔
3561
          arity: arity,
3562
          params: paramsIds,
3563
          isSimple: !hasDestructuring && !pastRest && !pastDefault
3564
        };
3565
      }
3566
    }
3567
  }
3568

3569
  /**
3570
   * Factory function for creating objects used to track statistics of function
3571
   * literals.
3572
   *
3573
   * @param {string} name - the identifier name to associate with the function
3574
   * @param {object} [token] - token responsible for creating the function
3575
   *                           object
3576
   * @param {object} [overwrites] - a collection of properties that should
3577
   *                                override the corresponding default value of
3578
   *                                the new "functor" object
3579
   */
3580
  function functor(name, token, overwrites) {
6✔
3581
    var funct = {
24,870✔
3582
      "(name)"      : name,
3583
      "(breakage)"  : 0,
3584
      "(loopage)"   : 0,
3585
      // The strictness of the function body is tracked via a dedicated
3586
      // property (as opposed to via the global `state` object) so that the
3587
      // value can be referenced after the body has been fully parsed (i.e.
3588
      // when validating the identifier used in function declarations and
3589
      // function expressions).
3590
      "(isStrict)"  : "unknown",
3591

3592
      "(global)"    : false,
3593

3594
      "(line)"      : null,
3595
      "(character)" : null,
3596
      "(metrics)"   : null,
3597
      "(statement)" : null,
3598
      "(context)"   : null,
3599
      "(scope)"     : null,
3600
      "(comparray)" : null,
3601
      "(generator)" : null,
3602
      "(arrow)"     : null,
3603
      "(async)"     : null,
3604
      "(params)"    : null
3605
    };
3606

3607
    if (token) {
24,870✔
3608
      _.extend(funct, {
15,210✔
3609
        "(line)"     : token.line,