angular/tools/esm-interop/esm-main-loader.mjs
Paul Gschwendtner 9cd89569f5 build: create NodeJS ESM loader for supporting Bazel setup (#48521)
Replaces the existing ESM loader for dealing with external module
imports. This loader was introduced by Aspect for AIO `.mjs` scripts.

The loader will be used as foundation for a more extensive loader
that also properly handles first-party packages.

Additionally another loader is added, all packed as a single
loader because our current NodeJS version only supports a single
loader per node invocation. So we implement chaining ourselves.

The new loader will attempt rewriting `.js` extensions to `.mjs`,
also it will add `.mjs` if not already done. This is necessary
in the transition phase because we don't/cannot use explicit `.mts`
extensions and also we don't specify extensions in imports yet.

Long-term we would likely use `.mts` and explicit import extensions,
but it's not yet clear how we would sync this into g3 too.

PR Close #48521
2022-12-19 19:50:40 +00:00

39 lines
1.3 KiB
JavaScript

/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {extname} from 'path';
import {fileURLToPath} from 'url';
import * as extensionLoader from './esm-extension-loader.mjs';
import * as nodeModuleLoader from './esm-node-module-loader.mjs';
const loaders = [extensionLoader, nodeModuleLoader];
export async function resolve(initialSpecifier, initialCtx, defaultResolve) {
let nextFn = (i) => (s, c) => {
if (i === loaders.length) {
return defaultResolve(s, c, defaultResolve);
}
return loaders[i].resolve(s, c, nextFn(i + 1));
};
return nextFn(0)(initialSpecifier, initialCtx);
}
export async function load(url, context, defaultLoad) {
// Using `--loader` causes non-ESM extension-less files like
// for `typescript/bin/tsc` to be considered as ESM. This is a bug
// via: https://github.com/nodejs/node/issues/33226.
// Workaround is to load such extension-less files as CommonJS. Similar
// to how they are loaded without `--loader` being specified.
if (url.startsWith('file://') && extname(fileURLToPath(url)) === '') {
context.format = 'commonjs';
}
return defaultLoad(url, context, defaultLoad);
}