diff --git a/src/server/create-renderer.js b/src/server/create-renderer.js index 751c68a0..369c4751 100644 --- a/src/server/create-renderer.js +++ b/src/server/create-renderer.js @@ -3,8 +3,7 @@ import RenderStream from './render-stream' import { createRenderFunction } from './render' import { warn } from 'core/util/debug' - -export const MAX_STACK_DEPTH = 1000 +import { createWriteFunction } from './write' export function createRenderer ({ modules = [], @@ -35,28 +34,9 @@ export function createRenderer ({ done: (err: ?Error, res: ?string) => any ): void { let result = '' - let stackDepth = 0 - - const write = (text: string, next: Function) => { - if (write.caching && text) { - write.buffer += text - } + const write = createWriteFunction(text => { result += text - if (stackDepth >= MAX_STACK_DEPTH) { - process.nextTick(() => { - try { next() } catch (e) { - done(e) - } - }) - } else { - stackDepth++ - next() - stackDepth-- - } - } - write.caching = false - write.buffer = '' - + }, done) try { render(component, write, () => { done(null, result) diff --git a/src/server/render-stream.js b/src/server/render-stream.js index a69a1ca2..c3990741 100644 --- a/src/server/render-stream.js +++ b/src/server/render-stream.js @@ -1,7 +1,7 @@ /* @flow */ import stream from 'stream' -import { MAX_STACK_DEPTH } from './create-renderer' +import { createWriteFunction } from './write' /** * Original RenderStream implmentation by Sasha Aickin (@aickin) @@ -25,33 +25,17 @@ export default class RenderStream extends stream.Readable { this.expectedSize = 0 this.stackDepth = 0 - const write = this.write = (text: string, next: Function) => { - if (write.caching && text) { - write.buffer += text - } + this.write = createWriteFunction((text, next) => { const n = this.expectedSize this.buffer += text if (this.buffer.length >= n) { this.next = next this.pushBySize(n) - } else { - // continue rendering until we have enough text to call this.push(). - // sometimes do this as process.nextTick to get out of stack overflows. - if (this.stackDepth >= MAX_STACK_DEPTH) { - process.nextTick(() => { - try { next() } catch (e) { - this.emit('error', e) - } - }) - } else { - this.stackDepth++ - next() - this.stackDepth-- - } + return true // we will decide when to call next } - } - write.caching = false - write.buffer = '' + }, err => { + this.emit('error', err) + }) this.end = () => { // the rendering is finished; we should push out the last of the buffer. diff --git a/src/server/write.js b/src/server/write.js new file mode 100644 index 00000000..24bf33f3 --- /dev/null +++ b/src/server/write.js @@ -0,0 +1,32 @@ +/* @flow */ + +const MAX_STACK_DEPTH = 1000 + +export function createWriteFunction ( + write: Function, + onError: Function +): Function { + let stackDepth = 0 + const cachedWrite = (text, next) => { + if (text && cachedWrite.caching) { + cachedWrite.buffer += text + } + const waitForNext = write(text, next) + if (!waitForNext) { + if (stackDepth >= MAX_STACK_DEPTH) { + process.nextTick(() => { + try { next() } catch (e) { + onError(e) + } + }) + } else { + stackDepth++ + next() + stackDepth-- + } + } + } + cachedWrite.caching = false + cachedWrite.buffer = '' + return cachedWrite +}