Skip to content

Commit 9beb665

Browse files
committed
refactor: rm self cell
1 parent b7bc61f commit 9beb665

File tree

4 files changed

+91
-62
lines changed

4 files changed

+91
-62
lines changed

src/cache.rs

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@ use rustc_hash::FxHasher;
1515
use tokio::sync::OnceCell as OnceLock;
1616

1717
use crate::{
18-
context::ResolveContext as Ctx, package_json::PackageJson, path::PathUtil, FileMetadata,
19-
FileSystem, ResolveError, ResolveOptions, TsConfig,
18+
context::ResolveContext as Ctx,
19+
package_json::{off_to_location, PackageJson},
20+
path::PathUtil,
21+
FileMetadata, FileSystem, JSONError, ResolveError, ResolveOptions, TsConfig,
2022
};
2123

2224
#[derive(Default)]
@@ -319,12 +321,32 @@ impl CachedPathImpl {
319321
} else {
320322
package_json_path.clone()
321323
};
322-
PackageJson::parse(package_json_path.clone(), real_path, package_json_string)
323-
.map(Arc::new)
324-
.map(Some)
324+
match PackageJson::parse(package_json_path.clone(), real_path, package_json_string) {
325+
Ok(v) => Ok(Some(Arc::new(v))),
326+
Err(parse_err) => {
327+
let package_json_path = self.path.join("package.json");
328+
let package_json_string = match fs.read_to_string(&package_json_path).await {
329+
Ok(c) => c,
330+
Err(io_err) => {
331+
return Err(ResolveError::from(io_err));
332+
}
333+
};
334+
335+
let (line, column) = off_to_location(&package_json_string, parse_err.index());
336+
337+
Err(ResolveError::JSON(JSONError {
338+
path: package_json_path,
339+
message: format!("Parsing error: {:?}", parse_err.error()),
340+
line,
341+
column,
342+
content: Some(package_json_string),
343+
}))
344+
}
345+
}
325346
})
326347
.await
327348
.cloned();
349+
328350
// https://github.com/webpack/enhanced-resolve/blob/58464fc7cb56673c9aa849e68e6300239601e615/lib/DescriptionFileUtils.js#L68-L82
329351
match &result {
330352
Ok(Some(package_json)) => {

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1772,7 +1772,7 @@ impl<Fs: FileSystem + Send + Sync> ResolverGeneric<Fs> {
17721772
&& (pattern_trailer.is_empty()
17731773
|| (match_key.len() >= expansion_key.len()
17741774
&& match_key.ends_with(pattern_trailer)))
1775-
&& Self::pattern_key_compare(&best_key, &expansion_key).is_gt()
1775+
&& Self::pattern_key_compare(&best_key, expansion_key).is_gt()
17761776
{
17771777
// 1. Let target be the value of matchObj[expansionKey].
17781778
best_target = Some(target);

src/package_json/mod.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,24 @@ pub enum SideEffects {
3636
String(String),
3737
Array(Vec<String>),
3838
}
39+
40+
pub fn off_to_location(json: &str, offset: usize) -> (usize, usize) {
41+
let mut line = 0;
42+
let mut col = 0;
43+
let mut current_offset = 0;
44+
for ch in json.chars() {
45+
let b = ch.len_utf8();
46+
current_offset += b;
47+
if ch == '\n' {
48+
line += 1;
49+
col = 0;
50+
} else {
51+
col += b;
52+
}
53+
54+
if current_offset >= offset {
55+
break;
56+
}
57+
}
58+
(line + 1, col + 1)
59+
}

src/package_json/simd.rs

Lines changed: 42 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,16 @@
33
//! Code related to export field are copied from [Parcel's resolver](https://github.com/parcel-bundler/parcel/blob/v2/packages/utils/node-resolver-rs/src/package_json.rs)
44
55
use std::{
6-
fmt::Debug,
6+
fmt::{Debug, Formatter},
7+
marker::PhantomData,
78
path::{Path, PathBuf},
89
};
910

10-
use self_cell::self_cell;
11-
use simd_json::{borrowed::Value, prelude::*, to_borrowed_value};
11+
use simd_json::{
12+
borrowed::Value, prelude::*, to_borrowed_value, BorrowedValue, Error as ParseError,
13+
};
1214

13-
use crate::{path::PathUtil, JSONError, ResolveError};
15+
use crate::{path::PathUtil, ResolveError};
1416

1517
pub type JSONMap<'a> = simd_json::borrowed::Object<'a>;
1618

@@ -20,19 +22,44 @@ pub use simd_json::BorrowedValue as JSONValue;
2022

2123
use crate::package_json::{ModuleType, SideEffects};
2224

23-
self_cell!(
24-
struct JSONCell {
25-
owner: Vec<u8>,
25+
pub struct JSONCell {
26+
value: BorrowedValue<'static>,
27+
buf: Vec<u8>,
28+
_invariant: PhantomData<&'static str>,
29+
}
2630

27-
#[covariant]
28-
dependent: JSONValue,
29-
}
30-
impl {Debug}
31-
);
31+
impl JSONCell {
32+
pub fn try_new(mut buf: Vec<u8>) -> Result<Self, ParseError> {
33+
let value = to_borrowed_value(&mut buf)?;
34+
// SAFETY: This is safe because `buf` is owned by the `JSONCell` struct,
35+
let value = unsafe { std::mem::transmute::<BorrowedValue<'_>, BorrowedValue<'static>>(value) };
36+
37+
Ok(Self {
38+
value,
39+
buf,
40+
_invariant: PhantomData,
41+
})
42+
}
43+
44+
pub fn borrow_dependent<'a>(&'a self) -> &'a JSONValue<'a> {
45+
&self.value
46+
}
47+
}
48+
49+
impl Debug for JSONCell {
50+
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
51+
let str = String::from_utf8_lossy(&self.buf);
52+
f.write_fmt(format_args!("JSONCell({str})"))
53+
}
54+
}
3255

3356
impl Default for JSONCell {
3457
fn default() -> Self {
35-
Self::new(Vec::new(), |_data| JSONValue::Static(StaticNode::Null))
58+
Self {
59+
value: JSONValue::Static(StaticNode::Null),
60+
buf: Vec::new(),
61+
_invariant: PhantomData,
62+
}
3663
}
3764
}
3865

@@ -70,27 +97,8 @@ pub struct PackageJson {
7097
impl PackageJson {
7198
/// # Panics
7299
/// # Errors
73-
pub(crate) fn parse(
74-
path: PathBuf,
75-
realpath: PathBuf,
76-
json: Vec<u8>,
77-
) -> Result<Self, ResolveError> {
78-
let json_cell = JSONCell::try_new(json, |v| {
79-
// SAFETY: We have exclusive ownership of the Vec<u8>, so it's safe to cast to mutable.
80-
let slice = unsafe { std::slice::from_raw_parts_mut(v.as_ptr().cast_mut(), v.len()) };
81-
82-
to_borrowed_value(slice).map_err(|e| {
83-
let content = String::from_utf8_lossy(v);
84-
let (line, column) = offset_to_location(&content, e.index());
85-
ResolveError::JSON(JSONError {
86-
path: path.clone(),
87-
message: format!("JSON parse error: {:?}", e.error()),
88-
line,
89-
column,
90-
content: Some(content.to_string()),
91-
})
92-
})
93-
})?;
100+
pub(crate) fn parse(path: PathBuf, realpath: PathBuf, json: Vec<u8>) -> Result<Self, ParseError> {
101+
let json_cell = JSONCell::try_new(json)?;
94102

95103
let mut package_json = Self::default();
96104
if let Some(json_object) = json_cell.borrow_dependent().as_object() {
@@ -302,28 +310,6 @@ impl PackageJson {
302310
}
303311
}
304312

305-
fn offset_to_location(json: &str, offset: usize) -> (usize, usize) {
306-
let mut line = 0;
307-
let mut col = 0;
308-
let mut current_offset = 0;
309-
for ch in json.chars() {
310-
let b = ch.len_utf8();
311-
current_offset += b;
312-
if ch == '\n' {
313-
line += 1;
314-
col = 0;
315-
} else {
316-
col += b;
317-
}
318-
319-
if current_offset >= offset {
320-
break;
321-
}
322-
}
323-
// zero-based to one-based
324-
(line + 1, col + 1)
325-
}
326-
327313
impl<'a> TryFrom<&'a JSONValue<'a>> for SideEffects {
328314
type Error = &'static str;
329315
fn try_from(value: &'a JSONValue<'a>) -> Result<Self, Self::Error> {

0 commit comments

Comments
 (0)