forked from angular/angular
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhooks.mjs
More file actions
75 lines (63 loc) 路 2.5 KB
/
Copy pathhooks.mjs
File metadata and controls
75 lines (63 loc) 路 2.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
/**
* @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.dev/license
*/
/**
* @fileoverview
*
* Module loader that augments NodeJS's execution to:
*
* - support native execution of Angular JavaScript output
* that isn't strict ESM at this point (lack of explicit extensions).
* - support path mappings at runtime. This allows us to natively execute ESM
* without having to pre-bundle for testing, or use the slow full npm linked packages
*/
import {parseTsconfig, createPathsMatcher} from 'get-tsconfig';
import path from 'node:path';
const explicitExtensionRe = /\.[mc]?js$/;
const nonModuleImportRe = /^[.\/]/;
const runfilesRoot = process.env.JS_BINARY__RUNFILES;
const tsconfigPath = path.join(runfilesRoot, '_main/packages/tsconfig-build.json');
const tsconfig = parseTsconfig(tsconfigPath);
const pathMappingMatcher = createPathsMatcher({config: tsconfig, path: tsconfigPath});
/** @type {import('module').ResolveHook} */
export const resolve = async (specifier, context, nextResolve) => {
// True when it's a non-module import without explicit extensions.
const isNonModuleExtensionlessImport =
nonModuleImportRe.test(specifier) && !explicitExtensionRe.test(specifier);
const pathMappings = !nonModuleImportRe.test(specifier) ? pathMappingMatcher(specifier) : [];
// If it's neither path mapped, nor an extension-less import that may be fixed up, exit early.
if (!isNonModuleExtensionlessImport && pathMappings.length === 0) {
return nextResolve(specifier, context);
}
if (pathMappings.length > 0) {
for (const mapping of pathMappings) {
const res = await catchError(() => resolve(mapping, context, nextResolve));
if (res !== null) {
return res;
}
}
} else {
const fixedResult =
(await catchError(() => nextResolve(`${specifier}.js`, context))) ||
(await catchError(() => nextResolve(`${specifier}/index.js`, context))) ||
// Legacy variants for the `zone.js` variant using still `ts_library`.
// TODO(rules_js migration): Remove this.
(await catchError(() => nextResolve(`${specifier}.mjs`, context))) ||
(await catchError(() => nextResolve(`${specifier}/index.mjs`, context)));
if (fixedResult !== null) {
return fixedResult;
}
}
return await nextResolve(specifier, context);
};
async function catchError(fn) {
try {
return await fn();
} catch {
return null;
}
}