-
-
Notifications
You must be signed in to change notification settings - Fork 5.8k
Description
I recently realized we've got bug with our invalidation logic for NodePath that can cause some real weirdness. Here it is on ASTExplorer and here:
var mem = template("property.access")();
traverse(mem, {noScope: true});
var p2 = path.insertAfter(mem)[0];
console.log(p2.get("expression").hub);
will print undefined for hub even through p2.hub is the Hub class instance.
Which is surprising because in
| if (!hub && parentPath) { |
hub value is explicitly supposed to pass down.
It fails in this case because on
| if (pathCheck.node === targetNode) { |
The problem is, what do we do. Two options come to mind:
- Overwrite the
.hubon the cache result. - Only accept items from the cache if the hub is correct.
Option 1
Pretty gross because we could just as easily be introducing another bug by removing a Hub instance that was supposed to be there
Option 2
Sounds reasonable, until you realize that we actually crucially rely on this gross caching behavior to instantiate NodePath with the correct Hub instance in the first place.
In File init in
| hub: this.hub, |
NodePath, but then we never really do anything with it. Traversal begins on | traverse(file.ast, visitor, file.scope); |
this.path at all. That path ends up being used, thus using the root Hub, because it is present in the cache. If we explicitly test for the Hub in the cache, we'll break this weird cache-based pass-through logic.
Solution?
To me, the "feature" we're breaking in option 2 is totally a mistake to rely on since it is essentially relying on sideeffects to the extreme. This means we need a way to do two things:
- Initialize the NodePath up front, so it can be stored on the
Fileclass instance - Perform a traversal using this NodePath, while ensuring that same traversal logic we have now is preserved.
The exact details on how we do those two things is up in the air, but feels like something we should figure out ASAP.
Incidentally, this same bug is the reason we have to do
babel/packages/babel-template/src/index.js
Line 218 in d511cfc
| traverse.clearNode(node); |
babel-template would trigger this bug, due to the internal traversal, which doesn't have a hub, polluting the cache.