From f0685406200555cbcc3c6f71f62820673a3d1bb9 Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Fri, 17 Jan 2025 03:07:50 +0100 Subject: [PATCH 1/5] fix: always ensure element before set to weakmap --- packages/next/src/client/app-dir/link.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/next/src/client/app-dir/link.tsx b/packages/next/src/client/app-dir/link.tsx index adf90964deb75..b538946af6029 100644 --- a/packages/next/src/client/app-dir/link.tsx +++ b/packages/next/src/client/app-dir/link.tsx @@ -193,7 +193,9 @@ function mountLinkInstance( // case there's a logical error somewhere else. unmountLinkInstance(element) } - links.set(element, instance) + if (element) { + links.set(element, instance) + } if (observer !== null) { observer.observe(element) } From def6c3300d05ed759ed42a0aea2fce13cdb0177f Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Fri, 17 Jan 2025 03:40:51 +0100 Subject: [PATCH 2/5] guard observe --- packages/next/src/client/app-dir/link.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/next/src/client/app-dir/link.tsx b/packages/next/src/client/app-dir/link.tsx index b538946af6029..21de88db62ab8 100644 --- a/packages/next/src/client/app-dir/link.tsx +++ b/packages/next/src/client/app-dir/link.tsx @@ -195,9 +195,9 @@ function mountLinkInstance( } if (element) { links.set(element, instance) - } - if (observer !== null) { - observer.observe(element) + if (observer !== null) { + observer.observe(element) + } } } From a5eb34ddce65ab81138aa8ba0c6c33dcfd22daff Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Fri, 17 Jan 2025 10:55:22 +0100 Subject: [PATCH 3/5] early return --- packages/next/src/client/app-dir/link.tsx | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/packages/next/src/client/app-dir/link.tsx b/packages/next/src/client/app-dir/link.tsx index 21de88db62ab8..6dc667a517f5c 100644 --- a/packages/next/src/client/app-dir/link.tsx +++ b/packages/next/src/client/app-dir/link.tsx @@ -156,6 +156,11 @@ function mountLinkInstance( router: AppRouterInstance, kind: PrefetchKind.AUTO | PrefetchKind.FULL ) { + // Element could be possible undefined which leads to failed on later + // WeakMap and IntersectionObserver operations. + if (!element) { + return + } let prefetchUrl: URL | null = null try { prefetchUrl = createPrefetchURL(href) @@ -193,11 +198,9 @@ function mountLinkInstance( // case there's a logical error somewhere else. unmountLinkInstance(element) } - if (element) { - links.set(element, instance) - if (observer !== null) { - observer.observe(element) - } + links.set(element, instance) + if (observer !== null) { + observer.observe(element) } } From 8331e3924cb4934149f3dd2cc03eded02eb44b70 Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Fri, 17 Jan 2025 12:56:16 +0100 Subject: [PATCH 4/5] move to ref check --- packages/next/src/client/app-dir/link.tsx | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/packages/next/src/client/app-dir/link.tsx b/packages/next/src/client/app-dir/link.tsx index 6dc667a517f5c..d999162774280 100644 --- a/packages/next/src/client/app-dir/link.tsx +++ b/packages/next/src/client/app-dir/link.tsx @@ -156,11 +156,6 @@ function mountLinkInstance( router: AppRouterInstance, kind: PrefetchKind.AUTO | PrefetchKind.FULL ) { - // Element could be possible undefined which leads to failed on later - // WeakMap and IntersectionObserver operations. - if (!element) { - return - } let prefetchUrl: URL | null = null try { prefetchUrl = createPrefetchURL(href) @@ -645,12 +640,18 @@ const Link = React.forwardRef( // currently mounted instances, e.g. so we can re-prefetch them after // a revalidation or refresh. const observeLinkVisibilityOnMount = React.useCallback( - (element: HTMLAnchorElement | SVGAElement) => { + (element: HTMLAnchorElement | SVGAElement | null) => { if (prefetchEnabled && router !== null) { - mountLinkInstance(element, href, router, appPrefetchKind) + // The useMergedRef could return null + if (element) { + mountLinkInstance(element, href, router, appPrefetchKind) + } } return () => { - unmountLinkInstance(element) + // The useMergedRef could return null + if (element) { + unmountLinkInstance(element) + } } }, [prefetchEnabled, href, router, appPrefetchKind] From 8a543b61b74e8fda2a60f64b627ed3e8bedaa659 Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Fri, 17 Jan 2025 15:12:00 +0100 Subject: [PATCH 5/5] update link --- packages/next/src/client/app-dir/link.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/next/src/client/app-dir/link.tsx b/packages/next/src/client/app-dir/link.tsx index d999162774280..cf7706995cb36 100644 --- a/packages/next/src/client/app-dir/link.tsx +++ b/packages/next/src/client/app-dir/link.tsx @@ -642,13 +642,12 @@ const Link = React.forwardRef( const observeLinkVisibilityOnMount = React.useCallback( (element: HTMLAnchorElement | SVGAElement | null) => { if (prefetchEnabled && router !== null) { - // The useMergedRef could return null + // FIXME: element still can be null here in some cases. Require further investigation. if (element) { mountLinkInstance(element, href, router, appPrefetchKind) } } return () => { - // The useMergedRef could return null if (element) { unmountLinkInstance(element) }