Skip to main content

turbopack_ecmascript/analyzer/well_known/
kinds.rs

1use swc_core::ecma::atoms::Atom;
2
3use crate::analyzer::{ConstantString, JsValue, RequireContextValue};
4
5/// A list of well-known objects that have special meaning in the analysis.
6#[derive(Debug, Clone, Hash, PartialEq, Eq)]
7pub enum WellKnownObjectKind {
8    GlobalObject,
9    PathModule,
10    PathModuleDefault,
11    FsModule,
12    FsModuleDefault,
13    FsModulePromises,
14    FsExtraModule,
15    FsExtraModuleDefault,
16    GracefulFsModule,
17    GracefulFsModuleDefault,
18    ModuleModule,
19    ModuleModuleDefault,
20    UrlModule,
21    UrlModuleDefault,
22    WorkerThreadsModule,
23    WorkerThreadsModuleDefault,
24    ChildProcessModule,
25    ChildProcessModuleDefault,
26    OsModule,
27    OsModuleDefault,
28    NodeProcessModule,
29    NodeProcessArgv,
30    NodeProcessEnv,
31    NodePreGyp,
32    NodeExpressApp,
33    NodeProtobufLoader,
34    NodeBuffer,
35    RequireCache,
36    ImportMeta,
37    ImportMetaEnv,
38    /// An iterator object, used to model generator return values.
39    Generator,
40    /// The `module.hot` object providing HMR API.
41    ModuleHot,
42    /// The browser `navigator` global.
43    Navigator,
44    /// The `navigator.serviceWorker` container (`ServiceWorkerContainer`).
45    NavigatorServiceWorker,
46}
47
48impl WellKnownObjectKind {
49    pub fn as_define_name(&self) -> Option<&[&str]> {
50        match self {
51            Self::GlobalObject => Some(&["Object"]),
52            Self::PathModule => Some(&["path"]),
53            Self::FsModule => Some(&["fs"]),
54            Self::UrlModule => Some(&["url"]),
55            Self::ChildProcessModule => Some(&["child_process"]),
56            Self::OsModule => Some(&["os"]),
57            Self::WorkerThreadsModule => Some(&["worker_threads"]),
58            Self::NodeProcessModule => Some(&["process"]),
59            Self::NodeProcessArgv => Some(&["process", "argv"]),
60            Self::NodeProcessEnv => Some(&["process", "env"]),
61            Self::NodeBuffer => Some(&["Buffer"]),
62            Self::RequireCache => Some(&["require", "cache"]),
63            Self::ImportMeta => Some(&["import", "meta"]),
64            _ => None,
65        }
66    }
67
68    /// Returns a short display name and a longer explanation for this object,
69    /// used when rendering [`JsValue`][crate::analyzer::JsValue] explanations.
70    pub fn explain(&self) -> (&'static str, &'static str) {
71        match self {
72            Self::Generator => (
73                "Generator",
74                "A Generator or AsyncGenerator object: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator",
75            ),
76            Self::GlobalObject => ("Object", "The global Object variable"),
77            Self::PathModule | Self::PathModuleDefault => (
78                "path",
79                "The Node.js path module: https://nodejs.org/api/path.html",
80            ),
81            Self::FsModule | Self::FsModuleDefault => (
82                "fs",
83                "The Node.js fs module: https://nodejs.org/api/fs.html",
84            ),
85            Self::FsExtraModule | Self::FsExtraModuleDefault => (
86                "fs-extra",
87                "The Node.js fs-extra module: https://github.com/jprichardson/node-fs-extra",
88            ),
89            Self::GracefulFsModule | Self::GracefulFsModuleDefault => (
90                "graceful-fs",
91                "The Node.js graceful-fs module: https://github.com/isaacs/node-graceful-fs",
92            ),
93            Self::FsModulePromises => (
94                "fs/promises",
95                "The Node.js fs module: https://nodejs.org/api/fs.html#promises-api",
96            ),
97            Self::UrlModule | Self::UrlModuleDefault => (
98                "url",
99                "The Node.js url module: https://nodejs.org/api/url.html",
100            ),
101            Self::ModuleModule | Self::ModuleModuleDefault => (
102                "module",
103                "The Node.js `module` module: https://nodejs.org/api/module.html",
104            ),
105            Self::WorkerThreadsModule | Self::WorkerThreadsModuleDefault => (
106                "worker_threads",
107                "The Node.js `worker_threads` module: https://nodejs.org/api/worker_threads.html",
108            ),
109            Self::ChildProcessModule | Self::ChildProcessModuleDefault => (
110                "child_process",
111                "The Node.js child_process module: https://nodejs.org/api/child_process.html",
112            ),
113            Self::OsModule | Self::OsModuleDefault => (
114                "os",
115                "The Node.js os module: https://nodejs.org/api/os.html",
116            ),
117            Self::NodeProcessModule => (
118                "process",
119                "The Node.js process module: https://nodejs.org/api/process.html",
120            ),
121            Self::NodeProcessArgv => (
122                "process.argv",
123                "The Node.js process.argv property: https://nodejs.org/api/process.html#processargv",
124            ),
125            Self::NodeProcessEnv => (
126                "process.env",
127                "The Node.js process.env property: https://nodejs.org/api/process.html#processenv",
128            ),
129            Self::NodePreGyp => (
130                "@mapbox/node-pre-gyp",
131                "The Node.js @mapbox/node-pre-gyp module: https://github.com/mapbox/node-pre-gyp",
132            ),
133            Self::NodeExpressApp => (
134                "express",
135                "The Node.js express package: https://github.com/expressjs/express",
136            ),
137            Self::NodeProtobufLoader => (
138                "@grpc/proto-loader",
139                "The Node.js @grpc/proto-loader package: https://github.com/grpc/grpc-node",
140            ),
141            Self::NodeBuffer => (
142                "Buffer",
143                "The Node.js Buffer object: https://nodejs.org/api/buffer.html#class-buffer",
144            ),
145            Self::RequireCache => (
146                "require.cache",
147                "The CommonJS require.cache object: https://nodejs.org/api/modules.html#requirecache",
148            ),
149            Self::ImportMeta => ("import.meta", "The import.meta object"),
150            Self::ImportMetaEnv => ("import.meta.env", "The import.meta.env object"),
151            Self::ModuleHot => ("module.hot", "The module.hot HMR API"),
152            Self::Navigator => (
153                "navigator",
154                "The browser navigator global: https://developer.mozilla.org/en-US/docs/Web/API/Navigator",
155            ),
156            Self::NavigatorServiceWorker => (
157                "navigator.serviceWorker",
158                "The ServiceWorkerContainer: https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerContainer",
159            ),
160        }
161    }
162}
163
164/// A list of well-known functions that have special meaning in the analysis.
165#[derive(Debug, Clone, Hash, PartialEq)]
166pub enum WellKnownFunctionKind<'a> {
167    ArrayFilter,
168    ArrayForEach,
169    ArrayMap,
170    ObjectAssign,
171    PathJoin,
172    PathDirname,
173    /// `0` is the current working directory.
174    PathResolve(&'a JsValue<'a>),
175    Import,
176    Require,
177    /// `0` is the path to resolve from (relative to the current module).
178    RequireFrom(Box<ConstantString>),
179    RequireResolve,
180    RequireContext,
181    // Boxed: `RequireContextValue` wraps a 56-byte `FxIndexMap`. Inlining it here dominates
182    // `WellKnownFunctionKind`'s size (64 bytes) and by extension `JsValue`.
183    RequireContextRequire(Box<RequireContextValue>),
184    RequireContextRequireKeys(Box<RequireContextValue>),
185    RequireContextRequireResolve(Box<RequireContextValue>),
186    Define,
187    FsReadMethod(Atom),
188    FsReadDir,
189    PathToFileUrl,
190    CreateRequire,
191    ChildProcessSpawnMethod(Atom),
192    ChildProcessFork,
193    OsArch,
194    OsPlatform,
195    OsEndianness,
196    ProcessCwd,
197    NodePreGypFind,
198    NodeGypBuild,
199    NodeBindings,
200    NodeExpress,
201    NodeExpressSet,
202    NodeStrongGlobalize,
203    NodeStrongGlobalizeSetRootDir,
204    NodeResolveFrom,
205    NodeProtobufLoad,
206    WorkerConstructor,
207    SharedWorkerConstructor,
208    // The worker_threads Worker class
209    NodeWorkerConstructor,
210    /// `navigator.serviceWorker.register(scriptURL, options?)`
211    ServiceWorkerRegister,
212    URLConstructor,
213    /// `module.hot.accept(deps, callback, errorHandler)` — accept HMR updates for dependencies.
214    ModuleHotAccept,
215    /// `module.hot.decline(deps)` — decline HMR updates for dependencies.
216    ModuleHotDecline,
217    /// `import.meta.glob(patterns, options?)` — Vite-compatible glob import.
218    ImportMetaGlob,
219    /// `__turbopack_emit__` — Emit data to the bundler.
220    TurbopackEmit,
221    /// `__turbopack_collect__` — Collect emitted data from the bundler.
222    TurbopackCollect,
223}
224
225impl WellKnownFunctionKind<'_> {
226    pub fn as_define_name(&self) -> Option<&[&str]> {
227        match self {
228            Self::Import { .. } => Some(&["import"]),
229            Self::Require { .. } => Some(&["require"]),
230            Self::RequireResolve => Some(&["require", "resolve"]),
231            Self::RequireContext => Some(&["require", "context"]),
232            Self::Define => Some(&["define"]),
233            _ => None,
234        }
235    }
236
237    /// Returns a short display name and a longer explanation for this function,
238    /// used when rendering [`JsValue`][crate::analyzer::JsValue] explanations.
239    pub fn explain(&self) -> (String, &'static str) {
240        match self {
241            Self::ArrayFilter => (
242                "Array.prototype.filter".to_string(),
243                "The standard Array.prototype.filter method: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter",
244            ),
245            Self::ArrayForEach => (
246                "Array.prototype.forEach".to_string(),
247                "The standard Array.prototype.forEach method: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach",
248            ),
249            Self::ArrayMap => (
250                "Array.prototype.map".to_string(),
251                "The standard Array.prototype.map method: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map",
252            ),
253            Self::ObjectAssign => (
254                "Object.assign".to_string(),
255                "Object.assign method: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/assign",
256            ),
257            Self::PathJoin => (
258                "path.join".to_string(),
259                "The Node.js path.join method: https://nodejs.org/api/path.html#pathjoinpaths",
260            ),
261            Self::PathDirname => (
262                "path.dirname".to_string(),
263                "The Node.js path.dirname method: https://nodejs.org/api/path.html#pathdirnamepath",
264            ),
265            Self::PathResolve(cwd) => (
266                format!("path.resolve({cwd})"),
267                "The Node.js path.resolve method: https://nodejs.org/api/path.html#pathresolvepaths",
268            ),
269            Self::Import => (
270                "import".to_string(),
271                "The dynamic import() method from the ESM specification: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#dynamic_imports",
272            ),
273            Self::Require => ("require".to_string(), "The require method from CommonJS"),
274            Self::RequireFrom(rel) => (
275                format!("createRequire('{rel}')"),
276                "The return value of Node.js module.createRequire: https://nodejs.org/api/module.html#modulecreaterequirefilename",
277            ),
278            Self::RequireResolve => (
279                "require.resolve".to_string(),
280                "The require.resolve method from CommonJS",
281            ),
282            Self::RequireContext => (
283                "require.context".to_string(),
284                "The require.context method from webpack",
285            ),
286            Self::RequireContextRequire(..) => (
287                "require.context(...)".to_string(),
288                "The require.context(...) method from webpack: https://webpack.js.org/api/module-methods/#requirecontext",
289            ),
290            Self::RequireContextRequireKeys(..) => (
291                "require.context(...).keys".to_string(),
292                "The require.context(...).keys method from webpack: https://webpack.js.org/guides/dependency-management/#requirecontext",
293            ),
294            Self::RequireContextRequireResolve(..) => (
295                "require.context(...).resolve".to_string(),
296                "The require.context(...).resolve method from webpack: https://webpack.js.org/guides/dependency-management/#requirecontext",
297            ),
298            Self::Define => ("define".to_string(), "The define method from AMD"),
299            Self::FsReadMethod(name) => (
300                format!("fs.{name}"),
301                "A file reading method from the Node.js fs module: https://nodejs.org/api/fs.html",
302            ),
303            Self::FsReadDir => (
304                "fs.readdir".to_string(),
305                "The Node.js fs.readdir method: https://nodejs.org/api/fs.html",
306            ),
307            Self::PathToFileUrl => (
308                "url.pathToFileURL".to_string(),
309                "The Node.js url.pathToFileURL method: https://nodejs.org/api/url.html#urlpathtofileurlpath",
310            ),
311            Self::CreateRequire => (
312                "module.createRequire".to_string(),
313                "The Node.js module.createRequire method: https://nodejs.org/api/module.html#modulecreaterequirefilename",
314            ),
315            Self::ChildProcessSpawnMethod(name) => (
316                format!("child_process.{name}"),
317                "A process spawning method from the Node.js child_process module: https://nodejs.org/api/child_process.html",
318            ),
319            Self::ChildProcessFork => (
320                "child_process.fork".to_string(),
321                "The Node.js child_process.fork method: https://nodejs.org/api/child_process.html#child_processforkmodulepath-args-options",
322            ),
323            Self::OsArch => (
324                "os.arch".to_string(),
325                "The Node.js os.arch method: https://nodejs.org/api/os.html#os_os_arch",
326            ),
327            Self::OsPlatform => (
328                "os.process".to_string(),
329                "The Node.js os.process method: https://nodejs.org/api/os.html#os_os_process",
330            ),
331            Self::OsEndianness => (
332                "os.endianness".to_string(),
333                "The Node.js os.endianness method: https://nodejs.org/api/os.html#os_os_endianness",
334            ),
335            Self::ProcessCwd => (
336                "process.cwd".to_string(),
337                "The Node.js process.cwd method: https://nodejs.org/api/process.html#processcwd",
338            ),
339            Self::NodePreGypFind => (
340                "binary.find".to_string(),
341                "The Node.js @mapbox/node-pre-gyp module: https://github.com/mapbox/node-pre-gyp",
342            ),
343            Self::NodeGypBuild => (
344                "node-gyp-build".to_string(),
345                "The Node.js node-gyp-build module: https://github.com/prebuild/node-gyp-build",
346            ),
347            Self::NodeBindings => (
348                "bindings".to_string(),
349                "The Node.js bindings module: https://github.com/TooTallNate/node-bindings",
350            ),
351            Self::NodeExpress => (
352                "express".to_string(),
353                "require('express')() : https://github.com/expressjs/express",
354            ),
355            Self::NodeExpressSet => (
356                "set".to_string(),
357                "require('express')().set('view engine', 'jade')  https://github.com/expressjs/express",
358            ),
359            Self::NodeStrongGlobalize => (
360                "SetRootDir".to_string(),
361                "require('strong-globalize')()  https://github.com/strongloop/strong-globalize",
362            ),
363            Self::NodeStrongGlobalizeSetRootDir => (
364                "SetRootDir".to_string(),
365                "require('strong-globalize').SetRootDir(__dirname)  https://github.com/strongloop/strong-globalize",
366            ),
367            Self::NodeResolveFrom => (
368                "resolveFrom".to_string(),
369                "require('resolve-from')(__dirname, 'node-gyp/bin/node-gyp')  https://github.com/sindresorhus/resolve-from",
370            ),
371            Self::NodeProtobufLoad => (
372                "load/loadSync".to_string(),
373                "require('@grpc/proto-loader').load(filepath, { includeDirs: [root] }) https://github.com/grpc/grpc-node",
374            ),
375            Self::NodeWorkerConstructor => (
376                "Worker".to_string(),
377                "The Node.js worker_threads Worker constructor: https://nodejs.org/api/worker_threads.html#worker_threads_class_worker",
378            ),
379            Self::WorkerConstructor => (
380                "Worker".to_string(),
381                "The standard Worker constructor: https://developer.mozilla.org/en-US/docs/Web/API/Worker/Worker",
382            ),
383            Self::SharedWorkerConstructor => (
384                "SharedWorker".to_string(),
385                "The standard SharedWorker constructor: https://developer.mozilla.org/en-US/docs/Web/API/SharedWorker/SharedWorker",
386            ),
387            Self::ServiceWorkerRegister => (
388                "navigator.serviceWorker.register".to_string(),
389                "The ServiceWorkerContainer.register method: https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerContainer/register",
390            ),
391            Self::URLConstructor => (
392                "URL".to_string(),
393                "The standard URL constructor: https://developer.mozilla.org/en-US/docs/Web/API/URL/URL",
394            ),
395            Self::ModuleHotAccept => (
396                "module.hot.accept".to_string(),
397                "The module.hot.accept HMR API: https://webpack.js.org/api/hot-module-replacement/#accept",
398            ),
399            Self::ModuleHotDecline => (
400                "module.hot.decline".to_string(),
401                "The module.hot.decline HMR API: https://webpack.js.org/api/hot-module-replacement/#decline",
402            ),
403            Self::ImportMetaGlob => (
404                "import.meta.glob".to_string(),
405                "The import.meta.glob() function from Vite: https://vite.dev/guide/features.html#glob-import",
406            ),
407            Self::TurbopackEmit => (
408                "__turbopack_emit__".to_string(),
409                "The __turbopack_emit__ function for emitting data to the bundler"
410            ),
411            Self::TurbopackCollect => (
412                "__turbopack_collect__".to_string(),
413                "The __turbopack_collect__ function for collecting emitted data from the bundler"
414            )
415        }
416    }
417}