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 @@ -36,11 +36,14 @@ declare var ASSET_SUFFIX: string
declare var CROSS_ORIGIN: 'anonymous' | 'use-credentials' | null
declare var WORKER_FORWARDED_GLOBALS: string[]

// Support runtime public path from window.publicPath
// Support runtime public path modes.
function getRuntimeChunkBasePath(basePath: string = CHUNK_BASE_PATH): string {
if (CHUNK_BASE_PATH === '__RUNTIME_PUBLIC_PATH__') {
if (basePath === '__RUNTIME_PUBLIC_PATH__') {
return contextPrototype.p()
}
if (basePath === '__AUTO_PUBLIC_PATH__') {
return contextPrototype.p('auto')
}
return basePath
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ type GetWorkerURL = (
shared: boolean
) => URL

type GetPublicPath = () => string
type GetPublicPath = (mode?: 'auto') => string

type ExternalRequire = (
id: DependencySpecifier,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -834,11 +834,53 @@ contextPrototype.z = requireStub
// Make `globalThis` available to the module in a way that cannot be shadowed by a local variable.
contextPrototype.g = globalThis

let cachedAutomaticPublicPath: string | undefined

function getAutomaticPublicPath(): string {
if (cachedAutomaticPublicPath !== undefined) {
return cachedAutomaticPublicPath
}

let scriptUrl: string | undefined
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

In ES modules, document.currentScript is always null. To support environments where the runtime might be loaded as an ES module, consider checking import.meta.url if available. This is the standard way to determine the current script's URL in ESM and would improve the reliability of the automatic public path in modern environments.

if (typeof document === 'object') {
const currentScript = document.currentScript as HTMLScriptElement | null
scriptUrl = currentScript?.src

if (!scriptUrl) {
const scripts = document.getElementsByTagName('script')
const script = scripts[scripts.length - 1]
scriptUrl = script?.src
}
Comment on lines +849 to +853
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The current fallback logic only checks the last script tag in the document. If the last script is an inline script (which lacks a src attribute), it will fail to resolve the public path even if the runtime script is present earlier in the document. Iterating backwards through the scripts to find the first one with a src attribute would be more robust and consistent with how other bundlers like Webpack implement auto public path detection.

    if (!scriptUrl) {
      const scripts = document.getElementsByTagName('script')
      for (let i = scripts.length - 1; i >= 0; i--) {
        const script = scripts[i] as HTMLScriptElement | undefined
        if (script?.src) {
          scriptUrl = script.src
          break
        }
      }
    }

}

if (
!scriptUrl &&
typeof (globalThis as any).importScripts === 'function' &&
(globalThis as any).location
) {
scriptUrl = String((globalThis as any).location)
}

cachedAutomaticPublicPath = scriptUrl
? scriptUrl
.replace(/^blob:/, '')
.replace(/#.*$/, '')
.replace(/\?.*$/, '')
.replace(/\/[^/]*$/, '/')
: ''

return cachedAutomaticPublicPath
}

/**
* Gets the public path for runtime assets.
* Checks globalThis.publicPath and falls back to empty string.
*/
function getPublicPath(): string {
function getPublicPath(mode?: 'auto'): string {
if (mode === 'auto') {
return getAutomaticPublicPath()
}

if (
typeof globalThis !== 'undefined' &&
typeof (globalThis as any).publicPath === 'string'
Expand Down
11 changes: 11 additions & 0 deletions turbopack/crates/turbopack-static/src/ecma.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,17 @@ impl EcmascriptChunkPlaceable for StaticUrlJsModule {
}
.cell());
}
if let Some(asset_path) = url.strip_prefix("__AUTO_PUBLIC_PATH__") {
let code = format!(
"{TURBOPACK_EXPORT_VALUE}({TURBOPACK_PUBLIC_PATH}(\"auto\") + {path});",
path = StringifyJs(asset_path)
);
return Ok(EcmascriptChunkItemContent {
inner_code: code.into(),
..Default::default()
}
.cell());
}

let url_behavior = chunking_context.url_behavior(this.tag.clone()).await?;

Expand Down
Loading