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

[Packager] Fix @providesModule not being ignored properly #3625

Closed
wants to merge 4 commits into from

Conversation

skevy
Copy link
Contributor

@skevy skevy commented Oct 23, 2015

There's quite a bit of code scattered around the packager regarding ignoring the @providesModule Haste pragma in any file that isn't in react-native, react-tools or parse. There is even a (passing) test case.

However, there's an edge case.

Take, for example, fbjs. It has a module inside of it called ErrorUtils. react-relay requires this file normally, in Common.JS style, by doing require('fbjs/libs/ErrorUtils'). But when react-native attempts to require ErrorUtils using the HasteModule format (in it's JavaScript initialization), it resolves the fbjs ErrorUtils module, instead of RN's ErrorUtils.

This happens, it turns out, because when a module is read (in Module._read), it's not caring about whether or not it should pay attention to @providesModule, and is just assigning the @providesModule value as the id of the module no matter what. Then when Module.getName is called, it will always use that data.id that was set, thus creating the wrong dependency tree.

This PR fixes that. :)

@facebook-github-bot
Copy link
Contributor

By analyzing the blame information on this pull request, we identified @martinbigio, @amasad and @vjeux to be potential reviewers.

@facebook-github-bot facebook-github-bot added GH Review: review-needed CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. labels Oct 23, 2015
@@ -22,6 +22,7 @@ jest
var Fastfs = require('../fastfs');
var Module = require('../Module');
var ModuleCache = require('../ModuleCache');
var Helpers = require('../DependencyGraph/Helpers');
Copy link
Contributor

Choose a reason for hiding this comment

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

We might want to rename this module to be more descriptive (not sure what though. DependencyGraphHelpers?) since it's being used outside of DependencyGraph now.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Totally agree.

@ide ide added the Packager label Oct 23, 2015
@facebook-github-bot
Copy link
Contributor

@skevy updated the pull request.

@skevy
Copy link
Contributor Author

skevy commented Nov 9, 2015

@martinbigio should I update and rebase this PR, or are you guys fixing this issue in a different way?

@vjeux
Copy link
Contributor

vjeux commented Nov 9, 2015

@skevy fyi Martin is in PTO for three weeks starting today :x Let me take it

@vjeux vjeux assigned vjeux and unassigned martinbigio Nov 9, 2015
@skevy
Copy link
Contributor Author

skevy commented Nov 9, 2015

