-
Notifications
You must be signed in to change notification settings - Fork 132
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
fix: fix re-export at esm entry point #158
Conversation
/cc @weswigham |
First, on this change: This simply changes the import style and doesn't change the file we import, so isn't doing what #143 is asking for at all. I don't really understand why you'd want to do what this PR is doing - more explanation is definitely required. Second, on #143 itself: the original premise is flawed - we do not want to reexport anything other than exactly what our cjs entrypoint looks at, because we only want a single copy of each of these helpers bouncing around in a runtime (on the offchance any use state, like some template literal helpers were/are). The "newness" of the format of the source code has no bearing on it. |
@weswigham,
|
You sure it's not just a bug in the node flag? I'm pretty sure it's not supposed to change the behavior of imports. |
I do not consider myself an expert in this, so I cannot say for sure. I only found an example when cjc-to-esm import interoperability seems violated when Btw, this case illustrates exactly how Jest loads modules. CC @SimenB, you may be interested |
09939d8
to
98539de
Compare
98539de
to
94bf5bd
Compare
@orta, could you run the tests again? |
Perhaps I'm using vm api incorrectly. Unfortunately, I could not find a way to explicitly specify / inherit the current module load method for
Perhaps you're right about the flag / nodejs bug. The patch, even if it appears, cannot be applied to the past, right? The official doc says, vm.SourceTextModule was introduced in 2018 since Node.js v9.6.0, so if you intend to support |
is any chance to land this change? |
let's merge this:
|
I did some local testing and this doesn't actually work. A import fs from "node:fs"
import { dirname, resolve } from "node:path";
import { fileURLToPath } from "node:url";
import vm from 'node:vm';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const modulerefContents = `
import * as tslib from '../tslib.js';
checkTslib(tslib);
`;
const tslibjsContents = fs.readFileSync(resolve(__dirname, "node_modules/tslib/tslib.js"), {encoding: "utf8"});
const contextifiedObject = vm.createContext({
checkTslib(tslib) {
console.log(`typeof tslib: ${typeof tslib}`);
console.log(`typeof tslib.__assign: ${typeof tslib.__assign}`);
console.log(`typeof tslib.default: ${typeof tslib.default}`);
console.log(`typeof tslib.default.__assign: ${typeof tslib.default.__assign}`);
}
});
async function linker(specifier, referencingModule) {
if (specifier === '../tslib.js') {
return new vm.SourceTextModule(tslibjsContents, { context: referencingModule.context });
}
throw new Error(`Unable to resolve dependency: ${specifier}`);
}
const m = new vm.SourceTextModule(modulerefContents, { context: contextifiedObject })
await m.link(linker);
await m.evaluate(); The above example (based on your test), prints the following:
Instead, you probably need to use a import fs from "node:fs"
import { dirname, resolve } from "node:path";
import { fileURLToPath } from "node:url";
import vm from 'node:vm';
import module from 'node:module';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const modulerefContents = `
import * as tslib from '../tslib.js';
checkTslib(tslib);
`;
const tslibjsContents = fs.readFileSync(resolve(__dirname, "node_modules/tslib/tslib.js"), {encoding: "utf8"});
const contextifiedObject = vm.createContext({
checkTslib(tslib) {
console.log(`typeof tslib: ${typeof tslib}`);
console.log(`typeof tslib.__assign: ${typeof tslib.__assign}`);
console.log(`typeof tslib.default: ${typeof tslib.default}`);
console.log(`typeof tslib.default.__assign: ${typeof tslib.default.__assign}`);
}
});
async function linker(specifier, referencingModule) {
if (specifier === '../tslib.js') {
return new vm.SyntheticModule(['default'], function () {
const wrapper = vm.compileFunction(tslibjsContents, ["module"], { parsingContext: referencingModule.context });
const module = { exports: {} };
wrapper(module);
this.setExport('default', module.exports);
}, { context: referencingModule.context });
}
throw new Error(`Unable to resolve dependency: ${specifier}`);
}
const m = new vm.SourceTextModule(modulerefContents, { context: contextifiedObject })
await m.link(linker);
await m.evaluate(); Which prints:
Using |
Thanks for the explanation. It's clear, we need to refactor our module loader: we expect if some module has an ESM entry point, then all other resources of this package, that are referenced by this point, are also ESM formatted. This hypothesis is wrong, as we now know. Unfortunately, |
Leveraging
Also, I'm not entirely sure if there would be any impact for web servers that serve up a copy of |
That's reasonable, I have nothing to object to. But it still looks like we need some sort of tweak for esm entry. Here 's tslib export: "exports": {
".": {
"module": "./modules/index.js",
"import": "./tslib.es6.js",
"default": "./tslib.js"
},
"./": "./"
}
UPD nvm, seems that my issue is covered by #171 |
relates (?) #143