Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(path): make isWindows check compatible with Node and Bun #4961

Merged
merged 18 commits into from
Aug 29, 2024

Conversation

BenMcLean981
Copy link
Contributor

@BenMcLean981 BenMcLean981 commented Jun 5, 2024

Description

As described by the linked issue the isWindows function @std/path is not cross runtime. In it's existing state it should work on Deno and the browser (though there are issues there) but not bun or node. In this PR I believe I have resolved those issues and added support for bun or node.

Tested Runtimes

I manually tested this solution in the following runtimes:

  • Deno on Fedora Linux
  • Firefox on Fedora Linux
  • Node on Fedora Linux
  • Bun on Fedora Linux
  • Deno on Windows 10
  • Firefox on Windows 10
  • Node on Windows 10
  • Bun on Windows 10

I couldn't think of an easy way to test this automatically. I could probably write a bash script to do it so that it can be added to the pipeline if necessary.

Potential Issues with Existing Browser Support

As mentioned in the discussion there may have been issues with the existing implementation for browsers. The navigator.appVersion property is deprecated, so I moved away from that and started using navigator.userAgent.

Bun and Node Support

I got Bun and Node working using Node's os module which also has an implementation in bun. The code for this is pretty ugly, as require does not exist in Deno or the browser. I could not think of a better way to do this.

Resolves #4914

