@jsenv/core 41.0.2 → 41.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/build/build.js +1 -43
- package/dist/start_build_server/jsenv_core_packages.js +1 -114
- package/dist/start_build_server/start_build_server.js +13 -59
- package/dist/start_dev_server/jsenv_core_packages.js +2213 -2213
- package/dist/start_dev_server/start_dev_server.js +9240 -9200
- package/package.json +2 -2
- package/src/build/start_build_server.js +12 -58
- package/src/{plugins/chrome_devtools_json/jsenv_plugin_chrome_devtools_json.js → dev/dev_server_plugins/dev_server_plugin_chrome_devtools_json.js} +4 -6
- package/src/dev/dev_server_plugins/dev_server_plugin_inject_server_response_header.js +27 -0
- package/src/dev/dev_server_plugins/dev_server_plugin_omega_error_handler.js +44 -0
- package/src/dev/dev_server_plugins/dev_server_plugin_serve_source_files.js +410 -0
- package/src/dev/start_dev_server.js +88 -521
- package/src/plugins/plugins.js +0 -2
- /package/src/dev/{user_agent.js → dev_server_plugins/user_agent.js} +0 -0
|
@@ -3809,2481 +3809,2481 @@ const bufferToEtag = (buffer) => {
|
|
|
3809
3809
|
return `"${length.toString(16)}-${hashBase64StringSubset}"`;
|
|
3810
3810
|
};
|
|
3811
3811
|
|
|
3812
|
-
|
|
3813
|
-
|
|
3814
|
-
|
|
3815
|
-
return [];
|
|
3812
|
+
const assertImportMap = (value) => {
|
|
3813
|
+
if (value === null) {
|
|
3814
|
+
throw new TypeError(`an importMap must be an object, got null`);
|
|
3816
3815
|
}
|
|
3817
|
-
|
|
3818
|
-
|
|
3819
|
-
|
|
3820
|
-
|
|
3821
|
-
packageConditions.push(packageCondition);
|
|
3822
|
-
}
|
|
3823
|
-
if (arg.includes("--conditions=")) {
|
|
3824
|
-
const packageCondition = arg.slice("--conditions=".length);
|
|
3825
|
-
packageConditions.push(packageCondition);
|
|
3826
|
-
}
|
|
3816
|
+
|
|
3817
|
+
const type = typeof value;
|
|
3818
|
+
if (type !== "object") {
|
|
3819
|
+
throw new TypeError(`an importMap must be an object, received ${value}`);
|
|
3827
3820
|
}
|
|
3828
|
-
return packageConditions;
|
|
3829
|
-
};
|
|
3830
3821
|
|
|
3831
|
-
|
|
3832
|
-
|
|
3833
|
-
|
|
3834
|
-
|
|
3822
|
+
if (Array.isArray(value)) {
|
|
3823
|
+
throw new TypeError(
|
|
3824
|
+
`an importMap must be an object, received array ${value}`,
|
|
3825
|
+
);
|
|
3835
3826
|
}
|
|
3836
|
-
return new URL("./", url).href;
|
|
3837
3827
|
};
|
|
3838
3828
|
|
|
3839
|
-
|
|
3840
|
-
|
|
3841
|
-
|
|
3842
|
-
// returns "file:///C:/" instead of "file:///"
|
|
3843
|
-
const resource = url.slice("file://".length);
|
|
3844
|
-
const slashLastIndex = resource.lastIndexOf("/");
|
|
3845
|
-
if (slashLastIndex === -1) {
|
|
3846
|
-
return url;
|
|
3847
|
-
}
|
|
3848
|
-
const lastCharIndex = resource.length - 1;
|
|
3849
|
-
if (slashLastIndex === lastCharIndex) {
|
|
3850
|
-
const slashBeforeLastIndex = resource.lastIndexOf(
|
|
3851
|
-
"/",
|
|
3852
|
-
slashLastIndex - 1,
|
|
3853
|
-
);
|
|
3854
|
-
if (slashBeforeLastIndex === -1) {
|
|
3855
|
-
return url;
|
|
3856
|
-
}
|
|
3857
|
-
return `file://${resource.slice(0, slashBeforeLastIndex + 1)}`;
|
|
3858
|
-
}
|
|
3829
|
+
// duplicated from @jsenv/log to avoid the dependency
|
|
3830
|
+
const createDetailedMessage = (message, details = {}) => {
|
|
3831
|
+
let string = `${message}`;
|
|
3859
3832
|
|
|
3860
|
-
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
}
|
|
3833
|
+
Object.keys(details).forEach((key) => {
|
|
3834
|
+
const value = details[key];
|
|
3835
|
+
string += `
|
|
3836
|
+
--- ${key} ---
|
|
3837
|
+
${
|
|
3838
|
+
Array.isArray(value)
|
|
3839
|
+
? value.join(`
|
|
3840
|
+
`)
|
|
3841
|
+
: value
|
|
3842
|
+
}`;
|
|
3843
|
+
});
|
|
3864
3844
|
|
|
3865
|
-
|
|
3866
|
-
try {
|
|
3867
|
-
// eslint-disable-next-line no-new
|
|
3868
|
-
new URL(url);
|
|
3869
|
-
return true;
|
|
3870
|
-
} catch {
|
|
3871
|
-
return false;
|
|
3872
|
-
}
|
|
3845
|
+
return string;
|
|
3873
3846
|
};
|
|
3874
3847
|
|
|
3875
|
-
const
|
|
3876
|
-
|
|
3877
|
-
const pathnameBeforeLastSlash = pathname.endsWith("/")
|
|
3878
|
-
? pathname.slice(0, -1)
|
|
3879
|
-
: pathname;
|
|
3880
|
-
const slashLastIndex = pathnameBeforeLastSlash.lastIndexOf("/");
|
|
3881
|
-
const filename =
|
|
3882
|
-
slashLastIndex === -1
|
|
3883
|
-
? pathnameBeforeLastSlash
|
|
3884
|
-
: pathnameBeforeLastSlash.slice(slashLastIndex + 1);
|
|
3885
|
-
return filename;
|
|
3848
|
+
const hasScheme = (string) => {
|
|
3849
|
+
return /^[a-zA-Z]{2,}:/.test(string);
|
|
3886
3850
|
};
|
|
3887
3851
|
|
|
3888
|
-
const
|
|
3889
|
-
const
|
|
3890
|
-
|
|
3891
|
-
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
return
|
|
3852
|
+
const pathnameToParentPathname = (pathname) => {
|
|
3853
|
+
const slashLastIndex = pathname.lastIndexOf("/");
|
|
3854
|
+
if (slashLastIndex === -1) {
|
|
3855
|
+
return "/";
|
|
3856
|
+
}
|
|
3857
|
+
|
|
3858
|
+
return pathname.slice(0, slashLastIndex + 1);
|
|
3895
3859
|
};
|
|
3896
3860
|
|
|
3897
|
-
const
|
|
3898
|
-
|
|
3899
|
-
|
|
3900
|
-
|
|
3901
|
-
return null;
|
|
3902
|
-
}
|
|
3903
|
-
const packageJsonUrlObject = new URL("package.json", scopeUrl);
|
|
3904
|
-
if (existsSync(packageJsonUrlObject)) {
|
|
3905
|
-
return scopeUrl;
|
|
3906
|
-
}
|
|
3907
|
-
scopeUrl = getParentUrl(scopeUrl);
|
|
3908
|
-
}
|
|
3909
|
-
return null;
|
|
3861
|
+
const urlToScheme = (urlString) => {
|
|
3862
|
+
const colonIndex = urlString.indexOf(":");
|
|
3863
|
+
if (colonIndex === -1) return "";
|
|
3864
|
+
return urlString.slice(0, colonIndex);
|
|
3910
3865
|
};
|
|
3911
3866
|
|
|
3912
|
-
const
|
|
3913
|
-
const
|
|
3914
|
-
|
|
3915
|
-
|
|
3916
|
-
|
|
3917
|
-
} catch (e) {
|
|
3918
|
-
if (e.code === "ENOENT") {
|
|
3919
|
-
return null;
|
|
3920
|
-
}
|
|
3921
|
-
throw e;
|
|
3867
|
+
const urlToOrigin = (urlString) => {
|
|
3868
|
+
const scheme = urlToScheme(urlString);
|
|
3869
|
+
|
|
3870
|
+
if (scheme === "file") {
|
|
3871
|
+
return "file://";
|
|
3922
3872
|
}
|
|
3923
|
-
|
|
3924
|
-
|
|
3925
|
-
const
|
|
3926
|
-
|
|
3927
|
-
|
|
3928
|
-
return
|
|
3929
|
-
|
|
3930
|
-
throw new Error(`Invalid package configuration at ${packageJsonFileUrl}`);
|
|
3873
|
+
|
|
3874
|
+
if (scheme === "http" || scheme === "https") {
|
|
3875
|
+
const secondProtocolSlashIndex = scheme.length + "://".length;
|
|
3876
|
+
const pathnameSlashIndex = urlString.indexOf("/", secondProtocolSlashIndex);
|
|
3877
|
+
|
|
3878
|
+
if (pathnameSlashIndex === -1) return urlString;
|
|
3879
|
+
return urlString.slice(0, pathnameSlashIndex);
|
|
3931
3880
|
}
|
|
3932
|
-
};
|
|
3933
3881
|
|
|
3934
|
-
|
|
3882
|
+
return urlString.slice(0, scheme.length + 1);
|
|
3883
|
+
};
|
|
3935
3884
|
|
|
3936
|
-
const
|
|
3937
|
-
|
|
3938
|
-
specifier,
|
|
3939
|
-
{ parentUrl },
|
|
3940
|
-
) => {
|
|
3941
|
-
const error = new Error(
|
|
3942
|
-
`Invalid module "${specifier}" ${reason} imported from ${fileURLToPath(
|
|
3943
|
-
parentUrl,
|
|
3944
|
-
)}`,
|
|
3945
|
-
);
|
|
3946
|
-
error.code = "INVALID_MODULE_SPECIFIER";
|
|
3947
|
-
return error;
|
|
3885
|
+
const urlToPathname = (urlString) => {
|
|
3886
|
+
return ressourceToPathname(urlToRessource(urlString));
|
|
3948
3887
|
};
|
|
3949
3888
|
|
|
3950
|
-
const
|
|
3951
|
-
|
|
3952
|
-
|
|
3953
|
-
|
|
3954
|
-
)
|
|
3955
|
-
let message;
|
|
3956
|
-
if (key === ".") {
|
|
3957
|
-
message = `Invalid "exports" main target defined in ${fileURLToPath(
|
|
3958
|
-
packageDirectoryUrl,
|
|
3959
|
-
)}package.json imported from ${fileURLToPath(parentUrl)}; ${reason}`;
|
|
3960
|
-
} else {
|
|
3961
|
-
message = `Invalid "${
|
|
3962
|
-
isImport ? "imports" : "exports"
|
|
3963
|
-
}" target ${JSON.stringify(target)} defined for "${key}" in ${fileURLToPath(
|
|
3964
|
-
packageDirectoryUrl,
|
|
3965
|
-
)}package.json imported from ${fileURLToPath(parentUrl)}; ${reason}`;
|
|
3889
|
+
const urlToRessource = (urlString) => {
|
|
3890
|
+
const scheme = urlToScheme(urlString);
|
|
3891
|
+
|
|
3892
|
+
if (scheme === "file") {
|
|
3893
|
+
return urlString.slice("file://".length);
|
|
3966
3894
|
}
|
|
3967
|
-
const error = new Error(message);
|
|
3968
|
-
error.code = "INVALID_PACKAGE_TARGET";
|
|
3969
|
-
return error;
|
|
3970
|
-
};
|
|
3971
3895
|
|
|
3972
|
-
|
|
3973
|
-
|
|
3974
|
-
|
|
3975
|
-
|
|
3976
|
-
|
|
3977
|
-
if (subpath === ".") {
|
|
3978
|
-
message = `No "exports" main defined in ${fileURLToPath(
|
|
3979
|
-
packageDirectoryUrl,
|
|
3980
|
-
)}package.json imported from ${fileURLToPath(parentUrl)}`;
|
|
3981
|
-
} else {
|
|
3982
|
-
message = `Package subpath "${subpath}" is not defined by "exports" in ${fileURLToPath(
|
|
3983
|
-
packageDirectoryUrl,
|
|
3984
|
-
)}package.json imported from ${fileURLToPath(parentUrl)}`;
|
|
3896
|
+
if (scheme === "https" || scheme === "http") {
|
|
3897
|
+
// remove origin
|
|
3898
|
+
const afterProtocol = urlString.slice(scheme.length + "://".length);
|
|
3899
|
+
const pathnameSlashIndex = afterProtocol.indexOf("/", "://".length);
|
|
3900
|
+
return afterProtocol.slice(pathnameSlashIndex);
|
|
3985
3901
|
}
|
|
3986
|
-
const error = new Error(message);
|
|
3987
|
-
error.code = "PACKAGE_PATH_NOT_EXPORTED";
|
|
3988
|
-
return error;
|
|
3989
|
-
};
|
|
3990
3902
|
|
|
3991
|
-
|
|
3992
|
-
const error = new Error(
|
|
3993
|
-
`Cannot find "${specifier}" imported from ${fileURLToPath(parentUrl)}`,
|
|
3994
|
-
);
|
|
3995
|
-
error.code = "MODULE_NOT_FOUND";
|
|
3996
|
-
return error;
|
|
3903
|
+
return urlString.slice(scheme.length + 1);
|
|
3997
3904
|
};
|
|
3998
3905
|
|
|
3999
|
-
const
|
|
4000
|
-
|
|
4001
|
-
|
|
4002
|
-
|
|
4003
|
-
|
|
4004
|
-
`Package import specifier "${specifier}" is not defined in ${fileURLToPath(
|
|
4005
|
-
packageDirectoryUrl,
|
|
4006
|
-
)}package.json imported from ${fileURLToPath(parentUrl)}`,
|
|
4007
|
-
);
|
|
4008
|
-
error.code = "PACKAGE_IMPORT_NOT_DEFINED";
|
|
4009
|
-
return error;
|
|
3906
|
+
const ressourceToPathname = (ressource) => {
|
|
3907
|
+
const searchSeparatorIndex = ressource.indexOf("?");
|
|
3908
|
+
return searchSeparatorIndex === -1
|
|
3909
|
+
? ressource
|
|
3910
|
+
: ressource.slice(0, searchSeparatorIndex);
|
|
4010
3911
|
};
|
|
4011
3912
|
|
|
4012
|
-
|
|
4013
|
-
return (
|
|
4014
|
-
specifier.startsWith("node:") ||
|
|
4015
|
-
NODE_BUILTIN_MODULE_SPECIFIERS.includes(specifier)
|
|
4016
|
-
);
|
|
4017
|
-
};
|
|
3913
|
+
// could be useful: https://url.spec.whatwg.org/#url-miscellaneous
|
|
4018
3914
|
|
|
4019
|
-
const NODE_BUILTIN_MODULE_SPECIFIERS = [
|
|
4020
|
-
"assert",
|
|
4021
|
-
"assert/strict",
|
|
4022
|
-
"async_hooks",
|
|
4023
|
-
"buffer_ieee754",
|
|
4024
|
-
"buffer",
|
|
4025
|
-
"child_process",
|
|
4026
|
-
"cluster",
|
|
4027
|
-
"console",
|
|
4028
|
-
"constants",
|
|
4029
|
-
"crypto",
|
|
4030
|
-
"_debugger",
|
|
4031
|
-
"diagnostics_channel",
|
|
4032
|
-
"dgram",
|
|
4033
|
-
"dns",
|
|
4034
|
-
"domain",
|
|
4035
|
-
"events",
|
|
4036
|
-
"freelist",
|
|
4037
|
-
"fs",
|
|
4038
|
-
"fsevents",
|
|
4039
|
-
"fs/promises",
|
|
4040
|
-
"_http_agent",
|
|
4041
|
-
"_http_client",
|
|
4042
|
-
"_http_common",
|
|
4043
|
-
"_http_incoming",
|
|
4044
|
-
"_http_outgoing",
|
|
4045
|
-
"_http_server",
|
|
4046
|
-
"http",
|
|
4047
|
-
"http2",
|
|
4048
|
-
"https",
|
|
4049
|
-
"inspector",
|
|
4050
|
-
"_linklist",
|
|
4051
|
-
"module",
|
|
4052
|
-
"net",
|
|
4053
|
-
"node-inspect/lib/_inspect",
|
|
4054
|
-
"node-inspect/lib/internal/inspect_client",
|
|
4055
|
-
"node-inspect/lib/internal/inspect_repl",
|
|
4056
|
-
"os",
|
|
4057
|
-
"path",
|
|
4058
|
-
"perf_hooks",
|
|
4059
|
-
"process",
|
|
4060
|
-
"punycode",
|
|
4061
|
-
"querystring",
|
|
4062
|
-
"readline",
|
|
4063
|
-
"repl",
|
|
4064
|
-
"smalloc",
|
|
4065
|
-
"sqlite",
|
|
4066
|
-
"_stream_duplex",
|
|
4067
|
-
"_stream_transform",
|
|
4068
|
-
"_stream_wrap",
|
|
4069
|
-
"_stream_passthrough",
|
|
4070
|
-
"_stream_readable",
|
|
4071
|
-
"_stream_writable",
|
|
4072
|
-
"stream",
|
|
4073
|
-
"stream/promises",
|
|
4074
|
-
"string_decoder",
|
|
4075
|
-
"sys",
|
|
4076
|
-
"timers",
|
|
4077
|
-
"_tls_common",
|
|
4078
|
-
"_tls_legacy",
|
|
4079
|
-
"_tls_wrap",
|
|
4080
|
-
"tls",
|
|
4081
|
-
"trace_events",
|
|
4082
|
-
"tty",
|
|
4083
|
-
"url",
|
|
4084
|
-
"util",
|
|
4085
|
-
"v8/tools/arguments",
|
|
4086
|
-
"v8/tools/codemap",
|
|
4087
|
-
"v8/tools/consarray",
|
|
4088
|
-
"v8/tools/csvparser",
|
|
4089
|
-
"v8/tools/logreader",
|
|
4090
|
-
"v8/tools/profile_view",
|
|
4091
|
-
"v8/tools/splaytree",
|
|
4092
|
-
"v8",
|
|
4093
|
-
"vm",
|
|
4094
|
-
"worker_threads",
|
|
4095
|
-
"zlib",
|
|
4096
|
-
// global is special
|
|
4097
|
-
"global",
|
|
4098
|
-
];
|
|
4099
3915
|
|
|
4100
|
-
|
|
4101
|
-
|
|
4102
|
-
|
|
4103
|
-
|
|
4104
|
-
|
|
4105
|
-
|
|
4106
|
-
|
|
4107
|
-
|
|
4108
|
-
|
|
4109
|
-
* or use the real path when inside
|
|
4110
|
-
*/
|
|
3916
|
+
const resolveUrl = (specifier, baseUrl) => {
|
|
3917
|
+
if (baseUrl) {
|
|
3918
|
+
if (typeof baseUrl !== "string") {
|
|
3919
|
+
throw new TypeError(writeBaseUrlMustBeAString({ baseUrl, specifier }));
|
|
3920
|
+
}
|
|
3921
|
+
if (!hasScheme(baseUrl)) {
|
|
3922
|
+
throw new Error(writeBaseUrlMustBeAbsolute({ baseUrl, specifier }));
|
|
3923
|
+
}
|
|
3924
|
+
}
|
|
4111
3925
|
|
|
4112
|
-
|
|
4113
|
-
|
|
4114
|
-
|
|
4115
|
-
|
|
4116
|
-
|
|
4117
|
-
|
|
4118
|
-
|
|
4119
|
-
|
|
4120
|
-
|
|
4121
|
-
|
|
4122
|
-
|
|
4123
|
-
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
|
|
4132
|
-
|
|
4133
|
-
|
|
4134
|
-
|
|
4135
|
-
|
|
4136
|
-
|
|
3926
|
+
if (hasScheme(specifier)) {
|
|
3927
|
+
return specifier;
|
|
3928
|
+
}
|
|
3929
|
+
|
|
3930
|
+
if (!baseUrl) {
|
|
3931
|
+
throw new Error(writeBaseUrlRequired({ baseUrl, specifier }));
|
|
3932
|
+
}
|
|
3933
|
+
|
|
3934
|
+
// scheme relative
|
|
3935
|
+
if (specifier.slice(0, 2) === "//") {
|
|
3936
|
+
return `${urlToScheme(baseUrl)}:${specifier}`;
|
|
3937
|
+
}
|
|
3938
|
+
|
|
3939
|
+
// origin relative
|
|
3940
|
+
if (specifier[0] === "/") {
|
|
3941
|
+
return `${urlToOrigin(baseUrl)}${specifier}`;
|
|
3942
|
+
}
|
|
3943
|
+
|
|
3944
|
+
const baseOrigin = urlToOrigin(baseUrl);
|
|
3945
|
+
const basePathname = urlToPathname(baseUrl);
|
|
3946
|
+
|
|
3947
|
+
if (specifier === ".") {
|
|
3948
|
+
const baseDirectoryPathname = pathnameToParentPathname(basePathname);
|
|
3949
|
+
return `${baseOrigin}${baseDirectoryPathname}`;
|
|
3950
|
+
}
|
|
3951
|
+
|
|
3952
|
+
// pathname relative inside
|
|
3953
|
+
if (specifier.slice(0, 2) === "./") {
|
|
3954
|
+
const baseDirectoryPathname = pathnameToParentPathname(basePathname);
|
|
3955
|
+
return `${baseOrigin}${baseDirectoryPathname}${specifier.slice(2)}`;
|
|
3956
|
+
}
|
|
3957
|
+
|
|
3958
|
+
// pathname relative outside
|
|
3959
|
+
if (specifier.slice(0, 3) === "../") {
|
|
3960
|
+
let unresolvedPathname = specifier;
|
|
3961
|
+
const importerFolders = basePathname.split("/");
|
|
3962
|
+
importerFolders.pop();
|
|
3963
|
+
|
|
3964
|
+
while (unresolvedPathname.slice(0, 3) === "../") {
|
|
3965
|
+
unresolvedPathname = unresolvedPathname.slice(3);
|
|
3966
|
+
// when there is no folder left to resolved
|
|
3967
|
+
// we just ignore '../'
|
|
3968
|
+
if (importerFolders.length) {
|
|
3969
|
+
importerFolders.pop();
|
|
3970
|
+
}
|
|
4137
3971
|
}
|
|
4138
|
-
|
|
3972
|
+
|
|
3973
|
+
const resolvedPathname = `${importerFolders.join(
|
|
3974
|
+
"/",
|
|
3975
|
+
)}/${unresolvedPathname}`;
|
|
3976
|
+
return `${baseOrigin}${resolvedPathname}`;
|
|
4139
3977
|
}
|
|
4140
|
-
|
|
3978
|
+
|
|
3979
|
+
// bare
|
|
3980
|
+
if (basePathname === "") {
|
|
3981
|
+
return `${baseOrigin}/${specifier}`;
|
|
3982
|
+
}
|
|
3983
|
+
if (basePathname[basePathname.length] === "/") {
|
|
3984
|
+
return `${baseOrigin}${basePathname}${specifier}`;
|
|
3985
|
+
}
|
|
3986
|
+
return `${baseOrigin}${pathnameToParentPathname(basePathname)}${specifier}`;
|
|
4141
3987
|
};
|
|
4142
3988
|
|
|
4143
|
-
const
|
|
4144
|
-
|
|
3989
|
+
const writeBaseUrlMustBeAString = ({
|
|
3990
|
+
baseUrl,
|
|
3991
|
+
specifier,
|
|
3992
|
+
}) => `baseUrl must be a string.
|
|
3993
|
+
--- base url ---
|
|
3994
|
+
${baseUrl}
|
|
3995
|
+
--- specifier ---
|
|
3996
|
+
${specifier}`;
|
|
3997
|
+
|
|
3998
|
+
const writeBaseUrlMustBeAbsolute = ({
|
|
3999
|
+
baseUrl,
|
|
4000
|
+
specifier,
|
|
4001
|
+
}) => `baseUrl must be absolute.
|
|
4002
|
+
--- base url ---
|
|
4003
|
+
${baseUrl}
|
|
4004
|
+
--- specifier ---
|
|
4005
|
+
${specifier}`;
|
|
4006
|
+
|
|
4007
|
+
const writeBaseUrlRequired = ({
|
|
4008
|
+
baseUrl,
|
|
4009
|
+
specifier,
|
|
4010
|
+
}) => `baseUrl required to resolve relative specifier.
|
|
4011
|
+
--- base url ---
|
|
4012
|
+
${baseUrl}
|
|
4013
|
+
--- specifier ---
|
|
4014
|
+
${specifier}`;
|
|
4015
|
+
|
|
4016
|
+
const tryUrlResolution = (string, url) => {
|
|
4017
|
+
const result = resolveUrl(string, url);
|
|
4018
|
+
return hasScheme(result) ? result : null;
|
|
4145
4019
|
};
|
|
4146
4020
|
|
|
4147
|
-
const
|
|
4148
|
-
const { parentUrl } = resolutionContext;
|
|
4149
|
-
// relative specifier
|
|
4021
|
+
const resolveSpecifier = (specifier, importer) => {
|
|
4150
4022
|
if (
|
|
4023
|
+
specifier === "." ||
|
|
4151
4024
|
specifier[0] === "/" ||
|
|
4152
4025
|
specifier.startsWith("./") ||
|
|
4153
4026
|
specifier.startsWith("../")
|
|
4154
4027
|
) {
|
|
4155
|
-
|
|
4156
|
-
const browserFieldResolution = applyBrowserFieldResolution(
|
|
4157
|
-
specifier,
|
|
4158
|
-
resolutionContext,
|
|
4159
|
-
);
|
|
4160
|
-
if (browserFieldResolution) {
|
|
4161
|
-
return browserFieldResolution;
|
|
4162
|
-
}
|
|
4163
|
-
}
|
|
4164
|
-
return createResolutionResult({
|
|
4165
|
-
type: "relative_specifier",
|
|
4166
|
-
url: new URL(specifier, parentUrl).href,
|
|
4167
|
-
});
|
|
4028
|
+
return resolveUrl(specifier, importer);
|
|
4168
4029
|
}
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
try {
|
|
4173
|
-
const urlObject = new URL(specifier);
|
|
4174
|
-
if (specifier.startsWith("node:")) {
|
|
4175
|
-
return createResolutionResult({
|
|
4176
|
-
type: "node_builtin_specifier",
|
|
4177
|
-
url: specifier,
|
|
4178
|
-
});
|
|
4179
|
-
}
|
|
4180
|
-
return createResolutionResult({
|
|
4181
|
-
type: "absolute_specifier",
|
|
4182
|
-
url: urlObject.href,
|
|
4183
|
-
});
|
|
4184
|
-
} catch {
|
|
4185
|
-
// bare specifier
|
|
4186
|
-
const browserFieldResolution = applyBrowserFieldResolution(
|
|
4187
|
-
specifier,
|
|
4188
|
-
resolutionContext,
|
|
4189
|
-
);
|
|
4190
|
-
if (browserFieldResolution) {
|
|
4191
|
-
return browserFieldResolution;
|
|
4192
|
-
}
|
|
4193
|
-
const packageResolution = applyPackageResolve(specifier, resolutionContext);
|
|
4194
|
-
const search = new URL(specifier, "file:///").search;
|
|
4195
|
-
if (search && !new URL(packageResolution.url).search) {
|
|
4196
|
-
packageResolution.url = `${packageResolution.url}${search}`;
|
|
4197
|
-
}
|
|
4198
|
-
return packageResolution;
|
|
4030
|
+
|
|
4031
|
+
if (hasScheme(specifier)) {
|
|
4032
|
+
return specifier;
|
|
4199
4033
|
}
|
|
4034
|
+
|
|
4035
|
+
return null;
|
|
4200
4036
|
};
|
|
4201
4037
|
|
|
4202
|
-
const
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
return
|
|
4208
|
-
|
|
4209
|
-
|
|
4210
|
-
|
|
4211
|
-
|
|
4212
|
-
|
|
4213
|
-
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
4038
|
+
const applyImportMap = ({
|
|
4039
|
+
importMap,
|
|
4040
|
+
specifier,
|
|
4041
|
+
importer,
|
|
4042
|
+
createBareSpecifierError = ({ specifier, importer }) => {
|
|
4043
|
+
return new Error(
|
|
4044
|
+
createDetailedMessage(`Unmapped bare specifier.`, {
|
|
4045
|
+
specifier,
|
|
4046
|
+
importer,
|
|
4047
|
+
}),
|
|
4048
|
+
);
|
|
4049
|
+
},
|
|
4050
|
+
onImportMapping = () => {},
|
|
4051
|
+
}) => {
|
|
4052
|
+
assertImportMap(importMap);
|
|
4053
|
+
if (typeof specifier !== "string") {
|
|
4054
|
+
throw new TypeError(
|
|
4055
|
+
createDetailedMessage("specifier must be a string.", {
|
|
4056
|
+
specifier,
|
|
4057
|
+
importer,
|
|
4058
|
+
}),
|
|
4059
|
+
);
|
|
4220
4060
|
}
|
|
4221
|
-
if (
|
|
4222
|
-
|
|
4061
|
+
if (importer) {
|
|
4062
|
+
if (typeof importer !== "string") {
|
|
4063
|
+
throw new TypeError(
|
|
4064
|
+
createDetailedMessage("importer must be a string.", {
|
|
4065
|
+
importer,
|
|
4066
|
+
specifier,
|
|
4067
|
+
}),
|
|
4068
|
+
);
|
|
4069
|
+
}
|
|
4070
|
+
if (!hasScheme(importer)) {
|
|
4071
|
+
throw new Error(
|
|
4072
|
+
createDetailedMessage(`importer must be an absolute url.`, {
|
|
4073
|
+
importer,
|
|
4074
|
+
specifier,
|
|
4075
|
+
}),
|
|
4076
|
+
);
|
|
4077
|
+
}
|
|
4223
4078
|
}
|
|
4224
|
-
|
|
4225
|
-
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
|
|
4233
|
-
|
|
4079
|
+
|
|
4080
|
+
const specifierUrl = resolveSpecifier(specifier, importer);
|
|
4081
|
+
const specifierNormalized = specifierUrl || specifier;
|
|
4082
|
+
|
|
4083
|
+
const { scopes } = importMap;
|
|
4084
|
+
if (scopes && importer) {
|
|
4085
|
+
const scopeSpecifierMatching = Object.keys(scopes).find(
|
|
4086
|
+
(scopeSpecifier) => {
|
|
4087
|
+
return (
|
|
4088
|
+
scopeSpecifier === importer ||
|
|
4089
|
+
specifierIsPrefixOf(scopeSpecifier, importer)
|
|
4090
|
+
);
|
|
4091
|
+
},
|
|
4092
|
+
);
|
|
4093
|
+
if (scopeSpecifierMatching) {
|
|
4094
|
+
const scopeMappings = scopes[scopeSpecifierMatching];
|
|
4095
|
+
const mappingFromScopes = applyMappings(
|
|
4096
|
+
scopeMappings,
|
|
4097
|
+
specifierNormalized,
|
|
4098
|
+
scopeSpecifierMatching,
|
|
4099
|
+
onImportMapping,
|
|
4100
|
+
);
|
|
4101
|
+
if (mappingFromScopes !== null) {
|
|
4102
|
+
return mappingFromScopes;
|
|
4103
|
+
}
|
|
4234
4104
|
}
|
|
4235
|
-
}
|
|
4236
|
-
|
|
4237
|
-
|
|
4238
|
-
|
|
4239
|
-
|
|
4240
|
-
|
|
4105
|
+
}
|
|
4106
|
+
|
|
4107
|
+
const { imports } = importMap;
|
|
4108
|
+
if (imports) {
|
|
4109
|
+
const mappingFromImports = applyMappings(
|
|
4110
|
+
imports,
|
|
4111
|
+
specifierNormalized,
|
|
4112
|
+
undefined,
|
|
4113
|
+
onImportMapping,
|
|
4114
|
+
);
|
|
4115
|
+
if (mappingFromImports !== null) {
|
|
4116
|
+
return mappingFromImports;
|
|
4241
4117
|
}
|
|
4242
4118
|
}
|
|
4243
|
-
|
|
4244
|
-
|
|
4245
|
-
|
|
4246
|
-
isMain: true,
|
|
4247
|
-
packageDirectoryUrl,
|
|
4248
|
-
packageJson,
|
|
4249
|
-
url,
|
|
4250
|
-
});
|
|
4119
|
+
|
|
4120
|
+
if (specifierUrl) {
|
|
4121
|
+
return specifierUrl;
|
|
4251
4122
|
}
|
|
4252
|
-
|
|
4123
|
+
|
|
4124
|
+
throw createBareSpecifierError({ specifier, importer });
|
|
4253
4125
|
};
|
|
4254
4126
|
|
|
4255
|
-
const
|
|
4256
|
-
|
|
4257
|
-
|
|
4127
|
+
const applyMappings = (
|
|
4128
|
+
mappings,
|
|
4129
|
+
specifierNormalized,
|
|
4130
|
+
scope,
|
|
4131
|
+
onImportMapping,
|
|
4258
4132
|
) => {
|
|
4259
|
-
const
|
|
4260
|
-
|
|
4261
|
-
|
|
4262
|
-
|
|
4263
|
-
|
|
4264
|
-
|
|
4265
|
-
)
|
|
4266
|
-
|
|
4267
|
-
|
|
4268
|
-
|
|
4269
|
-
|
|
4270
|
-
|
|
4271
|
-
|
|
4272
|
-
|
|
4273
|
-
...resolutionContext,
|
|
4274
|
-
packageDirectoryUrl,
|
|
4275
|
-
packageJson,
|
|
4276
|
-
isImport: true,
|
|
4133
|
+
const specifierCandidates = Object.keys(mappings);
|
|
4134
|
+
|
|
4135
|
+
let i = 0;
|
|
4136
|
+
while (i < specifierCandidates.length) {
|
|
4137
|
+
const specifierCandidate = specifierCandidates[i];
|
|
4138
|
+
i++;
|
|
4139
|
+
if (specifierCandidate === specifierNormalized) {
|
|
4140
|
+
const address = mappings[specifierCandidate];
|
|
4141
|
+
onImportMapping({
|
|
4142
|
+
scope,
|
|
4143
|
+
from: specifierCandidate,
|
|
4144
|
+
to: address,
|
|
4145
|
+
before: specifierNormalized,
|
|
4146
|
+
after: address,
|
|
4277
4147
|
});
|
|
4278
|
-
|
|
4279
|
-
|
|
4280
|
-
|
|
4148
|
+
return address;
|
|
4149
|
+
}
|
|
4150
|
+
if (specifierIsPrefixOf(specifierCandidate, specifierNormalized)) {
|
|
4151
|
+
const address = mappings[specifierCandidate];
|
|
4152
|
+
const afterSpecifier = specifierNormalized.slice(
|
|
4153
|
+
specifierCandidate.length,
|
|
4154
|
+
);
|
|
4155
|
+
const addressFinal = tryUrlResolution(afterSpecifier, address);
|
|
4156
|
+
onImportMapping({
|
|
4157
|
+
scope,
|
|
4158
|
+
from: specifierCandidate,
|
|
4159
|
+
to: address,
|
|
4160
|
+
before: specifierNormalized,
|
|
4161
|
+
after: addressFinal,
|
|
4162
|
+
});
|
|
4163
|
+
return addressFinal;
|
|
4281
4164
|
}
|
|
4282
4165
|
}
|
|
4283
|
-
|
|
4284
|
-
|
|
4285
|
-
packageDirectoryUrl,
|
|
4286
|
-
});
|
|
4166
|
+
|
|
4167
|
+
return null;
|
|
4287
4168
|
};
|
|
4288
4169
|
|
|
4289
|
-
const
|
|
4290
|
-
|
|
4291
|
-
|
|
4292
|
-
|
|
4293
|
-
|
|
4170
|
+
const specifierIsPrefixOf = (specifierHref, href) => {
|
|
4171
|
+
return (
|
|
4172
|
+
specifierHref[specifierHref.length - 1] === "/" &&
|
|
4173
|
+
href.startsWith(specifierHref)
|
|
4174
|
+
);
|
|
4175
|
+
};
|
|
4176
|
+
|
|
4177
|
+
// https://github.com/systemjs/systemjs/blob/89391f92dfeac33919b0223bbf834a1f4eea5750/src/common.js#L136
|
|
4178
|
+
|
|
4179
|
+
const composeTwoImportMaps = (leftImportMap, rightImportMap) => {
|
|
4180
|
+
assertImportMap(leftImportMap);
|
|
4181
|
+
assertImportMap(rightImportMap);
|
|
4182
|
+
|
|
4183
|
+
const importMap = {};
|
|
4184
|
+
|
|
4185
|
+
const leftImports = leftImportMap.imports;
|
|
4186
|
+
const rightImports = rightImportMap.imports;
|
|
4187
|
+
const leftHasImports = Boolean(leftImports);
|
|
4188
|
+
const rightHasImports = Boolean(rightImports);
|
|
4189
|
+
if (leftHasImports && rightHasImports) {
|
|
4190
|
+
importMap.imports = composeTwoMappings(leftImports, rightImports);
|
|
4191
|
+
} else if (leftHasImports) {
|
|
4192
|
+
importMap.imports = { ...leftImports };
|
|
4193
|
+
} else if (rightHasImports) {
|
|
4194
|
+
importMap.imports = { ...rightImports };
|
|
4294
4195
|
}
|
|
4295
|
-
|
|
4296
|
-
|
|
4297
|
-
|
|
4298
|
-
)
|
|
4299
|
-
|
|
4300
|
-
|
|
4301
|
-
|
|
4302
|
-
|
|
4196
|
+
|
|
4197
|
+
const leftScopes = leftImportMap.scopes;
|
|
4198
|
+
const rightScopes = rightImportMap.scopes;
|
|
4199
|
+
const leftHasScopes = Boolean(leftScopes);
|
|
4200
|
+
const rightHasScopes = Boolean(rightScopes);
|
|
4201
|
+
if (leftHasScopes && rightHasScopes) {
|
|
4202
|
+
importMap.scopes = composeTwoScopes(
|
|
4203
|
+
leftScopes,
|
|
4204
|
+
rightScopes,
|
|
4205
|
+
importMap.imports || {},
|
|
4206
|
+
);
|
|
4207
|
+
} else if (leftHasScopes) {
|
|
4208
|
+
importMap.scopes = { ...leftScopes };
|
|
4209
|
+
} else if (rightHasScopes) {
|
|
4210
|
+
importMap.scopes = { ...rightScopes };
|
|
4303
4211
|
}
|
|
4304
|
-
|
|
4305
|
-
|
|
4306
|
-
packageName[0] === "." ||
|
|
4307
|
-
packageName.includes("\\") ||
|
|
4308
|
-
packageName.includes("%")
|
|
4309
|
-
) {
|
|
4310
|
-
throw createInvalidModuleSpecifierError(
|
|
4311
|
-
`is not a valid package name`,
|
|
4312
|
-
packageName,
|
|
4313
|
-
resolutionContext,
|
|
4314
|
-
);
|
|
4315
|
-
}
|
|
4316
|
-
if (isImport && packageSubpath.endsWith("/")) {
|
|
4317
|
-
throw new Error("invalid module specifier");
|
|
4318
|
-
}
|
|
4319
|
-
const questionCharIndex = packageName.indexOf("?");
|
|
4320
|
-
if (questionCharIndex > -1) {
|
|
4321
|
-
packageName = packageName.slice(0, questionCharIndex);
|
|
4322
|
-
}
|
|
4323
|
-
const selfResolution = applyPackageSelfResolution(packageSubpath, {
|
|
4324
|
-
...resolutionContext,
|
|
4325
|
-
packageName,
|
|
4326
|
-
});
|
|
4327
|
-
if (selfResolution) {
|
|
4328
|
-
return selfResolution;
|
|
4329
|
-
}
|
|
4330
|
-
let currentUrl = parentUrl;
|
|
4331
|
-
while (currentUrl !== "file:///") {
|
|
4332
|
-
const packageDirectoryFacadeUrl = new URL(
|
|
4333
|
-
`node_modules/${packageName}/`,
|
|
4334
|
-
currentUrl,
|
|
4335
|
-
).href;
|
|
4336
|
-
if (!existsSync(new URL(packageDirectoryFacadeUrl))) {
|
|
4337
|
-
currentUrl = getParentUrl(currentUrl);
|
|
4338
|
-
continue;
|
|
4339
|
-
}
|
|
4340
|
-
const packageDirectoryUrl = preservesSymlink
|
|
4341
|
-
? packageDirectoryFacadeUrl
|
|
4342
|
-
: resolvePackageSymlink(packageDirectoryFacadeUrl);
|
|
4343
|
-
const packageJson = readPackageJson(packageDirectoryUrl);
|
|
4344
|
-
if (packageJson !== null) {
|
|
4345
|
-
const { exports: exports$1 } = packageJson;
|
|
4346
|
-
if (exports$1 !== null && exports$1 !== undefined) {
|
|
4347
|
-
return applyPackageExportsResolution(packageSubpath, {
|
|
4348
|
-
...resolutionContext,
|
|
4349
|
-
packageDirectoryUrl,
|
|
4350
|
-
packageJson,
|
|
4351
|
-
exports: exports$1,
|
|
4352
|
-
});
|
|
4353
|
-
}
|
|
4354
|
-
}
|
|
4355
|
-
return applyLegacySubpathResolution(packageSubpath, {
|
|
4356
|
-
...resolutionContext,
|
|
4357
|
-
packageDirectoryUrl,
|
|
4358
|
-
packageJson,
|
|
4359
|
-
});
|
|
4360
|
-
}
|
|
4361
|
-
throw createModuleNotFoundError(packageName, resolutionContext);
|
|
4212
|
+
|
|
4213
|
+
return importMap;
|
|
4362
4214
|
};
|
|
4363
4215
|
|
|
4364
|
-
const
|
|
4365
|
-
const
|
|
4366
|
-
|
|
4367
|
-
|
|
4368
|
-
|
|
4369
|
-
|
|
4370
|
-
|
|
4371
|
-
const packageJson = readPackageJson(packageDirectoryUrl);
|
|
4372
|
-
if (!packageJson) {
|
|
4373
|
-
return undefined;
|
|
4374
|
-
}
|
|
4375
|
-
if (packageJson.name !== packageName) {
|
|
4376
|
-
return undefined;
|
|
4377
|
-
}
|
|
4378
|
-
const { exports: exports$1 } = packageJson;
|
|
4379
|
-
if (!exports$1) {
|
|
4380
|
-
const subpathResolution = applyLegacySubpathResolution(packageSubpath, {
|
|
4381
|
-
...resolutionContext,
|
|
4382
|
-
packageDirectoryUrl,
|
|
4383
|
-
packageJson,
|
|
4384
|
-
});
|
|
4385
|
-
if (subpathResolution && subpathResolution.type !== "subpath") {
|
|
4386
|
-
return subpathResolution;
|
|
4216
|
+
const composeTwoMappings = (leftMappings, rightMappings) => {
|
|
4217
|
+
const mappings = {};
|
|
4218
|
+
|
|
4219
|
+
Object.keys(leftMappings).forEach((leftSpecifier) => {
|
|
4220
|
+
if (objectHasKey(rightMappings, leftSpecifier)) {
|
|
4221
|
+
// will be overidden
|
|
4222
|
+
return;
|
|
4387
4223
|
}
|
|
4388
|
-
|
|
4389
|
-
|
|
4390
|
-
|
|
4391
|
-
|
|
4392
|
-
|
|
4393
|
-
|
|
4224
|
+
const leftAddress = leftMappings[leftSpecifier];
|
|
4225
|
+
const rightSpecifier = Object.keys(rightMappings).find((rightSpecifier) => {
|
|
4226
|
+
return compareAddressAndSpecifier(leftAddress, rightSpecifier);
|
|
4227
|
+
});
|
|
4228
|
+
mappings[leftSpecifier] = rightSpecifier
|
|
4229
|
+
? rightMappings[rightSpecifier]
|
|
4230
|
+
: leftAddress;
|
|
4231
|
+
});
|
|
4232
|
+
|
|
4233
|
+
Object.keys(rightMappings).forEach((rightSpecifier) => {
|
|
4234
|
+
mappings[rightSpecifier] = rightMappings[rightSpecifier];
|
|
4394
4235
|
});
|
|
4236
|
+
|
|
4237
|
+
return mappings;
|
|
4395
4238
|
};
|
|
4396
4239
|
|
|
4397
|
-
|
|
4398
|
-
|
|
4399
|
-
|
|
4400
|
-
|
|
4401
|
-
|
|
4402
|
-
|
|
4403
|
-
|
|
4404
|
-
|
|
4405
|
-
|
|
4240
|
+
const objectHasKey = (object, key) =>
|
|
4241
|
+
Object.prototype.hasOwnProperty.call(object, key);
|
|
4242
|
+
|
|
4243
|
+
const compareAddressAndSpecifier = (address, specifier) => {
|
|
4244
|
+
const addressUrl = resolveUrl(address, "file:///");
|
|
4245
|
+
const specifierUrl = resolveUrl(specifier, "file:///");
|
|
4246
|
+
return addressUrl === specifierUrl;
|
|
4247
|
+
};
|
|
4248
|
+
|
|
4249
|
+
const composeTwoScopes = (leftScopes, rightScopes, imports) => {
|
|
4250
|
+
const scopes = {};
|
|
4251
|
+
|
|
4252
|
+
Object.keys(leftScopes).forEach((leftScopeKey) => {
|
|
4253
|
+
if (objectHasKey(rightScopes, leftScopeKey)) {
|
|
4254
|
+
// will be merged
|
|
4255
|
+
scopes[leftScopeKey] = leftScopes[leftScopeKey];
|
|
4256
|
+
return;
|
|
4406
4257
|
}
|
|
4407
|
-
const
|
|
4408
|
-
|
|
4409
|
-
|
|
4410
|
-
|
|
4411
|
-
|
|
4412
|
-
|
|
4258
|
+
const topLevelSpecifier = Object.keys(imports).find(
|
|
4259
|
+
(topLevelSpecifierCandidate) => {
|
|
4260
|
+
return compareAddressAndSpecifier(
|
|
4261
|
+
leftScopeKey,
|
|
4262
|
+
topLevelSpecifierCandidate,
|
|
4263
|
+
);
|
|
4264
|
+
},
|
|
4265
|
+
);
|
|
4266
|
+
if (topLevelSpecifier) {
|
|
4267
|
+
scopes[imports[topLevelSpecifier]] = leftScopes[leftScopeKey];
|
|
4268
|
+
} else {
|
|
4269
|
+
scopes[leftScopeKey] = leftScopes[leftScopeKey];
|
|
4413
4270
|
}
|
|
4414
|
-
|
|
4415
|
-
|
|
4416
|
-
|
|
4417
|
-
|
|
4418
|
-
|
|
4419
|
-
|
|
4420
|
-
|
|
4421
|
-
|
|
4422
|
-
|
|
4423
|
-
|
|
4424
|
-
|
|
4425
|
-
|
|
4426
|
-
return resolved;
|
|
4271
|
+
});
|
|
4272
|
+
|
|
4273
|
+
Object.keys(rightScopes).forEach((rightScopeKey) => {
|
|
4274
|
+
if (objectHasKey(scopes, rightScopeKey)) {
|
|
4275
|
+
scopes[rightScopeKey] = composeTwoMappings(
|
|
4276
|
+
scopes[rightScopeKey],
|
|
4277
|
+
rightScopes[rightScopeKey],
|
|
4278
|
+
);
|
|
4279
|
+
} else {
|
|
4280
|
+
scopes[rightScopeKey] = {
|
|
4281
|
+
...rightScopes[rightScopeKey],
|
|
4282
|
+
};
|
|
4427
4283
|
}
|
|
4428
|
-
}
|
|
4429
|
-
|
|
4284
|
+
});
|
|
4285
|
+
|
|
4286
|
+
return scopes;
|
|
4430
4287
|
};
|
|
4431
4288
|
|
|
4432
|
-
const
|
|
4433
|
-
const
|
|
4434
|
-
const matchObject = isImport ? packageJson.imports : packageJson.exports;
|
|
4289
|
+
const sortImports = (imports) => {
|
|
4290
|
+
const mappingsSorted = {};
|
|
4435
4291
|
|
|
4436
|
-
|
|
4437
|
-
|
|
4438
|
-
|
|
4439
|
-
|
|
4440
|
-
key: matchKey,
|
|
4441
|
-
isImport,
|
|
4292
|
+
Object.keys(imports)
|
|
4293
|
+
.sort(compareLengthOrLocaleCompare)
|
|
4294
|
+
.forEach((name) => {
|
|
4295
|
+
mappingsSorted[name] = imports[name];
|
|
4442
4296
|
});
|
|
4443
|
-
|
|
4444
|
-
|
|
4445
|
-
|
|
4446
|
-
|
|
4447
|
-
|
|
4448
|
-
|
|
4449
|
-
|
|
4450
|
-
|
|
4451
|
-
|
|
4452
|
-
|
|
4453
|
-
|
|
4454
|
-
}
|
|
4455
|
-
const target = matchObject[expansionKey];
|
|
4456
|
-
const subpath = matchKey.slice(
|
|
4457
|
-
patternBase.length,
|
|
4458
|
-
matchKey.length - patternTrailer.length,
|
|
4459
|
-
);
|
|
4460
|
-
return applyPackageTargetResolution(target, {
|
|
4461
|
-
...resolutionContext,
|
|
4462
|
-
key: matchKey,
|
|
4463
|
-
subpath,
|
|
4464
|
-
pattern: true,
|
|
4465
|
-
isImport,
|
|
4297
|
+
|
|
4298
|
+
return mappingsSorted;
|
|
4299
|
+
};
|
|
4300
|
+
|
|
4301
|
+
const sortScopes = (scopes) => {
|
|
4302
|
+
const scopesSorted = {};
|
|
4303
|
+
|
|
4304
|
+
Object.keys(scopes)
|
|
4305
|
+
.sort(compareLengthOrLocaleCompare)
|
|
4306
|
+
.forEach((scopeSpecifier) => {
|
|
4307
|
+
scopesSorted[scopeSpecifier] = sortImports(scopes[scopeSpecifier]);
|
|
4466
4308
|
});
|
|
4467
|
-
|
|
4468
|
-
return
|
|
4309
|
+
|
|
4310
|
+
return scopesSorted;
|
|
4469
4311
|
};
|
|
4470
4312
|
|
|
4471
|
-
const
|
|
4472
|
-
|
|
4473
|
-
|
|
4474
|
-
packageDirectoryUrl,
|
|
4475
|
-
packageJson,
|
|
4476
|
-
key,
|
|
4477
|
-
subpath = "",
|
|
4478
|
-
pattern = false,
|
|
4479
|
-
isImport = false,
|
|
4480
|
-
} = resolutionContext;
|
|
4313
|
+
const compareLengthOrLocaleCompare = (a, b) => {
|
|
4314
|
+
return b.length - a.length || a.localeCompare(b);
|
|
4315
|
+
};
|
|
4481
4316
|
|
|
4482
|
-
|
|
4483
|
-
|
|
4484
|
-
throw new Error("invalid module specifier");
|
|
4485
|
-
}
|
|
4486
|
-
if (target.startsWith("./")) {
|
|
4487
|
-
const targetUrl = new URL(target, packageDirectoryUrl).href;
|
|
4488
|
-
if (!targetUrl.startsWith(packageDirectoryUrl)) {
|
|
4489
|
-
throw createInvalidPackageTargetError(
|
|
4490
|
-
`target must be inside package`,
|
|
4491
|
-
target,
|
|
4492
|
-
resolutionContext,
|
|
4493
|
-
);
|
|
4494
|
-
}
|
|
4495
|
-
return createResolutionResult({
|
|
4496
|
-
type: isImport ? "field:imports" : "field:exports",
|
|
4497
|
-
isMain: subpath === "" || subpath === ".",
|
|
4498
|
-
packageDirectoryUrl,
|
|
4499
|
-
packageJson,
|
|
4500
|
-
url: pattern
|
|
4501
|
-
? targetUrl.replaceAll("*", subpath)
|
|
4502
|
-
: new URL(subpath, targetUrl).href,
|
|
4503
|
-
});
|
|
4504
|
-
}
|
|
4505
|
-
if (!isImport || target.startsWith("../") || isValidUrl(target)) {
|
|
4506
|
-
throw createInvalidPackageTargetError(
|
|
4507
|
-
`target must starst with "./"`,
|
|
4508
|
-
target,
|
|
4509
|
-
resolutionContext,
|
|
4510
|
-
);
|
|
4511
|
-
}
|
|
4512
|
-
return applyPackageResolve(
|
|
4513
|
-
pattern ? target.replaceAll("*", subpath) : `${target}${subpath}`,
|
|
4514
|
-
{
|
|
4515
|
-
...resolutionContext,
|
|
4516
|
-
parentUrl: packageDirectoryUrl,
|
|
4517
|
-
},
|
|
4518
|
-
);
|
|
4519
|
-
}
|
|
4520
|
-
if (Array.isArray(target)) {
|
|
4521
|
-
if (target.length === 0) {
|
|
4522
|
-
return null;
|
|
4523
|
-
}
|
|
4524
|
-
let lastResult;
|
|
4525
|
-
let i = 0;
|
|
4526
|
-
while (i < target.length) {
|
|
4527
|
-
const targetValue = target[i];
|
|
4528
|
-
i++;
|
|
4529
|
-
try {
|
|
4530
|
-
const resolved = applyPackageTargetResolution(targetValue, {
|
|
4531
|
-
...resolutionContext,
|
|
4532
|
-
key: `${key}[${i}]`,
|
|
4533
|
-
subpath,
|
|
4534
|
-
pattern,
|
|
4535
|
-
isImport,
|
|
4536
|
-
});
|
|
4537
|
-
if (resolved) {
|
|
4538
|
-
return resolved;
|
|
4539
|
-
}
|
|
4540
|
-
lastResult = resolved;
|
|
4541
|
-
} catch (e) {
|
|
4542
|
-
if (e.code === "INVALID_PACKAGE_TARGET") {
|
|
4543
|
-
continue;
|
|
4544
|
-
}
|
|
4545
|
-
lastResult = e;
|
|
4546
|
-
}
|
|
4547
|
-
}
|
|
4548
|
-
if (lastResult) {
|
|
4549
|
-
throw lastResult;
|
|
4550
|
-
}
|
|
4551
|
-
return null;
|
|
4552
|
-
}
|
|
4553
|
-
if (target === null) {
|
|
4554
|
-
return null;
|
|
4555
|
-
}
|
|
4556
|
-
if (typeof target === "object") {
|
|
4557
|
-
const keys = Object.keys(target);
|
|
4558
|
-
for (const key of keys) {
|
|
4559
|
-
if (Number.isInteger(key)) {
|
|
4560
|
-
throw new Error("Invalid package configuration");
|
|
4561
|
-
}
|
|
4562
|
-
let matched;
|
|
4563
|
-
if (key === "default") {
|
|
4564
|
-
matched = true;
|
|
4565
|
-
} else {
|
|
4566
|
-
for (const conditionCandidate of conditions) {
|
|
4567
|
-
if (conditionCandidate === key) {
|
|
4568
|
-
matched = true;
|
|
4569
|
-
break;
|
|
4570
|
-
}
|
|
4571
|
-
if (conditionCandidate.includes("*")) {
|
|
4572
|
-
const conditionCandidateRegex = new RegExp(
|
|
4573
|
-
`^${conditionCandidate.replace(/\*/g, "(.*)")}$`,
|
|
4574
|
-
);
|
|
4575
|
-
if (conditionCandidateRegex.test(key)) {
|
|
4576
|
-
matched = true;
|
|
4577
|
-
break;
|
|
4578
|
-
}
|
|
4579
|
-
}
|
|
4580
|
-
}
|
|
4581
|
-
}
|
|
4582
|
-
if (matched) {
|
|
4583
|
-
const targetValue = target[key];
|
|
4584
|
-
const resolved = applyPackageTargetResolution(targetValue, {
|
|
4585
|
-
...resolutionContext,
|
|
4586
|
-
key,
|
|
4587
|
-
subpath,
|
|
4588
|
-
pattern,
|
|
4589
|
-
isImport,
|
|
4590
|
-
});
|
|
4591
|
-
if (resolved) {
|
|
4592
|
-
return resolved;
|
|
4593
|
-
}
|
|
4594
|
-
}
|
|
4595
|
-
}
|
|
4596
|
-
return null;
|
|
4597
|
-
}
|
|
4598
|
-
throw createInvalidPackageTargetError(
|
|
4599
|
-
`target must be a string, array, object or null`,
|
|
4600
|
-
target,
|
|
4601
|
-
resolutionContext,
|
|
4602
|
-
);
|
|
4603
|
-
};
|
|
4317
|
+
const normalizeImportMap = (importMap, baseUrl) => {
|
|
4318
|
+
assertImportMap(importMap);
|
|
4604
4319
|
|
|
4605
|
-
|
|
4606
|
-
|
|
4607
|
-
if (Array.isArray(packageExports)) {
|
|
4608
|
-
return {
|
|
4609
|
-
type: "array",
|
|
4610
|
-
};
|
|
4611
|
-
}
|
|
4612
|
-
if (packageExports === null) {
|
|
4613
|
-
return {};
|
|
4614
|
-
}
|
|
4615
|
-
if (typeof packageExports === "object") {
|
|
4616
|
-
const keys = Object.keys(packageExports);
|
|
4617
|
-
const relativeKeys = [];
|
|
4618
|
-
const conditionalKeys = [];
|
|
4619
|
-
keys.forEach((availableKey) => {
|
|
4620
|
-
if (availableKey.startsWith(".")) {
|
|
4621
|
-
relativeKeys.push(availableKey);
|
|
4622
|
-
} else {
|
|
4623
|
-
conditionalKeys.push(availableKey);
|
|
4624
|
-
}
|
|
4625
|
-
});
|
|
4626
|
-
const hasRelativeKey = relativeKeys.length > 0;
|
|
4627
|
-
if (hasRelativeKey && conditionalKeys.length > 0) {
|
|
4628
|
-
throw new Error(
|
|
4629
|
-
`Invalid package configuration: cannot mix relative and conditional keys in package.exports
|
|
4630
|
-
--- unexpected keys ---
|
|
4631
|
-
${conditionalKeys.map((key) => `"${key}"`).join("\n")}
|
|
4632
|
-
--- package directory url ---
|
|
4633
|
-
${packageDirectoryUrl}`,
|
|
4634
|
-
);
|
|
4635
|
-
}
|
|
4636
|
-
return {
|
|
4637
|
-
type: "object",
|
|
4638
|
-
hasRelativeKey,
|
|
4639
|
-
allKeysAreRelative: relativeKeys.length === keys.length,
|
|
4640
|
-
};
|
|
4641
|
-
}
|
|
4642
|
-
if (typeof packageExports === "string") {
|
|
4643
|
-
return { type: "string" };
|
|
4320
|
+
if (!isStringOrUrl(baseUrl)) {
|
|
4321
|
+
throw new TypeError(formulateBaseUrlMustBeStringOrUrl({ baseUrl }));
|
|
4644
4322
|
}
|
|
4645
|
-
return {};
|
|
4646
|
-
};
|
|
4647
4323
|
|
|
4648
|
-
const
|
|
4649
|
-
|
|
4650
|
-
const firstSlashIndex = packageSpecifier.indexOf("/");
|
|
4651
|
-
if (firstSlashIndex === -1) {
|
|
4652
|
-
throw new Error("invalid module specifier");
|
|
4653
|
-
}
|
|
4654
|
-
const secondSlashIndex = packageSpecifier.indexOf("/", firstSlashIndex + 1);
|
|
4655
|
-
if (secondSlashIndex === -1) {
|
|
4656
|
-
return {
|
|
4657
|
-
packageName: packageSpecifier,
|
|
4658
|
-
packageSubpath: ".",
|
|
4659
|
-
isScoped: true,
|
|
4660
|
-
};
|
|
4661
|
-
}
|
|
4662
|
-
const packageName = packageSpecifier.slice(0, secondSlashIndex);
|
|
4663
|
-
const afterSecondSlash = packageSpecifier.slice(secondSlashIndex + 1);
|
|
4664
|
-
const packageSubpath = `./${afterSecondSlash}`;
|
|
4665
|
-
return {
|
|
4666
|
-
packageName,
|
|
4667
|
-
packageSubpath,
|
|
4668
|
-
isScoped: true,
|
|
4669
|
-
};
|
|
4670
|
-
}
|
|
4671
|
-
const firstSlashIndex = packageSpecifier.indexOf("/");
|
|
4672
|
-
if (firstSlashIndex === -1) {
|
|
4673
|
-
return {
|
|
4674
|
-
packageName: packageSpecifier,
|
|
4675
|
-
packageSubpath: ".",
|
|
4676
|
-
};
|
|
4677
|
-
}
|
|
4678
|
-
const packageName = packageSpecifier.slice(0, firstSlashIndex);
|
|
4679
|
-
const afterFirstSlash = packageSpecifier.slice(firstSlashIndex + 1);
|
|
4680
|
-
if (afterFirstSlash === "") {
|
|
4681
|
-
return {
|
|
4682
|
-
packageName,
|
|
4683
|
-
packageSubpath: "/",
|
|
4684
|
-
};
|
|
4685
|
-
}
|
|
4686
|
-
const packageSubpath = `./${afterFirstSlash}`;
|
|
4324
|
+
const { imports, scopes } = importMap;
|
|
4325
|
+
|
|
4687
4326
|
return {
|
|
4688
|
-
|
|
4689
|
-
|
|
4327
|
+
imports: imports ? normalizeMappings(imports, baseUrl) : undefined,
|
|
4328
|
+
scopes: scopes ? normalizeScopes(scopes, baseUrl) : undefined,
|
|
4690
4329
|
};
|
|
4691
4330
|
};
|
|
4692
4331
|
|
|
4693
|
-
const
|
|
4694
|
-
|
|
4695
|
-
|
|
4696
|
-
if (
|
|
4697
|
-
packageExportsInfo.type === "array" ||
|
|
4698
|
-
packageExportsInfo.type === "string"
|
|
4699
|
-
) {
|
|
4700
|
-
return packageJson.exports;
|
|
4332
|
+
const isStringOrUrl = (value) => {
|
|
4333
|
+
if (typeof value === "string") {
|
|
4334
|
+
return true;
|
|
4701
4335
|
}
|
|
4702
|
-
|
|
4703
|
-
|
|
4704
|
-
|
|
4705
|
-
}
|
|
4706
|
-
return packageJson.exports;
|
|
4336
|
+
|
|
4337
|
+
if (typeof URL === "function" && value instanceof URL) {
|
|
4338
|
+
return true;
|
|
4707
4339
|
}
|
|
4708
|
-
|
|
4340
|
+
|
|
4341
|
+
return false;
|
|
4709
4342
|
};
|
|
4710
4343
|
|
|
4711
|
-
const
|
|
4712
|
-
const
|
|
4344
|
+
const normalizeMappings = (mappings, baseUrl) => {
|
|
4345
|
+
const mappingsNormalized = {};
|
|
4713
4346
|
|
|
4714
|
-
|
|
4715
|
-
|
|
4716
|
-
}
|
|
4717
|
-
const browserFieldResolution = applyBrowserFieldResolution(
|
|
4718
|
-
packageSubpath,
|
|
4719
|
-
resolutionContext,
|
|
4720
|
-
);
|
|
4721
|
-
if (browserFieldResolution) {
|
|
4722
|
-
return browserFieldResolution;
|
|
4723
|
-
}
|
|
4724
|
-
return createResolutionResult({
|
|
4725
|
-
type: "subpath",
|
|
4726
|
-
isMain: packageSubpath === ".",
|
|
4727
|
-
packageDirectoryUrl,
|
|
4728
|
-
packageJson,
|
|
4729
|
-
url: new URL(packageSubpath, packageDirectoryUrl).href,
|
|
4730
|
-
});
|
|
4731
|
-
};
|
|
4347
|
+
Object.keys(mappings).forEach((specifier) => {
|
|
4348
|
+
const address = mappings[specifier];
|
|
4732
4349
|
|
|
4733
|
-
|
|
4734
|
-
|
|
4735
|
-
|
|
4736
|
-
|
|
4737
|
-
|
|
4738
|
-
|
|
4739
|
-
|
|
4740
|
-
|
|
4741
|
-
if (resolved) {
|
|
4742
|
-
return createResolutionResult({
|
|
4743
|
-
type: resolved.type,
|
|
4744
|
-
isMain: resolved.isMain,
|
|
4745
|
-
packageDirectoryUrl,
|
|
4746
|
-
packageJson,
|
|
4747
|
-
url: new URL(resolved.path, packageDirectoryUrl).href,
|
|
4748
|
-
});
|
|
4749
|
-
}
|
|
4750
|
-
}
|
|
4751
|
-
return createResolutionResult({
|
|
4752
|
-
type: "field:main", // the absence of "main" field
|
|
4753
|
-
isMain: true,
|
|
4754
|
-
packageDirectoryUrl,
|
|
4755
|
-
packageJson,
|
|
4756
|
-
url: new URL("index.js", packageDirectoryUrl).href,
|
|
4757
|
-
});
|
|
4758
|
-
};
|
|
4759
|
-
const mainLegacyResolvers = {
|
|
4760
|
-
import: ({ packageJson }) => {
|
|
4761
|
-
if (typeof packageJson.module === "string") {
|
|
4762
|
-
return { type: "field:module", isMain: true, path: packageJson.module };
|
|
4763
|
-
}
|
|
4764
|
-
if (typeof packageJson.jsnext === "string") {
|
|
4765
|
-
return { type: "field:jsnext", isMain: true, path: packageJson.jsnext };
|
|
4766
|
-
}
|
|
4767
|
-
if (typeof packageJson.main === "string") {
|
|
4768
|
-
return { type: "field:main", isMain: true, path: packageJson.main };
|
|
4350
|
+
if (typeof address !== "string") {
|
|
4351
|
+
console.warn(
|
|
4352
|
+
formulateAddressMustBeAString({
|
|
4353
|
+
address,
|
|
4354
|
+
specifier,
|
|
4355
|
+
}),
|
|
4356
|
+
);
|
|
4357
|
+
return;
|
|
4769
4358
|
}
|
|
4770
|
-
return null;
|
|
4771
|
-
},
|
|
4772
|
-
browser: ({ packageDirectoryUrl, packageJson }) => {
|
|
4773
|
-
const browserMain = (() => {
|
|
4774
|
-
if (typeof packageJson.browser === "string") {
|
|
4775
|
-
return packageJson.browser;
|
|
4776
|
-
}
|
|
4777
|
-
if (
|
|
4778
|
-
typeof packageJson.browser === "object" &&
|
|
4779
|
-
packageJson.browser !== null
|
|
4780
|
-
) {
|
|
4781
|
-
return packageJson.browser["."];
|
|
4782
|
-
}
|
|
4783
|
-
return "";
|
|
4784
|
-
})();
|
|
4785
4359
|
|
|
4786
|
-
|
|
4787
|
-
|
|
4788
|
-
|
|
4789
|
-
|
|
4790
|
-
|
|
4791
|
-
|
|
4792
|
-
|
|
4793
|
-
|
|
4794
|
-
|
|
4795
|
-
|
|
4796
|
-
|
|
4797
|
-
|
|
4798
|
-
packageJson.module === browserMain
|
|
4799
|
-
) {
|
|
4800
|
-
return {
|
|
4801
|
-
type: "field:browser",
|
|
4802
|
-
isMain: true,
|
|
4803
|
-
path: browserMain,
|
|
4804
|
-
};
|
|
4805
|
-
}
|
|
4806
|
-
const browserMainUrlObject = new URL(browserMain, packageDirectoryUrl);
|
|
4807
|
-
const content = readFileSync(browserMainUrlObject, "utf-8");
|
|
4808
|
-
if (
|
|
4809
|
-
(/typeof exports\s*==/.test(content) &&
|
|
4810
|
-
/typeof module\s*==/.test(content)) ||
|
|
4811
|
-
/module\.exports\s*=/.test(content)
|
|
4812
|
-
) {
|
|
4813
|
-
return {
|
|
4814
|
-
type: "field:module",
|
|
4815
|
-
isMain: true,
|
|
4816
|
-
path: packageJson.module,
|
|
4817
|
-
};
|
|
4818
|
-
}
|
|
4819
|
-
return {
|
|
4820
|
-
type: "field:browser",
|
|
4821
|
-
isMain: true,
|
|
4822
|
-
path: browserMain,
|
|
4823
|
-
};
|
|
4824
|
-
},
|
|
4825
|
-
node: ({ packageJson, conditions }) => {
|
|
4826
|
-
if (conditions.includes("import") && !conditions.includes("require")) {
|
|
4827
|
-
if (typeof packageJson.module === "string") {
|
|
4828
|
-
return { type: "field:module", isMain: true, path: packageJson.module };
|
|
4829
|
-
}
|
|
4830
|
-
if (typeof packageJson.jsnext === "string") {
|
|
4831
|
-
return { type: "field:jsnext", isMain: true, path: packageJson.jsnext };
|
|
4832
|
-
}
|
|
4833
|
-
}
|
|
4834
|
-
if (typeof packageJson.main === "string") {
|
|
4835
|
-
return { type: "field:main", isMain: true, path: packageJson.main };
|
|
4360
|
+
const specifierResolved = resolveSpecifier(specifier, baseUrl) || specifier;
|
|
4361
|
+
|
|
4362
|
+
const addressUrl = tryUrlResolution(address, baseUrl);
|
|
4363
|
+
if (addressUrl === null) {
|
|
4364
|
+
console.warn(
|
|
4365
|
+
formulateAdressResolutionFailed({
|
|
4366
|
+
address,
|
|
4367
|
+
baseUrl,
|
|
4368
|
+
specifier,
|
|
4369
|
+
}),
|
|
4370
|
+
);
|
|
4371
|
+
return;
|
|
4836
4372
|
}
|
|
4837
|
-
return null;
|
|
4838
|
-
},
|
|
4839
|
-
};
|
|
4840
|
-
mainLegacyResolvers.require = mainLegacyResolvers.node;
|
|
4841
4373
|
|
|
4842
|
-
|
|
4843
|
-
|
|
4844
|
-
|
|
4845
|
-
|
|
4846
|
-
|
|
4847
|
-
|
|
4848
|
-
|
|
4849
|
-
|
|
4850
|
-
|
|
4851
|
-
|
|
4852
|
-
|
|
4853
|
-
if (baseLengthA > baseLengthB) {
|
|
4854
|
-
return -1;
|
|
4855
|
-
}
|
|
4856
|
-
if (baseLengthB > baseLengthA) {
|
|
4857
|
-
return 1;
|
|
4858
|
-
}
|
|
4859
|
-
if (aStarIndex === -1) {
|
|
4860
|
-
return 1;
|
|
4861
|
-
}
|
|
4862
|
-
if (bStarIndex === -1) {
|
|
4863
|
-
return -1;
|
|
4864
|
-
}
|
|
4865
|
-
if (keyA.length > keyB.length) {
|
|
4866
|
-
return -1;
|
|
4867
|
-
}
|
|
4868
|
-
if (keyB.length > keyA.length) {
|
|
4869
|
-
return 1;
|
|
4870
|
-
}
|
|
4871
|
-
return 0;
|
|
4872
|
-
};
|
|
4374
|
+
if (specifier.endsWith("/") && !addressUrl.endsWith("/")) {
|
|
4375
|
+
console.warn(
|
|
4376
|
+
formulateAddressUrlRequiresTrailingSlash({
|
|
4377
|
+
address,
|
|
4378
|
+
specifier,
|
|
4379
|
+
}),
|
|
4380
|
+
);
|
|
4381
|
+
return;
|
|
4382
|
+
}
|
|
4383
|
+
mappingsNormalized[specifierResolved] = addressUrl;
|
|
4384
|
+
});
|
|
4873
4385
|
|
|
4874
|
-
|
|
4875
|
-
const packageDirectoryPath = realpathSync(new URL(packageDirectoryUrl));
|
|
4876
|
-
const packageDirectoryResolvedUrl = pathToFileURL(packageDirectoryPath).href;
|
|
4877
|
-
return `${packageDirectoryResolvedUrl}/`;
|
|
4386
|
+
return sortImports(mappingsNormalized);
|
|
4878
4387
|
};
|
|
4879
4388
|
|
|
4880
|
-
const
|
|
4881
|
-
|
|
4882
|
-
{ fileStat, magicDirectoryIndex, magicExtensions },
|
|
4883
|
-
) => {
|
|
4884
|
-
const result = {
|
|
4885
|
-
stat: null,
|
|
4886
|
-
url: fileUrl,
|
|
4887
|
-
magicExtension: "",
|
|
4888
|
-
magicDirectoryIndex: false,
|
|
4889
|
-
lastENOENTError: null,
|
|
4890
|
-
};
|
|
4891
|
-
|
|
4892
|
-
if (fileStat === undefined) {
|
|
4893
|
-
try {
|
|
4894
|
-
fileStat = readEntryStatSync(new URL(fileUrl));
|
|
4895
|
-
} catch (e) {
|
|
4896
|
-
if (e.code === "ENOENT") {
|
|
4897
|
-
result.lastENOENTError = e;
|
|
4898
|
-
fileStat = null;
|
|
4899
|
-
} else {
|
|
4900
|
-
throw e;
|
|
4901
|
-
}
|
|
4902
|
-
}
|
|
4903
|
-
}
|
|
4389
|
+
const normalizeScopes = (scopes, baseUrl) => {
|
|
4390
|
+
const scopesNormalized = {};
|
|
4904
4391
|
|
|
4905
|
-
|
|
4906
|
-
|
|
4907
|
-
|
|
4908
|
-
|
|
4909
|
-
|
|
4910
|
-
|
|
4911
|
-
|
|
4912
|
-
|
|
4913
|
-
|
|
4914
|
-
|
|
4915
|
-
|
|
4916
|
-
magicExtensions,
|
|
4917
|
-
});
|
|
4918
|
-
return {
|
|
4919
|
-
...result,
|
|
4920
|
-
...subResult,
|
|
4921
|
-
magicDirectoryIndex: true,
|
|
4922
|
-
};
|
|
4392
|
+
Object.keys(scopes).forEach((scopeSpecifier) => {
|
|
4393
|
+
const scopeMappings = scopes[scopeSpecifier];
|
|
4394
|
+
const scopeUrl = tryUrlResolution(scopeSpecifier, baseUrl);
|
|
4395
|
+
if (scopeUrl === null) {
|
|
4396
|
+
console.warn(
|
|
4397
|
+
formulateScopeResolutionFailed({
|
|
4398
|
+
scope: scopeSpecifier,
|
|
4399
|
+
baseUrl,
|
|
4400
|
+
}),
|
|
4401
|
+
);
|
|
4402
|
+
return;
|
|
4923
4403
|
}
|
|
4924
|
-
|
|
4925
|
-
|
|
4926
|
-
|
|
4927
|
-
}
|
|
4404
|
+
const scopeValueNormalized = normalizeMappings(scopeMappings, baseUrl);
|
|
4405
|
+
scopesNormalized[scopeUrl] = scopeValueNormalized;
|
|
4406
|
+
});
|
|
4928
4407
|
|
|
4929
|
-
|
|
4930
|
-
const parentUrl = new URL("./", fileUrl).href;
|
|
4931
|
-
const urlFilename = urlToFilename(fileUrl);
|
|
4932
|
-
for (const extensionToTry of magicExtensions) {
|
|
4933
|
-
const urlCandidate = `${parentUrl}${urlFilename}${extensionToTry}`;
|
|
4934
|
-
let stat;
|
|
4935
|
-
try {
|
|
4936
|
-
stat = readEntryStatSync(new URL(urlCandidate));
|
|
4937
|
-
} catch (e) {
|
|
4938
|
-
if (e.code === "ENOENT") {
|
|
4939
|
-
stat = null;
|
|
4940
|
-
} else {
|
|
4941
|
-
throw e;
|
|
4942
|
-
}
|
|
4943
|
-
}
|
|
4944
|
-
if (stat) {
|
|
4945
|
-
result.stat = stat;
|
|
4946
|
-
result.url = `${fileUrl}${extensionToTry}`;
|
|
4947
|
-
result.magicExtension = extensionToTry;
|
|
4948
|
-
return result;
|
|
4949
|
-
}
|
|
4950
|
-
}
|
|
4951
|
-
}
|
|
4952
|
-
// magic extension not found
|
|
4953
|
-
return result;
|
|
4408
|
+
return sortScopes(scopesNormalized);
|
|
4954
4409
|
};
|
|
4955
4410
|
|
|
4956
|
-
const
|
|
4957
|
-
|
|
4958
|
-
|
|
4959
|
-
|
|
4960
|
-
|
|
4961
|
-
magicExtensions.forEach((magicExtension) => {
|
|
4962
|
-
if (magicExtension === "inherit") {
|
|
4963
|
-
const importerExtension = urlToExtension(importer);
|
|
4964
|
-
extensionsSet.add(importerExtension);
|
|
4965
|
-
} else {
|
|
4966
|
-
extensionsSet.add(magicExtension);
|
|
4967
|
-
}
|
|
4968
|
-
});
|
|
4969
|
-
return Array.from(extensionsSet.values());
|
|
4970
|
-
};
|
|
4411
|
+
const formulateBaseUrlMustBeStringOrUrl = ({
|
|
4412
|
+
baseUrl,
|
|
4413
|
+
}) => `baseUrl must be a string or an url.
|
|
4414
|
+
--- base url ---
|
|
4415
|
+
${baseUrl}`;
|
|
4971
4416
|
|
|
4972
|
-
const
|
|
4973
|
-
|
|
4974
|
-
|
|
4975
|
-
|
|
4976
|
-
|
|
4977
|
-
|
|
4417
|
+
const formulateAddressMustBeAString = ({
|
|
4418
|
+
specifier,
|
|
4419
|
+
address,
|
|
4420
|
+
}) => `Address must be a string.
|
|
4421
|
+
--- address ---
|
|
4422
|
+
${address}
|
|
4423
|
+
--- specifier ---
|
|
4424
|
+
${specifier}`;
|
|
4425
|
+
|
|
4426
|
+
const formulateAdressResolutionFailed = ({
|
|
4427
|
+
address,
|
|
4428
|
+
baseUrl,
|
|
4429
|
+
specifier,
|
|
4430
|
+
}) => `Address url resolution failed.
|
|
4431
|
+
--- address ---
|
|
4432
|
+
${address}
|
|
4433
|
+
--- base url ---
|
|
4434
|
+
${baseUrl}
|
|
4435
|
+
--- specifier ---
|
|
4436
|
+
${specifier}`;
|
|
4437
|
+
|
|
4438
|
+
const formulateAddressUrlRequiresTrailingSlash = ({
|
|
4439
|
+
addressURL,
|
|
4440
|
+
address,
|
|
4441
|
+
specifier,
|
|
4442
|
+
}) => `Address must end with /.
|
|
4443
|
+
--- address url ---
|
|
4444
|
+
${addressURL}
|
|
4445
|
+
--- address ---
|
|
4446
|
+
${address}
|
|
4447
|
+
--- specifier ---
|
|
4448
|
+
${specifier}`;
|
|
4449
|
+
|
|
4450
|
+
const formulateScopeResolutionFailed = ({
|
|
4451
|
+
scope,
|
|
4452
|
+
baseUrl,
|
|
4453
|
+
}) => `Scope url resolution failed.
|
|
4454
|
+
--- scope ---
|
|
4455
|
+
${scope}
|
|
4456
|
+
--- base url ---
|
|
4457
|
+
${baseUrl}`;
|
|
4458
|
+
|
|
4459
|
+
const pathnameToExtension = (pathname) => {
|
|
4460
|
+
const slashLastIndex = pathname.lastIndexOf("/");
|
|
4461
|
+
if (slashLastIndex !== -1) {
|
|
4462
|
+
pathname = pathname.slice(slashLastIndex + 1);
|
|
4978
4463
|
}
|
|
4979
|
-
throw new TypeError(`version must be a number or a string, got ${value}`);
|
|
4980
|
-
};
|
|
4981
4464
|
|
|
4982
|
-
const
|
|
4983
|
-
return
|
|
4984
|
-
|
|
4985
|
-
|
|
4986
|
-
patch: 0,
|
|
4987
|
-
};
|
|
4465
|
+
const dotLastIndex = pathname.lastIndexOf(".");
|
|
4466
|
+
if (dotLastIndex === -1) return "";
|
|
4467
|
+
// if (dotLastIndex === pathname.length - 1) return ""
|
|
4468
|
+
return pathname.slice(dotLastIndex);
|
|
4988
4469
|
};
|
|
4989
4470
|
|
|
4990
|
-
const
|
|
4991
|
-
|
|
4992
|
-
|
|
4993
|
-
|
|
4994
|
-
|
|
4995
|
-
|
|
4996
|
-
|
|
4997
|
-
|
|
4471
|
+
const resolveImport = ({
|
|
4472
|
+
specifier,
|
|
4473
|
+
importer,
|
|
4474
|
+
importMap,
|
|
4475
|
+
defaultExtension = false,
|
|
4476
|
+
createBareSpecifierError,
|
|
4477
|
+
onImportMapping = () => {},
|
|
4478
|
+
}) => {
|
|
4479
|
+
let url;
|
|
4480
|
+
if (importMap) {
|
|
4481
|
+
url = applyImportMap({
|
|
4482
|
+
importMap,
|
|
4483
|
+
specifier,
|
|
4484
|
+
importer,
|
|
4485
|
+
createBareSpecifierError,
|
|
4486
|
+
onImportMapping,
|
|
4487
|
+
});
|
|
4488
|
+
} else {
|
|
4489
|
+
url = resolveUrl(specifier, importer);
|
|
4998
4490
|
}
|
|
4999
4491
|
|
|
5000
|
-
if (
|
|
5001
|
-
|
|
5002
|
-
major: 0,
|
|
5003
|
-
minor: 0,
|
|
5004
|
-
patch: 0,
|
|
5005
|
-
};
|
|
4492
|
+
if (defaultExtension) {
|
|
4493
|
+
url = applyDefaultExtension({ url, importer, defaultExtension });
|
|
5006
4494
|
}
|
|
5007
4495
|
|
|
5008
|
-
return
|
|
5009
|
-
major: Number(string),
|
|
5010
|
-
minor: 0,
|
|
5011
|
-
patch: 0,
|
|
5012
|
-
};
|
|
4496
|
+
return url;
|
|
5013
4497
|
};
|
|
5014
4498
|
|
|
5015
|
-
const
|
|
5016
|
-
|
|
5017
|
-
|
|
5018
|
-
const majorDiff = semanticVersionA.major - semanticVersionB.major;
|
|
5019
|
-
if (majorDiff > 0) {
|
|
5020
|
-
return majorDiff;
|
|
5021
|
-
}
|
|
5022
|
-
if (majorDiff < 0) {
|
|
5023
|
-
return majorDiff;
|
|
5024
|
-
}
|
|
5025
|
-
const minorDiff = semanticVersionA.minor - semanticVersionB.minor;
|
|
5026
|
-
if (minorDiff > 0) {
|
|
5027
|
-
return minorDiff;
|
|
5028
|
-
}
|
|
5029
|
-
if (minorDiff < 0) {
|
|
5030
|
-
return minorDiff;
|
|
4499
|
+
const applyDefaultExtension = ({ url, importer, defaultExtension }) => {
|
|
4500
|
+
if (urlToPathname(url).endsWith("/")) {
|
|
4501
|
+
return url;
|
|
5031
4502
|
}
|
|
5032
|
-
|
|
5033
|
-
if (
|
|
5034
|
-
|
|
4503
|
+
|
|
4504
|
+
if (typeof defaultExtension === "string") {
|
|
4505
|
+
const extension = pathnameToExtension(url);
|
|
4506
|
+
if (extension === "") {
|
|
4507
|
+
return `${url}${defaultExtension}`;
|
|
4508
|
+
}
|
|
4509
|
+
return url;
|
|
5035
4510
|
}
|
|
5036
|
-
|
|
5037
|
-
|
|
4511
|
+
|
|
4512
|
+
if (defaultExtension === true) {
|
|
4513
|
+
const extension = pathnameToExtension(url);
|
|
4514
|
+
if (extension === "" && importer) {
|
|
4515
|
+
const importerPathname = urlToPathname(importer);
|
|
4516
|
+
const importerExtension = pathnameToExtension(importerPathname);
|
|
4517
|
+
return `${url}${importerExtension}`;
|
|
4518
|
+
}
|
|
5038
4519
|
}
|
|
5039
|
-
return 0;
|
|
5040
|
-
};
|
|
5041
4520
|
|
|
5042
|
-
|
|
5043
|
-
return compareTwoVersions(versionSupposedBelow, versionSupposedAbove) < 0;
|
|
4521
|
+
return url;
|
|
5044
4522
|
};
|
|
5045
4523
|
|
|
5046
|
-
const
|
|
5047
|
-
|
|
5048
|
-
|
|
5049
|
-
|
|
5050
|
-
|
|
4524
|
+
const isEscaped = (i, string) => {
|
|
4525
|
+
let backslashBeforeCount = 0;
|
|
4526
|
+
while (i--) {
|
|
4527
|
+
const previousChar = string[i];
|
|
4528
|
+
if (previousChar === "\\") {
|
|
4529
|
+
backslashBeforeCount++;
|
|
5051
4530
|
}
|
|
5052
|
-
|
|
5053
|
-
}
|
|
4531
|
+
break;
|
|
4532
|
+
}
|
|
4533
|
+
const isEven = backslashBeforeCount % 2 === 0;
|
|
4534
|
+
return !isEven;
|
|
5054
4535
|
};
|
|
5055
4536
|
|
|
5056
|
-
const
|
|
5057
|
-
|
|
5058
|
-
|
|
5059
|
-
|
|
5060
|
-
|
|
5061
|
-
|
|
5062
|
-
|
|
5063
|
-
|
|
5064
|
-
|
|
5065
|
-
|
|
5066
|
-
|
|
5067
|
-
|
|
5068
|
-
|
|
5069
|
-
|
|
5070
|
-
|
|
5071
|
-
|
|
5072
|
-
|
|
5073
|
-
|
|
5074
|
-
|
|
5075
|
-
|
|
5076
|
-
// https://caniuse.com/?search=import.meta
|
|
5077
|
-
import_meta: {
|
|
5078
|
-
android: "9",
|
|
5079
|
-
chrome: "64",
|
|
5080
|
-
edge: "79",
|
|
5081
|
-
firefox: "62",
|
|
5082
|
-
ios: "12",
|
|
5083
|
-
opera: "51",
|
|
5084
|
-
safari: "11.1",
|
|
5085
|
-
samsung: "9.2",
|
|
5086
|
-
},
|
|
5087
|
-
import_meta_resolve: {
|
|
5088
|
-
chrome: "107",
|
|
5089
|
-
edge: "105",
|
|
5090
|
-
firefox: "106",
|
|
5091
|
-
node: "20.0.0",
|
|
5092
|
-
},
|
|
5093
|
-
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#browser_compatibility
|
|
5094
|
-
import_dynamic: {
|
|
5095
|
-
android: "8",
|
|
5096
|
-
chrome: "63",
|
|
5097
|
-
edge: "79",
|
|
5098
|
-
firefox: "67",
|
|
5099
|
-
ios: "11.3",
|
|
5100
|
-
opera: "50",
|
|
5101
|
-
safari: "11.3",
|
|
5102
|
-
samsung: "8.0",
|
|
5103
|
-
node: "13.2",
|
|
4537
|
+
const JS_QUOTES = {
|
|
4538
|
+
pickBest: (string, { canUseTemplateString, defaultQuote = DOUBLE } = {}) => {
|
|
4539
|
+
// check default first, once tested do no re-test it
|
|
4540
|
+
if (!string.includes(defaultQuote)) {
|
|
4541
|
+
return defaultQuote;
|
|
4542
|
+
}
|
|
4543
|
+
if (defaultQuote !== DOUBLE && !string.includes(DOUBLE)) {
|
|
4544
|
+
return DOUBLE;
|
|
4545
|
+
}
|
|
4546
|
+
if (defaultQuote !== SINGLE && !string.includes(SINGLE)) {
|
|
4547
|
+
return SINGLE;
|
|
4548
|
+
}
|
|
4549
|
+
if (
|
|
4550
|
+
canUseTemplateString &&
|
|
4551
|
+
defaultQuote !== BACKTICK &&
|
|
4552
|
+
!string.includes(BACKTICK)
|
|
4553
|
+
) {
|
|
4554
|
+
return BACKTICK;
|
|
4555
|
+
}
|
|
4556
|
+
return defaultQuote;
|
|
5104
4557
|
},
|
|
5105
|
-
|
|
5106
|
-
|
|
5107
|
-
|
|
5108
|
-
|
|
5109
|
-
|
|
5110
|
-
|
|
5111
|
-
|
|
5112
|
-
|
|
5113
|
-
|
|
5114
|
-
|
|
5115
|
-
|
|
5116
|
-
|
|
5117
|
-
|
|
5118
|
-
|
|
5119
|
-
|
|
5120
|
-
|
|
5121
|
-
|
|
5122
|
-
|
|
5123
|
-
|
|
5124
|
-
|
|
5125
|
-
|
|
5126
|
-
|
|
5127
|
-
|
|
5128
|
-
|
|
5129
|
-
|
|
5130
|
-
|
|
5131
|
-
|
|
5132
|
-
|
|
5133
|
-
|
|
5134
|
-
|
|
5135
|
-
|
|
5136
|
-
|
|
5137
|
-
|
|
5138
|
-
|
|
5139
|
-
|
|
5140
|
-
|
|
5141
|
-
|
|
5142
|
-
|
|
5143
|
-
|
|
5144
|
-
|
|
5145
|
-
|
|
5146
|
-
|
|
5147
|
-
|
|
5148
|
-
|
|
5149
|
-
|
|
5150
|
-
|
|
5151
|
-
|
|
5152
|
-
|
|
5153
|
-
|
|
5154
|
-
|
|
5155
|
-
|
|
5156
|
-
|
|
5157
|
-
|
|
5158
|
-
|
|
5159
|
-
|
|
5160
|
-
|
|
5161
|
-
|
|
5162
|
-
|
|
5163
|
-
|
|
5164
|
-
|
|
5165
|
-
|
|
5166
|
-
|
|
5167
|
-
|
|
5168
|
-
chrome: "80",
|
|
5169
|
-
edge: "80",
|
|
5170
|
-
opera: "67",
|
|
5171
|
-
android: "80",
|
|
5172
|
-
},
|
|
5173
|
-
service_worker_importmap: {},
|
|
5174
|
-
shared_worker: {
|
|
5175
|
-
chrome: "4",
|
|
5176
|
-
edge: "79",
|
|
5177
|
-
firefox: "29",
|
|
5178
|
-
opera: "10.6",
|
|
5179
|
-
},
|
|
5180
|
-
shared_worker_type_module: {
|
|
5181
|
-
chrome: "80",
|
|
5182
|
-
edge: "80",
|
|
5183
|
-
opera: "67",
|
|
5184
|
-
},
|
|
5185
|
-
shared_worker_importmap: {},
|
|
5186
|
-
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/globalThis#browser_compatibility
|
|
5187
|
-
global_this: {
|
|
5188
|
-
edge: "79",
|
|
5189
|
-
firefox: "65",
|
|
5190
|
-
chrome: "71",
|
|
5191
|
-
safari: "12.1",
|
|
5192
|
-
opera: "58",
|
|
5193
|
-
ios: "12.2",
|
|
5194
|
-
android: "94",
|
|
5195
|
-
node: "12",
|
|
5196
|
-
},
|
|
5197
|
-
async_generator_function: {
|
|
5198
|
-
chrome: "63",
|
|
5199
|
-
opera: "50",
|
|
5200
|
-
edge: "79",
|
|
5201
|
-
firefox: "57",
|
|
5202
|
-
safari: "12",
|
|
5203
|
-
node: "10",
|
|
5204
|
-
ios: "12",
|
|
5205
|
-
samsung: "8",
|
|
5206
|
-
electron: "3",
|
|
5207
|
-
},
|
|
5208
|
-
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#browser_compatibility
|
|
5209
|
-
template_literals: {
|
|
5210
|
-
chrome: "41",
|
|
5211
|
-
edge: "12",
|
|
5212
|
-
firefox: "34",
|
|
5213
|
-
opera: "28",
|
|
5214
|
-
safari: "9",
|
|
5215
|
-
ios: "9",
|
|
5216
|
-
android: "4",
|
|
5217
|
-
node: "4",
|
|
5218
|
-
},
|
|
5219
|
-
arrow_function: {
|
|
5220
|
-
chrome: "47",
|
|
5221
|
-
opera: "34",
|
|
5222
|
-
edge: "13",
|
|
5223
|
-
firefox: "45",
|
|
5224
|
-
safari: "10",
|
|
5225
|
-
node: "6",
|
|
5226
|
-
ios: "10",
|
|
5227
|
-
samsung: "5",
|
|
5228
|
-
electron: "0.36",
|
|
5229
|
-
},
|
|
5230
|
-
const_bindings: {
|
|
5231
|
-
chrome: "41",
|
|
5232
|
-
opera: "28",
|
|
5233
|
-
edge: "12",
|
|
5234
|
-
firefox: "46",
|
|
5235
|
-
safari: "10",
|
|
5236
|
-
node: "4",
|
|
5237
|
-
ie: "11",
|
|
5238
|
-
ios: "10",
|
|
5239
|
-
samsung: "3.4",
|
|
5240
|
-
electron: "0.22",
|
|
4558
|
+
|
|
4559
|
+
escapeSpecialChars: (
|
|
4560
|
+
string,
|
|
4561
|
+
{
|
|
4562
|
+
quote = "pickBest",
|
|
4563
|
+
canUseTemplateString,
|
|
4564
|
+
defaultQuote,
|
|
4565
|
+
allowEscapeForVersioning = false,
|
|
4566
|
+
},
|
|
4567
|
+
) => {
|
|
4568
|
+
quote =
|
|
4569
|
+
quote === "pickBest"
|
|
4570
|
+
? JS_QUOTES.pickBest(string, { canUseTemplateString, defaultQuote })
|
|
4571
|
+
: quote;
|
|
4572
|
+
const replacements = JS_QUOTE_REPLACEMENTS[quote];
|
|
4573
|
+
let result = "";
|
|
4574
|
+
let last = 0;
|
|
4575
|
+
let i = 0;
|
|
4576
|
+
while (i < string.length) {
|
|
4577
|
+
const char = string[i];
|
|
4578
|
+
i++;
|
|
4579
|
+
if (isEscaped(i - 1, string)) continue;
|
|
4580
|
+
const replacement = replacements[char];
|
|
4581
|
+
if (replacement) {
|
|
4582
|
+
if (
|
|
4583
|
+
allowEscapeForVersioning &&
|
|
4584
|
+
char === quote &&
|
|
4585
|
+
string.slice(i, i + 6) === "+__v__"
|
|
4586
|
+
) {
|
|
4587
|
+
let isVersioningConcatenation = false;
|
|
4588
|
+
let j = i + 6; // start after the +
|
|
4589
|
+
while (j < string.length) {
|
|
4590
|
+
const lookAheadChar = string[j];
|
|
4591
|
+
j++;
|
|
4592
|
+
if (
|
|
4593
|
+
lookAheadChar === "+" &&
|
|
4594
|
+
string[j] === quote &&
|
|
4595
|
+
!isEscaped(j - 1, string)
|
|
4596
|
+
) {
|
|
4597
|
+
isVersioningConcatenation = true;
|
|
4598
|
+
break;
|
|
4599
|
+
}
|
|
4600
|
+
}
|
|
4601
|
+
if (isVersioningConcatenation) {
|
|
4602
|
+
// it's a concatenation
|
|
4603
|
+
// skip until the end of concatenation (the second +)
|
|
4604
|
+
// and resume from there
|
|
4605
|
+
i = j + 1;
|
|
4606
|
+
continue;
|
|
4607
|
+
}
|
|
4608
|
+
}
|
|
4609
|
+
if (last === i - 1) {
|
|
4610
|
+
result += replacement;
|
|
4611
|
+
} else {
|
|
4612
|
+
result += `${string.slice(last, i - 1)}${replacement}`;
|
|
4613
|
+
}
|
|
4614
|
+
last = i;
|
|
4615
|
+
}
|
|
4616
|
+
}
|
|
4617
|
+
if (last !== string.length) {
|
|
4618
|
+
result += string.slice(last);
|
|
4619
|
+
}
|
|
4620
|
+
return `${quote}${result}${quote}`;
|
|
5241
4621
|
},
|
|
5242
|
-
|
|
5243
|
-
|
|
5244
|
-
|
|
5245
|
-
|
|
5246
|
-
|
|
5247
|
-
|
|
5248
|
-
|
|
5249
|
-
|
|
5250
|
-
|
|
5251
|
-
|
|
4622
|
+
};
|
|
4623
|
+
|
|
4624
|
+
const DOUBLE = `"`;
|
|
4625
|
+
const SINGLE = `'`;
|
|
4626
|
+
const BACKTICK = "`";
|
|
4627
|
+
const lineEndingEscapes = {
|
|
4628
|
+
"\n": "\\n",
|
|
4629
|
+
"\r": "\\r",
|
|
4630
|
+
"\u2028": "\\u2028",
|
|
4631
|
+
"\u2029": "\\u2029",
|
|
4632
|
+
};
|
|
4633
|
+
const JS_QUOTE_REPLACEMENTS = {
|
|
4634
|
+
[DOUBLE]: {
|
|
4635
|
+
'"': '\\"',
|
|
4636
|
+
...lineEndingEscapes,
|
|
5252
4637
|
},
|
|
5253
|
-
|
|
5254
|
-
|
|
5255
|
-
|
|
5256
|
-
edge: "12",
|
|
5257
|
-
firefox: "2",
|
|
5258
|
-
safari: "3.1",
|
|
5259
|
-
node: "0.10",
|
|
5260
|
-
ie: "9",
|
|
5261
|
-
android: "4.4",
|
|
5262
|
-
ios: "6",
|
|
5263
|
-
phantom: "2",
|
|
5264
|
-
samsung: "1",
|
|
5265
|
-
electron: "0.20",
|
|
4638
|
+
[SINGLE]: {
|
|
4639
|
+
"'": "\\'",
|
|
4640
|
+
...lineEndingEscapes,
|
|
5266
4641
|
},
|
|
5267
|
-
|
|
5268
|
-
|
|
5269
|
-
|
|
5270
|
-
edge: "12",
|
|
5271
|
-
firefox: "36",
|
|
5272
|
-
safari: "9",
|
|
5273
|
-
ios: "9",
|
|
5274
|
-
samsung: "4",
|
|
5275
|
-
node: "0.12",
|
|
4642
|
+
[BACKTICK]: {
|
|
4643
|
+
"`": "\\`",
|
|
4644
|
+
"$": "\\$",
|
|
5276
4645
|
},
|
|
5277
4646
|
};
|
|
5278
4647
|
|
|
5279
|
-
|
|
5280
|
-
|
|
5281
|
-
|
|
5282
|
-
|
|
5283
|
-
|
|
5284
|
-
|
|
5285
|
-
|
|
5286
|
-
|
|
5287
|
-
|
|
5288
|
-
|
|
5289
|
-
|
|
5290
|
-
|
|
5291
|
-
|
|
5292
|
-
|
|
5293
|
-
|
|
5294
|
-
|
|
4648
|
+
// https://nodejs.org/api/packages.html#resolving-user-conditions
|
|
4649
|
+
const readCustomConditionsFromProcessArgs = () => {
|
|
4650
|
+
if (process.env.IGNORE_PACKAGE_CONDITIONS) {
|
|
4651
|
+
return [];
|
|
4652
|
+
}
|
|
4653
|
+
const packageConditions = [];
|
|
4654
|
+
for (const arg of process.execArgv) {
|
|
4655
|
+
if (arg.includes("-C=")) {
|
|
4656
|
+
const packageCondition = arg.slice(0, "-C=".length);
|
|
4657
|
+
packageConditions.push(packageCondition);
|
|
4658
|
+
}
|
|
4659
|
+
if (arg.includes("--conditions=")) {
|
|
4660
|
+
const packageCondition = arg.slice("--conditions=".length);
|
|
4661
|
+
packageConditions.push(packageCondition);
|
|
4662
|
+
}
|
|
4663
|
+
}
|
|
4664
|
+
return packageConditions;
|
|
4665
|
+
};
|
|
4666
|
+
|
|
4667
|
+
const asDirectoryUrl = (url) => {
|
|
4668
|
+
const { pathname } = new URL(url);
|
|
4669
|
+
if (pathname.endsWith("/")) {
|
|
4670
|
+
return url;
|
|
4671
|
+
}
|
|
4672
|
+
return new URL("./", url).href;
|
|
4673
|
+
};
|
|
4674
|
+
|
|
4675
|
+
const getParentUrl = (url) => {
|
|
4676
|
+
if (url.startsWith("file://")) {
|
|
4677
|
+
// With node.js new URL('../', 'file:///C:/').href
|
|
4678
|
+
// returns "file:///C:/" instead of "file:///"
|
|
4679
|
+
const resource = url.slice("file://".length);
|
|
4680
|
+
const slashLastIndex = resource.lastIndexOf("/");
|
|
4681
|
+
if (slashLastIndex === -1) {
|
|
4682
|
+
return url;
|
|
4683
|
+
}
|
|
4684
|
+
const lastCharIndex = resource.length - 1;
|
|
4685
|
+
if (slashLastIndex === lastCharIndex) {
|
|
4686
|
+
const slashBeforeLastIndex = resource.lastIndexOf(
|
|
4687
|
+
"/",
|
|
4688
|
+
slashLastIndex - 1,
|
|
4689
|
+
);
|
|
4690
|
+
if (slashBeforeLastIndex === -1) {
|
|
4691
|
+
return url;
|
|
5295
4692
|
}
|
|
5296
|
-
|
|
5297
|
-
|
|
5298
|
-
},
|
|
4693
|
+
return `file://${resource.slice(0, slashBeforeLastIndex + 1)}`;
|
|
4694
|
+
}
|
|
5299
4695
|
|
|
5300
|
-
|
|
5301
|
-
|
|
5302
|
-
|
|
5303
|
-
|
|
5304
|
-
|
|
5305
|
-
|
|
5306
|
-
|
|
5307
|
-
|
|
5308
|
-
|
|
5309
|
-
|
|
5310
|
-
|
|
5311
|
-
|
|
4696
|
+
return `file://${resource.slice(0, slashLastIndex + 1)}`;
|
|
4697
|
+
}
|
|
4698
|
+
return new URL(url.endsWith("/") ? "../" : "./", url).href;
|
|
4699
|
+
};
|
|
4700
|
+
|
|
4701
|
+
const isValidUrl = (url) => {
|
|
4702
|
+
try {
|
|
4703
|
+
// eslint-disable-next-line no-new
|
|
4704
|
+
new URL(url);
|
|
4705
|
+
return true;
|
|
4706
|
+
} catch {
|
|
4707
|
+
return false;
|
|
4708
|
+
}
|
|
4709
|
+
};
|
|
4710
|
+
|
|
4711
|
+
const urlToFilename = (url) => {
|
|
4712
|
+
const { pathname } = new URL(url);
|
|
4713
|
+
const pathnameBeforeLastSlash = pathname.endsWith("/")
|
|
4714
|
+
? pathname.slice(0, -1)
|
|
4715
|
+
: pathname;
|
|
4716
|
+
const slashLastIndex = pathnameBeforeLastSlash.lastIndexOf("/");
|
|
4717
|
+
const filename =
|
|
4718
|
+
slashLastIndex === -1
|
|
4719
|
+
? pathnameBeforeLastSlash
|
|
4720
|
+
: pathnameBeforeLastSlash.slice(slashLastIndex + 1);
|
|
4721
|
+
return filename;
|
|
4722
|
+
};
|
|
4723
|
+
|
|
4724
|
+
const urlToExtension = (url) => {
|
|
4725
|
+
const filename = urlToFilename(url);
|
|
4726
|
+
const dotLastIndex = filename.lastIndexOf(".");
|
|
4727
|
+
if (dotLastIndex === -1) return "";
|
|
4728
|
+
// if (dotLastIndex === pathname.length - 1) return ""
|
|
4729
|
+
const extension = filename.slice(dotLastIndex);
|
|
4730
|
+
return extension;
|
|
4731
|
+
};
|
|
4732
|
+
|
|
4733
|
+
const defaultLookupPackageScope = (url) => {
|
|
4734
|
+
let scopeUrl = asDirectoryUrl(url);
|
|
4735
|
+
while (scopeUrl !== "file:///") {
|
|
4736
|
+
if (scopeUrl.endsWith("node_modules/")) {
|
|
4737
|
+
return null;
|
|
4738
|
+
}
|
|
4739
|
+
const packageJsonUrlObject = new URL("package.json", scopeUrl);
|
|
4740
|
+
if (existsSync(packageJsonUrlObject)) {
|
|
4741
|
+
return scopeUrl;
|
|
4742
|
+
}
|
|
4743
|
+
scopeUrl = getParentUrl(scopeUrl);
|
|
4744
|
+
}
|
|
4745
|
+
return null;
|
|
4746
|
+
};
|
|
4747
|
+
|
|
4748
|
+
const defaultReadPackageJson = (packageUrl) => {
|
|
4749
|
+
const packageJsonFileUrl = new URL("./package.json", packageUrl);
|
|
4750
|
+
let packageJsonFileContentBuffer;
|
|
4751
|
+
try {
|
|
4752
|
+
packageJsonFileContentBuffer = readFileSync(packageJsonFileUrl, "utf8");
|
|
4753
|
+
} catch (e) {
|
|
4754
|
+
if (e.code === "ENOENT") {
|
|
4755
|
+
return null;
|
|
4756
|
+
}
|
|
4757
|
+
throw e;
|
|
4758
|
+
}
|
|
4759
|
+
const packageJsonFileContentString = String(packageJsonFileContentBuffer);
|
|
4760
|
+
try {
|
|
4761
|
+
const packageJsonFileContentObject = JSON.parse(
|
|
4762
|
+
packageJsonFileContentString,
|
|
4763
|
+
);
|
|
4764
|
+
return packageJsonFileContentObject;
|
|
4765
|
+
} catch {
|
|
4766
|
+
throw new Error(`Invalid package configuration at ${packageJsonFileUrl}`);
|
|
4767
|
+
}
|
|
4768
|
+
};
|
|
4769
|
+
|
|
4770
|
+
// https://github.com/nodejs/node/blob/0367b5c35ea0f98b323175a4aaa8e651af7a91e7/tools/node_modules/eslint/node_modules/%40babel/core/lib/vendor/import-meta-resolve.js#L2473
|
|
4771
|
+
|
|
4772
|
+
const createInvalidModuleSpecifierError = (
|
|
4773
|
+
reason,
|
|
4774
|
+
specifier,
|
|
4775
|
+
{ parentUrl },
|
|
4776
|
+
) => {
|
|
4777
|
+
const error = new Error(
|
|
4778
|
+
`Invalid module "${specifier}" ${reason} imported from ${fileURLToPath(
|
|
4779
|
+
parentUrl,
|
|
4780
|
+
)}`,
|
|
4781
|
+
);
|
|
4782
|
+
error.code = "INVALID_MODULE_SPECIFIER";
|
|
4783
|
+
return error;
|
|
4784
|
+
};
|
|
4785
|
+
|
|
4786
|
+
const createInvalidPackageTargetError = (
|
|
4787
|
+
reason,
|
|
4788
|
+
target,
|
|
4789
|
+
{ parentUrl, packageDirectoryUrl, key, isImport },
|
|
4790
|
+
) => {
|
|
4791
|
+
let message;
|
|
4792
|
+
if (key === ".") {
|
|
4793
|
+
message = `Invalid "exports" main target defined in ${fileURLToPath(
|
|
4794
|
+
packageDirectoryUrl,
|
|
4795
|
+
)}package.json imported from ${fileURLToPath(parentUrl)}; ${reason}`;
|
|
4796
|
+
} else {
|
|
4797
|
+
message = `Invalid "${
|
|
4798
|
+
isImport ? "imports" : "exports"
|
|
4799
|
+
}" target ${JSON.stringify(target)} defined for "${key}" in ${fileURLToPath(
|
|
4800
|
+
packageDirectoryUrl,
|
|
4801
|
+
)}package.json imported from ${fileURLToPath(parentUrl)}; ${reason}`;
|
|
4802
|
+
}
|
|
4803
|
+
const error = new Error(message);
|
|
4804
|
+
error.code = "INVALID_PACKAGE_TARGET";
|
|
4805
|
+
return error;
|
|
4806
|
+
};
|
|
4807
|
+
|
|
4808
|
+
const createPackagePathNotExportedError = (
|
|
4809
|
+
subpath,
|
|
4810
|
+
{ parentUrl, packageDirectoryUrl },
|
|
4811
|
+
) => {
|
|
4812
|
+
let message;
|
|
4813
|
+
if (subpath === ".") {
|
|
4814
|
+
message = `No "exports" main defined in ${fileURLToPath(
|
|
4815
|
+
packageDirectoryUrl,
|
|
4816
|
+
)}package.json imported from ${fileURLToPath(parentUrl)}`;
|
|
4817
|
+
} else {
|
|
4818
|
+
message = `Package subpath "${subpath}" is not defined by "exports" in ${fileURLToPath(
|
|
4819
|
+
packageDirectoryUrl,
|
|
4820
|
+
)}package.json imported from ${fileURLToPath(parentUrl)}`;
|
|
4821
|
+
}
|
|
4822
|
+
const error = new Error(message);
|
|
4823
|
+
error.code = "PACKAGE_PATH_NOT_EXPORTED";
|
|
4824
|
+
return error;
|
|
4825
|
+
};
|
|
4826
|
+
|
|
4827
|
+
const createModuleNotFoundError = (specifier, { parentUrl }) => {
|
|
4828
|
+
const error = new Error(
|
|
4829
|
+
`Cannot find "${specifier}" imported from ${fileURLToPath(parentUrl)}`,
|
|
4830
|
+
);
|
|
4831
|
+
error.code = "MODULE_NOT_FOUND";
|
|
4832
|
+
return error;
|
|
4833
|
+
};
|
|
4834
|
+
|
|
4835
|
+
const createPackageImportNotDefinedError = (
|
|
4836
|
+
specifier,
|
|
4837
|
+
{ parentUrl, packageDirectoryUrl },
|
|
4838
|
+
) => {
|
|
4839
|
+
const error = new Error(
|
|
4840
|
+
`Package import specifier "${specifier}" is not defined in ${fileURLToPath(
|
|
4841
|
+
packageDirectoryUrl,
|
|
4842
|
+
)}package.json imported from ${fileURLToPath(parentUrl)}`,
|
|
4843
|
+
);
|
|
4844
|
+
error.code = "PACKAGE_IMPORT_NOT_DEFINED";
|
|
4845
|
+
return error;
|
|
4846
|
+
};
|
|
4847
|
+
|
|
4848
|
+
const isSpecifierForNodeBuiltin = (specifier) => {
|
|
4849
|
+
return (
|
|
4850
|
+
specifier.startsWith("node:") ||
|
|
4851
|
+
NODE_BUILTIN_MODULE_SPECIFIERS.includes(specifier)
|
|
4852
|
+
);
|
|
4853
|
+
};
|
|
4854
|
+
|
|
4855
|
+
const NODE_BUILTIN_MODULE_SPECIFIERS = [
|
|
4856
|
+
"assert",
|
|
4857
|
+
"assert/strict",
|
|
4858
|
+
"async_hooks",
|
|
4859
|
+
"buffer_ieee754",
|
|
4860
|
+
"buffer",
|
|
4861
|
+
"child_process",
|
|
4862
|
+
"cluster",
|
|
4863
|
+
"console",
|
|
4864
|
+
"constants",
|
|
4865
|
+
"crypto",
|
|
4866
|
+
"_debugger",
|
|
4867
|
+
"diagnostics_channel",
|
|
4868
|
+
"dgram",
|
|
4869
|
+
"dns",
|
|
4870
|
+
"domain",
|
|
4871
|
+
"events",
|
|
4872
|
+
"freelist",
|
|
4873
|
+
"fs",
|
|
4874
|
+
"fsevents",
|
|
4875
|
+
"fs/promises",
|
|
4876
|
+
"_http_agent",
|
|
4877
|
+
"_http_client",
|
|
4878
|
+
"_http_common",
|
|
4879
|
+
"_http_incoming",
|
|
4880
|
+
"_http_outgoing",
|
|
4881
|
+
"_http_server",
|
|
4882
|
+
"http",
|
|
4883
|
+
"http2",
|
|
4884
|
+
"https",
|
|
4885
|
+
"inspector",
|
|
4886
|
+
"_linklist",
|
|
4887
|
+
"module",
|
|
4888
|
+
"net",
|
|
4889
|
+
"node-inspect/lib/_inspect",
|
|
4890
|
+
"node-inspect/lib/internal/inspect_client",
|
|
4891
|
+
"node-inspect/lib/internal/inspect_repl",
|
|
4892
|
+
"os",
|
|
4893
|
+
"path",
|
|
4894
|
+
"perf_hooks",
|
|
4895
|
+
"process",
|
|
4896
|
+
"punycode",
|
|
4897
|
+
"querystring",
|
|
4898
|
+
"readline",
|
|
4899
|
+
"repl",
|
|
4900
|
+
"smalloc",
|
|
4901
|
+
"sqlite",
|
|
4902
|
+
"_stream_duplex",
|
|
4903
|
+
"_stream_transform",
|
|
4904
|
+
"_stream_wrap",
|
|
4905
|
+
"_stream_passthrough",
|
|
4906
|
+
"_stream_readable",
|
|
4907
|
+
"_stream_writable",
|
|
4908
|
+
"stream",
|
|
4909
|
+
"stream/promises",
|
|
4910
|
+
"string_decoder",
|
|
4911
|
+
"sys",
|
|
4912
|
+
"timers",
|
|
4913
|
+
"_tls_common",
|
|
4914
|
+
"_tls_legacy",
|
|
4915
|
+
"_tls_wrap",
|
|
4916
|
+
"tls",
|
|
4917
|
+
"trace_events",
|
|
4918
|
+
"tty",
|
|
4919
|
+
"url",
|
|
4920
|
+
"util",
|
|
4921
|
+
"v8/tools/arguments",
|
|
4922
|
+
"v8/tools/codemap",
|
|
4923
|
+
"v8/tools/consarray",
|
|
4924
|
+
"v8/tools/csvparser",
|
|
4925
|
+
"v8/tools/logreader",
|
|
4926
|
+
"v8/tools/profile_view",
|
|
4927
|
+
"v8/tools/splaytree",
|
|
4928
|
+
"v8",
|
|
4929
|
+
"vm",
|
|
4930
|
+
"worker_threads",
|
|
4931
|
+
"zlib",
|
|
4932
|
+
// global is special
|
|
4933
|
+
"global",
|
|
4934
|
+
];
|
|
4935
|
+
|
|
4936
|
+
/*
|
|
4937
|
+
* https://nodejs.org/api/esm.html#resolver-algorithm-specification
|
|
4938
|
+
* https://github.com/nodejs/node/blob/0367b5c35ea0f98b323175a4aaa8e651af7a91e7/lib/internal/modules/esm/resolve.js#L1
|
|
4939
|
+
* deviations from the spec:
|
|
4940
|
+
* - take into account "browser", "module" and "jsnext"
|
|
4941
|
+
* - the check for isDirectory -> throw is delayed is descoped to the caller
|
|
4942
|
+
* - the call to real path ->
|
|
4943
|
+
* delayed to the caller so that we can decide to
|
|
4944
|
+
* maintain symlink as facade url when it's outside project directory
|
|
4945
|
+
* or use the real path when inside
|
|
4946
|
+
*/
|
|
4947
|
+
|
|
4948
|
+
const applyNodeEsmResolution = ({
|
|
4949
|
+
specifier,
|
|
4950
|
+
parentUrl,
|
|
4951
|
+
conditions = [...readCustomConditionsFromProcessArgs(), "node", "import"],
|
|
4952
|
+
lookupPackageScope = defaultLookupPackageScope,
|
|
4953
|
+
readPackageJson = defaultReadPackageJson,
|
|
4954
|
+
preservesSymlink = false,
|
|
4955
|
+
}) => {
|
|
4956
|
+
const resolution = applyPackageSpecifierResolution(specifier, {
|
|
4957
|
+
parentUrl: String(parentUrl),
|
|
4958
|
+
conditions,
|
|
4959
|
+
lookupPackageScope,
|
|
4960
|
+
readPackageJson,
|
|
4961
|
+
preservesSymlink,
|
|
4962
|
+
});
|
|
4963
|
+
const { url } = resolution;
|
|
4964
|
+
if (url.startsWith("file:")) {
|
|
4965
|
+
if (url.includes("%2F") || url.includes("%5C")) {
|
|
4966
|
+
throw createInvalidModuleSpecifierError(
|
|
4967
|
+
`must not include encoded "/" or "\\" characters`,
|
|
4968
|
+
specifier,
|
|
4969
|
+
{
|
|
4970
|
+
parentUrl,
|
|
4971
|
+
},
|
|
5312
4972
|
);
|
|
5313
|
-
return highestVersion !== runtimeVersion;
|
|
5314
|
-
});
|
|
5315
|
-
return !runtimeWithoutCompat;
|
|
5316
|
-
},
|
|
5317
|
-
};
|
|
5318
|
-
|
|
5319
|
-
const getFeatureCompat = (feature) => {
|
|
5320
|
-
if (typeof feature === "string") {
|
|
5321
|
-
const compat = featuresCompatMap[feature];
|
|
5322
|
-
if (!compat) {
|
|
5323
|
-
throw new Error(`"${feature}" feature is unknown`);
|
|
5324
4973
|
}
|
|
5325
|
-
return
|
|
5326
|
-
}
|
|
5327
|
-
if (typeof feature !== "object") {
|
|
5328
|
-
throw new TypeError(
|
|
5329
|
-
`feature must be a string or an object, got ${feature}`,
|
|
5330
|
-
);
|
|
4974
|
+
return resolution;
|
|
5331
4975
|
}
|
|
5332
|
-
return
|
|
4976
|
+
return resolution;
|
|
5333
4977
|
};
|
|
5334
4978
|
|
|
5335
|
-
const
|
|
5336
|
-
return
|
|
4979
|
+
const createResolutionResult = (data) => {
|
|
4980
|
+
return data;
|
|
5337
4981
|
};
|
|
5338
4982
|
|
|
5339
|
-
|
|
5340
|
-
const
|
|
5341
|
-
|
|
5342
|
-
|
|
5343
|
-
|
|
5344
|
-
|
|
4983
|
+
const applyPackageSpecifierResolution = (specifier, resolutionContext) => {
|
|
4984
|
+
const { parentUrl } = resolutionContext;
|
|
4985
|
+
// relative specifier
|
|
4986
|
+
if (
|
|
4987
|
+
specifier[0] === "/" ||
|
|
4988
|
+
specifier.startsWith("./") ||
|
|
4989
|
+
specifier.startsWith("../")
|
|
4990
|
+
) {
|
|
4991
|
+
if (specifier[0] !== "/") {
|
|
4992
|
+
const browserFieldResolution = applyBrowserFieldResolution(
|
|
4993
|
+
specifier,
|
|
4994
|
+
resolutionContext,
|
|
4995
|
+
);
|
|
4996
|
+
if (browserFieldResolution) {
|
|
4997
|
+
return browserFieldResolution;
|
|
4998
|
+
}
|
|
4999
|
+
}
|
|
5000
|
+
return createResolutionResult({
|
|
5001
|
+
type: "relative_specifier",
|
|
5002
|
+
url: new URL(specifier, parentUrl).href,
|
|
5003
|
+
});
|
|
5345
5004
|
}
|
|
5346
|
-
if (
|
|
5347
|
-
return
|
|
5005
|
+
if (specifier[0] === "#") {
|
|
5006
|
+
return applyPackageImportsResolution(specifier, resolutionContext);
|
|
5348
5007
|
}
|
|
5349
|
-
|
|
5350
|
-
|
|
5351
|
-
|
|
5352
|
-
|
|
5353
|
-
|
|
5354
|
-
|
|
5355
|
-
};
|
|
5356
|
-
|
|
5357
|
-
|
|
5358
|
-
|
|
5359
|
-
|
|
5360
|
-
// see https://w3c.github.io/webappsec-subresource-integrity/#parse-metadata
|
|
5361
|
-
const parseIntegrity = (string) => {
|
|
5362
|
-
const integrityMetadata = {};
|
|
5363
|
-
string
|
|
5364
|
-
.trim()
|
|
5365
|
-
.split(/\s+/)
|
|
5366
|
-
.forEach((token) => {
|
|
5367
|
-
const { isValid, algo, base64Value, optionExpression } =
|
|
5368
|
-
parseAsHashWithOptions(token);
|
|
5369
|
-
if (!isValid) {
|
|
5370
|
-
return;
|
|
5371
|
-
}
|
|
5372
|
-
if (!isSupportedAlgorithm(algo)) {
|
|
5373
|
-
return;
|
|
5374
|
-
}
|
|
5375
|
-
const metadataList = integrityMetadata[algo];
|
|
5376
|
-
const metadata = { base64Value, optionExpression };
|
|
5377
|
-
integrityMetadata[algo] = metadataList
|
|
5378
|
-
? [...metadataList, metadata]
|
|
5379
|
-
: [metadata];
|
|
5008
|
+
try {
|
|
5009
|
+
const urlObject = new URL(specifier);
|
|
5010
|
+
if (specifier.startsWith("node:")) {
|
|
5011
|
+
return createResolutionResult({
|
|
5012
|
+
type: "node_builtin_specifier",
|
|
5013
|
+
url: specifier,
|
|
5014
|
+
});
|
|
5015
|
+
}
|
|
5016
|
+
return createResolutionResult({
|
|
5017
|
+
type: "absolute_specifier",
|
|
5018
|
+
url: urlObject.href,
|
|
5380
5019
|
});
|
|
5381
|
-
|
|
5020
|
+
} catch {
|
|
5021
|
+
// bare specifier
|
|
5022
|
+
const browserFieldResolution = applyBrowserFieldResolution(
|
|
5023
|
+
specifier,
|
|
5024
|
+
resolutionContext,
|
|
5025
|
+
);
|
|
5026
|
+
if (browserFieldResolution) {
|
|
5027
|
+
return browserFieldResolution;
|
|
5028
|
+
}
|
|
5029
|
+
const packageResolution = applyPackageResolve(specifier, resolutionContext);
|
|
5030
|
+
const search = new URL(specifier, "file:///").search;
|
|
5031
|
+
if (search && !new URL(packageResolution.url).search) {
|
|
5032
|
+
packageResolution.url = `${packageResolution.url}${search}`;
|
|
5033
|
+
}
|
|
5034
|
+
return packageResolution;
|
|
5035
|
+
}
|
|
5382
5036
|
};
|
|
5383
5037
|
|
|
5384
|
-
|
|
5385
|
-
const
|
|
5386
|
-
|
|
5387
|
-
|
|
5388
|
-
|
|
5038
|
+
const applyBrowserFieldResolution = (specifier, resolutionContext) => {
|
|
5039
|
+
const { parentUrl, conditions, lookupPackageScope, readPackageJson } =
|
|
5040
|
+
resolutionContext;
|
|
5041
|
+
const browserCondition = conditions.includes("browser");
|
|
5042
|
+
if (!browserCondition) {
|
|
5043
|
+
return null;
|
|
5389
5044
|
}
|
|
5390
|
-
const
|
|
5391
|
-
|
|
5392
|
-
|
|
5393
|
-
const algo = beforeDash;
|
|
5394
|
-
if (questionIndex === -1) {
|
|
5395
|
-
const base64Value = afterDash;
|
|
5396
|
-
const isValid = BASE64_REGEX.test(afterDash);
|
|
5397
|
-
return { isValid, algo, base64Value };
|
|
5045
|
+
const packageDirectoryUrl = lookupPackageScope(parentUrl);
|
|
5046
|
+
if (!packageDirectoryUrl) {
|
|
5047
|
+
return null;
|
|
5398
5048
|
}
|
|
5399
|
-
const
|
|
5400
|
-
|
|
5401
|
-
|
|
5402
|
-
BASE64_REGEX.test(afterDash) && VCHAR_REGEX.test(optionExpression);
|
|
5403
|
-
return { isValid, algo, base64Value, optionExpression };
|
|
5404
|
-
};
|
|
5405
|
-
|
|
5406
|
-
const BASE64_REGEX = /^[A-Za-z0-9+/=]+$/;
|
|
5407
|
-
const VCHAR_REGEX = /^[\x21-\x7E]+$/;
|
|
5408
|
-
|
|
5409
|
-
// https://www.w3.org/TR/SRI/#does-response-match-metadatalist
|
|
5410
|
-
const validateResponseIntegrity = (
|
|
5411
|
-
{ url, type, dataRepresentation },
|
|
5412
|
-
integrity,
|
|
5413
|
-
) => {
|
|
5414
|
-
if (!isResponseEligibleForIntegrityValidation({ type })) {
|
|
5415
|
-
return false;
|
|
5049
|
+
const packageJson = readPackageJson(packageDirectoryUrl);
|
|
5050
|
+
if (!packageJson) {
|
|
5051
|
+
return null;
|
|
5416
5052
|
}
|
|
5417
|
-
const
|
|
5418
|
-
|
|
5419
|
-
|
|
5420
|
-
return true;
|
|
5053
|
+
const { browser } = packageJson;
|
|
5054
|
+
if (!browser) {
|
|
5055
|
+
return null;
|
|
5421
5056
|
}
|
|
5422
|
-
|
|
5423
|
-
|
|
5424
|
-
strongestAlgo =
|
|
5425
|
-
getPrioritizedHashFunction(strongestAlgo, algoCandidate) || strongestAlgo;
|
|
5426
|
-
});
|
|
5427
|
-
const metadataList = integrityMetadata[strongestAlgo];
|
|
5428
|
-
const actualBase64Value = applyAlgoToRepresentationData(
|
|
5429
|
-
strongestAlgo,
|
|
5430
|
-
dataRepresentation,
|
|
5431
|
-
);
|
|
5432
|
-
const acceptedBase64Values = metadataList.map(
|
|
5433
|
-
(metadata) => metadata.base64Value,
|
|
5434
|
-
);
|
|
5435
|
-
const someIsMatching = acceptedBase64Values.includes(actualBase64Value);
|
|
5436
|
-
if (someIsMatching) {
|
|
5437
|
-
return true;
|
|
5057
|
+
if (typeof browser !== "object") {
|
|
5058
|
+
return null;
|
|
5438
5059
|
}
|
|
5439
|
-
|
|
5440
|
-
|
|
5441
|
-
|
|
5442
|
-
|
|
5443
|
-
|
|
5444
|
-
|
|
5445
|
-
|
|
5060
|
+
let url;
|
|
5061
|
+
if (specifier.startsWith(".")) {
|
|
5062
|
+
const specifierUrl = new URL(specifier, parentUrl).href;
|
|
5063
|
+
const specifierRelativeUrl = specifierUrl.slice(packageDirectoryUrl.length);
|
|
5064
|
+
const secifierRelativeNotation = `./${specifierRelativeUrl}`;
|
|
5065
|
+
const browserMapping = browser[secifierRelativeNotation];
|
|
5066
|
+
if (typeof browserMapping === "string") {
|
|
5067
|
+
url = new URL(browserMapping, packageDirectoryUrl).href;
|
|
5068
|
+
} else if (browserMapping === false) {
|
|
5069
|
+
url = `file:///@ignore/${specifierUrl.slice("file:///")}`;
|
|
5070
|
+
}
|
|
5071
|
+
} else {
|
|
5072
|
+
const browserMapping = browser[specifier];
|
|
5073
|
+
if (typeof browserMapping === "string") {
|
|
5074
|
+
url = new URL(browserMapping, packageDirectoryUrl).href;
|
|
5075
|
+
} else if (browserMapping === false) {
|
|
5076
|
+
url = `file:///@ignore/${specifier}`;
|
|
5077
|
+
}
|
|
5078
|
+
}
|
|
5079
|
+
if (url) {
|
|
5080
|
+
return createResolutionResult({
|
|
5081
|
+
type: "field:browser",
|
|
5082
|
+
isMain: true,
|
|
5083
|
+
packageDirectoryUrl,
|
|
5084
|
+
packageJson,
|
|
5085
|
+
url,
|
|
5086
|
+
});
|
|
5087
|
+
}
|
|
5088
|
+
return null;
|
|
5446
5089
|
};
|
|
5447
5090
|
|
|
5448
|
-
|
|
5449
|
-
|
|
5450
|
-
|
|
5091
|
+
const applyPackageImportsResolution = (
|
|
5092
|
+
internalSpecifier,
|
|
5093
|
+
resolutionContext,
|
|
5094
|
+
) => {
|
|
5095
|
+
const { parentUrl, lookupPackageScope, readPackageJson } = resolutionContext;
|
|
5096
|
+
if (internalSpecifier === "#" || internalSpecifier.startsWith("#/")) {
|
|
5097
|
+
throw createInvalidModuleSpecifierError(
|
|
5098
|
+
"not a valid internal imports specifier name",
|
|
5099
|
+
internalSpecifier,
|
|
5100
|
+
resolutionContext,
|
|
5101
|
+
);
|
|
5102
|
+
}
|
|
5103
|
+
const packageDirectoryUrl = lookupPackageScope(parentUrl);
|
|
5104
|
+
if (packageDirectoryUrl !== null) {
|
|
5105
|
+
const packageJson = readPackageJson(packageDirectoryUrl);
|
|
5106
|
+
const { imports } = packageJson;
|
|
5107
|
+
if (imports !== null && typeof imports === "object") {
|
|
5108
|
+
const resolved = applyPackageImportsExportsResolution(internalSpecifier, {
|
|
5109
|
+
...resolutionContext,
|
|
5110
|
+
packageDirectoryUrl,
|
|
5111
|
+
packageJson,
|
|
5112
|
+
isImport: true,
|
|
5113
|
+
});
|
|
5114
|
+
if (resolved) {
|
|
5115
|
+
return resolved;
|
|
5116
|
+
}
|
|
5117
|
+
}
|
|
5118
|
+
}
|
|
5119
|
+
throw createPackageImportNotDefinedError(internalSpecifier, {
|
|
5120
|
+
...resolutionContext,
|
|
5121
|
+
packageDirectoryUrl,
|
|
5122
|
+
});
|
|
5451
5123
|
};
|
|
5452
5124
|
|
|
5453
|
-
const
|
|
5454
|
-
|
|
5455
|
-
|
|
5125
|
+
const applyPackageResolve = (packageSpecifier, resolutionContext) => {
|
|
5126
|
+
const { parentUrl, conditions, readPackageJson, preservesSymlink, isImport } =
|
|
5127
|
+
resolutionContext;
|
|
5128
|
+
if (packageSpecifier === "") {
|
|
5129
|
+
throw new Error("invalid module specifier");
|
|
5456
5130
|
}
|
|
5457
|
-
|
|
5458
|
-
|
|
5459
|
-
|
|
5460
|
-
|
|
5131
|
+
if (
|
|
5132
|
+
conditions.includes("node") &&
|
|
5133
|
+
isSpecifierForNodeBuiltin(packageSpecifier)
|
|
5134
|
+
) {
|
|
5135
|
+
return createResolutionResult({
|
|
5136
|
+
type: "node_builtin_specifier",
|
|
5137
|
+
url: `node:${packageSpecifier}`,
|
|
5138
|
+
});
|
|
5461
5139
|
}
|
|
5462
|
-
|
|
5463
|
-
if (
|
|
5464
|
-
|
|
5465
|
-
|
|
5140
|
+
let { packageName, packageSubpath } = parsePackageSpecifier(packageSpecifier);
|
|
5141
|
+
if (
|
|
5142
|
+
packageName[0] === "." ||
|
|
5143
|
+
packageName.includes("\\") ||
|
|
5144
|
+
packageName.includes("%")
|
|
5145
|
+
) {
|
|
5146
|
+
throw createInvalidModuleSpecifierError(
|
|
5147
|
+
`is not a valid package name`,
|
|
5148
|
+
packageName,
|
|
5149
|
+
resolutionContext,
|
|
5466
5150
|
);
|
|
5467
5151
|
}
|
|
5468
|
-
|
|
5469
|
-
|
|
5470
|
-
|
|
5471
|
-
const
|
|
5472
|
-
|
|
5473
|
-
|
|
5474
|
-
|
|
5475
|
-
|
|
5476
|
-
|
|
5477
|
-
|
|
5478
|
-
${
|
|
5479
|
-
Array.isArray(value)
|
|
5480
|
-
? value.join(`
|
|
5481
|
-
`)
|
|
5482
|
-
: value
|
|
5483
|
-
}`;
|
|
5152
|
+
if (isImport && packageSubpath.endsWith("/")) {
|
|
5153
|
+
throw new Error("invalid module specifier");
|
|
5154
|
+
}
|
|
5155
|
+
const questionCharIndex = packageName.indexOf("?");
|
|
5156
|
+
if (questionCharIndex > -1) {
|
|
5157
|
+
packageName = packageName.slice(0, questionCharIndex);
|
|
5158
|
+
}
|
|
5159
|
+
const selfResolution = applyPackageSelfResolution(packageSubpath, {
|
|
5160
|
+
...resolutionContext,
|
|
5161
|
+
packageName,
|
|
5484
5162
|
});
|
|
5485
|
-
|
|
5486
|
-
|
|
5487
|
-
};
|
|
5488
|
-
|
|
5489
|
-
const hasScheme = (string) => {
|
|
5490
|
-
return /^[a-zA-Z]{2,}:/.test(string);
|
|
5491
|
-
};
|
|
5492
|
-
|
|
5493
|
-
const pathnameToParentPathname = (pathname) => {
|
|
5494
|
-
const slashLastIndex = pathname.lastIndexOf("/");
|
|
5495
|
-
if (slashLastIndex === -1) {
|
|
5496
|
-
return "/";
|
|
5163
|
+
if (selfResolution) {
|
|
5164
|
+
return selfResolution;
|
|
5497
5165
|
}
|
|
5498
|
-
|
|
5499
|
-
|
|
5500
|
-
|
|
5501
|
-
|
|
5502
|
-
|
|
5503
|
-
|
|
5504
|
-
|
|
5505
|
-
|
|
5166
|
+
let currentUrl = parentUrl;
|
|
5167
|
+
while (currentUrl !== "file:///") {
|
|
5168
|
+
const packageDirectoryFacadeUrl = new URL(
|
|
5169
|
+
`node_modules/${packageName}/`,
|
|
5170
|
+
currentUrl,
|
|
5171
|
+
).href;
|
|
5172
|
+
if (!existsSync(new URL(packageDirectoryFacadeUrl))) {
|
|
5173
|
+
currentUrl = getParentUrl(currentUrl);
|
|
5174
|
+
continue;
|
|
5175
|
+
}
|
|
5176
|
+
const packageDirectoryUrl = preservesSymlink
|
|
5177
|
+
? packageDirectoryFacadeUrl
|
|
5178
|
+
: resolvePackageSymlink(packageDirectoryFacadeUrl);
|
|
5179
|
+
const packageJson = readPackageJson(packageDirectoryUrl);
|
|
5180
|
+
if (packageJson !== null) {
|
|
5181
|
+
const { exports: exports$1 } = packageJson;
|
|
5182
|
+
if (exports$1 !== null && exports$1 !== undefined) {
|
|
5183
|
+
return applyPackageExportsResolution(packageSubpath, {
|
|
5184
|
+
...resolutionContext,
|
|
5185
|
+
packageDirectoryUrl,
|
|
5186
|
+
packageJson,
|
|
5187
|
+
exports: exports$1,
|
|
5188
|
+
});
|
|
5189
|
+
}
|
|
5190
|
+
}
|
|
5191
|
+
return applyLegacySubpathResolution(packageSubpath, {
|
|
5192
|
+
...resolutionContext,
|
|
5193
|
+
packageDirectoryUrl,
|
|
5194
|
+
packageJson,
|
|
5195
|
+
});
|
|
5196
|
+
}
|
|
5197
|
+
throw createModuleNotFoundError(packageName, resolutionContext);
|
|
5506
5198
|
};
|
|
5507
5199
|
|
|
5508
|
-
const
|
|
5509
|
-
const
|
|
5510
|
-
|
|
5511
|
-
|
|
5512
|
-
|
|
5200
|
+
const applyPackageSelfResolution = (packageSubpath, resolutionContext) => {
|
|
5201
|
+
const { parentUrl, packageName, lookupPackageScope, readPackageJson } =
|
|
5202
|
+
resolutionContext;
|
|
5203
|
+
const packageDirectoryUrl = lookupPackageScope(parentUrl);
|
|
5204
|
+
if (!packageDirectoryUrl) {
|
|
5205
|
+
return undefined;
|
|
5513
5206
|
}
|
|
5514
|
-
|
|
5515
|
-
if (
|
|
5516
|
-
|
|
5517
|
-
const pathnameSlashIndex = urlString.indexOf("/", secondProtocolSlashIndex);
|
|
5518
|
-
|
|
5519
|
-
if (pathnameSlashIndex === -1) return urlString;
|
|
5520
|
-
return urlString.slice(0, pathnameSlashIndex);
|
|
5207
|
+
const packageJson = readPackageJson(packageDirectoryUrl);
|
|
5208
|
+
if (!packageJson) {
|
|
5209
|
+
return undefined;
|
|
5521
5210
|
}
|
|
5522
|
-
|
|
5523
|
-
|
|
5524
|
-
}
|
|
5525
|
-
|
|
5526
|
-
|
|
5527
|
-
|
|
5211
|
+
if (packageJson.name !== packageName) {
|
|
5212
|
+
return undefined;
|
|
5213
|
+
}
|
|
5214
|
+
const { exports: exports$1 } = packageJson;
|
|
5215
|
+
if (!exports$1) {
|
|
5216
|
+
const subpathResolution = applyLegacySubpathResolution(packageSubpath, {
|
|
5217
|
+
...resolutionContext,
|
|
5218
|
+
packageDirectoryUrl,
|
|
5219
|
+
packageJson,
|
|
5220
|
+
});
|
|
5221
|
+
if (subpathResolution && subpathResolution.type !== "subpath") {
|
|
5222
|
+
return subpathResolution;
|
|
5223
|
+
}
|
|
5224
|
+
return undefined;
|
|
5225
|
+
}
|
|
5226
|
+
return applyPackageExportsResolution(packageSubpath, {
|
|
5227
|
+
...resolutionContext,
|
|
5228
|
+
packageDirectoryUrl,
|
|
5229
|
+
packageJson,
|
|
5230
|
+
});
|
|
5528
5231
|
};
|
|
5529
5232
|
|
|
5530
|
-
|
|
5531
|
-
|
|
5532
|
-
|
|
5533
|
-
|
|
5534
|
-
|
|
5233
|
+
// https://github.com/nodejs/node/blob/0367b5c35ea0f98b323175a4aaa8e651af7a91e7/lib/internal/modules/esm/resolve.js#L642
|
|
5234
|
+
const applyPackageExportsResolution = (packageSubpath, resolutionContext) => {
|
|
5235
|
+
if (packageSubpath === ".") {
|
|
5236
|
+
const mainExport = applyMainExportResolution(resolutionContext);
|
|
5237
|
+
if (!mainExport) {
|
|
5238
|
+
throw createPackagePathNotExportedError(
|
|
5239
|
+
packageSubpath,
|
|
5240
|
+
resolutionContext,
|
|
5241
|
+
);
|
|
5242
|
+
}
|
|
5243
|
+
const resolved = applyPackageTargetResolution(mainExport, {
|
|
5244
|
+
...resolutionContext,
|
|
5245
|
+
key: ".",
|
|
5246
|
+
});
|
|
5247
|
+
if (resolved) {
|
|
5248
|
+
return resolved;
|
|
5249
|
+
}
|
|
5250
|
+
throw createPackagePathNotExportedError(packageSubpath, resolutionContext);
|
|
5535
5251
|
}
|
|
5536
|
-
|
|
5537
|
-
if (
|
|
5538
|
-
|
|
5539
|
-
|
|
5540
|
-
|
|
5541
|
-
|
|
5252
|
+
const packageExportsInfo = readExports(resolutionContext);
|
|
5253
|
+
if (
|
|
5254
|
+
packageExportsInfo.type === "object" &&
|
|
5255
|
+
packageExportsInfo.allKeysAreRelative
|
|
5256
|
+
) {
|
|
5257
|
+
const resolved = applyPackageImportsExportsResolution(packageSubpath, {
|
|
5258
|
+
...resolutionContext,
|
|
5259
|
+
isImport: false,
|
|
5260
|
+
});
|
|
5261
|
+
if (resolved) {
|
|
5262
|
+
return resolved;
|
|
5263
|
+
}
|
|
5542
5264
|
}
|
|
5543
|
-
|
|
5544
|
-
return urlString.slice(scheme.length + 1);
|
|
5265
|
+
throw createPackagePathNotExportedError(packageSubpath, resolutionContext);
|
|
5545
5266
|
};
|
|
5546
5267
|
|
|
5547
|
-
const
|
|
5548
|
-
const
|
|
5549
|
-
|
|
5550
|
-
? ressource
|
|
5551
|
-
: ressource.slice(0, searchSeparatorIndex);
|
|
5552
|
-
};
|
|
5268
|
+
const applyPackageImportsExportsResolution = (matchKey, resolutionContext) => {
|
|
5269
|
+
const { packageJson, isImport } = resolutionContext;
|
|
5270
|
+
const matchObject = isImport ? packageJson.imports : packageJson.exports;
|
|
5553
5271
|
|
|
5554
|
-
|
|
5272
|
+
if (!matchKey.includes("*") && matchObject.hasOwnProperty(matchKey)) {
|
|
5273
|
+
const target = matchObject[matchKey];
|
|
5274
|
+
return applyPackageTargetResolution(target, {
|
|
5275
|
+
...resolutionContext,
|
|
5276
|
+
key: matchKey,
|
|
5277
|
+
isImport,
|
|
5278
|
+
});
|
|
5279
|
+
}
|
|
5280
|
+
const expansionKeys = Object.keys(matchObject)
|
|
5281
|
+
.filter((key) => key.split("*").length === 2)
|
|
5282
|
+
.sort(comparePatternKeys);
|
|
5283
|
+
for (const expansionKey of expansionKeys) {
|
|
5284
|
+
const [patternBase, patternTrailer] = expansionKey.split("*");
|
|
5285
|
+
if (matchKey === patternBase) continue;
|
|
5286
|
+
if (!matchKey.startsWith(patternBase)) continue;
|
|
5287
|
+
if (patternTrailer.length > 0) {
|
|
5288
|
+
if (!matchKey.endsWith(patternTrailer)) continue;
|
|
5289
|
+
if (matchKey.length < expansionKey.length) continue;
|
|
5290
|
+
}
|
|
5291
|
+
const target = matchObject[expansionKey];
|
|
5292
|
+
const subpath = matchKey.slice(
|
|
5293
|
+
patternBase.length,
|
|
5294
|
+
matchKey.length - patternTrailer.length,
|
|
5295
|
+
);
|
|
5296
|
+
return applyPackageTargetResolution(target, {
|
|
5297
|
+
...resolutionContext,
|
|
5298
|
+
key: matchKey,
|
|
5299
|
+
subpath,
|
|
5300
|
+
pattern: true,
|
|
5301
|
+
isImport,
|
|
5302
|
+
});
|
|
5303
|
+
}
|
|
5304
|
+
return null;
|
|
5305
|
+
};
|
|
5555
5306
|
|
|
5307
|
+
const applyPackageTargetResolution = (target, resolutionContext) => {
|
|
5308
|
+
const {
|
|
5309
|
+
conditions,
|
|
5310
|
+
packageDirectoryUrl,
|
|
5311
|
+
packageJson,
|
|
5312
|
+
key,
|
|
5313
|
+
subpath = "",
|
|
5314
|
+
pattern = false,
|
|
5315
|
+
isImport = false,
|
|
5316
|
+
} = resolutionContext;
|
|
5556
5317
|
|
|
5557
|
-
|
|
5558
|
-
|
|
5559
|
-
|
|
5560
|
-
throw new TypeError(writeBaseUrlMustBeAString({ baseUrl, specifier }));
|
|
5318
|
+
if (typeof target === "string") {
|
|
5319
|
+
if (pattern === false && subpath !== "" && !target.endsWith("/")) {
|
|
5320
|
+
throw new Error("invalid module specifier");
|
|
5561
5321
|
}
|
|
5562
|
-
if (
|
|
5563
|
-
|
|
5322
|
+
if (target.startsWith("./")) {
|
|
5323
|
+
const targetUrl = new URL(target, packageDirectoryUrl).href;
|
|
5324
|
+
if (!targetUrl.startsWith(packageDirectoryUrl)) {
|
|
5325
|
+
throw createInvalidPackageTargetError(
|
|
5326
|
+
`target must be inside package`,
|
|
5327
|
+
target,
|
|
5328
|
+
resolutionContext,
|
|
5329
|
+
);
|
|
5330
|
+
}
|
|
5331
|
+
return createResolutionResult({
|
|
5332
|
+
type: isImport ? "field:imports" : "field:exports",
|
|
5333
|
+
isMain: subpath === "" || subpath === ".",
|
|
5334
|
+
packageDirectoryUrl,
|
|
5335
|
+
packageJson,
|
|
5336
|
+
url: pattern
|
|
5337
|
+
? targetUrl.replaceAll("*", subpath)
|
|
5338
|
+
: new URL(subpath, targetUrl).href,
|
|
5339
|
+
});
|
|
5564
5340
|
}
|
|
5341
|
+
if (!isImport || target.startsWith("../") || isValidUrl(target)) {
|
|
5342
|
+
throw createInvalidPackageTargetError(
|
|
5343
|
+
`target must starst with "./"`,
|
|
5344
|
+
target,
|
|
5345
|
+
resolutionContext,
|
|
5346
|
+
);
|
|
5347
|
+
}
|
|
5348
|
+
return applyPackageResolve(
|
|
5349
|
+
pattern ? target.replaceAll("*", subpath) : `${target}${subpath}`,
|
|
5350
|
+
{
|
|
5351
|
+
...resolutionContext,
|
|
5352
|
+
parentUrl: packageDirectoryUrl,
|
|
5353
|
+
},
|
|
5354
|
+
);
|
|
5565
5355
|
}
|
|
5566
|
-
|
|
5567
|
-
|
|
5568
|
-
|
|
5569
|
-
|
|
5570
|
-
|
|
5571
|
-
|
|
5572
|
-
|
|
5356
|
+
if (Array.isArray(target)) {
|
|
5357
|
+
if (target.length === 0) {
|
|
5358
|
+
return null;
|
|
5359
|
+
}
|
|
5360
|
+
let lastResult;
|
|
5361
|
+
let i = 0;
|
|
5362
|
+
while (i < target.length) {
|
|
5363
|
+
const targetValue = target[i];
|
|
5364
|
+
i++;
|
|
5365
|
+
try {
|
|
5366
|
+
const resolved = applyPackageTargetResolution(targetValue, {
|
|
5367
|
+
...resolutionContext,
|
|
5368
|
+
key: `${key}[${i}]`,
|
|
5369
|
+
subpath,
|
|
5370
|
+
pattern,
|
|
5371
|
+
isImport,
|
|
5372
|
+
});
|
|
5373
|
+
if (resolved) {
|
|
5374
|
+
return resolved;
|
|
5375
|
+
}
|
|
5376
|
+
lastResult = resolved;
|
|
5377
|
+
} catch (e) {
|
|
5378
|
+
if (e.code === "INVALID_PACKAGE_TARGET") {
|
|
5379
|
+
continue;
|
|
5380
|
+
}
|
|
5381
|
+
lastResult = e;
|
|
5382
|
+
}
|
|
5383
|
+
}
|
|
5384
|
+
if (lastResult) {
|
|
5385
|
+
throw lastResult;
|
|
5386
|
+
}
|
|
5387
|
+
return null;
|
|
5573
5388
|
}
|
|
5574
|
-
|
|
5575
|
-
|
|
5576
|
-
if (specifier.slice(0, 2) === "//") {
|
|
5577
|
-
return `${urlToScheme(baseUrl)}:${specifier}`;
|
|
5389
|
+
if (target === null) {
|
|
5390
|
+
return null;
|
|
5578
5391
|
}
|
|
5579
|
-
|
|
5580
|
-
|
|
5581
|
-
|
|
5582
|
-
|
|
5392
|
+
if (typeof target === "object") {
|
|
5393
|
+
const keys = Object.keys(target);
|
|
5394
|
+
for (const key of keys) {
|
|
5395
|
+
if (Number.isInteger(key)) {
|
|
5396
|
+
throw new Error("Invalid package configuration");
|
|
5397
|
+
}
|
|
5398
|
+
let matched;
|
|
5399
|
+
if (key === "default") {
|
|
5400
|
+
matched = true;
|
|
5401
|
+
} else {
|
|
5402
|
+
for (const conditionCandidate of conditions) {
|
|
5403
|
+
if (conditionCandidate === key) {
|
|
5404
|
+
matched = true;
|
|
5405
|
+
break;
|
|
5406
|
+
}
|
|
5407
|
+
if (conditionCandidate.includes("*")) {
|
|
5408
|
+
const conditionCandidateRegex = new RegExp(
|
|
5409
|
+
`^${conditionCandidate.replace(/\*/g, "(.*)")}$`,
|
|
5410
|
+
);
|
|
5411
|
+
if (conditionCandidateRegex.test(key)) {
|
|
5412
|
+
matched = true;
|
|
5413
|
+
break;
|
|
5414
|
+
}
|
|
5415
|
+
}
|
|
5416
|
+
}
|
|
5417
|
+
}
|
|
5418
|
+
if (matched) {
|
|
5419
|
+
const targetValue = target[key];
|
|
5420
|
+
const resolved = applyPackageTargetResolution(targetValue, {
|
|
5421
|
+
...resolutionContext,
|
|
5422
|
+
key,
|
|
5423
|
+
subpath,
|
|
5424
|
+
pattern,
|
|
5425
|
+
isImport,
|
|
5426
|
+
});
|
|
5427
|
+
if (resolved) {
|
|
5428
|
+
return resolved;
|
|
5429
|
+
}
|
|
5430
|
+
}
|
|
5431
|
+
}
|
|
5432
|
+
return null;
|
|
5583
5433
|
}
|
|
5434
|
+
throw createInvalidPackageTargetError(
|
|
5435
|
+
`target must be a string, array, object or null`,
|
|
5436
|
+
target,
|
|
5437
|
+
resolutionContext,
|
|
5438
|
+
);
|
|
5439
|
+
};
|
|
5584
5440
|
|
|
5585
|
-
|
|
5586
|
-
const
|
|
5587
|
-
|
|
5588
|
-
|
|
5589
|
-
|
|
5590
|
-
|
|
5441
|
+
const readExports = ({ packageDirectoryUrl, packageJson }) => {
|
|
5442
|
+
const packageExports = packageJson.exports;
|
|
5443
|
+
if (Array.isArray(packageExports)) {
|
|
5444
|
+
return {
|
|
5445
|
+
type: "array",
|
|
5446
|
+
};
|
|
5591
5447
|
}
|
|
5592
|
-
|
|
5593
|
-
|
|
5594
|
-
if (specifier.slice(0, 2) === "./") {
|
|
5595
|
-
const baseDirectoryPathname = pathnameToParentPathname(basePathname);
|
|
5596
|
-
return `${baseOrigin}${baseDirectoryPathname}${specifier.slice(2)}`;
|
|
5448
|
+
if (packageExports === null) {
|
|
5449
|
+
return {};
|
|
5597
5450
|
}
|
|
5598
|
-
|
|
5599
|
-
|
|
5600
|
-
|
|
5601
|
-
|
|
5602
|
-
|
|
5603
|
-
|
|
5604
|
-
|
|
5605
|
-
|
|
5606
|
-
|
|
5607
|
-
// when there is no folder left to resolved
|
|
5608
|
-
// we just ignore '../'
|
|
5609
|
-
if (importerFolders.length) {
|
|
5610
|
-
importerFolders.pop();
|
|
5451
|
+
if (typeof packageExports === "object") {
|
|
5452
|
+
const keys = Object.keys(packageExports);
|
|
5453
|
+
const relativeKeys = [];
|
|
5454
|
+
const conditionalKeys = [];
|
|
5455
|
+
keys.forEach((availableKey) => {
|
|
5456
|
+
if (availableKey.startsWith(".")) {
|
|
5457
|
+
relativeKeys.push(availableKey);
|
|
5458
|
+
} else {
|
|
5459
|
+
conditionalKeys.push(availableKey);
|
|
5611
5460
|
}
|
|
5461
|
+
});
|
|
5462
|
+
const hasRelativeKey = relativeKeys.length > 0;
|
|
5463
|
+
if (hasRelativeKey && conditionalKeys.length > 0) {
|
|
5464
|
+
throw new Error(
|
|
5465
|
+
`Invalid package configuration: cannot mix relative and conditional keys in package.exports
|
|
5466
|
+
--- unexpected keys ---
|
|
5467
|
+
${conditionalKeys.map((key) => `"${key}"`).join("\n")}
|
|
5468
|
+
--- package directory url ---
|
|
5469
|
+
${packageDirectoryUrl}`,
|
|
5470
|
+
);
|
|
5612
5471
|
}
|
|
5613
|
-
|
|
5614
|
-
|
|
5615
|
-
|
|
5616
|
-
|
|
5617
|
-
|
|
5618
|
-
}
|
|
5619
|
-
|
|
5620
|
-
// bare
|
|
5621
|
-
if (basePathname === "") {
|
|
5622
|
-
return `${baseOrigin}/${specifier}`;
|
|
5472
|
+
return {
|
|
5473
|
+
type: "object",
|
|
5474
|
+
hasRelativeKey,
|
|
5475
|
+
allKeysAreRelative: relativeKeys.length === keys.length,
|
|
5476
|
+
};
|
|
5623
5477
|
}
|
|
5624
|
-
if (
|
|
5625
|
-
return
|
|
5478
|
+
if (typeof packageExports === "string") {
|
|
5479
|
+
return { type: "string" };
|
|
5626
5480
|
}
|
|
5627
|
-
return
|
|
5481
|
+
return {};
|
|
5628
5482
|
};
|
|
5629
5483
|
|
|
5630
|
-
const
|
|
5631
|
-
|
|
5632
|
-
|
|
5633
|
-
|
|
5634
|
-
|
|
5635
|
-
|
|
5636
|
-
|
|
5637
|
-
|
|
5638
|
-
|
|
5639
|
-
|
|
5640
|
-
|
|
5641
|
-
|
|
5642
|
-
}
|
|
5643
|
-
|
|
5644
|
-
|
|
5645
|
-
|
|
5646
|
-
|
|
5647
|
-
|
|
5648
|
-
|
|
5649
|
-
|
|
5650
|
-
|
|
5651
|
-
}
|
|
5652
|
-
|
|
5653
|
-
|
|
5654
|
-
|
|
5655
|
-
|
|
5656
|
-
|
|
5657
|
-
|
|
5658
|
-
|
|
5659
|
-
|
|
5484
|
+
const parsePackageSpecifier = (packageSpecifier) => {
|
|
5485
|
+
if (packageSpecifier[0] === "@") {
|
|
5486
|
+
const firstSlashIndex = packageSpecifier.indexOf("/");
|
|
5487
|
+
if (firstSlashIndex === -1) {
|
|
5488
|
+
throw new Error("invalid module specifier");
|
|
5489
|
+
}
|
|
5490
|
+
const secondSlashIndex = packageSpecifier.indexOf("/", firstSlashIndex + 1);
|
|
5491
|
+
if (secondSlashIndex === -1) {
|
|
5492
|
+
return {
|
|
5493
|
+
packageName: packageSpecifier,
|
|
5494
|
+
packageSubpath: ".",
|
|
5495
|
+
isScoped: true,
|
|
5496
|
+
};
|
|
5497
|
+
}
|
|
5498
|
+
const packageName = packageSpecifier.slice(0, secondSlashIndex);
|
|
5499
|
+
const afterSecondSlash = packageSpecifier.slice(secondSlashIndex + 1);
|
|
5500
|
+
const packageSubpath = `./${afterSecondSlash}`;
|
|
5501
|
+
return {
|
|
5502
|
+
packageName,
|
|
5503
|
+
packageSubpath,
|
|
5504
|
+
isScoped: true,
|
|
5505
|
+
};
|
|
5506
|
+
}
|
|
5507
|
+
const firstSlashIndex = packageSpecifier.indexOf("/");
|
|
5508
|
+
if (firstSlashIndex === -1) {
|
|
5509
|
+
return {
|
|
5510
|
+
packageName: packageSpecifier,
|
|
5511
|
+
packageSubpath: ".",
|
|
5512
|
+
};
|
|
5513
|
+
}
|
|
5514
|
+
const packageName = packageSpecifier.slice(0, firstSlashIndex);
|
|
5515
|
+
const afterFirstSlash = packageSpecifier.slice(firstSlashIndex + 1);
|
|
5516
|
+
if (afterFirstSlash === "") {
|
|
5517
|
+
return {
|
|
5518
|
+
packageName,
|
|
5519
|
+
packageSubpath: "/",
|
|
5520
|
+
};
|
|
5521
|
+
}
|
|
5522
|
+
const packageSubpath = `./${afterFirstSlash}`;
|
|
5523
|
+
return {
|
|
5524
|
+
packageName,
|
|
5525
|
+
packageSubpath,
|
|
5526
|
+
};
|
|
5660
5527
|
};
|
|
5661
5528
|
|
|
5662
|
-
const
|
|
5529
|
+
const applyMainExportResolution = (resolutionContext) => {
|
|
5530
|
+
const { packageJson } = resolutionContext;
|
|
5531
|
+
const packageExportsInfo = readExports(resolutionContext);
|
|
5663
5532
|
if (
|
|
5664
|
-
|
|
5665
|
-
|
|
5666
|
-
specifier.startsWith("./") ||
|
|
5667
|
-
specifier.startsWith("../")
|
|
5533
|
+
packageExportsInfo.type === "array" ||
|
|
5534
|
+
packageExportsInfo.type === "string"
|
|
5668
5535
|
) {
|
|
5669
|
-
return
|
|
5536
|
+
return packageJson.exports;
|
|
5670
5537
|
}
|
|
5671
|
-
|
|
5672
|
-
|
|
5673
|
-
|
|
5538
|
+
if (packageExportsInfo.type === "object") {
|
|
5539
|
+
if (packageExportsInfo.hasRelativeKey) {
|
|
5540
|
+
return packageJson.exports["."];
|
|
5541
|
+
}
|
|
5542
|
+
return packageJson.exports;
|
|
5674
5543
|
}
|
|
5675
|
-
|
|
5676
|
-
return null;
|
|
5544
|
+
return undefined;
|
|
5677
5545
|
};
|
|
5678
5546
|
|
|
5679
|
-
const
|
|
5680
|
-
|
|
5681
|
-
|
|
5682
|
-
|
|
5683
|
-
|
|
5684
|
-
return new Error(
|
|
5685
|
-
createDetailedMessage(`Unmapped bare specifier.`, {
|
|
5686
|
-
specifier,
|
|
5687
|
-
importer,
|
|
5688
|
-
}),
|
|
5689
|
-
);
|
|
5690
|
-
},
|
|
5691
|
-
onImportMapping = () => {},
|
|
5692
|
-
}) => {
|
|
5693
|
-
assertImportMap(importMap);
|
|
5694
|
-
if (typeof specifier !== "string") {
|
|
5695
|
-
throw new TypeError(
|
|
5696
|
-
createDetailedMessage("specifier must be a string.", {
|
|
5697
|
-
specifier,
|
|
5698
|
-
importer,
|
|
5699
|
-
}),
|
|
5700
|
-
);
|
|
5547
|
+
const applyLegacySubpathResolution = (packageSubpath, resolutionContext) => {
|
|
5548
|
+
const { packageDirectoryUrl, packageJson } = resolutionContext;
|
|
5549
|
+
|
|
5550
|
+
if (packageSubpath === ".") {
|
|
5551
|
+
return applyLegacyMainResolution(packageSubpath, resolutionContext);
|
|
5701
5552
|
}
|
|
5702
|
-
|
|
5703
|
-
|
|
5704
|
-
|
|
5705
|
-
|
|
5706
|
-
|
|
5707
|
-
|
|
5708
|
-
|
|
5709
|
-
|
|
5553
|
+
const browserFieldResolution = applyBrowserFieldResolution(
|
|
5554
|
+
packageSubpath,
|
|
5555
|
+
resolutionContext,
|
|
5556
|
+
);
|
|
5557
|
+
if (browserFieldResolution) {
|
|
5558
|
+
return browserFieldResolution;
|
|
5559
|
+
}
|
|
5560
|
+
return createResolutionResult({
|
|
5561
|
+
type: "subpath",
|
|
5562
|
+
isMain: packageSubpath === ".",
|
|
5563
|
+
packageDirectoryUrl,
|
|
5564
|
+
packageJson,
|
|
5565
|
+
url: new URL(packageSubpath, packageDirectoryUrl).href,
|
|
5566
|
+
});
|
|
5567
|
+
};
|
|
5568
|
+
|
|
5569
|
+
const applyLegacyMainResolution = (packageSubpath, resolutionContext) => {
|
|
5570
|
+
const { conditions, packageDirectoryUrl, packageJson } = resolutionContext;
|
|
5571
|
+
for (const condition of conditions) {
|
|
5572
|
+
const conditionResolver = mainLegacyResolvers[condition];
|
|
5573
|
+
if (!conditionResolver) {
|
|
5574
|
+
continue;
|
|
5710
5575
|
}
|
|
5711
|
-
|
|
5712
|
-
|
|
5713
|
-
|
|
5714
|
-
|
|
5715
|
-
|
|
5716
|
-
|
|
5717
|
-
|
|
5576
|
+
const resolved = conditionResolver(resolutionContext);
|
|
5577
|
+
if (resolved) {
|
|
5578
|
+
return createResolutionResult({
|
|
5579
|
+
type: resolved.type,
|
|
5580
|
+
isMain: resolved.isMain,
|
|
5581
|
+
packageDirectoryUrl,
|
|
5582
|
+
packageJson,
|
|
5583
|
+
url: new URL(resolved.path, packageDirectoryUrl).href,
|
|
5584
|
+
});
|
|
5718
5585
|
}
|
|
5719
5586
|
}
|
|
5587
|
+
return createResolutionResult({
|
|
5588
|
+
type: "field:main", // the absence of "main" field
|
|
5589
|
+
isMain: true,
|
|
5590
|
+
packageDirectoryUrl,
|
|
5591
|
+
packageJson,
|
|
5592
|
+
url: new URL("index.js", packageDirectoryUrl).href,
|
|
5593
|
+
});
|
|
5594
|
+
};
|
|
5595
|
+
const mainLegacyResolvers = {
|
|
5596
|
+
import: ({ packageJson }) => {
|
|
5597
|
+
if (typeof packageJson.module === "string") {
|
|
5598
|
+
return { type: "field:module", isMain: true, path: packageJson.module };
|
|
5599
|
+
}
|
|
5600
|
+
if (typeof packageJson.jsnext === "string") {
|
|
5601
|
+
return { type: "field:jsnext", isMain: true, path: packageJson.jsnext };
|
|
5602
|
+
}
|
|
5603
|
+
if (typeof packageJson.main === "string") {
|
|
5604
|
+
return { type: "field:main", isMain: true, path: packageJson.main };
|
|
5605
|
+
}
|
|
5606
|
+
return null;
|
|
5607
|
+
},
|
|
5608
|
+
browser: ({ packageDirectoryUrl, packageJson }) => {
|
|
5609
|
+
const browserMain = (() => {
|
|
5610
|
+
if (typeof packageJson.browser === "string") {
|
|
5611
|
+
return packageJson.browser;
|
|
5612
|
+
}
|
|
5613
|
+
if (
|
|
5614
|
+
typeof packageJson.browser === "object" &&
|
|
5615
|
+
packageJson.browser !== null
|
|
5616
|
+
) {
|
|
5617
|
+
return packageJson.browser["."];
|
|
5618
|
+
}
|
|
5619
|
+
return "";
|
|
5620
|
+
})();
|
|
5720
5621
|
|
|
5721
|
-
|
|
5722
|
-
|
|
5723
|
-
|
|
5724
|
-
|
|
5725
|
-
|
|
5726
|
-
|
|
5727
|
-
|
|
5728
|
-
|
|
5729
|
-
|
|
5730
|
-
|
|
5731
|
-
|
|
5732
|
-
|
|
5733
|
-
|
|
5734
|
-
|
|
5735
|
-
|
|
5736
|
-
|
|
5737
|
-
|
|
5738
|
-
|
|
5739
|
-
|
|
5740
|
-
|
|
5741
|
-
|
|
5742
|
-
|
|
5743
|
-
|
|
5622
|
+
if (!browserMain) {
|
|
5623
|
+
if (typeof packageJson.module === "string") {
|
|
5624
|
+
return {
|
|
5625
|
+
type: "field:module",
|
|
5626
|
+
isMain: true,
|
|
5627
|
+
path: packageJson.module,
|
|
5628
|
+
};
|
|
5629
|
+
}
|
|
5630
|
+
return null;
|
|
5631
|
+
}
|
|
5632
|
+
if (
|
|
5633
|
+
typeof packageJson.module !== "string" ||
|
|
5634
|
+
packageJson.module === browserMain
|
|
5635
|
+
) {
|
|
5636
|
+
return {
|
|
5637
|
+
type: "field:browser",
|
|
5638
|
+
isMain: true,
|
|
5639
|
+
path: browserMain,
|
|
5640
|
+
};
|
|
5641
|
+
}
|
|
5642
|
+
const browserMainUrlObject = new URL(browserMain, packageDirectoryUrl);
|
|
5643
|
+
const content = readFileSync(browserMainUrlObject, "utf-8");
|
|
5644
|
+
if (
|
|
5645
|
+
(/typeof exports\s*==/.test(content) &&
|
|
5646
|
+
/typeof module\s*==/.test(content)) ||
|
|
5647
|
+
/module\.exports\s*=/.test(content)
|
|
5648
|
+
) {
|
|
5649
|
+
return {
|
|
5650
|
+
type: "field:module",
|
|
5651
|
+
isMain: true,
|
|
5652
|
+
path: packageJson.module,
|
|
5653
|
+
};
|
|
5654
|
+
}
|
|
5655
|
+
return {
|
|
5656
|
+
type: "field:browser",
|
|
5657
|
+
isMain: true,
|
|
5658
|
+
path: browserMain,
|
|
5659
|
+
};
|
|
5660
|
+
},
|
|
5661
|
+
node: ({ packageJson, conditions }) => {
|
|
5662
|
+
if (conditions.includes("import") && !conditions.includes("require")) {
|
|
5663
|
+
if (typeof packageJson.module === "string") {
|
|
5664
|
+
return { type: "field:module", isMain: true, path: packageJson.module };
|
|
5665
|
+
}
|
|
5666
|
+
if (typeof packageJson.jsnext === "string") {
|
|
5667
|
+
return { type: "field:jsnext", isMain: true, path: packageJson.jsnext };
|
|
5744
5668
|
}
|
|
5745
5669
|
}
|
|
5670
|
+
if (typeof packageJson.main === "string") {
|
|
5671
|
+
return { type: "field:main", isMain: true, path: packageJson.main };
|
|
5672
|
+
}
|
|
5673
|
+
return null;
|
|
5674
|
+
},
|
|
5675
|
+
};
|
|
5676
|
+
mainLegacyResolvers.require = mainLegacyResolvers.node;
|
|
5677
|
+
|
|
5678
|
+
const comparePatternKeys = (keyA, keyB) => {
|
|
5679
|
+
if (!keyA.endsWith("/") && !keyA.includes("*")) {
|
|
5680
|
+
throw new Error("Invalid package configuration");
|
|
5681
|
+
}
|
|
5682
|
+
if (!keyB.endsWith("/") && !keyB.includes("*")) {
|
|
5683
|
+
throw new Error("Invalid package configuration");
|
|
5684
|
+
}
|
|
5685
|
+
const aStarIndex = keyA.indexOf("*");
|
|
5686
|
+
const baseLengthA = aStarIndex > -1 ? aStarIndex + 1 : keyA.length;
|
|
5687
|
+
const bStarIndex = keyB.indexOf("*");
|
|
5688
|
+
const baseLengthB = bStarIndex > -1 ? bStarIndex + 1 : keyB.length;
|
|
5689
|
+
if (baseLengthA > baseLengthB) {
|
|
5690
|
+
return -1;
|
|
5746
5691
|
}
|
|
5747
|
-
|
|
5748
|
-
|
|
5749
|
-
if (imports) {
|
|
5750
|
-
const mappingFromImports = applyMappings(
|
|
5751
|
-
imports,
|
|
5752
|
-
specifierNormalized,
|
|
5753
|
-
undefined,
|
|
5754
|
-
onImportMapping,
|
|
5755
|
-
);
|
|
5756
|
-
if (mappingFromImports !== null) {
|
|
5757
|
-
return mappingFromImports;
|
|
5758
|
-
}
|
|
5692
|
+
if (baseLengthB > baseLengthA) {
|
|
5693
|
+
return 1;
|
|
5759
5694
|
}
|
|
5760
|
-
|
|
5761
|
-
|
|
5762
|
-
|
|
5695
|
+
if (aStarIndex === -1) {
|
|
5696
|
+
return 1;
|
|
5697
|
+
}
|
|
5698
|
+
if (bStarIndex === -1) {
|
|
5699
|
+
return -1;
|
|
5700
|
+
}
|
|
5701
|
+
if (keyA.length > keyB.length) {
|
|
5702
|
+
return -1;
|
|
5703
|
+
}
|
|
5704
|
+
if (keyB.length > keyA.length) {
|
|
5705
|
+
return 1;
|
|
5763
5706
|
}
|
|
5707
|
+
return 0;
|
|
5708
|
+
};
|
|
5764
5709
|
|
|
5765
|
-
|
|
5710
|
+
const resolvePackageSymlink = (packageDirectoryUrl) => {
|
|
5711
|
+
const packageDirectoryPath = realpathSync(new URL(packageDirectoryUrl));
|
|
5712
|
+
const packageDirectoryResolvedUrl = pathToFileURL(packageDirectoryPath).href;
|
|
5713
|
+
return `${packageDirectoryResolvedUrl}/`;
|
|
5766
5714
|
};
|
|
5767
5715
|
|
|
5768
|
-
const
|
|
5769
|
-
|
|
5770
|
-
|
|
5771
|
-
scope,
|
|
5772
|
-
onImportMapping,
|
|
5716
|
+
const applyFileSystemMagicResolution = (
|
|
5717
|
+
fileUrl,
|
|
5718
|
+
{ fileStat, magicDirectoryIndex, magicExtensions },
|
|
5773
5719
|
) => {
|
|
5774
|
-
const
|
|
5720
|
+
const result = {
|
|
5721
|
+
stat: null,
|
|
5722
|
+
url: fileUrl,
|
|
5723
|
+
magicExtension: "",
|
|
5724
|
+
magicDirectoryIndex: false,
|
|
5725
|
+
lastENOENTError: null,
|
|
5726
|
+
};
|
|
5775
5727
|
|
|
5776
|
-
|
|
5777
|
-
|
|
5778
|
-
|
|
5779
|
-
|
|
5780
|
-
|
|
5781
|
-
|
|
5782
|
-
|
|
5783
|
-
|
|
5784
|
-
|
|
5785
|
-
|
|
5786
|
-
before: specifierNormalized,
|
|
5787
|
-
after: address,
|
|
5788
|
-
});
|
|
5789
|
-
return address;
|
|
5728
|
+
if (fileStat === undefined) {
|
|
5729
|
+
try {
|
|
5730
|
+
fileStat = readEntryStatSync(new URL(fileUrl));
|
|
5731
|
+
} catch (e) {
|
|
5732
|
+
if (e.code === "ENOENT") {
|
|
5733
|
+
result.lastENOENTError = e;
|
|
5734
|
+
fileStat = null;
|
|
5735
|
+
} else {
|
|
5736
|
+
throw e;
|
|
5737
|
+
}
|
|
5790
5738
|
}
|
|
5791
|
-
|
|
5792
|
-
|
|
5793
|
-
|
|
5794
|
-
|
|
5795
|
-
|
|
5796
|
-
|
|
5797
|
-
|
|
5798
|
-
|
|
5799
|
-
|
|
5800
|
-
|
|
5801
|
-
|
|
5802
|
-
|
|
5739
|
+
}
|
|
5740
|
+
|
|
5741
|
+
if (fileStat && fileStat.isFile()) {
|
|
5742
|
+
result.stat = fileStat;
|
|
5743
|
+
result.url = fileUrl;
|
|
5744
|
+
return result;
|
|
5745
|
+
}
|
|
5746
|
+
if (fileStat && fileStat.isDirectory()) {
|
|
5747
|
+
if (magicDirectoryIndex) {
|
|
5748
|
+
const indexFileSuffix = fileUrl.endsWith("/") ? "index" : "/index";
|
|
5749
|
+
const indexFileUrl = `${fileUrl}${indexFileSuffix}`;
|
|
5750
|
+
const subResult = applyFileSystemMagicResolution(indexFileUrl, {
|
|
5751
|
+
magicDirectoryIndex: false,
|
|
5752
|
+
magicExtensions,
|
|
5803
5753
|
});
|
|
5804
|
-
return
|
|
5754
|
+
return {
|
|
5755
|
+
...result,
|
|
5756
|
+
...subResult,
|
|
5757
|
+
magicDirectoryIndex: true,
|
|
5758
|
+
};
|
|
5805
5759
|
}
|
|
5760
|
+
result.stat = fileStat;
|
|
5761
|
+
result.url = fileUrl;
|
|
5762
|
+
return result;
|
|
5806
5763
|
}
|
|
5807
5764
|
|
|
5808
|
-
|
|
5765
|
+
if (magicExtensions && magicExtensions.length) {
|
|
5766
|
+
const parentUrl = new URL("./", fileUrl).href;
|
|
5767
|
+
const urlFilename = urlToFilename(fileUrl);
|
|
5768
|
+
for (const extensionToTry of magicExtensions) {
|
|
5769
|
+
const urlCandidate = `${parentUrl}${urlFilename}${extensionToTry}`;
|
|
5770
|
+
let stat;
|
|
5771
|
+
try {
|
|
5772
|
+
stat = readEntryStatSync(new URL(urlCandidate));
|
|
5773
|
+
} catch (e) {
|
|
5774
|
+
if (e.code === "ENOENT") {
|
|
5775
|
+
stat = null;
|
|
5776
|
+
} else {
|
|
5777
|
+
throw e;
|
|
5778
|
+
}
|
|
5779
|
+
}
|
|
5780
|
+
if (stat) {
|
|
5781
|
+
result.stat = stat;
|
|
5782
|
+
result.url = `${fileUrl}${extensionToTry}`;
|
|
5783
|
+
result.magicExtension = extensionToTry;
|
|
5784
|
+
return result;
|
|
5785
|
+
}
|
|
5786
|
+
}
|
|
5787
|
+
}
|
|
5788
|
+
// magic extension not found
|
|
5789
|
+
return result;
|
|
5809
5790
|
};
|
|
5810
5791
|
|
|
5811
|
-
const
|
|
5812
|
-
|
|
5813
|
-
|
|
5814
|
-
|
|
5815
|
-
);
|
|
5792
|
+
const getExtensionsToTry = (magicExtensions, importer) => {
|
|
5793
|
+
if (!magicExtensions) {
|
|
5794
|
+
return [];
|
|
5795
|
+
}
|
|
5796
|
+
const extensionsSet = new Set();
|
|
5797
|
+
magicExtensions.forEach((magicExtension) => {
|
|
5798
|
+
if (magicExtension === "inherit") {
|
|
5799
|
+
const importerExtension = urlToExtension(importer);
|
|
5800
|
+
extensionsSet.add(importerExtension);
|
|
5801
|
+
} else {
|
|
5802
|
+
extensionsSet.add(magicExtension);
|
|
5803
|
+
}
|
|
5804
|
+
});
|
|
5805
|
+
return Array.from(extensionsSet.values());
|
|
5816
5806
|
};
|
|
5817
5807
|
|
|
5818
|
-
|
|
5819
|
-
|
|
5820
|
-
|
|
5821
|
-
assertImportMap(leftImportMap);
|
|
5822
|
-
assertImportMap(rightImportMap);
|
|
5823
|
-
|
|
5824
|
-
const importMap = {};
|
|
5825
|
-
|
|
5826
|
-
const leftImports = leftImportMap.imports;
|
|
5827
|
-
const rightImports = rightImportMap.imports;
|
|
5828
|
-
const leftHasImports = Boolean(leftImports);
|
|
5829
|
-
const rightHasImports = Boolean(rightImports);
|
|
5830
|
-
if (leftHasImports && rightHasImports) {
|
|
5831
|
-
importMap.imports = composeTwoMappings(leftImports, rightImports);
|
|
5832
|
-
} else if (leftHasImports) {
|
|
5833
|
-
importMap.imports = { ...leftImports };
|
|
5834
|
-
} else if (rightHasImports) {
|
|
5835
|
-
importMap.imports = { ...rightImports };
|
|
5808
|
+
const versionFromValue = (value) => {
|
|
5809
|
+
if (typeof value === "number") {
|
|
5810
|
+
return numberToVersion(value);
|
|
5836
5811
|
}
|
|
5837
|
-
|
|
5838
|
-
|
|
5839
|
-
const rightScopes = rightImportMap.scopes;
|
|
5840
|
-
const leftHasScopes = Boolean(leftScopes);
|
|
5841
|
-
const rightHasScopes = Boolean(rightScopes);
|
|
5842
|
-
if (leftHasScopes && rightHasScopes) {
|
|
5843
|
-
importMap.scopes = composeTwoScopes(
|
|
5844
|
-
leftScopes,
|
|
5845
|
-
rightScopes,
|
|
5846
|
-
importMap.imports || {},
|
|
5847
|
-
);
|
|
5848
|
-
} else if (leftHasScopes) {
|
|
5849
|
-
importMap.scopes = { ...leftScopes };
|
|
5850
|
-
} else if (rightHasScopes) {
|
|
5851
|
-
importMap.scopes = { ...rightScopes };
|
|
5812
|
+
if (typeof value === "string") {
|
|
5813
|
+
return stringToVersion(value);
|
|
5852
5814
|
}
|
|
5815
|
+
throw new TypeError(`version must be a number or a string, got ${value}`);
|
|
5816
|
+
};
|
|
5853
5817
|
|
|
5854
|
-
|
|
5818
|
+
const numberToVersion = (number) => {
|
|
5819
|
+
return {
|
|
5820
|
+
major: number,
|
|
5821
|
+
minor: 0,
|
|
5822
|
+
patch: 0,
|
|
5823
|
+
};
|
|
5855
5824
|
};
|
|
5856
5825
|
|
|
5857
|
-
const
|
|
5858
|
-
|
|
5826
|
+
const stringToVersion = (string) => {
|
|
5827
|
+
if (string.indexOf(".") > -1) {
|
|
5828
|
+
const parts = string.split(".");
|
|
5829
|
+
return {
|
|
5830
|
+
major: Number(parts[0]),
|
|
5831
|
+
minor: parts[1] ? Number(parts[1]) : 0,
|
|
5832
|
+
patch: parts[2] ? Number(parts[2]) : 0,
|
|
5833
|
+
};
|
|
5834
|
+
}
|
|
5859
5835
|
|
|
5860
|
-
|
|
5861
|
-
|
|
5862
|
-
|
|
5863
|
-
|
|
5864
|
-
|
|
5865
|
-
|
|
5866
|
-
|
|
5867
|
-
return compareAddressAndSpecifier(leftAddress, rightSpecifier);
|
|
5868
|
-
});
|
|
5869
|
-
mappings[leftSpecifier] = rightSpecifier
|
|
5870
|
-
? rightMappings[rightSpecifier]
|
|
5871
|
-
: leftAddress;
|
|
5872
|
-
});
|
|
5836
|
+
if (isNaN(string)) {
|
|
5837
|
+
return {
|
|
5838
|
+
major: 0,
|
|
5839
|
+
minor: 0,
|
|
5840
|
+
patch: 0,
|
|
5841
|
+
};
|
|
5842
|
+
}
|
|
5873
5843
|
|
|
5874
|
-
|
|
5875
|
-
|
|
5876
|
-
|
|
5844
|
+
return {
|
|
5845
|
+
major: Number(string),
|
|
5846
|
+
minor: 0,
|
|
5847
|
+
patch: 0,
|
|
5848
|
+
};
|
|
5849
|
+
};
|
|
5877
5850
|
|
|
5878
|
-
|
|
5851
|
+
const compareTwoVersions = (versionA, versionB) => {
|
|
5852
|
+
const semanticVersionA = versionFromValue(versionA);
|
|
5853
|
+
const semanticVersionB = versionFromValue(versionB);
|
|
5854
|
+
const majorDiff = semanticVersionA.major - semanticVersionB.major;
|
|
5855
|
+
if (majorDiff > 0) {
|
|
5856
|
+
return majorDiff;
|
|
5857
|
+
}
|
|
5858
|
+
if (majorDiff < 0) {
|
|
5859
|
+
return majorDiff;
|
|
5860
|
+
}
|
|
5861
|
+
const minorDiff = semanticVersionA.minor - semanticVersionB.minor;
|
|
5862
|
+
if (minorDiff > 0) {
|
|
5863
|
+
return minorDiff;
|
|
5864
|
+
}
|
|
5865
|
+
if (minorDiff < 0) {
|
|
5866
|
+
return minorDiff;
|
|
5867
|
+
}
|
|
5868
|
+
const patchDiff = semanticVersionA.patch - semanticVersionB.patch;
|
|
5869
|
+
if (patchDiff > 0) {
|
|
5870
|
+
return patchDiff;
|
|
5871
|
+
}
|
|
5872
|
+
if (patchDiff < 0) {
|
|
5873
|
+
return patchDiff;
|
|
5874
|
+
}
|
|
5875
|
+
return 0;
|
|
5879
5876
|
};
|
|
5880
5877
|
|
|
5881
|
-
const
|
|
5882
|
-
|
|
5883
|
-
|
|
5884
|
-
const compareAddressAndSpecifier = (address, specifier) => {
|
|
5885
|
-
const addressUrl = resolveUrl(address, "file:///");
|
|
5886
|
-
const specifierUrl = resolveUrl(specifier, "file:///");
|
|
5887
|
-
return addressUrl === specifierUrl;
|
|
5878
|
+
const versionIsBelow = (versionSupposedBelow, versionSupposedAbove) => {
|
|
5879
|
+
return compareTwoVersions(versionSupposedBelow, versionSupposedAbove) < 0;
|
|
5888
5880
|
};
|
|
5889
5881
|
|
|
5890
|
-
const
|
|
5891
|
-
|
|
5892
|
-
|
|
5893
|
-
|
|
5894
|
-
|
|
5895
|
-
// will be merged
|
|
5896
|
-
scopes[leftScopeKey] = leftScopes[leftScopeKey];
|
|
5897
|
-
return;
|
|
5898
|
-
}
|
|
5899
|
-
const topLevelSpecifier = Object.keys(imports).find(
|
|
5900
|
-
(topLevelSpecifierCandidate) => {
|
|
5901
|
-
return compareAddressAndSpecifier(
|
|
5902
|
-
leftScopeKey,
|
|
5903
|
-
topLevelSpecifierCandidate,
|
|
5904
|
-
);
|
|
5905
|
-
},
|
|
5906
|
-
);
|
|
5907
|
-
if (topLevelSpecifier) {
|
|
5908
|
-
scopes[imports[topLevelSpecifier]] = leftScopes[leftScopeKey];
|
|
5909
|
-
} else {
|
|
5910
|
-
scopes[leftScopeKey] = leftScopes[leftScopeKey];
|
|
5911
|
-
}
|
|
5912
|
-
});
|
|
5913
|
-
|
|
5914
|
-
Object.keys(rightScopes).forEach((rightScopeKey) => {
|
|
5915
|
-
if (objectHasKey(scopes, rightScopeKey)) {
|
|
5916
|
-
scopes[rightScopeKey] = composeTwoMappings(
|
|
5917
|
-
scopes[rightScopeKey],
|
|
5918
|
-
rightScopes[rightScopeKey],
|
|
5919
|
-
);
|
|
5920
|
-
} else {
|
|
5921
|
-
scopes[rightScopeKey] = {
|
|
5922
|
-
...rightScopes[rightScopeKey],
|
|
5923
|
-
};
|
|
5882
|
+
const findHighestVersion = (...values) => {
|
|
5883
|
+
if (values.length === 0) throw new Error(`missing argument`);
|
|
5884
|
+
return values.reduce((highestVersion, value) => {
|
|
5885
|
+
if (versionIsBelow(highestVersion, value)) {
|
|
5886
|
+
return value;
|
|
5924
5887
|
}
|
|
5888
|
+
return highestVersion;
|
|
5925
5889
|
});
|
|
5926
|
-
|
|
5927
|
-
return scopes;
|
|
5928
5890
|
};
|
|
5929
5891
|
|
|
5930
|
-
const
|
|
5931
|
-
|
|
5932
|
-
|
|
5933
|
-
|
|
5934
|
-
|
|
5935
|
-
.
|
|
5936
|
-
|
|
5937
|
-
|
|
5938
|
-
|
|
5939
|
-
|
|
5892
|
+
const featuresCompatMap = {
|
|
5893
|
+
script_type_module: {
|
|
5894
|
+
edge: "16",
|
|
5895
|
+
firefox: "60",
|
|
5896
|
+
chrome: "61",
|
|
5897
|
+
safari: "10.1",
|
|
5898
|
+
opera: "48",
|
|
5899
|
+
ios: "10.3",
|
|
5900
|
+
android: "61",
|
|
5901
|
+
samsung: "8.2",
|
|
5902
|
+
},
|
|
5903
|
+
document_current_script: {
|
|
5904
|
+
edge: "12",
|
|
5905
|
+
firefox: "4",
|
|
5906
|
+
chrome: "29",
|
|
5907
|
+
safari: "8",
|
|
5908
|
+
opera: "16",
|
|
5909
|
+
android: "4.4",
|
|
5910
|
+
samsung: "4",
|
|
5911
|
+
},
|
|
5912
|
+
// https://caniuse.com/?search=import.meta
|
|
5913
|
+
import_meta: {
|
|
5914
|
+
android: "9",
|
|
5915
|
+
chrome: "64",
|
|
5916
|
+
edge: "79",
|
|
5917
|
+
firefox: "62",
|
|
5918
|
+
ios: "12",
|
|
5919
|
+
opera: "51",
|
|
5920
|
+
safari: "11.1",
|
|
5921
|
+
samsung: "9.2",
|
|
5922
|
+
},
|
|
5923
|
+
import_meta_resolve: {
|
|
5924
|
+
chrome: "107",
|
|
5925
|
+
edge: "105",
|
|
5926
|
+
firefox: "106",
|
|
5927
|
+
node: "20.0.0",
|
|
5928
|
+
},
|
|
5929
|
+
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#browser_compatibility
|
|
5930
|
+
import_dynamic: {
|
|
5931
|
+
android: "8",
|
|
5932
|
+
chrome: "63",
|
|
5933
|
+
edge: "79",
|
|
5934
|
+
firefox: "67",
|
|
5935
|
+
ios: "11.3",
|
|
5936
|
+
opera: "50",
|
|
5937
|
+
safari: "11.3",
|
|
5938
|
+
samsung: "8.0",
|
|
5939
|
+
node: "13.2",
|
|
5940
|
+
},
|
|
5941
|
+
top_level_await: {
|
|
5942
|
+
edge: "89",
|
|
5943
|
+
chrome: "89",
|
|
5944
|
+
firefox: "89",
|
|
5945
|
+
opera: "75",
|
|
5946
|
+
safari: "15",
|
|
5947
|
+
samsung: "15",
|
|
5948
|
+
ios: "15",
|
|
5949
|
+
node: "14.8",
|
|
5950
|
+
},
|
|
5951
|
+
// https://caniuse.com/import-maps
|
|
5952
|
+
importmap: {
|
|
5953
|
+
edge: "89",
|
|
5954
|
+
chrome: "89",
|
|
5955
|
+
opera: "76",
|
|
5956
|
+
samsung: "15",
|
|
5957
|
+
firefox: "108",
|
|
5958
|
+
safari: "16.4",
|
|
5959
|
+
},
|
|
5960
|
+
import_type_json: {
|
|
5961
|
+
chrome: "123",
|
|
5962
|
+
safari: "17.2",
|
|
5963
|
+
},
|
|
5964
|
+
import_type_css: {
|
|
5965
|
+
chrome: "123",
|
|
5966
|
+
},
|
|
5967
|
+
import_type_text: {},
|
|
5968
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet#browser_compatibility
|
|
5969
|
+
new_stylesheet: {
|
|
5970
|
+
chrome: "73",
|
|
5971
|
+
edge: "79",
|
|
5972
|
+
opera: "53",
|
|
5973
|
+
android: "73",
|
|
5974
|
+
},
|
|
5975
|
+
// https://caniuse.com/?search=worker
|
|
5976
|
+
worker: {
|
|
5977
|
+
ie: "10",
|
|
5978
|
+
edge: "12",
|
|
5979
|
+
firefox: "3.5",
|
|
5980
|
+
chrome: "4",
|
|
5981
|
+
opera: "11.5",
|
|
5982
|
+
safari: "4",
|
|
5983
|
+
ios: "5",
|
|
5984
|
+
android: "4.4",
|
|
5985
|
+
},
|
|
5986
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/Worker/Worker#browser_compatibility
|
|
5987
|
+
worker_type_module: {
|
|
5988
|
+
chrome: "80",
|
|
5989
|
+
edge: "80",
|
|
5990
|
+
opera: "67",
|
|
5991
|
+
android: "80",
|
|
5992
|
+
},
|
|
5993
|
+
worker_importmap: {},
|
|
5994
|
+
service_worker: {
|
|
5995
|
+
edge: "17",
|
|
5996
|
+
firefox: "44",
|
|
5997
|
+
chrome: "40",
|
|
5998
|
+
safari: "11.1",
|
|
5999
|
+
opera: "27",
|
|
6000
|
+
ios: "11.3",
|
|
6001
|
+
android: "12.12",
|
|
6002
|
+
},
|
|
6003
|
+
service_worker_type_module: {
|
|
6004
|
+
chrome: "80",
|
|
6005
|
+
edge: "80",
|
|
6006
|
+
opera: "67",
|
|
6007
|
+
android: "80",
|
|
6008
|
+
},
|
|
6009
|
+
service_worker_importmap: {},
|
|
6010
|
+
shared_worker: {
|
|
6011
|
+
chrome: "4",
|
|
6012
|
+
edge: "79",
|
|
6013
|
+
firefox: "29",
|
|
6014
|
+
opera: "10.6",
|
|
6015
|
+
},
|
|
6016
|
+
shared_worker_type_module: {
|
|
6017
|
+
chrome: "80",
|
|
6018
|
+
edge: "80",
|
|
6019
|
+
opera: "67",
|
|
6020
|
+
},
|
|
6021
|
+
shared_worker_importmap: {},
|
|
6022
|
+
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/globalThis#browser_compatibility
|
|
6023
|
+
global_this: {
|
|
6024
|
+
edge: "79",
|
|
6025
|
+
firefox: "65",
|
|
6026
|
+
chrome: "71",
|
|
6027
|
+
safari: "12.1",
|
|
6028
|
+
opera: "58",
|
|
6029
|
+
ios: "12.2",
|
|
6030
|
+
android: "94",
|
|
6031
|
+
node: "12",
|
|
6032
|
+
},
|
|
6033
|
+
async_generator_function: {
|
|
6034
|
+
chrome: "63",
|
|
6035
|
+
opera: "50",
|
|
6036
|
+
edge: "79",
|
|
6037
|
+
firefox: "57",
|
|
6038
|
+
safari: "12",
|
|
6039
|
+
node: "10",
|
|
6040
|
+
ios: "12",
|
|
6041
|
+
samsung: "8",
|
|
6042
|
+
electron: "3",
|
|
6043
|
+
},
|
|
6044
|
+
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#browser_compatibility
|
|
6045
|
+
template_literals: {
|
|
6046
|
+
chrome: "41",
|
|
6047
|
+
edge: "12",
|
|
6048
|
+
firefox: "34",
|
|
6049
|
+
opera: "28",
|
|
6050
|
+
safari: "9",
|
|
6051
|
+
ios: "9",
|
|
6052
|
+
android: "4",
|
|
6053
|
+
node: "4",
|
|
6054
|
+
},
|
|
6055
|
+
arrow_function: {
|
|
6056
|
+
chrome: "47",
|
|
6057
|
+
opera: "34",
|
|
6058
|
+
edge: "13",
|
|
6059
|
+
firefox: "45",
|
|
6060
|
+
safari: "10",
|
|
6061
|
+
node: "6",
|
|
6062
|
+
ios: "10",
|
|
6063
|
+
samsung: "5",
|
|
6064
|
+
electron: "0.36",
|
|
6065
|
+
},
|
|
6066
|
+
const_bindings: {
|
|
6067
|
+
chrome: "41",
|
|
6068
|
+
opera: "28",
|
|
6069
|
+
edge: "12",
|
|
6070
|
+
firefox: "46",
|
|
6071
|
+
safari: "10",
|
|
6072
|
+
node: "4",
|
|
6073
|
+
ie: "11",
|
|
6074
|
+
ios: "10",
|
|
6075
|
+
samsung: "3.4",
|
|
6076
|
+
electron: "0.22",
|
|
6077
|
+
},
|
|
6078
|
+
object_properties_shorthand: {
|
|
6079
|
+
chrome: "43",
|
|
6080
|
+
opera: "30",
|
|
6081
|
+
edge: "12",
|
|
6082
|
+
firefox: "33",
|
|
6083
|
+
safari: "9",
|
|
6084
|
+
node: "4",
|
|
6085
|
+
ios: "9",
|
|
6086
|
+
samsung: "4",
|
|
6087
|
+
electron: "0.28",
|
|
6088
|
+
},
|
|
6089
|
+
reserved_words: {
|
|
6090
|
+
chrome: "13",
|
|
6091
|
+
opera: "10.50",
|
|
6092
|
+
edge: "12",
|
|
6093
|
+
firefox: "2",
|
|
6094
|
+
safari: "3.1",
|
|
6095
|
+
node: "0.10",
|
|
6096
|
+
ie: "9",
|
|
6097
|
+
android: "4.4",
|
|
6098
|
+
ios: "6",
|
|
6099
|
+
phantom: "2",
|
|
6100
|
+
samsung: "1",
|
|
6101
|
+
electron: "0.20",
|
|
6102
|
+
},
|
|
6103
|
+
symbols: {
|
|
6104
|
+
chrome: "38",
|
|
6105
|
+
opera: "25",
|
|
6106
|
+
edge: "12",
|
|
6107
|
+
firefox: "36",
|
|
6108
|
+
safari: "9",
|
|
6109
|
+
ios: "9",
|
|
6110
|
+
samsung: "4",
|
|
6111
|
+
node: "0.12",
|
|
6112
|
+
},
|
|
5940
6113
|
};
|
|
5941
6114
|
|
|
5942
|
-
const
|
|
5943
|
-
|
|
6115
|
+
const RUNTIME_COMPAT = {
|
|
6116
|
+
featuresCompatMap,
|
|
5944
6117
|
|
|
5945
|
-
|
|
5946
|
-
|
|
5947
|
-
|
|
5948
|
-
|
|
6118
|
+
add: (originalRuntimeCompat, feature) => {
|
|
6119
|
+
const featureCompat = getFeatureCompat(feature);
|
|
6120
|
+
const runtimeCompat = {
|
|
6121
|
+
...originalRuntimeCompat,
|
|
6122
|
+
};
|
|
6123
|
+
Object.keys(originalRuntimeCompat).forEach((runtimeName) => {
|
|
6124
|
+
const secondVersion = featureCompat[runtimeName]; // the version supported by the feature
|
|
6125
|
+
if (secondVersion) {
|
|
6126
|
+
const firstVersion = originalRuntimeCompat[runtimeName];
|
|
6127
|
+
runtimeCompat[runtimeName] = findHighestVersion(
|
|
6128
|
+
firstVersion,
|
|
6129
|
+
secondVersion,
|
|
6130
|
+
);
|
|
6131
|
+
}
|
|
5949
6132
|
});
|
|
6133
|
+
return runtimeCompat;
|
|
6134
|
+
},
|
|
5950
6135
|
|
|
5951
|
-
|
|
5952
|
-
|
|
5953
|
-
|
|
5954
|
-
|
|
5955
|
-
|
|
5956
|
-
|
|
5957
|
-
|
|
5958
|
-
const
|
|
5959
|
-
|
|
5960
|
-
|
|
5961
|
-
|
|
5962
|
-
|
|
5963
|
-
}
|
|
5964
|
-
|
|
5965
|
-
const { imports, scopes } = importMap;
|
|
5966
|
-
|
|
5967
|
-
return {
|
|
5968
|
-
imports: imports ? normalizeMappings(imports, baseUrl) : undefined,
|
|
5969
|
-
scopes: scopes ? normalizeScopes(scopes, baseUrl) : undefined,
|
|
5970
|
-
};
|
|
5971
|
-
};
|
|
5972
|
-
|
|
5973
|
-
const isStringOrUrl = (value) => {
|
|
5974
|
-
if (typeof value === "string") {
|
|
5975
|
-
return true;
|
|
5976
|
-
}
|
|
5977
|
-
|
|
5978
|
-
if (typeof URL === "function" && value instanceof URL) {
|
|
5979
|
-
return true;
|
|
5980
|
-
}
|
|
5981
|
-
|
|
5982
|
-
return false;
|
|
5983
|
-
};
|
|
5984
|
-
|
|
5985
|
-
const normalizeMappings = (mappings, baseUrl) => {
|
|
5986
|
-
const mappingsNormalized = {};
|
|
5987
|
-
|
|
5988
|
-
Object.keys(mappings).forEach((specifier) => {
|
|
5989
|
-
const address = mappings[specifier];
|
|
5990
|
-
|
|
5991
|
-
if (typeof address !== "string") {
|
|
5992
|
-
console.warn(
|
|
5993
|
-
formulateAddressMustBeAString({
|
|
5994
|
-
address,
|
|
5995
|
-
specifier,
|
|
5996
|
-
}),
|
|
5997
|
-
);
|
|
5998
|
-
return;
|
|
5999
|
-
}
|
|
6000
|
-
|
|
6001
|
-
const specifierResolved = resolveSpecifier(specifier, baseUrl) || specifier;
|
|
6002
|
-
|
|
6003
|
-
const addressUrl = tryUrlResolution(address, baseUrl);
|
|
6004
|
-
if (addressUrl === null) {
|
|
6005
|
-
console.warn(
|
|
6006
|
-
formulateAdressResolutionFailed({
|
|
6007
|
-
address,
|
|
6008
|
-
baseUrl,
|
|
6009
|
-
specifier,
|
|
6010
|
-
}),
|
|
6011
|
-
);
|
|
6012
|
-
return;
|
|
6013
|
-
}
|
|
6014
|
-
|
|
6015
|
-
if (specifier.endsWith("/") && !addressUrl.endsWith("/")) {
|
|
6016
|
-
console.warn(
|
|
6017
|
-
formulateAddressUrlRequiresTrailingSlash({
|
|
6018
|
-
address,
|
|
6019
|
-
specifier,
|
|
6020
|
-
}),
|
|
6021
|
-
);
|
|
6022
|
-
return;
|
|
6023
|
-
}
|
|
6024
|
-
mappingsNormalized[specifierResolved] = addressUrl;
|
|
6025
|
-
});
|
|
6026
|
-
|
|
6027
|
-
return sortImports(mappingsNormalized);
|
|
6028
|
-
};
|
|
6029
|
-
|
|
6030
|
-
const normalizeScopes = (scopes, baseUrl) => {
|
|
6031
|
-
const scopesNormalized = {};
|
|
6032
|
-
|
|
6033
|
-
Object.keys(scopes).forEach((scopeSpecifier) => {
|
|
6034
|
-
const scopeMappings = scopes[scopeSpecifier];
|
|
6035
|
-
const scopeUrl = tryUrlResolution(scopeSpecifier, baseUrl);
|
|
6036
|
-
if (scopeUrl === null) {
|
|
6037
|
-
console.warn(
|
|
6038
|
-
formulateScopeResolutionFailed({
|
|
6039
|
-
scope: scopeSpecifier,
|
|
6040
|
-
baseUrl,
|
|
6041
|
-
}),
|
|
6136
|
+
isSupported: (
|
|
6137
|
+
runtimeCompat,
|
|
6138
|
+
feature,
|
|
6139
|
+
featureCompat = getFeatureCompat(feature),
|
|
6140
|
+
) => {
|
|
6141
|
+
const runtimeNames = Object.keys(runtimeCompat);
|
|
6142
|
+
const runtimeWithoutCompat = runtimeNames.find((runtimeName) => {
|
|
6143
|
+
const runtimeVersion = runtimeCompat[runtimeName];
|
|
6144
|
+
const runtimeVersionCompatible = featureCompat[runtimeName] || "Infinity";
|
|
6145
|
+
const highestVersion = findHighestVersion(
|
|
6146
|
+
runtimeVersion,
|
|
6147
|
+
runtimeVersionCompatible,
|
|
6042
6148
|
);
|
|
6043
|
-
return;
|
|
6044
|
-
}
|
|
6045
|
-
const scopeValueNormalized = normalizeMappings(scopeMappings, baseUrl);
|
|
6046
|
-
scopesNormalized[scopeUrl] = scopeValueNormalized;
|
|
6047
|
-
});
|
|
6048
|
-
|
|
6049
|
-
return sortScopes(scopesNormalized);
|
|
6050
|
-
};
|
|
6051
|
-
|
|
6052
|
-
const formulateBaseUrlMustBeStringOrUrl = ({
|
|
6053
|
-
baseUrl,
|
|
6054
|
-
}) => `baseUrl must be a string or an url.
|
|
6055
|
-
--- base url ---
|
|
6056
|
-
${baseUrl}`;
|
|
6057
|
-
|
|
6058
|
-
const formulateAddressMustBeAString = ({
|
|
6059
|
-
specifier,
|
|
6060
|
-
address,
|
|
6061
|
-
}) => `Address must be a string.
|
|
6062
|
-
--- address ---
|
|
6063
|
-
${address}
|
|
6064
|
-
--- specifier ---
|
|
6065
|
-
${specifier}`;
|
|
6066
|
-
|
|
6067
|
-
const formulateAdressResolutionFailed = ({
|
|
6068
|
-
address,
|
|
6069
|
-
baseUrl,
|
|
6070
|
-
specifier,
|
|
6071
|
-
}) => `Address url resolution failed.
|
|
6072
|
-
--- address ---
|
|
6073
|
-
${address}
|
|
6074
|
-
--- base url ---
|
|
6075
|
-
${baseUrl}
|
|
6076
|
-
--- specifier ---
|
|
6077
|
-
${specifier}`;
|
|
6078
|
-
|
|
6079
|
-
const formulateAddressUrlRequiresTrailingSlash = ({
|
|
6080
|
-
addressURL,
|
|
6081
|
-
address,
|
|
6082
|
-
specifier,
|
|
6083
|
-
}) => `Address must end with /.
|
|
6084
|
-
--- address url ---
|
|
6085
|
-
${addressURL}
|
|
6086
|
-
--- address ---
|
|
6087
|
-
${address}
|
|
6088
|
-
--- specifier ---
|
|
6089
|
-
${specifier}`;
|
|
6090
|
-
|
|
6091
|
-
const formulateScopeResolutionFailed = ({
|
|
6092
|
-
scope,
|
|
6093
|
-
baseUrl,
|
|
6094
|
-
}) => `Scope url resolution failed.
|
|
6095
|
-
--- scope ---
|
|
6096
|
-
${scope}
|
|
6097
|
-
--- base url ---
|
|
6098
|
-
${baseUrl}`;
|
|
6099
|
-
|
|
6100
|
-
const pathnameToExtension = (pathname) => {
|
|
6101
|
-
const slashLastIndex = pathname.lastIndexOf("/");
|
|
6102
|
-
if (slashLastIndex !== -1) {
|
|
6103
|
-
pathname = pathname.slice(slashLastIndex + 1);
|
|
6104
|
-
}
|
|
6105
|
-
|
|
6106
|
-
const dotLastIndex = pathname.lastIndexOf(".");
|
|
6107
|
-
if (dotLastIndex === -1) return "";
|
|
6108
|
-
// if (dotLastIndex === pathname.length - 1) return ""
|
|
6109
|
-
return pathname.slice(dotLastIndex);
|
|
6110
|
-
};
|
|
6111
|
-
|
|
6112
|
-
const resolveImport = ({
|
|
6113
|
-
specifier,
|
|
6114
|
-
importer,
|
|
6115
|
-
importMap,
|
|
6116
|
-
defaultExtension = false,
|
|
6117
|
-
createBareSpecifierError,
|
|
6118
|
-
onImportMapping = () => {},
|
|
6119
|
-
}) => {
|
|
6120
|
-
let url;
|
|
6121
|
-
if (importMap) {
|
|
6122
|
-
url = applyImportMap({
|
|
6123
|
-
importMap,
|
|
6124
|
-
specifier,
|
|
6125
|
-
importer,
|
|
6126
|
-
createBareSpecifierError,
|
|
6127
|
-
onImportMapping,
|
|
6149
|
+
return highestVersion !== runtimeVersion;
|
|
6128
6150
|
});
|
|
6129
|
-
|
|
6130
|
-
|
|
6131
|
-
|
|
6151
|
+
return !runtimeWithoutCompat;
|
|
6152
|
+
},
|
|
6153
|
+
};
|
|
6132
6154
|
|
|
6133
|
-
|
|
6134
|
-
|
|
6155
|
+
const getFeatureCompat = (feature) => {
|
|
6156
|
+
if (typeof feature === "string") {
|
|
6157
|
+
const compat = featuresCompatMap[feature];
|
|
6158
|
+
if (!compat) {
|
|
6159
|
+
throw new Error(`"${feature}" feature is unknown`);
|
|
6160
|
+
}
|
|
6161
|
+
return compat;
|
|
6162
|
+
}
|
|
6163
|
+
if (typeof feature !== "object") {
|
|
6164
|
+
throw new TypeError(
|
|
6165
|
+
`feature must be a string or an object, got ${feature}`,
|
|
6166
|
+
);
|
|
6135
6167
|
}
|
|
6168
|
+
return feature;
|
|
6169
|
+
};
|
|
6136
6170
|
|
|
6137
|
-
|
|
6171
|
+
const isSupportedAlgorithm = (algo) => {
|
|
6172
|
+
return SUPPORTED_ALGORITHMS.includes(algo);
|
|
6138
6173
|
};
|
|
6139
6174
|
|
|
6140
|
-
|
|
6141
|
-
|
|
6142
|
-
|
|
6175
|
+
// https://www.w3.org/TR/SRI/#priority
|
|
6176
|
+
const getPrioritizedHashFunction = (firstAlgo, secondAlgo) => {
|
|
6177
|
+
const firstIndex = SUPPORTED_ALGORITHMS.indexOf(firstAlgo);
|
|
6178
|
+
const secondIndex = SUPPORTED_ALGORITHMS.indexOf(secondAlgo);
|
|
6179
|
+
if (firstIndex === secondIndex) {
|
|
6180
|
+
return "";
|
|
6143
6181
|
}
|
|
6144
|
-
|
|
6145
|
-
|
|
6146
|
-
const extension = pathnameToExtension(url);
|
|
6147
|
-
if (extension === "") {
|
|
6148
|
-
return `${url}${defaultExtension}`;
|
|
6149
|
-
}
|
|
6150
|
-
return url;
|
|
6182
|
+
if (firstIndex < secondIndex) {
|
|
6183
|
+
return secondAlgo;
|
|
6151
6184
|
}
|
|
6185
|
+
return firstAlgo;
|
|
6186
|
+
};
|
|
6152
6187
|
|
|
6153
|
-
|
|
6154
|
-
|
|
6155
|
-
|
|
6156
|
-
|
|
6157
|
-
const importerExtension = pathnameToExtension(importerPathname);
|
|
6158
|
-
return `${url}${importerExtension}`;
|
|
6159
|
-
}
|
|
6160
|
-
}
|
|
6188
|
+
const applyAlgoToRepresentationData = (algo, data) => {
|
|
6189
|
+
const base64Value = crypto.createHash(algo).update(data).digest("base64");
|
|
6190
|
+
return base64Value;
|
|
6191
|
+
};
|
|
6161
6192
|
|
|
6162
|
-
|
|
6193
|
+
// keep this ordered by collision resistance as it is also used by "getPrioritizedHashFunction"
|
|
6194
|
+
const SUPPORTED_ALGORITHMS = ["sha256", "sha384", "sha512"];
|
|
6195
|
+
|
|
6196
|
+
// see https://w3c.github.io/webappsec-subresource-integrity/#parse-metadata
|
|
6197
|
+
const parseIntegrity = (string) => {
|
|
6198
|
+
const integrityMetadata = {};
|
|
6199
|
+
string
|
|
6200
|
+
.trim()
|
|
6201
|
+
.split(/\s+/)
|
|
6202
|
+
.forEach((token) => {
|
|
6203
|
+
const { isValid, algo, base64Value, optionExpression } =
|
|
6204
|
+
parseAsHashWithOptions(token);
|
|
6205
|
+
if (!isValid) {
|
|
6206
|
+
return;
|
|
6207
|
+
}
|
|
6208
|
+
if (!isSupportedAlgorithm(algo)) {
|
|
6209
|
+
return;
|
|
6210
|
+
}
|
|
6211
|
+
const metadataList = integrityMetadata[algo];
|
|
6212
|
+
const metadata = { base64Value, optionExpression };
|
|
6213
|
+
integrityMetadata[algo] = metadataList
|
|
6214
|
+
? [...metadataList, metadata]
|
|
6215
|
+
: [metadata];
|
|
6216
|
+
});
|
|
6217
|
+
return integrityMetadata;
|
|
6163
6218
|
};
|
|
6164
6219
|
|
|
6165
|
-
|
|
6166
|
-
|
|
6167
|
-
|
|
6168
|
-
|
|
6169
|
-
|
|
6170
|
-
backslashBeforeCount++;
|
|
6171
|
-
}
|
|
6172
|
-
break;
|
|
6220
|
+
// see https://w3c.github.io/webappsec-subresource-integrity/#the-integrity-attribute
|
|
6221
|
+
const parseAsHashWithOptions = (token) => {
|
|
6222
|
+
const dashIndex = token.indexOf("-");
|
|
6223
|
+
if (dashIndex === -1) {
|
|
6224
|
+
return { isValid: false };
|
|
6173
6225
|
}
|
|
6174
|
-
const
|
|
6175
|
-
|
|
6226
|
+
const beforeDash = token.slice(0, dashIndex);
|
|
6227
|
+
const afterDash = token.slice(dashIndex + 1);
|
|
6228
|
+
const questionIndex = afterDash.indexOf("?");
|
|
6229
|
+
const algo = beforeDash;
|
|
6230
|
+
if (questionIndex === -1) {
|
|
6231
|
+
const base64Value = afterDash;
|
|
6232
|
+
const isValid = BASE64_REGEX.test(afterDash);
|
|
6233
|
+
return { isValid, algo, base64Value };
|
|
6234
|
+
}
|
|
6235
|
+
const base64Value = afterDash.slice(0, questionIndex);
|
|
6236
|
+
const optionExpression = afterDash.slice(questionIndex + 1);
|
|
6237
|
+
const isValid =
|
|
6238
|
+
BASE64_REGEX.test(afterDash) && VCHAR_REGEX.test(optionExpression);
|
|
6239
|
+
return { isValid, algo, base64Value, optionExpression };
|
|
6176
6240
|
};
|
|
6177
6241
|
|
|
6178
|
-
const
|
|
6179
|
-
|
|
6180
|
-
// check default first, once tested do no re-test it
|
|
6181
|
-
if (!string.includes(defaultQuote)) {
|
|
6182
|
-
return defaultQuote;
|
|
6183
|
-
}
|
|
6184
|
-
if (defaultQuote !== DOUBLE && !string.includes(DOUBLE)) {
|
|
6185
|
-
return DOUBLE;
|
|
6186
|
-
}
|
|
6187
|
-
if (defaultQuote !== SINGLE && !string.includes(SINGLE)) {
|
|
6188
|
-
return SINGLE;
|
|
6189
|
-
}
|
|
6190
|
-
if (
|
|
6191
|
-
canUseTemplateString &&
|
|
6192
|
-
defaultQuote !== BACKTICK &&
|
|
6193
|
-
!string.includes(BACKTICK)
|
|
6194
|
-
) {
|
|
6195
|
-
return BACKTICK;
|
|
6196
|
-
}
|
|
6197
|
-
return defaultQuote;
|
|
6198
|
-
},
|
|
6242
|
+
const BASE64_REGEX = /^[A-Za-z0-9+/=]+$/;
|
|
6243
|
+
const VCHAR_REGEX = /^[\x21-\x7E]+$/;
|
|
6199
6244
|
|
|
6200
|
-
|
|
6201
|
-
|
|
6202
|
-
|
|
6203
|
-
|
|
6204
|
-
|
|
6205
|
-
|
|
6206
|
-
|
|
6207
|
-
|
|
6208
|
-
|
|
6209
|
-
|
|
6210
|
-
|
|
6211
|
-
|
|
6212
|
-
|
|
6213
|
-
|
|
6214
|
-
|
|
6215
|
-
|
|
6216
|
-
|
|
6217
|
-
|
|
6218
|
-
|
|
6219
|
-
|
|
6220
|
-
|
|
6221
|
-
|
|
6222
|
-
|
|
6223
|
-
|
|
6224
|
-
|
|
6225
|
-
|
|
6226
|
-
|
|
6227
|
-
|
|
6228
|
-
|
|
6229
|
-
|
|
6230
|
-
|
|
6231
|
-
|
|
6232
|
-
|
|
6233
|
-
|
|
6234
|
-
|
|
6235
|
-
|
|
6236
|
-
|
|
6237
|
-
) {
|
|
6238
|
-
isVersioningConcatenation = true;
|
|
6239
|
-
break;
|
|
6240
|
-
}
|
|
6241
|
-
}
|
|
6242
|
-
if (isVersioningConcatenation) {
|
|
6243
|
-
// it's a concatenation
|
|
6244
|
-
// skip until the end of concatenation (the second +)
|
|
6245
|
-
// and resume from there
|
|
6246
|
-
i = j + 1;
|
|
6247
|
-
continue;
|
|
6248
|
-
}
|
|
6249
|
-
}
|
|
6250
|
-
if (last === i - 1) {
|
|
6251
|
-
result += replacement;
|
|
6252
|
-
} else {
|
|
6253
|
-
result += `${string.slice(last, i - 1)}${replacement}`;
|
|
6254
|
-
}
|
|
6255
|
-
last = i;
|
|
6256
|
-
}
|
|
6257
|
-
}
|
|
6258
|
-
if (last !== string.length) {
|
|
6259
|
-
result += string.slice(last);
|
|
6260
|
-
}
|
|
6261
|
-
return `${quote}${result}${quote}`;
|
|
6262
|
-
},
|
|
6245
|
+
// https://www.w3.org/TR/SRI/#does-response-match-metadatalist
|
|
6246
|
+
const validateResponseIntegrity = (
|
|
6247
|
+
{ url, type, dataRepresentation },
|
|
6248
|
+
integrity,
|
|
6249
|
+
) => {
|
|
6250
|
+
if (!isResponseEligibleForIntegrityValidation({ type })) {
|
|
6251
|
+
return false;
|
|
6252
|
+
}
|
|
6253
|
+
const integrityMetadata = parseIntegrity(integrity);
|
|
6254
|
+
const algos = Object.keys(integrityMetadata);
|
|
6255
|
+
if (algos.length === 0) {
|
|
6256
|
+
return true;
|
|
6257
|
+
}
|
|
6258
|
+
let strongestAlgo = algos[0];
|
|
6259
|
+
algos.slice(1).forEach((algoCandidate) => {
|
|
6260
|
+
strongestAlgo =
|
|
6261
|
+
getPrioritizedHashFunction(strongestAlgo, algoCandidate) || strongestAlgo;
|
|
6262
|
+
});
|
|
6263
|
+
const metadataList = integrityMetadata[strongestAlgo];
|
|
6264
|
+
const actualBase64Value = applyAlgoToRepresentationData(
|
|
6265
|
+
strongestAlgo,
|
|
6266
|
+
dataRepresentation,
|
|
6267
|
+
);
|
|
6268
|
+
const acceptedBase64Values = metadataList.map(
|
|
6269
|
+
(metadata) => metadata.base64Value,
|
|
6270
|
+
);
|
|
6271
|
+
const someIsMatching = acceptedBase64Values.includes(actualBase64Value);
|
|
6272
|
+
if (someIsMatching) {
|
|
6273
|
+
return true;
|
|
6274
|
+
}
|
|
6275
|
+
const error = new Error(
|
|
6276
|
+
`Integrity validation failed for resource "${url}". The integrity found for this resource is "${strongestAlgo}-${actualBase64Value}"`,
|
|
6277
|
+
);
|
|
6278
|
+
error.code = "EINTEGRITY";
|
|
6279
|
+
error.algorithm = strongestAlgo;
|
|
6280
|
+
error.found = actualBase64Value;
|
|
6281
|
+
throw error;
|
|
6263
6282
|
};
|
|
6264
6283
|
|
|
6265
|
-
|
|
6266
|
-
const
|
|
6267
|
-
|
|
6268
|
-
const lineEndingEscapes = {
|
|
6269
|
-
"\n": "\\n",
|
|
6270
|
-
"\r": "\\r",
|
|
6271
|
-
"\u2028": "\\u2028",
|
|
6272
|
-
"\u2029": "\\u2029",
|
|
6273
|
-
};
|
|
6274
|
-
const JS_QUOTE_REPLACEMENTS = {
|
|
6275
|
-
[DOUBLE]: {
|
|
6276
|
-
'"': '\\"',
|
|
6277
|
-
...lineEndingEscapes,
|
|
6278
|
-
},
|
|
6279
|
-
[SINGLE]: {
|
|
6280
|
-
"'": "\\'",
|
|
6281
|
-
...lineEndingEscapes,
|
|
6282
|
-
},
|
|
6283
|
-
[BACKTICK]: {
|
|
6284
|
-
"`": "\\`",
|
|
6285
|
-
"$": "\\$",
|
|
6286
|
-
},
|
|
6284
|
+
// https://www.w3.org/TR/SRI/#is-response-eligible-for-integrity-validation
|
|
6285
|
+
const isResponseEligibleForIntegrityValidation = (response) => {
|
|
6286
|
+
return ["basic", "cors", "default"].includes(response.type);
|
|
6287
6287
|
};
|
|
6288
6288
|
|
|
6289
6289
|
const memoizeByFirstArgument = (compute) => {
|