| /* |
| * Copyright (C) 2013-2015 Apple Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS |
| * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
| * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A |
| * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| // This namespace is injected into every test page. Its functions are invoked by |
| // InspectorTest methods on the inspector page via a TestHarness subclass. |
| TestPage = {}; |
| TestPage._initializers = []; |
| |
| // Helper scripts like `debugger-test.js` must register their initialization |
| // function with this method so it will be marshalled to the inspector page. |
| TestPage.registerInitializer = function(initializer) |
| { |
| if (typeof initializer === "function") |
| this._initializers.push(initializer.toString()); |
| } |
| |
| // This function is called by the test document's body onload handler. |
| |
| // It initializes the inspector and loads any `*-test.js` helper scripts |
| // into the inspector page context. |
| function runTest() |
| { |
| // Don't try to use testRunner if running through the browser. |
| if (!window.testRunner) |
| return; |
| |
| // Set up the test page before the load event fires. |
| testRunner.dumpAsText(); |
| testRunner.waitUntilDone(); |
| |
| window.internals.setInspectorIsUnderTest(true); |
| testRunner.showWebInspector(); |
| |
| let testFunction = window.test; |
| if (typeof testFunction !== "function") { |
| alert("Failed to send test() because it is not a function."); |
| testRunner.notifyDone(); |
| } |
| |
| function runInitializationMethodsInFrontend(initializersArray) |
| { |
| InspectorTest.testPageDidLoad(); |
| |
| // If the test page reloaded but we started running the test in a previous |
| // navigation, then don't initialize the inspector frontend again. |
| if (InspectorTest.didInjectTestCode) |
| return; |
| |
| for (let initializer of initializersArray) { |
| try { |
| initializer(); |
| } catch (e) { |
| console.error("Exception in test initialization: " + e, e.stack || "(no stack trace)"); |
| InspectorTest.completeTest(); |
| } |
| } |
| } |
| |
| function runTestMethodInFrontend(testFunction) |
| { |
| if (InspectorTest.didInjectTestCode) |
| return; |
| |
| InspectorTest.didInjectTestCode = true; |
| |
| try { |
| testFunction(); |
| } catch (e) { |
| // Using this instead of window.onerror will preserve the stack trace. |
| e.code = testFunction.toString(); |
| InspectorTest.reportUncaughtException(e); |
| } |
| } |
| |
| let initializationCodeString = `(${runInitializationMethodsInFrontend.toString()})([${TestPage._initializers}]);`; |
| let testFunctionCodeString = `(${runTestMethodInFrontend.toString()})(${testFunction.toString()});`; |
| |
| TestPage.evaluateInWebInspector(initializationCodeString); |
| TestPage.evaluateInWebInspector(testFunctionCodeString); |
| } |
| |
| function runTestHTTPS() |
| { |
| if (window.testRunner) { |
| testRunner.dumpAsText(); |
| testRunner.waitUntilDone(); |
| } |
| |
| let url = new URL(document.URL); |
| if (url.protocol !== "https:") { |
| url.protocol = "https:"; |
| url.port = "8443"; |
| window.location.href = url.toString(); |
| return; |
| } |
| |
| runTest(); |
| } |
| |
| TestPage.completeTest = function() |
| { |
| // Don't try to use testRunner if running through the browser. |
| if (!window.testRunner) |
| return; |
| |
| // Close inspector asynchrously in case we want to test tear-down behavior. |
| setTimeout(() => { |
| testRunner.closeWebInspector(); |
| setTimeout(() => { testRunner.notifyDone(); }, 0); |
| }, 0); |
| } |
| |
| // Logs message to unbuffered process stdout, avoiding timeouts. |
| // only be used to debug tests and not to produce normal test output. |
| TestPage.debugLog = function(message) |
| { |
| window.alert(message); |
| } |
| |
| // Use this to dump evaluations that are sent from the TestPage to the InspectorTest page. |
| TestPage.debug = function() |
| { |
| this.dumpInspectorPageEvaluations = true; |
| } |
| |
| TestPage.evaluateInWebInspector = function(code) |
| { |
| if (this.dumpInspectorPageEvaluations) |
| this.debugLog(code); |
| |
| testRunner.evaluateInWebInspector(code); |
| } |
| |
| // Add and clear test output from the results window. |
| TestPage.addResult = function(text) |
| { |
| // For early errors triggered when loading the test page, write to stderr. |
| if (!document.body) { |
| this.debugLog(text); |
| this.completeTest(); |
| } |
| |
| if (!this._resultElement) { |
| this._resultElement = document.createElement("pre"); |
| this._resultElement.id = "output"; |
| document.body.appendChild(this._resultElement); |
| } |
| |
| this._resultElement.append(text, document.createElement("br")); |
| } |
| |
| TestPage.log = TestPage.addResult; |
| |
| TestPage.clearOutput = function() |
| { |
| if (!this._resultElement) |
| return; |
| |
| let output = this._resultElement; |
| while (output.firstChild) |
| output.removeChild(output.firstChild); |
| } |
| |
| TestPage.dispatchEventToFrontend = function(eventName, data) |
| { |
| let dispatchEventCodeString = `InspectorTest.dispatchEventToListeners(${JSON.stringify(eventName)}, ${JSON.stringify(data)});`; |
| this.evaluateInWebInspector(dispatchEventCodeString); |
| }; |
| |
| TestPage.allowUncaughtExceptions = false; |
| TestPage.needToSanitizeUncaughtExceptionURLs = false; |
| |
| TestPage.reportUncaughtException = function(message, url, lineNumber) |
| { |
| if (TestPage.needToSanitizeUncaughtExceptionURLs) { |
| if (typeof url === "string") { |
| let lastSlash = url.lastIndexOf("/"); |
| let lastBackSlash = url.lastIndexOf("\\"); |
| let lastPathSeparator = Math.max(lastSlash, lastBackSlash); |
| if (lastPathSeparator > 0) |
| url = url.substr(lastPathSeparator + 1); |
| } |
| } |
| |
| let result = `Uncaught exception in test page: ${message} [${url}:${lineNumber}]`; |
| TestPage.addResult(result); |
| |
| if (!TestPage.allowUncaughtExceptions) |
| TestPage.completeTest(); |
| } |
| |
| // Catch syntax errors, type errors, and other exceptions. Run this before loading other files. |
| window.onerror = TestPage.reportUncaughtException.bind(TestPage); |