Skip to content

Commit

Permalink
fix(nuxt): prioritise vue app context when available (#20910)
Browse files Browse the repository at this point in the history
  • Loading branch information
danielroe committed May 17, 2023
1 parent f39eb6e commit d2e14b6
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 11 deletions.
23 changes: 12 additions & 11 deletions packages/nuxt/src/app/nuxt.ts
@@ -1,5 +1,5 @@
/* eslint-disable no-use-before-define */
import { getCurrentInstance, reactive } from 'vue'
import { getCurrentInstance, hasInjectionContext, reactive } from 'vue'
import type { App, Ref, VNode, onErrorCaptured } from 'vue'
import type { RouteLocationNormalizedLoaded } from '#vue-router'
import type { HookCallback, Hookable } from 'hookable'
Expand Down Expand Up @@ -435,19 +435,20 @@ export function callWithNuxt<T extends (...args: any[]) => any> (nuxt: NuxtApp |
/**
* Returns the current Nuxt instance.
*/
export function useNuxtApp () {
const nuxtAppInstance = nuxtAppCtx.tryUse()
export function useNuxtApp (): NuxtApp {
let nuxtAppInstance
if (hasInjectionContext()) {
nuxtAppInstance = getCurrentInstance()?.appContext.app.$nuxt
}

nuxtAppInstance = nuxtAppInstance || nuxtAppCtx.tryUse()

if (!nuxtAppInstance) {
const vm = getCurrentInstance()
if (!vm) {
if (process.dev) {
throw new Error('[nuxt] A composable that requires access to the Nuxt instance was called outside of a plugin, Nuxt hook, Nuxt middleware, or Vue setup function. This is probably not a Nuxt bug. Find out more at `https://nuxt.com/docs/guide/concepts/auto-imports#using-vue-and-nuxt-composables`.')
} else {
throw new Error('[nuxt] instance unavailable')
}
if (process.dev) {
throw new Error('[nuxt] A composable that requires access to the Nuxt instance was called outside of a plugin, Nuxt hook, Nuxt middleware, or Vue setup function. This is probably not a Nuxt bug. Find out more at `https://nuxt.com/docs/guide/concepts/auto-imports#using-vue-and-nuxt-composables`.')
} else {
throw new Error('[nuxt] instance unavailable')
}
return vm.appContext.app.$nuxt as NuxtApp
}

return nuxtAppInstance
Expand Down
16 changes: 16 additions & 0 deletions test/basic.test.ts
Expand Up @@ -596,6 +596,22 @@ describe('navigate', () => {
})
})

describe('preserves current instance', () => {
// TODO: reenable when https://github.com/vuejs/core/issues/7733 is resolved
it('should not return getCurrentInstance when there\'s an error in data', async () => {
await fetch('/instance/error')
const html = await $fetch('/instance/next-request')
expect(html).toContain('This should be false: false')
})
// TODO: re-enable when https://github.com/nuxt/nuxt/issues/15164 is resolved
it.skipIf(isWindows)('should not lose current nuxt app after await in vue component', async () => {
const requests = await Promise.all(Array.from({ length: 100 }).map(() => $fetch('/instance/next-request')))
for (const html of requests) {
expect(html).toContain('This should be true: true')
}
})
})

describe('errors', () => {
it('should render a JSON error page', async () => {
const res = await fetch('/error', {
Expand Down
13 changes: 13 additions & 0 deletions test/fixtures/basic/pages/instance/error.vue
@@ -0,0 +1,13 @@
<script lang="ts">
export default defineComponent({
data () {
throw new Error('💀')
}
})
</script>

<template>
<div>
This should not display.
</div>
</template>
14 changes: 14 additions & 0 deletions test/fixtures/basic/pages/instance/next-request.vue
@@ -0,0 +1,14 @@
<script setup>
const nuxtApp = useNuxtApp()
await new Promise(resolve => setTimeout(resolve, 150))
const isSameApp = nuxtApp === useNuxtApp()
if (!isSameApp) {
throw new Error('💀')
}
</script>
<template>
<div>
This should be false: {{ $wasVueAppInstanceWronglyPreserved }}
This should be true: {{ isSameApp }}
</div>
</template>
9 changes: 9 additions & 0 deletions test/fixtures/basic/plugins/context-error.ts
@@ -0,0 +1,9 @@
export default defineNuxtPlugin(() => {
// this should be undefined
const vueApp = getCurrentInstance()
return {
provide: {
wasVueAppInstanceWronglyPreserved: !!vueApp
}
}
})

0 comments on commit d2e14b6

Please sign in to comment.