Skip to content

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

@mscdexmscdex added the esm Issues and PRs related to the ECMAScript Modules implementation. label Nov 19, 2017
@guybedfordguybedford changed the title Fix for #1730 CJS dependency shared with loadermodule: Fix for #1730 CJS dependency shared with loaderNov 19, 2017
@refackrefack changed the title module: Fix for #1730 CJS dependency shared with loadermodule: Fix for #17130 CJS dependency shared with loaderNov 19, 2017
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
ContributorAuthor

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

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

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){
consturl=getURLFromFilePath(filename);
consturlString=`${url}`;
if(ESMLoader.moduleMap.has(urlString)!==true){
constctx=createDynamicModule(['default'],url);
ctx.reflect.exports.default.set(this.exports);
ESMLoader.moduleMap.set(urlString,
newModuleJob(ESMLoader,url,async()=>ctx));
}else{
constjob=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.


constfs=require('fs');
constinternalCJSModule=require('internal/module');
constCJSModule=require('module');
Copy link
ContributorAuthor

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.

returnctx;
}
returncreateDynamicModule(['default'],url,(reflect)=>{
debug(`Loading CJSModule ${url}`);
Copy link
Member

@jdaltonjdaltonNov 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

@devsnekdevsnekNov 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{
constjob=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

@devsnekdevsnekNov 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

@guybedford
Copy link
ContributorAuthor

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

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
ContributorAuthor

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

@guybedford
Copy link
ContributorAuthor

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
ContributorAuthor

@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
ContributorAuthor

@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
ContributorAuthor

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

@bmeck
Copy link
Member

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
ContributorAuthor

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 <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Timothy Gu <[email protected]> Reviewed-By: Bradley Farias <[email protected]>
@guybedford
Copy link
ContributorAuthor

Landed in 1f5ee33.

@TimothyGuTimothyGu 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 <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Timothy Gu <[email protected]> Reviewed-By: Bradley Farias <[email protected]>
MylesBorins pushed a commit that referenced this pull request Dec 12, 2017
PR-URL: #17131 Reviewed-By: Michaël Zasso <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Timothy Gu <[email protected]> Reviewed-By: Bradley Farias <[email protected]>
MylesBorins pushed a commit that referenced this pull request Dec 12, 2017
PR-URL: #17131 Reviewed-By: Michaël Zasso <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Timothy Gu <[email protected]> Reviewed-By: Bradley Farias <[email protected]>
@MylesBorinsMylesBorins 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 <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Timothy Gu <[email protected]> Reviewed-By: Bradley Farias <[email protected]>
@gibfahngibfahn 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 <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Timothy Gu <[email protected]> Reviewed-By: Bradley Farias <[email protected]>
@gibfahngibfahn mentioned this pull request Dec 20, 2017
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

esmIssues and PRs related to the ECMAScript Modules implementation.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

11 participants

@guybedford@joyeecheung@targos@jdalton@bmeck@jasnell@TimothyGu@cjihrig@devsnek@mscdex@gibfahn