state.js
3.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
"use strict";
var NameStack = require("./name-stack.js");
var state = {
syntax: {},
/**
* Determine if the code currently being linted is strict mode code.
*
* @returns {boolean}
*/
isStrict: function() {
return this.directive["use strict"] || this.inClassBody ||
this.option.module || this.option.strict === "implied";
},
/**
* Determine if the current state warrants a warning for statements outside
* of strict mode code.
*
* While emitting warnings based on function scope would be more intuitive
* (and less noisy), JSHint observes statement-based semantics in order to
* preserve legacy behavior.
*
* This method does not take the state of the parser into account, making no
* distinction between global code and function code. Because the "missing
* 'use strict'" warning is *also* reported at function boundaries, this
* function interprets `strict` option values `true` and `undefined` as
* equivalent.
*/
stmtMissingStrict: function() {
if (this.option.strict === "global") {
return true;
}
if (this.option.strict === false) {
return false;
}
if (this.option.globalstrict) {
return true;
}
return false;
},
allowsGlobalUsd: function() {
return this.option.strict === "global" || this.option.globalstrict ||
this.option.module || this.impliedClosure();
},
/**
* Determine if the current configuration describes an environment that is
* wrapped in an immediately-invoked function expression prior to evaluation.
*
* @returns {boolean}
*/
impliedClosure: function() {
return this.option.node || this.option.phantom || this.option.browserify;
},
// Assumption: chronologically ES3 < ES5 < ES6 < Moz
inMoz: function() {
return this.option.moz;
},
/**
* @param {boolean} strict - When `true`, only consider ES6 when in
* "esversion: 6" code.
*/
inES6: function(strict) {
if (strict) {
return this.esVersion === 6;
}
return this.option.moz || this.esVersion >= 6;
},
/**
* @param {boolean} strict - When `true`, return `true` only when
* esVersion is exactly 5
*/
inES5: function(strict) {
if (strict) {
return (!this.esVersion || this.esVersion === 5) && !this.option.moz;
}
return !this.esVersion || this.esVersion >= 5 || this.option.moz;
},
/**
* Determine the current version of the input language by inspecting the
* value of all ECMAScript-version-related options. This logic is necessary
* to ensure compatibility with deprecated options `es3`, `es5`, and
* `esnext`, and it may be drastically simplified when those options are
* removed.
*
* @returns {string|null} - the name of any incompatible option detected,
* `null` otherwise
*/
inferEsVersion: function() {
var badOpt = null;
if (this.option.esversion) {
if (this.option.es3) {
badOpt = "es3";
} else if (this.option.es5) {
badOpt = "es5";
} else if (this.option.esnext) {
badOpt = "esnext";
}
if (badOpt) {
return badOpt;
}
if (this.option.esversion === 2015) {
this.esVersion = 6;
} else {
this.esVersion = this.option.esversion;
}
} else if (this.option.es3) {
this.esVersion = 3;
} else if (this.option.esnext) {
this.esVersion = 6;
}
return null;
},
reset: function() {
this.tokens = {
prev: null,
next: null,
curr: null
};
this.option = {};
this.esVersion = 5;
this.funct = null;
this.ignored = {};
this.directive = {};
this.jsonMode = false;
this.jsonWarnings = [];
this.lines = [];
this.tab = "";
this.cache = {}; // Node.JS doesn't have Map. Sniff.
this.ignoredLines = {};
this.forinifcheckneeded = false;
this.nameStack = new NameStack();
this.inClassBody = false;
}
};
exports.state = state;