Spaces:
Sleeping
Sleeping
| // tslint:disable:no-console | |
| ; | |
| Object.defineProperty(exports, "__esModule", { | |
| value: true | |
| }); | |
| 0 && (module.exports = { | |
| createKey: null, | |
| default: null, | |
| matchesMiddleware: null | |
| }); | |
| function _export(target, all) { | |
| for(var name in all)Object.defineProperty(target, name, { | |
| enumerable: true, | |
| get: all[name] | |
| }); | |
| } | |
| _export(exports, { | |
| createKey: function() { | |
| return createKey; | |
| }, | |
| default: function() { | |
| return Router; | |
| }, | |
| matchesMiddleware: function() { | |
| return matchesMiddleware; | |
| } | |
| }); | |
| const _interop_require_default = require("@swc/helpers/_/_interop_require_default"); | |
| const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard"); | |
| const _removetrailingslash = require("./utils/remove-trailing-slash"); | |
| const _routeloader = require("../../../client/route-loader"); | |
| const _script = require("../../../client/script"); | |
| const _iserror = /*#__PURE__*/ _interop_require_wildcard._(require("../../../lib/is-error")); | |
| const _denormalizepagepath = require("../page-path/denormalize-page-path"); | |
| const _normalizelocalepath = require("../i18n/normalize-locale-path"); | |
| const _mitt = /*#__PURE__*/ _interop_require_default._(require("../mitt")); | |
| const _utils = require("../utils"); | |
| const _isdynamic = require("./utils/is-dynamic"); | |
| const _parserelativeurl = require("./utils/parse-relative-url"); | |
| const _routematcher = require("./utils/route-matcher"); | |
| const _routeregex = require("./utils/route-regex"); | |
| const _formaturl = require("./utils/format-url"); | |
| const _detectdomainlocale = require("../../../client/detect-domain-locale"); | |
| const _parsepath = require("./utils/parse-path"); | |
| const _addlocale = require("../../../client/add-locale"); | |
| const _removelocale = require("../../../client/remove-locale"); | |
| const _removebasepath = require("../../../client/remove-base-path"); | |
| const _addbasepath = require("../../../client/add-base-path"); | |
| const _hasbasepath = require("../../../client/has-base-path"); | |
| const _resolvehref = require("../../../client/resolve-href"); | |
| const _isapiroute = require("../../../lib/is-api-route"); | |
| const _getnextpathnameinfo = require("./utils/get-next-pathname-info"); | |
| const _formatnextpathnameinfo = require("./utils/format-next-pathname-info"); | |
| const _comparestates = require("./utils/compare-states"); | |
| const _islocalurl = require("./utils/is-local-url"); | |
| const _isbot = require("./utils/is-bot"); | |
| const _omit = require("./utils/omit"); | |
| const _interpolateas = require("./utils/interpolate-as"); | |
| const _disablesmoothscroll = require("./utils/disable-smooth-scroll"); | |
| const _constants = require("../../../lib/constants"); | |
| let resolveRewrites; | |
| if (process.env.__NEXT_HAS_REWRITES) { | |
| resolveRewrites = require('./utils/resolve-rewrites').default; | |
| } | |
| function buildCancellationError() { | |
| return Object.assign(Object.defineProperty(new Error('Route Cancelled'), "__NEXT_ERROR_CODE", { | |
| value: "E315", | |
| enumerable: false, | |
| configurable: true | |
| }), { | |
| cancelled: true | |
| }); | |
| } | |
| async function matchesMiddleware(options) { | |
| const matchers = await Promise.resolve(options.router.pageLoader.getMiddleware()); | |
| if (!matchers) return false; | |
| const { pathname: asPathname } = (0, _parsepath.parsePath)(options.asPath); | |
| // remove basePath first since path prefix has to be in the order of `/${basePath}/${locale}` | |
| const cleanedAs = (0, _hasbasepath.hasBasePath)(asPathname) ? (0, _removebasepath.removeBasePath)(asPathname) : asPathname; | |
| const asWithBasePathAndLocale = (0, _addbasepath.addBasePath)((0, _addlocale.addLocale)(cleanedAs, options.locale)); | |
| // Check only path match on client. Matching "has" should be done on server | |
| // where we can access more info such as headers, HttpOnly cookie, etc. | |
| return matchers.some((m)=>new RegExp(m.regexp).test(asWithBasePathAndLocale)); | |
| } | |
| function stripOrigin(url) { | |
| const origin = (0, _utils.getLocationOrigin)(); | |
| return url.startsWith(origin) ? url.substring(origin.length) : url; | |
| } | |
| function prepareUrlAs(router, url, as) { | |
| // If url and as provided as an object representation, | |
| // we'll format them into the string version here. | |
| let [resolvedHref, resolvedAs] = (0, _resolvehref.resolveHref)(router, url, true); | |
| const origin = (0, _utils.getLocationOrigin)(); | |
| const hrefWasAbsolute = resolvedHref.startsWith(origin); | |
| const asWasAbsolute = resolvedAs && resolvedAs.startsWith(origin); | |
| resolvedHref = stripOrigin(resolvedHref); | |
| resolvedAs = resolvedAs ? stripOrigin(resolvedAs) : resolvedAs; | |
| const preparedUrl = hrefWasAbsolute ? resolvedHref : (0, _addbasepath.addBasePath)(resolvedHref); | |
| const preparedAs = as ? stripOrigin((0, _resolvehref.resolveHref)(router, as)) : resolvedAs || resolvedHref; | |
| return { | |
| url: preparedUrl, | |
| as: asWasAbsolute ? preparedAs : (0, _addbasepath.addBasePath)(preparedAs) | |
| }; | |
| } | |
| function resolveDynamicRoute(pathname, pages) { | |
| const cleanPathname = (0, _removetrailingslash.removeTrailingSlash)((0, _denormalizepagepath.denormalizePagePath)(pathname)); | |
| if (cleanPathname === '/404' || cleanPathname === '/_error') { | |
| return pathname; | |
| } | |
| // handle resolving href for dynamic routes | |
| if (!pages.includes(cleanPathname)) { | |
| // eslint-disable-next-line array-callback-return | |
| pages.some((page)=>{ | |
| if ((0, _isdynamic.isDynamicRoute)(page) && (0, _routeregex.getRouteRegex)(page).re.test(cleanPathname)) { | |
| pathname = page; | |
| return true; | |
| } | |
| }); | |
| } | |
| return (0, _removetrailingslash.removeTrailingSlash)(pathname); | |
| } | |
| function getMiddlewareData(source, response, options) { | |
| const nextConfig = { | |
| basePath: options.router.basePath, | |
| i18n: { | |
| locales: options.router.locales | |
| }, | |
| trailingSlash: Boolean(process.env.__NEXT_TRAILING_SLASH) | |
| }; | |
| const rewriteHeader = response.headers.get('x-nextjs-rewrite'); | |
| let rewriteTarget = rewriteHeader || response.headers.get('x-nextjs-matched-path'); | |
| const matchedPath = response.headers.get(_constants.MATCHED_PATH_HEADER); | |
| if (matchedPath && !rewriteTarget && !matchedPath.includes('__next_data_catchall') && !matchedPath.includes('/_error') && !matchedPath.includes('/404')) { | |
| // leverage x-matched-path to detect next.config.js rewrites | |
| rewriteTarget = matchedPath; | |
| } | |
| if (rewriteTarget) { | |
| if (rewriteTarget.startsWith('/') || process.env.__NEXT_EXTERNAL_MIDDLEWARE_REWRITE_RESOLVE) { | |
| const parsedRewriteTarget = (0, _parserelativeurl.parseRelativeUrl)(rewriteTarget); | |
| const pathnameInfo = (0, _getnextpathnameinfo.getNextPathnameInfo)(parsedRewriteTarget.pathname, { | |
| nextConfig, | |
| parseData: true | |
| }); | |
| let fsPathname = (0, _removetrailingslash.removeTrailingSlash)(pathnameInfo.pathname); | |
| return Promise.all([ | |
| options.router.pageLoader.getPageList(), | |
| (0, _routeloader.getClientBuildManifest)() | |
| ]).then((param)=>{ | |
| let [pages, { __rewrites: rewrites }] = param; | |
| let as = (0, _addlocale.addLocale)(pathnameInfo.pathname, pathnameInfo.locale); | |
| if ((0, _isdynamic.isDynamicRoute)(as) || !rewriteHeader && pages.includes((0, _normalizelocalepath.normalizeLocalePath)((0, _removebasepath.removeBasePath)(as), options.router.locales).pathname)) { | |
| const parsedSource = (0, _getnextpathnameinfo.getNextPathnameInfo)((0, _parserelativeurl.parseRelativeUrl)(source).pathname, { | |
| nextConfig: process.env.__NEXT_HAS_REWRITES ? undefined : nextConfig, | |
| parseData: true | |
| }); | |
| as = (0, _addbasepath.addBasePath)(parsedSource.pathname); | |
| parsedRewriteTarget.pathname = as; | |
| } | |
| if (process.env.__NEXT_HAS_REWRITES) { | |
| const result = resolveRewrites(as, pages, rewrites, parsedRewriteTarget.query, (path)=>resolveDynamicRoute(path, pages), options.router.locales); | |
| if (result.matchedPage) { | |
| parsedRewriteTarget.pathname = result.parsedAs.pathname; | |
| as = parsedRewriteTarget.pathname; | |
| Object.assign(parsedRewriteTarget.query, result.parsedAs.query); | |
| } | |
| } else if (!pages.includes(fsPathname)) { | |
| const resolvedPathname = resolveDynamicRoute(fsPathname, pages); | |
| if (resolvedPathname !== fsPathname) { | |
| fsPathname = resolvedPathname; | |
| } | |
| } | |
| const resolvedHref = !pages.includes(fsPathname) ? resolveDynamicRoute((0, _normalizelocalepath.normalizeLocalePath)((0, _removebasepath.removeBasePath)(parsedRewriteTarget.pathname), options.router.locales).pathname, pages) : fsPathname; | |
| if ((0, _isdynamic.isDynamicRoute)(resolvedHref)) { | |
| const matches = (0, _routematcher.getRouteMatcher)((0, _routeregex.getRouteRegex)(resolvedHref))(as); | |
| Object.assign(parsedRewriteTarget.query, matches || {}); | |
| } | |
| return { | |
| type: 'rewrite', | |
| parsedAs: parsedRewriteTarget, | |
| resolvedHref | |
| }; | |
| }); | |
| } | |
| const src = (0, _parsepath.parsePath)(source); | |
| const pathname = (0, _formatnextpathnameinfo.formatNextPathnameInfo)({ | |
| ...(0, _getnextpathnameinfo.getNextPathnameInfo)(src.pathname, { | |
| nextConfig, | |
| parseData: true | |
| }), | |
| defaultLocale: options.router.defaultLocale, | |
| buildId: '' | |
| }); | |
| return Promise.resolve({ | |
| type: 'redirect-external', | |
| destination: "" + pathname + src.query + src.hash | |
| }); | |
| } | |
| const redirectTarget = response.headers.get('x-nextjs-redirect'); | |
| if (redirectTarget) { | |
| if (redirectTarget.startsWith('/')) { | |
| const src = (0, _parsepath.parsePath)(redirectTarget); | |
| const pathname = (0, _formatnextpathnameinfo.formatNextPathnameInfo)({ | |
| ...(0, _getnextpathnameinfo.getNextPathnameInfo)(src.pathname, { | |
| nextConfig, | |
| parseData: true | |
| }), | |
| defaultLocale: options.router.defaultLocale, | |
| buildId: '' | |
| }); | |
| return Promise.resolve({ | |
| type: 'redirect-internal', | |
| newAs: "" + pathname + src.query + src.hash, | |
| newUrl: "" + pathname + src.query + src.hash | |
| }); | |
| } | |
| return Promise.resolve({ | |
| type: 'redirect-external', | |
| destination: redirectTarget | |
| }); | |
| } | |
| return Promise.resolve({ | |
| type: 'next' | |
| }); | |
| } | |
| async function withMiddlewareEffects(options) { | |
| const matches = await matchesMiddleware(options); | |
| if (!matches || !options.fetchData) { | |
| return null; | |
| } | |
| const data = await options.fetchData(); | |
| const effect = await getMiddlewareData(data.dataHref, data.response, options); | |
| return { | |
| dataHref: data.dataHref, | |
| json: data.json, | |
| response: data.response, | |
| text: data.text, | |
| cacheKey: data.cacheKey, | |
| effect | |
| }; | |
| } | |
| const manualScrollRestoration = process.env.__NEXT_SCROLL_RESTORATION && typeof window !== 'undefined' && 'scrollRestoration' in window.history && !!function() { | |
| try { | |
| let v = '__next'; | |
| // eslint-disable-next-line no-sequences | |
| return sessionStorage.setItem(v, v), sessionStorage.removeItem(v), true; | |
| } catch (n) {} | |
| }(); | |
| const SSG_DATA_NOT_FOUND = Symbol('SSG_DATA_NOT_FOUND'); | |
| function fetchRetry(url, attempts, options) { | |
| return fetch(url, { | |
| // Cookies are required to be present for Next.js' SSG "Preview Mode". | |
| // Cookies may also be required for `getServerSideProps`. | |
| // | |
| // > `fetch` won’t send cookies, unless you set the credentials init | |
| // > option. | |
| // https://developer.mozilla.org/docs/Web/API/Fetch_API/Using_Fetch | |
| // | |
| // > For maximum browser compatibility when it comes to sending & | |
| // > receiving cookies, always supply the `credentials: 'same-origin'` | |
| // > option instead of relying on the default. | |
| // https://github.com/github/fetch#caveats | |
| credentials: 'same-origin', | |
| method: options.method || 'GET', | |
| headers: Object.assign({}, options.headers, { | |
| 'x-nextjs-data': '1' | |
| }) | |
| }).then((response)=>{ | |
| return !response.ok && attempts > 1 && response.status >= 500 ? fetchRetry(url, attempts - 1, options) : response; | |
| }); | |
| } | |
| function tryToParseAsJSON(text) { | |
| try { | |
| return JSON.parse(text); | |
| } catch (error) { | |
| return null; | |
| } | |
| } | |
| function fetchNextData(param) { | |
| let { dataHref, inflightCache, isPrefetch, hasMiddleware, isServerRender, parseJSON, persistCache, isBackground, unstable_skipClientCache } = param; | |
| const { href: cacheKey } = new URL(dataHref, window.location.href); | |
| const getData = (params)=>{ | |
| var _params_method; | |
| return fetchRetry(dataHref, isServerRender ? 3 : 1, { | |
| headers: Object.assign({}, isPrefetch ? { | |
| purpose: 'prefetch' | |
| } : {}, isPrefetch && hasMiddleware ? { | |
| 'x-middleware-prefetch': '1' | |
| } : {}, process.env.NEXT_DEPLOYMENT_ID ? { | |
| 'x-deployment-id': process.env.NEXT_DEPLOYMENT_ID | |
| } : {}), | |
| method: (_params_method = params == null ? void 0 : params.method) != null ? _params_method : 'GET' | |
| }).then((response)=>{ | |
| if (response.ok && (params == null ? void 0 : params.method) === 'HEAD') { | |
| return { | |
| dataHref, | |
| response, | |
| text: '', | |
| json: {}, | |
| cacheKey | |
| }; | |
| } | |
| return response.text().then((text)=>{ | |
| if (!response.ok) { | |
| /** | |
| * When the data response is a redirect because of a middleware | |
| * we do not consider it an error. The headers must bring the | |
| * mapped location. | |
| * TODO: Change the status code in the handler. | |
| */ if (hasMiddleware && [ | |
| 301, | |
| 302, | |
| 307, | |
| 308 | |
| ].includes(response.status)) { | |
| return { | |
| dataHref, | |
| response, | |
| text, | |
| json: {}, | |
| cacheKey | |
| }; | |
| } | |
| if (response.status === 404) { | |
| var _tryToParseAsJSON; | |
| if ((_tryToParseAsJSON = tryToParseAsJSON(text)) == null ? void 0 : _tryToParseAsJSON.notFound) { | |
| return { | |
| dataHref, | |
| json: { | |
| notFound: SSG_DATA_NOT_FOUND | |
| }, | |
| response, | |
| text, | |
| cacheKey | |
| }; | |
| } | |
| } | |
| const error = Object.defineProperty(new Error("Failed to load static props"), "__NEXT_ERROR_CODE", { | |
| value: "E124", | |
| enumerable: false, | |
| configurable: true | |
| }); | |
| /** | |
| * We should only trigger a server-side transition if this was | |
| * caused on a client-side transition. Otherwise, we'd get into | |
| * an infinite loop. | |
| */ if (!isServerRender) { | |
| (0, _routeloader.markAssetError)(error); | |
| } | |
| throw error; | |
| } | |
| return { | |
| dataHref, | |
| json: parseJSON ? tryToParseAsJSON(text) : null, | |
| response, | |
| text, | |
| cacheKey | |
| }; | |
| }); | |
| }).then((data)=>{ | |
| if (!persistCache || process.env.NODE_ENV !== 'production' || data.response.headers.get('x-middleware-cache') === 'no-cache') { | |
| delete inflightCache[cacheKey]; | |
| } | |
| return data; | |
| }).catch((err)=>{ | |
| if (!unstable_skipClientCache) { | |
| delete inflightCache[cacheKey]; | |
| } | |
| if (// chrome | |
| err.message === 'Failed to fetch' || // firefox | |
| err.message === 'NetworkError when attempting to fetch resource.' || // safari | |
| err.message === 'Load failed') { | |
| (0, _routeloader.markAssetError)(err); | |
| } | |
| throw err; | |
| }); | |
| }; | |
| // when skipping client cache we wait to update | |
| // inflight cache until successful data response | |
| // this allows racing click event with fetching newer data | |
| // without blocking navigation when stale data is available | |
| if (unstable_skipClientCache && persistCache) { | |
| return getData({}).then((data)=>{ | |
| if (data.response.headers.get('x-middleware-cache') !== 'no-cache') { | |
| // only update cache if not marked as no-cache | |
| inflightCache[cacheKey] = Promise.resolve(data); | |
| } | |
| return data; | |
| }); | |
| } | |
| if (inflightCache[cacheKey] !== undefined) { | |
| return inflightCache[cacheKey]; | |
| } | |
| return inflightCache[cacheKey] = getData(isBackground ? { | |
| method: 'HEAD' | |
| } : {}); | |
| } | |
| function createKey() { | |
| return Math.random().toString(36).slice(2, 10); | |
| } | |
| function handleHardNavigation(param) { | |
| let { url, router } = param; | |
| // ensure we don't trigger a hard navigation to the same | |
| // URL as this can end up with an infinite refresh | |
| if (url === (0, _addbasepath.addBasePath)((0, _addlocale.addLocale)(router.asPath, router.locale))) { | |
| throw Object.defineProperty(new Error("Invariant: attempted to hard navigate to the same URL " + url + " " + location.href), "__NEXT_ERROR_CODE", { | |
| value: "E282", | |
| enumerable: false, | |
| configurable: true | |
| }); | |
| } | |
| window.location.href = url; | |
| } | |
| const getCancelledHandler = (param)=>{ | |
| let { route, router } = param; | |
| let cancelled = false; | |
| const cancel = router.clc = ()=>{ | |
| cancelled = true; | |
| }; | |
| const handleCancelled = ()=>{ | |
| if (cancelled) { | |
| const error = Object.defineProperty(new Error('Abort fetching component for route: "' + route + '"'), "__NEXT_ERROR_CODE", { | |
| value: "E483", | |
| enumerable: false, | |
| configurable: true | |
| }); | |
| error.cancelled = true; | |
| throw error; | |
| } | |
| if (cancel === router.clc) { | |
| router.clc = null; | |
| } | |
| }; | |
| return handleCancelled; | |
| }; | |
| class Router { | |
| reload() { | |
| window.location.reload(); | |
| } | |
| /** | |
| * Go back in history | |
| */ back() { | |
| window.history.back(); | |
| } | |
| /** | |
| * Go forward in history | |
| */ forward() { | |
| window.history.forward(); | |
| } | |
| /** | |
| * Performs a `pushState` with arguments | |
| * @param url of the route | |
| * @param as masks `url` for the browser | |
| * @param options object you can define `shallow` and other options | |
| */ push(url, as, options) { | |
| if (options === void 0) options = {}; | |
| if (process.env.__NEXT_SCROLL_RESTORATION) { | |
| // TODO: remove in the future when we update history before route change | |
| // is complete, as the popstate event should handle this capture. | |
| if (manualScrollRestoration) { | |
| try { | |
| // Snapshot scroll position right before navigating to a new page: | |
| sessionStorage.setItem('__next_scroll_' + this._key, JSON.stringify({ | |
| x: self.pageXOffset, | |
| y: self.pageYOffset | |
| })); | |
| } catch (e) {} | |
| } | |
| } | |
| ; | |
| ({ url, as } = prepareUrlAs(this, url, as)); | |
| return this.change('pushState', url, as, options); | |
| } | |
| /** | |
| * Performs a `replaceState` with arguments | |
| * @param url of the route | |
| * @param as masks `url` for the browser | |
| * @param options object you can define `shallow` and other options | |
| */ replace(url, as, options) { | |
| if (options === void 0) options = {}; | |
| ; | |
| ({ url, as } = prepareUrlAs(this, url, as)); | |
| return this.change('replaceState', url, as, options); | |
| } | |
| async _bfl(as, resolvedAs, locale, skipNavigate) { | |
| if (process.env.__NEXT_CLIENT_ROUTER_FILTER_ENABLED) { | |
| if (!this._bfl_s && !this._bfl_d) { | |
| const { BloomFilter } = require('../../lib/bloom-filter'); | |
| let staticFilterData; | |
| let dynamicFilterData; | |
| try { | |
| ; | |
| ({ __routerFilterStatic: staticFilterData, __routerFilterDynamic: dynamicFilterData } = await (0, _routeloader.getClientBuildManifest)()); | |
| } catch (err) { | |
| // failed to load build manifest hard navigate | |
| // to be safe | |
| console.error(err); | |
| if (skipNavigate) { | |
| return true; | |
| } | |
| handleHardNavigation({ | |
| url: (0, _addbasepath.addBasePath)((0, _addlocale.addLocale)(as, locale || this.locale, this.defaultLocale)), | |
| router: this | |
| }); | |
| return new Promise(()=>{}); | |
| } | |
| const routerFilterSValue = process.env.__NEXT_CLIENT_ROUTER_S_FILTER; | |
| if (!staticFilterData && routerFilterSValue) { | |
| staticFilterData = routerFilterSValue ? routerFilterSValue : undefined; | |
| } | |
| const routerFilterDValue = process.env.__NEXT_CLIENT_ROUTER_D_FILTER; | |
| if (!dynamicFilterData && routerFilterDValue) { | |
| dynamicFilterData = routerFilterDValue ? routerFilterDValue : undefined; | |
| } | |
| if (staticFilterData == null ? void 0 : staticFilterData.numHashes) { | |
| this._bfl_s = new BloomFilter(staticFilterData.numItems, staticFilterData.errorRate); | |
| this._bfl_s.import(staticFilterData); | |
| } | |
| if (dynamicFilterData == null ? void 0 : dynamicFilterData.numHashes) { | |
| this._bfl_d = new BloomFilter(dynamicFilterData.numItems, dynamicFilterData.errorRate); | |
| this._bfl_d.import(dynamicFilterData); | |
| } | |
| } | |
| let matchesBflStatic = false; | |
| let matchesBflDynamic = false; | |
| const pathsToCheck = [ | |
| { | |
| as | |
| }, | |
| { | |
| as: resolvedAs | |
| } | |
| ]; | |
| for (const { as: curAs, allowMatchCurrent } of pathsToCheck){ | |
| if (curAs) { | |
| const asNoSlash = (0, _removetrailingslash.removeTrailingSlash)(new URL(curAs, 'http://n').pathname); | |
| const asNoSlashLocale = (0, _addbasepath.addBasePath)((0, _addlocale.addLocale)(asNoSlash, locale || this.locale)); | |
| if (allowMatchCurrent || asNoSlash !== (0, _removetrailingslash.removeTrailingSlash)(new URL(this.asPath, 'http://n').pathname)) { | |
| var _this__bfl_s, _this__bfl_s1; | |
| matchesBflStatic = matchesBflStatic || !!((_this__bfl_s = this._bfl_s) == null ? void 0 : _this__bfl_s.contains(asNoSlash)) || !!((_this__bfl_s1 = this._bfl_s) == null ? void 0 : _this__bfl_s1.contains(asNoSlashLocale)); | |
| for (const normalizedAS of [ | |
| asNoSlash, | |
| asNoSlashLocale | |
| ]){ | |
| // if any sub-path of as matches a dynamic filter path | |
| // it should be hard navigated | |
| const curAsParts = normalizedAS.split('/'); | |
| for(let i = 0; !matchesBflDynamic && i < curAsParts.length + 1; i++){ | |
| var _this__bfl_d; | |
| const currentPart = curAsParts.slice(0, i).join('/'); | |
| if (currentPart && ((_this__bfl_d = this._bfl_d) == null ? void 0 : _this__bfl_d.contains(currentPart))) { | |
| matchesBflDynamic = true; | |
| break; | |
| } | |
| } | |
| } | |
| // if the client router filter is matched then we trigger | |
| // a hard navigation | |
| if (matchesBflStatic || matchesBflDynamic) { | |
| if (skipNavigate) { | |
| return true; | |
| } | |
| handleHardNavigation({ | |
| url: (0, _addbasepath.addBasePath)((0, _addlocale.addLocale)(as, locale || this.locale, this.defaultLocale)), | |
| router: this | |
| }); | |
| return new Promise(()=>{}); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| return false; | |
| } | |
| async change(method, url, as, options, forcedScroll) { | |
| var _this_components_pathname; | |
| if (!(0, _islocalurl.isLocalURL)(url)) { | |
| handleHardNavigation({ | |
| url, | |
| router: this | |
| }); | |
| return false; | |
| } | |
| // WARNING: `_h` is an internal option for handing Next.js client-side | |
| // hydration. Your app should _never_ use this property. It may change at | |
| // any time without notice. | |
| const isQueryUpdating = options._h === 1; | |
| if (!isQueryUpdating && !options.shallow) { | |
| await this._bfl(as, undefined, options.locale); | |
| } | |
| let shouldResolveHref = isQueryUpdating || options._shouldResolveHref || (0, _parsepath.parsePath)(url).pathname === (0, _parsepath.parsePath)(as).pathname; | |
| const nextState = { | |
| ...this.state | |
| }; | |
| // for static pages with query params in the URL we delay | |
| // marking the router ready until after the query is updated | |
| // or a navigation has occurred | |
| const readyStateChange = this.isReady !== true; | |
| this.isReady = true; | |
| const isSsr = this.isSsr; | |
| if (!isQueryUpdating) { | |
| this.isSsr = false; | |
| } | |
| // if a route transition is already in progress before | |
| // the query updating is triggered ignore query updating | |
| if (isQueryUpdating && this.clc) { | |
| return false; | |
| } | |
| const prevLocale = nextState.locale; | |
| if (process.env.__NEXT_I18N_SUPPORT) { | |
| nextState.locale = options.locale === false ? this.defaultLocale : options.locale || nextState.locale; | |
| if (typeof options.locale === 'undefined') { | |
| options.locale = nextState.locale; | |
| } | |
| const parsedAs = (0, _parserelativeurl.parseRelativeUrl)((0, _hasbasepath.hasBasePath)(as) ? (0, _removebasepath.removeBasePath)(as) : as); | |
| const localePathResult = (0, _normalizelocalepath.normalizeLocalePath)(parsedAs.pathname, this.locales); | |
| if (localePathResult.detectedLocale) { | |
| nextState.locale = localePathResult.detectedLocale; | |
| parsedAs.pathname = (0, _addbasepath.addBasePath)(parsedAs.pathname); | |
| as = (0, _formaturl.formatWithValidation)(parsedAs); | |
| url = (0, _addbasepath.addBasePath)((0, _normalizelocalepath.normalizeLocalePath)((0, _hasbasepath.hasBasePath)(url) ? (0, _removebasepath.removeBasePath)(url) : url, this.locales).pathname); | |
| } | |
| let didNavigate = false; | |
| // we need to wrap this in the env check again since regenerator runtime | |
| // moves this on its own due to the return | |
| if (process.env.__NEXT_I18N_SUPPORT) { | |
| var _this_locales; | |
| // if the locale isn't configured hard navigate to show 404 page | |
| if (!((_this_locales = this.locales) == null ? void 0 : _this_locales.includes(nextState.locale))) { | |
| parsedAs.pathname = (0, _addlocale.addLocale)(parsedAs.pathname, nextState.locale); | |
| handleHardNavigation({ | |
| url: (0, _formaturl.formatWithValidation)(parsedAs), | |
| router: this | |
| }); | |
| // this was previously a return but was removed in favor | |
| // of better dead code elimination with regenerator runtime | |
| didNavigate = true; | |
| } | |
| } | |
| const detectedDomain = (0, _detectdomainlocale.detectDomainLocale)(this.domainLocales, undefined, nextState.locale); | |
| // we need to wrap this in the env check again since regenerator runtime | |
| // moves this on its own due to the return | |
| if (process.env.__NEXT_I18N_SUPPORT) { | |
| // if we are navigating to a domain locale ensure we redirect to the | |
| // correct domain | |
| if (!didNavigate && detectedDomain && this.isLocaleDomain && self.location.hostname !== detectedDomain.domain) { | |
| const asNoBasePath = (0, _removebasepath.removeBasePath)(as); | |
| handleHardNavigation({ | |
| url: "http" + (detectedDomain.http ? '' : 's') + "://" + detectedDomain.domain + (0, _addbasepath.addBasePath)("" + (nextState.locale === detectedDomain.defaultLocale ? '' : "/" + nextState.locale) + (asNoBasePath === '/' ? '' : asNoBasePath) || '/'), | |
| router: this | |
| }); | |
| // this was previously a return but was removed in favor | |
| // of better dead code elimination with regenerator runtime | |
| didNavigate = true; | |
| } | |
| } | |
| if (didNavigate) { | |
| return new Promise(()=>{}); | |
| } | |
| } | |
| // marking route changes as a navigation start entry | |
| if (_utils.ST) { | |
| performance.mark('routeChange'); | |
| } | |
| const { shallow = false, scroll = true } = options; | |
| const routeProps = { | |
| shallow | |
| }; | |
| if (this._inFlightRoute && this.clc) { | |
| if (!isSsr) { | |
| Router.events.emit('routeChangeError', buildCancellationError(), this._inFlightRoute, routeProps); | |
| } | |
| this.clc(); | |
| this.clc = null; | |
| } | |
| as = (0, _addbasepath.addBasePath)((0, _addlocale.addLocale)((0, _hasbasepath.hasBasePath)(as) ? (0, _removebasepath.removeBasePath)(as) : as, options.locale, this.defaultLocale)); | |
| const cleanedAs = (0, _removelocale.removeLocale)((0, _hasbasepath.hasBasePath)(as) ? (0, _removebasepath.removeBasePath)(as) : as, nextState.locale); | |
| this._inFlightRoute = as; | |
| const localeChange = prevLocale !== nextState.locale; | |
| // If the url change is only related to a hash change | |
| // We should not proceed. We should only change the state. | |
| if (!isQueryUpdating && this.onlyAHashChange(cleanedAs) && !localeChange) { | |
| nextState.asPath = cleanedAs; | |
| Router.events.emit('hashChangeStart', as, routeProps); | |
| // TODO: do we need the resolved href when only a hash change? | |
| this.changeState(method, url, as, { | |
| ...options, | |
| scroll: false | |
| }); | |
| if (scroll) { | |
| this.scrollToHash(cleanedAs); | |
| } | |
| try { | |
| await this.set(nextState, this.components[nextState.route], null); | |
| } catch (err) { | |
| if ((0, _iserror.default)(err) && err.cancelled) { | |
| Router.events.emit('routeChangeError', err, cleanedAs, routeProps); | |
| } | |
| throw err; | |
| } | |
| Router.events.emit('hashChangeComplete', as, routeProps); | |
| return true; | |
| } | |
| let parsed = (0, _parserelativeurl.parseRelativeUrl)(url); | |
| let { pathname, query } = parsed; | |
| // The build manifest needs to be loaded before auto-static dynamic pages | |
| // get their query parameters to allow ensuring they can be parsed properly | |
| // when rewritten to | |
| let pages, rewrites; | |
| try { | |
| ; | |
| [pages, { __rewrites: rewrites }] = await Promise.all([ | |
| this.pageLoader.getPageList(), | |
| (0, _routeloader.getClientBuildManifest)(), | |
| this.pageLoader.getMiddleware() | |
| ]); | |
| } catch (err) { | |
| // If we fail to resolve the page list or client-build manifest, we must | |
| // do a server-side transition: | |
| handleHardNavigation({ | |
| url: as, | |
| router: this | |
| }); | |
| return false; | |
| } | |
| // If asked to change the current URL we should reload the current page | |
| // (not location.reload() but reload getInitialProps and other Next.js stuffs) | |
| // We also need to set the method = replaceState always | |
| // as this should not go into the history (That's how browsers work) | |
| // We should compare the new asPath to the current asPath, not the url | |
| if (!this.urlIsNew(cleanedAs) && !localeChange) { | |
| method = 'replaceState'; | |
| } | |
| // we need to resolve the as value using rewrites for dynamic SSG | |
| // pages to allow building the data URL correctly | |
| let resolvedAs = as; | |
| // url and as should always be prefixed with basePath by this | |
| // point by either next/link or router.push/replace so strip the | |
| // basePath from the pathname to match the pages dir 1-to-1 | |
| pathname = pathname ? (0, _removetrailingslash.removeTrailingSlash)((0, _removebasepath.removeBasePath)(pathname)) : pathname; | |
| let route = (0, _removetrailingslash.removeTrailingSlash)(pathname); | |
| const parsedAsPathname = as.startsWith('/') && (0, _parserelativeurl.parseRelativeUrl)(as).pathname; | |
| // if we detected the path as app route during prefetching | |
| // trigger hard navigation | |
| if ((_this_components_pathname = this.components[pathname]) == null ? void 0 : _this_components_pathname.__appRouter) { | |
| handleHardNavigation({ | |
| url: as, | |
| router: this | |
| }); | |
| return new Promise(()=>{}); | |
| } | |
| const isMiddlewareRewrite = !!(parsedAsPathname && route !== parsedAsPathname && (!(0, _isdynamic.isDynamicRoute)(route) || !(0, _routematcher.getRouteMatcher)((0, _routeregex.getRouteRegex)(route))(parsedAsPathname))); | |
| // we don't attempt resolve asPath when we need to execute | |
| // middleware as the resolving will occur server-side | |
| const isMiddlewareMatch = !options.shallow && await matchesMiddleware({ | |
| asPath: as, | |
| locale: nextState.locale, | |
| router: this | |
| }); | |
| if (isQueryUpdating && isMiddlewareMatch) { | |
| shouldResolveHref = false; | |
| } | |
| if (shouldResolveHref && pathname !== '/_error') { | |
| ; | |
| options._shouldResolveHref = true; | |
| if (process.env.__NEXT_HAS_REWRITES && as.startsWith('/')) { | |
| const rewritesResult = resolveRewrites((0, _addbasepath.addBasePath)((0, _addlocale.addLocale)(cleanedAs, nextState.locale), true), pages, rewrites, query, (p)=>resolveDynamicRoute(p, pages), this.locales); | |
| if (rewritesResult.externalDest) { | |
| handleHardNavigation({ | |
| url: as, | |
| router: this | |
| }); | |
| return true; | |
| } | |
| if (!isMiddlewareMatch) { | |
| resolvedAs = rewritesResult.asPath; | |
| } | |
| if (rewritesResult.matchedPage && rewritesResult.resolvedHref) { | |
| // if this directly matches a page we need to update the href to | |
| // allow the correct page chunk to be loaded | |
| pathname = rewritesResult.resolvedHref; | |
| parsed.pathname = (0, _addbasepath.addBasePath)(pathname); | |
| if (!isMiddlewareMatch) { | |
| url = (0, _formaturl.formatWithValidation)(parsed); | |
| } | |
| } | |
| } else { | |
| parsed.pathname = resolveDynamicRoute(pathname, pages); | |
| if (parsed.pathname !== pathname) { | |
| pathname = parsed.pathname; | |
| parsed.pathname = (0, _addbasepath.addBasePath)(pathname); | |
| if (!isMiddlewareMatch) { | |
| url = (0, _formaturl.formatWithValidation)(parsed); | |
| } | |
| } | |
| } | |
| } | |
| if (!(0, _islocalurl.isLocalURL)(as)) { | |
| if (process.env.NODE_ENV !== 'production') { | |
| throw Object.defineProperty(new Error('Invalid href: "' + url + '" and as: "' + as + '", received relative href and external as' + "\nSee more info: https://nextjs.org/docs/messages/invalid-relative-url-external-as"), "__NEXT_ERROR_CODE", { | |
| value: "E380", | |
| enumerable: false, | |
| configurable: true | |
| }); | |
| } | |
| handleHardNavigation({ | |
| url: as, | |
| router: this | |
| }); | |
| return false; | |
| } | |
| resolvedAs = (0, _removelocale.removeLocale)((0, _removebasepath.removeBasePath)(resolvedAs), nextState.locale); | |
| route = (0, _removetrailingslash.removeTrailingSlash)(pathname); | |
| let routeMatch = false; | |
| if ((0, _isdynamic.isDynamicRoute)(route)) { | |
| const parsedAs = (0, _parserelativeurl.parseRelativeUrl)(resolvedAs); | |
| const asPathname = parsedAs.pathname; | |
| const routeRegex = (0, _routeregex.getRouteRegex)(route); | |
| routeMatch = (0, _routematcher.getRouteMatcher)(routeRegex)(asPathname); | |
| const shouldInterpolate = route === asPathname; | |
| const interpolatedAs = shouldInterpolate ? (0, _interpolateas.interpolateAs)(route, asPathname, query) : {}; | |
| if (!routeMatch || shouldInterpolate && !interpolatedAs.result) { | |
| const missingParams = Object.keys(routeRegex.groups).filter((param)=>!query[param] && !routeRegex.groups[param].optional); | |
| if (missingParams.length > 0 && !isMiddlewareMatch) { | |
| if (process.env.NODE_ENV !== 'production') { | |
| console.warn("" + (shouldInterpolate ? "Interpolating href" : "Mismatching `as` and `href`") + " failed to manually provide " + ("the params: " + missingParams.join(', ') + " in the `href`'s `query`")); | |
| } | |
| throw Object.defineProperty(new Error((shouldInterpolate ? "The provided `href` (" + url + ") value is missing query values (" + missingParams.join(', ') + ") to be interpolated properly. " : "The provided `as` value (" + asPathname + ") is incompatible with the `href` value (" + route + "). ") + ("Read more: https://nextjs.org/docs/messages/" + (shouldInterpolate ? 'href-interpolation-failed' : 'incompatible-href-as'))), "__NEXT_ERROR_CODE", { | |
| value: "E344", | |
| enumerable: false, | |
| configurable: true | |
| }); | |
| } | |
| } else if (shouldInterpolate) { | |
| as = (0, _formaturl.formatWithValidation)(Object.assign({}, parsedAs, { | |
| pathname: interpolatedAs.result, | |
| query: (0, _omit.omit)(query, interpolatedAs.params) | |
| })); | |
| } else { | |
| // Merge params into `query`, overwriting any specified in search | |
| Object.assign(query, routeMatch); | |
| } | |
| } | |
| if (!isQueryUpdating) { | |
| Router.events.emit('routeChangeStart', as, routeProps); | |
| } | |
| const isErrorRoute = this.pathname === '/404' || this.pathname === '/_error'; | |
| try { | |
| var _self___NEXT_DATA___props_pageProps, _self___NEXT_DATA___props, _routeInfo_props; | |
| let routeInfo = await this.getRouteInfo({ | |
| route, | |
| pathname, | |
| query, | |
| as, | |
| resolvedAs, | |
| routeProps, | |
| locale: nextState.locale, | |
| isPreview: nextState.isPreview, | |
| hasMiddleware: isMiddlewareMatch, | |
| unstable_skipClientCache: options.unstable_skipClientCache, | |
| isQueryUpdating: isQueryUpdating && !this.isFallback, | |
| isMiddlewareRewrite | |
| }); | |
| if (!isQueryUpdating && !options.shallow) { | |
| await this._bfl(as, 'resolvedAs' in routeInfo ? routeInfo.resolvedAs : undefined, nextState.locale); | |
| } | |
| if ('route' in routeInfo && isMiddlewareMatch) { | |
| pathname = routeInfo.route || route; | |
| route = pathname; | |
| if (!routeProps.shallow) { | |
| query = Object.assign({}, routeInfo.query || {}, query); | |
| } | |
| const cleanedParsedPathname = (0, _hasbasepath.hasBasePath)(parsed.pathname) ? (0, _removebasepath.removeBasePath)(parsed.pathname) : parsed.pathname; | |
| if (routeMatch && pathname !== cleanedParsedPathname) { | |
| Object.keys(routeMatch).forEach((key)=>{ | |
| if (routeMatch && query[key] === routeMatch[key]) { | |
| delete query[key]; | |
| } | |
| }); | |
| } | |
| if ((0, _isdynamic.isDynamicRoute)(pathname)) { | |
| const prefixedAs = !routeProps.shallow && routeInfo.resolvedAs ? routeInfo.resolvedAs : (0, _addbasepath.addBasePath)((0, _addlocale.addLocale)(new URL(as, location.href).pathname, nextState.locale), true); | |
| let rewriteAs = prefixedAs; | |
| if ((0, _hasbasepath.hasBasePath)(rewriteAs)) { | |
| rewriteAs = (0, _removebasepath.removeBasePath)(rewriteAs); | |
| } | |
| if (process.env.__NEXT_I18N_SUPPORT) { | |
| const localeResult = (0, _normalizelocalepath.normalizeLocalePath)(rewriteAs, this.locales); | |
| nextState.locale = localeResult.detectedLocale || nextState.locale; | |
| rewriteAs = localeResult.pathname; | |
| } | |
| const routeRegex = (0, _routeregex.getRouteRegex)(pathname); | |
| const curRouteMatch = (0, _routematcher.getRouteMatcher)(routeRegex)(new URL(rewriteAs, location.href).pathname); | |
| if (curRouteMatch) { | |
| Object.assign(query, curRouteMatch); | |
| } | |
| } | |
| } | |
| // If the routeInfo brings a redirect we simply apply it. | |
| if ('type' in routeInfo) { | |
| if (routeInfo.type === 'redirect-internal') { | |
| return this.change(method, routeInfo.newUrl, routeInfo.newAs, options); | |
| } else { | |
| handleHardNavigation({ | |
| url: routeInfo.destination, | |
| router: this | |
| }); | |
| return new Promise(()=>{}); | |
| } | |
| } | |
| const component = routeInfo.Component; | |
| if (component && component.unstable_scriptLoader) { | |
| const scripts = [].concat(component.unstable_scriptLoader()); | |
| scripts.forEach((script)=>{ | |
| (0, _script.handleClientScriptLoad)(script.props); | |
| }); | |
| } | |
| // handle redirect on client-transition | |
| if ((routeInfo.__N_SSG || routeInfo.__N_SSP) && routeInfo.props) { | |
| if (routeInfo.props.pageProps && routeInfo.props.pageProps.__N_REDIRECT) { | |
| // Use the destination from redirect without adding locale | |
| options.locale = false; | |
| const destination = routeInfo.props.pageProps.__N_REDIRECT; | |
| // check if destination is internal (resolves to a page) and attempt | |
| // client-navigation if it is falling back to hard navigation if | |
| // it's not | |
| if (destination.startsWith('/') && routeInfo.props.pageProps.__N_REDIRECT_BASE_PATH !== false) { | |
| const parsedHref = (0, _parserelativeurl.parseRelativeUrl)(destination); | |
| parsedHref.pathname = resolveDynamicRoute(parsedHref.pathname, pages); | |
| const { url: newUrl, as: newAs } = prepareUrlAs(this, destination, destination); | |
| return this.change(method, newUrl, newAs, options); | |
| } | |
| handleHardNavigation({ | |
| url: destination, | |
| router: this | |
| }); | |
| return new Promise(()=>{}); | |
| } | |
| nextState.isPreview = !!routeInfo.props.__N_PREVIEW; | |
| // handle SSG data 404 | |
| if (routeInfo.props.notFound === SSG_DATA_NOT_FOUND) { | |
| let notFoundRoute; | |
| try { | |
| await this.fetchComponent('/404'); | |
| notFoundRoute = '/404'; | |
| } catch (_) { | |
| notFoundRoute = '/_error'; | |
| } | |
| routeInfo = await this.getRouteInfo({ | |
| route: notFoundRoute, | |
| pathname: notFoundRoute, | |
| query, | |
| as, | |
| resolvedAs, | |
| routeProps: { | |
| shallow: false | |
| }, | |
| locale: nextState.locale, | |
| isPreview: nextState.isPreview, | |
| isNotFound: true | |
| }); | |
| if ('type' in routeInfo) { | |
| throw Object.defineProperty(new Error("Unexpected middleware effect on /404"), "__NEXT_ERROR_CODE", { | |
| value: "E158", | |
| enumerable: false, | |
| configurable: true | |
| }); | |
| } | |
| } | |
| } | |
| if (isQueryUpdating && this.pathname === '/_error' && ((_self___NEXT_DATA___props = self.__NEXT_DATA__.props) == null ? void 0 : (_self___NEXT_DATA___props_pageProps = _self___NEXT_DATA___props.pageProps) == null ? void 0 : _self___NEXT_DATA___props_pageProps.statusCode) === 500 && ((_routeInfo_props = routeInfo.props) == null ? void 0 : _routeInfo_props.pageProps)) { | |
| // ensure statusCode is still correct for static 500 page | |
| // when updating query information | |
| routeInfo.props.pageProps.statusCode = 500; | |
| } | |
| var _routeInfo_route; | |
| // shallow routing is only allowed for same page URL changes. | |
| const isValidShallowRoute = options.shallow && nextState.route === ((_routeInfo_route = routeInfo.route) != null ? _routeInfo_route : route); | |
| var _options_scroll; | |
| const shouldScroll = (_options_scroll = options.scroll) != null ? _options_scroll : !isQueryUpdating && !isValidShallowRoute; | |
| const resetScroll = shouldScroll ? { | |
| x: 0, | |
| y: 0 | |
| } : null; | |
| const upcomingScrollState = forcedScroll != null ? forcedScroll : resetScroll; | |
| // the new state that the router gonna set | |
| const upcomingRouterState = { | |
| ...nextState, | |
| route, | |
| pathname, | |
| query, | |
| asPath: cleanedAs, | |
| isFallback: false | |
| }; | |
| // When the page being rendered is the 404 page, we should only update the | |
| // query parameters. Route changes here might add the basePath when it | |
| // wasn't originally present. This is also why this block is before the | |
| // below `changeState` call which updates the browser's history (changing | |
| // the URL). | |
| if (isQueryUpdating && isErrorRoute) { | |
| var _self___NEXT_DATA___props_pageProps1, _self___NEXT_DATA___props1, _routeInfo_props1; | |
| routeInfo = await this.getRouteInfo({ | |
| route: this.pathname, | |
| pathname: this.pathname, | |
| query, | |
| as, | |
| resolvedAs, | |
| routeProps: { | |
| shallow: false | |
| }, | |
| locale: nextState.locale, | |
| isPreview: nextState.isPreview, | |
| isQueryUpdating: isQueryUpdating && !this.isFallback | |
| }); | |
| if ('type' in routeInfo) { | |
| throw Object.defineProperty(new Error("Unexpected middleware effect on " + this.pathname), "__NEXT_ERROR_CODE", { | |
| value: "E225", | |
| enumerable: false, | |
| configurable: true | |
| }); | |
| } | |
| if (this.pathname === '/_error' && ((_self___NEXT_DATA___props1 = self.__NEXT_DATA__.props) == null ? void 0 : (_self___NEXT_DATA___props_pageProps1 = _self___NEXT_DATA___props1.pageProps) == null ? void 0 : _self___NEXT_DATA___props_pageProps1.statusCode) === 500 && ((_routeInfo_props1 = routeInfo.props) == null ? void 0 : _routeInfo_props1.pageProps)) { | |
| // ensure statusCode is still correct for static 500 page | |
| // when updating query information | |
| routeInfo.props.pageProps.statusCode = 500; | |
| } | |
| try { | |
| await this.set(upcomingRouterState, routeInfo, upcomingScrollState); | |
| } catch (err) { | |
| if ((0, _iserror.default)(err) && err.cancelled) { | |
| Router.events.emit('routeChangeError', err, cleanedAs, routeProps); | |
| } | |
| throw err; | |
| } | |
| return true; | |
| } | |
| Router.events.emit('beforeHistoryChange', as, routeProps); | |
| this.changeState(method, url, as, options); | |
| // for query updates we can skip it if the state is unchanged and we don't | |
| // need to scroll | |
| // https://github.com/vercel/next.js/issues/37139 | |
| const canSkipUpdating = isQueryUpdating && !upcomingScrollState && !readyStateChange && !localeChange && (0, _comparestates.compareRouterStates)(upcomingRouterState, this.state); | |
| if (!canSkipUpdating) { | |
| try { | |
| await this.set(upcomingRouterState, routeInfo, upcomingScrollState); | |
| } catch (e) { | |
| if (e.cancelled) routeInfo.error = routeInfo.error || e; | |
| else throw e; | |
| } | |
| if (routeInfo.error) { | |
| if (!isQueryUpdating) { | |
| Router.events.emit('routeChangeError', routeInfo.error, cleanedAs, routeProps); | |
| } | |
| throw routeInfo.error; | |
| } | |
| if (process.env.__NEXT_I18N_SUPPORT) { | |
| if (nextState.locale) { | |
| document.documentElement.lang = nextState.locale; | |
| } | |
| } | |
| if (!isQueryUpdating) { | |
| Router.events.emit('routeChangeComplete', as, routeProps); | |
| } | |
| // A hash mark # is the optional last part of a URL | |
| const hashRegex = /#.+$/; | |
| if (shouldScroll && hashRegex.test(as)) { | |
| this.scrollToHash(as); | |
| } | |
| } | |
| return true; | |
| } catch (err) { | |
| if ((0, _iserror.default)(err) && err.cancelled) { | |
| return false; | |
| } | |
| throw err; | |
| } | |
| } | |
| changeState(method, url, as, options) { | |
| if (options === void 0) options = {}; | |
| if (process.env.NODE_ENV !== 'production') { | |
| if (typeof window.history === 'undefined') { | |
| console.error("Warning: window.history is not available."); | |
| return; | |
| } | |
| if (typeof window.history[method] === 'undefined') { | |
| console.error("Warning: window.history." + method + " is not available"); | |
| return; | |
| } | |
| } | |
| if (method !== 'pushState' || (0, _utils.getURL)() !== as) { | |
| this._shallow = options.shallow; | |
| window.history[method]({ | |
| url, | |
| as, | |
| options, | |
| __N: true, | |
| key: this._key = method !== 'pushState' ? this._key : createKey() | |
| }, // Most browsers currently ignores this parameter, although they may use it in the future. | |
| // Passing the empty string here should be safe against future changes to the method. | |
| // https://developer.mozilla.org/docs/Web/API/History/replaceState | |
| '', as); | |
| } | |
| } | |
| async handleRouteInfoError(err, pathname, query, as, routeProps, loadErrorFail) { | |
| if (err.cancelled) { | |
| // bubble up cancellation errors | |
| throw err; | |
| } | |
| if ((0, _routeloader.isAssetError)(err) || loadErrorFail) { | |
| Router.events.emit('routeChangeError', err, as, routeProps); | |
| // If we can't load the page it could be one of following reasons | |
| // 1. Page doesn't exists | |
| // 2. Page does exist in a different zone | |
| // 3. Internal error while loading the page | |
| // So, doing a hard reload is the proper way to deal with this. | |
| handleHardNavigation({ | |
| url: as, | |
| router: this | |
| }); | |
| // Changing the URL doesn't block executing the current code path. | |
| // So let's throw a cancellation error stop the routing logic. | |
| throw buildCancellationError(); | |
| } | |
| console.error(err); | |
| try { | |
| let props; | |
| const { page: Component, styleSheets } = await this.fetchComponent('/_error'); | |
| const routeInfo = { | |
| props, | |
| Component, | |
| styleSheets, | |
| err, | |
| error: err | |
| }; | |
| if (!routeInfo.props) { | |
| try { | |
| routeInfo.props = await this.getInitialProps(Component, { | |
| err, | |
| pathname, | |
| query | |
| }); | |
| } catch (gipErr) { | |
| console.error('Error in error page `getInitialProps`: ', gipErr); | |
| routeInfo.props = {}; | |
| } | |
| } | |
| return routeInfo; | |
| } catch (routeInfoErr) { | |
| return this.handleRouteInfoError((0, _iserror.default)(routeInfoErr) ? routeInfoErr : Object.defineProperty(new Error(routeInfoErr + ''), "__NEXT_ERROR_CODE", { | |
| value: "E394", | |
| enumerable: false, | |
| configurable: true | |
| }), pathname, query, as, routeProps, true); | |
| } | |
| } | |
| async getRouteInfo(param) { | |
| let { route: requestedRoute, pathname, query, as, resolvedAs, routeProps, locale, hasMiddleware, isPreview, unstable_skipClientCache, isQueryUpdating, isMiddlewareRewrite, isNotFound } = param; | |
| /** | |
| * This `route` binding can change if there's a rewrite | |
| * so we keep a reference to the original requested route | |
| * so we can store the cache for it and avoid re-requesting every time | |
| * for shallow routing purposes. | |
| */ let route = requestedRoute; | |
| try { | |
| var _data_effect, _data_effect1, _data_effect2, _data_response; | |
| let existingInfo = this.components[route]; | |
| if (routeProps.shallow && existingInfo && this.route === route) { | |
| return existingInfo; | |
| } | |
| const handleCancelled = getCancelledHandler({ | |
| route, | |
| router: this | |
| }); | |
| if (hasMiddleware) { | |
| existingInfo = undefined; | |
| } | |
| let cachedRouteInfo = existingInfo && !('initial' in existingInfo) && process.env.NODE_ENV !== 'development' ? existingInfo : undefined; | |
| const isBackground = isQueryUpdating; | |
| const fetchNextDataParams = { | |
| dataHref: this.pageLoader.getDataHref({ | |
| href: (0, _formaturl.formatWithValidation)({ | |
| pathname, | |
| query | |
| }), | |
| skipInterpolation: true, | |
| asPath: isNotFound ? '/404' : resolvedAs, | |
| locale | |
| }), | |
| hasMiddleware: true, | |
| isServerRender: this.isSsr, | |
| parseJSON: true, | |
| inflightCache: isBackground ? this.sbc : this.sdc, | |
| persistCache: !isPreview, | |
| isPrefetch: false, | |
| unstable_skipClientCache, | |
| isBackground | |
| }; | |
| let data = isQueryUpdating && !isMiddlewareRewrite ? null : await withMiddlewareEffects({ | |
| fetchData: ()=>fetchNextData(fetchNextDataParams), | |
| asPath: isNotFound ? '/404' : resolvedAs, | |
| locale: locale, | |
| router: this | |
| }).catch((err)=>{ | |
| // we don't hard error during query updating | |
| // as it's un-necessary and doesn't need to be fatal | |
| // unless it is a fallback route and the props can't | |
| // be loaded | |
| if (isQueryUpdating) { | |
| return null; | |
| } | |
| throw err; | |
| }); | |
| // when rendering error routes we don't apply middleware | |
| // effects | |
| if (data && (pathname === '/_error' || pathname === '/404')) { | |
| data.effect = undefined; | |
| } | |
| if (isQueryUpdating) { | |
| if (!data) { | |
| data = { | |
| json: self.__NEXT_DATA__.props | |
| }; | |
| } else { | |
| data.json = self.__NEXT_DATA__.props; | |
| } | |
| } | |
| handleCancelled(); | |
| if ((data == null ? void 0 : (_data_effect = data.effect) == null ? void 0 : _data_effect.type) === 'redirect-internal' || (data == null ? void 0 : (_data_effect1 = data.effect) == null ? void 0 : _data_effect1.type) === 'redirect-external') { | |
| return data.effect; | |
| } | |
| if ((data == null ? void 0 : (_data_effect2 = data.effect) == null ? void 0 : _data_effect2.type) === 'rewrite') { | |
| const resolvedRoute = (0, _removetrailingslash.removeTrailingSlash)(data.effect.resolvedHref); | |
| const pages = await this.pageLoader.getPageList(); | |
| // during query updating the page must match although during | |
| // client-transition a redirect that doesn't match a page | |
| // can be returned and this should trigger a hard navigation | |
| // which is valid for incremental migration | |
| if (!isQueryUpdating || pages.includes(resolvedRoute)) { | |
| route = resolvedRoute; | |
| pathname = data.effect.resolvedHref; | |
| query = { | |
| ...query, | |
| ...data.effect.parsedAs.query | |
| }; | |
| resolvedAs = (0, _removebasepath.removeBasePath)((0, _normalizelocalepath.normalizeLocalePath)(data.effect.parsedAs.pathname, this.locales).pathname); | |
| // Check again the cache with the new destination. | |
| existingInfo = this.components[route]; | |
| if (routeProps.shallow && existingInfo && this.route === route && !hasMiddleware) { | |
| // If we have a match with the current route due to rewrite, | |
| // we can copy the existing information to the rewritten one. | |
| // Then, we return the information along with the matched route. | |
| return { | |
| ...existingInfo, | |
| route | |
| }; | |
| } | |
| } | |
| } | |
| if ((0, _isapiroute.isAPIRoute)(route)) { | |
| handleHardNavigation({ | |
| url: as, | |
| router: this | |
| }); | |
| return new Promise(()=>{}); | |
| } | |
| const routeInfo = cachedRouteInfo || await this.fetchComponent(route).then((res)=>({ | |
| Component: res.page, | |
| styleSheets: res.styleSheets, | |
| __N_SSG: res.mod.__N_SSG, | |
| __N_SSP: res.mod.__N_SSP | |
| })); | |
| if (process.env.NODE_ENV !== 'production') { | |
| const { isValidElementType } = require('next/dist/compiled/react-is'); | |
| if (!isValidElementType(routeInfo.Component)) { | |
| throw Object.defineProperty(new Error('The default export is not a React Component in page: "' + pathname + '"'), "__NEXT_ERROR_CODE", { | |
| value: "E286", | |
| enumerable: false, | |
| configurable: true | |
| }); | |
| } | |
| } | |
| const wasBailedPrefetch = data == null ? void 0 : (_data_response = data.response) == null ? void 0 : _data_response.headers.get('x-middleware-skip'); | |
| const shouldFetchData = routeInfo.__N_SSG || routeInfo.__N_SSP; | |
| // For non-SSG prefetches that bailed before sending data | |
| // we clear the cache to fetch full response | |
| if (wasBailedPrefetch && (data == null ? void 0 : data.dataHref)) { | |
| delete this.sdc[data.dataHref]; | |
| } | |
| const { props, cacheKey } = await this._getData(async ()=>{ | |
| if (shouldFetchData) { | |
| if ((data == null ? void 0 : data.json) && !wasBailedPrefetch) { | |
| return { | |
| cacheKey: data.cacheKey, | |
| props: data.json | |
| }; | |
| } | |
| const dataHref = (data == null ? void 0 : data.dataHref) ? data.dataHref : this.pageLoader.getDataHref({ | |
| href: (0, _formaturl.formatWithValidation)({ | |
| pathname, | |
| query | |
| }), | |
| asPath: resolvedAs, | |
| locale | |
| }); | |
| const fetched = await fetchNextData({ | |
| dataHref, | |
| isServerRender: this.isSsr, | |
| parseJSON: true, | |
| inflightCache: wasBailedPrefetch ? {} : this.sdc, | |
| persistCache: !isPreview, | |
| isPrefetch: false, | |
| unstable_skipClientCache | |
| }); | |
| return { | |
| cacheKey: fetched.cacheKey, | |
| props: fetched.json || {} | |
| }; | |
| } | |
| return { | |
| headers: {}, | |
| props: await this.getInitialProps(routeInfo.Component, // we provide AppTree later so this needs to be `any` | |
| { | |
| pathname, | |
| query, | |
| asPath: as, | |
| locale, | |
| locales: this.locales, | |
| defaultLocale: this.defaultLocale | |
| }) | |
| }; | |
| }); | |
| // Only bust the data cache for SSP routes although | |
| // middleware can skip cache per request with | |
| // x-middleware-cache: no-cache as well | |
| if (routeInfo.__N_SSP && fetchNextDataParams.dataHref && cacheKey) { | |
| delete this.sdc[cacheKey]; | |
| } | |
| // we kick off a HEAD request in the background | |
| // when a non-prefetch request is made to signal revalidation | |
| if (!this.isPreview && routeInfo.__N_SSG && process.env.NODE_ENV !== 'development' && !isQueryUpdating) { | |
| fetchNextData(Object.assign({}, fetchNextDataParams, { | |
| isBackground: true, | |
| persistCache: false, | |
| inflightCache: this.sbc | |
| })).catch(()=>{}); | |
| } | |
| props.pageProps = Object.assign({}, props.pageProps); | |
| routeInfo.props = props; | |
| routeInfo.route = route; | |
| routeInfo.query = query; | |
| routeInfo.resolvedAs = resolvedAs; | |
| this.components[route] = routeInfo; | |
| return routeInfo; | |
| } catch (err) { | |
| return this.handleRouteInfoError((0, _iserror.getProperError)(err), pathname, query, as, routeProps); | |
| } | |
| } | |
| set(state, data, resetScroll) { | |
| this.state = state; | |
| return this.sub(data, this.components['/_app'].Component, resetScroll); | |
| } | |
| /** | |
| * Callback to execute before replacing router state | |
| * @param cb callback to be executed | |
| */ beforePopState(cb) { | |
| this._bps = cb; | |
| } | |
| onlyAHashChange(as) { | |
| if (!this.asPath) return false; | |
| const [oldUrlNoHash, oldHash] = this.asPath.split('#', 2); | |
| const [newUrlNoHash, newHash] = as.split('#', 2); | |
| // Makes sure we scroll to the provided hash if the url/hash are the same | |
| if (newHash && oldUrlNoHash === newUrlNoHash && oldHash === newHash) { | |
| return true; | |
| } | |
| // If the urls are change, there's more than a hash change | |
| if (oldUrlNoHash !== newUrlNoHash) { | |
| return false; | |
| } | |
| // If the hash has changed, then it's a hash only change. | |
| // This check is necessary to handle both the enter and | |
| // leave hash === '' cases. The identity case falls through | |
| // and is treated as a next reload. | |
| return oldHash !== newHash; | |
| } | |
| scrollToHash(as) { | |
| const [, hash = ''] = as.split('#', 2); | |
| (0, _disablesmoothscroll.disableSmoothScrollDuringRouteTransition)(()=>{ | |
| // Scroll to top if the hash is just `#` with no value or `#top` | |
| // To mirror browsers | |
| if (hash === '' || hash === 'top') { | |
| window.scrollTo(0, 0); | |
| return; | |
| } | |
| // Decode hash to make non-latin anchor works. | |
| const rawHash = decodeURIComponent(hash); | |
| // First we check if the element by id is found | |
| const idEl = document.getElementById(rawHash); | |
| if (idEl) { | |
| idEl.scrollIntoView(); | |
| return; | |
| } | |
| // If there's no element with the id, we check the `name` property | |
| // To mirror browsers | |
| const nameEl = document.getElementsByName(rawHash)[0]; | |
| if (nameEl) { | |
| nameEl.scrollIntoView(); | |
| } | |
| }, { | |
| onlyHashChange: this.onlyAHashChange(as) | |
| }); | |
| } | |
| urlIsNew(asPath) { | |
| return this.asPath !== asPath; | |
| } | |
| /** | |
| * Prefetch page code, you may wait for the data during page rendering. | |
| * This feature only works in production! | |
| * @param url the href of prefetched page | |
| * @param asPath the as path of the prefetched page | |
| */ async prefetch(url, asPath, options) { | |
| if (asPath === void 0) asPath = url; | |
| if (options === void 0) options = {}; | |
| // Prefetch is not supported in development mode because it would trigger on-demand-entries | |
| if (process.env.NODE_ENV !== 'production') { | |
| return; | |
| } | |
| if (typeof window !== 'undefined' && (0, _isbot.isBot)(window.navigator.userAgent)) { | |
| // No prefetches for bots that render the link since they are typically navigating | |
| // links via the equivalent of a hard navigation and hence never utilize these | |
| // prefetches. | |
| return; | |
| } | |
| let parsed = (0, _parserelativeurl.parseRelativeUrl)(url); | |
| const urlPathname = parsed.pathname; | |
| let { pathname, query } = parsed; | |
| const originalPathname = pathname; | |
| if (process.env.__NEXT_I18N_SUPPORT) { | |
| if (options.locale === false) { | |
| pathname = (0, _normalizelocalepath.normalizeLocalePath)(pathname, this.locales).pathname; | |
| parsed.pathname = pathname; | |
| url = (0, _formaturl.formatWithValidation)(parsed); | |
| let parsedAs = (0, _parserelativeurl.parseRelativeUrl)(asPath); | |
| const localePathResult = (0, _normalizelocalepath.normalizeLocalePath)(parsedAs.pathname, this.locales); | |
| parsedAs.pathname = localePathResult.pathname; | |
| options.locale = localePathResult.detectedLocale || this.defaultLocale; | |
| asPath = (0, _formaturl.formatWithValidation)(parsedAs); | |
| } | |
| } | |
| const pages = await this.pageLoader.getPageList(); | |
| let resolvedAs = asPath; | |
| const locale = typeof options.locale !== 'undefined' ? options.locale || undefined : this.locale; | |
| const isMiddlewareMatch = await matchesMiddleware({ | |
| asPath: asPath, | |
| locale: locale, | |
| router: this | |
| }); | |
| if (process.env.__NEXT_HAS_REWRITES && asPath.startsWith('/')) { | |
| let rewrites; | |
| ({ __rewrites: rewrites } = await (0, _routeloader.getClientBuildManifest)()); | |
| const rewritesResult = resolveRewrites((0, _addbasepath.addBasePath)((0, _addlocale.addLocale)(asPath, this.locale), true), pages, rewrites, parsed.query, (p)=>resolveDynamicRoute(p, pages), this.locales); | |
| if (rewritesResult.externalDest) { | |
| return; | |
| } | |
| if (!isMiddlewareMatch) { | |
| resolvedAs = (0, _removelocale.removeLocale)((0, _removebasepath.removeBasePath)(rewritesResult.asPath), this.locale); | |
| } | |
| if (rewritesResult.matchedPage && rewritesResult.resolvedHref) { | |
| // if this directly matches a page we need to update the href to | |
| // allow the correct page chunk to be loaded | |
| pathname = rewritesResult.resolvedHref; | |
| parsed.pathname = pathname; | |
| if (!isMiddlewareMatch) { | |
| url = (0, _formaturl.formatWithValidation)(parsed); | |
| } | |
| } | |
| } | |
| parsed.pathname = resolveDynamicRoute(parsed.pathname, pages); | |
| if ((0, _isdynamic.isDynamicRoute)(parsed.pathname)) { | |
| pathname = parsed.pathname; | |
| parsed.pathname = pathname; | |
| Object.assign(query, (0, _routematcher.getRouteMatcher)((0, _routeregex.getRouteRegex)(parsed.pathname))((0, _parsepath.parsePath)(asPath).pathname) || {}); | |
| if (!isMiddlewareMatch) { | |
| url = (0, _formaturl.formatWithValidation)(parsed); | |
| } | |
| } | |
| const data = process.env.__NEXT_MIDDLEWARE_PREFETCH === 'strict' ? null : await withMiddlewareEffects({ | |
| fetchData: ()=>fetchNextData({ | |
| dataHref: this.pageLoader.getDataHref({ | |
| href: (0, _formaturl.formatWithValidation)({ | |
| pathname: originalPathname, | |
| query | |
| }), | |
| skipInterpolation: true, | |
| asPath: resolvedAs, | |
| locale | |
| }), | |
| hasMiddleware: true, | |
| isServerRender: false, | |
| parseJSON: true, | |
| inflightCache: this.sdc, | |
| persistCache: !this.isPreview, | |
| isPrefetch: true | |
| }), | |
| asPath: asPath, | |
| locale: locale, | |
| router: this | |
| }); | |
| /** | |
| * If there was a rewrite we apply the effects of the rewrite on the | |
| * current parameters for the prefetch. | |
| */ if ((data == null ? void 0 : data.effect.type) === 'rewrite') { | |
| parsed.pathname = data.effect.resolvedHref; | |
| pathname = data.effect.resolvedHref; | |
| query = { | |
| ...query, | |
| ...data.effect.parsedAs.query | |
| }; | |
| resolvedAs = data.effect.parsedAs.pathname; | |
| url = (0, _formaturl.formatWithValidation)(parsed); | |
| } | |
| /** | |
| * If there is a redirect to an external destination then we don't have | |
| * to prefetch content as it will be unused. | |
| */ if ((data == null ? void 0 : data.effect.type) === 'redirect-external') { | |
| return; | |
| } | |
| const route = (0, _removetrailingslash.removeTrailingSlash)(pathname); | |
| if (await this._bfl(asPath, resolvedAs, options.locale, true)) { | |
| this.components[urlPathname] = { | |
| __appRouter: true | |
| }; | |
| } | |
| await Promise.all([ | |
| this.pageLoader._isSsg(route).then((isSsg)=>{ | |
| return isSsg ? fetchNextData({ | |
| dataHref: (data == null ? void 0 : data.json) ? data == null ? void 0 : data.dataHref : this.pageLoader.getDataHref({ | |
| href: url, | |
| asPath: resolvedAs, | |
| locale: locale | |
| }), | |
| isServerRender: false, | |
| parseJSON: true, | |
| inflightCache: this.sdc, | |
| persistCache: !this.isPreview, | |
| isPrefetch: true, | |
| unstable_skipClientCache: options.unstable_skipClientCache || options.priority && !!process.env.__NEXT_OPTIMISTIC_CLIENT_CACHE | |
| }).then(()=>false).catch(()=>false) : false; | |
| }), | |
| this.pageLoader[options.priority ? 'loadPage' : 'prefetch'](route) | |
| ]); | |
| } | |
| async fetchComponent(route) { | |
| const handleCancelled = getCancelledHandler({ | |
| route, | |
| router: this | |
| }); | |
| try { | |
| const componentResult = await this.pageLoader.loadPage(route); | |
| handleCancelled(); | |
| return componentResult; | |
| } catch (err) { | |
| handleCancelled(); | |
| throw err; | |
| } | |
| } | |
| _getData(fn) { | |
| let cancelled = false; | |
| const cancel = ()=>{ | |
| cancelled = true; | |
| }; | |
| this.clc = cancel; | |
| return fn().then((data)=>{ | |
| if (cancel === this.clc) { | |
| this.clc = null; | |
| } | |
| if (cancelled) { | |
| const err = Object.defineProperty(new Error('Loading initial props cancelled'), "__NEXT_ERROR_CODE", { | |
| value: "E405", | |
| enumerable: false, | |
| configurable: true | |
| }); | |
| err.cancelled = true; | |
| throw err; | |
| } | |
| return data; | |
| }); | |
| } | |
| getInitialProps(Component, ctx) { | |
| const { Component: App } = this.components['/_app']; | |
| const AppTree = this._wrapApp(App); | |
| ctx.AppTree = AppTree; | |
| return (0, _utils.loadGetInitialProps)(App, { | |
| AppTree, | |
| Component, | |
| router: this, | |
| ctx | |
| }); | |
| } | |
| get route() { | |
| return this.state.route; | |
| } | |
| get pathname() { | |
| return this.state.pathname; | |
| } | |
| get query() { | |
| return this.state.query; | |
| } | |
| get asPath() { | |
| return this.state.asPath; | |
| } | |
| get locale() { | |
| return this.state.locale; | |
| } | |
| get isFallback() { | |
| return this.state.isFallback; | |
| } | |
| get isPreview() { | |
| return this.state.isPreview; | |
| } | |
| constructor(pathname, query, as, { initialProps, pageLoader, App, wrapApp, Component, err, subscription, isFallback, locale, locales, defaultLocale, domainLocales, isPreview }){ | |
| // Server Data Cache (full data requests) | |
| this.sdc = {}; | |
| // Server Background Cache (HEAD requests) | |
| this.sbc = {}; | |
| this.isFirstPopStateEvent = true; | |
| this._key = createKey(); | |
| this.onPopState = (e)=>{ | |
| const { isFirstPopStateEvent } = this; | |
| this.isFirstPopStateEvent = false; | |
| const state = e.state; | |
| if (!state) { | |
| // We get state as undefined for two reasons. | |
| // 1. With older safari (< 8) and older chrome (< 34) | |
| // 2. When the URL changed with # | |
| // | |
| // In the both cases, we don't need to proceed and change the route. | |
| // (as it's already changed) | |
| // But we can simply replace the state with the new changes. | |
| // Actually, for (1) we don't need to nothing. But it's hard to detect that event. | |
| // So, doing the following for (1) does no harm. | |
| const { pathname, query } = this; | |
| this.changeState('replaceState', (0, _formaturl.formatWithValidation)({ | |
| pathname: (0, _addbasepath.addBasePath)(pathname), | |
| query | |
| }), (0, _utils.getURL)()); | |
| return; | |
| } | |
| // __NA is used to identify if the history entry can be handled by the app-router. | |
| if (state.__NA) { | |
| window.location.reload(); | |
| return; | |
| } | |
| if (!state.__N) { | |
| return; | |
| } | |
| // Safari fires popstateevent when reopening the browser. | |
| if (isFirstPopStateEvent && this.locale === state.options.locale && state.as === this.asPath) { | |
| return; | |
| } | |
| let forcedScroll; | |
| const { url, as, options, key } = state; | |
| if (process.env.__NEXT_SCROLL_RESTORATION) { | |
| if (manualScrollRestoration) { | |
| if (this._key !== key) { | |
| // Snapshot current scroll position: | |
| try { | |
| sessionStorage.setItem('__next_scroll_' + this._key, JSON.stringify({ | |
| x: self.pageXOffset, | |
| y: self.pageYOffset | |
| })); | |
| } catch (e) {} | |
| // Restore old scroll position: | |
| try { | |
| const v = sessionStorage.getItem('__next_scroll_' + key); | |
| forcedScroll = JSON.parse(v); | |
| } catch (e) { | |
| forcedScroll = { | |
| x: 0, | |
| y: 0 | |
| }; | |
| } | |
| } | |
| } | |
| } | |
| this._key = key; | |
| const { pathname } = (0, _parserelativeurl.parseRelativeUrl)(url); | |
| // Make sure we don't re-render on initial load, | |
| // can be caused by navigating back from an external site | |
| if (this.isSsr && as === (0, _addbasepath.addBasePath)(this.asPath) && pathname === (0, _addbasepath.addBasePath)(this.pathname)) { | |
| return; | |
| } | |
| // If the downstream application returns falsy, return. | |
| // They will then be responsible for handling the event. | |
| if (this._bps && !this._bps(state)) { | |
| return; | |
| } | |
| this.change('replaceState', url, as, Object.assign({}, options, { | |
| shallow: options.shallow && this._shallow, | |
| locale: options.locale || this.defaultLocale, | |
| // @ts-ignore internal value not exposed on types | |
| _h: 0 | |
| }), forcedScroll); | |
| }; | |
| // represents the current component key | |
| const route = (0, _removetrailingslash.removeTrailingSlash)(pathname); | |
| // set up the component cache (by route keys) | |
| this.components = {}; | |
| // We should not keep the cache, if there's an error | |
| // Otherwise, this cause issues when when going back and | |
| // come again to the errored page. | |
| if (pathname !== '/_error') { | |
| this.components[route] = { | |
| Component, | |
| initial: true, | |
| props: initialProps, | |
| err, | |
| __N_SSG: initialProps && initialProps.__N_SSG, | |
| __N_SSP: initialProps && initialProps.__N_SSP | |
| }; | |
| } | |
| this.components['/_app'] = { | |
| Component: App, | |
| styleSheets: [] | |
| }; | |
| // Backwards compat for Router.router.events | |
| // TODO: Should be remove the following major version as it was never documented | |
| this.events = Router.events; | |
| this.pageLoader = pageLoader; | |
| // if auto prerendered and dynamic route wait to update asPath | |
| // until after mount to prevent hydration mismatch | |
| const autoExportDynamic = (0, _isdynamic.isDynamicRoute)(pathname) && self.__NEXT_DATA__.autoExport; | |
| this.basePath = process.env.__NEXT_ROUTER_BASEPATH || ''; | |
| this.sub = subscription; | |
| this.clc = null; | |
| this._wrapApp = wrapApp; | |
| // make sure to ignore extra popState in safari on navigating | |
| // back from external site | |
| this.isSsr = true; | |
| this.isLocaleDomain = false; | |
| this.isReady = !!(self.__NEXT_DATA__.gssp || self.__NEXT_DATA__.gip || self.__NEXT_DATA__.isExperimentalCompile || self.__NEXT_DATA__.appGip && !self.__NEXT_DATA__.gsp || !autoExportDynamic && !self.location.search && !process.env.__NEXT_HAS_REWRITES); | |
| if (process.env.__NEXT_I18N_SUPPORT) { | |
| this.locales = locales; | |
| this.defaultLocale = defaultLocale; | |
| this.domainLocales = domainLocales; | |
| this.isLocaleDomain = !!(0, _detectdomainlocale.detectDomainLocale)(domainLocales, self.location.hostname); | |
| } | |
| this.state = { | |
| route, | |
| pathname, | |
| query, | |
| asPath: autoExportDynamic ? pathname : as, | |
| isPreview: !!isPreview, | |
| locale: process.env.__NEXT_I18N_SUPPORT ? locale : undefined, | |
| isFallback | |
| }; | |
| this._initialMatchesMiddlewarePromise = Promise.resolve(false); | |
| if (typeof window !== 'undefined') { | |
| // make sure "as" doesn't start with double slashes or else it can | |
| // throw an error as it's considered invalid | |
| if (!as.startsWith('//')) { | |
| // in order for `e.state` to work on the `onpopstate` event | |
| // we have to register the initial route upon initialization | |
| const options = { | |
| locale | |
| }; | |
| const asPath = (0, _utils.getURL)(); | |
| this._initialMatchesMiddlewarePromise = matchesMiddleware({ | |
| router: this, | |
| locale, | |
| asPath | |
| }).then((matches)=>{ | |
| // if middleware matches we leave resolving to the change function | |
| // as the server needs to resolve for correct priority | |
| ; | |
| options._shouldResolveHref = as !== pathname; | |
| this.changeState('replaceState', matches ? asPath : (0, _formaturl.formatWithValidation)({ | |
| pathname: (0, _addbasepath.addBasePath)(pathname), | |
| query | |
| }), asPath, options); | |
| return matches; | |
| }); | |
| } | |
| window.addEventListener('popstate', this.onPopState); | |
| // enable custom scroll restoration handling when available | |
| // otherwise fallback to browser's default handling | |
| if (process.env.__NEXT_SCROLL_RESTORATION) { | |
| if (manualScrollRestoration) { | |
| window.history.scrollRestoration = 'manual'; | |
| } | |
| } | |
| } | |
| } | |
| } | |
| Router.events = (0, _mitt.default)(); | |
| //# sourceMappingURL=router.js.map |