Improve babel-helper-define-polyfill-provider resolveSource logic#249
Improve babel-helper-define-polyfill-provider resolveSource logic#249nicolo-ribaudo merged 3 commits intobabel:mainfrom
babel-helper-define-polyfill-provider resolveSource logic#249Conversation
c1d157f to
6f65df9
Compare
nicolo-ribaudo
left a comment
There was a problem hiding this comment.
Thank you! Can you add also a test case for the ambiguous (a + b).foo?
nicolo-ribaudo
left a comment
There was a problem hiding this comment.
Code changes look good to me
It's already here. Sure, the case that could be determined, but I think it's future work. |
1110399 to
889abad
Compare
nicolo-ribaudo
left a comment
There was a problem hiding this comment.
Awesome, thanks again :)
|
It seems some more moments. For example, |
|
Yes, |
|
Done. |
|
Thank you! I'm going to merge this and release. We are doing some clean up and dropping old Node.js versions (#250), so if we will then need more releases also for the Babel 7 release line those will take a bit more effort. |
|
@nicolo-ribaudo I wanted to save compatibility of the plugin with Babel@7 - will it be compatible? Sure, since Node requirement will be bumped - not in the scope of |
|
It seems because |
|
I noticed that the changes to resolveSource in #249 may introduce an infinite loop issue. Like this: ProblemThe new version of resolveSource adds recursive calls to itself in several cases: case "SequenceExpression": {
return resolveSource(expressions[expressions.length - 1]);
}
case "AssignmentExpression": {
return resolveSource(...get("right"));
}
case "ConditionalExpression": {
const consequent = resolveSource(...);
const alternate = resolveSource(...);
}
case "ParenthesizedExpression":
return resolveSource(...);
// TypeScript/Flow type wrappers also have recursive callsHowever, unlike the resolve function which uses a visited Set to prevent infinite loops: function resolve(
path: NodePath,
resolved: Set<NodePath> = new Set(), // ✅ Has protection
): NodePath | undefined {
if (resolved.has(path)) return;
resolved.add(path);
// ...
}The resolveSource function has no such protection mechanism. How it can cause infinite loopSince resolveSource calls resolve(obj) internally, and resolve may return the same path or a related node, the recursive calls in the new cases can potentially loop indefinitely. For example, with complex nested expressions or edge cases in AST manipulation. Suggested fixAdd a visited Set parameter to resolveSource: export function resolveSource(
obj: NodePath,
visited: Set<NodePath> = new Set()
): { id: string | null; placement: "prototype" | "static" | null } {
if (visited.has(obj)) {
return { id: null, placement: null };
}
visited.add(obj);
// ... existing logic ...
// Pass visited to all recursive calls
case "SequenceExpression": {
return resolveSource(expressions[expressions.length - 1], visited);
}
// ... etc
}I encountered this infinite loop issue in production. Would you be able to take a look? Thanks! |
It will be compatible with Babel 7 on Node.js 20+, which supports require(esm) |
|
@jackjsj could you open a PR? |

Some years ago, I found that
babel-helper-define-polyfill-providercouldn't properly determineNumberinstance properties (in Babel 7, number literals produceNumericLiteralnodes), and templates weren't recognized as strings. I didn't have time to explore the problem further.Now I'm working on a Babel plugin for
core-js@4, and I need better type inference logic for instance properties -)