saha
saha

Reputation: 47

traversing unvisited nodes in Babel

I want to traverse some of the string literals in one traversal and generate the ouput. and the string literals that are not visited in the first traversal should be traversed in the second traversal. the rule that which string literals should be visited in the first traversal and which should be visited in the second traversal is not important. the important note is that I want to traverse unvisited nodes in the second traversal. to know which of the nodes are visited in the first traversal I used a weakset and put the visited nodes in the weakset. and in the second traversal I check the weakset for the existence of the node and if it doesn't exist I change it. but this approach doesn't work. I understand that the when I put some nodes in the weakset and in the second traversal check for the existence of that nodes the result is false (the node exist in the weakset but it says that it doesn't exist). see the below code:

const babel = require('@babel/core');

const code = `
function greet(name) {
  return 'Hello ' + name;
}
console.log(greet('tanhauhau')); 
`;
var visited_past = new WeakSet(); 

const output = babel.transformSync(code, {
  plugins: [
    function myCustomPlugin() {
      return {
        visitor: {
            
          StringLiteral(path) {
          console.log("first traversal :");
            console.log(path.node);
            visited_past.add(path.node);
          },
          
        },
      };
    },
  ],
});
const output2 = babel.transformSync(code, {
  plugins: [
    function myCustomPlugin() {
      return {
        visitor: {
       
          StringLiteral(path) {  
           console.log("second traversal :");
              console.log(path.node);       
            console.log(visited_past.has(path.node));
          },
        },
      };
    },
  ],
});

the output is:

first traversal :
Node {
  type: 'StringLiteral',
  start: 33,
  end: 41,
  loc: SourceLocation {
    start: Position { line: 3, column: 9, index: 33 },
    end: Position { line: 3, column: 17, index: 41 },
    filename: undefined,
    identifierName: undefined
  },
  extra: { rawValue: 'Hello ', raw: "'Hello '" },
  value: 'Hello ',
  leadingComments: undefined,
  innerComments: undefined,
  trailingComments: undefined
}
first traversal :
Node {
  type: 'StringLiteral',
  start: 70,
  end: 81,
  loc: SourceLocation {
    start: Position { line: 5, column: 18, index: 70 },
    end: Position { line: 5, column: 29, index: 81 },
    filename: undefined,
    identifierName: undefined
  },
  extra: { rawValue: 'tanhauhau', raw: "'tanhauhau'" },
  value: 'tanhauhau',
  leadingComments: undefined,
  innerComments: undefined,
  trailingComments: undefined
}
second traversal :
Node {
  type: 'StringLiteral',
  start: 33,
  end: 41,
  loc: SourceLocation {
    start: Position { line: 3, column: 9, index: 33 },
    end: Position { line: 3, column: 17, index: 41 },
    filename: undefined,
    identifierName: undefined
  },
  extra: { rawValue: 'Hello ', raw: "'Hello '" },
  value: 'Hello ',
  leadingComments: undefined,
  innerComments: undefined,
  trailingComments: undefined
}
false
second traversal :
Node {
  type: 'StringLiteral',
  start: 70,
  end: 81,
  loc: SourceLocation {
    start: Position { line: 5, column: 18, index: 70 },
    end: Position { line: 5, column: 29, index: 81 },
    filename: undefined,
    identifierName: undefined
  },
  extra: { rawValue: 'tanhauhau', raw: "'tanhauhau'" },
  value: 'tanhauhau',
  leadingComments: undefined,
  innerComments: undefined,
  trailingComments: undefined
}
false

what should I do?

Upvotes: 1

Views: 251

Answers (1)

Tim Brown
Tim Brown

Reputation: 3241

Depending on your use case, you could do a few things:

If you aren't changing anything in the file, you could just store the path.node.start of visited nodes and then skip those on the second traversal.

If things could change length, but not order, you could use path.scope.generateUidIdentifier("uid") as a key for each node as you visit them.

Otherwise you'll have to get clever with something like following the node parentPath chain to build a key, or using the text value itself.

Upvotes: 0

Related Questions