eslint 9.0.0-beta.1 → 9.0.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -146,7 +146,9 @@ module.exports = {
146
146
  continue;
147
147
  }
148
148
 
149
- uselessReturns.push(...segmentInfoMap.get(segment).uselessReturns);
149
+ if (segmentInfoMap.has(segment)) {
150
+ uselessReturns.push(...segmentInfoMap.get(segment).uselessReturns);
151
+ }
150
152
  }
151
153
 
152
154
  return uselessReturns;
@@ -182,6 +184,10 @@ module.exports = {
182
184
 
183
185
  const info = segmentInfoMap.get(segment);
184
186
 
187
+ if (!info) {
188
+ return;
189
+ }
190
+
185
191
  info.uselessReturns = info.uselessReturns.filter(node => {
186
192
  if (scopeInfo.traversedTryBlockStatements && scopeInfo.traversedTryBlockStatements.length > 0) {
187
193
  const returnInitialRange = node.range[0];
@@ -275,7 +281,6 @@ module.exports = {
275
281
  * NOTE: This event is notified for only reachable segments.
276
282
  */
277
283
  onCodePathSegmentStart(segment) {
278
-
279
284
  scopeInfo.currentSegments.add(segment);
280
285
 
281
286
  const info = {
@@ -0,0 +1,240 @@
1
+ /**
2
+ * @fileoverview Utility functions to locate the source text of each code unit in the value of a string literal or template token.
3
+ * @author Francesco Trotta
4
+ */
5
+
6
+ "use strict";
7
+
8
+ /**
9
+ * Represents a code unit produced by the evaluation of a JavaScript common token like a string
10
+ * literal or template token.
11
+ */
12
+ class CodeUnit {
13
+ constructor(start, source) {
14
+ this.start = start;
15
+ this.source = source;
16
+ }
17
+
18
+ get end() {
19
+ return this.start + this.length;
20
+ }
21
+
22
+ get length() {
23
+ return this.source.length;
24
+ }
25
+ }
26
+
27
+ /**
28
+ * An object used to keep track of the position in a source text where the next characters will be read.
29
+ */
30
+ class TextReader {
31
+ constructor(source) {
32
+ this.source = source;
33
+ this.pos = 0;
34
+ }
35
+
36
+ /**
37
+ * Advances the reading position of the specified number of characters.
38
+ * @param {number} length Number of characters to advance.
39
+ * @returns {void}
40
+ */
41
+ advance(length) {
42
+ this.pos += length;
43
+ }
44
+
45
+ /**
46
+ * Reads characters from the source.
47
+ * @param {number} [offset=0] The offset where reading starts, relative to the current position.
48
+ * @param {number} [length=1] Number of characters to read.
49
+ * @returns {string} A substring of source characters.
50
+ */
51
+ read(offset = 0, length = 1) {
52
+ const start = offset + this.pos;
53
+
54
+ return this.source.slice(start, start + length);
55
+ }
56
+ }
57
+
58
+ const SIMPLE_ESCAPE_SEQUENCES =
59
+ { __proto__: null, b: "\b", f: "\f", n: "\n", r: "\r", t: "\t", v: "\v" };
60
+
61
+ /**
62
+ * Reads a hex escape sequence.
63
+ * @param {TextReader} reader The reader should be positioned on the first hexadecimal digit.
64
+ * @param {number} length The number of hexadecimal digits.
65
+ * @returns {string} A code unit.
66
+ */
67
+ function readHexSequence(reader, length) {
68
+ const str = reader.read(0, length);
69
+ const charCode = parseInt(str, 16);
70
+
71
+ reader.advance(length);
72
+ return String.fromCharCode(charCode);
73
+ }
74
+
75
+ /**
76
+ * Reads a Unicode escape sequence.
77
+ * @param {TextReader} reader The reader should be positioned after the "u".
78
+ * @returns {string} A code unit.
79
+ */
80
+ function readUnicodeSequence(reader) {
81
+ const regExp = /\{(?<hexDigits>[\dA-Fa-f]+)\}/uy;
82
+
83
+ regExp.lastIndex = reader.pos;
84
+ const match = regExp.exec(reader.source);
85
+
86
+ if (match) {
87
+ const codePoint = parseInt(match.groups.hexDigits, 16);
88
+
89
+ reader.pos = regExp.lastIndex;
90
+ return String.fromCodePoint(codePoint);
91
+ }
92
+ return readHexSequence(reader, 4);
93
+ }
94
+
95
+ /**
96
+ * Reads an octal escape sequence.
97
+ * @param {TextReader} reader The reader should be positioned after the first octal digit.
98
+ * @param {number} maxLength The maximum number of octal digits.
99
+ * @returns {string} A code unit.
100
+ */
101
+ function readOctalSequence(reader, maxLength) {
102
+ const [octalStr] = reader.read(-1, maxLength).match(/^[0-7]+/u);
103
+
104
+ reader.advance(octalStr.length - 1);
105
+ const octal = parseInt(octalStr, 8);
106
+
107
+ return String.fromCharCode(octal);
108
+ }
109
+
110
+ /**
111
+ * Reads an escape sequence or line continuation.
112
+ * @param {TextReader} reader The reader should be positioned on the backslash.
113
+ * @returns {string} A string of zero, one or two code units.
114
+ */
115
+ function readEscapeSequenceOrLineContinuation(reader) {
116
+ const char = reader.read(1);
117
+
118
+ reader.advance(2);
119
+ const unitChar = SIMPLE_ESCAPE_SEQUENCES[char];
120
+
121
+ if (unitChar) {
122
+ return unitChar;
123
+ }
124
+ switch (char) {
125
+ case "x":
126
+ return readHexSequence(reader, 2);
127
+ case "u":
128
+ return readUnicodeSequence(reader);
129
+ case "\r":
130
+ if (reader.read() === "\n") {
131
+ reader.advance(1);
132
+ }
133
+
134
+ // fallthrough
135
+ case "\n":
136
+ case "\u2028":
137
+ case "\u2029":
138
+ return "";
139
+ case "0":
140
+ case "1":
141
+ case "2":
142
+ case "3":
143
+ return readOctalSequence(reader, 3);
144
+ case "4":
145
+ case "5":
146
+ case "6":
147
+ case "7":
148
+ return readOctalSequence(reader, 2);
149
+ default:
150
+ return char;
151
+ }
152
+ }
153
+
154
+ /**
155
+ * Reads an escape sequence or line continuation and generates the respective `CodeUnit` elements.
156
+ * @param {TextReader} reader The reader should be positioned on the backslash.
157
+ * @returns {Generator<CodeUnit>} Zero, one or two `CodeUnit` elements.
158
+ */
159
+ function *mapEscapeSequenceOrLineContinuation(reader) {
160
+ const start = reader.pos;
161
+ const str = readEscapeSequenceOrLineContinuation(reader);
162
+ const end = reader.pos;
163
+ const source = reader.source.slice(start, end);
164
+
165
+ switch (str.length) {
166
+ case 0:
167
+ break;
168
+ case 1:
169
+ yield new CodeUnit(start, source);
170
+ break;
171
+ default:
172
+ yield new CodeUnit(start, source);
173
+ yield new CodeUnit(start, source);
174
+ break;
175
+ }
176
+ }
177
+
178
+ /**
179
+ * Parses a string literal.
180
+ * @param {string} source The string literal to parse, including the delimiting quotes.
181
+ * @returns {CodeUnit[]} A list of code units produced by the string literal.
182
+ */
183
+ function parseStringLiteral(source) {
184
+ const reader = new TextReader(source);
185
+ const quote = reader.read();
186
+
187
+ reader.advance(1);
188
+ const codeUnits = [];
189
+
190
+ for (;;) {
191
+ const char = reader.read();
192
+
193
+ if (char === quote) {
194
+ break;
195
+ }
196
+ if (char === "\\") {
197
+ codeUnits.push(...mapEscapeSequenceOrLineContinuation(reader));
198
+ } else {
199
+ codeUnits.push(new CodeUnit(reader.pos, char));
200
+ reader.advance(1);
201
+ }
202
+ }
203
+ return codeUnits;
204
+ }
205
+
206
+ /**
207
+ * Parses a template token.
208
+ * @param {string} source The template token to parse, including the delimiting sequences `` ` ``, `${` and `}`.
209
+ * @returns {CodeUnit[]} A list of code units produced by the template token.
210
+ */
211
+ function parseTemplateToken(source) {
212
+ const reader = new TextReader(source);
213
+
214
+ reader.advance(1);
215
+ const codeUnits = [];
216
+
217
+ for (;;) {
218
+ const char = reader.read();
219
+
220
+ if (char === "`" || char === "$" && reader.read(1) === "{") {
221
+ break;
222
+ }
223
+ if (char === "\\") {
224
+ codeUnits.push(...mapEscapeSequenceOrLineContinuation(reader));
225
+ } else {
226
+ let unitSource;
227
+
228
+ if (char === "\r" && reader.read(1) === "\n") {
229
+ unitSource = "\r\n";
230
+ } else {
231
+ unitSource = char;
232
+ }
233
+ codeUnits.push(new CodeUnit(reader.pos, unitSource));
234
+ reader.advance(unitSource.length);
235
+ }
236
+ }
237
+ return codeUnits;
238
+ }
239
+
240
+ module.exports = { parseStringLiteral, parseTemplateToken };
@@ -6,7 +6,7 @@
6
6
 
7
7
  const debug = require("debug")("eslint:rules");
8
8
 
9
- /** @typedef {import("./types").Rule} Rule */
9
+ /** @typedef {import("../../shared/types").Rule} Rule */
10
10
 
11
11
  /**
12
12
  * The `Map` object that loads each rule when it's accessed.
@@ -3,9 +3,14 @@
3
3
  */
4
4
  "use strict";
5
5
 
6
+ const isCombiningCharacter = require("./is-combining-character");
7
+ const isEmojiModifier = require("./is-emoji-modifier");
8
+ const isRegionalIndicatorSymbol = require("./is-regional-indicator-symbol");
9
+ const isSurrogatePair = require("./is-surrogate-pair");
10
+
6
11
  module.exports = {
7
- isCombiningCharacter: require("./is-combining-character"),
8
- isEmojiModifier: require("./is-emoji-modifier"),
9
- isRegionalIndicatorSymbol: require("./is-regional-indicator-symbol"),
10
- isSurrogatePair: require("./is-surrogate-pair")
12
+ isCombiningCharacter,
13
+ isEmojiModifier,
14
+ isRegionalIndicatorSymbol,
15
+ isSurrogatePair
11
16
  };
@@ -162,6 +162,7 @@ function version() {
162
162
  //------------------------------------------------------------------------------
163
163
 
164
164
  module.exports = {
165
+ __esModule: true, // Indicate intent for imports, remove ambiguity for Knip (see: https://github.com/eslint/eslint/pull/18005#discussion_r1484422616)
165
166
  environment,
166
167
  version
167
168
  };
@@ -1,5 +1,7 @@
1
1
  "use strict";
2
2
 
3
+ const SourceCode = require("./source-code");
4
+
3
5
  module.exports = {
4
- SourceCode: require("./source-code")
6
+ SourceCode
5
7
  };
@@ -18,8 +18,12 @@ const
18
18
  directivesPattern
19
19
  } = require("../shared/directives"),
20
20
 
21
- /* eslint-disable-next-line n/no-restricted-require -- Too messy to figure out right now. */
21
+ /* eslint-disable n/no-restricted-require -- Should eventually be moved into SourceCode. */
22
+ CodePathAnalyzer = require("../linter/code-path-analysis/code-path-analyzer"),
23
+ createEmitter = require("../linter/safe-emitter"),
22
24
  ConfigCommentParser = require("../linter/config-comment-parser"),
25
+ /* eslint-enable n/no-restricted-require -- Should eventually be moved into SourceCode. */
26
+
23
27
  eslintScope = require("eslint-scope");
24
28
 
25
29
  //------------------------------------------------------------------------------
@@ -34,6 +38,16 @@ const
34
38
 
35
39
  const commentParser = new ConfigCommentParser();
36
40
 
41
+ const CODE_PATH_EVENTS = [
42
+ "onCodePathStart",
43
+ "onCodePathEnd",
44
+ "onCodePathSegmentStart",
45
+ "onCodePathSegmentEnd",
46
+ "onCodePathSegmentLoop",
47
+ "onUnreachableCodePathSegmentStart",
48
+ "onUnreachableCodePathSegmentEnd"
49
+ ];
50
+
37
51
  /**
38
52
  * Validates that the given AST has the required information.
39
53
  * @param {ASTNode} ast The Program node of the AST to check.
@@ -300,6 +314,65 @@ function markExportedVariables(globalScope, variables) {
300
314
 
301
315
  }
302
316
 
317
+ const STEP_KIND = {
318
+ visit: 1,
319
+ call: 2
320
+ };
321
+
322
+ /**
323
+ * A class to represent a step in the traversal process.
324
+ */
325
+ class TraversalStep {
326
+
327
+ /**
328
+ * The type of the step.
329
+ * @type {string}
330
+ */
331
+ type;
332
+
333
+ /**
334
+ * The kind of the step. Represents the same data as the `type` property
335
+ * but it's a number for performance.
336
+ * @type {number}
337
+ */
338
+ kind;
339
+
340
+ /**
341
+ * The target of the step.
342
+ * @type {ASTNode|string}
343
+ */
344
+ target;
345
+
346
+ /**
347
+ * The phase of the step.
348
+ * @type {number|undefined}
349
+ */
350
+ phase;
351
+
352
+ /**
353
+ * The arguments of the step.
354
+ * @type {Array<any>}
355
+ */
356
+ args;
357
+
358
+ /**
359
+ * Creates a new instance.
360
+ * @param {Object} options The options for the step.
361
+ * @param {string} options.type The type of the step.
362
+ * @param {ASTNode|string} options.target The target of the step.
363
+ * @param {number|undefined} [options.phase] The phase of the step.
364
+ * @param {Array<any>} options.args The arguments of the step.
365
+ * @returns {void}
366
+ */
367
+ constructor({ type, target, phase, args }) {
368
+ this.type = type;
369
+ this.kind = STEP_KIND[type];
370
+ this.target = target;
371
+ this.phase = phase;
372
+ this.args = args;
373
+ }
374
+ }
375
+
303
376
  //------------------------------------------------------------------------------
304
377
  // Public Interface
305
378
  //------------------------------------------------------------------------------
@@ -311,6 +384,12 @@ const caches = Symbol("caches");
311
384
  */
312
385
  class SourceCode extends TokenStore {
313
386
 
387
+ /**
388
+ * The cache of steps that were taken while traversing the source code.
389
+ * @type {Array<TraversalStep>}
390
+ */
391
+ #steps;
392
+
314
393
  /**
315
394
  * @param {string|Object} textOrConfig The source code text or config object.
316
395
  * @param {string} textOrConfig.text The source code text.
@@ -972,6 +1051,91 @@ class SourceCode extends TokenStore {
972
1051
 
973
1052
  }
974
1053
 
1054
+ /**
1055
+ * Traverse the source code and return the steps that were taken.
1056
+ * @returns {Array<TraversalStep>} The steps that were taken while traversing the source code.
1057
+ */
1058
+ traverse() {
1059
+
1060
+ // Because the AST doesn't mutate, we can cache the steps
1061
+ if (this.#steps) {
1062
+ return this.#steps;
1063
+ }
1064
+
1065
+ const steps = this.#steps = [];
1066
+
1067
+ /*
1068
+ * This logic works for any AST, not just ESTree. Because ESLint has allowed
1069
+ * custom parsers to return any AST, we need to ensure that the traversal
1070
+ * logic works for any AST.
1071
+ */
1072
+ const emitter = createEmitter();
1073
+ let analyzer = {
1074
+ enterNode(node) {
1075
+ steps.push(new TraversalStep({
1076
+ type: "visit",
1077
+ target: node,
1078
+ phase: 1,
1079
+ args: [node, node.parent]
1080
+ }));
1081
+ },
1082
+ leaveNode(node) {
1083
+ steps.push(new TraversalStep({
1084
+ type: "visit",
1085
+ target: node,
1086
+ phase: 2,
1087
+ args: [node, node.parent]
1088
+ }));
1089
+ },
1090
+ emitter
1091
+ };
1092
+
1093
+ /*
1094
+ * We do code path analysis for ESTree only. Code path analysis is not
1095
+ * necessary for other ASTs, and it's also not possible to do for other
1096
+ * ASTs because the necessary information is not available.
1097
+ *
1098
+ * Generally speaking, we can tell that the AST is an ESTree if it has a
1099
+ * Program node at the top level. This is not a perfect heuristic, but it
1100
+ * is good enough for now.
1101
+ */
1102
+ const isESTree = this.ast.type === "Program";
1103
+
1104
+ if (isESTree) {
1105
+ analyzer = new CodePathAnalyzer(analyzer);
1106
+
1107
+ CODE_PATH_EVENTS.forEach(eventName => {
1108
+ emitter.on(eventName, (...args) => {
1109
+ steps.push(new TraversalStep({
1110
+ type: "call",
1111
+ target: eventName,
1112
+ args
1113
+ }));
1114
+ });
1115
+ });
1116
+ }
1117
+
1118
+ /*
1119
+ * The actual AST traversal is done by the `Traverser` class. This class
1120
+ * is responsible for walking the AST and calling the appropriate methods
1121
+ * on the `analyzer` object, which is appropriate for the given AST.
1122
+ */
1123
+ Traverser.traverse(this.ast, {
1124
+ enter(node, parent) {
1125
+
1126
+ // save the parent node on a property for backwards compatibility
1127
+ node.parent = parent;
1128
+
1129
+ analyzer.enterNode(node);
1130
+ },
1131
+ leave(node) {
1132
+ analyzer.leaveNode(node);
1133
+ },
1134
+ visitorKeys: this.visitorKeys
1135
+ });
1136
+
1137
+ return steps;
1138
+ }
975
1139
  }
976
1140
 
977
1141
  module.exports = SourceCode;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint",
3
- "version": "9.0.0-beta.1",
3
+ "version": "9.0.0-rc.0",
4
4
  "author": "Nicholas C. Zakas <nicholas+npm@nczconsulting.com>",
5
5
  "description": "An AST-based pattern checker for JavaScript.",
6
6
  "bin": {
@@ -23,6 +23,7 @@
23
23
  "lint:docs:rule-examples": "node Makefile.js checkRuleExamples",
24
24
  "lint:fix": "node Makefile.js lint -- fix",
25
25
  "lint:fix:docs:js": "node Makefile.js lintDocsJS -- fix",
26
+ "lint:unused": "knip",
26
27
  "release:generate:alpha": "node Makefile.js generatePrerelease -- alpha",
27
28
  "release:generate:beta": "node Makefile.js generatePrerelease -- beta",
28
29
  "release:generate:latest": "node Makefile.js generateRelease",
@@ -48,7 +49,7 @@
48
49
  "node tools/fetch-docs-links.js",
49
50
  "git add docs/src/_data/further_reading_links.json"
50
51
  ],
51
- "docs/**/*.svg": "npx svgo -r --multipass"
52
+ "docs/**/*.svg": "npx -y svgo -r --multipass"
52
53
  },
53
54
  "files": [
54
55
  "LICENSE",
@@ -66,7 +67,7 @@
66
67
  "@eslint-community/eslint-utils": "^4.2.0",
67
68
  "@eslint-community/regexpp": "^4.6.1",
68
69
  "@eslint/eslintrc": "^3.0.2",
69
- "@eslint/js": "9.0.0-beta.1",
70
+ "@eslint/js": "9.0.0-rc.0",
70
71
  "@humanwhocodes/config-array": "^0.11.14",
71
72
  "@humanwhocodes/module-importer": "^1.0.1",
72
73
  "@nodelib/fs.walk": "^1.2.8",
@@ -75,7 +76,7 @@
75
76
  "cross-spawn": "^7.0.2",
76
77
  "debug": "^4.3.2",
77
78
  "escape-string-regexp": "^4.0.0",
78
- "eslint-scope": "^8.0.0",
79
+ "eslint-scope": "^8.0.1",
79
80
  "eslint-visitor-keys": "^4.0.0",
80
81
  "espree": "^10.0.1",
81
82
  "esquery": "^1.4.2",
@@ -101,6 +102,8 @@
101
102
  "devDependencies": {
102
103
  "@babel/core": "^7.4.3",
103
104
  "@babel/preset-env": "^7.4.3",
105
+ "@types/estree": "^1.0.5",
106
+ "@types/node": "^20.11.5",
104
107
  "@wdio/browser-runner": "^8.14.6",
105
108
  "@wdio/cli": "^8.14.6",
106
109
  "@wdio/concise-reporter": "^8.14.0",
@@ -131,6 +134,7 @@
131
134
  "got": "^11.8.3",
132
135
  "gray-matter": "^4.0.3",
133
136
  "js-yaml": "^4.1.0",
137
+ "knip": "^5.0.1",
134
138
  "lint-staged": "^11.0.0",
135
139
  "load-perf": "^0.2.0",
136
140
  "markdown-it": "^12.2.0",
@@ -138,7 +142,6 @@
138
142
  "markdownlint": "^0.33.0",
139
143
  "markdownlint-cli": "^0.39.0",
140
144
  "marked": "^4.0.8",
141
- "memfs": "^3.0.1",
142
145
  "metascraper": "^5.25.7",
143
146
  "metascraper-description": "^5.25.7",
144
147
  "metascraper-image": "^5.29.3",
@@ -157,8 +160,8 @@
157
160
  "semver": "^7.5.3",
158
161
  "shelljs": "^0.8.5",
159
162
  "sinon": "^11.0.0",
163
+ "typescript": "^5.3.3",
160
164
  "vite-plugin-commonjs": "^0.10.0",
161
- "webdriverio": "^8.14.6",
162
165
  "webpack": "^5.23.0",
163
166
  "webpack-cli": "^4.5.0",
164
167
  "yorkie": "^2.0.0"
@@ -1,34 +0,0 @@
1
- /**
2
- * @fileoverview XML character escaper
3
- * @author George Chung
4
- */
5
- "use strict";
6
-
7
- //------------------------------------------------------------------------------
8
- // Public Interface
9
- //------------------------------------------------------------------------------
10
-
11
- /**
12
- * Returns the escaped value for a character
13
- * @param {string} s string to examine
14
- * @returns {string} severity level
15
- * @private
16
- */
17
- module.exports = function(s) {
18
- return (`${s}`).replace(/[<>&"'\x00-\x1F\x7F\u0080-\uFFFF]/gu, c => { // eslint-disable-line no-control-regex -- Converting controls to entities
19
- switch (c) {
20
- case "<":
21
- return "&lt;";
22
- case ">":
23
- return "&gt;";
24
- case "&":
25
- return "&amp;";
26
- case "\"":
27
- return "&quot;";
28
- case "'":
29
- return "&apos;";
30
- default:
31
- return `&#${c.charCodeAt(0)};`;
32
- }
33
- });
34
- };
@@ -1,58 +0,0 @@
1
- /**
2
- * @fileoverview Provide the function that emits deprecation warnings.
3
- * @author Toru Nagashima <http://github.com/mysticatea>
4
- */
5
- "use strict";
6
-
7
- //------------------------------------------------------------------------------
8
- // Requirements
9
- //------------------------------------------------------------------------------
10
-
11
- const path = require("path");
12
-
13
- //------------------------------------------------------------------------------
14
- // Private
15
- //------------------------------------------------------------------------------
16
-
17
- // Definitions for deprecation warnings.
18
- const deprecationWarningMessages = {
19
- ESLINT_LEGACY_ECMAFEATURES:
20
- "The 'ecmaFeatures' config file property is deprecated and has no effect."
21
- };
22
-
23
- const sourceFileErrorCache = new Set();
24
-
25
- /**
26
- * Emits a deprecation warning containing a given filepath. A new deprecation warning is emitted
27
- * for each unique file path, but repeated invocations with the same file path have no effect.
28
- * No warnings are emitted if the `--no-deprecation` or `--no-warnings` Node runtime flags are active.
29
- * @param {string} source The name of the configuration source to report the warning for.
30
- * @param {string} errorCode The warning message to show.
31
- * @returns {void}
32
- */
33
- function emitDeprecationWarning(source, errorCode) {
34
- const cacheKey = JSON.stringify({ source, errorCode });
35
-
36
- if (sourceFileErrorCache.has(cacheKey)) {
37
- return;
38
- }
39
-
40
- sourceFileErrorCache.add(cacheKey);
41
-
42
- const rel = path.relative(process.cwd(), source);
43
- const message = deprecationWarningMessages[errorCode];
44
-
45
- process.emitWarning(
46
- `${message} (found in "${rel}")`,
47
- "DeprecationWarning",
48
- errorCode
49
- );
50
- }
51
-
52
- //------------------------------------------------------------------------------
53
- // Public Interface
54
- //------------------------------------------------------------------------------
55
-
56
- module.exports = {
57
- emitDeprecationWarning
58
- };