-
-
Notifications
You must be signed in to change notification settings - Fork 33.2k
Closed
Labels
esmIssues and PRs related to the ECMAScript Modules implementation.Issues and PRs related to the ECMAScript Modules implementation.loadersIssues and PRs related to ES module loadersIssues and PRs related to ES module loaders
Description
Version
v20.3.1
Platform
Darwin Kernel Version 22.5.0: Mon Apr 24 20:52:24 PDT 2023; root:xnu-8796.121.2~5/RELEASE_ARM64_T6000 arm64
Subsystem
esm, loaders
What steps will reproduce the bug?
- Have Yarn 3+ installed
corepack enable
yarn set version berry
yarn set version 4
- Write a custom loader that uses the
load
hook- Within that hook use
await import(someFile);
- Within
someFile
import a package that requires another loader to resolve
- Within that hook use
Reproducible repo: https://github.com/izaakschroeder/loader-chain-issue
Run the following:
yarn
cd packages/demo
yarn demo
/packages/banana-loader/loader.mjs:
import * as path from 'node:path';
import module from 'node:module';
import { fileURLToPath } from 'node:url'
const DEFAULT_EXTENSIONS = ['.banana'];
const compile = async (code, filepath) => {
// We are second loader in chain so we have PnP injected yay all this works
const pnpApi = module.findPnpApi(filepath);
const packageLocator = pnpApi.findPackageLocator(filepath);
const packageInformation = pnpApi.getPackageInformation(packageLocator);
const configFile = path.join(packageInformation.packageLocation, 'banana.config.mjs');
// This fails complaining that "banana-config" cannot be resolved
// This confuses me because shouldn't PnP be active at this point? If the previous
// code works then how can this not? And specifically importing `configFile`
// itself is OK, only the import WITHIN it fails.
const configModule = await import(configFile);
if (configModule.default.magic !== 42) {
throw new Error('Bad banana');
}
return code;
}
export const load = async (url, context, nextLoad) => {
if (DEFAULT_EXTENSIONS.some((ext) => url.endsWith(ext))) {
const {source, responseURL, format} = await nextLoad(url, {...context, format: 'module'});
const code = await compile(source.toString('utf8'), fileURLToPath(responseURL));
return {
format,
source: code,
shortCircuit: true,
};
}
return nextLoad(url, context);
}
/packages/demo/banana.config.mjs:
import {createConfig} from "banana-config";
export default createConfig();
/packages/demo/test.banana:
console.log('Hello world');
/packages/banana-config/config.mjs:
export const createConfig = () => {
return {magic: 42};
};
How often does it reproduce? Is there a required condition?
No response
What is the expected behavior? Why is that the expected behavior?
Using await import(...)
should respect the existing loader chain.
What do you see instead?
Module resolution fails inside an import
'd module.
Additional information
No response
Metadata
Metadata
Assignees
Labels
esmIssues and PRs related to the ECMAScript Modules implementation.Issues and PRs related to the ECMAScript Modules implementation.loadersIssues and PRs related to ES module loadersIssues and PRs related to ES module loaders