Skip to content

Conversation

@vespa7
Copy link

@vespa7 vespa7 commented Nov 19, 2025

Closes #173

package.json Outdated
"migrations",
"node.js"
],
"node.js" ],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you should revert this change

Copy link
Member

@AugustinMauroy AugustinMauroy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing test case for dynamic import

@vespa7
Copy link
Author

vespa7 commented Nov 19, 2025

Missing test case for dynamic import

Yes, it’s in draft. It doesn’t need to be corrected yet. I’m waiting for a question to be resolved.

@JakobJingleheimer
Copy link
Member

Yes, it’s in draft. It doesn’t need to be corrected yet. I’m waiting for a question to be resolved.

I don't see a question. Is it something we can help with? (Could you point us to it?)

@vespa7 vespa7 marked this pull request as ready for review November 20, 2025 13:50
@JakobJingleheimer JakobJingleheimer added the awaiting reviewer Author has responded and needs action from the reviewer label Nov 27, 2025
"codemod",
"migrations",
"node.js"
"node.js"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"node.js"
"node.js"

@AugustinMauroy
Copy link
Member

What the current state of this pr ?

@vespa7
Copy link
Author

vespa7 commented Nov 28, 2025

What the current state of this pr ?

The PR is ready to be reviewed.

Copy link
Member

@AugustinMauroy AugustinMauroy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not too bad, good job but there are serval part of the implementation that need to be discussed

@@ -0,0 +1,21 @@
schema_version: "1.0"
name: "@nodejs/net-setSimultaneousAccepts-migration"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
name: "@nodejs/net-setSimultaneousAccepts-migration"
name: "@nodejs/net-setSimultaneousAccepts-deprecation"

#namingIsHard @nodejs/userland-migrations what do you think

const linesToRemove: Range[] = [];

const netImportStatements = getAllNetImportStatements(root);
if (netImportStatements.length === 0) return null;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (netImportStatements.length === 0) return null;
// If no import found we don't process the file
if (!netImportStatements.length) return null;

processNetImportStatement(rootNode, statement, linesToRemove, edits);
}

if (edits.length === 0 && linesToRemove.length === 0) return null;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (edits.length === 0 && linesToRemove.length === 0) return null;
// If there aren't any change we don't try to modify something
if (!edits.length && !linesToRemove.length) return null;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe "No changes, nothing to do" for the comment

Comment on lines +45 to +47
...getNodeImportStatements(root, 'node:net'),
...getNodeImportCalls(root, 'node:net'),
...getNodeRequireCalls(root, 'node:net'),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
...getNodeImportStatements(root, 'node:net'),
...getNodeImportCalls(root, 'node:net'),
...getNodeRequireCalls(root, 'node:net'),
...getNodeImportStatements(root, 'net'),
...getNodeImportCalls(root, 'net'),
...getNodeRequireCalls(root, 'net'),

the node: isn't needed theses functions catch it

