Suspense issues withAsyncContext called without active current instance
Vue version
3.2.45
Link to minimal reproduction
Steps to reproduce
Wrap a Suspense tag around a component with a top-level await.
What is expected?
The Suspense will render the #fallback element, and render the #default element once its Promise is resolved.
What is actually happening?
Neither the parent nor the child component are rendered. I receive an error
withAsyncContext called without active current instance. This is likely a bug.
System Info
System:
OS: Windows 10 10.0.22621
CPU: (8) x64 Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz
Memory: 5.37 GB / 15.71 GB
Binaries:
Node: 18.7.0 - C:\Program Files\nodejs\node.EXE
Yarn: 3.3.0 - C:\Program Files\nodejs\yarn.CMD
npm: 8.19.1 - C:\Program Files\nodejs\npm.CMD
Browsers:
Edge: Spartan (44.22621.819.0), Chromium (108.0.1462.54)
Internet Explorer: 11.0.22621.1
npmPackages:
vue: ^3.2.45 => 3.2.45
Any additional comments?
{
"vue": "^3.2.45",
"typescript": "^4.9.3",
"vite": "^4.0.0",
"vue-router": "^4.1.6",
"vue-tsc": "^1.0.11"
}
Just to make sure: Are you seeing this exact problem in an App? or just in the playground? Is your app using SSR? Is it Nuxt?
Because in the playground, the error goes away when you disable "SSR" in the upper right.
I am seeing the issue in #7393 in my app. The app is using SSR and not using Nuxt. When I replicate the problem area in the playground, I am getting a similar but different issue as described in this bug. Strangely enough, in the playground example, nothing even renders for me (SSR on or off) unless:
- I remove the await from the
Comp.vue
. Content renders as expected. - I remove the
Suspense
fromApp.vue
and just leave the placeholder tr and contents. This will then render what was in the now-deletedSuspense #default
block with the correct content from thev-for
.
My mistake, I missed the resolve in the playground. I have updated that which can be found in this playground.
After the resolution fix, when SSR is off this renders correctly without errors. However, with SSR enabled I receive the following errors and nothing is rendered. Why might that be the case when using this with Suspense?
It's likely just a bug in the playground, which had to mind of stimulate the Server side step, as it all runs in the client.
I have found the cause of the problem. The vue.runtime.esm-browser.js
and server-renderer.esm-browser.js
modules contain some of the same code, as shown below:
let currentInstance = null;
const setCurrentInstance = (instance) => {
currentInstance = instance;
instance.scope.on();
};
const unsetCurrentInstance = () => {
currentInstance && currentInstance.scope.off();
currentInstance = null;
};
Because renderToString
is run in the server-renderer.esm-browser.js
module and updates the value of currentInstance
when it runs, it is not possible to access this value in the vue.runtime.esm-browser.js
module because they belong to different module scopes. Therefore, when the getCurrentInstance
function is run in the vue.runtime.esm-browser.js
module, it cannot get the correct value, which leads to this bug.
I have found the cause of the problem. The
vue.runtime.esm-browser.js
andserver-renderer.esm-browser.js
modules contain some of the same code, as shown below:let currentInstance = null; const setCurrentInstance = (instance) => { currentInstance = instance; instance.scope.on(); }; const unsetCurrentInstance = () => { currentInstance && currentInstance.scope.off(); currentInstance = null; };
Because
renderToString
is run in theserver-renderer.esm-browser.js
module and updates the value ofcurrentInstance
when it runs, it is not possible to access this value in thevue.runtime.esm-browser.js
module because they belong to different module scopes. Therefore, when thegetCurrentInstance
function is run in thevue.runtime.esm-browser.js
module, it cannot get the correct value, which leads to this bug.
#7672 Is this the same cause causing the problem?