Skip to content

Commit

Permalink
Native resolver plugin (#9776)
Browse files Browse the repository at this point in the history
* Get resolver building

* Make InMemoryFileSystem use FileSystemRef

* Update default resolve to use new API

* Fix options usage

* Add resolver test

* Rollback meta option

* Update comment

* Fix meta

* Fix more meta

* Fix tests
  • Loading branch information
mattcompiles authored Jun 7, 2024
1 parent 5b0f645 commit a323b03
Show file tree
Hide file tree
Showing 11 changed files with 377 additions and 48 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 8 additions & 4 deletions crates/parcel/src/plugins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ impl<'a> Plugins<'a> {
mod tests {
use std::path::PathBuf;
use std::rc::Rc;
use std::sync::Arc;

use parcel_config::parcel_config_fixtures::default_config;
use parcel_core::plugin::PluginConfig;
Expand All @@ -200,7 +201,7 @@ mod tests {
fn ctx() -> PluginContext {
PluginContext {
config: PluginConfig::new(
Rc::new(InMemoryFileSystem::default()),
Arc::new(InMemoryFileSystem::default()),
PathBuf::default(),
PathBuf::default(),
),
Expand Down Expand Up @@ -267,10 +268,10 @@ mod tests {

#[test]
fn returns_reporters() {
let resolvers = plugins(&ctx()).reporters();
let reporters = plugins(&ctx()).reporters();

assert_eq!(
format!("{:?}", resolvers),
format!("{:?}", reporters),
"[NapiReporterPlugin { name: \"@parcel/reporter-dev-server\" }]"
)
}
Expand All @@ -279,7 +280,10 @@ mod tests {
fn returns_resolvers() {
let resolvers = plugins(&ctx()).resolvers();

assert_eq!(format!("{:?}", resolvers), "Ok([ParcelResolver])")
assert_eq!(
format!("{:?}", resolvers),
"Ok([ParcelResolver { cache: Cache, project_root: \"\", mode: Development }])"
)
}

#[test]
Expand Down
4 changes: 3 additions & 1 deletion crates/parcel_core/src/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,6 @@ pub struct PluginContext {
pub struct PluginLogger {}

#[derive(Default)]
pub struct PluginOptions {}
pub struct PluginOptions {
pub mode: crate::types::BuildMode,
}
35 changes: 19 additions & 16 deletions crates/parcel_core/src/plugin/plugin_config.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
use std::path::PathBuf;
use std::rc::Rc;

use parcel_filesystem::search::find_ancestor_file;
use parcel_filesystem::FileSystem;
use parcel_filesystem::FileSystemRef;
use serde::de::DeserializeOwned;

use crate::types::JSONObject;

/// Enables plugins to load config in various formats
pub struct PluginConfig {
fs: Rc<dyn FileSystem>,
project_root: PathBuf,
search_path: PathBuf,
pub fs: FileSystemRef,
pub project_root: PathBuf,
pub search_path: PathBuf,
}

// TODO JavaScript configs, invalidations, dev deps, etc
impl PluginConfig {
pub fn new(fs: Rc<dyn FileSystem>, project_root: PathBuf, search_path: PathBuf) -> Self {
pub fn new(fs: FileSystemRef, project_root: PathBuf, search_path: PathBuf) -> Self {
Self {
fs,
project_root,
Expand Down Expand Up @@ -68,6 +67,8 @@ mod tests {
use super::*;

mod load_json_config {
use std::sync::Arc;

use serde::Deserialize;

use super::*;
Expand All @@ -81,7 +82,7 @@ mod tests {
let search_path = project_root.join("index");

let config = PluginConfig {
fs: Rc::new(InMemoryFileSystem::default()),
fs: Arc::new(InMemoryFileSystem::default()),
project_root,
search_path: search_path.clone(),
};
Expand All @@ -99,7 +100,7 @@ mod tests {

#[test]
fn returns_an_error_when_the_config_is_outside_the_search_path() {
let fs = Rc::new(InMemoryFileSystem::default());
let fs = Arc::new(InMemoryFileSystem::default());
let project_root = PathBuf::from("/project-root");
let search_path = project_root.join("index");

Expand Down Expand Up @@ -127,7 +128,7 @@ mod tests {

#[test]
fn returns_an_error_when_the_config_is_outside_the_project_root() {
let fs = Rc::new(InMemoryFileSystem::default());
let fs = Arc::new(InMemoryFileSystem::default());
let project_root = PathBuf::from("/project-root");
let search_path = project_root.join("index");

Expand All @@ -152,7 +153,7 @@ mod tests {

#[test]
fn returns_json_config_at_search_path() {
let fs = Rc::new(InMemoryFileSystem::default());
let fs = Arc::new(InMemoryFileSystem::default());
let project_root = PathBuf::from("/project-root");
let search_path = project_root.join("index");
let config_path = search_path.join("config.json");
Expand All @@ -175,7 +176,7 @@ mod tests {

#[test]
fn returns_json_config_at_project_root() {
let fs = Rc::new(InMemoryFileSystem::default());
let fs = Arc::new(InMemoryFileSystem::default());
let project_root = PathBuf::from("/project-root");
let search_path = project_root.join("index");
let config_path = project_root.join("config.json");
Expand All @@ -198,6 +199,8 @@ mod tests {
}

mod load_package_json_config {
use std::sync::Arc;

use serde_json::Map;
use serde_json::Value;

Expand Down Expand Up @@ -229,7 +232,7 @@ mod tests {
let search_path = project_root.join("index");

let config = PluginConfig {
fs: Rc::new(InMemoryFileSystem::default()),
fs: Arc::new(InMemoryFileSystem::default()),
project_root,
search_path: search_path.clone(),
};
Expand All @@ -247,7 +250,7 @@ mod tests {

#[test]
fn returns_an_error_when_config_key_does_not_exist_at_search_path() {
let fs = Rc::new(InMemoryFileSystem::default());
let fs = Arc::new(InMemoryFileSystem::default());
let project_root = PathBuf::from("/project-root");
let search_path = project_root.join("index");
let package_path = search_path.join("package.json");
Expand All @@ -274,7 +277,7 @@ mod tests {

#[test]
fn returns_an_error_when_config_key_does_not_exist_at_project_root() {
let fs = Rc::new(InMemoryFileSystem::default());
let fs = Arc::new(InMemoryFileSystem::default());
let project_root = PathBuf::from("/project-root");
let search_path = project_root.join("index");
let package_path = project_root.join("package.json");
Expand All @@ -300,7 +303,7 @@ mod tests {

#[test]
fn returns_package_config_at_search_path() {
let fs = Rc::new(InMemoryFileSystem::default());
let fs = Arc::new(InMemoryFileSystem::default());
let project_root = PathBuf::from("/project-root");
let search_path = project_root.join("index");
let package_path = search_path.join("package.json");
Expand All @@ -323,7 +326,7 @@ mod tests {

#[test]
fn returns_package_config_at_project_root() {
let fs = Rc::new(InMemoryFileSystem::default());
let fs = Arc::new(InMemoryFileSystem::default());
let project_root = PathBuf::from("/project-root");
let search_path = project_root.join("index");
let package_path = project_root.join("package.json");
Expand Down
2 changes: 1 addition & 1 deletion crates/parcel_core/src/plugin/resolver_plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pub struct ResolveContext {
pub pipeline: Option<String>,
}

#[derive(Debug, Default)]
#[derive(Debug, Default, PartialEq)]
pub struct Resolution {
/// Whether this dependency can be deferred by Parcel itself
pub can_defer: bool,
Expand Down
3 changes: 2 additions & 1 deletion crates/parcel_core/src/types/parcel_options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ pub struct ParcelOptions {
pub project_root: PathBuf,
}

#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug, PartialEq, Default)]
pub enum BuildMode {
#[default]
Development,
Production,
Other(String),
Expand Down
34 changes: 16 additions & 18 deletions crates/parcel_filesystem/src/in_memory_file_system.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use std::cell::RefCell;
use std::collections::HashMap;
use std::path::Component;
use std::path::Path;
use std::path::PathBuf;
use std::sync::RwLock;

use crate::FileSystem;

Expand All @@ -16,49 +16,46 @@ enum InMemoryFileSystemEntry {
/// In memory implementation of the `FileSystem` trait, for testing purpouses.
#[derive(Debug)]
pub struct InMemoryFileSystem {
files: RefCell<HashMap<PathBuf, InMemoryFileSystemEntry>>,
current_working_directory: RefCell<PathBuf>,
files: RwLock<HashMap<PathBuf, InMemoryFileSystemEntry>>,
current_working_directory: RwLock<PathBuf>,
}

impl InMemoryFileSystem {
/// Change the current working directory. Used for resolving relative paths.
pub fn set_current_working_directory(&self, cwd: PathBuf) {
self.current_working_directory.replace(cwd);
let mut state = self.current_working_directory.write().unwrap();
*state = cwd;
}

/// Create a directory at path.
pub fn create_directory(&self, path: &Path) {
self
.files
.borrow_mut()
.insert(path.into(), InMemoryFileSystemEntry::Directory);
let mut files = self.files.write().unwrap();
files.insert(path.into(), InMemoryFileSystemEntry::Directory);
}

/// Write a file at path.
pub fn write_file(&self, path: &Path, contents: String) {
self
.files
.borrow_mut()
.insert(path.into(), InMemoryFileSystemEntry::File { contents });
let mut files = self.files.write().unwrap();
files.insert(path.into(), InMemoryFileSystemEntry::File { contents });
}
}

impl Default for InMemoryFileSystem {
fn default() -> Self {
Self {
files: Default::default(),
current_working_directory: RefCell::new(PathBuf::from("/")),
current_working_directory: RwLock::new(PathBuf::from("/")),
}
}
}

impl FileSystem for InMemoryFileSystem {
fn cwd(&self) -> std::io::Result<PathBuf> {
Ok(self.current_working_directory.borrow().clone())
Ok(self.current_working_directory.read().unwrap().clone())
}

fn canonicalize_base(&self, path: &Path) -> std::io::Result<PathBuf> {
let cwd = self.current_working_directory.borrow();
let cwd = self.current_working_directory.read().unwrap();
let mut result = if path.is_absolute() {
vec![]
} else {
Expand Down Expand Up @@ -88,7 +85,8 @@ impl FileSystem for InMemoryFileSystem {
}

fn read_to_string(&self, path: &Path) -> std::io::Result<String> {
self.files.borrow().get(path).map_or_else(
let files = self.files.read().unwrap();
files.get(path).map_or_else(
|| {
Err(std::io::Error::new(
std::io::ErrorKind::NotFound,
Expand All @@ -106,13 +104,13 @@ impl FileSystem for InMemoryFileSystem {
}

fn is_file(&self, path: &Path) -> bool {
let files = self.files.borrow();
let files = self.files.read().unwrap();
let file = files.get(path);
matches!(file, Some(InMemoryFileSystemEntry::File { .. }))
}

fn is_dir(&self, path: &Path) -> bool {
let files = self.files.borrow();
let files = self.files.read().unwrap();
let file = files.get(path);
matches!(file, Some(InMemoryFileSystemEntry::Directory { .. }))
}
Expand Down
5 changes: 4 additions & 1 deletion crates/parcel_plugin_resolver/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,8 @@ path = "./src/lib.rs"

[dependencies]
parcel_core = { path = "../parcel_core" }

parcel-resolver = { path = "../../packages/utils/node-resolver-rs" }
anyhow = "1"

[dev-dependencies]
parcel_filesystem = { path = "../parcel_filesystem" }
Loading

0 comments on commit a323b03

Please sign in to comment.