source: imaps-frontend/node_modules/eslint-scope/dist/eslint-scope.cjs@ d565449

main
Last change on this file since d565449 was d565449, checked in by stefan toskovski <stefantoska84@…>, 4 weeks ago

Update repo after prototype presentation

  • Property mode set to 100644
File size: 67.7 KB
RevLine 
[d565449]1'use strict';
2
3Object.defineProperty(exports, '__esModule', { value: true });
4
5var assert = require('assert');
6var estraverse = require('estraverse');
7var esrecurse = require('esrecurse');
8
9function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
10
11var assert__default = /*#__PURE__*/_interopDefaultLegacy(assert);
12var estraverse__default = /*#__PURE__*/_interopDefaultLegacy(estraverse);
13var esrecurse__default = /*#__PURE__*/_interopDefaultLegacy(esrecurse);
14
15/*
16 Copyright (C) 2015 Yusuke Suzuki <utatane.tea@gmail.com>
17
18 Redistribution and use in source and binary forms, with or without
19 modification, are permitted provided that the following conditions are met:
20
21 * Redistributions of source code must retain the above copyright
22 notice, this list of conditions and the following disclaimer.
23 * Redistributions in binary form must reproduce the above copyright
24 notice, this list of conditions and the following disclaimer in the
25 documentation and/or other materials provided with the distribution.
26
27 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
28 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
31 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
32 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
33 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
34 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
36 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37*/
38
39const READ = 0x1;
40const WRITE = 0x2;
41const RW = READ | WRITE;
42
43/**
44 * A Reference represents a single occurrence of an identifier in code.
45 * @constructor Reference
46 */
47class Reference {
48 constructor(ident, scope, flag, writeExpr, maybeImplicitGlobal, partial, init) {
49
50 /**
51 * Identifier syntax node.
52 * @member {espreeIdentifier} Reference#identifier
53 */
54 this.identifier = ident;
55
56 /**
57 * Reference to the enclosing Scope.
58 * @member {Scope} Reference#from
59 */
60 this.from = scope;
61
62 /**
63 * Whether the reference comes from a dynamic scope (such as 'eval',
64 * 'with', etc.), and may be trapped by dynamic scopes.
65 * @member {boolean} Reference#tainted
66 */
67 this.tainted = false;
68
69 /**
70 * The variable this reference is resolved with.
71 * @member {Variable} Reference#resolved
72 */
73 this.resolved = null;
74
75 /**
76 * The read-write mode of the reference. (Value is one of {@link
77 * Reference.READ}, {@link Reference.RW}, {@link Reference.WRITE}).
78 * @member {number} Reference#flag
79 * @private
80 */
81 this.flag = flag;
82 if (this.isWrite()) {
83
84 /**
85 * If reference is writeable, this is the tree being written to it.
86 * @member {espreeNode} Reference#writeExpr
87 */
88 this.writeExpr = writeExpr;
89
90 /**
91 * Whether the Reference might refer to a partial value of writeExpr.
92 * @member {boolean} Reference#partial
93 */
94 this.partial = partial;
95
96 /**
97 * Whether the Reference is to write of initialization.
98 * @member {boolean} Reference#init
99 */
100 this.init = init;
101 }
102 this.__maybeImplicitGlobal = maybeImplicitGlobal;
103 }
104
105 /**
106 * Whether the reference is static.
107 * @function Reference#isStatic
108 * @returns {boolean} static
109 */
110 isStatic() {
111 return !this.tainted && this.resolved && this.resolved.scope.isStatic();
112 }
113
114 /**
115 * Whether the reference is writeable.
116 * @function Reference#isWrite
117 * @returns {boolean} write
118 */
119 isWrite() {
120 return !!(this.flag & Reference.WRITE);
121 }
122
123 /**
124 * Whether the reference is readable.
125 * @function Reference#isRead
126 * @returns {boolean} read
127 */
128 isRead() {
129 return !!(this.flag & Reference.READ);
130 }
131
132 /**
133 * Whether the reference is read-only.
134 * @function Reference#isReadOnly
135 * @returns {boolean} read only
136 */
137 isReadOnly() {
138 return this.flag === Reference.READ;
139 }
140
141 /**
142 * Whether the reference is write-only.
143 * @function Reference#isWriteOnly
144 * @returns {boolean} write only
145 */
146 isWriteOnly() {
147 return this.flag === Reference.WRITE;
148 }
149
150 /**
151 * Whether the reference is read-write.
152 * @function Reference#isReadWrite
153 * @returns {boolean} read write
154 */
155 isReadWrite() {
156 return this.flag === Reference.RW;
157 }
158}
159
160/**
161 * @constant Reference.READ
162 * @private
163 */
164Reference.READ = READ;
165
166/**
167 * @constant Reference.WRITE
168 * @private
169 */
170Reference.WRITE = WRITE;
171
172/**
173 * @constant Reference.RW
174 * @private
175 */
176Reference.RW = RW;
177
178/* vim: set sw=4 ts=4 et tw=80 : */
179
180/*
181 Copyright (C) 2015 Yusuke Suzuki <utatane.tea@gmail.com>
182
183 Redistribution and use in source and binary forms, with or without
184 modification, are permitted provided that the following conditions are met:
185
186 * Redistributions of source code must retain the above copyright
187 notice, this list of conditions and the following disclaimer.
188 * Redistributions in binary form must reproduce the above copyright
189 notice, this list of conditions and the following disclaimer in the
190 documentation and/or other materials provided with the distribution.
191
192 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
193 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
194 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
195 ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
196 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
197 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
198 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
199 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
200 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
201 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
202*/
203
204/**
205 * A Variable represents a locally scoped identifier. These include arguments to
206 * functions.
207 * @constructor Variable
208 */
209class Variable {
210 constructor(name, scope) {
211
212 /**
213 * The variable name, as given in the source code.
214 * @member {string} Variable#name
215 */
216 this.name = name;
217
218 /**
219 * List of defining occurrences of this variable (like in 'var ...'
220 * statements or as parameter), as AST nodes.
221 * @member {espree.Identifier[]} Variable#identifiers
222 */
223 this.identifiers = [];
224
225 /**
226 * List of {@link Reference|references} of this variable (excluding parameter entries)
227 * in its defining scope and all nested scopes. For defining
228 * occurrences only see {@link Variable#defs}.
229 * @member {Reference[]} Variable#references
230 */
231 this.references = [];
232
233 /**
234 * List of defining occurrences of this variable (like in 'var ...'
235 * statements or as parameter), as custom objects.
236 * @member {Definition[]} Variable#defs
237 */
238 this.defs = [];
239
240 this.tainted = false;
241
242 /**
243 * Whether this is a stack variable.
244 * @member {boolean} Variable#stack
245 */
246 this.stack = true;
247
248 /**
249 * Reference to the enclosing Scope.
250 * @member {Scope} Variable#scope
251 */
252 this.scope = scope;
253 }
254}
255
256Variable.CatchClause = "CatchClause";
257Variable.Parameter = "Parameter";
258Variable.FunctionName = "FunctionName";
259Variable.ClassName = "ClassName";
260Variable.Variable = "Variable";
261Variable.ImportBinding = "ImportBinding";
262Variable.ImplicitGlobalVariable = "ImplicitGlobalVariable";
263
264/* vim: set sw=4 ts=4 et tw=80 : */
265
266/*
267 Copyright (C) 2015 Yusuke Suzuki <utatane.tea@gmail.com>
268
269 Redistribution and use in source and binary forms, with or without
270 modification, are permitted provided that the following conditions are met:
271
272 * Redistributions of source code must retain the above copyright
273 notice, this list of conditions and the following disclaimer.
274 * Redistributions in binary form must reproduce the above copyright
275 notice, this list of conditions and the following disclaimer in the
276 documentation and/or other materials provided with the distribution.
277
278 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
279 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
280 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
281 ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
282 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
283 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
284 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
285 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
286 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
287 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
288*/
289
290/**
291 * @constructor Definition
292 */
293class Definition {
294 constructor(type, name, node, parent, index, kind) {
295
296 /**
297 * @member {string} Definition#type - type of the occurrence (e.g. "Parameter", "Variable", ...).
298 */
299 this.type = type;
300
301 /**
302 * @member {espree.Identifier} Definition#name - the identifier AST node of the occurrence.
303 */
304 this.name = name;
305
306 /**
307 * @member {espree.Node} Definition#node - the enclosing node of the identifier.
308 */
309 this.node = node;
310
311 /**
312 * @member {espree.Node?} Definition#parent - the enclosing statement node of the identifier.
313 */
314 this.parent = parent;
315
316 /**
317 * @member {number?} Definition#index - the index in the declaration statement.
318 */
319 this.index = index;
320
321 /**
322 * @member {string?} Definition#kind - the kind of the declaration statement.
323 */
324 this.kind = kind;
325 }
326}
327
328/**
329 * @constructor ParameterDefinition
330 */
331class ParameterDefinition extends Definition {
332 constructor(name, node, index, rest) {
333 super(Variable.Parameter, name, node, null, index, null);
334
335 /**
336 * Whether the parameter definition is a part of a rest parameter.
337 * @member {boolean} ParameterDefinition#rest
338 */
339 this.rest = rest;
340 }
341}
342
343/* vim: set sw=4 ts=4 et tw=80 : */
344
345/*
346 Copyright (C) 2015 Yusuke Suzuki <utatane.tea@gmail.com>
347
348 Redistribution and use in source and binary forms, with or without
349 modification, are permitted provided that the following conditions are met:
350
351 * Redistributions of source code must retain the above copyright
352 notice, this list of conditions and the following disclaimer.
353 * Redistributions in binary form must reproduce the above copyright
354 notice, this list of conditions and the following disclaimer in the
355 documentation and/or other materials provided with the distribution.
356
357 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
358 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
359 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
360 ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
361 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
362 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
363 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
364 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
365 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
366 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
367*/
368
369const { Syntax: Syntax$2 } = estraverse__default["default"];
370
371/**
372 * Test if scope is struct
373 * @param {Scope} scope scope
374 * @param {Block} block block
375 * @param {boolean} isMethodDefinition is method definition
376 * @param {boolean} useDirective use directive
377 * @returns {boolean} is strict scope
378 */
379function isStrictScope(scope, block, isMethodDefinition, useDirective) {
380 let body;
381
382 // When upper scope is exists and strict, inner scope is also strict.
383 if (scope.upper && scope.upper.isStrict) {
384 return true;
385 }
386
387 if (isMethodDefinition) {
388 return true;
389 }
390
391 if (scope.type === "class" || scope.type === "module") {
392 return true;
393 }
394
395 if (scope.type === "block" || scope.type === "switch") {
396 return false;
397 }
398
399 if (scope.type === "function") {
400 if (block.type === Syntax$2.ArrowFunctionExpression && block.body.type !== Syntax$2.BlockStatement) {
401 return false;
402 }
403
404 if (block.type === Syntax$2.Program) {
405 body = block;
406 } else {
407 body = block.body;
408 }
409
410 if (!body) {
411 return false;
412 }
413 } else if (scope.type === "global") {
414 body = block;
415 } else {
416 return false;
417 }
418
419 // Search 'use strict' directive.
420 if (useDirective) {
421 for (let i = 0, iz = body.body.length; i < iz; ++i) {
422 const stmt = body.body[i];
423
424 if (stmt.type !== Syntax$2.DirectiveStatement) {
425 break;
426 }
427 if (stmt.raw === "\"use strict\"" || stmt.raw === "'use strict'") {
428 return true;
429 }
430 }
431 } else {
432 for (let i = 0, iz = body.body.length; i < iz; ++i) {
433 const stmt = body.body[i];
434
435 if (stmt.type !== Syntax$2.ExpressionStatement) {
436 break;
437 }
438 const expr = stmt.expression;
439
440 if (expr.type !== Syntax$2.Literal || typeof expr.value !== "string") {
441 break;
442 }
443 if (expr.raw !== null && expr.raw !== undefined) {
444 if (expr.raw === "\"use strict\"" || expr.raw === "'use strict'") {
445 return true;
446 }
447 } else {
448 if (expr.value === "use strict") {
449 return true;
450 }
451 }
452 }
453 }
454 return false;
455}
456
457/**
458 * Register scope
459 * @param {ScopeManager} scopeManager scope manager
460 * @param {Scope} scope scope
461 * @returns {void}
462 */
463function registerScope(scopeManager, scope) {
464 scopeManager.scopes.push(scope);
465
466 const scopes = scopeManager.__nodeToScope.get(scope.block);
467
468 if (scopes) {
469 scopes.push(scope);
470 } else {
471 scopeManager.__nodeToScope.set(scope.block, [scope]);
472 }
473}
474
475/**
476 * Should be statically
477 * @param {Object} def def
478 * @returns {boolean} should be statically
479 */
480function shouldBeStatically(def) {
481 return (
482 (def.type === Variable.ClassName) ||
483 (def.type === Variable.Variable && def.parent.kind !== "var")
484 );
485}
486
487/**
488 * @constructor Scope
489 */
490class Scope {
491 constructor(scopeManager, type, upperScope, block, isMethodDefinition) {
492
493 /**
494 * One of "global", "module", "function", "function-expression-name", "block", "switch", "catch", "with", "for",
495 * "class", "class-field-initializer", "class-static-block".
496 * @member {string} Scope#type
497 */
498 this.type = type;
499
500 /**
501 * The scoped {@link Variable}s of this scope, as <code>{ Variable.name
502 * : Variable }</code>.
503 * @member {Map} Scope#set
504 */
505 this.set = new Map();
506
507 /**
508 * The tainted variables of this scope, as <code>{ Variable.name :
509 * boolean }</code>.
510 * @member {Map} Scope#taints */
511 this.taints = new Map();
512
513 /**
514 * Generally, through the lexical scoping of JS you can always know
515 * which variable an identifier in the source code refers to. There are
516 * a few exceptions to this rule. With 'global' and 'with' scopes you
517 * can only decide at runtime which variable a reference refers to.
518 * Moreover, if 'eval()' is used in a scope, it might introduce new
519 * bindings in this or its parent scopes.
520 * All those scopes are considered 'dynamic'.
521 * @member {boolean} Scope#dynamic
522 */
523 this.dynamic = this.type === "global" || this.type === "with";
524
525 /**
526 * A reference to the scope-defining syntax node.
527 * @member {espree.Node} Scope#block
528 */
529 this.block = block;
530
531 /**
532 * The {@link Reference|references} that are not resolved with this scope.
533 * @member {Reference[]} Scope#through
534 */
535 this.through = [];
536
537 /**
538 * The scoped {@link Variable}s of this scope. In the case of a
539 * 'function' scope this includes the automatic argument <em>arguments</em> as
540 * its first element, as well as all further formal arguments.
541 * @member {Variable[]} Scope#variables
542 */
543 this.variables = [];
544
545 /**
546 * Any variable {@link Reference|reference} found in this scope. This
547 * includes occurrences of local variables as well as variables from
548 * parent scopes (including the global scope). For local variables
549 * this also includes defining occurrences (like in a 'var' statement).
550 * In a 'function' scope this does not include the occurrences of the
551 * formal parameter in the parameter list.
552 * @member {Reference[]} Scope#references
553 */
554 this.references = [];
555
556 /**
557 * For 'global' and 'function' scopes, this is a self-reference. For
558 * other scope types this is the <em>variableScope</em> value of the
559 * parent scope.
560 * @member {Scope} Scope#variableScope
561 */
562 this.variableScope =
563 this.type === "global" ||
564 this.type === "module" ||
565 this.type === "function" ||
566 this.type === "class-field-initializer" ||
567 this.type === "class-static-block"
568 ? this
569 : upperScope.variableScope;
570
571 /**
572 * Whether this scope is created by a FunctionExpression.
573 * @member {boolean} Scope#functionExpressionScope
574 */
575 this.functionExpressionScope = false;
576
577 /**
578 * Whether this is a scope that contains an 'eval()' invocation.
579 * @member {boolean} Scope#directCallToEvalScope
580 */
581 this.directCallToEvalScope = false;
582
583 /**
584 * @member {boolean} Scope#thisFound
585 */
586 this.thisFound = false;
587
588 this.__left = [];
589
590 /**
591 * Reference to the parent {@link Scope|scope}.
592 * @member {Scope} Scope#upper
593 */
594 this.upper = upperScope;
595
596 /**
597 * Whether 'use strict' is in effect in this scope.
598 * @member {boolean} Scope#isStrict
599 */
600 this.isStrict = scopeManager.isStrictModeSupported()
601 ? isStrictScope(this, block, isMethodDefinition, scopeManager.__useDirective())
602 : false;
603
604 /**
605 * List of nested {@link Scope}s.
606 * @member {Scope[]} Scope#childScopes
607 */
608 this.childScopes = [];
609 if (this.upper) {
610 this.upper.childScopes.push(this);
611 }
612
613 this.__declaredVariables = scopeManager.__declaredVariables;
614
615 registerScope(scopeManager, this);
616 }
617
618 __shouldStaticallyClose(scopeManager) {
619 return (!this.dynamic || scopeManager.__isOptimistic());
620 }
621
622 __shouldStaticallyCloseForGlobal(ref) {
623
624 // On global scope, let/const/class declarations should be resolved statically.
625 const name = ref.identifier.name;
626
627 if (!this.set.has(name)) {
628 return false;
629 }
630
631 const variable = this.set.get(name);
632 const defs = variable.defs;
633
634 return defs.length > 0 && defs.every(shouldBeStatically);
635 }
636
637 __staticCloseRef(ref) {
638 if (!this.__resolve(ref)) {
639 this.__delegateToUpperScope(ref);
640 }
641 }
642
643 __dynamicCloseRef(ref) {
644
645 // notify all names are through to global
646 let current = this;
647
648 do {
649 current.through.push(ref);
650 current = current.upper;
651 } while (current);
652 }
653
654 __globalCloseRef(ref) {
655
656 // let/const/class declarations should be resolved statically.
657 // others should be resolved dynamically.
658 if (this.__shouldStaticallyCloseForGlobal(ref)) {
659 this.__staticCloseRef(ref);
660 } else {
661 this.__dynamicCloseRef(ref);
662 }
663 }
664
665 __close(scopeManager) {
666 let closeRef;
667
668 if (this.__shouldStaticallyClose(scopeManager)) {
669 closeRef = this.__staticCloseRef;
670 } else if (this.type !== "global") {
671 closeRef = this.__dynamicCloseRef;
672 } else {
673 closeRef = this.__globalCloseRef;
674 }
675
676 // Try Resolving all references in this scope.
677 for (let i = 0, iz = this.__left.length; i < iz; ++i) {
678 const ref = this.__left[i];
679
680 closeRef.call(this, ref);
681 }
682 this.__left = null;
683
684 return this.upper;
685 }
686
687 // To override by function scopes.
688 // References in default parameters isn't resolved to variables which are in their function body.
689 __isValidResolution(ref, variable) { // eslint-disable-line class-methods-use-this, no-unused-vars
690 return true;
691 }
692
693 __resolve(ref) {
694 const name = ref.identifier.name;
695
696 if (!this.set.has(name)) {
697 return false;
698 }
699 const variable = this.set.get(name);
700
701 if (!this.__isValidResolution(ref, variable)) {
702 return false;
703 }
704 variable.references.push(ref);
705 variable.stack = variable.stack && ref.from.variableScope === this.variableScope;
706 if (ref.tainted) {
707 variable.tainted = true;
708 this.taints.set(variable.name, true);
709 }
710 ref.resolved = variable;
711
712 return true;
713 }
714
715 __delegateToUpperScope(ref) {
716 if (this.upper) {
717 this.upper.__left.push(ref);
718 }
719 this.through.push(ref);
720 }
721
722 __addDeclaredVariablesOfNode(variable, node) {
723 if (node === null || node === undefined) {
724 return;
725 }
726
727 let variables = this.__declaredVariables.get(node);
728
729 if (variables === null || variables === undefined) {
730 variables = [];
731 this.__declaredVariables.set(node, variables);
732 }
733 if (variables.indexOf(variable) === -1) {
734 variables.push(variable);
735 }
736 }
737
738 __defineGeneric(name, set, variables, node, def) {
739 let variable;
740
741 variable = set.get(name);
742 if (!variable) {
743 variable = new Variable(name, this);
744 set.set(name, variable);
745 variables.push(variable);
746 }
747
748 if (def) {
749 variable.defs.push(def);
750 this.__addDeclaredVariablesOfNode(variable, def.node);
751 this.__addDeclaredVariablesOfNode(variable, def.parent);
752 }
753 if (node) {
754 variable.identifiers.push(node);
755 }
756 }
757
758 __define(node, def) {
759 if (node && node.type === Syntax$2.Identifier) {
760 this.__defineGeneric(
761 node.name,
762 this.set,
763 this.variables,
764 node,
765 def
766 );
767 }
768 }
769
770 __referencing(node, assign, writeExpr, maybeImplicitGlobal, partial, init) {
771
772 // because Array element may be null
773 if (!node || node.type !== Syntax$2.Identifier) {
774 return;
775 }
776
777 // Specially handle like `this`.
778 if (node.name === "super") {
779 return;
780 }
781
782 const ref = new Reference(node, this, assign || Reference.READ, writeExpr, maybeImplicitGlobal, !!partial, !!init);
783
784 this.references.push(ref);
785 this.__left.push(ref);
786 }
787
788 __detectEval() {
789 let current = this;
790
791 this.directCallToEvalScope = true;
792 do {
793 current.dynamic = true;
794 current = current.upper;
795 } while (current);
796 }
797
798 __detectThis() {
799 this.thisFound = true;
800 }
801
802 __isClosed() {
803 return this.__left === null;
804 }
805
806 /**
807 * returns resolved {Reference}
808 * @function Scope#resolve
809 * @param {Espree.Identifier} ident identifier to be resolved.
810 * @returns {Reference} reference
811 */
812 resolve(ident) {
813 let ref, i, iz;
814
815 assert__default["default"](this.__isClosed(), "Scope should be closed.");
816 assert__default["default"](ident.type === Syntax$2.Identifier, "Target should be identifier.");
817 for (i = 0, iz = this.references.length; i < iz; ++i) {
818 ref = this.references[i];
819 if (ref.identifier === ident) {
820 return ref;
821 }
822 }
823 return null;
824 }
825
826 /**
827 * returns this scope is static
828 * @function Scope#isStatic
829 * @returns {boolean} static
830 */
831 isStatic() {
832 return !this.dynamic;
833 }
834
835 /**
836 * returns this scope has materialized arguments
837 * @function Scope#isArgumentsMaterialized
838 * @returns {boolean} arguemnts materialized
839 */
840 isArgumentsMaterialized() { // eslint-disable-line class-methods-use-this
841 return true;
842 }
843
844 /**
845 * returns this scope has materialized `this` reference
846 * @function Scope#isThisMaterialized
847 * @returns {boolean} this materialized
848 */
849 isThisMaterialized() { // eslint-disable-line class-methods-use-this
850 return true;
851 }
852
853 isUsedName(name) {
854 if (this.set.has(name)) {
855 return true;
856 }
857 for (let i = 0, iz = this.through.length; i < iz; ++i) {
858 if (this.through[i].identifier.name === name) {
859 return true;
860 }
861 }
862 return false;
863 }
864}
865
866class GlobalScope extends Scope {
867 constructor(scopeManager, block) {
868 super(scopeManager, "global", null, block, false);
869 this.implicit = {
870 set: new Map(),
871 variables: [],
872
873 /**
874 * List of {@link Reference}s that are left to be resolved (i.e. which
875 * need to be linked to the variable they refer to).
876 * @member {Reference[]} Scope#implicit#left
877 */
878 left: []
879 };
880 }
881
882 __close(scopeManager) {
883 const implicit = [];
884
885 for (let i = 0, iz = this.__left.length; i < iz; ++i) {
886 const ref = this.__left[i];
887
888 if (ref.__maybeImplicitGlobal && !this.set.has(ref.identifier.name)) {
889 implicit.push(ref.__maybeImplicitGlobal);
890 }
891 }
892
893 // create an implicit global variable from assignment expression
894 for (let i = 0, iz = implicit.length; i < iz; ++i) {
895 const info = implicit[i];
896
897 this.__defineImplicit(info.pattern,
898 new Definition(
899 Variable.ImplicitGlobalVariable,
900 info.pattern,
901 info.node,
902 null,
903 null,
904 null
905 ));
906
907 }
908
909 this.implicit.left = this.__left;
910
911 return super.__close(scopeManager);
912 }
913
914 __defineImplicit(node, def) {
915 if (node && node.type === Syntax$2.Identifier) {
916 this.__defineGeneric(
917 node.name,
918 this.implicit.set,
919 this.implicit.variables,
920 node,
921 def
922 );
923 }
924 }
925}
926
927class ModuleScope extends Scope {
928 constructor(scopeManager, upperScope, block) {
929 super(scopeManager, "module", upperScope, block, false);
930 }
931}
932
933class FunctionExpressionNameScope extends Scope {
934 constructor(scopeManager, upperScope, block) {
935 super(scopeManager, "function-expression-name", upperScope, block, false);
936 this.__define(block.id,
937 new Definition(
938 Variable.FunctionName,
939 block.id,
940 block,
941 null,
942 null,
943 null
944 ));
945 this.functionExpressionScope = true;
946 }
947}
948
949class CatchScope extends Scope {
950 constructor(scopeManager, upperScope, block) {
951 super(scopeManager, "catch", upperScope, block, false);
952 }
953}
954
955class WithScope extends Scope {
956 constructor(scopeManager, upperScope, block) {
957 super(scopeManager, "with", upperScope, block, false);
958 }
959
960 __close(scopeManager) {
961 if (this.__shouldStaticallyClose(scopeManager)) {
962 return super.__close(scopeManager);
963 }
964
965 for (let i = 0, iz = this.__left.length; i < iz; ++i) {
966 const ref = this.__left[i];
967
968 ref.tainted = true;
969 this.__delegateToUpperScope(ref);
970 }
971 this.__left = null;
972
973 return this.upper;
974 }
975}
976
977class BlockScope extends Scope {
978 constructor(scopeManager, upperScope, block) {
979 super(scopeManager, "block", upperScope, block, false);
980 }
981}
982
983class SwitchScope extends Scope {
984 constructor(scopeManager, upperScope, block) {
985 super(scopeManager, "switch", upperScope, block, false);
986 }
987}
988
989class FunctionScope extends Scope {
990 constructor(scopeManager, upperScope, block, isMethodDefinition) {
991 super(scopeManager, "function", upperScope, block, isMethodDefinition);
992
993 // section 9.2.13, FunctionDeclarationInstantiation.
994 // NOTE Arrow functions never have an arguments objects.
995 if (this.block.type !== Syntax$2.ArrowFunctionExpression) {
996 this.__defineArguments();
997 }
998 }
999
1000 isArgumentsMaterialized() {
1001
1002 // TODO(Constellation)
1003 // We can more aggressive on this condition like this.
1004 //
1005 // function t() {
1006 // // arguments of t is always hidden.
1007 // function arguments() {
1008 // }
1009 // }
1010 if (this.block.type === Syntax$2.ArrowFunctionExpression) {
1011 return false;
1012 }
1013
1014 if (!this.isStatic()) {
1015 return true;
1016 }
1017
1018 const variable = this.set.get("arguments");
1019
1020 assert__default["default"](variable, "Always have arguments variable.");
1021 return variable.tainted || variable.references.length !== 0;
1022 }
1023
1024 isThisMaterialized() {
1025 if (!this.isStatic()) {
1026 return true;
1027 }
1028 return this.thisFound;
1029 }
1030
1031 __defineArguments() {
1032 this.__defineGeneric(
1033 "arguments",
1034 this.set,
1035 this.variables,
1036 null,
1037 null
1038 );
1039 this.taints.set("arguments", true);
1040 }
1041
1042 // References in default parameters isn't resolved to variables which are in their function body.
1043 // const x = 1
1044 // function f(a = x) { // This `x` is resolved to the `x` in the outer scope.
1045 // const x = 2
1046 // console.log(a)
1047 // }
1048 __isValidResolution(ref, variable) {
1049
1050 // If `options.nodejsScope` is true, `this.block` becomes a Program node.
1051 if (this.block.type === "Program") {
1052 return true;
1053 }
1054
1055 const bodyStart = this.block.body.range[0];
1056
1057 // It's invalid resolution in the following case:
1058 return !(
1059 variable.scope === this &&
1060 ref.identifier.range[0] < bodyStart && // the reference is in the parameter part.
1061 variable.defs.every(d => d.name.range[0] >= bodyStart) // the variable is in the body.
1062 );
1063 }
1064}
1065
1066class ForScope extends Scope {
1067 constructor(scopeManager, upperScope, block) {
1068 super(scopeManager, "for", upperScope, block, false);
1069 }
1070}
1071
1072class ClassScope extends Scope {
1073 constructor(scopeManager, upperScope, block) {
1074 super(scopeManager, "class", upperScope, block, false);
1075 }
1076}
1077
1078class ClassFieldInitializerScope extends Scope {
1079 constructor(scopeManager, upperScope, block) {
1080 super(scopeManager, "class-field-initializer", upperScope, block, true);
1081 }
1082}
1083
1084class ClassStaticBlockScope extends Scope {
1085 constructor(scopeManager, upperScope, block) {
1086 super(scopeManager, "class-static-block", upperScope, block, true);
1087 }
1088}
1089
1090/* vim: set sw=4 ts=4 et tw=80 : */
1091
1092/*
1093 Copyright (C) 2015 Yusuke Suzuki <utatane.tea@gmail.com>
1094
1095 Redistribution and use in source and binary forms, with or without
1096 modification, are permitted provided that the following conditions are met:
1097
1098 * Redistributions of source code must retain the above copyright
1099 notice, this list of conditions and the following disclaimer.
1100 * Redistributions in binary form must reproduce the above copyright
1101 notice, this list of conditions and the following disclaimer in the
1102 documentation and/or other materials provided with the distribution.
1103
1104 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1105 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1106 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1107 ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
1108 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
1109 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
1110 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
1111 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1112 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
1113 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1114*/
1115
1116/**
1117 * @constructor ScopeManager
1118 */
1119class ScopeManager {
1120 constructor(options) {
1121 this.scopes = [];
1122 this.globalScope = null;
1123 this.__nodeToScope = new WeakMap();
1124 this.__currentScope = null;
1125 this.__options = options;
1126 this.__declaredVariables = new WeakMap();
1127 }
1128
1129 __useDirective() {
1130 return this.__options.directive;
1131 }
1132
1133 __isOptimistic() {
1134 return this.__options.optimistic;
1135 }
1136
1137 __ignoreEval() {
1138 return this.__options.ignoreEval;
1139 }
1140
1141 isGlobalReturn() {
1142 return this.__options.nodejsScope || this.__options.sourceType === "commonjs";
1143 }
1144
1145 isModule() {
1146 return this.__options.sourceType === "module";
1147 }
1148
1149 isImpliedStrict() {
1150 return this.__options.impliedStrict;
1151 }
1152
1153 isStrictModeSupported() {
1154 return this.__options.ecmaVersion >= 5;
1155 }
1156
1157 // Returns appropriate scope for this node.
1158 __get(node) {
1159 return this.__nodeToScope.get(node);
1160 }
1161
1162 /**
1163 * Get variables that are declared by the node.
1164 *
1165 * "are declared by the node" means the node is same as `Variable.defs[].node` or `Variable.defs[].parent`.
1166 * If the node declares nothing, this method returns an empty array.
1167 * CAUTION: This API is experimental. See https://github.com/estools/escope/pull/69 for more details.
1168 * @param {Espree.Node} node a node to get.
1169 * @returns {Variable[]} variables that declared by the node.
1170 */
1171 getDeclaredVariables(node) {
1172 return this.__declaredVariables.get(node) || [];
1173 }
1174
1175 /**
1176 * acquire scope from node.
1177 * @function ScopeManager#acquire
1178 * @param {Espree.Node} node node for the acquired scope.
1179 * @param {?boolean} [inner=false] look up the most inner scope, default value is false.
1180 * @returns {Scope?} Scope from node
1181 */
1182 acquire(node, inner) {
1183
1184 /**
1185 * predicate
1186 * @param {Scope} testScope scope to test
1187 * @returns {boolean} predicate
1188 */
1189 function predicate(testScope) {
1190 if (testScope.type === "function" && testScope.functionExpressionScope) {
1191 return false;
1192 }
1193 return true;
1194 }
1195
1196 const scopes = this.__get(node);
1197
1198 if (!scopes || scopes.length === 0) {
1199 return null;
1200 }
1201
1202 // Heuristic selection from all scopes.
1203 // If you would like to get all scopes, please use ScopeManager#acquireAll.
1204 if (scopes.length === 1) {
1205 return scopes[0];
1206 }
1207
1208 if (inner) {
1209 for (let i = scopes.length - 1; i >= 0; --i) {
1210 const scope = scopes[i];
1211
1212 if (predicate(scope)) {
1213 return scope;
1214 }
1215 }
1216 } else {
1217 for (let i = 0, iz = scopes.length; i < iz; ++i) {
1218 const scope = scopes[i];
1219
1220 if (predicate(scope)) {
1221 return scope;
1222 }
1223 }
1224 }
1225
1226 return null;
1227 }
1228
1229 /**
1230 * acquire all scopes from node.
1231 * @function ScopeManager#acquireAll
1232 * @param {Espree.Node} node node for the acquired scope.
1233 * @returns {Scopes?} Scope array
1234 */
1235 acquireAll(node) {
1236 return this.__get(node);
1237 }
1238
1239 /**
1240 * release the node.
1241 * @function ScopeManager#release
1242 * @param {Espree.Node} node releasing node.
1243 * @param {?boolean} [inner=false] look up the most inner scope, default value is false.
1244 * @returns {Scope?} upper scope for the node.
1245 */
1246 release(node, inner) {
1247 const scopes = this.__get(node);
1248
1249 if (scopes && scopes.length) {
1250 const scope = scopes[0].upper;
1251
1252 if (!scope) {
1253 return null;
1254 }
1255 return this.acquire(scope.block, inner);
1256 }
1257 return null;
1258 }
1259
1260 attach() { } // eslint-disable-line class-methods-use-this
1261
1262 detach() { } // eslint-disable-line class-methods-use-this
1263
1264 __nestScope(scope) {
1265 if (scope instanceof GlobalScope) {
1266 assert__default["default"](this.__currentScope === null);
1267 this.globalScope = scope;
1268 }
1269 this.__currentScope = scope;
1270 return scope;
1271 }
1272
1273 __nestGlobalScope(node) {
1274 return this.__nestScope(new GlobalScope(this, node));
1275 }
1276
1277 __nestBlockScope(node) {
1278 return this.__nestScope(new BlockScope(this, this.__currentScope, node));
1279 }
1280
1281 __nestFunctionScope(node, isMethodDefinition) {
1282 return this.__nestScope(new FunctionScope(this, this.__currentScope, node, isMethodDefinition));
1283 }
1284
1285 __nestForScope(node) {
1286 return this.__nestScope(new ForScope(this, this.__currentScope, node));
1287 }
1288
1289 __nestCatchScope(node) {
1290 return this.__nestScope(new CatchScope(this, this.__currentScope, node));
1291 }
1292
1293 __nestWithScope(node) {
1294 return this.__nestScope(new WithScope(this, this.__currentScope, node));
1295 }
1296
1297 __nestClassScope(node) {
1298 return this.__nestScope(new ClassScope(this, this.__currentScope, node));
1299 }
1300
1301 __nestClassFieldInitializerScope(node) {
1302 return this.__nestScope(new ClassFieldInitializerScope(this, this.__currentScope, node));
1303 }
1304
1305 __nestClassStaticBlockScope(node) {
1306 return this.__nestScope(new ClassStaticBlockScope(this, this.__currentScope, node));
1307 }
1308
1309 __nestSwitchScope(node) {
1310 return this.__nestScope(new SwitchScope(this, this.__currentScope, node));
1311 }
1312
1313 __nestModuleScope(node) {
1314 return this.__nestScope(new ModuleScope(this, this.__currentScope, node));
1315 }
1316
1317 __nestFunctionExpressionNameScope(node) {
1318 return this.__nestScope(new FunctionExpressionNameScope(this, this.__currentScope, node));
1319 }
1320
1321 __isES6() {
1322 return this.__options.ecmaVersion >= 6;
1323 }
1324}
1325
1326/* vim: set sw=4 ts=4 et tw=80 : */
1327
1328/*
1329 Copyright (C) 2015 Yusuke Suzuki <utatane.tea@gmail.com>
1330
1331 Redistribution and use in source and binary forms, with or without
1332 modification, are permitted provided that the following conditions are met:
1333
1334 * Redistributions of source code must retain the above copyright
1335 notice, this list of conditions and the following disclaimer.
1336 * Redistributions in binary form must reproduce the above copyright
1337 notice, this list of conditions and the following disclaimer in the
1338 documentation and/or other materials provided with the distribution.
1339
1340 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1341 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1342 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1343 ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
1344 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
1345 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
1346 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
1347 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1348 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
1349 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1350*/
1351
1352const { Syntax: Syntax$1 } = estraverse__default["default"];
1353
1354/**
1355 * Get last array element
1356 * @param {Array} xs array
1357 * @returns {any} Last elment
1358 */
1359function getLast(xs) {
1360 return xs[xs.length - 1] || null;
1361}
1362
1363class PatternVisitor extends esrecurse__default["default"].Visitor {
1364 static isPattern(node) {
1365 const nodeType = node.type;
1366
1367 return (
1368 nodeType === Syntax$1.Identifier ||
1369 nodeType === Syntax$1.ObjectPattern ||
1370 nodeType === Syntax$1.ArrayPattern ||
1371 nodeType === Syntax$1.SpreadElement ||
1372 nodeType === Syntax$1.RestElement ||
1373 nodeType === Syntax$1.AssignmentPattern
1374 );
1375 }
1376
1377 constructor(options, rootPattern, callback) {
1378 super(null, options);
1379 this.rootPattern = rootPattern;
1380 this.callback = callback;
1381 this.assignments = [];
1382 this.rightHandNodes = [];
1383 this.restElements = [];
1384 }
1385
1386 Identifier(pattern) {
1387 const lastRestElement = getLast(this.restElements);
1388
1389 this.callback(pattern, {
1390 topLevel: pattern === this.rootPattern,
1391 rest: lastRestElement !== null && lastRestElement !== undefined && lastRestElement.argument === pattern,
1392 assignments: this.assignments
1393 });
1394 }
1395
1396 Property(property) {
1397
1398 // Computed property's key is a right hand node.
1399 if (property.computed) {
1400 this.rightHandNodes.push(property.key);
1401 }
1402
1403 // If it's shorthand, its key is same as its value.
1404 // If it's shorthand and has its default value, its key is same as its value.left (the value is AssignmentPattern).
1405 // If it's not shorthand, the name of new variable is its value's.
1406 this.visit(property.value);
1407 }
1408
1409 ArrayPattern(pattern) {
1410 for (let i = 0, iz = pattern.elements.length; i < iz; ++i) {
1411 const element = pattern.elements[i];
1412
1413 this.visit(element);
1414 }
1415 }
1416
1417 AssignmentPattern(pattern) {
1418 this.assignments.push(pattern);
1419 this.visit(pattern.left);
1420 this.rightHandNodes.push(pattern.right);
1421 this.assignments.pop();
1422 }
1423
1424 RestElement(pattern) {
1425 this.restElements.push(pattern);
1426 this.visit(pattern.argument);
1427 this.restElements.pop();
1428 }
1429
1430 MemberExpression(node) {
1431
1432 // Computed property's key is a right hand node.
1433 if (node.computed) {
1434 this.rightHandNodes.push(node.property);
1435 }
1436
1437 // the object is only read, write to its property.
1438 this.rightHandNodes.push(node.object);
1439 }
1440
1441 //
1442 // ForInStatement.left and AssignmentExpression.left are LeftHandSideExpression.
1443 // By spec, LeftHandSideExpression is Pattern or MemberExpression.
1444 // (see also: https://github.com/estree/estree/pull/20#issuecomment-74584758)
1445 // But espree 2.0 parses to ArrayExpression, ObjectExpression, etc...
1446 //
1447
1448 SpreadElement(node) {
1449 this.visit(node.argument);
1450 }
1451
1452 ArrayExpression(node) {
1453 node.elements.forEach(this.visit, this);
1454 }
1455
1456 AssignmentExpression(node) {
1457 this.assignments.push(node);
1458 this.visit(node.left);
1459 this.rightHandNodes.push(node.right);
1460 this.assignments.pop();
1461 }
1462
1463 CallExpression(node) {
1464
1465 // arguments are right hand nodes.
1466 node.arguments.forEach(a => {
1467 this.rightHandNodes.push(a);
1468 });
1469 this.visit(node.callee);
1470 }
1471}
1472
1473/* vim: set sw=4 ts=4 et tw=80 : */
1474
1475/*
1476 Copyright (C) 2015 Yusuke Suzuki <utatane.tea@gmail.com>
1477
1478 Redistribution and use in source and binary forms, with or without
1479 modification, are permitted provided that the following conditions are met:
1480
1481 * Redistributions of source code must retain the above copyright
1482 notice, this list of conditions and the following disclaimer.
1483 * Redistributions in binary form must reproduce the above copyright
1484 notice, this list of conditions and the following disclaimer in the
1485 documentation and/or other materials provided with the distribution.
1486
1487 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1488 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1489 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1490 ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
1491 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
1492 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
1493 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
1494 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1495 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
1496 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1497*/
1498
1499const { Syntax } = estraverse__default["default"];
1500
1501/**
1502 * Traverse identifier in pattern
1503 * @param {Object} options options
1504 * @param {pattern} rootPattern root pattern
1505 * @param {Refencer} referencer referencer
1506 * @param {callback} callback callback
1507 * @returns {void}
1508 */
1509function traverseIdentifierInPattern(options, rootPattern, referencer, callback) {
1510
1511 // Call the callback at left hand identifier nodes, and Collect right hand nodes.
1512 const visitor = new PatternVisitor(options, rootPattern, callback);
1513
1514 visitor.visit(rootPattern);
1515
1516 // Process the right hand nodes recursively.
1517 if (referencer !== null && referencer !== undefined) {
1518 visitor.rightHandNodes.forEach(referencer.visit, referencer);
1519 }
1520}
1521
1522// Importing ImportDeclaration.
1523// http://people.mozilla.org/~jorendorff/es6-draft.html#sec-moduledeclarationinstantiation
1524// https://github.com/estree/estree/blob/master/es6.md#importdeclaration
1525// FIXME: Now, we don't create module environment, because the context is
1526// implementation dependent.
1527
1528class Importer extends esrecurse__default["default"].Visitor {
1529 constructor(declaration, referencer) {
1530 super(null, referencer.options);
1531 this.declaration = declaration;
1532 this.referencer = referencer;
1533 }
1534
1535 visitImport(id, specifier) {
1536 this.referencer.visitPattern(id, pattern => {
1537 this.referencer.currentScope().__define(pattern,
1538 new Definition(
1539 Variable.ImportBinding,
1540 pattern,
1541 specifier,
1542 this.declaration,
1543 null,
1544 null
1545 ));
1546 });
1547 }
1548
1549 ImportNamespaceSpecifier(node) {
1550 const local = (node.local || node.id);
1551
1552 if (local) {
1553 this.visitImport(local, node);
1554 }
1555 }
1556
1557 ImportDefaultSpecifier(node) {
1558 const local = (node.local || node.id);
1559
1560 this.visitImport(local, node);
1561 }
1562
1563 ImportSpecifier(node) {
1564 const local = (node.local || node.id);
1565
1566 if (node.name) {
1567 this.visitImport(node.name, node);
1568 } else {
1569 this.visitImport(local, node);
1570 }
1571 }
1572}
1573
1574// Referencing variables and creating bindings.
1575class Referencer extends esrecurse__default["default"].Visitor {
1576 constructor(options, scopeManager) {
1577 super(null, options);
1578 this.options = options;
1579 this.scopeManager = scopeManager;
1580 this.parent = null;
1581 this.isInnerMethodDefinition = false;
1582 }
1583
1584 currentScope() {
1585 return this.scopeManager.__currentScope;
1586 }
1587
1588 close(node) {
1589 while (this.currentScope() && node === this.currentScope().block) {
1590 this.scopeManager.__currentScope = this.currentScope().__close(this.scopeManager);
1591 }
1592 }
1593
1594 pushInnerMethodDefinition(isInnerMethodDefinition) {
1595 const previous = this.isInnerMethodDefinition;
1596
1597 this.isInnerMethodDefinition = isInnerMethodDefinition;
1598 return previous;
1599 }
1600
1601 popInnerMethodDefinition(isInnerMethodDefinition) {
1602 this.isInnerMethodDefinition = isInnerMethodDefinition;
1603 }
1604
1605 referencingDefaultValue(pattern, assignments, maybeImplicitGlobal, init) {
1606 const scope = this.currentScope();
1607
1608 assignments.forEach(assignment => {
1609 scope.__referencing(
1610 pattern,
1611 Reference.WRITE,
1612 assignment.right,
1613 maybeImplicitGlobal,
1614 pattern !== assignment.left,
1615 init
1616 );
1617 });
1618 }
1619
1620 visitPattern(node, options, callback) {
1621 let visitPatternOptions = options;
1622 let visitPatternCallback = callback;
1623
1624 if (typeof options === "function") {
1625 visitPatternCallback = options;
1626 visitPatternOptions = { processRightHandNodes: false };
1627 }
1628
1629 traverseIdentifierInPattern(
1630 this.options,
1631 node,
1632 visitPatternOptions.processRightHandNodes ? this : null,
1633 visitPatternCallback
1634 );
1635 }
1636
1637 visitFunction(node) {
1638 let i, iz;
1639
1640 // FunctionDeclaration name is defined in upper scope
1641 // NOTE: Not referring variableScope. It is intended.
1642 // Since
1643 // in ES5, FunctionDeclaration should be in FunctionBody.
1644 // in ES6, FunctionDeclaration should be block scoped.
1645
1646 if (node.type === Syntax.FunctionDeclaration) {
1647
1648 // id is defined in upper scope
1649 this.currentScope().__define(node.id,
1650 new Definition(
1651 Variable.FunctionName,
1652 node.id,
1653 node,
1654 null,
1655 null,
1656 null
1657 ));
1658 }
1659
1660 // FunctionExpression with name creates its special scope;
1661 // FunctionExpressionNameScope.
1662 if (node.type === Syntax.FunctionExpression && node.id) {
1663 this.scopeManager.__nestFunctionExpressionNameScope(node);
1664 }
1665
1666 // Consider this function is in the MethodDefinition.
1667 this.scopeManager.__nestFunctionScope(node, this.isInnerMethodDefinition);
1668
1669 const that = this;
1670
1671 /**
1672 * Visit pattern callback
1673 * @param {pattern} pattern pattern
1674 * @param {Object} info info
1675 * @returns {void}
1676 */
1677 function visitPatternCallback(pattern, info) {
1678 that.currentScope().__define(pattern,
1679 new ParameterDefinition(
1680 pattern,
1681 node,
1682 i,
1683 info.rest
1684 ));
1685
1686 that.referencingDefaultValue(pattern, info.assignments, null, true);
1687 }
1688
1689 // Process parameter declarations.
1690 for (i = 0, iz = node.params.length; i < iz; ++i) {
1691 this.visitPattern(node.params[i], { processRightHandNodes: true }, visitPatternCallback);
1692 }
1693
1694 // if there's a rest argument, add that
1695 if (node.rest) {
1696 this.visitPattern({
1697 type: "RestElement",
1698 argument: node.rest
1699 }, pattern => {
1700 this.currentScope().__define(pattern,
1701 new ParameterDefinition(
1702 pattern,
1703 node,
1704 node.params.length,
1705 true
1706 ));
1707 });
1708 }
1709
1710 // In TypeScript there are a number of function-like constructs which have no body,
1711 // so check it exists before traversing
1712 if (node.body) {
1713
1714 // Skip BlockStatement to prevent creating BlockStatement scope.
1715 if (node.body.type === Syntax.BlockStatement) {
1716 this.visitChildren(node.body);
1717 } else {
1718 this.visit(node.body);
1719 }
1720 }
1721
1722 this.close(node);
1723 }
1724
1725 visitClass(node) {
1726 if (node.type === Syntax.ClassDeclaration) {
1727 this.currentScope().__define(node.id,
1728 new Definition(
1729 Variable.ClassName,
1730 node.id,
1731 node,
1732 null,
1733 null,
1734 null
1735 ));
1736 }
1737
1738 this.visit(node.superClass);
1739
1740 this.scopeManager.__nestClassScope(node);
1741
1742 if (node.id) {
1743 this.currentScope().__define(node.id,
1744 new Definition(
1745 Variable.ClassName,
1746 node.id,
1747 node
1748 ));
1749 }
1750 this.visit(node.body);
1751
1752 this.close(node);
1753 }
1754
1755 visitProperty(node) {
1756 let previous;
1757
1758 if (node.computed) {
1759 this.visit(node.key);
1760 }
1761
1762 const isMethodDefinition = node.type === Syntax.MethodDefinition;
1763
1764 if (isMethodDefinition) {
1765 previous = this.pushInnerMethodDefinition(true);
1766 }
1767 this.visit(node.value);
1768 if (isMethodDefinition) {
1769 this.popInnerMethodDefinition(previous);
1770 }
1771 }
1772
1773 visitForIn(node) {
1774 if (node.left.type === Syntax.VariableDeclaration && node.left.kind !== "var") {
1775 this.scopeManager.__nestForScope(node);
1776 }
1777
1778 if (node.left.type === Syntax.VariableDeclaration) {
1779 this.visit(node.left);
1780 this.visitPattern(node.left.declarations[0].id, pattern => {
1781 this.currentScope().__referencing(pattern, Reference.WRITE, node.right, null, true, true);
1782 });
1783 } else {
1784 this.visitPattern(node.left, { processRightHandNodes: true }, (pattern, info) => {
1785 let maybeImplicitGlobal = null;
1786
1787 if (!this.currentScope().isStrict) {
1788 maybeImplicitGlobal = {
1789 pattern,
1790 node
1791 };
1792 }
1793 this.referencingDefaultValue(pattern, info.assignments, maybeImplicitGlobal, false);
1794 this.currentScope().__referencing(pattern, Reference.WRITE, node.right, maybeImplicitGlobal, true, false);
1795 });
1796 }
1797 this.visit(node.right);
1798 this.visit(node.body);
1799
1800 this.close(node);
1801 }
1802
1803 visitVariableDeclaration(variableTargetScope, type, node, index) {
1804
1805 const decl = node.declarations[index];
1806 const init = decl.init;
1807
1808 this.visitPattern(decl.id, { processRightHandNodes: true }, (pattern, info) => {
1809 variableTargetScope.__define(
1810 pattern,
1811 new Definition(
1812 type,
1813 pattern,
1814 decl,
1815 node,
1816 index,
1817 node.kind
1818 )
1819 );
1820
1821 this.referencingDefaultValue(pattern, info.assignments, null, true);
1822 if (init) {
1823 this.currentScope().__referencing(pattern, Reference.WRITE, init, null, !info.topLevel, true);
1824 }
1825 });
1826 }
1827
1828 AssignmentExpression(node) {
1829 if (PatternVisitor.isPattern(node.left)) {
1830 if (node.operator === "=") {
1831 this.visitPattern(node.left, { processRightHandNodes: true }, (pattern, info) => {
1832 let maybeImplicitGlobal = null;
1833
1834 if (!this.currentScope().isStrict) {
1835 maybeImplicitGlobal = {
1836 pattern,
1837 node
1838 };
1839 }
1840 this.referencingDefaultValue(pattern, info.assignments, maybeImplicitGlobal, false);
1841 this.currentScope().__referencing(pattern, Reference.WRITE, node.right, maybeImplicitGlobal, !info.topLevel, false);
1842 });
1843 } else {
1844 this.currentScope().__referencing(node.left, Reference.RW, node.right);
1845 }
1846 } else {
1847 this.visit(node.left);
1848 }
1849 this.visit(node.right);
1850 }
1851
1852 CatchClause(node) {
1853 this.scopeManager.__nestCatchScope(node);
1854
1855 this.visitPattern(node.param, { processRightHandNodes: true }, (pattern, info) => {
1856 this.currentScope().__define(pattern,
1857 new Definition(
1858 Variable.CatchClause,
1859 node.param,
1860 node,
1861 null,
1862 null,
1863 null
1864 ));
1865 this.referencingDefaultValue(pattern, info.assignments, null, true);
1866 });
1867 this.visit(node.body);
1868
1869 this.close(node);
1870 }
1871
1872 Program(node) {
1873 this.scopeManager.__nestGlobalScope(node);
1874
1875 if (this.scopeManager.isGlobalReturn()) {
1876
1877 // Force strictness of GlobalScope to false when using node.js scope.
1878 this.currentScope().isStrict = false;
1879 this.scopeManager.__nestFunctionScope(node, false);
1880 }
1881
1882 if (this.scopeManager.__isES6() && this.scopeManager.isModule()) {
1883 this.scopeManager.__nestModuleScope(node);
1884 }
1885
1886 if (this.scopeManager.isStrictModeSupported() && this.scopeManager.isImpliedStrict()) {
1887 this.currentScope().isStrict = true;
1888 }
1889
1890 this.visitChildren(node);
1891 this.close(node);
1892 }
1893
1894 Identifier(node) {
1895 this.currentScope().__referencing(node);
1896 }
1897
1898 // eslint-disable-next-line class-methods-use-this
1899 PrivateIdentifier() {
1900
1901 // Do nothing.
1902 }
1903
1904 UpdateExpression(node) {
1905 if (PatternVisitor.isPattern(node.argument)) {
1906 this.currentScope().__referencing(node.argument, Reference.RW, null);
1907 } else {
1908 this.visitChildren(node);
1909 }
1910 }
1911
1912 MemberExpression(node) {
1913 this.visit(node.object);
1914 if (node.computed) {
1915 this.visit(node.property);
1916 }
1917 }
1918
1919 Property(node) {
1920 this.visitProperty(node);
1921 }
1922
1923 PropertyDefinition(node) {
1924 const { computed, key, value } = node;
1925
1926 if (computed) {
1927 this.visit(key);
1928 }
1929 if (value) {
1930 this.scopeManager.__nestClassFieldInitializerScope(value);
1931 this.visit(value);
1932 this.close(value);
1933 }
1934 }
1935
1936 StaticBlock(node) {
1937 this.scopeManager.__nestClassStaticBlockScope(node);
1938
1939 this.visitChildren(node);
1940
1941 this.close(node);
1942 }
1943
1944 MethodDefinition(node) {
1945 this.visitProperty(node);
1946 }
1947
1948 BreakStatement() {} // eslint-disable-line class-methods-use-this
1949
1950 ContinueStatement() {} // eslint-disable-line class-methods-use-this
1951
1952 LabeledStatement(node) {
1953 this.visit(node.body);
1954 }
1955
1956 ForStatement(node) {
1957
1958 // Create ForStatement declaration.
1959 // NOTE: In ES6, ForStatement dynamically generates
1960 // per iteration environment. However, escope is
1961 // a static analyzer, we only generate one scope for ForStatement.
1962 if (node.init && node.init.type === Syntax.VariableDeclaration && node.init.kind !== "var") {
1963 this.scopeManager.__nestForScope(node);
1964 }
1965
1966 this.visitChildren(node);
1967
1968 this.close(node);
1969 }
1970
1971 ClassExpression(node) {
1972 this.visitClass(node);
1973 }
1974
1975 ClassDeclaration(node) {
1976 this.visitClass(node);
1977 }
1978
1979 CallExpression(node) {
1980
1981 // Check this is direct call to eval
1982 if (!this.scopeManager.__ignoreEval() && node.callee.type === Syntax.Identifier && node.callee.name === "eval") {
1983
1984 // NOTE: This should be `variableScope`. Since direct eval call always creates Lexical environment and
1985 // let / const should be enclosed into it. Only VariableDeclaration affects on the caller's environment.
1986 this.currentScope().variableScope.__detectEval();
1987 }
1988 this.visitChildren(node);
1989 }
1990
1991 BlockStatement(node) {
1992 if (this.scopeManager.__isES6()) {
1993 this.scopeManager.__nestBlockScope(node);
1994 }
1995
1996 this.visitChildren(node);
1997
1998 this.close(node);
1999 }
2000
2001 ThisExpression() {
2002 this.currentScope().variableScope.__detectThis();
2003 }
2004
2005 WithStatement(node) {
2006 this.visit(node.object);
2007
2008 // Then nest scope for WithStatement.
2009 this.scopeManager.__nestWithScope(node);
2010
2011 this.visit(node.body);
2012
2013 this.close(node);
2014 }
2015
2016 VariableDeclaration(node) {
2017 const variableTargetScope = (node.kind === "var") ? this.currentScope().variableScope : this.currentScope();
2018
2019 for (let i = 0, iz = node.declarations.length; i < iz; ++i) {
2020 const decl = node.declarations[i];
2021
2022 this.visitVariableDeclaration(variableTargetScope, Variable.Variable, node, i);
2023 if (decl.init) {
2024 this.visit(decl.init);
2025 }
2026 }
2027 }
2028
2029 // sec 13.11.8
2030 SwitchStatement(node) {
2031 this.visit(node.discriminant);
2032
2033 if (this.scopeManager.__isES6()) {
2034 this.scopeManager.__nestSwitchScope(node);
2035 }
2036
2037 for (let i = 0, iz = node.cases.length; i < iz; ++i) {
2038 this.visit(node.cases[i]);
2039 }
2040
2041 this.close(node);
2042 }
2043
2044 FunctionDeclaration(node) {
2045 this.visitFunction(node);
2046 }
2047
2048 FunctionExpression(node) {
2049 this.visitFunction(node);
2050 }
2051
2052 ForOfStatement(node) {
2053 this.visitForIn(node);
2054 }
2055
2056 ForInStatement(node) {
2057 this.visitForIn(node);
2058 }
2059
2060 ArrowFunctionExpression(node) {
2061 this.visitFunction(node);
2062 }
2063
2064 ImportDeclaration(node) {
2065 assert__default["default"](this.scopeManager.__isES6() && this.scopeManager.isModule(), "ImportDeclaration should appear when the mode is ES6 and in the module context.");
2066
2067 const importer = new Importer(node, this);
2068
2069 importer.visit(node);
2070 }
2071
2072 visitExportDeclaration(node) {
2073 if (node.source) {
2074 return;
2075 }
2076 if (node.declaration) {
2077 this.visit(node.declaration);
2078 return;
2079 }
2080
2081 this.visitChildren(node);
2082 }
2083
2084 // TODO: ExportDeclaration doesn't exist. for bc?
2085 ExportDeclaration(node) {
2086 this.visitExportDeclaration(node);
2087 }
2088
2089 ExportAllDeclaration(node) {
2090 this.visitExportDeclaration(node);
2091 }
2092
2093 ExportDefaultDeclaration(node) {
2094 this.visitExportDeclaration(node);
2095 }
2096
2097 ExportNamedDeclaration(node) {
2098 this.visitExportDeclaration(node);
2099 }
2100
2101 ExportSpecifier(node) {
2102
2103 // TODO: `node.id` doesn't exist. for bc?
2104 const local = (node.id || node.local);
2105
2106 this.visit(local);
2107 }
2108
2109 MetaProperty() { // eslint-disable-line class-methods-use-this
2110
2111 // do nothing.
2112 }
2113}
2114
2115/* vim: set sw=4 ts=4 et tw=80 : */
2116
2117const version = "7.2.2";
2118
2119/*
2120 Copyright (C) 2012-2014 Yusuke Suzuki <utatane.tea@gmail.com>
2121 Copyright (C) 2013 Alex Seville <hi@alexanderseville.com>
2122 Copyright (C) 2014 Thiago de Arruda <tpadilha84@gmail.com>
2123
2124 Redistribution and use in source and binary forms, with or without
2125 modification, are permitted provided that the following conditions are met:
2126
2127 * Redistributions of source code must retain the above copyright
2128 notice, this list of conditions and the following disclaimer.
2129 * Redistributions in binary form must reproduce the above copyright
2130 notice, this list of conditions and the following disclaimer in the
2131 documentation and/or other materials provided with the distribution.
2132
2133 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2134 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2135 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2136 ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
2137 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
2138 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
2139 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
2140 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2141 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2142 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2143*/
2144
2145/**
2146 * Set the default options
2147 * @returns {Object} options
2148 */
2149function defaultOptions() {
2150 return {
2151 optimistic: false,
2152 directive: false,
2153 nodejsScope: false,
2154 impliedStrict: false,
2155 sourceType: "script", // one of ['script', 'module', 'commonjs']
2156 ecmaVersion: 5,
2157 childVisitorKeys: null,
2158 fallback: "iteration"
2159 };
2160}
2161
2162/**
2163 * Preform deep update on option object
2164 * @param {Object} target Options
2165 * @param {Object} override Updates
2166 * @returns {Object} Updated options
2167 */
2168function updateDeeply(target, override) {
2169
2170 /**
2171 * Is hash object
2172 * @param {Object} value Test value
2173 * @returns {boolean} Result
2174 */
2175 function isHashObject(value) {
2176 return typeof value === "object" && value instanceof Object && !(value instanceof Array) && !(value instanceof RegExp);
2177 }
2178
2179 for (const key in override) {
2180 if (Object.prototype.hasOwnProperty.call(override, key)) {
2181 const val = override[key];
2182
2183 if (isHashObject(val)) {
2184 if (isHashObject(target[key])) {
2185 updateDeeply(target[key], val);
2186 } else {
2187 target[key] = updateDeeply({}, val);
2188 }
2189 } else {
2190 target[key] = val;
2191 }
2192 }
2193 }
2194 return target;
2195}
2196
2197/**
2198 * Main interface function. Takes an Espree syntax tree and returns the
2199 * analyzed scopes.
2200 * @function analyze
2201 * @param {espree.Tree} tree Abstract Syntax Tree
2202 * @param {Object} providedOptions Options that tailor the scope analysis
2203 * @param {boolean} [providedOptions.optimistic=false] the optimistic flag
2204 * @param {boolean} [providedOptions.directive=false] the directive flag
2205 * @param {boolean} [providedOptions.ignoreEval=false] whether to check 'eval()' calls
2206 * @param {boolean} [providedOptions.nodejsScope=false] whether the whole
2207 * script is executed under node.js environment. When enabled, escope adds
2208 * a function scope immediately following the global scope.
2209 * @param {boolean} [providedOptions.impliedStrict=false] implied strict mode
2210 * (if ecmaVersion >= 5).
2211 * @param {string} [providedOptions.sourceType='script'] the source type of the script. one of 'script', 'module', and 'commonjs'
2212 * @param {number} [providedOptions.ecmaVersion=5] which ECMAScript version is considered
2213 * @param {Object} [providedOptions.childVisitorKeys=null] Additional known visitor keys. See [esrecurse](https://github.com/estools/esrecurse)'s the `childVisitorKeys` option.
2214 * @param {string} [providedOptions.fallback='iteration'] A kind of the fallback in order to encounter with unknown node. See [esrecurse](https://github.com/estools/esrecurse)'s the `fallback` option.
2215 * @returns {ScopeManager} ScopeManager
2216 */
2217function analyze(tree, providedOptions) {
2218 const options = updateDeeply(defaultOptions(), providedOptions);
2219 const scopeManager = new ScopeManager(options);
2220 const referencer = new Referencer(options, scopeManager);
2221
2222 referencer.visit(tree);
2223
2224 assert__default["default"](scopeManager.__currentScope === null, "currentScope should be null.");
2225
2226 return scopeManager;
2227}
2228
2229/* vim: set sw=4 ts=4 et tw=80 : */
2230
2231exports.Definition = Definition;
2232exports.PatternVisitor = PatternVisitor;
2233exports.Reference = Reference;
2234exports.Referencer = Referencer;
2235exports.Scope = Scope;
2236exports.ScopeManager = ScopeManager;
2237exports.Variable = Variable;
2238exports.analyze = analyze;
2239exports.version = version;
2240//# sourceMappingURL=eslint-scope.cjs.map
Note: See TracBrowser for help on using the repository browser.