Yay time off! I wish I could get some of that. :(

@skevy
Copy link
Contributor Author

skevy commented Nov 9, 2015

Thanks for taking over!

@vjeux
Copy link
Contributor

vjeux commented Nov 9, 2015

@facebook-github-bot import

@facebook-github-bot
Copy link
Contributor

Thanks for importing. If you are an FB employee go to https://our.intern.facebook.com/intern/opensource/github/pull_request/417058798495156/int_phab to review.

@@ -85,7 +86,7 @@ class Module {
this._reading = this._fastfs.readFile(this.path).then(content => {
const data = {};
const moduleDocBlock = docblock.parseAsObject(content);
if (moduleDocBlock.providesModule || moduleDocBlock.provides) {
if (!this._helpers.isNodeModulesDir(this.path) && (moduleDocBlock.providesModule || moduleDocBlock.provides)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: 80 columns.

if (!this._helpers.isNodeModulesDir(this.path) &&
    (moduleDocBlock.providesModule || moduleDocBlock.provides)) {

Copy link
Contributor

Choose a reason for hiding this comment

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

Personally I prefer:

if (!this._helpers.isNodeModulesDir(this.path) &&
    (moduleDocBlock.providesModule || moduleDocBlock.provides)
) {

but I don't wanna bikeshed :P

@facebook-github-bot
Copy link
Contributor

@skevy updated the pull request.

@vjeux
Copy link
Contributor

vjeux commented Nov 10, 2015

@facebook-github-bot import

@facebook-github-bot
Copy link
Contributor

Thanks for importing. If you are an FB employee go to https://our.intern.facebook.com/intern/opensource/github/pull_request/417058798495156/int_phab to review.

@vjeux
Copy link
Contributor

vjeux commented Nov 10, 2015

   Error  (FBESLINT0) ESLint reported an error.
    "fileWatcher" is not defined. (no-undef)

            2325 
            2326       var dgraph = new DependencyGraph({
            2327         roots: [root],
    >>>     2328         fileWatcher: fileWatcher,
            2329         assetExts: ['png', 'jpg'],
            2330         cache: cache,
            2331       });

   Error  (FBESLINT0) ESLint reported an error.
    "cache" is not defined. (no-undef)

            2327         roots: [root],
            2328         fileWatcher: fileWatcher,
            2329         assetExts: ['png', 'jpg'],
    >>>     2330         cache: cache,
            2331       });
            2332       return getOrderedDependenciesAsJSON(dgraph, '/root/index.js').then(function(deps) {
            2333         expect(deps)

The tests are not passing because it uses variables that are never defined :x

@vjeux
Copy link
Contributor

vjeux commented Nov 10, 2015

Could you rebase? :) I have no idea what i'm doing here :x

@skevy
Copy link
Contributor Author

skevy commented Nov 10, 2015

Sorry @vjeux, I didn't mean to push. I'm working on this now.

@skevy
Copy link
Contributor Author

skevy commented Nov 10, 2015

This issue with rebasing definitely has something to do with the work @cpojer is doing on the packager I think. I need to take a little bit of a look at what he's up to, and complete the rebase tomorrow when I'm fresh. Thanks for being johnny on the spot with this @vjeux...hopefully we can get it all fixed up and ready to ship tomorrow! :)

@cpojer
Copy link
Contributor

cpojer commented Nov 10, 2015

I'm about to pull out the resolver into a separate repo sometime this week. It would be great if you could rebase this asap and land it, so I don't run into issues with syncing this. Sorry for the trouble!

@@ -15,7 +15,7 @@ const replacePatterns = require('./replacePatterns');

class Module {

constructor(file, fastfs, moduleCache, cache) {
constructor(file, fastfs, moduleCache, cache, helpers) {
Copy link
Contributor

Choose a reason for hiding this comment

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

we should probably change this into taking a single object, and use destructuring in here.

@skevy skevy reopened this Dec 2, 2015
@skevy
Copy link
Contributor Author

skevy commented Dec 2, 2015

@martinbigio yah I'm reopening this now, because we actually determined that the test failures were a Facebook internal infra problem (related to a babel-transform that isn't open sourced), not a problem with this PR.

Wait till @vjeux tells you about this one :)

@martinbigio
Copy link
Contributor

Oh yeah, he told me how you guys fixed it. XP for the win :)

@martinbigio
Copy link
Contributor

@cpojer do any of the modified file should be modified on node-haste as well?

const moduleDocBlock = docblock.parseAsObject(content);
if (moduleDocBlock.providesModule || moduleDocBlock.provides) {
if (!this._depGraphHelpers.isNodeModulesDir(this.path) &&
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe we should add a comment explaining why checking for this is necessary. It's not immediately obvious to me

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure np.

@martinbigio
Copy link
Contributor

Looks great to me. @cpojer what do you want to do with the changes that affect node-haste? How far away are we from getting rid of the duplicated code? Maybe we should think about a strategy to avoid missing changes.

@facebook-github-bot
Copy link
Contributor

@skevy updated the pull request.

// This handles the case where a project may have a dep that has @providesModule
// docblock comments, but doesn't want it to conflict with whitelisted @providesModule
// modules, such as react-haste, fbjs-haste, or react-native or with non-dependency,
// project-specific code that is using @providesModule.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@martinbigio check out this explanation and let me know if that's good.

@facebook-github-bot
Copy link
Contributor

@skevy updated the pull request.

@skevy skevy force-pushed the providesModule-packager-fix branch from 74821ac to 7b69278 Compare December 4, 2015 00:42
@facebook-github-bot
Copy link
Contributor

@skevy updated the pull request.

@martinbigio
Copy link
Contributor

I'll chat with @cpojer to see how we can pull changes into the new resolver repo

@skevy skevy force-pushed the providesModule-packager-fix branch from 7b69278 to eab854c Compare December 24, 2015 14:43
@facebook-github-bot
Copy link
Contributor

@skevy updated the pull request.

@skevy skevy added the Size/L label Dec 24, 2015
…cyGraph

This resolves the packager not properly ignoring @providesModule when naming modules.
…ad()

Adds a comment that explains, in detail, why we should check whether the dependency is in the node_modules directory (or a whitelisted node_module) before getting it's name from @providesModule
…_modules' test case.

Rather than adding an additional test case for selectively whitelisted @providesModule, add to existing test case more robust tests that handle the previously unaccounted-for use case.
…le classes.

Renaming `_read` method in Module.js and Packager.js to `read`, as to not be a private method. This is done in order to allow for proper class inheritance, even when using Facebook's internal "babel-plugin-class-private-props" transform, which actually mangles method names starting with '_', preventing child classes from overriding the method.
@skevy skevy force-pushed the providesModule-packager-fix branch from eab854c to 1ddc0ab Compare December 24, 2015 15:10
@facebook-github-bot
Copy link
Contributor

@skevy updated the pull request.

}

invalidate() {
this._cache.invalidate(this.path);
}

_read() {
read() {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@vjeux just pointing out that I renamed this method as we discussed, as to allow for proper class inheritance and to not break due to babel-plugin-class-private-props.

cc @martinbigio

@vjeux
Copy link
Contributor

vjeux commented Dec 24, 2015

@facebook-github-bot shipit

@facebook-github-bot
Copy link
Contributor

Thanks for importing. If you are an FB employee go to https://our.intern.facebook.com/intern/opensource/github/pull_request/417058798495156/int_phab to review.

@skevy skevy closed this in 6cec263 Dec 24, 2015
@skevy
Copy link
Contributor Author

skevy commented Dec 24, 2015

Yay this finally merged! Thanks @vjeux

cpojer pushed a commit to facebook/metro that referenced this pull request Jan 26, 2017
Summary:
There's quite a bit of code scattered around the packager regarding ignoring the `providesModule` Haste pragma in any file that isn't in `react-native`, `react-tools` or `parse`. There is even a (passing) test case.

However, there's an edge case.

Take, for example, `fbjs`. It has a module inside of it called `ErrorUtils`. `react-relay` requires this file normally, in Common.JS style, by doing `require('fbjs/libs/ErrorUtils')`. But when `react-native` attempts to require `ErrorUtils` using the HasteModule format (in it's JavaScript initialization), it resolves the `fbjs` `ErrorUtils` module, instead of RN's `ErrorUtils`.

This happens, it turns out, because when a module is read (in `Module._read`), it's not caring about whether or not it should pay attention to `providesModule`, and is just assigning the `providesModule` value as the id of the module no matter what. Then when `Module.getName` is called, it will always use that `data.id` that was set, thus creating the wrong dependency tree.

This
Closes facebook/react-native#3625

Reviewed By: svcscm

Differential Revision: D2632317

Pulled By: vjeux

fb-gh-sync-id: efd8066eaf6f18fcf79698beab36cab90bf5cd6d
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants