fix(providence): swc-traverse does not fail on object proto builtins like "toString"

This commit is contained in:
Thijs Louisse 2023-11-29 12:40:20 +01:00 committed by Thijs Louisse
parent 42eca7b782
commit 292dcfc855
3 changed files with 18 additions and 8 deletions

View file

@ -0,0 +1,5 @@
---
'providence-analytics': patch
---
fix: corrected export path for MatchImportAnalyzer

View file

@ -107,7 +107,7 @@ function createSwcPath(node, parent, stop, scope) {
*/ */
function isBindingNode(parent, identifierValue) { function isBindingNode(parent, identifierValue) {
if (parent.type === 'VariableDeclarator') { if (parent.type === 'VariableDeclarator') {
// @ts-ignore // @ts-expect-error
return parent.id.value === identifierValue; return parent.id.value === identifierValue;
} }
return [ return [
@ -120,10 +120,7 @@ function isBindingNode(parent, identifierValue) {
} }
/** /**
* Is the node: * Is the node a reference to a binding (like "alert(a);")?
* - a declaration (like "const a = 1")?
* - an import specifier (like "import { a } from 'b'")?
* Handy to know if the parents of Identifiers mark a binding
* @param {SwcNode} parent * @param {SwcNode} parent
*/ */
function isBindingRefNode(parent) { function isBindingRefNode(parent) {
@ -184,7 +181,8 @@ function addPotentialBindingOrRefToScope(swcPathForIdentifier) {
} }
// In other cases, we are dealing with a reference that must be bound to a binding // In other cases, we are dealing with a reference that must be bound to a binding
else if (isBindingRefNode(parent)) { else if (isBindingRefNode(parent)) {
const binding = scope.bindings[node.value]; // eslint-disable-next-line no-prototype-builtins
const binding = scope.bindings.hasOwnProperty(node.value) && scope.bindings[node.value];
if (binding) { if (binding) {
binding.refs.push(parentPath); binding.refs.push(parentPath);
} else { } else {
@ -297,7 +295,7 @@ export function swcTraverse(swcAst, visitor, { needsAdvancedPaths = false } = {}
const newOrCurScope = getNewScope(swcPath, scope, traversalContext) || scope; const newOrCurScope = getNewScope(swcPath, scope, traversalContext) || scope;
swcPath.scope = newOrCurScope; swcPath.scope = newOrCurScope;
addPotentialBindingOrRefToScope(swcPath); addPotentialBindingOrRefToScope(swcPath);
return { newOrCurScope, swcPath }; return { swcPath, newOrCurScope };
}; };
/** /**
@ -355,6 +353,6 @@ export function swcTraverse(swcAst, visitor, { needsAdvancedPaths = false } = {}
prepareTree(swcAst, null, initialScope, traversalContext); prepareTree(swcAst, null, initialScope, traversalContext);
} }
visitTree(swcAst, null, initialScope, { hasPreparedTree: needsAdvancedPaths }, traversalContext); visitTree(swcAst, null, initialScope, { hasPreparedTree: needsAdvancedPaths }, traversalContext);
// @ts-ignore // @ts-expect-error
traversalContext.visitOnExitFns.reverse().forEach(fn => fn()); traversalContext.visitOnExitFns.reverse().forEach(fn => fn());
} }

View file

@ -113,6 +113,13 @@ describe('swcTraverse', () => {
// TODO: also add case for Script // TODO: also add case for Script
expect(rootPath.node.type).to.equal('Module'); expect(rootPath.node.type).to.equal('Module');
}); });
it('does not fail on object prototype built-ins (like "toString")', async () => {
const code = `const { toString } = x;`;
const swcAst = await AstService._getSwcAst(code);
expect(swcTraverse(swcAst, {})).to.not.throw;
});
}); });
describe.skip('Paths', () => { describe.skip('Paths', () => {