Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,7 @@ declare var CHUNK_SUFFIX_PATH: string
// Support runtime public path from window.publicPath
function getRuntimeChunkBasePath(): string {
if (CHUNK_BASE_PATH === "__RUNTIME_PUBLIC_PATH__") {
if (typeof globalThis !== 'undefined' && typeof (globalThis as any).publicPath === "string") {
return (globalThis as any).publicPath;
}
console.warn(
"publicPath is set to 'runtime' but window.publicPath is not defined or not a string, falling back to '/'"
);
return "/";
return contextPrototype.p();
}
return CHUNK_BASE_PATH;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ type AsyncModule = (

type ResolveAbsolutePath = (modulePath?: string) => string
type GetWorkerBlobURL = (chunks: ChunkPath[]) => string
type GetPublicPath = () => string

type ExternalRequire = (
id: DependencySpecifier,
Expand Down Expand Up @@ -138,4 +139,5 @@ interface TurbopackBaseContext<M> {
y: ExternalImport
z: CommonJsRequire
g: typeof globalThis
p: GetPublicPath
}
Original file line number Diff line number Diff line change
Expand Up @@ -712,6 +712,19 @@ contextPrototype.z = requireStub
// Make `globalThis` available to the module in a way that cannot be shadowed by a local variable.
contextPrototype.g = globalThis

/**
* Gets the public path for runtime assets.
* Checks globalThis.publicPath and falls back to empty string.
*/
function getPublicPath(): string {
if (typeof globalThis !== 'undefined' && typeof (globalThis as any).publicPath === "string") {
const publicPath = (globalThis as any).publicPath as string;
return publicPath.endsWith('/') ? publicPath : `${publicPath}/`;
}
return '';
}
contextPrototype.p = getPublicPath

type ContextConstructor<M> = {
new (module: Module, exports: Exports): TurbopackBaseContext<M>
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,11 @@ pub const TURBOPACK_REQUIRE_REAL: &TurbopackRuntimeFunctionShortcut = make_short
pub const TURBOPACK_WASM: &TurbopackRuntimeFunctionShortcut = make_shortcut!("w");
pub const TURBOPACK_WASM_MODULE: &TurbopackRuntimeFunctionShortcut = make_shortcut!("u");
pub const TURBOPACK_GLOBAL: &TurbopackRuntimeFunctionShortcut = make_shortcut!("g");
pub const TURBOPACK_PUBLIC_PATH: &TurbopackRuntimeFunctionShortcut = make_shortcut!("p");

/// Adding an entry to this list will automatically ensure that `__turbopack_XXX__` can be called
/// from user code (by inserting a replacement into free_var_references)
pub const TURBOPACK_RUNTIME_FUNCTION_SHORTCUTS: [(&str, &TurbopackRuntimeFunctionShortcut); 22] = [
pub const TURBOPACK_RUNTIME_FUNCTION_SHORTCUTS: [(&str, &TurbopackRuntimeFunctionShortcut); 23] = [
("__turbopack_require__", TURBOPACK_REQUIRE),
("__turbopack_module_context__", TURBOPACK_MODULE_CONTEXT),
("__turbopack_import__", TURBOPACK_IMPORT),
Expand Down Expand Up @@ -127,4 +128,5 @@ pub const TURBOPACK_RUNTIME_FUNCTION_SHORTCUTS: [(&str, &TurbopackRuntimeFunctio
),
("__turbopack_wasm__", TURBOPACK_WASM),
("__turbopack_wasm_module__", TURBOPACK_WASM_MODULE),
("__turbopack_public_path__", TURBOPACK_PUBLIC_PATH),
];
31 changes: 21 additions & 10 deletions turbopack/crates/turbopack-static/src/ecma.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use turbopack_ecmascript::{
EcmascriptChunkItem, EcmascriptChunkItemContent, EcmascriptChunkPlaceable,
EcmascriptChunkType, EcmascriptExports,
},
runtime_functions::TURBOPACK_EXPORT_VALUE,
runtime_functions::{TURBOPACK_EXPORT_VALUE, TURBOPACK_PUBLIC_PATH},
utils::StringifyJs,
};

Expand Down Expand Up @@ -131,17 +131,28 @@ impl ChunkItem for StaticUrlJsChunkItem {
impl EcmascriptChunkItem for StaticUrlJsChunkItem {
#[turbo_tasks::function]
async fn content(&self) -> Result<Vc<EcmascriptChunkItemContent>> {
Ok(EcmascriptChunkItemContent {
inner_code: format!(
let asset_url = self
.chunking_context
.asset_url(self.static_asset.path().owned().await?)
.await?;

let code = if asset_url.starts_with("__RUNTIME_PUBLIC_PATH__") {
// For runtime publicPath, use the getPublicPath() runtime function
let asset_path = &asset_url["__RUNTIME_PUBLIC_PATH__".len()..];
format!(
"{TURBOPACK_EXPORT_VALUE}({TURBOPACK_PUBLIC_PATH}() + {path});",
path = StringifyJs(asset_path)
)
} else {
// For static publicPath, use the full URL as a string literal
format!(
"{TURBOPACK_EXPORT_VALUE}({path});",
path = StringifyJs(
&self
.chunking_context
.asset_url(self.static_asset.path().owned().await?)
.await?
)
path = StringifyJs(&*asset_url)
)
.into(),
};

Ok(EcmascriptChunkItemContent {
inner_code: code.into(),
..Default::default()
}
.into())
Expand Down
Loading