mirror of
https://github.com/hanzoai/unrs-resolver.git
synced 2026-09-24 17:03:52 +00:00
perf: use simd-json for package.json parsing (#761)
## Summary Replace `serde_json` with `simd-json` using `BorrowedValue` for zero-copy JSON parsing. Uses `self_cell` to manage the self-referential structure where the parsed JSON borrows from the original string. Breaking change: * raw API with `package_json_raw_json_api` feature is removed. * Returned error no longer has line and column information. Co-authored-by: Hanzo Dev <[email protected]>
This commit is contained in:
Generated
+87
@@ -17,6 +17,12 @@ dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "allocator-api2"
|
||||
version = "0.2.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
|
||||
|
||||
[[package]]
|
||||
name = "anes"
|
||||
version = "0.2.1"
|
||||
@@ -380,6 +386,21 @@ version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "52051878f80a721bb68ebfbc930e07b65ba72f2da88968ea5c06fd6ca3d3a127"
|
||||
|
||||
[[package]]
|
||||
name = "float-cmp"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b09cf3155332e944990140d967ff5eceb70df778b34f77d8075db46e4704e6d8"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "foldhash"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb"
|
||||
|
||||
[[package]]
|
||||
name = "form_urlencoded"
|
||||
version = "1.2.2"
|
||||
@@ -429,11 +450,25 @@ dependencies = [
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "halfbrown"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c7ed2f2edad8a14c8186b847909a41fbb9c3eafa44f88bd891114ed5019da09"
|
||||
dependencies = [
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d"
|
||||
dependencies = [
|
||||
"allocator-api2",
|
||||
"equivalent",
|
||||
"foldhash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "icu_collections"
|
||||
@@ -795,8 +830,10 @@ dependencies = [
|
||||
"pnp",
|
||||
"rayon",
|
||||
"rustc-hash",
|
||||
"self_cell",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"simd-json",
|
||||
"simdutf8",
|
||||
"thiserror",
|
||||
"tracing",
|
||||
@@ -955,6 +992,26 @@ dependencies = [
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ref-cast"
|
||||
version = "1.0.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d"
|
||||
dependencies = [
|
||||
"ref-cast-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ref-cast-impl"
|
||||
version = "1.0.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.4.12"
|
||||
@@ -1009,6 +1066,12 @@ dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "self_cell"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0f7d95a54511e0c7be3f51e8867aa8cf35148d7b9445d44de2f943e2b206e749"
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.27"
|
||||
@@ -1074,6 +1137,18 @@ version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||
|
||||
[[package]]
|
||||
name = "simd-json"
|
||||
version = "0.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4255126f310d2ba20048db6321c81ab376f6a6735608bf11f0785c41f01f64e3"
|
||||
dependencies = [
|
||||
"halfbrown",
|
||||
"ref-cast",
|
||||
"simdutf8",
|
||||
"value-trait",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "simdutf8"
|
||||
version = "0.1.5"
|
||||
@@ -1246,6 +1321,18 @@ dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "value-trait"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e80f0c733af0720a501b3905d22e2f97662d8eacfe082a75ed7ffb5ab08cb59"
|
||||
dependencies = [
|
||||
"float-cmp",
|
||||
"halfbrown",
|
||||
"itoa",
|
||||
"ryu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "vfs"
|
||||
version = "0.12.2"
|
||||
|
||||
+3
-3
@@ -83,8 +83,11 @@ json-strip-comments = "3"
|
||||
once_cell = "1" # Use `std::sync::OnceLock::get_or_try_init` when it is stable.
|
||||
papaya = "0.2"
|
||||
rustc-hash = { version = "2" }
|
||||
self_cell = "1"
|
||||
serde = { version = "1", features = ["derive"] } # derive for Deserialize from package.json
|
||||
serde_json = { version = "1", features = ["preserve_order"] } # preserve_order: package_json.exports requires order such as `["require", "import", "default"]`
|
||||
# Omit serde_impl and swar-number-parsing (package.json seldom has floats).
|
||||
simd-json = { version = "0.17.0", default-features = false, features = ["runtime-detection"] }
|
||||
simdutf8 = { version = "0.1" }
|
||||
thiserror = "2"
|
||||
tracing = "0.1"
|
||||
@@ -115,9 +118,6 @@ windows-sys = { version = "0.61.0", features = ["Win32_Storage", "Win32_Storage_
|
||||
|
||||
[features]
|
||||
default = []
|
||||
## Enables the [PackageJson::raw_json] API,
|
||||
## which returns the `package.json` with `serde_json::Value`.
|
||||
package_json_raw_json_api = []
|
||||
## [Yarn Plug'n'Play](https://yarnpkg.com/features/pnp)
|
||||
yarn_pnp = ["pnp"]
|
||||
# For codspeed benchmark
|
||||
|
||||
+16
-25
@@ -283,33 +283,24 @@ fn bench_package_json_deserialization(c: &mut Criterion) {
|
||||
let test_path = PathBuf::from("/test/package.json");
|
||||
let test_realpath = test_path.clone();
|
||||
|
||||
group.bench_function("small", |b| {
|
||||
b.iter(|| {
|
||||
PackageJson::parse(test_path.clone(), test_realpath.clone(), small_json)
|
||||
.expect("Failed to parse small JSON");
|
||||
});
|
||||
});
|
||||
let data = [
|
||||
("small", small_json.to_string()),
|
||||
("medium", medium_json.to_string()),
|
||||
("large", large_json.to_string()),
|
||||
("complex_real", complex_json),
|
||||
];
|
||||
|
||||
group.bench_function("medium", |b| {
|
||||
b.iter(|| {
|
||||
PackageJson::parse(test_path.clone(), test_realpath.clone(), medium_json)
|
||||
.expect("Failed to parse medium JSON");
|
||||
for (name, json) in data {
|
||||
group.bench_function(name, |b| {
|
||||
b.iter_with_setup_wrapper(|runner| {
|
||||
let json = json.clone();
|
||||
runner.run(|| {
|
||||
PackageJson::parse(test_path.clone(), test_realpath.clone(), json)
|
||||
.expect("Failed to parse JSON");
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
group.bench_function("large", |b| {
|
||||
b.iter(|| {
|
||||
PackageJson::parse(test_path.clone(), test_realpath.clone(), large_json)
|
||||
.expect("Failed to parse large JSON");
|
||||
});
|
||||
});
|
||||
|
||||
group.bench_function("complex_real", |b| {
|
||||
b.iter(|| {
|
||||
PackageJson::parse(test_path.clone(), test_realpath.clone(), &complex_json)
|
||||
.expect("Failed to parse complex JSON");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
group.finish();
|
||||
}
|
||||
|
||||
@@ -96,6 +96,7 @@ allow = [
|
||||
"Unicode-3.0",
|
||||
"BSD-2-Clause",
|
||||
"MPL-2.0",
|
||||
"Zlib",
|
||||
# "Apache-2.0 WITH LLVM-exception",
|
||||
]
|
||||
# The confidence threshold for detecting a license from license text.
|
||||
|
||||
Vendored
+2
-2
@@ -120,9 +120,9 @@ impl<Fs: FileSystem> Cache<Fs> {
|
||||
} else {
|
||||
package_json_path.clone()
|
||||
};
|
||||
PackageJson::parse(package_json_path.clone(), real_path, &package_json_string)
|
||||
PackageJson::parse(package_json_path.clone(), real_path, package_json_string)
|
||||
.map(|package_json| Some(Arc::new(package_json)))
|
||||
.map_err(|error| ResolveError::from_serde_json_error(package_json_path, &error))
|
||||
.map_err(|error| ResolveError::from_simd_json_error(package_json_path, &error))
|
||||
})
|
||||
.cloned();
|
||||
// https://github.com/webpack/enhanced-resolve/blob/58464fc7cb56673c9aa849e68e6300239601e615/lib/DescriptionFileUtils.js#L68-L82
|
||||
|
||||
@@ -135,6 +135,17 @@ impl ResolveError {
|
||||
column: error.column(),
|
||||
})
|
||||
}
|
||||
|
||||
#[cold]
|
||||
#[must_use]
|
||||
pub fn from_simd_json_error(path: PathBuf, error: &simd_json::Error) -> Self {
|
||||
Self::Json(JSONError {
|
||||
path,
|
||||
message: error.to_string(),
|
||||
line: 0, // simd_json doesn't provide line/column info
|
||||
column: 0,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Error for [ResolveError::Specifier]
|
||||
|
||||
+1
-1
@@ -75,7 +75,7 @@ pub use crate::{
|
||||
},
|
||||
package_json::{
|
||||
ImportsExportsArray, ImportsExportsEntry, ImportsExportsKind, ImportsExportsMap,
|
||||
PackageJson, PackageType,
|
||||
PackageJson, PackageType, SideEffects,
|
||||
},
|
||||
path::PathUtil,
|
||||
resolution::{ModuleType, Resolution},
|
||||
|
||||
+165
-125
@@ -6,19 +6,29 @@ use std::{
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
use serde_json::Value as JSONValue;
|
||||
use simd_json::{BorrowedValue, prelude::*};
|
||||
|
||||
use crate::{ResolveError, path::PathUtil};
|
||||
|
||||
pub type JSONMap = serde_json::Map<String, JSONValue>;
|
||||
// Use simd_json's Object type which handles the hasher correctly based on features
|
||||
type BorrowedObject<'a> = simd_json::value::borrowed::Object<'a>;
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub enum PackageType {
|
||||
CommonJs,
|
||||
Module,
|
||||
}
|
||||
|
||||
impl PackageType {
|
||||
fn from_str(s: &str) -> Option<Self> {
|
||||
match s {
|
||||
"commonjs" => Some(Self::CommonJs),
|
||||
"module" => Some(Self::Module),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for PackageType {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
@@ -36,11 +46,26 @@ pub enum ImportsExportsKind {
|
||||
Invalid,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub enum SideEffects<'a> {
|
||||
Bool(bool),
|
||||
String(&'a str),
|
||||
Array(Vec<&'a str>),
|
||||
}
|
||||
|
||||
self_cell::self_cell! {
|
||||
struct PackageJsonCell {
|
||||
owner: Vec<u8>,
|
||||
|
||||
#[covariant]
|
||||
dependent: BorrowedValue,
|
||||
}
|
||||
}
|
||||
|
||||
/// Serde implementation for the deserialized `package.json`.
|
||||
///
|
||||
/// This implementation is used by the [crate::Cache] and enabled through the
|
||||
/// `fs_cache` feature.
|
||||
#[derive(Debug, Default)]
|
||||
pub struct PackageJson {
|
||||
/// Path to `package.json`. Contains the `package.json` filename.
|
||||
pub path: PathBuf,
|
||||
@@ -48,20 +73,18 @@ pub struct PackageJson {
|
||||
/// Realpath to `package.json`. Contains the `package.json` filename.
|
||||
pub realpath: PathBuf,
|
||||
|
||||
/// Name of the package.
|
||||
pub name: Option<String>,
|
||||
cell: PackageJsonCell,
|
||||
}
|
||||
|
||||
/// The "type" field.
|
||||
///
|
||||
/// <https://nodejs.org/api/packages.html#type>
|
||||
pub r#type: Option<PackageType>,
|
||||
|
||||
/// The "sideEffects" field.
|
||||
///
|
||||
/// <https://webpack.js.org/guides/tree-shaking>
|
||||
pub side_effects: Option<JSONValue>,
|
||||
|
||||
raw_json: std::sync::Arc<JSONValue>,
|
||||
impl fmt::Debug for PackageJson {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("PackageJson")
|
||||
.field("path", &self.path)
|
||||
.field("realpath", &self.realpath)
|
||||
.field("name", &self.name())
|
||||
.field("type", &self.r#type())
|
||||
.finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
impl PackageJson {
|
||||
@@ -106,7 +129,23 @@ impl PackageJson {
|
||||
/// <https://nodejs.org/api/packages.html#name>
|
||||
#[must_use]
|
||||
pub fn name(&self) -> Option<&str> {
|
||||
self.name.as_deref()
|
||||
self.cell
|
||||
.borrow_dependent()
|
||||
.as_object()
|
||||
.and_then(|obj| obj.get("name"))
|
||||
.and_then(|v| v.as_str())
|
||||
}
|
||||
|
||||
/// Version of the package.
|
||||
///
|
||||
/// <https://nodejs.org/api/packages.html#name>
|
||||
#[must_use]
|
||||
pub fn version(&self) -> Option<&str> {
|
||||
self.cell
|
||||
.borrow_dependent()
|
||||
.as_object()
|
||||
.and_then(|obj| obj.get("version"))
|
||||
.and_then(|v| v.as_str())
|
||||
}
|
||||
|
||||
/// Returns the package type, if one is configured in the `package.json`.
|
||||
@@ -114,7 +153,44 @@ impl PackageJson {
|
||||
/// <https://nodejs.org/api/packages.html#type>
|
||||
#[must_use]
|
||||
pub fn r#type(&self) -> Option<PackageType> {
|
||||
self.r#type
|
||||
self.cell
|
||||
.borrow_dependent()
|
||||
.as_object()
|
||||
.and_then(|obj| obj.get("type"))
|
||||
.and_then(|v| v.as_str())
|
||||
.and_then(PackageType::from_str)
|
||||
}
|
||||
|
||||
/// The "sideEffects" field.
|
||||
///
|
||||
/// <https://webpack.js.org/guides/tree-shaking>
|
||||
#[must_use]
|
||||
pub fn side_effects(&self) -> Option<SideEffects<'_>> {
|
||||
self.cell.borrow_dependent().as_object().and_then(|obj| obj.get("sideEffects")).and_then(
|
||||
|value| match value {
|
||||
BorrowedValue::Static(simd_json::StaticNode::Bool(b)) => {
|
||||
Some(SideEffects::Bool(*b))
|
||||
}
|
||||
BorrowedValue::String(s) => Some(SideEffects::String(s.as_ref())),
|
||||
BorrowedValue::Array(arr) => {
|
||||
let strings: Vec<&str> = arr.iter().filter_map(|v| v.as_str()).collect();
|
||||
Some(SideEffects::Array(strings))
|
||||
}
|
||||
_ => None,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
/// The "exports" field allows defining the entry points of a package.
|
||||
///
|
||||
/// <https://nodejs.org/api/packages.html#exports>
|
||||
#[must_use]
|
||||
pub fn exports(&self) -> Option<ImportsExportsEntry<'_>> {
|
||||
self.cell
|
||||
.borrow_dependent()
|
||||
.as_object()
|
||||
.and_then(|obj| obj.get("exports"))
|
||||
.map(ImportsExportsEntry)
|
||||
}
|
||||
|
||||
/// The "main" field defines the entry point of a package when imported by
|
||||
@@ -130,10 +206,13 @@ impl PackageJson {
|
||||
&'a self,
|
||||
main_fields: &'a [String],
|
||||
) -> impl Iterator<Item = &'a str> + 'a {
|
||||
let json_value = self.cell.borrow_dependent();
|
||||
let json_object = json_value.as_object();
|
||||
|
||||
main_fields
|
||||
.iter()
|
||||
.filter_map(|main_field| self.raw_json.get(main_field))
|
||||
.filter_map(JSONValue::as_str)
|
||||
.filter_map(move |main_field| json_object.and_then(|obj| obj.get(main_field.as_str())))
|
||||
.filter_map(|v| v.as_str())
|
||||
}
|
||||
|
||||
/// The "exports" field allows defining the entry points of a package when
|
||||
@@ -145,10 +224,12 @@ impl PackageJson {
|
||||
&'a self,
|
||||
exports_fields: &'a [Vec<String>],
|
||||
) -> impl Iterator<Item = ImportsExportsEntry<'a>> + 'a {
|
||||
let json_value = self.cell.borrow_dependent();
|
||||
|
||||
exports_fields
|
||||
.iter()
|
||||
.filter_map(|object_path| {
|
||||
self.raw_json
|
||||
.filter_map(move |object_path| {
|
||||
json_value
|
||||
.as_object()
|
||||
.and_then(|json_object| Self::get_value_by_path(json_object, object_path))
|
||||
})
|
||||
@@ -164,13 +245,15 @@ impl PackageJson {
|
||||
&'a self,
|
||||
imports_fields: &'a [Vec<String>],
|
||||
) -> impl Iterator<Item = ImportsExportsMap<'a>> + 'a {
|
||||
let json_value = self.cell.borrow_dependent();
|
||||
|
||||
imports_fields
|
||||
.iter()
|
||||
.filter_map(|object_path| {
|
||||
self.raw_json
|
||||
.filter_map(move |object_path| {
|
||||
json_value
|
||||
.as_object()
|
||||
.and_then(|json_object| Self::get_value_by_path(json_object, object_path))
|
||||
.and_then(JSONValue::as_object)
|
||||
.and_then(|v| v.as_object())
|
||||
})
|
||||
.map(ImportsExportsMap)
|
||||
}
|
||||
@@ -187,13 +270,14 @@ impl PackageJson {
|
||||
) -> Result<Option<&'a str>, ResolveError> {
|
||||
for object in self.browser_fields(alias_fields) {
|
||||
if let Some(request) = request {
|
||||
// Find matching key in object
|
||||
if let Some(value) = object.get(request) {
|
||||
return Self::alias_value(path, value);
|
||||
}
|
||||
} else {
|
||||
let dir = self.path.parent().unwrap();
|
||||
for (key, value) in object {
|
||||
let joined = dir.normalize_with(key);
|
||||
let joined = dir.normalize_with(key.as_ref());
|
||||
if joined == path {
|
||||
return Self::alias_value(path, value);
|
||||
}
|
||||
@@ -207,49 +291,40 @@ impl PackageJson {
|
||||
///
|
||||
/// # Panics
|
||||
/// # Errors
|
||||
pub fn parse(path: PathBuf, realpath: PathBuf, json: &str) -> Result<Self, serde_json::Error> {
|
||||
let json = json.trim_start_matches("\u{feff}"); // strip bom
|
||||
let mut raw_json: JSONValue = serde_json::from_str(json)?;
|
||||
let mut package_json = Self::default();
|
||||
|
||||
if let Some(json_object) = raw_json.as_object_mut() {
|
||||
// Remove large fields that are useless for pragmatic use.
|
||||
#[cfg(feature = "package_json_raw_json_api")]
|
||||
{
|
||||
json_object.remove("description");
|
||||
json_object.remove("keywords");
|
||||
json_object.remove("scripts");
|
||||
json_object.remove("dependencies");
|
||||
json_object.remove("devDependencies");
|
||||
json_object.remove("peerDependencies");
|
||||
json_object.remove("optionalDependencies");
|
||||
}
|
||||
|
||||
// Add name, type and sideEffects.
|
||||
package_json.name =
|
||||
json_object.get("name").and_then(|field| field.as_str()).map(ToString::to_string);
|
||||
package_json.r#type =
|
||||
json_object.get("type").and_then(|ty| serde_json::from_value(ty.clone()).ok());
|
||||
package_json.side_effects = json_object.get("sideEffects").cloned();
|
||||
pub fn parse(path: PathBuf, realpath: PathBuf, json: String) -> Result<Self, simd_json::Error> {
|
||||
// Strip BOM in place by replacing with spaces (no reallocation)
|
||||
let mut json_bytes = json.into_bytes();
|
||||
if json_bytes.starts_with(b"\xEF\xBB\xBF") {
|
||||
json_bytes[0] = b' ';
|
||||
json_bytes[1] = b' ';
|
||||
json_bytes[2] = b' ';
|
||||
}
|
||||
|
||||
package_json.path = path;
|
||||
package_json.realpath = realpath;
|
||||
package_json.raw_json = std::sync::Arc::new(raw_json);
|
||||
Ok(package_json)
|
||||
// Create the self-cell with the JSON bytes and parsed BorrowedValue
|
||||
let cell = PackageJsonCell::try_new(json_bytes.clone(), |bytes| {
|
||||
// We need a mutable slice from our owned data
|
||||
// SAFETY: We're creating a mutable reference to the owned data.
|
||||
// The self_cell ensures this reference is valid for the lifetime of the cell.
|
||||
let slice =
|
||||
unsafe { std::slice::from_raw_parts_mut(bytes.as_ptr().cast_mut(), bytes.len()) };
|
||||
simd_json::to_borrowed_value(slice)
|
||||
})?;
|
||||
|
||||
Ok(Self { path, realpath, cell })
|
||||
}
|
||||
|
||||
fn get_value_by_path<'a>(
|
||||
fields: &'a serde_json::Map<String, JSONValue>,
|
||||
fields: &'a BorrowedObject<'a>,
|
||||
path: &[String],
|
||||
) -> Option<&'a JSONValue> {
|
||||
) -> Option<&'a BorrowedValue<'a>> {
|
||||
if path.is_empty() {
|
||||
return None;
|
||||
}
|
||||
let mut value = fields.get(&path[0])?;
|
||||
let mut value = fields.get(path[0].as_str())?;
|
||||
|
||||
for key in path.iter().skip(1) {
|
||||
if let Some(inner_value) = value.as_object().and_then(|o| o.get(key)) {
|
||||
value = inner_value;
|
||||
if let Some(obj) = value.as_object() {
|
||||
value = obj.get(key.as_str())?;
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
@@ -257,21 +332,6 @@ impl PackageJson {
|
||||
Some(value)
|
||||
}
|
||||
|
||||
/// Raw serde json value of `package.json`.
|
||||
///
|
||||
/// This is currently used in Rspack for:
|
||||
/// * getting the `sideEffects` field
|
||||
/// * query in <https://www.rspack.dev/config/module.html#ruledescriptiondata> - search on GitHub indicates query on the `type` field.
|
||||
///
|
||||
/// To reduce overall memory consumption, large fields that useless for pragmatic use are removed.
|
||||
/// They are: `description`, `keywords`, `scripts`,
|
||||
/// `dependencies` and `devDependencies`, `peerDependencies`, `optionalDependencies`.
|
||||
#[cfg(feature = "package_json_raw_json_api")]
|
||||
#[must_use]
|
||||
pub const fn raw_json(&self) -> &std::sync::Arc<JSONValue> {
|
||||
&self.raw_json
|
||||
}
|
||||
|
||||
/// The "browser" field is provided by a module author as a hint to javascript bundlers or component tools when packaging modules for client side use.
|
||||
/// Multiple values are configured by [ResolveOptions::alias_fields].
|
||||
///
|
||||
@@ -279,9 +339,11 @@ impl PackageJson {
|
||||
pub(crate) fn browser_fields<'a>(
|
||||
&'a self,
|
||||
alias_fields: &'a [Vec<String>],
|
||||
) -> impl Iterator<Item = &'a JSONMap> + 'a {
|
||||
alias_fields.iter().filter_map(|object_path| {
|
||||
self.raw_json
|
||||
) -> impl Iterator<Item = &'a BorrowedObject<'a>> + 'a {
|
||||
let json_value = self.cell.borrow_dependent();
|
||||
|
||||
alias_fields.iter().filter_map(move |object_path| {
|
||||
json_value
|
||||
.as_object()
|
||||
.and_then(|json_object| Self::get_value_by_path(json_object, object_path))
|
||||
// Only object is valid, all other types are invalid
|
||||
@@ -292,57 +354,59 @@ impl PackageJson {
|
||||
|
||||
pub(crate) fn alias_value<'a>(
|
||||
key: &Path,
|
||||
value: &'a JSONValue,
|
||||
value: &'a BorrowedValue<'a>,
|
||||
) -> Result<Option<&'a str>, ResolveError> {
|
||||
match value {
|
||||
JSONValue::String(value) => Ok(Some(value.as_str())),
|
||||
JSONValue::Bool(b) if !b => Err(ResolveError::Ignored(key.to_path_buf())),
|
||||
BorrowedValue::String(s) => Ok(Some(s.as_ref())),
|
||||
BorrowedValue::Static(simd_json::StaticNode::Bool(false)) => {
|
||||
Err(ResolveError::Ignored(key.to_path_buf()))
|
||||
}
|
||||
_ => Ok(None),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ImportsExportsEntry<'a>(pub(crate) &'a JSONValue);
|
||||
pub struct ImportsExportsEntry<'a>(pub(crate) &'a BorrowedValue<'a>);
|
||||
|
||||
impl<'a> ImportsExportsEntry<'a> {
|
||||
#[must_use]
|
||||
pub fn kind(&self) -> ImportsExportsKind {
|
||||
match &self.0 {
|
||||
JSONValue::String(_) => ImportsExportsKind::String,
|
||||
JSONValue::Array(_) => ImportsExportsKind::Array,
|
||||
JSONValue::Object(_) => ImportsExportsKind::Map,
|
||||
_ => ImportsExportsKind::Invalid,
|
||||
match self.0 {
|
||||
BorrowedValue::String(_) => ImportsExportsKind::String,
|
||||
BorrowedValue::Array(_) => ImportsExportsKind::Array,
|
||||
BorrowedValue::Object(_) => ImportsExportsKind::Map,
|
||||
BorrowedValue::Static(_) => ImportsExportsKind::Invalid,
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn as_string(&self) -> Option<&'a str> {
|
||||
match &self.0 {
|
||||
JSONValue::String(string) => Some(string),
|
||||
match self.0 {
|
||||
BorrowedValue::String(s) => Some(s.as_ref()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn as_array(&self) -> Option<ImportsExportsArray<'a>> {
|
||||
match &self.0 {
|
||||
JSONValue::Array(vec) => Some(ImportsExportsArray(vec)),
|
||||
match self.0 {
|
||||
BorrowedValue::Array(arr) => Some(ImportsExportsArray(arr)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn as_map(&self) -> Option<ImportsExportsMap<'a>> {
|
||||
match &self.0 {
|
||||
JSONValue::Object(map) => Some(ImportsExportsMap(map)),
|
||||
match self.0 {
|
||||
BorrowedValue::Object(obj) => Some(ImportsExportsMap(obj)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ImportsExportsArray<'a>(&'a Vec<JSONValue>);
|
||||
pub struct ImportsExportsArray<'a>(&'a [BorrowedValue<'a>]);
|
||||
|
||||
impl<'a> ImportsExportsArray<'a> {
|
||||
#[must_use]
|
||||
@@ -356,12 +420,12 @@ impl<'a> ImportsExportsArray<'a> {
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> impl Iterator<Item = ImportsExportsEntry<'a>> {
|
||||
ImportsExportsArrayIter { vec: self.0, index: 0 }
|
||||
ImportsExportsArrayIter { slice: self.0, index: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
struct ImportsExportsArrayIter<'a> {
|
||||
vec: &'a Vec<JSONValue>,
|
||||
slice: &'a [BorrowedValue<'a>],
|
||||
index: usize,
|
||||
}
|
||||
|
||||
@@ -369,7 +433,7 @@ impl<'a> Iterator for ImportsExportsArrayIter<'a> {
|
||||
type Item = ImportsExportsEntry<'a>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.vec.get(self.index).map(|value| {
|
||||
self.slice.get(self.index).map(|value| {
|
||||
self.index += 1;
|
||||
ImportsExportsEntry(value)
|
||||
})
|
||||
@@ -377,7 +441,7 @@ impl<'a> Iterator for ImportsExportsArrayIter<'a> {
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ImportsExportsMap<'a>(pub(crate) &'a JSONMap);
|
||||
pub struct ImportsExportsMap<'a>(pub(crate) &'a BorrowedObject<'a>);
|
||||
|
||||
impl<'a> ImportsExportsMap<'a> {
|
||||
pub fn get(&self, key: &str) -> Option<ImportsExportsEntry<'a>> {
|
||||
@@ -385,34 +449,10 @@ impl<'a> ImportsExportsMap<'a> {
|
||||
}
|
||||
|
||||
pub fn keys(&self) -> impl Iterator<Item = &'a str> {
|
||||
ImportsExportsMapKeysIter { inner: self.0.keys() }
|
||||
self.0.keys().map(std::convert::AsRef::as_ref)
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> impl Iterator<Item = (&'a str, ImportsExportsEntry<'a>)> {
|
||||
ImportsExportsMapIter { inner: self.0.iter() }
|
||||
}
|
||||
}
|
||||
|
||||
struct ImportsExportsMapIter<'a> {
|
||||
inner: serde_json::map::Iter<'a>,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for ImportsExportsMapIter<'a> {
|
||||
type Item = (&'a str, ImportsExportsEntry<'a>);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.inner.next().map(|(key, value)| (key.as_str(), ImportsExportsEntry(value)))
|
||||
}
|
||||
}
|
||||
|
||||
struct ImportsExportsMapKeysIter<'a> {
|
||||
inner: serde_json::map::Keys<'a>,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for ImportsExportsMapKeysIter<'a> {
|
||||
type Item = &'a str;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.inner.next().map(String::as_str)
|
||||
self.0.iter().map(|(k, v)| (k.as_ref(), ImportsExportsEntry(v)))
|
||||
}
|
||||
}
|
||||
|
||||
+180
-177
File diff suppressed because it is too large
Load Diff
+95
-92
@@ -88,7 +88,7 @@ fn shared_resolvers() {
|
||||
// } else {
|
||||
// console.log(`expect: Some(vec!${JSON.stringify(c.expect)}),`)
|
||||
// }
|
||||
// console.log(`imports_field: imports_field(json!(${JSON.stringify(c.suite[0], null, 2)})),`)
|
||||
// console.log(`imports_field: imports_field(&json!(${JSON.stringify(c.suite[0], null, 2)})),`)
|
||||
// console.log(`request: "${c.suite[1]}",`)
|
||||
// console.log(`condition_names: vec!${JSON.stringify(c.suite[2])},`)
|
||||
// console.log("},")
|
||||
@@ -102,11 +102,14 @@ struct TestCase {
|
||||
condition_names: Vec<&'static str>,
|
||||
}
|
||||
|
||||
fn imports_field(value: serde_json::Value) -> ImportsExportsMap<'static> {
|
||||
let serde_json::Value::Object(map) = value else {
|
||||
fn imports_field(value: &serde_json::Value) -> ImportsExportsMap<'static> {
|
||||
// Serialize back to JSON string and parse with simd_json
|
||||
let json_str = serde_json::to_string(value).unwrap();
|
||||
let bytes = Box::leak::<'static>(Box::new(json_str.into_bytes()));
|
||||
let borrowed = simd_json::to_borrowed_value(bytes).unwrap();
|
||||
let simd_json::BorrowedValue::Object(map) = borrowed else {
|
||||
panic!("Expected an object");
|
||||
};
|
||||
// Don't do this at home:
|
||||
let map = Box::leak::<'static>(Box::new(map));
|
||||
ImportsExportsMap(map)
|
||||
}
|
||||
@@ -118,7 +121,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "sample #1",
|
||||
expect: Some(vec!["./dist/test/file.js"]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#abc/": {
|
||||
"import": [
|
||||
"./dist/",
|
||||
@@ -135,7 +138,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "sample #1",
|
||||
expect: Some(vec!["./src/test/file.js"]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#abc/": {
|
||||
"import": [
|
||||
"./src/"
|
||||
@@ -150,7 +153,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "sample #2",
|
||||
expect: Some(vec!["./data/timezones/pdt.mjs"]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#1/timezones/": "./data/timezones/"
|
||||
})),
|
||||
request: "#1/timezones/pdt.mjs",
|
||||
@@ -159,7 +162,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "sample #3",
|
||||
expect: Some(vec!["./data/timezones/timezones/pdt.mjs"]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#aaa/": "./data/timezones/",
|
||||
"#a/": "./data/timezones/"
|
||||
})),
|
||||
@@ -169,7 +172,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "sample #4",
|
||||
expect: Some(vec![]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/lib/": {
|
||||
"browser": [
|
||||
"./browser/"
|
||||
@@ -185,7 +188,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "sample #5",
|
||||
expect: Some(vec!["./browser/index.js"]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/lib/": {
|
||||
"browser": [
|
||||
"./browser/"
|
||||
@@ -202,7 +205,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "sample #6",
|
||||
expect: Some(vec![]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/dist/a": "./dist/index.js"
|
||||
})),
|
||||
request: "#a/dist/aaa",
|
||||
@@ -211,7 +214,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "sample #7",
|
||||
expect: Some(vec![]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/a/a/": "./dist/index.js"
|
||||
})),
|
||||
request: "#a/a/a",
|
||||
@@ -220,7 +223,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "sample #8",
|
||||
expect: Some(vec![]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a": "./index.js"
|
||||
})),
|
||||
request: "#a/timezones/pdt.mjs",
|
||||
@@ -229,7 +232,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "sample #9",
|
||||
expect: Some(vec!["./main.js"]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/index.js": "./main.js"
|
||||
})),
|
||||
request: "#a/index.js",
|
||||
@@ -238,7 +241,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "sample #10",
|
||||
expect: Some(vec!["./ok.js"]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/#foo": "./ok.js",
|
||||
"#a/module": "./ok.js",
|
||||
"#a/🎉": "./ok.js",
|
||||
@@ -252,7 +255,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "sample #11",
|
||||
expect: Some(vec!["./ok.js"]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/#foo": "./ok.js",
|
||||
"#a/module": "./ok.js",
|
||||
"#a/🎉": "./ok.js",
|
||||
@@ -266,7 +269,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "sample #12",
|
||||
expect: Some(vec!["./ok.js#abc"]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/#foo": "./ok.js",
|
||||
"#a/module": "./ok.js",
|
||||
"#a/🎉": "./ok.js",
|
||||
@@ -280,7 +283,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "sample #13",
|
||||
expect: Some(vec!["./ok.js?abc"]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/#foo": "./ok.js",
|
||||
"#a/module": "./ok.js",
|
||||
"#a/🎉": "./ok.js",
|
||||
@@ -294,7 +297,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "sample #14",
|
||||
expect: Some(vec!["./🎉.js"]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/#foo": "./ok.js",
|
||||
"#a/module": "./ok.js",
|
||||
"#a/🎉": "./ok.js",
|
||||
@@ -308,7 +311,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "sample #15",
|
||||
expect: Some(vec!["./%F0%9F%8E%89.js"]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/#foo": "./ok.js",
|
||||
"#a/module": "./ok.js",
|
||||
"#a/🎉": "./ok.js",
|
||||
@@ -322,7 +325,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "sample #16",
|
||||
expect: Some(vec!["./ok.js"]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/#foo": "./ok.js",
|
||||
"#a/module": "./ok.js",
|
||||
"#a/🎉": "./ok.js",
|
||||
@@ -336,7 +339,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "sample #17",
|
||||
expect: Some(vec!["./other.js"]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/#foo": "./ok.js",
|
||||
"#a/module": "./ok.js",
|
||||
"#a/🎉": "./ok.js",
|
||||
@@ -350,7 +353,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "sample #18",
|
||||
expect: Some(vec!["./ok.js"]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/#foo": "./ok.js",
|
||||
"#a/module": "./ok.js",
|
||||
"#a/🎉": "./ok.js",
|
||||
@@ -364,7 +367,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "sample #19",
|
||||
expect: Some(vec![]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/#foo": "./ok.js",
|
||||
"#a/module": "./ok.js",
|
||||
"#a/🎉": "./ok.js",
|
||||
@@ -378,7 +381,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "sample #20",
|
||||
expect: Some(vec![]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/#foo": "./ok.js",
|
||||
"#a/module": "./ok.js",
|
||||
"#a/🎉": "./ok.js",
|
||||
@@ -392,7 +395,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "sample #21",
|
||||
expect: Some(vec!["./d?e?f"]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/a?b?c/": "./"
|
||||
})),
|
||||
request: "#a/a?b?c/d?e?f",
|
||||
@@ -403,7 +406,7 @@ fn test_cases() {
|
||||
// We throw InvalidPackageTarget
|
||||
expect: None,
|
||||
// expect: Some(vec!["/user/a/index"]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/": "/user/a/"
|
||||
})),
|
||||
request: "#a/index",
|
||||
@@ -412,7 +415,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "path tree edge case #1",
|
||||
expect: Some(vec!["./A/b/d.js"]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/": "./A/",
|
||||
"#a/b/c": "./c.js"
|
||||
})),
|
||||
@@ -422,7 +425,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "path tree edge case #2",
|
||||
expect: Some(vec!["./A/c.js"]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/": "./A/",
|
||||
"#a/b": "./b.js"
|
||||
})),
|
||||
@@ -432,7 +435,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "path tree edge case #3",
|
||||
expect: Some(vec!["./A/b/c/d.js"]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/": "./A/",
|
||||
"#a/b/c/d": "./c.js"
|
||||
})),
|
||||
@@ -442,7 +445,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "Direct mapping #1",
|
||||
expect: Some(vec!["./dist/index.js"]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a": "./dist/index.js"
|
||||
})),
|
||||
request: "#a",
|
||||
@@ -451,7 +454,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "Direct mapping #2",
|
||||
expect: Some(vec![]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/": "./"
|
||||
})),
|
||||
request: "#a",
|
||||
@@ -460,7 +463,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "Direct mapping #3",
|
||||
expect: Some(vec!["./dist/a.js"]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/": "./dist/",
|
||||
"#a/index.js": "./dist/a.js"
|
||||
})),
|
||||
@@ -470,7 +473,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "Direct mapping #4",
|
||||
expect: Some(vec!["./index.js"]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/": {
|
||||
"browser": [
|
||||
"./browser/"
|
||||
@@ -486,7 +489,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "Direct mapping #5",
|
||||
expect: Some(vec![]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/": {
|
||||
"browser": [
|
||||
"./browser/"
|
||||
@@ -502,7 +505,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "Direct mapping #6",
|
||||
expect: Some(vec!["./index.js"]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a": {
|
||||
"browser": "./index.js",
|
||||
"node": "./src/node/index.js",
|
||||
@@ -515,7 +518,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "Direct mapping #7",
|
||||
expect: Some(vec!["./src/index.js"]), // `enhanced_resolve` is `None`
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a": {
|
||||
"default": "./src/index.js",
|
||||
"browser": "./index.js",
|
||||
@@ -528,7 +531,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "Direct mapping #8",
|
||||
expect: Some(vec!["./src/index.js"]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a": {
|
||||
"browser": "./index.js",
|
||||
"node": "./src/node/index.js",
|
||||
@@ -541,7 +544,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "Direct mapping #9",
|
||||
expect: Some(vec!["./index"]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a": "./index"
|
||||
})),
|
||||
request: "#a",
|
||||
@@ -550,7 +553,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "Direct mapping #10",
|
||||
expect: Some(vec!["./index.js"]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/index": "./index.js"
|
||||
})),
|
||||
request: "#a/index",
|
||||
@@ -561,7 +564,7 @@ fn test_cases() {
|
||||
// We throw InvalidPackageTarget
|
||||
// expect: Some(vec!["b"]),
|
||||
expect: None,
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a": "b"
|
||||
})),
|
||||
request: "#a",
|
||||
@@ -572,7 +575,7 @@ fn test_cases() {
|
||||
// We throw InvalidPackageTarget
|
||||
// expect: Some(vec!["b/index"]),
|
||||
expect: None,
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/": "b/"
|
||||
})),
|
||||
request: "#a/index",
|
||||
@@ -583,7 +586,7 @@ fn test_cases() {
|
||||
// We throw InvalidPackageTarget
|
||||
// expect: Some(vec!["b#anotherhashishere"]),
|
||||
expect: None,
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a?q=a#hashishere": "b#anotherhashishere"
|
||||
})),
|
||||
request: "#a?q=a#hashishere",
|
||||
@@ -592,7 +595,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "Direct and conditional mapping #1",
|
||||
expect: Some(vec![]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a": [
|
||||
{
|
||||
"browser": "./browser.js"
|
||||
@@ -611,7 +614,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "Direct and conditional mapping #2",
|
||||
expect: Some(vec!["./import.mjs"]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a": [
|
||||
{
|
||||
"browser": "./browser.js"
|
||||
@@ -630,7 +633,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "Direct and conditional mapping #3",
|
||||
expect: Some(vec!["./require.js"]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a": [
|
||||
{
|
||||
"browser": "./browser.js"
|
||||
@@ -650,7 +653,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "Direct and conditional mapping #3",
|
||||
expect: Some(vec!["./import.mjs"]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a": [
|
||||
{
|
||||
"browser": "./browser.js"
|
||||
@@ -666,7 +669,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "Direct and conditional mapping #4",
|
||||
expect: Some(vec!["./require.js"]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a": [
|
||||
{
|
||||
"browser": "./browser.js"
|
||||
@@ -691,7 +694,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "Direct and conditional mapping #4",
|
||||
expect: Some(vec!["./import.mjs"]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a": [
|
||||
{
|
||||
"browser": "./browser.js"
|
||||
@@ -711,7 +714,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "Direct and conditional mapping #4",
|
||||
expect: Some(vec![]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a": [
|
||||
{
|
||||
"browser": "./browser.js"
|
||||
@@ -729,7 +732,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "mapping to a folder root #1",
|
||||
expect: Some(vec![]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#timezones": "./data/timezones/"
|
||||
})),
|
||||
request: "#timezones/pdt.mjs",
|
||||
@@ -738,7 +741,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "mapping to a folder root #2",
|
||||
expect: None,
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#timezones/": "./data/timezones"
|
||||
})),
|
||||
request: "#timezones/pdt.mjs",
|
||||
@@ -747,7 +750,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "mapping to a folder root #3",
|
||||
expect: Some(vec!["./data/timezones/pdt/index.mjs"]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#timezones/pdt/": "./data/timezones/pdt/"
|
||||
})),
|
||||
request: "#timezones/pdt/index.mjs",
|
||||
@@ -756,7 +759,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "mapping to a folder root #4",
|
||||
expect: Some(vec!["./timezones/pdt.mjs"]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/": "./timezones/"
|
||||
})),
|
||||
request: "#a/pdt.mjs",
|
||||
@@ -765,7 +768,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "mapping to a folder root #5",
|
||||
expect: Some(vec!["./timezones/pdt.mjs"]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/": "./"
|
||||
})),
|
||||
request: "#a/timezones/pdt.mjs",
|
||||
@@ -774,7 +777,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "mapping to a folder root #6",
|
||||
expect: None,
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/": "."
|
||||
})),
|
||||
request: "#a/timezones/pdt.mjs",
|
||||
@@ -783,7 +786,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "mapping to a folder root #7",
|
||||
expect: Some(vec![]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a": "./"
|
||||
})),
|
||||
request: "#a/timezones/pdt.mjs",
|
||||
@@ -792,7 +795,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "the longest matching path prefix is prioritized #1",
|
||||
expect: Some(vec!["./lib/index.mjs"]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/": "./",
|
||||
"#a/dist/": "./lib/"
|
||||
})),
|
||||
@@ -802,7 +805,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "the longest matching path prefix is prioritized #2",
|
||||
expect: Some(vec!["./dist/utils/index.js"]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/dist/utils/": "./dist/utils/",
|
||||
"#a/dist/": "./lib/"
|
||||
})),
|
||||
@@ -812,7 +815,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "the longest matching path prefix is prioritized #3",
|
||||
expect: Some(vec!["./dist/utils/index.js"]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/dist/utils/index.js": "./dist/utils/index.js",
|
||||
"#a/dist/utils/": "./dist/utils/index.mjs",
|
||||
"#a/dist/": "./lib/"
|
||||
@@ -823,7 +826,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "the longest matching path prefix is prioritized #4",
|
||||
expect: Some(vec!["./lib/index.mjs"]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/": {
|
||||
"browser": "./browser/"
|
||||
},
|
||||
@@ -837,7 +840,7 @@ fn test_cases() {
|
||||
// This behaves differently from enhanced_resolve, because `lodash/` is an an InvalidPackageConfig
|
||||
// expect: Some(vec!["lodash/index.js"]),
|
||||
expect: Some(vec!["./utils/index.js"]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/": {
|
||||
"browser": [
|
||||
"lodash/",
|
||||
@@ -855,7 +858,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "conditional mapping folder #1",
|
||||
expect: Some(vec!["./utils/index.js"]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/": {
|
||||
"browser": [
|
||||
"./utils/"
|
||||
@@ -871,7 +874,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "conditional mapping folder #2",
|
||||
expect: Some(vec![]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/": {
|
||||
"webpack": "./wpk/",
|
||||
"browser": [
|
||||
@@ -889,7 +892,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "conditional mapping folder #3",
|
||||
expect: Some(vec!["./wpk/index.mjs"]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/": {
|
||||
"webpack": "./wpk/",
|
||||
"browser": [
|
||||
@@ -909,7 +912,7 @@ fn test_cases() {
|
||||
// We throw `PackageImportNotDefined`
|
||||
// expect: None,
|
||||
expect: Some(vec![]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"/utils/": "./a/"
|
||||
})),
|
||||
request: "#a/index.mjs",
|
||||
@@ -920,7 +923,7 @@ fn test_cases() {
|
||||
// We throw `PackageImportNotDefined`
|
||||
// expect: None,
|
||||
expect: Some(vec![]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"/utils/": {
|
||||
"browser": "./a/",
|
||||
"default": "./b/"
|
||||
@@ -932,7 +935,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "incorrect exports field #3",
|
||||
expect: Some(vec![]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/index": "./a/index.js"
|
||||
})),
|
||||
request: "#a/index.mjs",
|
||||
@@ -941,7 +944,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "incorrect exports field #4",
|
||||
expect: Some(vec![]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/index.mjs": "./a/index.js"
|
||||
})),
|
||||
request: "#a/index",
|
||||
@@ -950,7 +953,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "incorrect exports field #5",
|
||||
expect: Some(vec![]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/index": {
|
||||
"browser": "./a/index.js",
|
||||
"default": "./b/index.js"
|
||||
@@ -962,7 +965,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "incorrect exports field #6",
|
||||
expect: Some(vec![]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/index.mjs": {
|
||||
"browser": "./a/index.js",
|
||||
"default": "./b/index.js"
|
||||
@@ -976,7 +979,7 @@ fn test_cases() {
|
||||
// We don't throw in `package_imports_exports_resolve`
|
||||
// expect: None,
|
||||
expect: Some(vec![]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/": "./a/"
|
||||
})),
|
||||
request: "/utils/index.mjs",
|
||||
@@ -987,7 +990,7 @@ fn test_cases() {
|
||||
// We don't throw in `package_imports_exports_resolve`
|
||||
// expect: None,
|
||||
expect: Some(vec![]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/": {
|
||||
"browser": "./a/",
|
||||
"default": "./b/"
|
||||
@@ -1001,7 +1004,7 @@ fn test_cases() {
|
||||
// We don't throw in `package_imports_exports_resolve`, it's thrown in `package_imports_resolve`
|
||||
// expect: None,
|
||||
expect: Some(vec![]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/": {
|
||||
"browser": "./a/",
|
||||
"default": "./b/"
|
||||
@@ -1015,7 +1018,7 @@ fn test_cases() {
|
||||
// We don't throw in `package_imports_exports_resolve`, it's thrown in `package_imports_resolve`
|
||||
// expect: None,
|
||||
expect: Some(vec![]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/": {
|
||||
"browser": "./a/",
|
||||
"default": "./b/"
|
||||
@@ -1028,7 +1031,7 @@ fn test_cases() {
|
||||
name: "incorrect request #5",
|
||||
// expect: None,
|
||||
expect: Some(vec![]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/": {
|
||||
"browser": "./a/",
|
||||
"default": "./b/"
|
||||
@@ -1041,7 +1044,7 @@ fn test_cases() {
|
||||
name: "backtracking package base #1",
|
||||
// expect: Some(vec!["./dist/index"]),
|
||||
expect: Some(vec!["dist/index"]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/../../utils/": "./dist/"
|
||||
})),
|
||||
request: "#a/../../utils/index",
|
||||
@@ -1052,7 +1055,7 @@ fn test_cases() {
|
||||
// We throw InvalidPackageTarget
|
||||
// expect: Some(vec!["./dist/../../utils/index"]),
|
||||
expect: None,
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/": "./dist/"
|
||||
})),
|
||||
request: "#a/../../utils/index",
|
||||
@@ -1063,7 +1066,7 @@ fn test_cases() {
|
||||
// We throw InvalidPackageTarget
|
||||
// expect: Some(vec!["../src/index"]),
|
||||
expect: None,
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/": "../src/"
|
||||
})),
|
||||
request: "#a/index",
|
||||
@@ -1074,7 +1077,7 @@ fn test_cases() {
|
||||
// We throw InvalidPackageTarget
|
||||
// expect: Some(vec!["./utils/../../../index"]),
|
||||
expect: None,
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/": {
|
||||
"browser": "./utils/../../../"
|
||||
}
|
||||
@@ -1086,7 +1089,7 @@ fn test_cases() {
|
||||
name: "nested node_modules path #1",
|
||||
// expect: Some(vec!["moment/node_modules/lodash/dist/index.js"]),
|
||||
expect: None,
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/": {
|
||||
"browser": "moment/node_modules/"
|
||||
}
|
||||
@@ -1099,7 +1102,7 @@ fn test_cases() {
|
||||
// We throw InvalidPackageTarget
|
||||
// expect: Some(vec!["../node_modules/lodash/dist/index.js"]),
|
||||
expect: None,
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/": "../node_modules/"
|
||||
})),
|
||||
request: "#a/lodash/dist/index.js",
|
||||
@@ -1108,7 +1111,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "nested mapping #1",
|
||||
expect: Some(vec![]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/": {
|
||||
"browser": {
|
||||
"webpack": "./",
|
||||
@@ -1124,7 +1127,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "nested mapping #2",
|
||||
expect: Some(vec!["./index.js"]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/": {
|
||||
"browser": {
|
||||
"webpack": [
|
||||
@@ -1144,7 +1147,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "nested mapping #2",
|
||||
expect: Some(vec!["./node/index.js"]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/": {
|
||||
"browser": {
|
||||
"webpack": [
|
||||
@@ -1162,7 +1165,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "nested mapping #3",
|
||||
expect: Some(vec![]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/": {
|
||||
"browser": {
|
||||
"webpack": [
|
||||
@@ -1183,7 +1186,7 @@ fn test_cases() {
|
||||
// We throw NotFound
|
||||
// expect: Some(vec!["moment/node/index.js"]),
|
||||
expect: None,
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/": {
|
||||
"browser": {
|
||||
"webpack": [
|
||||
@@ -1202,7 +1205,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "nested mapping #5",
|
||||
expect: Some(vec![]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/": {
|
||||
"browser": {
|
||||
"webpack": [
|
||||
@@ -1225,7 +1228,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "nested mapping #6",
|
||||
expect: Some(vec!["./index.js"]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/": {
|
||||
"browser": {
|
||||
"webpack": [
|
||||
@@ -1249,7 +1252,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "nested mapping #6",
|
||||
expect: Some(vec!["./node/index.js"]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a/": {
|
||||
"browser": {
|
||||
"webpack": [
|
||||
@@ -1271,7 +1274,7 @@ fn test_cases() {
|
||||
TestCase {
|
||||
name: "nested mapping #7",
|
||||
expect: Some(vec!["./y.js"]),
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a": {
|
||||
"abc": {
|
||||
"def": "./x.js"
|
||||
@@ -1287,7 +1290,7 @@ fn test_cases() {
|
||||
// We throw PackageImportNotDefined
|
||||
// expect: Some(vec![]),
|
||||
expect: None,
|
||||
imports_field: imports_field(json!({
|
||||
imports_field: imports_field(&json!({
|
||||
"#a": {
|
||||
"abc": {
|
||||
"def": "./x.js",
|
||||
|
||||
@@ -9,14 +9,14 @@ use crate::{JSONError, ResolveContext, ResolveError, Resolver};
|
||||
fn incorrect_description_file_1() {
|
||||
let f = super::fixture().join("incorrect-package");
|
||||
let mut ctx = ResolveContext::default();
|
||||
let resolution = Resolver::default().resolve_with_context(f.join("pack1"), ".", &mut ctx);
|
||||
let error = ResolveError::Json(JSONError {
|
||||
path: f.join("pack1/package.json"),
|
||||
message: String::from("EOF while parsing a value at line 3 column 0"),
|
||||
line: 3,
|
||||
column: 0,
|
||||
});
|
||||
assert_eq!(resolution, Err(error));
|
||||
let error =
|
||||
Resolver::default().resolve_with_context(f.join("pack1"), ".", &mut ctx).unwrap_err();
|
||||
match error {
|
||||
ResolveError::Json(e) => {
|
||||
assert_eq!(e.path, f.join("pack1/package.json"));
|
||||
}
|
||||
_ => panic!("must be a json error."),
|
||||
}
|
||||
assert_eq!(ctx.file_dependencies, FxHashSet::from_iter([f.join("pack1/package.json")]));
|
||||
assert!(ctx.missing_dependencies.is_empty());
|
||||
}
|
||||
@@ -26,10 +26,11 @@ fn incorrect_description_file_1() {
|
||||
fn incorrect_description_file_2() {
|
||||
let f = super::fixture().join("incorrect-package");
|
||||
let resolution = Resolver::default().resolve(f.join("pack2"), ".");
|
||||
// simd_json has different error messages than serde_json
|
||||
let error = ResolveError::Json(JSONError {
|
||||
path: f.join("pack2/package.json"),
|
||||
message: String::from("EOF while parsing a value at line 1 column 0"),
|
||||
line: 1,
|
||||
message: String::from("Eof at character 0"),
|
||||
line: 0, // simd_json doesn't provide line/column info
|
||||
column: 0,
|
||||
});
|
||||
assert_eq!(resolution, Err(error));
|
||||
|
||||
@@ -21,7 +21,7 @@ fn test() {
|
||||
let package_json =
|
||||
resolver.resolve(&path, request).ok().and_then(|f| f.package_json().cloned());
|
||||
let package_json_path = package_json.as_ref().map(|p| &p.path);
|
||||
let package_json_name = package_json.as_ref().and_then(|p| p.name.as_deref());
|
||||
let package_json_name = package_json.as_ref().and_then(|p| p.name());
|
||||
assert_eq!(package_json_path, Some(&resolved_package_json_path), "{path:?} {request}");
|
||||
assert_eq!(package_json_name, Some("package-json-nested"), "{path:?} {request}");
|
||||
}
|
||||
@@ -42,7 +42,7 @@ fn adjacent_to_node_modules() {
|
||||
|
||||
let package_json = resolver.resolve(&path, request).unwrap().package_json().cloned();
|
||||
let package_json_path = package_json.as_ref().map(|p| &p.path);
|
||||
let package_json_name = package_json.as_ref().and_then(|p| p.name.as_deref());
|
||||
let package_json_name = package_json.as_ref().and_then(|p| p.name());
|
||||
assert_eq!(package_json_path, Some(&resolved_package_json_path));
|
||||
assert_eq!(package_json_name, Some("misc"));
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ fn package_json() {
|
||||
let package_json = resolution.package_json().unwrap();
|
||||
assert_eq!(package_json.name().unwrap(), "name");
|
||||
assert_eq!(package_json.r#type().unwrap().to_string(), "module".to_string());
|
||||
assert!(package_json.side_effects.as_ref().unwrap().is_object());
|
||||
assert_eq!(package_json.side_effects(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -84,20 +84,6 @@ fn tsconfig_extends_circular_reference() {
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(feature = "package_json_raw_json_api")]
|
||||
#[test]
|
||||
fn package_json_raw_json_api() {
|
||||
let resolution = resolve("./tests/package.json");
|
||||
assert!(
|
||||
resolution
|
||||
.package_json()
|
||||
.unwrap()
|
||||
.raw_json()
|
||||
.get("name")
|
||||
.is_some_and(|name| name == "name")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn clear_cache() {
|
||||
let resolver = Resolver::new(ResolveOptions::default());
|
||||
|
||||
Reference in New Issue
Block a user