1use std::mem::take;
2
3use anyhow::Result;
4use turbo_tasks::Vc;
5use turbopack_core::compile_time_info::CompileTimeInfo;
6use url::Url;
7
8use super::{
9 ConstantValue, JsValue, JsValueUrlKind, ModuleValue, WellKnownFunctionKind,
10 WellKnownObjectKind, imports::ImportAnnotations,
11};
12use crate::analyzer::RequireContextValue;
13
14pub async fn replace_well_known(
15 value: JsValue,
16 compile_time_info: Vc<CompileTimeInfo>,
17) -> Result<(JsValue, bool)> {
18 Ok(match value {
19 JsValue::Call(_, box JsValue::WellKnownFunction(kind), args) => (
20 well_known_function_call(
21 kind,
22 JsValue::unknown_empty(false, "this is not analyzed yet"),
23 args,
24 compile_time_info,
25 )
26 .await?,
27 true,
28 ),
29 JsValue::Call(usize, callee, args) => {
30 if args.len() == 1 {
33 if let JsValue::WellKnownObject(_) = &args[0] {
34 return Ok((args[0].clone(), true));
35 }
36 }
37 (JsValue::Call(usize, callee, args), false)
38 }
39 JsValue::Member(_, box JsValue::WellKnownObject(kind), box prop) => {
40 well_known_object_member(kind, prop, compile_time_info).await?
41 }
42 JsValue::Member(_, box JsValue::WellKnownFunction(kind), box prop) => {
43 well_known_function_member(kind, prop)
44 }
45 _ => (value, false),
46 })
47}
48
49pub async fn well_known_function_call(
50 kind: WellKnownFunctionKind,
51 _this: JsValue,
52 args: Vec<JsValue>,
53 compile_time_info: Vc<CompileTimeInfo>,
54) -> Result<JsValue> {
55 Ok(match kind {
56 WellKnownFunctionKind::ObjectAssign => object_assign(args),
57 WellKnownFunctionKind::PathJoin => path_join(args),
58 WellKnownFunctionKind::PathDirname => path_dirname(args),
59 WellKnownFunctionKind::PathResolve(cwd) => path_resolve(*cwd, args),
60 WellKnownFunctionKind::Import => import(args),
61 WellKnownFunctionKind::Require => require(args),
62 WellKnownFunctionKind::RequireContextRequire(value) => {
63 require_context_require(value, args).await?
64 }
65 WellKnownFunctionKind::RequireContextRequireKeys(value) => {
66 require_context_require_keys(value, args).await?
67 }
68 WellKnownFunctionKind::RequireContextRequireResolve(value) => {
69 require_context_require_resolve(value, args).await?
70 }
71 WellKnownFunctionKind::PathToFileUrl => path_to_file_url(args),
72 WellKnownFunctionKind::OsArch => compile_time_info
73 .environment()
74 .compile_target()
75 .await?
76 .arch
77 .as_str()
78 .into(),
79 WellKnownFunctionKind::OsPlatform => compile_time_info
80 .environment()
81 .compile_target()
82 .await?
83 .platform
84 .as_str()
85 .into(),
86 WellKnownFunctionKind::ProcessCwd => {
87 if let Some(cwd) = &*compile_time_info.environment().cwd().await? {
88 cwd.clone().into()
89 } else {
90 JsValue::unknown(
91 JsValue::call(Box::new(JsValue::WellKnownFunction(kind)), args),
92 true,
93 "process.cwd is not specified in the environment",
94 )
95 }
96 }
97 WellKnownFunctionKind::OsEndianness => compile_time_info
98 .environment()
99 .compile_target()
100 .await?
101 .endianness
102 .as_str()
103 .into(),
104 WellKnownFunctionKind::NodeExpress => {
105 JsValue::WellKnownObject(WellKnownObjectKind::NodeExpressApp)
106 }
107 WellKnownFunctionKind::NodeResolveFrom => {
109 JsValue::WellKnownFunction(WellKnownFunctionKind::NodeResolveFrom)
110 }
111
112 _ => JsValue::unknown(
113 JsValue::call(Box::new(JsValue::WellKnownFunction(kind)), args),
114 true,
115 "unsupported function",
116 ),
117 })
118}
119
120pub fn object_assign(args: Vec<JsValue>) -> JsValue {
121 if args.iter().all(|arg| matches!(arg, JsValue::Object { .. })) {
122 if let Some(mut merged_object) = args.into_iter().reduce(|mut acc, cur| {
123 if let JsValue::Object { parts, mutable, .. } = &mut acc {
124 if let JsValue::Object {
125 parts: next_parts,
126 mutable: next_mutable,
127 ..
128 } = &cur
129 {
130 parts.extend_from_slice(next_parts);
131 *mutable |= *next_mutable;
132 }
133 }
134 acc
135 }) {
136 merged_object.update_total_nodes();
137 merged_object
138 } else {
139 JsValue::unknown(
140 JsValue::call(
141 Box::new(JsValue::WellKnownFunction(
142 WellKnownFunctionKind::ObjectAssign,
143 )),
144 vec![],
145 ),
146 true,
147 "empty arguments for Object.assign",
148 )
149 }
150 } else {
151 JsValue::unknown(
152 JsValue::call(
153 Box::new(JsValue::WellKnownFunction(
154 WellKnownFunctionKind::ObjectAssign,
155 )),
156 args,
157 ),
158 true,
159 "only const object assign is supported",
160 )
161 }
162}
163
164pub fn path_join(args: Vec<JsValue>) -> JsValue {
165 if args.is_empty() {
166 return ".".into();
167 }
168 let mut parts = Vec::new();
169 for item in args {
170 if let Some(str) = item.as_str() {
171 let splitted = str.split('/');
172 parts.extend(splitted.map(|s| s.into()));
173 } else {
174 parts.push(item);
175 }
176 }
177 let mut results_final = Vec::new();
178 let mut results: Vec<JsValue> = Vec::new();
179 for item in parts {
180 if let Some(str) = item.as_str() {
181 match str {
182 "" | "." => {
183 if results_final.is_empty() && results.is_empty() {
184 results_final.push(item);
185 }
186 }
187 ".." => {
188 if results.pop().is_none() {
189 results_final.push(item);
190 }
191 }
192 _ => results.push(item),
193 }
194 } else {
195 results_final.append(&mut results);
196 results_final.push(item);
197 }
198 }
199 results_final.append(&mut results);
200 let mut iter = results_final.into_iter();
201 let first = iter.next().unwrap();
202 let mut last_is_str = first.as_str().is_some();
203 results.push(first);
204 for part in iter {
205 let is_str = part.as_str().is_some();
206 if last_is_str && is_str {
207 results.push("/".into());
208 } else {
209 results.push(JsValue::alternatives(vec!["/".into(), "".into()]));
210 }
211 results.push(part);
212 last_is_str = is_str;
213 }
214 JsValue::concat(results)
215}
216
217pub fn path_resolve(cwd: JsValue, mut args: Vec<JsValue>) -> JsValue {
218 if args.is_empty() {
221 return JsValue::unknown_empty(false, "cwd is not static analyzable");
222 }
223 if args.len() == 1 {
224 return args.into_iter().next().unwrap();
225 }
226
227 for (idx, arg) in args.iter().enumerate().rev() {
229 if idx != 0 {
230 if let Some(str) = arg.as_str() {
231 if str.starts_with('/') {
232 return path_resolve(cwd, args.drain(idx..).collect());
233 }
234 }
235 }
236 }
237
238 let mut results_final = Vec::new();
239 let mut results: Vec<JsValue> = Vec::new();
240 for item in args {
241 if let Some(str) = item.as_str() {
242 for str in str.split('/') {
243 match str {
244 "" | "." => {
245 if results_final.is_empty() && results.is_empty() {
246 results_final.push(str.into());
247 }
248 }
249 ".." => {
250 if results.pop().is_none() {
251 results_final.push("..".into());
252 }
253 }
254 _ => results.push(str.into()),
255 }
256 }
257 } else {
258 results_final.append(&mut results);
259 results_final.push(item);
260 }
261 }
262 results_final.append(&mut results);
263 let mut iter = results_final.into_iter();
264 let first = iter.next().unwrap();
265
266 let is_already_absolute =
267 first.is_empty_string() == Some(true) || first.starts_with("/") == Some(true);
268
269 let mut last_was_str = first.as_str().is_some();
270
271 if !is_already_absolute {
272 results.push(cwd);
273 }
274
275 results.push(first);
276 for part in iter {
277 let is_str = part.as_str().is_some();
278 if last_was_str && is_str {
279 results.push("/".into());
280 } else {
281 results.push(JsValue::alternatives(vec!["/".into(), "".into()]));
282 }
283 results.push(part);
284 last_was_str = is_str;
285 }
286
287 JsValue::concat(results)
288}
289
290pub fn path_dirname(mut args: Vec<JsValue>) -> JsValue {
291 if let Some(arg) = args.iter_mut().next() {
292 if let Some(str) = arg.as_str() {
293 if let Some(i) = str.rfind('/') {
294 return JsValue::Constant(ConstantValue::Str(str[..i].to_string().into()));
295 } else {
296 return JsValue::Constant(ConstantValue::Str("".into()));
297 }
298 } else if let JsValue::Concat(_, items) = arg {
299 if let Some(last) = items.last_mut() {
300 if let Some(str) = last.as_str() {
301 if let Some(i) = str.rfind('/') {
302 *last = JsValue::Constant(ConstantValue::Str(str[..i].to_string().into()));
303 return take(arg);
304 }
305 }
306 }
307 }
308 }
309 JsValue::unknown(
310 JsValue::call(
311 Box::new(JsValue::WellKnownFunction(
312 WellKnownFunctionKind::PathDirname,
313 )),
314 args,
315 ),
316 true,
317 "path.dirname with unsupported arguments",
318 )
319}
320
321pub fn import(args: Vec<JsValue>) -> JsValue {
324 match &args[..] {
325 [JsValue::Constant(ConstantValue::Str(v))] => {
326 JsValue::promise(Box::new(JsValue::Module(ModuleValue {
327 module: v.as_atom().into_owned(),
328 annotations: ImportAnnotations::default(),
329 })))
330 }
331 _ => JsValue::unknown(
332 JsValue::call(
333 Box::new(JsValue::WellKnownFunction(WellKnownFunctionKind::Import)),
334 args,
335 ),
336 true,
337 "only a single constant argument is supported",
338 ),
339 }
340}
341
342pub fn require(args: Vec<JsValue>) -> JsValue {
345 if args.len() == 1 {
346 if let Some(s) = args[0].as_str() {
347 JsValue::Module(ModuleValue {
348 module: s.into(),
349 annotations: ImportAnnotations::default(),
350 })
351 } else {
352 JsValue::unknown(
353 JsValue::call(
354 Box::new(JsValue::WellKnownFunction(WellKnownFunctionKind::Require)),
355 args,
356 ),
357 true,
358 "only constant argument is supported",
359 )
360 }
361 } else {
362 JsValue::unknown(
363 JsValue::call(
364 Box::new(JsValue::WellKnownFunction(WellKnownFunctionKind::Require)),
365 args,
366 ),
367 true,
368 "only a single argument is supported",
369 )
370 }
371}
372
373async fn require_context_require(val: RequireContextValue, args: Vec<JsValue>) -> Result<JsValue> {
375 if args.is_empty() {
376 return Ok(JsValue::unknown(
377 JsValue::call(
378 Box::new(JsValue::WellKnownFunction(
379 WellKnownFunctionKind::RequireContextRequire(val),
380 )),
381 args,
382 ),
383 true,
384 "require.context(...).require() requires an argument specifying the module path",
385 ));
386 }
387
388 let Some(s) = args[0].as_str() else {
389 return Ok(JsValue::unknown(
390 JsValue::call(
391 Box::new(JsValue::WellKnownFunction(
392 WellKnownFunctionKind::RequireContextRequire(val),
393 )),
394 args,
395 ),
396 true,
397 "require.context(...).require() only accepts a single, constant string argument",
398 ));
399 };
400
401 let Some(m) = val.0.get(s) else {
402 return Ok(JsValue::unknown(
403 JsValue::call(
404 Box::new(JsValue::WellKnownFunction(
405 WellKnownFunctionKind::RequireContextRequire(val),
406 )),
407 args,
408 ),
409 true,
410 "require.context(...).require() can only be called with an argument that's in the \
411 context",
412 ));
413 };
414
415 Ok(JsValue::Module(ModuleValue {
416 module: m.to_string().into(),
417 annotations: ImportAnnotations::default(),
418 }))
419}
420
421async fn require_context_require_keys(
423 val: RequireContextValue,
424 args: Vec<JsValue>,
425) -> Result<JsValue> {
426 Ok(if args.is_empty() {
427 JsValue::array(val.0.keys().cloned().map(|k| k.into()).collect())
428 } else {
429 JsValue::unknown(
430 JsValue::call(
431 Box::new(JsValue::WellKnownFunction(
432 WellKnownFunctionKind::RequireContextRequireKeys(val),
433 )),
434 args,
435 ),
436 true,
437 "require.context(...).keys() does not accept arguments",
438 )
439 })
440}
441
442async fn require_context_require_resolve(
444 val: RequireContextValue,
445 args: Vec<JsValue>,
446) -> Result<JsValue> {
447 if args.len() != 1 {
448 return Ok(JsValue::unknown(
449 JsValue::call(
450 Box::new(JsValue::WellKnownFunction(
451 WellKnownFunctionKind::RequireContextRequireResolve(val),
452 )),
453 args,
454 ),
455 true,
456 "require.context(...).resolve() only accepts a single, constant string argument",
457 ));
458 }
459
460 let Some(s) = args[0].as_str() else {
461 return Ok(JsValue::unknown(
462 JsValue::call(
463 Box::new(JsValue::WellKnownFunction(
464 WellKnownFunctionKind::RequireContextRequireResolve(val),
465 )),
466 args,
467 ),
468 true,
469 "require.context(...).resolve() only accepts a single, constant string argument",
470 ));
471 };
472
473 let Some(m) = val.0.get(s) else {
474 return Ok(JsValue::unknown(
475 JsValue::call(
476 Box::new(JsValue::WellKnownFunction(
477 WellKnownFunctionKind::RequireContextRequireResolve(val),
478 )),
479 args,
480 ),
481 true,
482 "require.context(...).resolve() can only be called with an argument that's in the \
483 context",
484 ));
485 };
486
487 Ok(m.as_str().into())
488}
489
490pub fn path_to_file_url(args: Vec<JsValue>) -> JsValue {
491 if args.len() == 1 {
492 if let Some(path) = args[0].as_str() {
493 Url::from_file_path(path)
494 .map(|url| JsValue::Url(String::from(url).into(), JsValueUrlKind::Absolute))
495 .unwrap_or_else(|_| {
496 JsValue::unknown(
497 JsValue::call(
498 Box::new(JsValue::WellKnownFunction(
499 WellKnownFunctionKind::PathToFileUrl,
500 )),
501 args,
502 ),
503 true,
504 "url not parseable: path is relative or has an invalid prefix",
505 )
506 })
507 } else {
508 JsValue::unknown(
509 JsValue::call(
510 Box::new(JsValue::WellKnownFunction(
511 WellKnownFunctionKind::PathToFileUrl,
512 )),
513 args,
514 ),
515 true,
516 "only constant argument is supported",
517 )
518 }
519 } else {
520 JsValue::unknown(
521 JsValue::call(
522 Box::new(JsValue::WellKnownFunction(
523 WellKnownFunctionKind::PathToFileUrl,
524 )),
525 args,
526 ),
527 true,
528 "only a single argument is supported",
529 )
530 }
531}
532
533pub fn well_known_function_member(kind: WellKnownFunctionKind, prop: JsValue) -> (JsValue, bool) {
534 let new_value = match (kind, prop.as_str()) {
535 (WellKnownFunctionKind::Require, Some("resolve")) => {
536 JsValue::WellKnownFunction(WellKnownFunctionKind::RequireResolve)
537 }
538 (WellKnownFunctionKind::Require, Some("cache")) => {
539 JsValue::WellKnownObject(WellKnownObjectKind::RequireCache)
540 }
541 (WellKnownFunctionKind::Require, Some("context")) => {
542 JsValue::WellKnownFunction(WellKnownFunctionKind::RequireContext)
543 }
544 (WellKnownFunctionKind::RequireContextRequire(val), Some("resolve")) => {
545 JsValue::WellKnownFunction(WellKnownFunctionKind::RequireContextRequireResolve(val))
546 }
547 (WellKnownFunctionKind::RequireContextRequire(val), Some("keys")) => {
548 JsValue::WellKnownFunction(WellKnownFunctionKind::RequireContextRequireKeys(val))
549 }
550 (WellKnownFunctionKind::NodeStrongGlobalize, Some("SetRootDir")) => {
551 JsValue::WellKnownFunction(WellKnownFunctionKind::NodeStrongGlobalizeSetRootDir)
552 }
553 (WellKnownFunctionKind::NodeResolveFrom, Some("silent")) => {
554 JsValue::WellKnownFunction(WellKnownFunctionKind::NodeResolveFrom)
555 }
556 (WellKnownFunctionKind::Import, Some("meta")) => {
557 JsValue::WellKnownObject(WellKnownObjectKind::ImportMeta)
558 }
559 #[allow(unreachable_patterns)]
560 (kind, _) => {
561 return (
562 JsValue::member(Box::new(JsValue::WellKnownFunction(kind)), Box::new(prop)),
563 false,
564 );
565 }
566 };
567 (new_value, true)
568}
569
570pub async fn well_known_object_member(
571 kind: WellKnownObjectKind,
572 prop: JsValue,
573 compile_time_info: Vc<CompileTimeInfo>,
574) -> Result<(JsValue, bool)> {
575 let new_value = match kind {
576 WellKnownObjectKind::GlobalObject => global_object(prop),
577 WellKnownObjectKind::PathModule | WellKnownObjectKind::PathModuleDefault => {
578 path_module_member(kind, prop)
579 }
580 WellKnownObjectKind::FsModule
581 | WellKnownObjectKind::FsModuleDefault
582 | WellKnownObjectKind::FsModulePromises => fs_module_member(kind, prop),
583 WellKnownObjectKind::UrlModule | WellKnownObjectKind::UrlModuleDefault => {
584 url_module_member(kind, prop)
585 }
586 WellKnownObjectKind::ChildProcess | WellKnownObjectKind::ChildProcessDefault => {
587 child_process_module_member(kind, prop)
588 }
589 WellKnownObjectKind::OsModule | WellKnownObjectKind::OsModuleDefault => {
590 os_module_member(kind, prop)
591 }
592 WellKnownObjectKind::NodeProcess => node_process_member(prop, compile_time_info).await?,
593 WellKnownObjectKind::NodePreGyp => node_pre_gyp(prop),
594 WellKnownObjectKind::NodeExpressApp => express(prop),
595 WellKnownObjectKind::NodeProtobufLoader => protobuf_loader(prop),
596 #[allow(unreachable_patterns)]
597 _ => {
598 return Ok((
599 JsValue::member(Box::new(JsValue::WellKnownObject(kind)), Box::new(prop)),
600 false,
601 ));
602 }
603 };
604 Ok((new_value, true))
605}
606
607fn global_object(prop: JsValue) -> JsValue {
608 match prop.as_str() {
609 Some("assign") => JsValue::WellKnownFunction(WellKnownFunctionKind::ObjectAssign),
610 _ => JsValue::unknown(
611 JsValue::member(
612 Box::new(JsValue::WellKnownObject(WellKnownObjectKind::GlobalObject)),
613 Box::new(prop),
614 ),
615 true,
616 "unsupported property on global Object",
617 ),
618 }
619}
620
621pub fn path_module_member(kind: WellKnownObjectKind, prop: JsValue) -> JsValue {
622 match (kind, prop.as_str()) {
623 (.., Some("join")) => JsValue::WellKnownFunction(WellKnownFunctionKind::PathJoin),
624 (.., Some("dirname")) => JsValue::WellKnownFunction(WellKnownFunctionKind::PathDirname),
625 (.., Some("resolve")) => {
626 JsValue::WellKnownFunction(WellKnownFunctionKind::PathResolve(Box::new(JsValue::from(
628 "",
629 ))))
630 }
631 (WellKnownObjectKind::PathModule, Some("default")) => {
632 JsValue::WellKnownObject(WellKnownObjectKind::PathModuleDefault)
633 }
634 _ => JsValue::unknown(
635 JsValue::member(
636 Box::new(JsValue::WellKnownObject(WellKnownObjectKind::PathModule)),
637 Box::new(prop),
638 ),
639 true,
640 "unsupported property on Node.js path module",
641 ),
642 }
643}
644
645pub fn fs_module_member(kind: WellKnownObjectKind, prop: JsValue) -> JsValue {
646 if let Some(word) = prop.as_str() {
647 match (kind, word) {
648 (
649 ..,
650 "realpath" | "realpathSync" | "stat" | "statSync" | "existsSync"
651 | "createReadStream" | "exists" | "open" | "openSync" | "readFile" | "readFileSync",
652 ) => {
653 return JsValue::WellKnownFunction(WellKnownFunctionKind::FsReadMethod(
654 word.into(),
655 ));
656 }
657 (WellKnownObjectKind::FsModule | WellKnownObjectKind::FsModuleDefault, "promises") => {
658 return JsValue::WellKnownObject(WellKnownObjectKind::FsModulePromises);
659 }
660 (WellKnownObjectKind::FsModule, "default") => {
661 return JsValue::WellKnownObject(WellKnownObjectKind::FsModuleDefault);
662 }
663 _ => {}
664 }
665 }
666 JsValue::unknown(
667 JsValue::member(
668 Box::new(JsValue::WellKnownObject(WellKnownObjectKind::FsModule)),
669 Box::new(prop),
670 ),
671 true,
672 "unsupported property on Node.js fs module",
673 )
674}
675
676pub fn url_module_member(kind: WellKnownObjectKind, prop: JsValue) -> JsValue {
677 match (kind, prop.as_str()) {
678 (.., Some("pathToFileURL")) => {
679 JsValue::WellKnownFunction(WellKnownFunctionKind::PathToFileUrl)
680 }
681 (WellKnownObjectKind::UrlModuleDefault, Some("default")) => {
682 JsValue::WellKnownObject(WellKnownObjectKind::UrlModuleDefault)
683 }
684 _ => JsValue::unknown(
685 JsValue::member(
686 Box::new(JsValue::WellKnownObject(WellKnownObjectKind::UrlModule)),
687 Box::new(prop),
688 ),
689 true,
690 "unsupported property on Node.js url module",
691 ),
692 }
693}
694
695pub fn child_process_module_member(kind: WellKnownObjectKind, prop: JsValue) -> JsValue {
696 let prop_str = prop.as_str();
697 match (kind, prop_str) {
698 (.., Some("spawn" | "spawnSync" | "execFile" | "execFileSync")) => {
699 JsValue::WellKnownFunction(WellKnownFunctionKind::ChildProcessSpawnMethod(
700 prop_str.unwrap().into(),
701 ))
702 }
703 (.., Some("fork")) => JsValue::WellKnownFunction(WellKnownFunctionKind::ChildProcessFork),
704 (WellKnownObjectKind::ChildProcess, Some("default")) => {
705 JsValue::WellKnownObject(WellKnownObjectKind::ChildProcessDefault)
706 }
707
708 _ => JsValue::unknown(
709 JsValue::member(
710 Box::new(JsValue::WellKnownObject(WellKnownObjectKind::ChildProcess)),
711 Box::new(prop),
712 ),
713 true,
714 "unsupported property on Node.js child_process module",
715 ),
716 }
717}
718
719fn os_module_member(kind: WellKnownObjectKind, prop: JsValue) -> JsValue {
720 match (kind, prop.as_str()) {
721 (.., Some("platform")) => JsValue::WellKnownFunction(WellKnownFunctionKind::OsPlatform),
722 (.., Some("arch")) => JsValue::WellKnownFunction(WellKnownFunctionKind::OsArch),
723 (.., Some("endianness")) => JsValue::WellKnownFunction(WellKnownFunctionKind::OsEndianness),
724 (WellKnownObjectKind::OsModule, Some("default")) => {
725 JsValue::WellKnownObject(WellKnownObjectKind::OsModuleDefault)
726 }
727 _ => JsValue::unknown(
728 JsValue::member(
729 Box::new(JsValue::WellKnownObject(WellKnownObjectKind::OsModule)),
730 Box::new(prop),
731 ),
732 true,
733 "unsupported property on Node.js os module",
734 ),
735 }
736}
737
738async fn node_process_member(
739 prop: JsValue,
740 compile_time_info: Vc<CompileTimeInfo>,
741) -> Result<JsValue> {
742 Ok(match prop.as_str() {
743 Some("arch") => compile_time_info
744 .environment()
745 .compile_target()
746 .await?
747 .arch
748 .as_str()
749 .into(),
750 Some("platform") => compile_time_info
751 .environment()
752 .compile_target()
753 .await?
754 .platform
755 .as_str()
756 .into(),
757 Some("cwd") => JsValue::WellKnownFunction(WellKnownFunctionKind::ProcessCwd),
758 Some("argv") => JsValue::WellKnownObject(WellKnownObjectKind::NodeProcessArgv),
759 Some("env") => JsValue::WellKnownObject(WellKnownObjectKind::NodeProcessEnv),
760 _ => JsValue::unknown(
761 JsValue::member(
762 Box::new(JsValue::WellKnownObject(WellKnownObjectKind::NodeProcess)),
763 Box::new(prop),
764 ),
765 true,
766 "unsupported property on Node.js process object",
767 ),
768 })
769}
770
771fn node_pre_gyp(prop: JsValue) -> JsValue {
772 match prop.as_str() {
773 Some("find") => JsValue::WellKnownFunction(WellKnownFunctionKind::NodePreGypFind),
774 _ => JsValue::unknown(
775 JsValue::member(
776 Box::new(JsValue::WellKnownObject(WellKnownObjectKind::NodePreGyp)),
777 Box::new(prop),
778 ),
779 true,
780 "unsupported property on @mapbox/node-pre-gyp module",
781 ),
782 }
783}
784
785fn express(prop: JsValue) -> JsValue {
786 match prop.as_str() {
787 Some("set") => JsValue::WellKnownFunction(WellKnownFunctionKind::NodeExpressSet),
788 _ => JsValue::unknown(
789 JsValue::member(
790 Box::new(JsValue::WellKnownObject(
791 WellKnownObjectKind::NodeExpressApp,
792 )),
793 Box::new(prop),
794 ),
795 true,
796 "unsupported property on require('express')() object",
797 ),
798 }
799}
800
801fn protobuf_loader(prop: JsValue) -> JsValue {
802 match prop.as_str() {
803 Some("load") | Some("loadSync") => {
804 JsValue::WellKnownFunction(WellKnownFunctionKind::NodeProtobufLoad)
805 }
806 _ => JsValue::unknown(
807 JsValue::member(
808 Box::new(JsValue::WellKnownObject(
809 WellKnownObjectKind::NodeProtobufLoader,
810 )),
811 Box::new(prop),
812 ),
813 true,
814 "unsupported property on require('@grpc/proto-loader') object",
815 ),
816 }
817}