Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adopt script rejection pattern for link onerror. #42645

Merged
merged 3 commits into from Nov 9, 2022
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
29 changes: 15 additions & 14 deletions packages/next/client/route-loader.ts
Expand Up @@ -80,6 +80,16 @@ export interface RouteLoader {
prefetch(route: string): Promise<void>
}

const ASSET_LOAD_ERROR = Symbol('ASSET_LOAD_ERROR')
// TODO: unexport
export function markAssetError(err: Error): Error {
return Object.defineProperty(err, ASSET_LOAD_ERROR, {})
}

export function isAssetError(err?: Error): boolean | undefined {
return err && ASSET_LOAD_ERROR in err
}

function hasPrefetch(link?: HTMLLinkElement): boolean {
try {
link = document.createElement('link')
Expand All @@ -101,13 +111,13 @@ function prefetchViaDom(
as: string,
link?: HTMLLinkElement
): Promise<any> {
return new Promise<void>((res, rej) => {
return new Promise<void>((resolve, reject) => {
const selector = `
link[rel="prefetch"][href^="${href}"],
link[rel="preload"][href^="${href}"],
script[src^="${href}"]`
if (document.querySelector(selector)) {
return res()
return resolve()
}

link = document.createElement('link')
Expand All @@ -116,8 +126,9 @@ function prefetchViaDom(
if (as) link!.as = as
link!.rel = `prefetch`
link!.crossOrigin = process.env.__NEXT_CROSS_ORIGIN!
link!.onload = res as any
link!.onerror = rej
link!.onload = resolve as any
link!.onerror = () =>
reject(markAssetError(new Error(`Failed to prefetch: ${href}`)))

// `href` should always be last:
link!.href = href
Expand All @@ -126,16 +137,6 @@ function prefetchViaDom(
})
}

const ASSET_LOAD_ERROR = Symbol('ASSET_LOAD_ERROR')
// TODO: unexport
export function markAssetError(err: Error): Error {
return Object.defineProperty(err, ASSET_LOAD_ERROR, {})
}

export function isAssetError(err?: Error): boolean | undefined {
return err && ASSET_LOAD_ERROR in err
}

function appendScript(
src: TrustedScriptURL | string,
script?: HTMLScriptElement
Expand Down