From 1eec3cf9b989ab0320034b57c59615241a137189 Mon Sep 17 00:00:00 2001 From: inikulin Date: Tue, 26 Jan 2016 14:02:56 +0300 Subject: [PATCH] Fix #98 with lock approach, to keep ParserStream sync in cases then we don't have async scripts. --- docs/07_version_history.md | 3 +++ lib/parser/stream.js | 26 +++++++++++++++----------- package.json | 2 +- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/docs/07_version_history.md b/docs/07_version_history.md index e6022d0e7..65a4a7868 100644 --- a/docs/07_version_history.md +++ b/docs/07_version_history.md @@ -1,5 +1,8 @@ # Version history +## 2.1.4 + * Fixed: Keep ParserStream sync for the inline scripts (GH [#98](https://github.com/inikulin/parse5/issues/98) follow up). + ## 2.1.3 * Fixed: Synchronously calling resume() leads to crash (GH [#98](https://github.com/inikulin/parse5/issues/98)). diff --git a/lib/parser/stream.js b/lib/parser/stream.js index 297328a42..0b19bba3a 100644 --- a/lib/parser/stream.js +++ b/lib/parser/stream.js @@ -34,6 +34,7 @@ var ParserStream = module.exports = function (options) { this.lastChunkWritten = false; this.writeCallback = null; + this.parserLoopLock = false; /** * The resulting document node. @@ -57,7 +58,7 @@ inherits(ParserStream, WritableStream); ParserStream.prototype._write = function (chunk, encoding, callback) { this.writeCallback = callback; this.parser.tokenizer.write(chunk.toString('utf8'), this.lastChunkWritten); - this.parser._runParsingLoop(this.writeCallback); + this._runParsingLoop(); }; ParserStream.prototype.end = function (chunk, encoding, callback) { @@ -66,6 +67,17 @@ ParserStream.prototype.end = function (chunk, encoding, callback) { }; //Scriptable parser implementation +ParserStream.prototype._runParsingLoop = function () { + // NOTE: This helps avoid reentrant invocation of parsing loop + // in cases then `resume` called synchronously + // (see: https://github.com/inikulin/parse5/issues/98). + if (!this.parserLoopLock) { + this.parserLoopLock = true; + this.parser._runParsingLoop(this.writeCallback); + this.parserLoopLock = false; + } +}; + ParserStream.prototype._resume = function () { if (!this.parser.pausedByScript) throw new Error('Parser was already resumed'); @@ -80,7 +92,7 @@ ParserStream.prototype._resume = function () { //NOTE: keep parsing if we don't wait for the next input chunk if (this.parser.tokenizer.active) - this.parser._runParsingLoop(this.writeCallback); + this._runParsingLoop(); }; ParserStream.prototype._documentWrite = function (html) { @@ -125,16 +137,8 @@ ParserStream.prototype.scriptHandler = function (scriptElement) { * parser.end(''); */ - var parser = this; - // NOTE: emit `script` on next tick so we let parsing - // loop stop spinning due to `pausedByScript` flag. - // This helps avoid reentrant invocation of parsing loop - // in cases then `resume` called synchronously - // (see: https://github.com/inikulin/parse5/issues/98). - process.nextTick(function () { - parser.emit('script', scriptElement, parser._documentWrite, parser._resume); - }); + this.emit('script', scriptElement, this._documentWrite, this._resume); } }; diff --git a/package.json b/package.json index 2b1b818f4..c6520fef6 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "parse5", "description": "WHATWG HTML5 specification-compliant, fast and ready for production HTML parsing/serialization toolset for Node.js", - "version": "2.1.3", + "version": "2.1.4", "author": "Ivan Nikulin (https://github.com/inikulin)", "contributors": [ "Alan Clarke (https://github.com/alanclarke)",