Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Maximum call stack size exceeded in SSR with a v-for with 1000 components #8545

Closed
chinesedfan opened this issue Jul 24, 2018 · 1 comment
Closed
Labels

Comments

@chinesedfan
Copy link

Version

2.5.16

Reproduction link

https://github.com/vuejs/vue

Steps to reproduce

Sorry I failed to visit gist or other online code share platforms.

Just run the following script with Node@8.9.0 and Vue@2.5.16 installed. But in Node@6, it is ok.

process.env.VUE_ENV = 'server'; // very important

const Vue = require('vue');
const renderer = require('vue-server-renderer').createRenderer({
});

Vue.component('c-child', {
    template: '<div class="c-child"></div>'
});

const vueInstance = new Vue({
    template: `<div class="root">
        <c-child v-for="(x, i) in items" :key="i"></c-child>
    </div>`,
    data: {
        items: Array(1000).fill(0)
    }
})

console.log('start to renderToString...');
renderer.renderToString(vueInstance, (error, html) => {
    if (error) {
        console.error(`render error!\n${error.stack}`);
        return;
    }

    console.log('what?!', html)
});

What is expected?

Output the html.

What is actually happening?

render error!
RangeError: Maximum call stack size exceeded
    at insert (timers.js:158:16)
    at Object.exports._unrefActive (timers.js:149:3)
    at WriteStream._unrefTimer (net.js:260:12)
    at WriteStream.Socket._writeGeneric (net.js:723:8)
    at WriteStream.Socket._write (net.js:786:8)
    at doWrite (_stream_writable.js:387:12)
    at writeOrBuffer (_stream_writable.js:373:5)
    at WriteStream.Writable.write (_stream_writable.js:290:11)
    at WriteStream.Socket.write (net.js:704:40)
    at write (console.js:108:12)

Someone used to mention this bug but without reproduction, #5445.

@posva posva added the bug label Aug 4, 2018
@posva posva changed the title Maximum call stack size exceeded in Node@8 SSR Maximum call stack size exceeded in SSR with a v-for with 1000 components Aug 4, 2018
@kikuchan
Copy link

kikuchan commented Oct 1, 2018

I've found that RenderContext.next calls itself recursively casuses this bug.
The bug is gone by converting the recursive calls to loop style.

But as you can see noted below, a recursive call still remains.
I'm not sure this is the best way to solve the issue, but it works at least for the simple case (1000 components).

(break indents intentionally to illustrate the strategy)

--- src/server/render-context.js.old    2018-10-01 14:29:09.647066000 +0900
+++ src/server/render-context.js        2018-10-01 14:37:53.207549000 +0900
@@ -66,6 +66,7 @@
   }

   next () {
+    while (true) {
     const lastState = this.renderStates[this.renderStates.length - 1]
     if (isUndef(lastState)) {
       return this.done()
@@ -81,15 +82,14 @@
           this.renderStates.pop()
           if (lastState.type === 'Element') {
             this.write(lastState.endTag, this.next)
-          } else {
-            this.next()
+            // a recursive call still remains here
+            return
           }
         }
         break
       case 'Component':
         this.renderStates.pop()
         this.activeInstance = lastState.prevActive
-        this.next()
         break
       case 'ComponentWithCache':
         this.renderStates.pop()
@@ -112,9 +112,9 @@
         }
         buffer.length = bufferIndex
         componentBuffer.length = bufferIndex
-        this.next()
         break
     }
+    }
   }
 }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants