Skip to content

Commit

Permalink
Fix #98 with lock approach, to keep ParserStream sync in cases then w…
Browse files Browse the repository at this point in the history
…e don't have async scripts.
  • Loading branch information
inikulin committed Jan 26, 2016
1 parent 99b9494 commit 1eec3cf
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 12 deletions.
3 changes: 3 additions & 0 deletions docs/07_version_history.md
Original file line number Diff line number Diff line change
@@ -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)).

Expand Down
26 changes: 15 additions & 11 deletions lib/parser/stream.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ var ParserStream = module.exports = function (options) {

this.lastChunkWritten = false;
this.writeCallback = null;
this.parserLoopLock = false;

/**
* The resulting document node.
Expand All @@ -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) {
Expand All @@ -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');
Expand All @@ -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) {
Expand Down Expand Up @@ -125,16 +137,8 @@ ParserStream.prototype.scriptHandler = function (scriptElement) {
* parser.end('<script src="example.com/script.js"></script>');
*/

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);
}
};

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -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 <ifaaan@gmail.com> (https://github.com/inikulin)",
"contributors": [
"Alan Clarke (https://github.com/alanclarke)",
Expand Down

0 comments on commit 1eec3cf

Please sign in to comment.