turbopack_ecmascript_runtime/
browser_runtime.rs1use std::io::Write;
2
3use anyhow::Result;
4use indoc::writedoc;
5use turbo_rcstr::{RcStr, rcstr};
6use turbo_tasks::{ResolvedVc, Vc};
7use turbopack_core::{
8 code_builder::{Code, CodeBuilder},
9 context::AssetContext,
10 environment::{ChunkLoading, Environment},
11};
12use turbopack_ecmascript::{magic_identifier, utils::StringifyJs};
13
14use crate::{RuntimeType, asset_context::get_runtime_asset_context, embed_js::embed_static_code};
15
16#[turbo_tasks::function]
18pub async fn get_browser_runtime_code(
19 environment: ResolvedVc<Environment>,
20 chunk_base_path: Vc<Option<RcStr>>,
21 chunk_suffix_path: Vc<Option<RcStr>>,
22 runtime_type: RuntimeType,
23 output_root_to_root_path: RcStr,
24 generate_source_map: bool,
25) -> Result<Vc<Code>> {
26 let asset_context = get_runtime_asset_context(*environment).resolve().await?;
27
28 let shared_runtime_utils_code = embed_static_code(
29 asset_context,
30 rcstr!("shared/runtime-utils.ts"),
31 generate_source_map,
32 );
33
34 let mut runtime_base_code = vec!["browser/runtime/base/runtime-base.ts"];
35 match runtime_type {
36 RuntimeType::Production => runtime_base_code.push("browser/runtime/base/build-base.ts"),
37 RuntimeType::Development => {
38 debug_assert!(
39 magic_identifier::mangle("module evaluation").as_str()
42 == "__TURBOPACK__module__evaluation__"
43 );
44 runtime_base_code.push("browser/runtime/base/dev-base.ts");
45 }
46 #[cfg(feature = "test")]
47 RuntimeType::Dummy => {
48 panic!("This configuration is not supported in the browser runtime")
49 }
50 }
51
52 let chunk_loading = &*asset_context
53 .compile_time_info()
54 .environment()
55 .chunk_loading()
56 .await?;
57
58 let mut runtime_backend_code = vec![];
59 match (chunk_loading, runtime_type) {
60 (ChunkLoading::Edge, RuntimeType::Development) => {
61 runtime_backend_code.push("browser/runtime/edge/runtime-backend-edge.ts");
62 runtime_backend_code.push("browser/runtime/edge/dev-backend-edge.ts");
63 }
64 (ChunkLoading::Edge, RuntimeType::Production) => {
65 runtime_backend_code.push("browser/runtime/edge/runtime-backend-edge.ts");
66 }
67 (ChunkLoading::NodeJs, _) => {
69 panic!("Node.js runtime is not supported in the browser runtime!")
70 }
71 (ChunkLoading::Dom, RuntimeType::Development) => {
72 runtime_backend_code.push("browser/runtime/dom/runtime-backend-dom.ts");
73 runtime_backend_code.push("browser/runtime/dom/dev-backend-dom.ts");
74 }
75 (ChunkLoading::Dom, RuntimeType::Production) => {
76 runtime_backend_code.push("browser/runtime/dom/runtime-backend-dom.ts");
77 }
78
79 #[cfg(feature = "test")]
80 (_, RuntimeType::Dummy) => {
81 panic!("This configuration is not supported in the browser runtime")
82 }
83 };
84
85 let mut code: CodeBuilder = CodeBuilder::default();
86 let relative_root_path = output_root_to_root_path;
87 let chunk_base_path = chunk_base_path.await?;
88 let chunk_base_path = chunk_base_path.as_ref().map_or_else(|| "", |f| f.as_str());
89 let chunk_suffix_path = chunk_suffix_path.await?;
90 let chunk_suffix_path = chunk_suffix_path
91 .as_ref()
92 .map_or_else(|| "", |f| f.as_str());
93
94 writedoc!(
95 code,
96 r#"
97 (() => {{
98 if (!Array.isArray(globalThis.TURBOPACK)) {{
99 return;
100 }}
101
102 const CHUNK_BASE_PATH = {};
103 const CHUNK_SUFFIX_PATH = {};
104 const RELATIVE_ROOT_PATH = {};
105 const RUNTIME_PUBLIC_PATH = {};
106 "#,
107 StringifyJs(chunk_base_path),
108 StringifyJs(chunk_suffix_path),
109 StringifyJs(relative_root_path.as_str()),
110 StringifyJs(chunk_base_path),
111 )?;
112
113 code.push_code(&*shared_runtime_utils_code.await?);
114 for runtime_code in runtime_base_code {
115 code.push_code(
116 &*embed_static_code(asset_context, runtime_code.into(), generate_source_map).await?,
117 );
118 }
119
120 if *environment.supports_commonjs_externals().await? {
121 code.push_code(
122 &*embed_static_code(
123 asset_context,
124 rcstr!("shared-node/base-externals-utils.ts"),
125 generate_source_map,
126 )
127 .await?,
128 );
129 }
130 if *environment.node_externals().await? {
131 code.push_code(
132 &*embed_static_code(
133 asset_context,
134 rcstr!("shared-node/node-externals-utils.ts"),
135 generate_source_map,
136 )
137 .await?,
138 );
139 }
140 if *environment.supports_wasm().await? {
141 code.push_code(
142 &*embed_static_code(
143 asset_context,
144 rcstr!("shared-node/node-wasm-utils.ts"),
145 generate_source_map,
146 )
147 .await?,
148 );
149 }
150
151 for backend_code in runtime_backend_code {
152 code.push_code(
153 &*embed_static_code(asset_context, backend_code.into(), generate_source_map).await?,
154 );
155 }
156
157 writedoc!(
160 code,
161 r#"
162 const chunksToRegister = globalThis.TURBOPACK;
163 globalThis.TURBOPACK = {{ push: registerChunk }};
164 chunksToRegister.forEach(registerChunk);
165 "#
166 )?;
167 if matches!(runtime_type, RuntimeType::Development) {
168 writedoc!(
169 code,
170 r#"
171 const chunkListsToRegister = globalThis.TURBOPACK_CHUNK_LISTS || [];
172 globalThis.TURBOPACK_CHUNK_LISTS = {{ push: registerChunkList }};
173 chunkListsToRegister.forEach(registerChunkList);
174 "#
175 )?;
176 }
177 writedoc!(
178 code,
179 r#"
180 }})();
181 "#
182 )?;
183
184 Ok(Code::cell(code.build()))
185}