diff --git a/lib/jsdom/browser/parser/html.js b/lib/jsdom/browser/parser/html.js index 8caf0bb4e1..10521ef42f 100644 --- a/lib/jsdom/browser/parser/html.js +++ b/lib/jsdom/browser/parser/html.js @@ -16,6 +16,34 @@ const OpenElementStack = require("parse5/lib/parser/open-element-stack"); const OpenElementStackOriginalPop = OpenElementStack.prototype.pop; const OpenElementStackOriginalPush = OpenElementStack.prototype.push; +// Horrible monkey-patch to implement https://github.com/inikulin/parse5/issues/237 +function wrapOpenElementStack(adapter) { + OpenElementStack.prototype.push = function (...args) { + OpenElementStackOriginalPush.apply(this, args); + adapter._currentElement = this.current; + + const after = this.items[this.stackTop]; + if (after._pushedOnStackOfOpenElements) { + after._pushedOnStackOfOpenElements(); + } + }; + OpenElementStack.prototype.pop = function (...args) { + const before = this.items[this.stackTop]; + + OpenElementStackOriginalPop.apply(this, args); + adapter._currentElement = this.current; + + if (before._poppedOffStackOfOpenElements) { + before._poppedOffStackOfOpenElements(); + } + }; +} + +function unwrapOpenElementStack() { + OpenElementStack.prototype.pop = OpenElementStackOriginalPop; + OpenElementStack.prototype.push = OpenElementStackOriginalPush; +} + class JSDOMParse5Adapter { constructor(documentImpl) { this._documentImpl = documentImpl; @@ -24,28 +52,6 @@ class JSDOMParse5Adapter { // Since the createElement hook doesn't provide the parent element, we keep track of this using _currentElement: // https://github.com/inikulin/parse5/issues/285 this._currentElement = undefined; - - // Horrible monkey-patch to implement https://github.com/inikulin/parse5/issues/237 - const adapter = this; - OpenElementStack.prototype.push = function (...args) { - OpenElementStackOriginalPush.apply(this, args); - adapter._currentElement = this.current; - - const after = this.items[this.stackTop]; - if (after._pushedOnStackOfOpenElements) { - after._pushedOnStackOfOpenElements(); - } - }; - OpenElementStack.prototype.pop = function (...args) { - const before = this.items[this.stackTop]; - - OpenElementStackOriginalPop.apply(this, args); - adapter._currentElement = this.current; - - if (before._poppedOffStackOfOpenElements) { - before._poppedOffStackOfOpenElements(); - } - }; } _ownerDocument() { @@ -165,7 +171,12 @@ function parseFragment(markup, contextElement) { treeAdapter: new JSDOMParse5Adapter(ownerDocument) }); - return parse5.parseFragment(contextElement, markup, config); + wrapOpenElementStack(config.treeAdapter); + try { + return parse5.parseFragment(contextElement, markup, config); + } finally { + unwrapOpenElementStack(); + } } function parseIntoDocument(markup, ownerDocument) { @@ -173,7 +184,12 @@ function parseIntoDocument(markup, ownerDocument) { treeAdapter: new JSDOMParse5Adapter(ownerDocument) }); - return parse5.parse(markup, config); + wrapOpenElementStack(config.treeAdapter); + try { + return parse5.parse(markup, config); + } finally { + unwrapOpenElementStack(); + } } module.exports = {