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

Remove resolve package #7508

Merged
merged 7 commits into from Feb 25, 2020
Merged

Conversation

fisker
Copy link
Sponsor Member

@fisker fisker commented Feb 1, 2020

I think require.resolve can do the job.

Tests from separate PR #7517

  • I’ve added tests to confirm my change works.
  • (If changing the API or CLI) I’ve documented the changes I’ve made (in the docs/ directory)
  • (If the change is user-facing) I’ve added my changes to changelog_unreleased/*/pr-XXXX.md file following changelog_unreleased/TEMPLATE.md.
  • I’ve read the contributing guidelines.

Try the playground for this PR

@fisker fisker force-pushed the resolve-to-require-resolve branch 2 times, most recently from 76dac9b to 2e121ab Compare February 1, 2020 11:52
const externalManualLoadPluginInfos = externalPluginNames.map(pluginName => ({
name: pluginName,
requirePath: eval("require").resolve(pluginName, { paths: [process.cwd()] })
}));
Copy link
Sponsor Member Author

Choose a reason for hiding this comment

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

This part might different with old one.

If pluginName = 'my-plugin' not pluginName = './my-plugin', result might different, will look for my-plugin package, insteadof ./my-plugin, but no tests cover it.

Copy link
Member

Choose a reason for hiding this comment

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

We should keep the existing behavior. I'd like to understand though what was the original motivation for using this module instead of require.resolve. Any ideas?

Copy link
Sponsor Member Author

@fisker fisker Feb 1, 2020

Choose a reason for hiding this comment

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

Copy link
Sponsor Member Author

Choose a reason for hiding this comment

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

Logic of this part has restored.

Copy link
Member

Choose a reason for hiding this comment

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

Can you please add a test for that case?

Copy link
Contributor

Choose a reason for hiding this comment

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

How important is it to support the old behavior in the new release (#6888)?

Copy link
Sponsor Member Author

Choose a reason for hiding this comment

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

This should take a while, I don't know where pluginName come from yet.

Copy link
Sponsor Member Author

Choose a reason for hiding this comment

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

Copy link
Sponsor Member Author

@fisker fisker Feb 2, 2020

Choose a reason for hiding this comment

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

I add a print

    console.log(
      JSON.stringify(
        {
          pluginName,
          "with-path.resolve": eval("require").resolve(
            path.resolve(process.cwd(), pluginName)
          ),
          "with-require.resolve(..., options)": eval("require").resolve(
            pluginName,
            {
              paths: [process.cwd()]
            }
          )
        },
        null,
        2
      )
    );

Got same result on ./automatic/node_modules/prettier-plugin-bar and automatic/node_modules/prettier-plugin-bar, not sure where .js lost this .js not lost, there is another test, but same result with .js

     {
       "pluginName": "./automatic/node_modules/prettier-plugin-bar",
       "with-path.resolve": "<repo>\\prettier\\tests_integration\\plugins\\automatic\\node_modules\\prettier-plugin-bar\\index.js",
       "with-require.resolve(..., options)": "<repo>\\prettier\\tests_integration\\plugins\\automatic\\node_modules\\prettier-plugin-bar\\index.js"
     }
    {
       "pluginName": "automatic/node_modules/prettier-plugin-bar",
       "with-path.resolve": "<repo>\\prettier\\tests_integration\\plugins\\automatic\\node_modules\\prettier-plugin-bar\\index.js",
       "with-require.resolve(..., options)": "<repo>\\prettier\\tests_integration\\plugins\\automatic\\node_modules\\prettier-plugin-bar\\index.js"
     }

But I ran on cmd, this failed as expected

<repo>\prettier\tests_integration\plugins>node
Welcome to Node.js v13.5.0.
Type ".help" for more information.
> require.resolve("automatic/node_modules/prettier-plugin-bar")
Uncaught Error: Cannot find module 'automatic/node_modules/prettier-plugin-bar'
Require stack:
- <repl>
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:966:17)
    at Function.resolve (internal/modules/cjs/helpers.js:78:19) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [ '<repl>' ]
}
> require.resolve("./automatic/node_modules/prettier-plugin-bar")
'<repo>\\prettier\\tests_integration\\plugins\\automatic\\node_modules\\prettier-plugin-bar\\index.js'

Copy link
Sponsor Member Author

Choose a reason for hiding this comment

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

@thorn0 have a look

@fisker
Copy link
Sponsor Member Author

fisker commented Feb 2, 2020

I found something interesting, I print the require.resolve.toString() on test,

"(moduleName, options) =>\n      this._requireResolve(from.filename, moduleName, options)"

But, on console

$ node -p "require.resolve.toString()"
function resolve(request, options) {
    validateString(request, 'request');
    return Module._resolveFilename(request, mod, false, options);
  }

They are different

So Jest not using the node.js require ???? Didn't find any docs about that.

@fisker
Copy link
Sponsor Member Author

fisker commented Feb 2, 2020

@fisker
Copy link
Sponsor Member Author

fisker commented Feb 2, 2020

Test that can catch this error added #7517

@SimenB
Copy link
Contributor

SimenB commented Feb 2, 2020

Jest implements require on its own to support transpilation and mocks

@brodybits
Copy link
Contributor

Jest implements require on its own to support transpilation and mocks

Is this documented somewhere?

@fisker
Copy link
Sponsor Member Author

fisker commented Feb 2, 2020

@SimenB yes, I figured, and there is a bug require.resolve('a-path/to/file') should try resolve a-path module not a-path/to/file.js file

@SimenB
Copy link
Contributor

SimenB commented Feb 2, 2020

I don't think so. require's implementation is an implementation detail, same as for bundlers

@brodybits brodybits mentioned this pull request Feb 2, 2020
4 tasks
Comment on lines +36 to 44
requirePath = eval("require").resolve(
path.resolve(process.cwd(), pluginName)
);
} catch (_) {
// try node modules
requirePath = resolve.sync(pluginName, { basedir: process.cwd() });
requirePath = eval("require").resolve(pluginName, {
paths: [process.cwd()]
});
}
Copy link
Sponsor Member Author

@fisker fisker Feb 2, 2020

Choose a reason for hiding this comment

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

I've merged #7517 into this one, to catch that error, remove this try part and run

yarn test tests_integration/__tests__/plugin-resolution.js

@fisker
Copy link
Sponsor Member Author

fisker commented Feb 2, 2020

@SimenB You can check my comment #7508 (comment) ,

If you want I can show you how to find the difference from jest require.resolve and node.js require.resolve .

@brodybits
Copy link
Contributor

If you want I can show you how to find the difference from jest require.resolve and node.js require.resolve .

I think it would be ideal if someone could do this in Q&A style on Stack Overflow. It would also help require.resolve newbies such as myself if someone can describe how this PR was able to overcome this limitation.

@SimenB
Copy link
Contributor

SimenB commented Feb 2, 2020

@SimenB You can check my comment #7508 (comment) ,

If you want I can show you how to find the difference from jest require.resolve and node.js require.resolve .

If you could open up an issue at fb/jest with a small reproduction that would be wonderful yeah

@fisker
Copy link
Sponsor Member Author

fisker commented Feb 2, 2020

@SimenB Let me try first on my machine

@fisker
Copy link
Sponsor Member Author

fisker commented Feb 2, 2020

@SimenB

checkout this repo

https://github.com/fisker/jest-require-resolve-bug

If you confirm that or something I did wrong, let me know here first, or in that repo.

@brodybits
Copy link
Contributor

https://github.com/fisker/jest-require-resolve-bug

It took me a little while to understand the difference between require.resolve on Node.js vs Jest. The difference I found is that require.resolve('foo/node_modules/bar', {paths: [process.cwd()]}) throws an error in Node.js but succeeds in Jest. Looks like a subtle bug in Jest.

I think it would also really help users in the future if someone could document what Jest does to the require statements and why. I am also wondering if Jest would do something similar to ES6 import statements.

@SimenB
Copy link
Contributor

SimenB commented Feb 2, 2020

Yeah, that's a bug. Seems like we're missing something in the implementation from jestjs/jest#6471. Something about making things relative while they're not seems off. Could you open up an issue with it?


@brodybits there should be no observable differences between Jest's require and node's implementations (by invoking the functions, not toString etc) beyond options passed to Jest that change it, like moduleNameMapper and code transforms. So nothing really to document. It'll be the same with ESM when that's implemented

@SimenB
Copy link
Contributor

SimenB commented Feb 4, 2020

Seeing as require.resolve with paths is broken in Node 10 (fixed in 12: nodejs/node#23683) I'd suggest to not land this until you also drop node 10.

EDIT: Or use createRequire{FromPath}(fromWhereIWannaLook).resolve instead. Note that while createRequire has landed on Jest master, it has not been released. I'd still suggest sticking with the resolve package, but your call 🙂

@fisker
Copy link
Sponsor Member Author

fisker commented Feb 4, 2020

@SimenB Doesn't matter anymore, new test code won't relay require.resolve to throw

@SimenB
Copy link
Contributor

SimenB commented Feb 4, 2020

I'm not talking about test code, I'm talking about loading user plugins, which is where you use the resolve package today. Using require.resolve('asdasd', {paths: []}) when you know it's broken on Node 10 seems irresponsible to me, especially if it's just about avoiding a single dependency and not some feature resolve doesn't support or resolve messing up browser builds or some such.

From the OP:

I think require.resolve can do the job.

It cannot, it's broken on node 10 for the use case you want to use it.


I'll unsubscribe since it doesn't really impact me (I don't use custom plugins), and I don't really have any interest in discussing this. Thanks for finding the inconsistency in Jest's implementation though! 😀 We'll replicate the implementation in the version of node we're running on (at least that's the current plan)

@fisker
Copy link
Sponsor Member Author

fisker commented Feb 4, 2020

Actually the node 10 behavior is more we want, when resolve plugin foo, we try <CWD>/foo first. So node 10 broken require.resolve doesn't effect us, we are not breaking anything.

We found that problem is because I tried to remove <CWD>/foo first, but didn't catch a error. So we improved the test, make sure we are not changing the logic.

@thorn0
Copy link
Member

thorn0 commented Feb 4, 2020

Might fix #7407 if require.resolve uses NODE_PATH.

@thorn0 thorn0 merged commit 129fcb6 into prettier:next Feb 25, 2020
@fisker fisker deleted the resolve-to-require-resolve branch February 25, 2020 08:40
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Feb 25, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants