-
Notifications
You must be signed in to change notification settings - Fork 142
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
Include named exports in CJS shims when using importSync
#1531
Conversation
Didn't find an integration/end-to-end test for importing cjs packages, so settled with a unit test. If I should add a test somewhere else instead let me know. |
`importSync()` is intended to work like `import()` (buy sync), which, in turns, is expected to work like a namespace import – `import * as NS from "foo";`. In general, we would expect that to be interchangable with `const NS = importSync("foo");`. Prior to this commit, this is not true for commonjs packages: ```js import * as QUnit1 from "qunit"; // => { QUnit, assert, begin, config, ... } QUnit1.assert // => function const QUnit2 = importSync("qunit"); // => { default: { QUnit, assert, begin, config, ... } } QUnit2.assert // => undefined ``` Of course, using ES imports on commonjs packages is, in itself, an ill-defined concept, but nevertheless, it is a very common interop requirement. The previous behavior is introduced in embroider-build#1076. The intent appears to be fixing a different interop issue, where we would expect these to work the same way: ```js import QUnit1 from "qunit"; // => { Qunit, assert, begin, config, ... } QUnit1.assert // => function const QUnit2 = importSync("qunit").default; // => { QUnit, assert, begin, config, ... } QUnit2.assert // => function ``` The fix in embroider-build#1076, however, broke the exepctation that `import()` should behave like a namespace improt statement for CJS modules. This commit attempts to satisfy both of these requirements, with one caveat: `importSync("foo").default` is present on the shimed CJS modules, but in `import * as FOO from "foo";`, `FOO.default` is undefined. Arguably, this is a bug in webpack's implementation – if you are able to write an import statement that references the default export, you should be able to do the same in the namespace import as per the spec. So, the implementation here is different but more correct. Fixes embroider-build#1530
Thanks. The test wasn't really doing what you wanted it to do -- that particular file is misleading and kind of silly. It was only testing build-time code and couldn't test runtime code. I moved it into a place that will do an end-to-end test. (We definitely need some better contributing docs on how to organize tests.) |
In classic builds, multiple different versions of `@embroider/macros` may get smashed together, overwriting each other's files in ways that we cannot control. If we want packages that upgrade to get this bugfix to reliably have it, they need to use a new name to refer to the module.
Making this do the right thing on classic builds is more annoying than it would seem, given that classic builds mash all the copies of all the different versions of Then that introduced test failures under embroider, due to an outstanding issue that I'm already working on. I can land this after landing that fix. |
importSync()
is intended to work likeimport()
(buy sync), which, in turns, is expected to work like a namespace import –import * as NS from "foo";
. In general, we would expect that to be interchangable withconst NS = importSync("foo");
.Prior to this commit, this is not true for commonjs packages:
Of course, using ES imports on commonjs packages is, in itself, an ill-defined concept, but nevertheless, it is a very common interop requirement.
The previous behavior is introduced in #1076. The intent appears to be fixing a different interop issue, where we would expect these to work the same way:
The fix in #1076, however, broke the exepctation that
import()
should behave like a namespace improt statement for CJS modules.This commit attempts to satisfy both of these requirements, with one caveat:
importSync("foo").default
is present on the shimed CJS modules, but inimport * as FOO from "foo";
,FOO.default
is undefined.Arguably, this is a bug in webpack's implementation – if you are able to write an import statement that references the default export, you should be able to do the same in the namespace import as per the spec.
So, the implementation here is different but more correct.