Skip to content

Commit

Permalink
fix: memory leak (#2616)
Browse files Browse the repository at this point in the history
* fix: `nuxtI18nOptions` being set and not cleaned up

* fix: use local `useNuxtApp` instead of passing nuxt context as argument

* fix: remove `nuxtI18nOptions` copy
  • Loading branch information
BobbieGoede authored Dec 13, 2023
1 parent 4bf4f50 commit 64fa2f6
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 56 deletions.
35 changes: 16 additions & 19 deletions src/runtime/internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
} from 'vue-i18n-routing'
import { hasProtocol } from 'ufo'
import isHTTPS from 'is-https'
import { useRequestHeaders, useRequestEvent, useCookie as useNuxtCookie } from '#imports'
import { useRequestHeaders, useRequestEvent, useCookie as useNuxtCookie, useRuntimeConfig, useNuxtApp } from '#imports'
import { nuxtI18nOptionsDefault, NUXT_I18N_MODULE_ID, isSSG } from '#build/i18n.options.mjs'

import type { NuxtApp } from '#app'
Expand Down Expand Up @@ -86,7 +86,7 @@ export function parseAcceptLanguage(input: string): string[] {
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
export function getBrowserLocale(options: Required<NuxtI18nInternalOptions>, context?: any): string | undefined {
export function getBrowserLocale(options: Required<NuxtI18nInternalOptions>): string | undefined {
let ret: string | undefined

if (process.client) {
Expand All @@ -108,16 +108,13 @@ export function getBrowserLocale(options: Required<NuxtI18nInternalOptions>, con
return ret
}

export function getLocaleCookie(
context: any,
{
useCookie = nuxtI18nOptionsDefault.detectBrowserLanguage.useCookie,
cookieKey = nuxtI18nOptionsDefault.detectBrowserLanguage.cookieKey,
localeCodes = []
}: Pick<DetectBrowserLanguageOptions, 'useCookie' | 'cookieKey'> & {
localeCodes?: readonly string[]
} = {}
): string | undefined {
export function getLocaleCookie({
useCookie = nuxtI18nOptionsDefault.detectBrowserLanguage.useCookie,
cookieKey = nuxtI18nOptionsDefault.detectBrowserLanguage.cookieKey,
localeCodes = []
}: Pick<DetectBrowserLanguageOptions, 'useCookie' | 'cookieKey'> & {
localeCodes?: readonly string[]
} = {}): string | undefined {
__DEBUG__ && console.log('getLocaleCookie', { useCookie, cookieKey, localeCodes })
if (!useCookie) {
return
Expand All @@ -134,7 +131,6 @@ export function getLocaleCookie(

export function setLocaleCookie(
locale: string,
context: any,
{
useCookie = nuxtI18nOptionsDefault.detectBrowserLanguage.useCookie,
cookieKey = nuxtI18nOptionsDefault.detectBrowserLanguage.cookieKey,
Expand Down Expand Up @@ -197,7 +193,6 @@ export const DefaultDetectBrowserLanguageFromResult: DetectBrowserLanguageFromRe

export function detectBrowserLanguage<Context extends NuxtApp = NuxtApp>(
route: string | Route | RouteLocationNormalized | RouteLocationNormalizedLoaded,
context: any,
nuxtI18nOptions: DeepRequired<NuxtI18nOptions<Context>>,
nuxtI18nInternalOptions: DeepRequired<NuxtI18nInternalOptions>,
vueI18nOptions: I18nOptions,
Expand Down Expand Up @@ -253,13 +248,13 @@ export function detectBrowserLanguage<Context extends NuxtApp = NuxtApp>(

// get preferred language from cookie if present and enabled
if (useCookie) {
matchedLocale = cookieLocale = getLocaleCookie(context, { ...nuxtI18nOptions.detectBrowserLanguage, localeCodes })
matchedLocale = cookieLocale = getLocaleCookie({ ...nuxtI18nOptions.detectBrowserLanguage, localeCodes })
localeFrom = 'cookie'
__DEBUG__ && console.log('detectBrowserLanguage: cookieLocale', cookieLocale)
}
// try to get locale from either navigator or header detection
if (!matchedLocale) {
matchedLocale = getBrowserLocale(nuxtI18nInternalOptions, context)
matchedLocale = getBrowserLocale(nuxtI18nInternalOptions)
localeFrom = 'navigator_or_header'
__DEBUG__ && console.log('detectBrowserLanguage: browserLocale', matchedLocale)
}
Expand Down Expand Up @@ -369,9 +364,11 @@ export function getLocaleDomain(locales: LocaleObject[]): string {
return host
}

export function getDomainFromLocale(localeCode: Locale, locales: LocaleObject[], nuxt?: NuxtApp): string | undefined {
export function getDomainFromLocale(localeCode: Locale, locales: LocaleObject[]): string | undefined {
const runtimeConfig = useRuntimeConfig()
const nuxtApp = useNuxtApp()
// lookup the `differentDomain` origin associated with given locale.
const config = nuxt?.$config.public.i18n as { locales?: Record<Locale, { domain?: string }> }
const config = runtimeConfig.public.i18n as { locales?: Record<Locale, { domain?: string }> }
const lang = locales.find(locale => locale.code === localeCode)
const domain = config?.locales?.[localeCode]?.domain ?? lang?.domain

Expand All @@ -383,7 +380,7 @@ export function getDomainFromLocale(localeCode: Locale, locales: LocaleObject[],
if (process.server) {
const {
node: { req }
} = useRequestEvent(nuxt)
} = useRequestEvent(nuxtApp)
protocol = req && isHTTPS(req) ? 'https:' : 'http:'
} else {
protocol = new URL(window.location.origin).protocol
Expand Down
30 changes: 15 additions & 15 deletions src/runtime/plugins/i18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,14 @@ import {
getLocale,
getComposer
} from 'vue-i18n-routing'
import { defineNuxtPlugin, useRouter, useRoute, addRouteMiddleware, defineNuxtRouteMiddleware } from '#imports'
import {
defineNuxtPlugin,
useRouter,
useRoute,
addRouteMiddleware,
defineNuxtRouteMiddleware,
useNuxtApp
} from '#imports'
import {
localeCodes,
vueI18nConfigs,
Expand Down Expand Up @@ -65,7 +72,7 @@ export default defineNuxtPlugin({
const { vueApp: app } = nuxt
const nuxtContext = nuxt as unknown as NuxtApp

const vueI18nOptions: I18nOptions = await loadVueI18nOptions(vueI18nConfigs, nuxtContext)
const vueI18nOptions: I18nOptions = await loadVueI18nOptions(vueI18nConfigs, useNuxtApp())

const useCookie = nuxtI18nOptions.detectBrowserLanguage && nuxtI18nOptions.detectBrowserLanguage.useCookie
const { __normalizedLocales: normalizedLocales } = nuxtI18nInternalOptions
Expand All @@ -85,7 +92,6 @@ export default defineNuxtPlugin({

nuxtI18nOptions.baseUrl = extendBaseUrl(nuxtI18nOptions.baseUrl, {
differentDomains,
nuxt: nuxtContext,
localeCodeLoader: defaultLocale,
normalizedLocales
})
Expand All @@ -103,7 +109,7 @@ export default defineNuxtPlugin({
registerGlobalOptions(router, {
...nuxtI18nOptions,
dynamicRouteParamsKey: 'nuxtI18n',
switchLocalePathIntercepter: extendSwitchLocalePathIntercepter(differentDomains, normalizedLocales, nuxtContext),
switchLocalePathIntercepter: extendSwitchLocalePathIntercepter(differentDomains, normalizedLocales),
prefixable: extendPrefixable(differentDomains)
})

Expand All @@ -112,7 +118,6 @@ export default defineNuxtPlugin({
// detect initial locale
let initialLocale = detectLocale(
route,
nuxt.ssrContext,
getLocaleFromRoute,
nuxtI18nOptions,
vueI18nOptions,
Expand Down Expand Up @@ -167,7 +172,6 @@ export default defineNuxtPlugin({
} = nuxtI18nOptions.detectBrowserLanguage
? detectBrowserLanguage(
route,
nuxtContext,
nuxtI18nOptions,
nuxtI18nInternalOptions,
vueI18nOptions,
Expand Down Expand Up @@ -207,7 +211,7 @@ export default defineNuxtPlugin({
})
composer.setLocale = async (locale: string) => {
const localeSetup = isInitialLocaleSetup(locale)
const [modified] = await loadAndSetLocale(locale, nuxtContext, localeMessages, i18n, {
const [modified] = await loadAndSetLocale(locale, localeMessages, i18n, {
useCookie,
differentDomains,
initial: localeSetup,
Expand All @@ -222,7 +226,6 @@ export default defineNuxtPlugin({

const redirectPath = detectRedirect({
route: { to: route },
context: nuxtContext,
targetLocale: locale,
routeLocaleGetter: getLocaleFromRoute,
nuxtI18nOptions
Expand All @@ -246,11 +249,10 @@ export default defineNuxtPlugin({
}
composer.differentDomains = differentDomains
composer.defaultLocale = defaultLocale
composer.getBrowserLocale = () => _getBrowserLocale(nuxtI18nInternalOptions, nuxt.ssrContext)
composer.getLocaleCookie = () =>
_getLocaleCookie(nuxt.ssrContext, { ...nuxtI18nOptions.detectBrowserLanguage, localeCodes })
composer.getBrowserLocale = () => _getBrowserLocale(nuxtI18nInternalOptions)
composer.getLocaleCookie = () => _getLocaleCookie({ ...nuxtI18nOptions.detectBrowserLanguage, localeCodes })
composer.setLocaleCookie = (locale: string) =>
_setLocaleCookie(locale, nuxt.ssrContext, nuxtI18nOptions.detectBrowserLanguage || undefined)
_setLocaleCookie(locale, nuxtI18nOptions.detectBrowserLanguage || undefined)

composer.onBeforeLanguageSwitch = (oldLocale, newLocale, initialSetup, context) =>
nuxt.callHook('i18n:beforeLocaleSwitch', { oldLocale, newLocale, initialSetup, context })
Expand Down Expand Up @@ -448,7 +450,6 @@ export default defineNuxtPlugin({

const locale = detectLocale(
to,
nuxt.ssrContext,
getLocaleFromRoute,
nuxtI18nOptions,
vueI18nOptions,
Expand All @@ -468,7 +469,7 @@ export default defineNuxtPlugin({
const localeSetup = isInitialLocaleSetup(locale)
__DEBUG__ && console.log('localeSetup', localeSetup)

const [modified] = await loadAndSetLocale(locale, nuxtContext, localeMessages, i18n, {
const [modified] = await loadAndSetLocale(locale, localeMessages, i18n, {
useCookie,
differentDomains,
initial: localeSetup,
Expand All @@ -483,7 +484,6 @@ export default defineNuxtPlugin({

const redirectPath = detectRedirect({
route: { to, from },
context: nuxtContext,
targetLocale: locale,
routeLocaleGetter: nuxtI18nOptions.strategy === 'no_prefix' ? () => locale : getLocaleFromRoute,
nuxtI18nOptions,
Expand Down
41 changes: 19 additions & 22 deletions src/runtime/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
} from 'vue-i18n-routing'
import { joinURL, isEqual } from 'ufo'
import { isString, isFunction, isArray, isObject } from '@intlify/shared'
import { navigateTo, useRoute, useState } from '#imports'
import { navigateTo, useNuxtApp, useRoute, useRuntimeConfig, useState } from '#imports'
import { nuxtI18nInternalOptions, nuxtI18nOptionsDefault, NUXT_I18N_MODULE_ID, isSSG } from '#build/i18n.options.mjs'
import {
detectBrowserLanguage,
Expand Down Expand Up @@ -90,7 +90,6 @@ export async function finalizePendingLocaleChange(i18n: I18n) {

export async function loadAndSetLocale<Context extends NuxtApp = NuxtApp>(
newLocale: string,
context: Context,
localeMessages: Record<Locale, LocaleInternalLoader[]>,
i18n: I18n,
{
Expand All @@ -106,6 +105,7 @@ export async function loadAndSetLocale<Context extends NuxtApp = NuxtApp>(
cacheMessages?: Map<string, LocaleMessages<DefineLocaleMessage>>
} = {}
): Promise<[boolean, string]> {
const nuxtApp = useNuxtApp()
let ret = false
const oldLocale = getLocale(i18n)
__DEBUG__ && console.log('setLocale: new -> ', newLocale, ' old -> ', oldLocale, ' initial -> ', initial)
Expand All @@ -123,7 +123,7 @@ export async function loadAndSetLocale<Context extends NuxtApp = NuxtApp>(
}

// call onBeforeLanguageSwitch
const localeOverride = await onBeforeLanguageSwitch(i18n, oldLocale, newLocale, initial, context)
const localeOverride = await onBeforeLanguageSwitch(i18n, oldLocale, newLocale, initial, nuxtApp)
const localeCodes = getLocaleCodes(i18n)
if (localeOverride && localeCodes && localeCodes.includes(localeOverride)) {
if (localeOverride === oldLocale) {
Expand Down Expand Up @@ -162,7 +162,6 @@ type LocaleLoader = () => Locale

export function detectLocale<Context extends NuxtApp = NuxtApp>(
route: string | Route | RouteLocationNormalized | RouteLocationNormalizedLoaded,
context: any,
routeLocaleGetter: ReturnType<typeof createLocaleFromRouteGetter>,
nuxtI18nOptions: DeepRequired<NuxtI18nOptions<Context>>,
vueI18nOptions: I18nOptions,
Expand All @@ -188,7 +187,6 @@ export function detectLocale<Context extends NuxtApp = NuxtApp>(
} = nuxtI18nOptions.detectBrowserLanguage
? detectBrowserLanguage(
route,
context,
nuxtI18nOptions,
nuxtI18nInternalOptions,
vueI18nOptions,
Expand Down Expand Up @@ -239,7 +237,7 @@ export function detectLocale<Context extends NuxtApp = NuxtApp>(
nuxtI18nOptions.detectBrowserLanguage
)
if (!finalLocale && nuxtI18nOptions.detectBrowserLanguage && nuxtI18nOptions.detectBrowserLanguage.useCookie) {
finalLocale = getLocaleCookie(context, { ...nuxtI18nOptions.detectBrowserLanguage, localeCodes }) || ''
finalLocale = getLocaleCookie({ ...nuxtI18nOptions.detectBrowserLanguage, localeCodes }) || ''
}

__DEBUG__ && console.log('detectLocale: finalLocale last (finalLocale, defaultLocale) -', finalLocale, defaultLocale)
Expand All @@ -253,7 +251,6 @@ export function detectLocale<Context extends NuxtApp = NuxtApp>(

export function detectRedirect<Context extends NuxtApp = NuxtApp>({
route,
context,
targetLocale,
routeLocaleGetter,
nuxtI18nOptions,
Expand All @@ -263,12 +260,12 @@ export function detectRedirect<Context extends NuxtApp = NuxtApp>({
to: Route | RouteLocationNormalized | RouteLocationNormalizedLoaded
from?: Route | RouteLocationNormalized | RouteLocationNormalizedLoaded
}
context: Context
targetLocale: Locale
routeLocaleGetter: ReturnType<typeof createLocaleFromRouteGetter>
nuxtI18nOptions: DeepRequired<NuxtI18nOptions<Context>>
calledWithRouting?: boolean
}): string {
const nuxtApp = useNuxtApp()
const { strategy, differentDomains } = nuxtI18nOptions
__DEBUG__ && console.log('detectRedirect: targetLocale -> ', targetLocale)
__DEBUG__ && console.log('detectRedirect: route -> ', route)
Expand All @@ -292,7 +289,7 @@ export function detectRedirect<Context extends NuxtApp = NuxtApp>({
routeLocaleGetter(route.to) !== targetLocale
) {
// the current route could be 404 in which case attempt to find matching route using the full path
const routePath = context.$switchLocalePath(targetLocale) || context.$localePath(toFullPath, targetLocale)
const routePath = nuxtApp.$switchLocalePath(targetLocale) || nuxtApp.$localePath(toFullPath, targetLocale)
__DEBUG__ && console.log('detectRedirect: calculate routePath -> ', routePath, toFullPath)
if (isString(routePath) && routePath && !isEqual(routePath, toFullPath) && !routePath.startsWith('//')) {
/**
Expand All @@ -314,9 +311,9 @@ export function detectRedirect<Context extends NuxtApp = NuxtApp>({
* let it be processed by the route of the router middleware.
*/
const switchLocalePath = useSwitchLocalePath({
i18n: getComposer(context.$i18n),
i18n: getComposer(nuxtApp.$i18n),
route: route.to,
router: context.$router
router: nuxtApp.$router
})
const routePath = switchLocalePath(targetLocale)
__DEBUG__ && console.log('detectRedirect: calculate domain or ssg routePath -> ', routePath)
Expand Down Expand Up @@ -443,12 +440,11 @@ export function extendPrefixable(differentDomains: boolean) {
// override switch locale path intercepter, support domain
export function extendSwitchLocalePathIntercepter(
differentDomains: boolean,
normalizedLocales: LocaleObject[],
nuxt: NuxtApp
normalizedLocales: LocaleObject[]
): SwitchLocalePathIntercepter {
return (path: string, locale: Locale): string => {
if (differentDomains) {
const domain = getDomainFromLocale(locale, normalizedLocales, nuxt)
const domain = getDomainFromLocale(locale, normalizedLocales)
__DEBUG__ && console.log('extendSwitchLocalePathIntercepter: domain -> ', domain, ' path -> ', path)
if (domain) {
return joinURL(domain, path)
Expand All @@ -461,32 +457,33 @@ export function extendSwitchLocalePathIntercepter(
}
}

export function extendBaseUrl<Context extends NuxtApp = NuxtApp>(
baseUrl: string | BaseUrlResolveHandler<Context>,
options: Pick<Required<NuxtI18nOptions<Context>>, 'differentDomains'> & {
nuxt?: Context
export function extendBaseUrl<Context = NuxtApp>(
baseUrl: string | BaseUrlResolveHandler<NuxtApp>,
options: Pick<Required<NuxtI18nOptions<NuxtApp>>, 'differentDomains'> & {
localeCodeLoader: Locale | LocaleLoader
normalizedLocales: LocaleObject[]
}
): BaseUrlResolveHandler<Context> {
return (context: Context): string => {
return (): string => {
const ctx = useNuxtApp()
const runtimeConfig = useRuntimeConfig()
if (isFunction(baseUrl)) {
const baseUrlResult = baseUrl(context)
const baseUrlResult = baseUrl(ctx)
__DEBUG__ && console.log('baseUrl: using localeLoader function -', baseUrlResult)
return baseUrlResult
}

const { differentDomains, localeCodeLoader, normalizedLocales } = options
const localeCode = isFunction(localeCodeLoader) ? localeCodeLoader() : localeCodeLoader
if (differentDomains && localeCode) {
const domain = getDomainFromLocale(localeCode, normalizedLocales, options.nuxt)
const domain = getDomainFromLocale(localeCode, normalizedLocales)
if (domain) {
__DEBUG__ && console.log('baseUrl: using differentDomains -', domain)
return domain
}
}

const config = context.$config?.public?.i18n as { baseUrl?: string }
const config = runtimeConfig?.public?.i18n as { baseUrl?: string }
if (config?.baseUrl) {
__DEBUG__ && console.log('baseUrl: using runtimeConfig -', config.baseUrl)
return config.baseUrl
Expand Down

0 comments on commit 64fa2f6

Please sign in to comment.