Skip to content

Commit da06b98

Browse files
committed
[turbopack] Create a chunk_group_bootstrap_params() function
1 parent 8f48625 commit da06b98

1 file changed

Lines changed: 49 additions & 38 deletions

File tree

  • turbopack/crates/turbopack-browser/src/ecmascript/evaluate

turbopack/crates/turbopack-browser/src/ecmascript/evaluate/chunk.rs

Lines changed: 49 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ use std::io::Write;
22

33
use anyhow::Result;
44
use either::Either;
5-
use indoc::writedoc;
5+
use indoc::formatdoc;
66
use serde::Serialize;
7-
use turbo_rcstr::rcstr;
7+
use turbo_rcstr::{RcStr, rcstr};
88
use turbo_tasks::{ResolvedVc, TryJoinIterExt, ValueToString, Vc, turbobail};
99
use turbo_tasks_fs::{File, FileContent, FileSystemPath};
1010
use turbopack_core::{
@@ -70,31 +70,14 @@ impl EcmascriptBrowserEvaluateChunk {
7070
))
7171
}
7272

73+
/// The params for bootstrapping: `{ otherChunks, runtimeModuleIds }`. This
74+
/// describes which other chunks must load and which runtime modules to instantiate.
75+
///
76+
/// The emitted evaluate-chunk file ([`Self::code`]) reuses these same params,
77+
/// wrapping them as `push([selfPath, params])`. Next.js inlines them in production.
7378
#[turbo_tasks::function]
74-
async fn code(self: Vc<Self>) -> Result<Vc<Code>> {
79+
pub(crate) async fn chunk_group_bootstrap_params(self: Vc<Self>) -> Result<Vc<RcStr>> {
7580
let this = self.await?;
76-
let source_maps = *this
77-
.chunking_context
78-
.reference_chunk_source_maps(Vc::upcast(self))
79-
.await?;
80-
// Lifetime hack to pull out the var into this scope
81-
let chunk_path;
82-
let script_or_path = match *this.chunking_context.current_chunk_method().await? {
83-
CurrentChunkMethod::StringLiteral => {
84-
let output_root = this.chunking_context.output_root().await?;
85-
let chunk_path_vc = self.path();
86-
chunk_path = chunk_path_vc.await?;
87-
let chunk_server_path = if let Some(path) = output_root.get_path_to(&chunk_path) {
88-
path
89-
} else {
90-
turbobail!("chunk path {chunk_path} is not in output root {output_root}");
91-
};
92-
Either::Left(StringifyJs(chunk_server_path))
93-
}
94-
CurrentChunkMethod::DocumentCurrentScript => {
95-
Either::Right(CURRENT_CHUNK_METHOD_DOCUMENT_CURRENT_SCRIPT_EXPR)
96-
}
97-
};
9881

9982
let other_chunks_data = self.chunks_data().await?;
10083
let other_chunks_data = other_chunks_data.iter().try_join().await?;
@@ -134,28 +117,56 @@ impl EcmascriptBrowserEvaluateChunk {
134117
runtime_module_ids,
135118
};
136119

137-
let mut code = CodeBuilder::new(
138-
source_maps,
139-
*this.chunking_context.debug_ids_enabled().await?,
140-
);
120+
Ok(Vc::cell(format!("{}", StringifyJs(&params)).into()))
121+
}
122+
123+
#[turbo_tasks::function]
124+
async fn code(self: Vc<Self>) -> Result<Vc<Code>> {
125+
let this = self.await?;
126+
let source_maps = *this
127+
.chunking_context
128+
.reference_chunk_source_maps(Vc::upcast(self))
129+
.await?;
141130

142-
// Use the configured chunk loading global variable to store the chunk here.
143-
// This allows multiple runtimes to coexist on the same page when using different global
144-
// names.
131+
let params = self.chunk_group_bootstrap_params().await?;
145132
let chunk_loading_global = this.chunking_context.chunk_loading_global().await?;
146-
writedoc!(
147-
code,
148-
// `||=` would be better but we need to be es2020 compatible
149-
//`x || (x = default)` is better than `x = x || default` simply because we avoid _writing_ the property in the common case.
133+
// `||=` would be better but we need to be es2020 compatible.
134+
// `x || (x = default)` avoids _writing_ the property in the common case.
135+
let use_string_literal = matches!(
136+
*this.chunking_context.current_chunk_method().await?,
137+
CurrentChunkMethod::StringLiteral
138+
);
139+
// Lifetime hack to keep the path read alive for the borrow below.
140+
let chunk_path;
141+
let script_or_path = if use_string_literal {
142+
let output_root = this.chunking_context.output_root().await?;
143+
chunk_path = self.path().await?;
144+
let chunk_server_path = if let Some(path) = output_root.get_path_to(&chunk_path) {
145+
path
146+
} else {
147+
turbobail!("chunk path {chunk_path} is not in output root {output_root}");
148+
};
149+
Either::Left(StringifyJs(chunk_server_path))
150+
} else {
151+
Either::Right(CURRENT_CHUNK_METHOD_DOCUMENT_CURRENT_SCRIPT_EXPR)
152+
};
153+
let statement = formatdoc! {
150154
r#"
151155
(globalThis[{chunk_loading_global}] || (globalThis[{chunk_loading_global}] = [])).push([
152156
{script_or_path},
153157
{params}
154158
]);
155159
"#,
156160
chunk_loading_global = StringifyJs(&chunk_loading_global),
157-
params = StringifyJs(&params),
158-
)?;
161+
script_or_path = script_or_path,
162+
params = &**params,
163+
};
164+
165+
let mut code = CodeBuilder::new(
166+
source_maps,
167+
*this.chunking_context.debug_ids_enabled().await?,
168+
);
169+
write!(code, "{}", statement)?;
159170

160171
let mut code = code.build();
161172

0 commit comments

Comments
 (0)