@babel/traverse 7.0.0-beta.46 → 7.0.0-beta.47
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.
Potentially problematic release.
This version of @babel/traverse might be problematic. Click here for more details.
- package/lib/cache.js +2 -2
- package/lib/context.js +34 -38
- package/lib/hub.js +6 -3
- package/lib/index.js +7 -7
- package/lib/path/ancestry.js +25 -31
- package/lib/path/comments.js +8 -8
- package/lib/path/context.js +17 -21
- package/lib/path/conversion.js +119 -126
- package/lib/path/evaluation.js +87 -99
- package/lib/path/family.js +26 -36
- package/lib/path/index.js +59 -77
- package/lib/path/inference/index.js +11 -11
- package/lib/path/inference/inferer-reference.js +36 -38
- package/lib/path/inference/inferers.js +14 -14
- package/lib/path/introspection.js +51 -57
- package/lib/path/lib/hoister.js +48 -50
- package/lib/path/lib/removal-hooks.js +2 -2
- package/lib/path/lib/virtual-types.js +75 -45
- package/lib/path/modification.js +33 -42
- package/lib/path/removal.js +3 -7
- package/lib/path/replacement.js +29 -32
- package/lib/scope/binding.js +20 -22
- package/lib/scope/index.js +271 -284
- package/lib/scope/lib/renamer.js +31 -33
- package/lib/visitors.js +59 -73
- package/package.json +9 -9
package/lib/cache.js
CHANGED
@@ -7,9 +7,9 @@ exports.clear = clear;
|
|
7
7
|
exports.clearPath = clearPath;
|
8
8
|
exports.clearScope = clearScope;
|
9
9
|
exports.scope = exports.path = void 0;
|
10
|
-
|
10
|
+
let path = new WeakMap();
|
11
11
|
exports.path = path;
|
12
|
-
|
12
|
+
let scope = new WeakMap();
|
13
13
|
exports.scope = scope;
|
14
14
|
|
15
15
|
function clear() {
|
package/lib/context.js
CHANGED
@@ -5,10 +5,10 @@ Object.defineProperty(exports, "__esModule", {
|
|
5
5
|
});
|
6
6
|
exports.default = void 0;
|
7
7
|
|
8
|
-
var
|
8
|
+
var _path = _interopRequireDefault(require("./path"));
|
9
9
|
|
10
10
|
function t() {
|
11
|
-
|
11
|
+
const data = _interopRequireWildcard(require("@babel/types"));
|
12
12
|
|
13
13
|
t = function t() {
|
14
14
|
return data;
|
@@ -21,10 +21,10 @@ function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj;
|
|
21
21
|
|
22
22
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
23
23
|
|
24
|
-
|
24
|
+
const testing = process.env.NODE_ENV === "test";
|
25
25
|
|
26
|
-
|
27
|
-
|
26
|
+
class TraversalContext {
|
27
|
+
constructor(scope, opts, state, parentPath) {
|
28
28
|
this.queue = null;
|
29
29
|
this.parentPath = parentPath;
|
30
30
|
this.scope = scope;
|
@@ -32,13 +32,11 @@ var TraversalContext = function () {
|
|
32
32
|
this.opts = opts;
|
33
33
|
}
|
34
34
|
|
35
|
-
|
36
|
-
|
37
|
-
_proto.shouldVisit = function shouldVisit(node) {
|
38
|
-
var opts = this.opts;
|
35
|
+
shouldVisit(node) {
|
36
|
+
const opts = this.opts;
|
39
37
|
if (opts.enter || opts.exit) return true;
|
40
38
|
if (opts[node.type]) return true;
|
41
|
-
|
39
|
+
const keys = t().VISITOR_KEYS[node.type];
|
42
40
|
if (!keys || !keys.length) return false;
|
43
41
|
|
44
42
|
for (var _iterator = keys, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
|
@@ -53,24 +51,24 @@ var TraversalContext = function () {
|
|
53
51
|
_ref = _i.value;
|
54
52
|
}
|
55
53
|
|
56
|
-
|
54
|
+
const key = _ref;
|
57
55
|
if (node[key]) return true;
|
58
56
|
}
|
59
57
|
|
60
58
|
return false;
|
61
|
-
}
|
59
|
+
}
|
62
60
|
|
63
|
-
|
64
|
-
return
|
61
|
+
create(node, obj, key, listKey) {
|
62
|
+
return _path.default.get({
|
65
63
|
parentPath: this.parentPath,
|
66
64
|
parent: node,
|
67
65
|
container: obj,
|
68
66
|
key: key,
|
69
|
-
listKey
|
67
|
+
listKey
|
70
68
|
});
|
71
|
-
}
|
69
|
+
}
|
72
70
|
|
73
|
-
|
71
|
+
maybeQueue(path, notPriority) {
|
74
72
|
if (this.trap) {
|
75
73
|
throw new Error("Infinite cycle detected");
|
76
74
|
}
|
@@ -82,14 +80,14 @@ var TraversalContext = function () {
|
|
82
80
|
this.priorityQueue.push(path);
|
83
81
|
}
|
84
82
|
}
|
85
|
-
}
|
83
|
+
}
|
86
84
|
|
87
|
-
|
85
|
+
visitMultiple(container, parent, listKey) {
|
88
86
|
if (container.length === 0) return false;
|
89
|
-
|
87
|
+
const queue = [];
|
90
88
|
|
91
|
-
for (
|
92
|
-
|
89
|
+
for (let key = 0; key < container.length; key++) {
|
90
|
+
const node = container[key];
|
93
91
|
|
94
92
|
if (node && this.shouldVisit(node)) {
|
95
93
|
queue.push(this.create(parent, container, key, listKey));
|
@@ -97,21 +95,21 @@ var TraversalContext = function () {
|
|
97
95
|
}
|
98
96
|
|
99
97
|
return this.visitQueue(queue);
|
100
|
-
}
|
98
|
+
}
|
101
99
|
|
102
|
-
|
100
|
+
visitSingle(node, key) {
|
103
101
|
if (this.shouldVisit(node[key])) {
|
104
102
|
return this.visitQueue([this.create(node, node, key)]);
|
105
103
|
} else {
|
106
104
|
return false;
|
107
105
|
}
|
108
|
-
}
|
106
|
+
}
|
109
107
|
|
110
|
-
|
108
|
+
visitQueue(queue) {
|
111
109
|
this.queue = queue;
|
112
110
|
this.priorityQueue = [];
|
113
|
-
|
114
|
-
|
111
|
+
const visited = [];
|
112
|
+
let stop = false;
|
115
113
|
|
116
114
|
for (var _iterator2 = queue, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) {
|
117
115
|
var _ref2;
|
@@ -125,7 +123,7 @@ var TraversalContext = function () {
|
|
125
123
|
_ref2 = _i2.value;
|
126
124
|
}
|
127
125
|
|
128
|
-
|
126
|
+
const path = _ref2;
|
129
127
|
path.resync();
|
130
128
|
|
131
129
|
if (path.contexts.length === 0 || path.contexts[path.contexts.length - 1] !== this) {
|
@@ -166,17 +164,16 @@ var TraversalContext = function () {
|
|
166
164
|
_ref3 = _i3.value;
|
167
165
|
}
|
168
166
|
|
169
|
-
|
170
|
-
|
171
|
-
_path.popContext();
|
167
|
+
const path = _ref3;
|
168
|
+
path.popContext();
|
172
169
|
}
|
173
170
|
|
174
171
|
this.queue = null;
|
175
172
|
return stop;
|
176
|
-
}
|
173
|
+
}
|
177
174
|
|
178
|
-
|
179
|
-
|
175
|
+
visit(node, key) {
|
176
|
+
const nodes = node[key];
|
180
177
|
if (!nodes) return false;
|
181
178
|
|
182
179
|
if (Array.isArray(nodes)) {
|
@@ -184,9 +181,8 @@ var TraversalContext = function () {
|
|
184
181
|
} else {
|
185
182
|
return this.visitSingle(node, key);
|
186
183
|
}
|
187
|
-
}
|
184
|
+
}
|
188
185
|
|
189
|
-
|
190
|
-
}();
|
186
|
+
}
|
191
187
|
|
192
188
|
exports.default = TraversalContext;
|
package/lib/hub.js
CHANGED
package/lib/index.js
CHANGED
@@ -31,7 +31,7 @@ var visitors = _interopRequireWildcard(require("./visitors"));
|
|
31
31
|
exports.visitors = visitors;
|
32
32
|
|
33
33
|
function _includes() {
|
34
|
-
|
34
|
+
const data = _interopRequireDefault(require("lodash/includes"));
|
35
35
|
|
36
36
|
_includes = function _includes() {
|
37
37
|
return data;
|
@@ -41,7 +41,7 @@ function _includes() {
|
|
41
41
|
}
|
42
42
|
|
43
43
|
function t() {
|
44
|
-
|
44
|
+
const data = _interopRequireWildcard(require("@babel/types"));
|
45
45
|
|
46
46
|
t = function t() {
|
47
47
|
return data;
|
@@ -68,7 +68,7 @@ function traverse(parent, opts, scope, state, parentPath) {
|
|
68
68
|
|
69
69
|
if (!opts.noScope && !scope) {
|
70
70
|
if (parent.type !== "Program" && parent.type !== "File") {
|
71
|
-
throw new Error("You must pass a scope and parentPath unless traversing a Program/File. " +
|
71
|
+
throw new Error("You must pass a scope and parentPath unless traversing a Program/File. " + `Instead of that you tried to traverse a ${parent.type} node without ` + "passing scope and parentPath.");
|
72
72
|
}
|
73
73
|
}
|
74
74
|
|
@@ -85,9 +85,9 @@ traverse.cheap = function (node, enter) {
|
|
85
85
|
};
|
86
86
|
|
87
87
|
traverse.node = function (node, opts, scope, state, parentPath, skipKeys) {
|
88
|
-
|
88
|
+
const keys = t().VISITOR_KEYS[node.type];
|
89
89
|
if (!keys) return;
|
90
|
-
|
90
|
+
const context = new _context.default(scope, opts, state, parentPath);
|
91
91
|
|
92
92
|
for (var _iterator = keys, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
|
93
93
|
var _ref;
|
@@ -101,7 +101,7 @@ traverse.node = function (node, opts, scope, state, parentPath, skipKeys) {
|
|
101
101
|
_ref = _i.value;
|
102
102
|
}
|
103
103
|
|
104
|
-
|
104
|
+
const key = _ref;
|
105
105
|
if (skipKeys && skipKeys[key]) continue;
|
106
106
|
if (context.visit(node, key)) return;
|
107
107
|
}
|
@@ -127,7 +127,7 @@ function hasBlacklistedType(path, state) {
|
|
127
127
|
traverse.hasType = function (tree, type, blacklistTypes) {
|
128
128
|
if ((0, _includes().default)(blacklistTypes, tree.type)) return false;
|
129
129
|
if (tree.type === type) return true;
|
130
|
-
|
130
|
+
const state = {
|
131
131
|
has: false,
|
132
132
|
type: type
|
133
133
|
};
|
package/lib/path/ancestry.js
CHANGED
@@ -15,7 +15,7 @@ exports.isDescendant = isDescendant;
|
|
15
15
|
exports.inType = inType;
|
16
16
|
|
17
17
|
function t() {
|
18
|
-
|
18
|
+
const data = _interopRequireWildcard(require("@babel/types"));
|
19
19
|
|
20
20
|
t = function t() {
|
21
21
|
return data;
|
@@ -31,7 +31,7 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
|
|
31
31
|
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
|
32
32
|
|
33
33
|
function findParent(callback) {
|
34
|
-
|
34
|
+
let path = this;
|
35
35
|
|
36
36
|
while (path = path.parentPath) {
|
37
37
|
if (callback(path)) return path;
|
@@ -41,7 +41,7 @@ function findParent(callback) {
|
|
41
41
|
}
|
42
42
|
|
43
43
|
function find(callback) {
|
44
|
-
|
44
|
+
let path = this;
|
45
45
|
|
46
46
|
do {
|
47
47
|
if (callback(path)) return path;
|
@@ -51,13 +51,11 @@ function find(callback) {
|
|
51
51
|
}
|
52
52
|
|
53
53
|
function getFunctionParent() {
|
54
|
-
return this.findParent(
|
55
|
-
return p.isFunction();
|
56
|
-
});
|
54
|
+
return this.findParent(p => p.isFunction());
|
57
55
|
}
|
58
56
|
|
59
57
|
function getStatementParent() {
|
60
|
-
|
58
|
+
let path = this;
|
61
59
|
|
62
60
|
do {
|
63
61
|
if (!path.parentPath || Array.isArray(path.container) && path.isStatement()) {
|
@@ -76,13 +74,13 @@ function getStatementParent() {
|
|
76
74
|
|
77
75
|
function getEarliestCommonAncestorFrom(paths) {
|
78
76
|
return this.getDeepestCommonAncestorFrom(paths, function (deepest, i, ancestries) {
|
79
|
-
|
80
|
-
|
77
|
+
let earliest;
|
78
|
+
const keys = t().VISITOR_KEYS[deepest.type];
|
81
79
|
var _arr = ancestries;
|
82
80
|
|
83
81
|
for (var _i = 0; _i < _arr.length; _i++) {
|
84
|
-
|
85
|
-
|
82
|
+
const ancestry = _arr[_i];
|
83
|
+
const path = ancestry[i + 1];
|
86
84
|
|
87
85
|
if (!earliest) {
|
88
86
|
earliest = path;
|
@@ -96,8 +94,8 @@ function getEarliestCommonAncestorFrom(paths) {
|
|
96
94
|
}
|
97
95
|
}
|
98
96
|
|
99
|
-
|
100
|
-
|
97
|
+
const earliestKeyIndex = keys.indexOf(earliest.parentKey);
|
98
|
+
const currentKeyIndex = keys.indexOf(path.parentKey);
|
101
99
|
|
102
100
|
if (earliestKeyIndex > currentKeyIndex) {
|
103
101
|
earliest = path;
|
@@ -109,8 +107,6 @@ function getEarliestCommonAncestorFrom(paths) {
|
|
109
107
|
}
|
110
108
|
|
111
109
|
function getDeepestCommonAncestorFrom(paths, filter) {
|
112
|
-
var _this = this;
|
113
|
-
|
114
110
|
if (!paths.length) {
|
115
111
|
return this;
|
116
112
|
}
|
@@ -119,14 +115,14 @@ function getDeepestCommonAncestorFrom(paths, filter) {
|
|
119
115
|
return paths[0];
|
120
116
|
}
|
121
117
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
118
|
+
let minDepth = Infinity;
|
119
|
+
let lastCommonIndex, lastCommon;
|
120
|
+
const ancestries = paths.map(path => {
|
121
|
+
const ancestry = [];
|
126
122
|
|
127
123
|
do {
|
128
124
|
ancestry.unshift(path);
|
129
|
-
} while ((path = path.parentPath) && path !==
|
125
|
+
} while ((path = path.parentPath) && path !== this);
|
130
126
|
|
131
127
|
if (ancestry.length < minDepth) {
|
132
128
|
minDepth = ancestry.length;
|
@@ -134,14 +130,14 @@ function getDeepestCommonAncestorFrom(paths, filter) {
|
|
134
130
|
|
135
131
|
return ancestry;
|
136
132
|
});
|
137
|
-
|
133
|
+
const first = ancestries[0];
|
138
134
|
|
139
|
-
depthLoop: for (
|
140
|
-
|
135
|
+
depthLoop: for (let i = 0; i < minDepth; i++) {
|
136
|
+
const shouldMatch = first[i];
|
141
137
|
var _arr2 = ancestries;
|
142
138
|
|
143
139
|
for (var _i2 = 0; _i2 < _arr2.length; _i2++) {
|
144
|
-
|
140
|
+
const ancestry = _arr2[_i2];
|
145
141
|
|
146
142
|
if (ancestry[i] !== shouldMatch) {
|
147
143
|
break depthLoop;
|
@@ -164,8 +160,8 @@ function getDeepestCommonAncestorFrom(paths, filter) {
|
|
164
160
|
}
|
165
161
|
|
166
162
|
function getAncestry() {
|
167
|
-
|
168
|
-
|
163
|
+
let path = this;
|
164
|
+
const paths = [];
|
169
165
|
|
170
166
|
do {
|
171
167
|
paths.push(path);
|
@@ -179,19 +175,17 @@ function isAncestor(maybeDescendant) {
|
|
179
175
|
}
|
180
176
|
|
181
177
|
function isDescendant(maybeAncestor) {
|
182
|
-
return !!this.findParent(
|
183
|
-
return parent === maybeAncestor;
|
184
|
-
});
|
178
|
+
return !!this.findParent(parent => parent === maybeAncestor);
|
185
179
|
}
|
186
180
|
|
187
181
|
function inType() {
|
188
|
-
|
182
|
+
let path = this;
|
189
183
|
|
190
184
|
while (path) {
|
191
185
|
var _arr3 = arguments;
|
192
186
|
|
193
187
|
for (var _i3 = 0; _i3 < _arr3.length; _i3++) {
|
194
|
-
|
188
|
+
const type = _arr3[_i3];
|
195
189
|
if (path.node.type === type) return true;
|
196
190
|
}
|
197
191
|
|
package/lib/path/comments.js
CHANGED
@@ -8,7 +8,7 @@ exports.addComment = addComment;
|
|
8
8
|
exports.addComments = addComments;
|
9
9
|
|
10
10
|
function t() {
|
11
|
-
|
11
|
+
const data = _interopRequireWildcard(require("@babel/types"));
|
12
12
|
|
13
13
|
t = function t() {
|
14
14
|
return data;
|
@@ -21,15 +21,15 @@ function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj;
|
|
21
21
|
|
22
22
|
function shareCommentsWithSiblings() {
|
23
23
|
if (typeof this.key === "string") return;
|
24
|
-
|
24
|
+
const node = this.node;
|
25
25
|
if (!node) return;
|
26
|
-
|
27
|
-
|
26
|
+
const trailing = node.trailingComments;
|
27
|
+
const leading = node.leadingComments;
|
28
28
|
if (!trailing && !leading) return;
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
29
|
+
const prev = this.getSibling(this.key - 1);
|
30
|
+
const next = this.getSibling(this.key + 1);
|
31
|
+
const hasPrev = Boolean(prev.node);
|
32
|
+
const hasNext = Boolean(next.node);
|
33
33
|
|
34
34
|
if (hasPrev && hasNext) {} else if (hasPrev) {
|
35
35
|
prev.addComments("trailing", trailing);
|
package/lib/path/context.js
CHANGED
@@ -29,7 +29,7 @@ var _index = _interopRequireDefault(require("../index"));
|
|
29
29
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
30
30
|
|
31
31
|
function call(key) {
|
32
|
-
|
32
|
+
const opts = this.opts;
|
33
33
|
this.debug(key);
|
34
34
|
|
35
35
|
if (this.node) {
|
@@ -58,18 +58,18 @@ function _call(fns) {
|
|
58
58
|
_ref = _i.value;
|
59
59
|
}
|
60
60
|
|
61
|
-
|
61
|
+
const fn = _ref;
|
62
62
|
if (!fn) continue;
|
63
|
-
|
63
|
+
const node = this.node;
|
64
64
|
if (!node) return true;
|
65
|
-
|
65
|
+
const ret = fn.call(this.state, this, this.state);
|
66
66
|
|
67
67
|
if (ret && typeof ret === "object" && typeof ret.then === "function") {
|
68
|
-
throw new Error(
|
68
|
+
throw new Error(`You appear to be using a plugin with an async traversal visitor, ` + `which your current version of Babel does not support.` + `If you're using a published plugin, you may need to upgrade ` + `your @babel/core version.`);
|
69
69
|
}
|
70
70
|
|
71
71
|
if (ret) {
|
72
|
-
throw new Error(
|
72
|
+
throw new Error(`Unexpected return value from visitor method ${fn}`);
|
73
73
|
}
|
74
74
|
|
75
75
|
if (this.node !== node) return true;
|
@@ -80,7 +80,7 @@ function _call(fns) {
|
|
80
80
|
}
|
81
81
|
|
82
82
|
function isBlacklisted() {
|
83
|
-
|
83
|
+
const blacklist = this.opts.blacklist;
|
84
84
|
return blacklist && blacklist.indexOf(this.node.type) > -1;
|
85
85
|
}
|
86
86
|
|
@@ -125,8 +125,8 @@ function stop() {
|
|
125
125
|
|
126
126
|
function setScope() {
|
127
127
|
if (this.opts && this.opts.noScope) return;
|
128
|
-
|
129
|
-
|
128
|
+
let path = this.parentPath;
|
129
|
+
let target;
|
130
130
|
|
131
131
|
while (path && !target) {
|
132
132
|
if (path.opts && path.opts.noScope) return;
|
@@ -175,13 +175,13 @@ function _resyncKey() {
|
|
175
175
|
if (this.node === this.container[this.key]) return;
|
176
176
|
|
177
177
|
if (Array.isArray(this.container)) {
|
178
|
-
for (
|
178
|
+
for (let i = 0; i < this.container.length; i++) {
|
179
179
|
if (this.container[i] === this.node) {
|
180
180
|
return this.setKey(i);
|
181
181
|
}
|
182
182
|
}
|
183
183
|
} else {
|
184
|
-
for (
|
184
|
+
for (const key in this.container) {
|
185
185
|
if (this.container[key] === this.node) {
|
186
186
|
return this.setKey(key);
|
187
187
|
}
|
@@ -193,7 +193,7 @@ function _resyncKey() {
|
|
193
193
|
|
194
194
|
function _resyncList() {
|
195
195
|
if (!this.parent || !this.inList) return;
|
196
|
-
|
196
|
+
const newContainer = this.parent[this.listKey];
|
197
197
|
if (this.container === newContainer) return;
|
198
198
|
this.container = newContainer || null;
|
199
199
|
}
|
@@ -234,13 +234,9 @@ function setKey(key) {
|
|
234
234
|
this.type = this.node && this.node.type;
|
235
235
|
}
|
236
236
|
|
237
|
-
function requeue(pathToQueue) {
|
238
|
-
if (pathToQueue === void 0) {
|
239
|
-
pathToQueue = this;
|
240
|
-
}
|
241
|
-
|
237
|
+
function requeue(pathToQueue = this) {
|
242
238
|
if (pathToQueue.removed) return;
|
243
|
-
|
239
|
+
const contexts = this.contexts;
|
244
240
|
|
245
241
|
for (var _iterator2 = contexts, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) {
|
246
242
|
var _ref2;
|
@@ -254,14 +250,14 @@ function requeue(pathToQueue) {
|
|
254
250
|
_ref2 = _i2.value;
|
255
251
|
}
|
256
252
|
|
257
|
-
|
253
|
+
const context = _ref2;
|
258
254
|
context.maybeQueue(pathToQueue);
|
259
255
|
}
|
260
256
|
}
|
261
257
|
|
262
258
|
function _getQueueContexts() {
|
263
|
-
|
264
|
-
|
259
|
+
let path = this;
|
260
|
+
let contexts = this.contexts;
|
265
261
|
|
266
262
|
while (!contexts.length) {
|
267
263
|
path = path.parentPath;
|