diff --git a/src/client/sandbox/node/document/index.js b/src/client/sandbox/node/document/index.js index 7dcf1a09d..961fbaa3e 100644 --- a/src/client/sandbox/node/document/index.js +++ b/src/client/sandbox/node/document/index.js @@ -17,11 +17,10 @@ export default class DocumentSandbox extends SandboxBase { this.documentWriter = null; } - _isUninitializedIframeWithoutSrc (doc) { - const wnd = doc.defaultView; - const frameElement = getFrameElement(wnd); + _isUninitializedIframeWithoutSrc (win) { + const frameElement = getFrameElement(win); - return wnd !== wnd.top && frameElement && isIframeWithoutSrc(frameElement) && + return win !== win.top && frameElement && isIframeWithoutSrc(frameElement) && !IframeSandbox.isIframeInitialized(frameElement); } @@ -69,7 +68,7 @@ export default class DocumentSandbox extends SandboxBase { const documentSandbox = this; document.open = (...args) => { - const isUninitializedIframe = this._isUninitializedIframeWithoutSrc(document); + const isUninitializedIframe = this._isUninitializedIframeWithoutSrc(window); if (!isUninitializedIframe) this._beforeDocumentCleaned(); @@ -99,7 +98,7 @@ export default class DocumentSandbox extends SandboxBase { const result = nativeMethods.documentClose.apply(document, args); - if (!this._isUninitializedIframeWithoutSrc(document)) + if (!this._isUninitializedIframeWithoutSrc(window)) this._onDocumentClosed(); return result; diff --git a/test/client/fixtures/sandbox/node/document-test.js b/test/client/fixtures/sandbox/node/document-test.js index 174aaac13..5748b3a8e 100644 --- a/test/client/fixtures/sandbox/node/document-test.js +++ b/test/client/fixtures/sandbox/node/document-test.js @@ -4,6 +4,7 @@ var SHADOW_UI_CLASSNAME = hammerhead.get('../shadow-ui/class-name'); var browserUtils = hammerhead.utils.browser; var nativeMethods = hammerhead.nativeMethods; var iframeSandbox = hammerhead.sandbox.iframe; +var Promise = hammerhead.Promise; QUnit.testStart(function () { // NOTE: The 'window.open' method used in QUnit. @@ -494,23 +495,66 @@ if (!browserUtils.isIE) { } test('an iframe should not contain self-removing scripts after document.close (GH-871)', function () { - var iframe = document.createElement('iframe'); + return createTestIframe() + .then(function (iframe) { + var iframeDocument = iframe.contentDocument; - iframe.id = 'test-gh-871'; + iframeDocument.designMode = 'On'; + iframeDocument.open(); + iframeDocument.write(''); + iframeDocument.close(); - document.body.appendChild(iframe); + var selfRemovingScripts = nativeMethods.querySelectorAll.call(iframeDocument, + '.' + SHADOW_UI_CLASSNAME.selfRemovingScript); - var iframeDocument = iframe.contentDocument; + strictEqual(selfRemovingScripts.length, 0); + }); +}); - iframeDocument.designMode = 'on'; - iframeDocument.open(); - iframeDocument.write(''); - iframeDocument.close(); +if (browserUtils.isWebKit) { + test('should not throw an error when document loses context window from defaultView property (GH-1272)', function () { + var wrapRejection = function (fn, reject) { + return function () { + try { + fn.apply(this, arguments); + } + catch (e) { + reject(e); + } + }; + }; - strictEqual(nativeMethods.querySelectorAll.call(document, '.' + SHADOW_UI_CLASSNAME.selfRemovingScript).length, 0); + return new Promise(function (resolve, reject) { + var iframe = document.createElement('iframe'); + var loadEventCount = 0; - iframe.parentNode.removeChild(iframe); -}); + iframe.id = 'test' + Date.now(); + iframe.src = 'javascript:"";'; + iframe.onload = wrapRejection(function () { + var doc = iframe.contentDocument; + + if (!doc.documentElement.innerText) { + setTimeout(wrapRejection(function () { + ++loadEventCount; + + doc.open(); + doc.write('
' + loadEventCount + '
'); + doc.close(); + + if (loadEventCount === 2) + resolve(iframe); + }, reject), 100); + } + }, reject); + + document.body.appendChild(iframe); + }) + .then(function (iframe) { + strictEqual(iframe.contentDocument.documentElement.innerText, '2'); + document.body.removeChild(iframe); + }); + }); +} test('querySelector should return an element if a selector contains the href attribute with hash as a value (GH-922)', function () { var testDiv = document.createElement('div');