Skip to content

Conversation

@nekojanai
Copy link
Contributor

@nekojanai nekojanai commented Jul 31, 2025

closes #130

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.

Nice! Already onto the second one 😀 Thanks for this!

#NamingIsHard I think this should be called fs-access-mode-constants (it affects more than only files).

@nekojanai nekojanai force-pushed the feat(`file-access-mode-constants`) branch from d5b73e4 to d30ad09 Compare August 4, 2025 14:49
@nekojanai nekojanai changed the title feat(file-access-mode-constants): introduce feat(fs-access-mode-constants): introduce Aug 4, 2025
@nekojanai nekojanai marked this pull request as ready for review August 4, 2025 14:50
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. test file should be something like file-x.js

Comment on lines 155 to 156
if (originalText.includes(", }") || originalText.includes(", ") || originalText.includes(" , ")) {
const newText = originalText.replace(" , ", "").replace(",,", ",").replace(", ", ", ").replace(", }", " }");
Copy link
Member

Choose a reason for hiding this comment

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

Is there a way to detect this leveraging ast-grep? (I think that would be more robust)

If not, I think you probably want a regex instead of hard strings. And also, I think you don't need to first test whether there is a match before trying to replace that match: you can feed string.replace a regex as the first arg; when there is no match, it will just do nothing (aka "fail gracefully").

Suggested change
if (originalText.includes(", }") || originalText.includes(", ") || originalText.includes(" , ")) {
const newText = originalText.replace(" , ", "").replace(",,", ",").replace(", ", ", ").replace(", }", " }");
const newText = originalText
.replace(/\s+,+\s+/, ' , ')
.replace(/\{\s*,/, '{ ')
.replace(/,\s*\}/, ' }');
if (newText !== originalText) {

You should test those regexes though (I think they're right, but I didn't confirm)

Copy link
Member

Choose a reason for hiding this comment

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

@brunocroh do we have a utility for that ?

Copy link
Member

Choose a reason for hiding this comment

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

Yes, we have an utility function utils/src/ast-grep/remove-binding.ts that can be used here

  let hasChange = false
  for (const key of ['F_OK', 'R_OK', 'W_OK', 'X_OK']) {
    const change = removeBinding(importStatement, key); //it will return a ast-grep.Edit to remove import if it exists
    if(change) {
       edits.push(change.edit)
       hasChange = true
    }
  }
  
  if(hasChange) {
    // add constants to import
  }

Copy link
Member

Choose a reason for hiding this comment

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

An easier way to handle destructured objects or named imports is

// get items inside of objectPattern
const imports = objectPattern.find({
  rule: {
    any: [
     {kind: 'import_specifier'},
     {kind: 'shorthand_property_identifier_pattern'}
    ]
  }
})
//now imported items will be in `imports` variable as a string array, that will be easier to transform, i.g
// imports.push('newImport')
// items.filter // remove import
// items.map // update import

// after transform just join the array with ", "
const newImportString = `{ ${newImports.join(", ")} }`

// Replace the entire object pattern with new object pattern
objectPattern.replace(newImportString)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

An easier way to handle destructured objects or named imports is

// get items inside of objectPattern
const imports = objectPattern.find({
  rule: {
    any: [
     {kind: 'import_specifier'},
     {kind: 'shorthand_property_identifier_pattern'}
    ]
  }
})
//now imported items will be in `imports` variable as a string array, that will be easier to transform, i.g
// imports.push('newImport')
// items.filter // remove import
// items.map // update import

// after transform just join the array with ", "
const newImportString = `{ ${newImports.join(", ")} }`

// Replace the entire object pattern with new object pattern
objectPattern.replace(newImportString)

I tried getting the import specifiers in an array via the ruleset provided above but going off of

    const objectPattern = statement.find({
      rule:
        { kind: 'object_pattern' },
    });

that didn't yield any results so I took a different approach

@nekojanai nekojanai force-pushed the feat(`file-access-mode-constants`) branch 3 times, most recently from cc2fabf to 92725a2 Compare August 7, 2025 22:01
@nekojanai
Copy link
Contributor Author

nekojanai commented Aug 7, 2025

incorporated feedback and adjusted coded accordingly
@brunocroh I choose not to use the utility function mentioned

my current approach allows me to handle every require and import statements with arrays containing the specifiers, and conditional replacements instead of removal is more streamlined imo

@brunocroh
Copy link
Member

incorporated feedback and adjusted coded accordingly @brunocroh I choose not to use the utility function mentioned

my current approach allows me to handle every require and import statements with arrays containing the specifiers, and conditional replacements instead of removal is more streamlined imo

That's fine, don't worry!

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.

LGMT with @brunocroh suggestion

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.

I think this is very close!

P.S. Sorry for my lag (been very busy).

@nekojanai nekojanai force-pushed the feat(`file-access-mode-constants`) branch 3 times, most recently from 63205d6 to 1ea440a Compare August 12, 2025 22:03
@nekojanai nekojanai force-pushed the feat(`file-access-mode-constants`) branch from 1ea440a to 33bbd6a Compare August 12, 2025 22:06
@JakobJingleheimer
Copy link
Member

JakobJingleheimer commented Aug 12, 2025

@nekojanai please stop force-pushing 🙏 Doing that makes it very difficult to review changes over time; instead of being able to see the subset of new changes, the reviewer has look at everything again because the periodic diff is broken.

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.

w00t! I think this is good to go (nits can be addressed in a follow-up if appropriate).

@@ -0,0 +1,6 @@
const fs = require('node:fs');

const mode = fs.R_OK | fs.W_OK;
Copy link
Member

@JakobJingleheimer JakobJingleheimer Aug 12, 2025

Choose a reason for hiding this comment

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

Is this deliberately using a binary OR (|) instead of a logical OR (||)?

Copy link
Member

Choose a reason for hiding this comment

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

const fs = require('node:fs');

const mode = fs.R_OK | fs.W_OK;
if (condition) {
Copy link
Member

Choose a reason for hiding this comment

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

Is condition supposed to be mode? (or vice versa)

Copy link
Member

Choose a reason for hiding this comment

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

@nekojanai could you answer about this though? (I know it doesn't especially matter, so fine to merge without the answer)

Comment on lines +41 to +44
let objPatArr = objectPattern.findAll({
rule:
{ kind: 'import_specifier' },
}).map((v) => v.text());
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 formatting makes this a bit difficult to grok

Suggested change
let objPatArr = objectPattern.findAll({
rule:
{ kind: 'import_specifier' },
}).map((v) => v.text());
let objPatArr = objectPattern.findAll({
rule: { kind: 'import_specifier' },
}).map((v) => v.text());

}
}

for (const _OK of ['F_OK', 'R_OK', 'W_OK', 'X_OK']) {
Copy link
Member

Choose a reason for hiding this comment

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

Nit: this array is declared and used multiple times. It could instead be declared as a const in the root scope and then referenced.

Copy link
Member

@brunocroh brunocroh left a comment

Choose a reason for hiding this comment

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

LGTM, Awesome work, thank you!

@nekojanai
Copy link
Contributor Author

uhhh, LGTM? @brunocroh @JakobJingleheimer @AugustinMauroy

@JakobJingleheimer
Copy link
Member

Yes, it's approved. I thought you might want to press the green button, but I can do.

@JakobJingleheimer JakobJingleheimer merged commit df518fc into nodejs:main Aug 23, 2025
12 checks passed
@nekojanai nekojanai deleted the feat(`file-access-mode-constants`) branch August 23, 2025 13:34
@JakobJingleheimer JakobJingleheimer added the dep:v24 Migration handles deprecation introduced in node v24 label Oct 18, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dep:v24 Migration handles deprecation introduced in node v24

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: handle fs.F_OK, fs.R_OK, fs.W_OK, fs.X_OK depreciation

5 participants