edits: Edit[]
): void {
const bindingPath = resolveBindingPath(statementNode, '$');
if (!bindingPath) return;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (!bindingPath) return;
if (!bindingPath) return;

/**
* Finds all _setSimultaneousAccepts() call expressions
*/
function findSetSimultaneousAcceptsCalls(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function isn't valuable. You can "hardcode" this query in the parent functio

const objDeclarations = rootNode.findAll({
rule: {
any: [
{ pattern: `const ${objectName} = $_` },
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why ast kind/ast query can we have something stronger ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mmm, I think there's probably a built-in way from ast-grep to get this without needing such a wide pattern.

Copy link
Member

@brunocroh brunocroh Dec 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand the scenario correctly, it can be rewritten as something like the code below.
It finds all variable declarations that use the name objectName.

const objDeclarations = rootNode.findAll({
  kind: 'variable_declarator',
  has: {
    kind: 'identifier',
    field: 'name',
    patern: objctName,
  }
})

Copy link
Author

@vespa7 vespa7 Dec 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking in something like this:

const pair = root
	.root()
	.findAll({ rule: { kind: "variable_declarator" } })
	.filter((decl) => decl.field("name")?.text() === objectName)
	.flatMap((decl) => decl.findAll({ rule: { kind: "pair" } }))
	.filter((p) => p.field("key")?.text() === keyName)
	.map((pair) => pair.field("value")?.text())[0]

@brunocroh @JakobJingleheimer @AugustinMauroy

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WTF that completely crazy

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@brunocroh yeah, that's exactly the sort of thing I was thinking :)

@vespa7 that is a bit… verbose, and I suspect, overly manual (it looks a bit like a Rube Goldberg machine as code 😄). I think there is a more concise way to do it. I would try something like Bruno suggested.

@AugustinMauroy that's maybe not the most constructive way to phrase it 😅

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops sorry

Copy link

@Ceres6 Ceres6 Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you're misunderstanding what @vespa7's comment is saying due to the thread, but the equivalent to @brunocroh's code in Alex's code is

const pair = rootNode
	.findAll({ rule: { kind: "variable_declarator" } })
	.filter((decl) => decl.field("name")?.text() === objectName)

If Brunos' code works it might be a bit better for that chunk, but the complete piece is substituting

	const objDeclarations = rootNode.findAll({
		rule: {
			any: [
				{ pattern: `const ${objectName} = $_` },
				{ pattern: `let ${objectName} = $_` },
				{ pattern: `var ${objectName} = $_` },
			],
		},
	});

	for (const objDecl of objDeclarations) {
		const objectLiterals = objDecl.findAll({ rule: { kind: 'object' } });

		for (const obj of objectLiterals) {
			const pairs = obj.findAll({ rule: { kind: 'pair' } });

			for (const pair of pairs) {
				const key = pair.child(0);
				if (key?.text() === propertyName) {
					const rangeWithComma = expandRangeToIncludeTrailingComma(
						pair.range(),
						rootNode.text()
					);
					linesToRemove.push(rangeWithComma);
				}
			}
		}
	}

And if you got that correctly I'm not sure how the new piece looks more verbose. Following on Bruno's proposal for the whole snippet, maybe something like

 const pairs = rootNode
        .findAll({
	        rule: {
		        kind: "variable_declarator",
		        has: {
			        kind: "identifier",
			        field: "name",
			        pattern: objectName,
		        },
	        },
        })
        .flatMap((decl) =>
	        decl.findAll({
		        rule: {
			        kind: "pair",
			        has: {
				        field: "key",
				        regex: keyName,
			        },
		        },
	        }),
        );

You can break it in the middle to give explanatory names to the steps

Comment on lines +154 to +171
for (const objDecl of objDeclarations) {
const objectLiterals = objDecl.findAll({ rule: { kind: 'object' } });

for (const obj of objectLiterals) {
const pairs = obj.findAll({ rule: { kind: 'pair' } });

for (const pair of pairs) {
const key = pair.child(0);
if (key?.text() === propertyName) {
const rangeWithComma = expandRangeToIncludeTrailingComma(
pair.range(),
rootNode.text()
);
linesToRemove.push(rangeWithComma);
}
}
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we have a loop that push to an array then iterate on this array to avoid 3th level of nested loop

varName: string,
linesToRemove: Range[]
): void {
const varDeclarationStatements = rootNode.findAll({
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

Copy link
Member

@JakobJingleheimer JakobJingleheimer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this! It's a good first :)

I think this could use some additional test-cases that include more things happening from node:net to ensure they don't get broken.

"codemod",
"migrations",
"node.js"
"node.js"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"node.js"
"node.js"

Comment on lines +12 to +15
const net = require("node:net");

-net._setSimultaneousAccepts(false);
const server = net.createServer();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const net = require("node:net");
-net._setSimultaneousAccepts(false);
const server = net.createServer();
const net = require("node:net");
- net._setSimultaneousAccepts(false);
const server = net.createServer();

processNetImportStatement(rootNode, statement, linesToRemove, edits);
}

if (edits.length === 0 && linesToRemove.length === 0) return null;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe "No changes, nothing to do" for the comment

Comment on lines +101 to +105
if (argKind === 'member_expression') {
handleMemberExpressionArgument(rootNode, argNode, linesToRemove);
} else if (argKind === 'identifier') {
handleIdentifierArgument(rootNode, argNode, linesToRemove);
}
Copy link
Member

@JakobJingleheimer JakobJingleheimer Dec 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: switch makes it more clear that it's inspecting the same condition for each.

Suggested change
if (argKind === 'member_expression') {
handleMemberExpressionArgument(rootNode, argNode, linesToRemove);
} else if (argKind === 'identifier') {
handleIdentifierArgument(rootNode, argNode, linesToRemove);
}
switch(argKind) {
case 'member_expression': handleMemberExpressionArgument(rootNode, argNode, linesToRemove); break;
case 'identifier': handleIdentifierArgument(rootNode, argNode, linesToRemove); break;
}

rule: { pattern: `${objectName}.${propertyName}` },
});

// Only remove if this is the only reference
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: the extra "only" is kind of cumbersome to read

Suggested change
// Only remove if this is the only reference
// Remove when this is the only reference

const objDeclarations = rootNode.findAll({
rule: {
any: [
{ pattern: `const ${objectName} = $_` },
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mmm, I think there's probably a built-in way from ast-grep to get this without needing such a wide pattern.

@JakobJingleheimer JakobJingleheimer added awaiting author Reviewer has requested something from the author and removed awaiting reviewer Author has responded and needs action from the reviewer labels Dec 1, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

awaiting author Reviewer has requested something from the author

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: handle net._setSimultaneousAccepts() deprecation

5 participants