1
1
use indexmap:: IndexSet ;
2
2
use lexer:: CommonJSModuleLexer ;
3
3
use oxc_resolver:: { ResolveError , ResolveOptions , Resolver } ;
4
- use std:: io:: { stdout, Write } ;
4
+ use std:: io:: { self , stdout, Write } ;
5
5
use std:: path:: Path ;
6
6
use std:: { env, fs} ;
7
7
@@ -20,6 +20,17 @@ fn main() {
20
20
while requires. len ( ) > 0 {
21
21
let ( js_filename, call_mode) = requires. pop ( ) . unwrap ( ) ;
22
22
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
+ }
23
34
let lexer = CommonJSModuleLexer :: init ( & js_filename, & code) . expect ( "failed to parse module" ) ;
24
35
let ( exports, reexports) = lexer. analyze ( & node_env, call_mode) ;
25
36
if exports. len ( ) == 0 && reexports. len ( ) == 1 && named_exports. len ( ) == 0 {
@@ -54,9 +65,11 @@ fn main() {
54
65
}
55
66
}
56
67
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
+ }
60
73
}
61
74
}
62
75
@@ -91,37 +104,30 @@ fn resolve(wd: &str, specifier: &str, containing_filename: Option<String>) -> Re
91
104
. unwrap ( )
92
105
. to_owned ( )
93
106
} ;
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
+ {
95
111
return Ok ( fullpath) ;
96
112
}
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
- }
113
113
if fullpath. ends_with ( ".js" ) {
114
114
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" ) {
116
116
return Ok ( maybe_exists) ;
117
117
}
118
118
}
119
119
if fullpath. ends_with ( ".cjs" ) {
120
120
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" ) {
122
122
return Ok ( maybe_exists) ;
123
123
}
124
124
}
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
+ }
125
131
126
132
// `/path/to/wd/node_modules/react/index` -> `react/index`
127
133
if specifier. starts_with ( "/" ) {
@@ -139,6 +145,52 @@ fn resolve(wd: &str, specifier: &str, containing_filename: Option<String>) -> Re
139
145
Ok ( ret. path ( ) . to_str ( ) . unwrap ( ) . to_owned ( ) )
140
146
}
141
147
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
+
142
194
fn is_node_builtin_module ( specifier : & str ) -> bool {
143
195
match specifier {
144
196
"_http_agent"
0 commit comments