| <!DOCTYPE html> |
| <html> |
| <head> |
| <title>JSFormatter Tool</title> |
| <link rel="stylesheet" href="../../UserInterface/External/CodeMirror/codemirror.css"> |
| <link rel="stylesheet" href="codemirror-additions.css"> |
| <script src="../../UserInterface/External/CodeMirror/codemirror.js"></script> |
| <script src="../../UserInterface/External/CodeMirror/javascript.js"></script> |
| |
| <script src="../../UserInterface/External/Esprima/esprima.js"></script> |
| <script src="../../UserInterface/Workers/Formatter/FormatterContentBuilder.js"></script> |
| <script src="../../UserInterface/Workers/Formatter/FormatterUtilities.js"></script> |
| <script src="../../UserInterface/Workers/Formatter/ESTreeWalker.js"></script> |
| <script src="../../UserInterface/Workers/Formatter/JSFormatter.js"></script> |
| <script src="JSFormatterDebug.js"></script> |
| </head> |
| <body> |
| <h1>Debug JSFormatter</h1> |
| |
| <!-- Controls --> |
| <button id="populate">Populate</button> |
| <select id="load-individual-test"><option>-- Load Test --</option></select> |
| <small> |
| <label><input id="program" type="radio" name="program-or-module"> Program</label> |
| <label><input id="module" type="radio" name="program-or-module" checked> Module</label> |
| </small> |
| <button id="run-tests">Run All Tests</button> |
| <button id="clear">Clear</button> |
| <button id="select-output">Select Output</button> |
| <button id="run-again">Run Again</button> |
| <button id="save-as-url">Save URL</button> |
| <small id="time"></small> |
| <br><br> |
| |
| <!-- Editor --> |
| <textarea id="code" name="code"></textarea> |
| |
| <!-- Output --> |
| <pre id="pretty"></pre> |
| <pre id="debug"></pre> |
| |
| <script> |
| const testURLPrefix = "../../../../LayoutTests/inspector/formatting/resources/javascript-tests/"; |
| |
| let tests = [ |
| "if-statement.js", |
| "import.js", |
| "for-statements.js", |
| "while-statement.js", |
| "do-while-statement.js", |
| "try-catch-finally-statements.js", |
| "switch-case-default.js", |
| "object-array-literal.js", |
| "unary-binary-expressions.js", |
| "logic-expressions.js", |
| "ternary-expressions.js", |
| "new-expression.js", |
| "numbers.js", |
| "label-break-continue-block.js", |
| "with-statement.js", |
| "return-statement.js", |
| "other-statements.js", |
| "variable-declaration.js", |
| "functions.js", |
| "classes.js", |
| "arrow-functions.js", |
| "generators.js", |
| "comments-and-preserve-newlines.js", |
| "comments-only.js", |
| "template-strings.js", |
| "sample-webinspector-object.js", |
| "sample-normal-utilities.js", |
| "sample-jquery.js", |
| "modules.js", |
| ]; |
| |
| // Initial values from URL. |
| let queryParams = {}; |
| if (window.location.search.length > 0) { |
| let searchString = window.location.search.substring(1); |
| let groups = searchString.split("&"); |
| for (let i = 0; i < groups.length; ++i) { |
| let pair = groups[i].split("="); |
| queryParams[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]); |
| } |
| } |
| |
| // Initial content. |
| let content = "(function(){let a=1;return a+1;})();"; |
| if (queryParams.content) |
| content = queryParams.content || ""; |
| if (queryParams.program) |
| document.getElementById("program").checked = true; |
| |
| // Setup CodeMirror. |
| let cm = CodeMirror.fromTextArea(document.getElementById("code"), {lineNumbers: true}); |
| cm.setValue(content); |
| cm.setOption("mode", "text/javascript"); |
| |
| // Populate button to populate with some canned content. |
| document.getElementById("populate").addEventListener("click", function(event) { |
| loadIndividualTest("sample-jquery.js"); |
| }); |
| |
| // Fill the individual tests button. |
| let testSelectElement = document.getElementById("load-individual-test"); |
| testSelectElement.addEventListener("change", function(event) { |
| let selectedOption = testSelectElement.selectedOptions[0]; |
| let test = selectedOption.value; |
| loadIndividualTest(test); |
| testSelectElement.selectedIndex = 0; |
| }); |
| |
| // Load up the known tests. |
| for (let test of tests) { |
| let option = testSelectElement.appendChild(document.createElement("option")); |
| option.textContent = test; |
| option.value = test; |
| } |
| |
| // Program / Module checkboxes. |
| let programCheckbox = document.getElementById("program"); |
| let moduleCheckbox = document.getElementById("module"); |
| programCheckbox.addEventListener("change", refresh); |
| moduleCheckbox.addEventListener("change", refresh); |
| |
| // Run Tests button. |
| document.getElementById("run-tests").addEventListener("click", function(event) { |
| cm.setValue("/* Running Tests... */"); |
| refresh(); |
| runAllTests(); |
| }); |
| |
| // Clear button. |
| document.getElementById("clear").addEventListener("click", function(event) { |
| cm.setValue(""); |
| refresh(); |
| }); |
| |
| // Select output button. |
| document.getElementById("select-output").addEventListener("click", function(event) { |
| let range = document.createRange(); |
| range.selectNodeContents(document.getElementById("pretty")); |
| let selection = window.getSelection(); |
| selection.removeAllRanges(); |
| selection.addRange(range); |
| }); |
| |
| // Run again button. |
| document.getElementById("run-again").addEventListener("click", function(event) { |
| refresh(); |
| }); |
| |
| // Save as URL button. |
| document.getElementById("save-as-url").addEventListener("click", function(event) { |
| let content = cm.getValue(); |
| let queryString = "?content=" + window.encodeURIComponent(content); |
| if (programCheckbox.checked) |
| queryString += "&program"; |
| window.location.search = queryString; |
| }); |
| |
| // Refresh after changes after a short delay. |
| let timer = null; |
| cm.on("change", function(codeMirror, change) { |
| if (timer) |
| clearTimeout(timer) |
| timer = setTimeout(function() { |
| clearTimeout(timer); |
| timer = null; |
| refresh(); |
| }, 500); |
| }); |
| |
| // Output elements. |
| let timeOutput = document.getElementById("time"); |
| let prettyPre = document.getElementById("pretty"); |
| let debugPre = document.getElementById("debug"); |
| |
| // Current value of checkboxes. |
| function currentSourceType() { |
| if (programCheckbox.checked) |
| return JSFormatter.SourceType.Script; |
| if (moduleCheckbox.checked) |
| return JSFormatter.SourceType.Module; |
| console.assert(false, "Program or Module radio button should be checked"); |
| return undefined; |
| } |
| |
| function refresh() { |
| if (timer) |
| clearTimeout(timer); |
| |
| // Time the formatter. |
| let startTime = Date.now(); |
| let formatter = new JSFormatter(cm.getValue(), currentSourceType()); |
| let endTime = Date.now(); |
| |
| // Show debug info. |
| let debugText; |
| try { |
| let debugFormatter = new JSFormatterDebug(cm.getValue(), currentSourceType()); |
| debugText = debugFormatter.debugText; |
| } catch (error) { |
| debugText = "Parse error: " + JSON.stringify(error, null, 2); |
| } |
| |
| // Output the results. |
| timeOutput.innerText = (endTime - startTime) + "ms"; |
| prettyPre.innerText = formatter.formattedText; |
| debugPre.innerText = debugText; |
| } |
| |
| setTimeout(refresh); |
| |
| // Testing. |
| |
| function isModuleTest(test) { |
| return test === "modules.js"; |
| } |
| |
| function loadIndividualTest(test) { |
| let testURL = testURLPrefix + test; |
| let xhr = new XMLHttpRequest; |
| xhr.open("GET", testURL, true); |
| xhr.onload = () => { cm.setValue(xhr.responseText); setTimeout(refresh); } |
| xhr.send(); |
| |
| if (isModuleTest(test)) |
| moduleCheckbox.checked = true; |
| else |
| programCheckbox.checked = true; |
| } |
| |
| function runAllTests() { |
| let index = -1; |
| let results = []; |
| setTimeout(runNextTest, 0); |
| |
| function runNextTest() { |
| // Next test. |
| index++; |
| |
| // Done. |
| if (index >= tests.length) { |
| printResults(); |
| return; |
| } |
| |
| // Load test and expected results. |
| let test = tests[index]; |
| let testURL = testURLPrefix + test; |
| let expectedURL = testURL.replace(/\.([^\.]+)$/, "-expected.$1"); |
| let xhr1 = new XMLHttpRequest; |
| xhr1.open("GET", testURL, false); |
| xhr1.send(); |
| let xhr2 = new XMLHttpRequest; |
| xhr2.open("GET", expectedURL, false); |
| xhr2.send(); |
| let testData = xhr1.responseText; |
| let expectedData = xhr2.responseText; |
| |
| // Run the test. |
| let sourceType = isModuleTest(test) ? JSFormatter.SourceType.Module : JSFormatter.SourceType.Script; |
| let formatter = new JSFormatter(testData, sourceType); |
| |
| // Compare results. |
| let pass = formatter.formattedText === expectedData; |
| results.push("/* " + (pass ? "PASS" : "!! FAIL") + ": " + test + " */"); |
| |
| // Output failures to console. |
| if (!pass) { |
| console.log("Test", test); |
| console.log("Formatted Output", formatter.formattedText ? formatter.formattedText.length : null); |
| console.log(formatter.formattedText); |
| console.log("Expected Output", expectedData.length); |
| console.log(expectedData); |
| } |
| |
| runNextTest(); |
| } |
| |
| function printResults() { |
| cm.setValue(results.join("\n")); |
| cm.refresh(); |
| } |
| } |
| </script> |
| </body> |
| </html> |