[traverse] Allow skipping nodes inserted with .replaceWith() (#9777)
* Avoid regression
This commit is contained in:
parent
b5b8055cc0
commit
43b623c1f1
@ -67,7 +67,12 @@ export function visit(): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.call("enter") || this.shouldSkip) {
|
||||
// Note: We need to check "this.shouldSkip" twice because
|
||||
// the visitor can set it to true. Usually .shouldSkip is false
|
||||
// before calling the enter visitor, but it can be true in case of
|
||||
// a requeued node (e.g. by .replaceWith()) that is then marked
|
||||
// with .skip().
|
||||
if (this.shouldSkip || this.call("enter") || this.shouldSkip) {
|
||||
this.debug("Skip...");
|
||||
return this.shouldStop;
|
||||
}
|
||||
@ -233,6 +238,14 @@ export function setKey(key) {
|
||||
export function requeue(pathToQueue = this) {
|
||||
if (pathToQueue.removed) return;
|
||||
|
||||
// TODO: Uncomment in Babel 8. If a path is skipped, and then replaced with a
|
||||
// new one, the new one shouldn't probably be skipped.
|
||||
// Note that this currently causes an infinite loop because of
|
||||
// packages/babel-plugin-transform-block-scoping/src/tdz.js#L52-L59
|
||||
// (b5b8055cc00756f94bf71deb45f288738520ee3c)
|
||||
//
|
||||
// pathToQueue.shouldSkip = false;
|
||||
|
||||
// TODO(loganfsmyth): This should be switched back to queue in parent contexts
|
||||
// automatically once #2892 and #4135 have been resolved. See #4140.
|
||||
// let contexts = this._getQueueContexts();
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import cloneDeep from "lodash/cloneDeep";
|
||||
import traverse from "../lib";
|
||||
import { parse } from "@babel/parser";
|
||||
import * as t from "@babel/types";
|
||||
|
||||
describe("traverse", function() {
|
||||
const code = `
|
||||
@ -174,4 +175,45 @@ describe("traverse", function() {
|
||||
expect(p).not.toBe(scopes[i]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("path.skip()", function() {
|
||||
it("replaced paths can be skipped", function() {
|
||||
const ast = parse("id");
|
||||
|
||||
let skipped;
|
||||
traverse(ast, {
|
||||
noScope: true,
|
||||
Identifier(path) {
|
||||
path.replaceWith(t.numericLiteral(0));
|
||||
path.skip();
|
||||
skipped = true;
|
||||
},
|
||||
NumericLiteral() {
|
||||
skipped = false;
|
||||
},
|
||||
});
|
||||
|
||||
expect(skipped).toBe(true);
|
||||
});
|
||||
|
||||
// Skipped: see the comment in the `NodePath.requque` method.
|
||||
it.skip("skipped and requeued paths should be visited", function() {
|
||||
const ast = parse("id");
|
||||
|
||||
let visited = false;
|
||||
traverse(ast, {
|
||||
noScope: true,
|
||||
Identifier(path) {
|
||||
path.replaceWith(t.numericLiteral(0));
|
||||
path.skip();
|
||||
path.requeue();
|
||||
},
|
||||
NumericLiteral() {
|
||||
visited = true;
|
||||
},
|
||||
});
|
||||
|
||||
expect(visited).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user