All that needs to be done here is to check if
the version is windows. Handling each combination
of runtime and operating system will make
the existing osType difficult to test and maintain.
It was using a deprecated web API.
@github-actions github-actions bot added the path label Jun 5, 2024
@BenMcLean981 BenMcLean981 changed the title feat(Made isWindows Cross Runtime) feat(path): Made isWindows Cross Runtime Jun 5, 2024
@BenMcLean981 BenMcLean981 marked this pull request as ready for review June 5, 2024 02:03
@BenMcLean981 BenMcLean981 requested a review from kt3k as a code owner June 5, 2024 02:03
@iuioiua iuioiua self-requested a review June 5, 2024 03:05
path/_os.ts Outdated
})();
function getNodeOsModule(): OsModule | undefined {
if (require !== undefined) {
return require("os");
Copy link
Member

Choose a reason for hiding this comment

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

If node.js is in ESM mode (.mjs or type: module in package.json), then it doesn't have require.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, I tested by manually converting to js and then running with node os.js, explains why this worked for me then.

I'll mark this PR as Draft again until I can come up with a better solution.

Copy link
Member

Choose a reason for hiding this comment

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

Thanks.

@std is published in JSR, and it's distributed as ESM in Node.js. So I think it's enough to only support ESM context.

@BenMcLean981 BenMcLean981 marked this pull request as draft June 5, 2024 13:09
@iuioiua
Copy link
Contributor

iuioiua commented Jun 5, 2024

This change can be far more easily made using navigator.userAgent, which Node and Bun support. For Bun, you can check navigator.userAgent.includes("Bun"). Same with Node.

Copy link

codecov bot commented Jun 5, 2024

Codecov Report

Attention: Patch coverage is 57.14286% with 3 lines in your changes missing coverage. Please review.

Project coverage is 96.26%. Comparing base (745c4a6) to head (aabaca9).
Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
path/_os.ts 57.14% 3 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main    #4961   +/-   ##
=======================================
  Coverage   96.26%   96.26%           
=======================================
  Files         479      479           
  Lines       38705    38700    -5     
  Branches     5617     5619    +2     
=======================================
- Hits        37259    37256    -3     
+ Misses       1403     1401    -2     
  Partials       43       43           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@BenMcLean981
Copy link
Contributor Author

I noticed that while I was testing. But that doesn't allow us to check if the underlying os is Windows (which is the only thing this module does that's public facing).

@iuioiua
Copy link
Contributor

iuioiua commented Jun 5, 2024

On second thought, we could do the following:

  1. Determine whether the current runtime is a browser or not (Deno, Bun, or Node).
  2. If in the browser, use navigator.userAgent to check if on Windows.
  3. If not a browser, dynamically import node:os to check if on Windows. That should take care of Deno, Bun and Node.

WDYT?

@kt3k
Copy link
Member

kt3k commented Jun 6, 2024

If not a browser, dynamically import node:os to check if on Windows. That should take care of Deno, Bun and Node.

I'm not in favor of this as this introduces Top-level await and makes the module async. We saw many issues about async modules in the past..

Node.js (>=21) and Bun seem exposing navigator.platform property, which seems usable for OS detection. https://nodejs.org/api/globals.html#navigatorplatform

@BenMcLean981
Copy link
Contributor Author

I also considered this and I don't like the idea of using async/await in any way. I'm going to look and see how the node os module works under the hood and see if maybe we can't just do it the same way they do.

This is how NodeJS checks to see
if the underlying OS is windows.
@BenMcLean981
Copy link
Contributor Author

I poked around in node's os module and saw how they check to see if node is running on windows. They just use process.platform, which we of course can do here as well. I've tested it and it seems to work.

@BenMcLean981 BenMcLean981 marked this pull request as ready for review June 6, 2024 11:16
@kt3k kt3k added the after 1.0 label Jun 6, 2024
@iuioiua
Copy link
Contributor

iuioiua commented Jun 6, 2024

Ah, yes, I forgot about top-level await being problematic. I think using navigator.platform is the best method. But we need to implement it in the runtime (see denoland/deno#24117).

@BenMcLean981
Copy link
Contributor Author

@iuioiua for this PR that isn't necessary. I was able to do it with process.platform in node and bun. In the browser and Deno I have this wrapped in a try/catch. This worked on all of the runtimes I listed in the PR description.

@iuioiua iuioiua changed the title feat(path): Made isWindows Cross Runtime feat(path): make @std/path compatible with Node and Bun Aug 29, 2024
@iuioiua iuioiua requested a review from kt3k August 29, 2024 01:13
Copy link
Contributor

@iuioiua iuioiua left a comment

Choose a reason for hiding this comment

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

Sorry for the delayed review, @BenMcLean981. I've simplified your logic to just use Deno.build.os or navigator.platform, depending on the runtime. This should all be compatible with Deno, Bun, Node and the browser.

Thank you very much for your contribution! @kt3k, can you PTAL and be sure to update the compatibility of @std/path on JSR once the next release is cut?

path/_os.ts Outdated Show resolved Hide resolved
@kt3k kt3k changed the title feat(path): make @std/path compatible with Node and Bun refactor(path): make @std/path compatible with Node and Bun Aug 29, 2024
@kt3k
Copy link
Member

kt3k commented Aug 29, 2024

I changed the commit type from feat to refactor as it's not tested with Node and Bun yet.

@iuioiua
Copy link
Contributor

iuioiua commented Aug 29, 2024

I don't see how this PR, in it's current state, not yet being tested on Node or Bun makes this a refactor PR. A package being made available in two new runtimes is a feature. @BenMcLean981, is there any chance you'd be able to test this PR, in its current state, on the various platforms/runtimes once more?

@kt3k
Copy link
Member

kt3k commented Aug 29, 2024

We can't ask somebody to test on every change. We need to set up CI to ensure it's working on specific platform.

@iuioiua
Copy link
Contributor

iuioiua commented Aug 29, 2024

I can confirm this works on macOS (POSIX) for Deno, Bun, Windows and Chrome.

@kt3k
Copy link
Member

kt3k commented Aug 29, 2024

I'd suggest we would make feat(path): add support of Node commit when we set up the CI on Node.

Copy link
Member

@kt3k kt3k left a comment

Choose a reason for hiding this comment

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

LGTM

@iuioiua
Copy link
Contributor

iuioiua commented Aug 29, 2024

While I disagree with this being a refactor PR, I can at least understand the reasoning. I'd like to get confirmation that this works on Windows before merging.

@kt3k kt3k changed the title refactor(path): make @std/path compatible with Node and Bun refactor(path): make isWindows check compatible with Node and Bun Aug 29, 2024
@kt3k
Copy link
Member

kt3k commented Aug 29, 2024

I changed the title a bit as there seem somethings remaining (like the usage of Deno.cwd()) to make @std/path truly compatible with Node

@BenMcLean981
Copy link
Contributor Author

@iuioiua I ran my little set of manual tests again on my Windows machine. It doesn't work on Node. An error gets thrown that navigator is undefined, if I use a nullish check on it then it incorrectly returns false. I added in a branch to the conditional check to use process.platform for the check, all is well now.

I agree with the discussion around cross-platform and cross-runtime automated testing. I was thinking about setting that up for this repo, but I think that needs to be part of a larger discussion. I'm also not sure what tooling even exists to make that happen.

@kt3k
Copy link
Member

kt3k commented Aug 29, 2024

Ah ok. navigator.platform seems only available on Node >= 21.2 https://nodejs.org/api/globals.html#navigatorplatform

It would be better to support lower versions like 18.x, 20.x, as they are still officially supported versions.

@iuioiua
Copy link
Contributor

iuioiua commented Aug 29, 2024

I think we should support from the LTS version (now v20.17.0), upwards. So the recent change makes sense. Thanks, @BenMcLean981 for confirming and checking.

@iuioiua iuioiua merged commit c3b113d into denoland:main Aug 29, 2024
16 checks passed
@BenMcLean981
Copy link
Contributor Author

I think we should support from the LTS version (now v20.17.0), upwards. So the recent change makes sense. Thanks, @BenMcLean981 for confirming and checking.

No problem! Happy I could contribute.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

suggestion: make isWindows cross-runtime in @std/path
3 participants