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