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

module: Fix for #17130 CJS dependency shared with loader #17131

Closed
wants to merge 2 commits into from

Conversation

guybedford
Copy link
Contributor

This fixes the issue of a CJS dependency loaded by the loader then not being defined when imported.

The reason for this is that CJS modules define themselves early into the loader on execution, instead of as a result of being imported by the loader. But this defining only happens the first time they are loaded. Because we use a different loader for the loader itself, the modules weren't being redefined, which has been fixed here.

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • tests and/or benchmarks are included
  • commit message follows commit guidelines
Affected core subsystem(s)

esmodules

@mscdex mscdex added the esm Issues and PRs related to the ECMAScript Modules implementation. label Nov 19, 2017
@guybedford guybedford changed the title Fix for #1730 CJS dependency shared with loader module: Fix for #1730 CJS dependency shared with loader Nov 19, 2017
@refack refack changed the title module: Fix for #1730 CJS dependency shared with loader module: Fix for #17130 CJS dependency shared with loader Nov 19, 2017
import dep from './loader-dep.js';
import assert from 'assert';

export function resolve (specifier, base, defaultResolve) {
Copy link
Member

Choose a reason for hiding this comment

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

Nit: no space before (

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks, fixed up.

@joyeecheung
Copy link
Member

@joyeecheung joyeecheung added the author ready PRs that have at least one approval, no pending requests for changes, and a CI started. label Nov 21, 2017
@guybedford guybedford force-pushed the loader-shared-dep branch 2 times, most recently from 8acb1e2 to 6462cbe Compare November 22, 2017 09:51
@guybedford
Copy link
Contributor Author

guybedford commented Nov 22, 2017

This failed the snapshot test unfortunately... I've adjusted the fix to deal with the snapshotting edge cases.

The snapshot test case is basically there to ensure the CJS module is its module.exports value at exactly the time of execution, and not after any further module.exports reassignments, as would be given if we just used the value in the require cache normally. That is why there is this injection of the CJS module into the loader at

node/lib/module.js

Lines 538 to 552 in 9c6f6b0

if (ESMLoader) {
const url = getURLFromFilePath(filename);
const urlString = `${url}`;
if (ESMLoader.moduleMap.has(urlString) !== true) {
const ctx = createDynamicModule(['default'], url);
ctx.reflect.exports.default.set(this.exports);
ESMLoader.moduleMap.set(urlString,
new ModuleJob(ESMLoader, url, async () => ctx));
} else {
const job = ESMLoader.moduleMap.get(urlString);
if (job.reflect)
job.reflect.exports.default.set(this.exports);
}
}
};
instead of just using the require() value in the loader itself

The fix here is to specifically catch the case of any modules loaded before the loader itself was initialized, based on using the module from the require cache if it is loaded there.

@@ -2,6 +2,7 @@

const fs = require('fs');
const internalCJSModule = require('internal/module');
const CJSModule = require('module');
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've also hoisted up this require by fixing the circular reference in module.js.

const ctx = createDynamicModule(['default'], url, undefined);
ctx.reflect.exports.default.set(module.exports);
return ctx;
}
return createDynamicModule(['default'], url, (reflect) => {
debug(`Loading CJSModule ${url}`);
Copy link
Member

@jdalton jdalton Nov 23, 2017

Choose a reason for hiding this comment

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

How come reflect isn't used inside the createDynamicModule callback for 'cjs'...

reflect.exports.default.set(exports);

...like it is for others and the cached case above 👆
(I'm not familiar with how things work with the loader)

Copy link
Member

@devsnek devsnek Nov 23, 2017

Choose a reason for hiding this comment

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

using _load calls around a bunch and eventually ends up here

node/lib/module.js

Lines 577 to 581 in 317f596

} else {
const job = ESMLoader.moduleMap.get(urlString);
if (job.reflect)
job.reflect.exports.default.set(this.exports);
}

Copy link
Member

Choose a reason for hiding this comment

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

@devsnek Ah, any way that could be tidied up so that all the reflect.exports.default.set is done near each other or at least in the same file?

Copy link
Member

@devsnek devsnek Nov 23, 2017

Choose a reason for hiding this comment

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

i think this is already as tidy as it will get, but i think a comment above line 49 would go a long way towards explaining what is going on. personally i had no idea how line 49 worked until when you asked because i decided it was time to figure it out. maybe something like we don't assign using reflect here Module.prototype.load handles setting it.

@targos
Copy link
Member

targos commented Nov 23, 2017

@guybedford
Copy link
Contributor Author

Thanks @targos. Hmm, CI seems to be failing on node-test-binary-windows but not node-compile-windows. Does anyone know what the difference is between those environments?

@targos
Copy link
Member

targos commented Nov 23, 2017

node-compile-windows compiles node.exe and then node-test-binary-windows takes it to run the tests in parallel on multiple machines.

@guybedford
Copy link
Contributor Author

Ah right, so it's as simple as a Windows failure. Thanks, will get the local test going here.

@guybedford
Copy link
Contributor Author

I've added the windows fix - was pretty much as to be expected.

CI: https://ci.nodejs.org/job/node-test-pull-request/11677/

@guybedford
Copy link
Contributor Author

@jdalton the function at https://github.com/nodejs/node/blob/master/lib/internal/url.js#L1317 could possibly be updated to convert to windows slashes.

@jdalton
Copy link
Member

jdalton commented Nov 23, 2017

@guybedford

the function at https://github.com/nodejs/node/blob/master/lib/internal/url.js#L1317 could possibly be updated to convert to windows slashes.

Ya, it should totally be updated. Node has methods to handle this without the need for one-off hacks.

@guybedford
Copy link
Contributor Author

@jasnell do you think it would make sense to have internalURLModule.getPathFromURL to do / to \ conversion in Windows? The case here would benefit from the consistency, as otherwise we need to do this as a custom step in https://github.com/nodejs/node/pull/17131/files#diff-c5e21b512cde1c24955c7231ebf52254R44.

@guybedford
Copy link
Contributor Author

//cc @bmeck if you have a moment to review.

@bmeck
Copy link
Member

bmeck commented Nov 27, 2017

This looks fine to me. I need to think on things a bit, but see no blockers.

I am wondering if we should move the module map to be based upon v8::Context rather than per loader and notice that #17153 also changes timing of snapshot when this PR is introduced.

It might be more consistent overall to use a separate Module Map during loader initialization but... well that can be done separately to this.

@guybedford
Copy link
Contributor Author

Thanks @bmeck. I'll aim to merge this tomorrow then. I'm sure these edge cases will change over time, but it would be good to get the bug fix in sooner rather than later.

guybedford added a commit that referenced this pull request Nov 28, 2017
PR-URL: #17131
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Timothy Gu <timothygu99@gmail.com>
Reviewed-By: Bradley Farias <bradley.meck@gmail.com>
@guybedford
Copy link
Contributor Author

Landed in 1f5ee33.

@guybedford guybedford closed this Nov 28, 2017
@TimothyGu TimothyGu removed the author ready PRs that have at least one approval, no pending requests for changes, and a CI started. label Nov 29, 2017
MylesBorins pushed a commit that referenced this pull request Dec 12, 2017
PR-URL: #17131
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Timothy Gu <timothygu99@gmail.com>
Reviewed-By: Bradley Farias <bradley.meck@gmail.com>
MylesBorins pushed a commit that referenced this pull request Dec 12, 2017
PR-URL: #17131
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Timothy Gu <timothygu99@gmail.com>
Reviewed-By: Bradley Farias <bradley.meck@gmail.com>
MylesBorins pushed a commit that referenced this pull request Dec 12, 2017
PR-URL: #17131
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Timothy Gu <timothygu99@gmail.com>
Reviewed-By: Bradley Farias <bradley.meck@gmail.com>
@MylesBorins MylesBorins mentioned this pull request Dec 12, 2017
gibfahn pushed a commit that referenced this pull request Dec 19, 2017
PR-URL: #17131
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Timothy Gu <timothygu99@gmail.com>
Reviewed-By: Bradley Farias <bradley.meck@gmail.com>
@gibfahn gibfahn mentioned this pull request Dec 20, 2017
gibfahn pushed a commit that referenced this pull request Dec 20, 2017
PR-URL: #17131
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Timothy Gu <timothygu99@gmail.com>
Reviewed-By: Bradley Farias <bradley.meck@gmail.com>
@gibfahn gibfahn mentioned this pull request Dec 20, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
esm Issues and PRs related to the ECMAScript Modules implementation.
Projects
None yet
Development

Successfully merging this pull request may close these issues.