Skip to content

Commit

Permalink
native: support json module
Browse files Browse the repository at this point in the history
  • Loading branch information
ije committed Dec 14, 2024
1 parent 2825c2f commit d5ee5f6
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 24 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

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

3 changes: 2 additions & 1 deletion native/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ edition = "2021"

[dependencies]
lexer = { path = "../lexer" }
oxc_resolver = "2.1.1"
indexmap = "2.7.0"
oxc_resolver = "2.1.1"
serde_json = "1.0.133"
98 changes: 75 additions & 23 deletions native/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use indexmap::IndexSet;
use lexer::CommonJSModuleLexer;
use oxc_resolver::{ResolveError, ResolveOptions, Resolver};
use std::io::{stdout, Write};
use std::io::{self, stdout, Write};
use std::path::Path;
use std::{env, fs};

Expand All @@ -20,6 +20,17 @@ fn main() {
while requires.len() > 0 {
let (js_filename, call_mode) = requires.pop().unwrap();
let code = fs::read_to_string(&js_filename).expect(("failed to read ".to_owned() + js_filename.as_str()).as_str());
if js_filename.ends_with(".json") {
let value: serde_json::Value = serde_json::from_str(&code).unwrap();
if let Some(value) = value.as_object() {
for key in value.keys() {
if is_js_identifier(&key) {
named_exports.insert(key.clone());
}
}
}
continue;
}
let lexer = CommonJSModuleLexer::init(&js_filename, &code).expect("failed to parse module");
let (exports, reexports) = lexer.analyze(&node_env, call_mode);
if exports.len() == 0 && reexports.len() == 1 && named_exports.len() == 0 {
Expand Down Expand Up @@ -54,9 +65,11 @@ fn main() {
}
}
for name in named_exports {
stdout
.write_all((name + "\n").as_bytes())
.expect("failed to write result to stdout");
if is_js_identifier(&name) {
stdout
.write_all((name + "\n").as_bytes())
.expect("failed to write result to stdout");
}
}
}

Expand Down Expand Up @@ -91,37 +104,30 @@ fn resolve(wd: &str, specifier: &str, containing_filename: Option<String>) -> Re
.unwrap()
.to_owned()
};
if fs::exists(&fullpath).expect("Can't check existence of file") {

if (fullpath.ends_with(".js") || fullpath.ends_with(".cjs") || fullpath.ends_with(".json"))
&& file_exists(&fullpath).expect("Can't check existence of file")
{
return Ok(fullpath);
}
let maybe_exists = fullpath.to_owned() + ".cjs";
if fs::exists(&maybe_exists).expect("Can't check existence of file") {
return Ok(maybe_exists);
}
let maybe_exists = fullpath.to_owned() + ".js";
if fs::exists(&maybe_exists).expect("Can't check existence of file") {
return Ok(maybe_exists);
}
let maybe_exists = fullpath.to_owned() + "/index.cjs";
if fs::exists(&maybe_exists).expect("Can't check existence of file") {
return Ok(maybe_exists);
}
let maybe_exists = fullpath.to_owned() + "/index.js";
if fs::exists(&maybe_exists).expect("Can't check existence of file") {
return Ok(maybe_exists);
}
if fullpath.ends_with(".js") {
let maybe_exists = fullpath[..fullpath.len() - 3].to_owned() + ".cjs";
if fs::exists(&maybe_exists).expect("Can't check existence of file") {
if file_exists(&maybe_exists).expect("Can't check existence of file") {
return Ok(maybe_exists);
}
}
if fullpath.ends_with(".cjs") {
let maybe_exists = fullpath[..fullpath.len() - 4].to_owned() + ".js";
if fs::exists(&maybe_exists).expect("Can't check existence of file") {
if file_exists(&maybe_exists).expect("Can't check existence of file") {
return Ok(maybe_exists);
}
}
let maybe_exists = fullpath.to_owned() + ".cjs";
if file_exists(&maybe_exists).expect("Can't check existence of file")
&& !dir_exists(&fullpath).expect("Can't check existence of directory")
{
return Ok(maybe_exists);
}

// `/path/to/wd/node_modules/react/index` -> `react/index`
if specifier.starts_with("/") {
Expand All @@ -139,6 +145,52 @@ fn resolve(wd: &str, specifier: &str, containing_filename: Option<String>) -> Re
Ok(ret.path().to_str().unwrap().to_owned())
}

pub fn dir_exists(path: &str) -> io::Result<bool> {
match fs::metadata(path) {
Ok(meta) => Ok(meta.is_dir() || meta.is_symlink()),
Err(error) if error.kind() == io::ErrorKind::NotFound => Ok(false),
Err(error) => Err(error),
}
}

pub fn file_exists(path: &str) -> io::Result<bool> {
match fs::metadata(path) {
Ok(meta) => Ok(meta.is_file()),
Err(error) if error.kind() == io::ErrorKind::NotFound => Ok(false),
Err(error) => Err(error),
}
}

fn is_js_identifier(s: &str) -> bool {
if s.len() == 0 {
return false;
}
let first_char = s.chars().next().unwrap();
if !is_alphabetic(first_char) {
return false;
}
for c in s.chars() {
if !is_alphabetic(c) && !is_numberic(c) {
return false;
}
}
return true;
}

fn is_alphabetic(c: char) -> bool {
match c {
'a'..='z' | 'A'..='Z' | '_' | '$' => true,
_ => false,
}
}

fn is_numberic(c: char) -> bool {
match c {
'0'..='9' => true,
_ => false,
}
}

fn is_node_builtin_module(specifier: &str) -> bool {
match specifier {
"_http_agent"
Expand Down

0 comments on commit d5ee5f6

Please sign in to comment.