-
Notifications
You must be signed in to change notification settings - Fork 72
/
Copy pathresolver.js
75 lines (67 loc) · 3.26 KB
/
resolver.js
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
'use strict';
const { URL } = require('url');
const { tryURLLikeSpecifierParse, BUILT_IN_MODULE_SCHEME, BUILT_IN_MODULE_PROTOCOL } = require('./utils.js');
const supportedBuiltInModules = new Set([`${BUILT_IN_MODULE_SCHEME}:blank`]);
exports.resolve = (specifier, parsedImportMap, scriptURL) => {
const asURL = tryURLLikeSpecifierParse(specifier, scriptURL);
const normalizedSpecifier = asURL ? asURL.href : specifier;
const scriptURLString = scriptURL.href;
for (const [scopePrefix, scopeImports] of Object.entries(parsedImportMap.scopes)) {
if (scopePrefix === scriptURLString ||
(scopePrefix.endsWith('/') && scriptURLString.startsWith(scopePrefix))) {
const scopeImportsMatch = resolveImportsMatch(normalizedSpecifier, scopeImports);
if (scopeImportsMatch !== null) {
return scopeImportsMatch;
}
}
}
const topLevelImportsMatch = resolveImportsMatch(normalizedSpecifier, parsedImportMap.imports);
if (topLevelImportsMatch !== null) {
return topLevelImportsMatch;
}
// The specifier was able to be turned into a URL, but wasn't remapped into anything.
if (asURL) {
if (asURL.protocol === BUILT_IN_MODULE_PROTOCOL && !supportedBuiltInModules.has(asURL.href)) {
throw new TypeError(`The "${asURL.href}" built-in module is not implemented.`);
}
return asURL;
}
throw new TypeError(`Unmapped bare specifier "${specifier}"`);
};
function resolveImportsMatch(normalizedSpecifier, specifierMap) {
for (const [specifierKey, addresses] of Object.entries(specifierMap)) {
// Exact-match case
if (specifierKey === normalizedSpecifier) {
if (addresses.length === 0) {
throw new TypeError(`Specifier "${normalizedSpecifier}" was mapped to no addresses.`);
} else if (addresses.length === 1) {
const singleAddress = addresses[0];
if (singleAddress.protocol === BUILT_IN_MODULE_PROTOCOL && !supportedBuiltInModules.has(singleAddress.href)) {
throw new TypeError(`The "${singleAddress.href}" built-in module is not implemented.`);
}
return singleAddress;
} else if (addresses.length === 2 &&
addresses[0].protocol === BUILT_IN_MODULE_PROTOCOL &&
addresses[1].protocol !== BUILT_IN_MODULE_PROTOCOL) {
return supportedBuiltInModules.has(addresses[0].href) ? addresses[0] : addresses[1];
} else {
throw new Error('The reference implementation for multi-address fallbacks that are not ' +
'[built-in module, fetch-scheme URL] is not yet implemented.');
}
}
// Package prefix-match case
if (specifierKey.endsWith('/') && normalizedSpecifier.startsWith(specifierKey)) {
if (addresses.length === 0) {
throw new TypeError(`Specifier "${normalizedSpecifier}" was mapped to no addresses ` +
`(via prefix specifier key "${specifierKey}").`);
} else if (addresses.length === 1) {
const afterPrefix = normalizedSpecifier.substring(specifierKey.length);
return new URL(afterPrefix, addresses[0]);
} else {
throw new Error('The reference implementation for multi-address fallbacks that are not ' +
'[built-in module, fetch-scheme URL] is not yet implemented.');
}
}
}
return null;
}