Skip to main content

turbopack_ecmascript_runtime/
nodejs_runtime.rs

1use anyhow::Result;
2use turbo_rcstr::rcstr;
3use turbo_tasks::{ResolvedVc, Vc};
4use turbopack_core::{
5    code_builder::{Code, CodeBuilder},
6    context::AssetContext,
7};
8
9use crate::{RuntimeType, embed_js::embed_static_code};
10
11/// Returns the code for the Node.js ECMAScript runtime.
12#[turbo_tasks::function]
13pub async fn get_nodejs_runtime_code(
14    asset_context: ResolvedVc<Box<dyn AssetContext>>,
15    runtime_type: RuntimeType,
16    include_async_module_runtime: bool,
17    generate_source_map: bool,
18) -> Result<Vc<Code>> {
19    let asset_context = *asset_context;
20
21    let shared_runtime_utils_code = embed_static_code(
22        asset_context,
23        rcstr!("shared/runtime/runtime-utils.ts"),
24        generate_source_map,
25    );
26    let shared_base_external_utils_code = embed_static_code(
27        asset_context,
28        rcstr!("shared-node/base-externals-utils.ts"),
29        generate_source_map,
30    );
31    let shared_node_external_utils_code = embed_static_code(
32        asset_context,
33        rcstr!("shared-node/node-externals-utils.ts"),
34        generate_source_map,
35    );
36    // Runtime base is shared between production and development
37    let runtime_base_code = embed_static_code(
38        asset_context,
39        rcstr!("nodejs/runtime/runtime-base.ts"),
40        generate_source_map,
41    );
42
43    let mut code = CodeBuilder::default();
44    code.push_code(&*shared_runtime_utils_code.await?);
45    if include_async_module_runtime {
46        code.push_code(
47            &*embed_static_code(
48                asset_context,
49                rcstr!("shared/runtime/async-module.ts"),
50                generate_source_map,
51            )
52            .await?,
53        );
54    }
55    code.push_code(&*shared_base_external_utils_code.await?);
56    code.push_code(&*shared_node_external_utils_code.await?);
57    code.push_code(&*runtime_base_code.await?);
58
59    match runtime_type {
60        RuntimeType::Production => {
61            code.push_code(
62                &*embed_static_code(
63                    asset_context,
64                    rcstr!("nodejs/runtime/build-base.ts"),
65                    generate_source_map,
66                )
67                .await?,
68            );
69        }
70        RuntimeType::Development => {
71            // Include shared HMR runtime (includes instantiateModuleShared, etc.)
72            code.push_code(
73                &*embed_static_code(
74                    asset_context,
75                    rcstr!("shared/runtime/hmr-runtime.ts"),
76                    generate_source_map,
77                )
78                .await?,
79            );
80
81            // Include Node.js-specific dev runtime
82            code.push_code(
83                &*embed_static_code(
84                    asset_context,
85                    rcstr!("nodejs/runtime/dev-base.ts"),
86                    generate_source_map,
87                )
88                .await?,
89            );
90
91            // Include Node.js HMR client (standalone, doesn't use shared ESM client)
92            code.push_code(
93                &*embed_static_code(
94                    asset_context,
95                    rcstr!("nodejs/dev/hmr-client.ts"),
96                    generate_source_map,
97                )
98                .await?,
99            );
100
101            // Include dev-nodejs (HMR initialization and __turbopack_server_hmr_apply__)
102            code.push_code(
103                &*embed_static_code(
104                    asset_context,
105                    rcstr!("nodejs/dev/dev-nodejs.ts"),
106                    generate_source_map,
107                )
108                .await?,
109            );
110        }
111        #[cfg(feature = "test")]
112        RuntimeType::Dummy => {
113            panic!("Dummy runtime is not supported in Node.js runtime")
114        }
115    }
116
117    Ok(Code::cell(code.build()))
118}