11use indexmap:: IndexSet ;
22use lexer:: CommonJSModuleLexer ;
33use oxc_resolver:: { ResolveError , ResolveOptions , Resolver } ;
4- use std:: io:: { stdout, Write } ;
4+ use std:: io:: { self , stdout, Write } ;
55use std:: path:: Path ;
66use std:: { env, fs} ;
77
@@ -20,6 +20,17 @@ fn main() {
2020 while requires. len ( ) > 0 {
2121 let ( js_filename, call_mode) = requires. pop ( ) . unwrap ( ) ;
2222 let code = fs:: read_to_string ( & js_filename) . expect ( ( "failed to read " . to_owned ( ) + js_filename. as_str ( ) ) . as_str ( ) ) ;
23+ if js_filename. ends_with ( ".json" ) {
24+ let value: serde_json:: Value = serde_json:: from_str ( & code) . unwrap ( ) ;
25+ if let Some ( value) = value. as_object ( ) {
26+ for key in value. keys ( ) {
27+ if is_js_identifier ( & key) {
28+ named_exports. insert ( key. clone ( ) ) ;
29+ }
30+ }
31+ }
32+ continue ;
33+ }
2334 let lexer = CommonJSModuleLexer :: init ( & js_filename, & code) . expect ( "failed to parse module" ) ;
2435 let ( exports, reexports) = lexer. analyze ( & node_env, call_mode) ;
2536 if exports. len ( ) == 0 && reexports. len ( ) == 1 && named_exports. len ( ) == 0 {
@@ -54,9 +65,11 @@ fn main() {
5465 }
5566 }
5667 for name in named_exports {
57- stdout
58- . write_all ( ( name + "\n " ) . as_bytes ( ) )
59- . expect ( "failed to write result to stdout" ) ;
68+ if is_js_identifier ( & name) {
69+ stdout
70+ . write_all ( ( name + "\n " ) . as_bytes ( ) )
71+ . expect ( "failed to write result to stdout" ) ;
72+ }
6073 }
6174}
6275
@@ -91,37 +104,30 @@ fn resolve(wd: &str, specifier: &str, containing_filename: Option<String>) -> Re
91104 . unwrap ( )
92105 . to_owned ( )
93106 } ;
94- if fs:: exists ( & fullpath) . expect ( "Can't check existence of file" ) {
107+
108+ if ( fullpath. ends_with ( ".js" ) || fullpath. ends_with ( ".cjs" ) || fullpath. ends_with ( ".json" ) )
109+ && file_exists ( & fullpath) . expect ( "Can't check existence of file" )
110+ {
95111 return Ok ( fullpath) ;
96112 }
97- let maybe_exists = fullpath. to_owned ( ) + ".cjs" ;
98- if fs:: exists ( & maybe_exists) . expect ( "Can't check existence of file" ) {
99- return Ok ( maybe_exists) ;
100- }
101- let maybe_exists = fullpath. to_owned ( ) + ".js" ;
102- if fs:: exists ( & maybe_exists) . expect ( "Can't check existence of file" ) {
103- return Ok ( maybe_exists) ;
104- }
105- let maybe_exists = fullpath. to_owned ( ) + "/index.cjs" ;
106- if fs:: exists ( & maybe_exists) . expect ( "Can't check existence of file" ) {
107- return Ok ( maybe_exists) ;
108- }
109- let maybe_exists = fullpath. to_owned ( ) + "/index.js" ;
110- if fs:: exists ( & maybe_exists) . expect ( "Can't check existence of file" ) {
111- return Ok ( maybe_exists) ;
112- }
113113 if fullpath. ends_with ( ".js" ) {
114114 let maybe_exists = fullpath[ ..fullpath. len ( ) - 3 ] . to_owned ( ) + ".cjs" ;
115- if fs :: exists ( & maybe_exists) . expect ( "Can't check existence of file" ) {
115+ if file_exists ( & maybe_exists) . expect ( "Can't check existence of file" ) {
116116 return Ok ( maybe_exists) ;
117117 }
118118 }
119119 if fullpath. ends_with ( ".cjs" ) {
120120 let maybe_exists = fullpath[ ..fullpath. len ( ) - 4 ] . to_owned ( ) + ".js" ;
121- if fs :: exists ( & maybe_exists) . expect ( "Can't check existence of file" ) {
121+ if file_exists ( & maybe_exists) . expect ( "Can't check existence of file" ) {
122122 return Ok ( maybe_exists) ;
123123 }
124124 }
125+ let maybe_exists = fullpath. to_owned ( ) + ".cjs" ;
126+ if file_exists ( & maybe_exists) . expect ( "Can't check existence of file" )
127+ && !dir_exists ( & fullpath) . expect ( "Can't check existence of directory" )
128+ {
129+ return Ok ( maybe_exists) ;
130+ }
125131
126132 // `/path/to/wd/node_modules/react/index` -> `react/index`
127133 if specifier. starts_with ( "/" ) {
@@ -139,6 +145,52 @@ fn resolve(wd: &str, specifier: &str, containing_filename: Option<String>) -> Re
139145 Ok ( ret. path ( ) . to_str ( ) . unwrap ( ) . to_owned ( ) )
140146}
141147
148+ pub fn dir_exists ( path : & str ) -> io:: Result < bool > {
149+ match fs:: metadata ( path) {
150+ Ok ( meta) => Ok ( meta. is_dir ( ) || meta. is_symlink ( ) ) ,
151+ Err ( error) if error. kind ( ) == io:: ErrorKind :: NotFound => Ok ( false ) ,
152+ Err ( error) => Err ( error) ,
153+ }
154+ }
155+
156+ pub fn file_exists ( path : & str ) -> io:: Result < bool > {
157+ match fs:: metadata ( path) {
158+ Ok ( meta) => Ok ( meta. is_file ( ) ) ,
159+ Err ( error) if error. kind ( ) == io:: ErrorKind :: NotFound => Ok ( false ) ,
160+ Err ( error) => Err ( error) ,
161+ }
162+ }
163+
164+ fn is_js_identifier ( s : & str ) -> bool {
165+ if s. len ( ) == 0 {
166+ return false ;
167+ }
168+ let first_char = s. chars ( ) . next ( ) . unwrap ( ) ;
169+ if !is_alphabetic ( first_char) {
170+ return false ;
171+ }
172+ for c in s. chars ( ) {
173+ if !is_alphabetic ( c) && !is_numberic ( c) {
174+ return false ;
175+ }
176+ }
177+ return true ;
178+ }
179+
180+ fn is_alphabetic ( c : char ) -> bool {
181+ match c {
182+ 'a' ..='z' | 'A' ..='Z' | '_' | '$' => true ,
183+ _ => false ,
184+ }
185+ }
186+
187+ fn is_numberic ( c : char ) -> bool {
188+ match c {
189+ '0' ..='9' => true ,
190+ _ => false ,
191+ }
192+ }
193+
142194fn is_node_builtin_module ( specifier : & str ) -> bool {
143195 match specifier {
144196 "_http_agent"
0 commit comments