Changeset 249831 in webkit


Ignore:
Timestamp:
Sep 13, 2019 3:05:36 AM (5 years ago)
Author:
Joseph Pecoraro
Message:

Web Inspector: Formatter: Pretty Print HTML resources (including inline <script>/<style>)
https://bugs.webkit.org/show_bug.cgi?id=201535
<rdar://problem/29119232>

Reviewed by Devin Rousso.

Source/JavaScriptCore:

  • debugger/Debugger.cpp:

(JSC::Debugger::resolveBreakpoint):
When resolving a breakpoint inside of an inline <script> we need to adjust
based on the starting position of the <script> in the HTML resource.

Source/WebInspectorUI:

Introduce HTMLFormatter, HTMLParser, and HTMLTreeBuilderFormatter.

  • HTMLParser tokenizes HTML content and passes it to a tree builder.
  • HTMLTreeBuilderFormatter uses those tokens to create a formatted dom tree of fake nodes.
  • HTMLFormatter then builds formatted content and a FormatterSourceMap from that DOM tree.

The output of HTMLFormatter is intended to just modify whitespace. So it won't be a
100% compatible DOM, but will be useful for debugging and reading inline <style>
and <script>, which is a more common debugging scenario. It also maintains original
author attribute quotations or lack therefore, because again it tries to only
change whitespace. A separate tree builder could be used for tidying content.

This introduces a few tools for working with formatting:

  • Tools/HTMLFormatter - debug the parser, tree builder, and output format
  • Tools/SourceMaps - debug formatted content and source mappings

This also:

  • renames "EsprimaFormatter" to "JSFormatter"
  • eliminates an extra trailing newline in CSSFormatter output
  • Tools/HTMLFormatter/HTMLTreeBuilderDebug.js: Added.
  • Tools/HTMLFormatter/index.html: Added.
  • Tools/HTMLFormatter/styles.css: Added.

Tool for debugging the HTML formatter components.

  • Tools/SourceMaps/.gitignore: Added.
  • Tools/SourceMaps/index.html: Added.
  • Tools/SourceMaps/setup.sh: Added.
  • Tools/SourceMaps/styles.css: Added.

Tool for debugging Formatter generated Source Maps.

  • Tools/JSFormatter/JSFormatterDebug.js: Renamed from Source/WebInspectorUI/Tools/Formatting/EsprimaFormatterDebug.js.
  • Tools/JSFormatter/codemirror-additions.css: Renamed from Source/WebInspectorUI/Tools/Formatting/codemirror-additions.css.
  • Tools/JSFormatter/index.html: Renamed from Source/WebInspectorUI/Tools/Formatting/index.html.

Renamed this tool. EsprimaFormatter => JSFormatter.

  • UserInterface/Controllers/FormatterSourceMap.js:

(WI.FormatterSourceMap.prototype.originalPositionToFormattedPosition):
(WI.FormatterSourceMap.prototype.formattedPositionToOriginalPosition):
New APIs used by tools and tests for translating "position" offsets and not line/columns.

  • UserInterface/Workers/Formatter/JSFormatter.js: Renamed from Source/WebInspectorUI/UserInterface/Workers/Formatter/EsprimaFormatter.js.

(JSFormatter):

  • UserInterface/Workers/Formatter/CSSFormatter.js:

(CSSFormatter):
Allow using a supplied builder, which is useful when formatting
inline content from HTMLFormatter (<style> / <script>).

  • UserInterface/Workers/Formatter/FormatterContentBuilder.js:

(FormatterContentBuilder.prototype.get indentString):
(FormatterContentBuilder.prototype.get originalContent):
(FormatterContentBuilder.prototype.get indentLevel):
(FormatterContentBuilder.prototype.get originalOffset):
(FormatterContentBuilder.prototype.set originalOffset):
(FormatterContentBuilder.prototype.appendNonToken):
(FormatterContentBuilder.prototype.appendToken):
(FormatterContentBuilder.prototype.appendTokenWithPossibleNewlines):
(FormatterContentBuilder.prototype.appendMapping):
(FormatterContentBuilder.prototype.indentToLevel):
(FormatterContentBuilder.prototype.finish):
Provide API for getting / setting the original offset and indent level.
This is useful when the HTMLFormatter runs the CSSFormatter/JSFormatter
in a nested context (<style> / <script>). Add a few more APIs for
conveniences when appending tokens or important positions.

  • UserInterface/Workers/Formatter/HTMLParser.js: Added.

(HTMLParser.prototype.parseDocument):
(HTMLParser.prototype._isEOF):
(HTMLParser.prototype._peek):
(HTMLParser.prototype._peekCharacterRegex):
(HTMLParser.prototype._peekString):
(HTMLParser.prototype._peekCaseInsensitiveString):
(HTMLParser.prototype._consumeWhitespace):
(HTMLParser.prototype._consumeUntilString):
(HTMLParser.prototype._consumeUntilRegex):
(HTMLParser.prototype._consumeDoubleQuotedString):
(HTMLParser):
Tokenize HTML content into nodes.

  • UserInterface/Workers/Formatter/HTMLTreeBuilderFormatter.js: Added.

(HTMLTreeBuilderFormatter.prototype.get dom):
(HTMLTreeBuilderFormatter.prototype.begin):
(HTMLTreeBuilderFormatter.prototype.pushParserNode):
(HTMLTreeBuilderFormatter.prototype.end):
(HTMLTreeBuilderFormatter.prototype._pushParserNodeTopLevel):
(HTMLTreeBuilderFormatter.prototype._pushParserNodeStack):
(HTMLTreeBuilderFormatter.prototype._isEmptyNode):
(HTMLTreeBuilderFormatter.prototype._buildDOMNodeFromOpenTag):
(HTMLTreeBuilderFormatter.prototype._buildErrorNodeFromCloseTag):
(HTMLTreeBuilderFormatter.prototype._buildSimpleNodeFromParserNode):
(HTMLTreeBuilderFormatter):
Build a simple DOM tree from parser nodes.

  • UserInterface/Workers/Formatter/HTMLFormatter.js: Added.

(HTMLFormatter.let.dom):
(HTMLFormatter):
(HTMLFormatter.prototype.get success):
(HTMLFormatter.prototype.get formattedText):
(HTMLFormatter.prototype.get sourceMapData):
(HTMLFormatter.prototype._walk):
(HTMLFormatter.prototype._walkChildren):
(HTMLFormatter.prototype._isNodeSelfClosing):
(HTMLFormatter.prototype._shouldHaveInlineContent):
(HTMLFormatter.prototype._hasMultipleNewLines):
(HTMLFormatter.prototype._buildAttributeString):
(HTMLFormatter.prototype._before):
(HTMLFormatter.prototype._after):
(HTMLFormatter.prototype._formatWithNestedFormatter):
(HTMLFormatter.prototype._formatScript):
(HTMLFormatter.prototype._formatStyle):
Output pretty printed text from a HTMLTreeBuilderFormatter dom tree.

  • UserInterface/Proxies/FormatterWorkerProxy.js:

(WI.FormatterWorkerProxy.prototype.formatHTML):

  • UserInterface/Workers/Formatter/FormatterWorker.js:

(FormatterWorker.prototype.formatJavaScript):
(FormatterWorker.prototype.formatCSS):
(FormatterWorker.prototype.formatHTML):

  • UserInterface/Views/TextEditor.js:

(WI.TextEditor.prototype.hasFormatter):
(WI.TextEditor.prototype._canUseFormatterWorker):
(WI.TextEditor.prototype._startWorkerPrettyPrint):
Allow pretty printing HTML resources.

  • UserInterface/Main.html:
  • UserInterface/Test.html:

New resources.

LayoutTests:

Mark slow test.

  • inspector/formatting/formatting-css.html:
  • inspector/formatting/formatting-html-expected.txt: Added.
  • inspector/formatting/formatting-html.html: Added.
  • inspector/formatting/formatting-javascript-expected.txt:
  • inspector/formatting/formatting-javascript.html:
  • inspector/formatting/formatting-json-expected.txt:
  • inspector/formatting/formatting-json.html:
  • inspector/formatting/resources/formatting-utilities.js: Renamed from LayoutTests/inspector/formatting/resources/utilities.js.

Update formatting tests to use new path to utilities.

  • inspector/formatting/resources/css-tests/basic-expected.css:
  • inspector/formatting/resources/css-tests/gradient-expected.css:
  • inspector/formatting/resources/css-tests/keyframes-expected.css:
  • inspector/formatting/resources/css-tests/media-query-expected.css:
  • inspector/formatting/resources/css-tests/selectors-expected.css:
  • inspector/formatting/resources/css-tests/wrapping-expected.css:
  • inspector/codemirror/resources/prettyprinting/css-tests/basic-expected.css:
  • inspector/codemirror/resources/prettyprinting/css-tests/calc-expected.css:
  • inspector/codemirror/resources/prettyprinting/css-tests/gradient-expected.css:
  • inspector/codemirror/resources/prettyprinting/css-tests/keyframes-expected.css:
  • inspector/codemirror/resources/prettyprinting/css-tests/media-query-expected.css:
  • inspector/codemirror/resources/prettyprinting/css-tests/selectors-expected.css:
  • inspector/codemirror/resources/prettyprinting/css-tests/wrapping-expected.css:

Eliminate an extra trailing newline in CSS formatted results.

  • inspector/formatting/resources/html-tests/attributes-expected.html: Added.
  • inspector/formatting/resources/html-tests/attributes.html: Added.
  • inspector/formatting/resources/html-tests/auto-close-expected.html: Added.
  • inspector/formatting/resources/html-tests/auto-close.html: Added.
  • inspector/formatting/resources/html-tests/basic-1-expected.html: Added.
  • inspector/formatting/resources/html-tests/basic-1.html: Added.
  • inspector/formatting/resources/html-tests/basic-2-expected.html: Added.
  • inspector/formatting/resources/html-tests/basic-2.html: Added.
  • inspector/formatting/resources/html-tests/comments-expected.html: Added.
  • inspector/formatting/resources/html-tests/comments.html: Added.
  • inspector/formatting/resources/html-tests/eof-1-expected.html: Added.
  • inspector/formatting/resources/html-tests/eof-1.html: Added.
  • inspector/formatting/resources/html-tests/eof-2-expected.html: Added.
  • inspector/formatting/resources/html-tests/eof-2.html: Added.
  • inspector/formatting/resources/html-tests/eof-3-expected.html: Added.
  • inspector/formatting/resources/html-tests/eof-3.html: Added.
  • inspector/formatting/resources/html-tests/eof-4-expected.html: Added.
  • inspector/formatting/resources/html-tests/eof-4.html: Added.
  • inspector/formatting/resources/html-tests/eof-5-expected.html: Added.
  • inspector/formatting/resources/html-tests/eof-5.html: Added.
  • inspector/formatting/resources/html-tests/eof-6-expected.html: Added.
  • inspector/formatting/resources/html-tests/eof-6.html: Added.
  • inspector/formatting/resources/html-tests/inline-script-expected.html: Added.
  • inspector/formatting/resources/html-tests/inline-script.html: Added.
  • inspector/formatting/resources/html-tests/inline-style-expected.html: Added.
  • inspector/formatting/resources/html-tests/inline-style.html: Added.
  • inspector/formatting/resources/html-tests/list-expected.html: Added.
  • inspector/formatting/resources/html-tests/list.html: Added.
  • inspector/formatting/resources/html-tests/not-well-formed-1-expected.html: Added.
  • inspector/formatting/resources/html-tests/not-well-formed-1.html: Added.
  • inspector/formatting/resources/html-tests/not-well-formed-2-expected.html: Added.
  • inspector/formatting/resources/html-tests/not-well-formed-2.html: Added.
  • inspector/formatting/resources/html-tests/not-well-formed-3-expected.html: Added.
  • inspector/formatting/resources/html-tests/not-well-formed-3.html: Added.
  • inspector/formatting/resources/html-tests/self-closing-expected.html: Added.
  • inspector/formatting/resources/html-tests/self-closing.html: Added.

HTMLFormatter tests.

  • inspector/formatting/resources/html-source-map-tests/1.html: Added.
  • inspector/formatting/resources/html-source-map-tests/2.html: Added.
  • inspector/formatting/resources/css-source-map-tests/1.css: Added.
  • inspector/formatting/resources/javascript-source-map-tests/1.js: Added.
  • inspector/formatting/source-map-css-1-expected.txt: Added.
  • inspector/formatting/source-map-css-1.html: Added.
  • inspector/formatting/source-map-html-1-expected.txt: Added.
  • inspector/formatting/source-map-html-1.html: Added.
  • inspector/formatting/source-map-html-2-expected.txt: Added.
  • inspector/formatting/source-map-html-2.html: Added.
  • inspector/formatting/source-map-javascript-1-expected.txt: Added.
  • inspector/formatting/source-map-javascript-1.html: Added.
  • inspector/formatting/resources/source-map-utilities.js: Added.

(TestPage.registerInitializer.logLocationWithContext):
(TestPage.registerInitializer.async.runSourceMapTest):
(TestPage.registerInitializer.):
(TestPage.registerInitializer.async.loadFormattedContentAndSourceMap):
(TestPage.registerInitializer.async.loadSourceMapTestResource):
(TestPage.registerInitializer.window.addSourceMapTest):
(TestPage.registerInitializer):
New formatter source map tests to ensure we can go back and forth reasonably
between formatted content and original content.

  • inspector/debugger/breakpoints/resolved-dump-all-inline-script-pause-locations-expected.txt: Added.
  • inspector/debugger/breakpoints/resolved-dump-all-inline-script-pause-locations.html: Added.
  • inspector/debugger/breakpoints/resources/dump-inline-scripts.html: Added.
  • inspector/debugger/breakpoints/resources/dump.js:

(TestPage.registerInitializer.window.addDumpAllPauseLocationsTestCase):
(TestPage.registerInitializer.addDumpAllPauseLocationsTestCaseForScript):
(TestPage.registerInitializer):

  • inspector/debugger/resources/log-pause-location.js:

(TestPage.registerInitializer.window.findScript):
(TestPage.registerInitializer.window.findResource):
Test for resolving breakpoints at column locations in <script> which was
not previously possible and would not have worked previously.

Location:
trunk
Files:
71 added
1 deleted
33 edited
3 copied
2 moved

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r249819 r249831  
     12019-09-13  Joseph Pecoraro  <pecoraro@apple.com>
     2
     3        Web Inspector: Formatter: Pretty Print HTML resources (including inline <script>/<style>)
     4        https://bugs.webkit.org/show_bug.cgi?id=201535
     5        <rdar://problem/29119232>
     6
     7        Reviewed by Devin Rousso.
     8
     9        * TestExpectations:
     10        Mark slow test.
     11
     12        * inspector/formatting/formatting-css.html:
     13        * inspector/formatting/formatting-html-expected.txt: Added.
     14        * inspector/formatting/formatting-html.html: Added.
     15        * inspector/formatting/formatting-javascript-expected.txt:
     16        * inspector/formatting/formatting-javascript.html:
     17        * inspector/formatting/formatting-json-expected.txt:
     18        * inspector/formatting/formatting-json.html:
     19        * inspector/formatting/resources/formatting-utilities.js: Renamed from LayoutTests/inspector/formatting/resources/utilities.js.
     20        Update formatting tests to use new path to utilities.
     21
     22        * inspector/formatting/resources/css-tests/basic-expected.css:
     23        * inspector/formatting/resources/css-tests/gradient-expected.css:
     24        * inspector/formatting/resources/css-tests/keyframes-expected.css:
     25        * inspector/formatting/resources/css-tests/media-query-expected.css:
     26        * inspector/formatting/resources/css-tests/selectors-expected.css:
     27        * inspector/formatting/resources/css-tests/wrapping-expected.css:
     28        * inspector/codemirror/resources/prettyprinting/css-tests/basic-expected.css:
     29        * inspector/codemirror/resources/prettyprinting/css-tests/calc-expected.css:
     30        * inspector/codemirror/resources/prettyprinting/css-tests/gradient-expected.css:
     31        * inspector/codemirror/resources/prettyprinting/css-tests/keyframes-expected.css:
     32        * inspector/codemirror/resources/prettyprinting/css-tests/media-query-expected.css:
     33        * inspector/codemirror/resources/prettyprinting/css-tests/selectors-expected.css:
     34        * inspector/codemirror/resources/prettyprinting/css-tests/wrapping-expected.css:
     35        Eliminate an extra trailing newline in CSS formatted results.
     36
     37        * inspector/formatting/resources/html-tests/attributes-expected.html: Added.
     38        * inspector/formatting/resources/html-tests/attributes.html: Added.
     39        * inspector/formatting/resources/html-tests/auto-close-expected.html: Added.
     40        * inspector/formatting/resources/html-tests/auto-close.html: Added.
     41        * inspector/formatting/resources/html-tests/basic-1-expected.html: Added.
     42        * inspector/formatting/resources/html-tests/basic-1.html: Added.
     43        * inspector/formatting/resources/html-tests/basic-2-expected.html: Added.
     44        * inspector/formatting/resources/html-tests/basic-2.html: Added.
     45        * inspector/formatting/resources/html-tests/comments-expected.html: Added.
     46        * inspector/formatting/resources/html-tests/comments.html: Added.
     47        * inspector/formatting/resources/html-tests/eof-1-expected.html: Added.
     48        * inspector/formatting/resources/html-tests/eof-1.html: Added.
     49        * inspector/formatting/resources/html-tests/eof-2-expected.html: Added.
     50        * inspector/formatting/resources/html-tests/eof-2.html: Added.
     51        * inspector/formatting/resources/html-tests/eof-3-expected.html: Added.
     52        * inspector/formatting/resources/html-tests/eof-3.html: Added.
     53        * inspector/formatting/resources/html-tests/eof-4-expected.html: Added.
     54        * inspector/formatting/resources/html-tests/eof-4.html: Added.
     55        * inspector/formatting/resources/html-tests/eof-5-expected.html: Added.
     56        * inspector/formatting/resources/html-tests/eof-5.html: Added.
     57        * inspector/formatting/resources/html-tests/eof-6-expected.html: Added.
     58        * inspector/formatting/resources/html-tests/eof-6.html: Added.
     59        * inspector/formatting/resources/html-tests/inline-script-expected.html: Added.
     60        * inspector/formatting/resources/html-tests/inline-script.html: Added.
     61        * inspector/formatting/resources/html-tests/inline-style-expected.html: Added.
     62        * inspector/formatting/resources/html-tests/inline-style.html: Added.
     63        * inspector/formatting/resources/html-tests/list-expected.html: Added.
     64        * inspector/formatting/resources/html-tests/list.html: Added.
     65        * inspector/formatting/resources/html-tests/not-well-formed-1-expected.html: Added.
     66        * inspector/formatting/resources/html-tests/not-well-formed-1.html: Added.
     67        * inspector/formatting/resources/html-tests/not-well-formed-2-expected.html: Added.
     68        * inspector/formatting/resources/html-tests/not-well-formed-2.html: Added.
     69        * inspector/formatting/resources/html-tests/not-well-formed-3-expected.html: Added.
     70        * inspector/formatting/resources/html-tests/not-well-formed-3.html: Added.
     71        * inspector/formatting/resources/html-tests/self-closing-expected.html: Added.
     72        * inspector/formatting/resources/html-tests/self-closing.html: Added.
     73        HTMLFormatter tests.
     74
     75        * inspector/formatting/resources/html-source-map-tests/1.html: Added.
     76        * inspector/formatting/resources/html-source-map-tests/2.html: Added.
     77        * inspector/formatting/resources/css-source-map-tests/1.css: Added.
     78        * inspector/formatting/resources/javascript-source-map-tests/1.js: Added.
     79        * inspector/formatting/source-map-css-1-expected.txt: Added.
     80        * inspector/formatting/source-map-css-1.html: Added.
     81        * inspector/formatting/source-map-html-1-expected.txt: Added.
     82        * inspector/formatting/source-map-html-1.html: Added.
     83        * inspector/formatting/source-map-html-2-expected.txt: Added.
     84        * inspector/formatting/source-map-html-2.html: Added.
     85        * inspector/formatting/source-map-javascript-1-expected.txt: Added.
     86        * inspector/formatting/source-map-javascript-1.html: Added.
     87        * inspector/formatting/resources/source-map-utilities.js: Added.
     88        (TestPage.registerInitializer.logLocationWithContext):
     89        (TestPage.registerInitializer.async.runSourceMapTest):
     90        (TestPage.registerInitializer.):
     91        (TestPage.registerInitializer.async.loadFormattedContentAndSourceMap):
     92        (TestPage.registerInitializer.async.loadSourceMapTestResource):
     93        (TestPage.registerInitializer.window.addSourceMapTest):
     94        (TestPage.registerInitializer):
     95        New formatter source map tests to ensure we can go back and forth reasonably
     96        between formatted content and original content.
     97
     98        * inspector/debugger/breakpoints/resolved-dump-all-inline-script-pause-locations-expected.txt: Added.
     99        * inspector/debugger/breakpoints/resolved-dump-all-inline-script-pause-locations.html: Added.
     100        * inspector/debugger/breakpoints/resources/dump-inline-scripts.html: Added.
     101        * inspector/debugger/breakpoints/resources/dump.js:
     102        (TestPage.registerInitializer.window.addDumpAllPauseLocationsTestCase):
     103        (TestPage.registerInitializer.addDumpAllPauseLocationsTestCaseForScript):
     104        (TestPage.registerInitializer):
     105        * inspector/debugger/resources/log-pause-location.js:
     106        (TestPage.registerInitializer.window.findScript):
     107        (TestPage.registerInitializer.window.findResource):
     108        Test for resolving breakpoints at column locations in <script> which was
     109        not previously possible and would not have worked previously.
     110
    11112019-09-12  Ryan Haddad  <ryanhaddad@apple.com>
    2112
  • trunk/LayoutTests/TestExpectations

    r249811 r249831  
    740740webkit.org/b/161951 [ Debug ] inspector/debugger/stepping [ Skip ]
    741741webkit.org/b/161951 [ Release ] inspector/debugger/stepping [ Slow Pass Failure ]
     742
     743# Source map tests produce a lot of output.
     744inspector/formatting/source-map-css-1.html [ Slow ]
     745inspector/formatting/source-map-javascript-1.html [ Slow ]
     746[ Debug ] inspector/formatting/source-map-html-1.html [ Skip ]
     747[ Debug ] inspector/formatting/source-map-html-2.html [ Skip ]
     748[ Release ] inspector/formatting/source-map-html-1.html [ Slow ]
     749[ Release ] inspector/formatting/source-map-html-2.html [ Slow ]
    742750
    743751[ Debug ] inspector/debugger/breakpoints [ Skip ]
  • trunk/LayoutTests/inspector/debugger/breakpoints/resources/dump.js

    r206653 r249831  
    88    // Tries to set a breakpoint at every line:column in the file and
    99    // logs all unique pause locations with the originator line:column.
    10     window.addDumpAllPauseLocationsTestCase = function(suite, {name, scriptRegex}) {
     10    window.addDumpAllPauseLocationsTestCase = function(suite, {name, scriptRegex, resourceRegex}) {
     11        if (scriptRegex) {
     12            let script = window.findScript(scriptRegex);
     13            addDumpAllPauseLocationsTestCaseForScript(suite, name, script);
     14            return;
     15        }
     16        if (resourceRegex) {
     17            let resource = window.findResource(resourceRegex);
     18            addDumpAllPauseLocationsTestCaseForResource(suite, name, resource);
     19            return;
     20        }
     21        throw "Missing scriptRegex or resourceRegex argument";
     22    };
     23
     24    function addDumpAllPauseLocationsTestCaseForScript(suite, name, script) {
    1125        suite.addTestCase({
    1226            name, test(resolve, reject) {
    13                 let script = window.findScript(scriptRegex);
    1427                window.loadLinesFromSourceCode(script).then((lines) => {
    1528                    // Iterate all possible pause locations in this file.
     
    4356                        resolve();
    4457                    });
     58                });
     59            }
     60        });
     61    }
     62
     63    function addDumpAllPauseLocationsTestCaseForResource(suite, name, resource) {
     64        suite.addTestCase({
     65            name, test(resolve, reject) {
     66                window.loadLinesFromSourceCode(resource).then((lines) => {
     67                    // Iterate all possible pause locations in this file.
     68                    let pauseLocations = new Map;
     69                    let seenPauseLocations = new Set;
     70
     71                    let scripts = resource.scripts.slice();
     72                    scripts.sort((a, b) => a.range.startLine - b.range.startLine);
     73
     74                    for (let script of scripts) {
     75                        for (let line = script.range.startLine; line <= script.range.endLine; ++line) {
     76                            let max = lines[line].length;
     77                            for (let column = 0; column <= max; ++column) {
     78                                DebuggerAgent.setBreakpointByUrl.invoke({url: resource.url, lineNumber: line, columnNumber: column}, (error, breakpointId, locations) => {
     79                                    if (error)
     80                                        return;
     81                                    if (!locations.length)
     82                                        return;
     83                                    let location = locations[0];
     84                                    let key = JSON.stringify(location);
     85                                    if (seenPauseLocations.has(key))
     86                                        return;
     87                                    pauseLocations.set({lineNumber: line, columnNumber: column}, location);
     88                                });
     89                            }
     90                        }
     91
     92                        // Log the unique locations and the first input that produced it.
     93                        InspectorBackend.runAfterPendingDispatches(() => {
     94                            InspectorTest.log("");
     95                            for (let [inputLocation, payload] of pauseLocations) {
     96                                InspectorTest.log(`INSERTING AT: ${inputLocation.lineNumber}:${inputLocation.columnNumber}`);
     97                                InspectorTest.log(`PAUSES AT: ${payload.lineNumber}:${payload.columnNumber}`);
     98                                let resolvedLocation = resource.createSourceCodeLocation(payload.lineNumber, payload.columnNumber);
     99                                window.logResolvedBreakpointLinesWithContext(inputLocation, resolvedLocation, 3);
     100                                InspectorTest.log("");
     101                            }
     102                            resolve();
     103                        });
     104                    }
    45105                });
    46106            }
  • trunk/LayoutTests/inspector/debugger/resources/log-pause-location.js

    r236766 r249831  
    1212                return resource.scripts[0];
    1313        }
     14        return null;
     15    }
     16
     17    window.findResource = function(regex) {
     18        for (let frame of WI.networkManager.frames) {
     19            if (regex.test(frame.mainResource.url))
     20                return frame.mainResource;
     21            for (let resource of frame.resourceCollection) {
     22                if (regex.test(resource.url))
     23                    return resource;
     24            }           
     25        }
     26        return null;
    1427    }
    1528
  • trunk/LayoutTests/inspector/debugger/tail-deleted-frames/tail-deleted-frames-vm-entry.html

    r249586 r249831  
    88function test()
    99{
    10     InspectorTest.debug();
    1110    let suite = InspectorTest.createAsyncSuite("Debugger.TailDeletedFrames.VMEntry");
    1211
  • trunk/LayoutTests/inspector/formatting/formatting-css.html

    r248197 r249831  
    33<head>
    44<script src="../../http/tests/inspector/resources/inspector-test.js"></script>
    5 <script src="resources/utilities.js"></script>
     5<script src="resources/formatting-utilities.js"></script>
    66<script>
    77function test()
  • trunk/LayoutTests/inspector/formatting/formatting-javascript-expected.txt

    r248760 r249831  
    22
    33
    4 == Running test suite: EsprimaFormatter.JavaScript
    5 -- Running test case: EsprimaFormatter.JavaScript
     4== Running test suite: JSFormatter
     5-- Running test case: JSFormatter
    66PASS: arrow-functions.js
    77PASS: classes.js
  • trunk/LayoutTests/inspector/formatting/formatting-javascript.html

    r248760 r249831  
    33<head>
    44<script src="../../http/tests/inspector/resources/inspector-test.js"></script>
    5 <script src="resources/utilities.js"></script>
     5<script src="resources/formatting-utilities.js"></script>
    66<script>
    77function test()
    88{
    9     let suite = InspectorTest.createAsyncSuite("EsprimaFormatter.JavaScript");
     9    let suite = InspectorTest.createAsyncSuite("JSFormatter");
    1010
    1111    addFormattingTests(suite, "text/javascript", [
  • trunk/LayoutTests/inspector/formatting/formatting-json-expected.txt

    r202933 r249831  
    22
    33
    4 == Running test suite: EsprimaFormatter.JSON
    5 -- Running test case: EsprimaFormatter.ValidJSON
     4== Running test suite: JSFormatter.JSON
     5-- Running test case: JSFormatter.ValidJSON
    66JSON: "{\"a\":123,\"b\":[1,2,3],\"c\":{\"d\":\"e\"}}"
    77PASS: JSON should be valid.
     
    1919}
    2020
    21 -- Running test case: EsprimaFormatter.InvalidButObject
     21-- Running test case: JSFormatter.InvalidButObject
    2222JSON: "{a:123,b:[1,2,3],c:{d:\"e\"}}"
    2323PASS: JSON should be invalid.
     
    3232}
    3333
    34 -- Running test case: EsprimaFormatter.InvalidWithComments
     34-- Running test case: JSFormatter.InvalidWithComments
    3535JSON: "{\"a\":123,\"b\":[1,2,3],\"c\":{\"d\":\"e\"}}/*Comment*/"
    3636PASS: JSON should be invalid.
     
    4646
    4747
    48 -- Running test case: EsprimaFormatter.Invalid
     48-- Running test case: JSFormatter.Invalid
    4949INPUT: "{a:1 b:2}"
    5050PASS: JSON should be invalid.
  • trunk/LayoutTests/inspector/formatting/formatting-json.html

    r220119 r249831  
    3333
    3434
    35     let suite = InspectorTest.createAsyncSuite("EsprimaFormatter.JSON");
     35    let suite = InspectorTest.createAsyncSuite("JSFormatter.JSON");
    3636
    3737    const isModule = false;
     
    4040
    4141    suite.addTestCase({
    42         name: "EsprimaFormatter.ValidJSON",
     42        name: "JSFormatter.ValidJSON",
    4343        description: "Format valid JSON",
    4444        test(resolve, reject) {
     
    5555
    5656    suite.addTestCase({
    57         name: "EsprimaFormatter.InvalidButObject",
     57        name: "JSFormatter.InvalidButObject",
    5858        description: "Format invalid JSON due to literal keys, but it can be evaluated as a valid JavaScript Object",
    5959        test(resolve, reject) {
     
    7171
    7272    suite.addTestCase({
    73         name: "EsprimaFormatter.InvalidWithComments",
     73        name: "JSFormatter.InvalidWithComments",
    7474        description: "Format invalid JSON due to comments, but it can be evaluated as a valid JavaScript Object",
    7575        test(resolve, reject) {
     
    8787
    8888    suite.addTestCase({
    89         name: "EsprimaFormatter.Invalid",
     89        name: "JSFormatter.Invalid",
    9090        description: "Format invalid JSON, that is not a valid JavaScript Object",
    9191        test(resolve, reject) {
  • trunk/LayoutTests/inspector/formatting/resources/css-tests/basic-expected.css

    r246178 r249831  
    8888    color: red
    8989}
    90 
  • trunk/LayoutTests/inspector/formatting/resources/css-tests/gradient-expected.css

    r246178 r249831  
    77    background: linear-gradient(top, rgb(126, 198, 234) 0%, rgb(70, 179, 234) 45%, rgb(3, 135, 201) 100%);
    88}
    9 
  • trunk/LayoutTests/inspector/formatting/resources/css-tests/keyframes-expected.css

    r246430 r249831  
    1818    }
    1919}
    20 
  • trunk/LayoutTests/inspector/formatting/resources/css-tests/media-query-expected.css

    r249607 r249831  
    9292    }
    9393}
    94 
  • trunk/LayoutTests/inspector/formatting/resources/css-tests/selectors-expected.css

    r246430 r249831  
    3535    color: red;
    3636}
    37 
  • trunk/LayoutTests/inspector/formatting/resources/css-tests/wrapping-expected.css

    r246430 r249831  
    1212    font-size: 1em
    1313}
    14 
  • trunk/LayoutTests/inspector/formatting/resources/formatting-utilities.js

    r249830 r249831  
    4646                break;
    4747            }
    48 
    4948            case "text/css":
    5049                workerProxy.formatCSS(testText, indentString, callback);
     50                break;
     51            case "text/html":
     52                workerProxy.formatHTML(testText, indentString, callback);
    5153                break;
    5254            }
  • trunk/Source/JavaScriptCore/ChangeLog

    r249830 r249831  
     12019-09-13  Joseph Pecoraro  <pecoraro@apple.com>
     2
     3        Web Inspector: Formatter: Pretty Print HTML resources (including inline <script>/<style>)
     4        https://bugs.webkit.org/show_bug.cgi?id=201535
     5        <rdar://problem/29119232>
     6
     7        Reviewed by Devin Rousso.
     8
     9        * debugger/Debugger.cpp:
     10        (JSC::Debugger::resolveBreakpoint):
     11        When resolving a breakpoint inside of an inline <script> we need to adjust
     12        based on the starting position of the <script> in the HTML resource.
     13
    1142019-09-13  Yusuke Suzuki  <ysuzuki@apple.com>
    215
  • trunk/Source/JavaScriptCore/debugger/Debugger.cpp

    r249450 r249831  
    364364    unsigned column = breakpoint.column ? breakpoint.column : Breakpoint::unspecifiedColumn;
    365365
     366    // Account for a <script>'s start position on the first line only.
     367    unsigned providerStartLine = sourceProvider->startPosition().m_line.oneBasedInt(); // One based to match the already adjusted line.
     368    unsigned providerStartColumn = sourceProvider->startPosition().m_column.zeroBasedInt(); // Zero based so column zero is zero.
     369    if (line == providerStartLine && column != Breakpoint::unspecifiedColumn) {
     370        ASSERT(providerStartColumn <= column);
     371        if (providerStartColumn)
     372            column -= providerStartColumn;
     373    }
     374
    366375    DebuggerParseData& parseData = debuggerParseData(breakpoint.sourceID, sourceProvider);
    367376    Optional<JSTextPosition> resolvedPosition = parseData.pausePositions.breakpointLocationForLineColumn((int)line, (int)column);
     
    371380    unsigned resolvedLine = resolvedPosition->line;
    372381    unsigned resolvedColumn = resolvedPosition->offset - resolvedPosition->lineStartOffset + 1;
     382
     383    // Re-account for a <script>'s start position on the first line only.
     384    if (resolvedLine == providerStartLine && column != Breakpoint::unspecifiedColumn) {
     385        if (providerStartColumn)
     386            resolvedColumn += providerStartColumn;
     387    }
    373388
    374389    breakpoint.line = resolvedLine - 1;
  • trunk/Source/WebInspectorUI/ChangeLog

    r249828 r249831  
     12019-09-13  Joseph Pecoraro  <pecoraro@apple.com>
     2
     3        Web Inspector: Formatter: Pretty Print HTML resources (including inline <script>/<style>)
     4        https://bugs.webkit.org/show_bug.cgi?id=201535
     5        <rdar://problem/29119232>
     6
     7        Reviewed by Devin Rousso.
     8
     9        Introduce HTMLFormatter, HTMLParser, and HTMLTreeBuilderFormatter.
     10
     11            - HTMLParser tokenizes HTML content and passes it to a tree builder.
     12            - HTMLTreeBuilderFormatter uses those tokens to create a formatted dom tree of fake nodes.
     13            - HTMLFormatter then builds formatted content and a FormatterSourceMap from that DOM tree.
     14       
     15        The output of HTMLFormatter is intended to just modify whitespace. So it won't be a
     16        100% compatible DOM, but will be useful for debugging and reading inline <style>
     17        and <script>, which is a more common debugging scenario. It also maintains original
     18        author attribute quotations or lack therefore, because again it tries to only
     19        change whitespace. A separate tree builder could be used for tidying content.
     20
     21        This introduces a few tools for working with formatting:
     22
     23            - Tools/HTMLFormatter - debug the parser, tree builder, and output format
     24            - Tools/SourceMaps - debug formatted content and source mappings
     25
     26        This also:
     27       
     28            - renames "EsprimaFormatter" to "JSFormatter"
     29            - eliminates an extra trailing newline in CSSFormatter output
     30
     31        * Tools/HTMLFormatter/HTMLTreeBuilderDebug.js: Added.
     32        * Tools/HTMLFormatter/index.html: Added.
     33        * Tools/HTMLFormatter/styles.css: Added.
     34        Tool for debugging the HTML formatter components.
     35
     36        * Tools/SourceMaps/.gitignore: Added.
     37        * Tools/SourceMaps/index.html: Added.
     38        * Tools/SourceMaps/setup.sh: Added.
     39        * Tools/SourceMaps/styles.css: Added.
     40        Tool for debugging Formatter generated Source Maps.
     41
     42        * Tools/JSFormatter/JSFormatterDebug.js: Renamed from Source/WebInspectorUI/Tools/Formatting/EsprimaFormatterDebug.js.
     43        * Tools/JSFormatter/codemirror-additions.css: Renamed from Source/WebInspectorUI/Tools/Formatting/codemirror-additions.css.
     44        * Tools/JSFormatter/index.html: Renamed from Source/WebInspectorUI/Tools/Formatting/index.html.
     45        Renamed this tool. EsprimaFormatter => JSFormatter.
     46
     47        * UserInterface/Controllers/FormatterSourceMap.js:
     48        (WI.FormatterSourceMap.prototype.originalPositionToFormattedPosition):
     49        (WI.FormatterSourceMap.prototype.formattedPositionToOriginalPosition):
     50        New APIs used by tools and tests for translating "position" offsets and not line/columns.
     51
     52        * UserInterface/Workers/Formatter/JSFormatter.js: Renamed from Source/WebInspectorUI/UserInterface/Workers/Formatter/EsprimaFormatter.js.
     53        (JSFormatter):
     54        * UserInterface/Workers/Formatter/CSSFormatter.js:
     55        (CSSFormatter):
     56        Allow using a supplied builder, which is useful when formatting
     57        inline content from HTMLFormatter (<style> / <script>).
     58
     59        * UserInterface/Workers/Formatter/FormatterContentBuilder.js:
     60        (FormatterContentBuilder.prototype.get indentString):
     61        (FormatterContentBuilder.prototype.get originalContent):
     62        (FormatterContentBuilder.prototype.get indentLevel):
     63        (FormatterContentBuilder.prototype.get originalOffset):
     64        (FormatterContentBuilder.prototype.set originalOffset):
     65        (FormatterContentBuilder.prototype.appendNonToken):
     66        (FormatterContentBuilder.prototype.appendToken):
     67        (FormatterContentBuilder.prototype.appendTokenWithPossibleNewlines):
     68        (FormatterContentBuilder.prototype.appendMapping):
     69        (FormatterContentBuilder.prototype.indentToLevel):
     70        (FormatterContentBuilder.prototype.finish):
     71        Provide API for getting / setting the original offset and indent level.
     72        This is useful when the HTMLFormatter runs the CSSFormatter/JSFormatter
     73        in a nested context (<style> / <script>). Add a few more APIs for
     74        conveniences when appending tokens or important positions.
     75
     76        * UserInterface/Workers/Formatter/HTMLParser.js: Added.
     77        (HTMLParser.prototype.parseDocument):
     78        (HTMLParser.prototype._isEOF):
     79        (HTMLParser.prototype._peek):
     80        (HTMLParser.prototype._peekCharacterRegex):
     81        (HTMLParser.prototype._peekString):
     82        (HTMLParser.prototype._peekCaseInsensitiveString):
     83        (HTMLParser.prototype._consumeWhitespace):
     84        (HTMLParser.prototype._consumeUntilString):
     85        (HTMLParser.prototype._consumeUntilRegex):
     86        (HTMLParser.prototype._consumeDoubleQuotedString):
     87        (HTMLParser):
     88        Tokenize HTML content into nodes.
     89
     90        * UserInterface/Workers/Formatter/HTMLTreeBuilderFormatter.js: Added.
     91        (HTMLTreeBuilderFormatter.prototype.get dom):
     92        (HTMLTreeBuilderFormatter.prototype.begin):
     93        (HTMLTreeBuilderFormatter.prototype.pushParserNode):
     94        (HTMLTreeBuilderFormatter.prototype.end):
     95        (HTMLTreeBuilderFormatter.prototype._pushParserNodeTopLevel):
     96        (HTMLTreeBuilderFormatter.prototype._pushParserNodeStack):
     97        (HTMLTreeBuilderFormatter.prototype._isEmptyNode):
     98        (HTMLTreeBuilderFormatter.prototype._buildDOMNodeFromOpenTag):
     99        (HTMLTreeBuilderFormatter.prototype._buildErrorNodeFromCloseTag):
     100        (HTMLTreeBuilderFormatter.prototype._buildSimpleNodeFromParserNode):
     101        (HTMLTreeBuilderFormatter):
     102        Build a simple DOM tree from parser nodes.
     103
     104        * UserInterface/Workers/Formatter/HTMLFormatter.js: Added.
     105        (HTMLFormatter.let.dom):
     106        (HTMLFormatter):
     107        (HTMLFormatter.prototype.get success):
     108        (HTMLFormatter.prototype.get formattedText):
     109        (HTMLFormatter.prototype.get sourceMapData):
     110        (HTMLFormatter.prototype._walk):
     111        (HTMLFormatter.prototype._walkChildren):
     112        (HTMLFormatter.prototype._isNodeSelfClosing):
     113        (HTMLFormatter.prototype._shouldHaveInlineContent):
     114        (HTMLFormatter.prototype._hasMultipleNewLines):
     115        (HTMLFormatter.prototype._buildAttributeString):
     116        (HTMLFormatter.prototype._before):
     117        (HTMLFormatter.prototype._after):
     118        (HTMLFormatter.prototype._formatWithNestedFormatter):
     119        (HTMLFormatter.prototype._formatScript):
     120        (HTMLFormatter.prototype._formatStyle):
     121        Output pretty printed text from a HTMLTreeBuilderFormatter dom tree.
     122
     123        * UserInterface/Proxies/FormatterWorkerProxy.js:
     124        (WI.FormatterWorkerProxy.prototype.formatHTML):
     125        * UserInterface/Workers/Formatter/FormatterWorker.js:
     126        (FormatterWorker.prototype.formatJavaScript):
     127        (FormatterWorker.prototype.formatCSS):
     128        (FormatterWorker.prototype.formatHTML):
     129        * UserInterface/Views/TextEditor.js:
     130        (WI.TextEditor.prototype.hasFormatter):
     131        (WI.TextEditor.prototype._canUseFormatterWorker):
     132        (WI.TextEditor.prototype._startWorkerPrettyPrint):
     133        Allow pretty printing HTML resources.
     134
     135        * UserInterface/Main.html:
     136        * UserInterface/Test.html:
     137        New resources.
     138
    11392019-09-13  Joseph Pecoraro  <pecoraro@apple.com>
    2140
  • trunk/Source/WebInspectorUI/Tools/JSFormatter/JSFormatterDebug.js

    r249830 r249831  
    1 EsprimaFormatterDebug = class EsprimaFormatterDebug
     1JSFormatterDebug = class JSFormatterDebug
    22{
    33    constructor(sourceText, sourceType)
  • trunk/Source/WebInspectorUI/Tools/JSFormatter/index.html

    r249830 r249831  
    22<html>
    33<head>
    4     <title>EsprimaFormatter Tool</title>
     4    <title>JSFormatter Tool</title>
    55    <link rel="stylesheet" href="../../UserInterface/External/CodeMirror/codemirror.css">
    66    <link rel="stylesheet" href="codemirror-additions.css">
     
    1212    <script src="../../UserInterface/Workers/Formatter/FormatterUtilities.js"></script>
    1313    <script src="../../UserInterface/Workers/Formatter/ESTreeWalker.js"></script>
    14     <script src="../../UserInterface/Workers/Formatter/EsprimaFormatter.js"></script>
    15     <script src="EsprimaFormatterDebug.js"></script>
     14    <script src="../../UserInterface/Workers/Formatter/JSFormatter.js"></script>
     15    <script src="JSFormatterDebug.js"></script>
    1616</head>
    1717<body>
    18     <h1>Debug EsprimaFormatter</h1>
     18    <h1>Debug JSFormatter</h1>
    1919
    2020    <!-- Controls -->
     
    181181    function currentSourceType() {
    182182        if (programCheckbox.checked)
    183             return EsprimaFormatter.SourceType.Script;
     183            return JSFormatter.SourceType.Script;
    184184        if (moduleCheckbox.checked)
    185             return EsprimaFormatter.SourceType.Module;
     185            return JSFormatter.SourceType.Module;
    186186        console.assert(false, "Program or Module radio button should be checked");
    187187        return undefined;
     
    194194        // Time the formatter.
    195195        let startTime = Date.now();
    196         let formatter = new EsprimaFormatter(cm.getValue(), currentSourceType());
     196        let formatter = new JSFormatter(cm.getValue(), currentSourceType());
    197197        let endTime = Date.now();
    198198
     
    200200        let debugText;
    201201        try {
    202             let debugFormatter = new EsprimaFormatterDebug(cm.getValue(), currentSourceType());
     202            let debugFormatter = new JSFormatterDebug(cm.getValue(), currentSourceType());
    203203            debugText = debugFormatter.debugText;
    204204        } catch (error) {
     
    262262
    263263            // Run the test.
    264             let sourceType = isModuleTest(test) ? EsprimaFormatter.SourceType.Module : EsprimaFormatter.SourceType.Script;
    265             let formatter = new EsprimaFormatter(testData, sourceType);
     264            let sourceType = isModuleTest(test) ? JSFormatter.SourceType.Module : JSFormatter.SourceType.Script;
     265            let formatter = new JSFormatter(testData, sourceType);
    266266
    267267            // Compare results.
  • trunk/Source/WebInspectorUI/UserInterface/Controllers/FormatterSourceMap.js

    r220119 r249831  
    5656    }
    5757
     58    originalPositionToFormattedPosition(originalPosition)
     59    {
     60        return this._convertPosition(this._mapping.original, this._mapping.formatted, originalPosition);
     61    }
     62
    5863    formattedToOriginal(lineNumber, columnNumber)
    5964    {
     
    6772        var originalPosition = this._convertPosition(this._mapping.formatted, this._mapping.original, formattedPosition);
    6873        return originalPosition;
     74    }
     75
     76    formattedPositionToOriginalPosition(formattedPosition)
     77    {
     78        return this._convertPosition(this._mapping.formatted, this._mapping.original, formattedPosition);
    6979    }
    7080
  • trunk/Source/WebInspectorUI/UserInterface/Models/Resource.js

    r249504 r249831  
    193193                classes.push("resource-type-range");
    194194        } else
    195             classes.push(resource.type)
     195            classes.push(resource.type);
    196196
    197197        return classes;
     
    10661066    async createLocalResourceOverride(initialContent)
    10671067    {
    1068         console.assert(!this.isLocalResourceOverride)
     1068        console.assert(!this.isLocalResourceOverride);
    10691069        console.assert(WI.NetworkManager.supportsLocalResourceOverrides());
    10701070
  • trunk/Source/WebInspectorUI/UserInterface/Proxies/FormatterWorkerProxy.js

    r246178 r249831  
    5656    }
    5757
     58    formatHTML(sourceText, indentString, includeSourceMapData)
     59    {
     60        this.performAction("formatHTML", ...arguments);
     61    }
     62
    5863    // Public
    5964
  • trunk/Source/WebInspectorUI/UserInterface/Test.html

    r249751 r249831  
    247247    <script src="Controllers/DatabaseManager.js"></script>
    248248    <script src="Controllers/DebuggerManager.js"></script>
     249    <script src="Controllers/FormatterSourceMap.js"></script>
    249250    <script src="Controllers/HARBuilder.js"></script>
    250251    <script src="Controllers/HeapManager.js"></script>
  • trunk/Source/WebInspectorUI/UserInterface/Views/DebuggerSidebarPanel.js

    r249800 r249831  
    16061606                        treeElementToSelect.select(omitFocus, selectedByUser);
    16071607                    }
    1608                 }               
     1608                }
    16091609            }
    16101610        }
  • trunk/Source/WebInspectorUI/UserInterface/Views/LocalResourceOverridePopover.js

    r249504 r249831  
    142142            labelElement.setAttribute("for", inputField.id);
    143143
    144             return {codeMirror, dataElement}
     144            return {codeMirror, dataElement};
    145145        };
    146146
     
    219219            let newNode = new WI.DataGridNode({name: "Header", value: "value"});
    220220            dataGrid.appendChild(newNode);
    221             dataGrid.updateLayoutIfNeeded();           
     221            dataGrid.updateLayoutIfNeeded();
    222222            this.update();
    223223            dataGrid.startEditingNode(newNode);
  • trunk/Source/WebInspectorUI/UserInterface/Views/LocalResourceOverrideTreeElement.js

    r249504 r249831  
    4646
    4747        this._localResourceOverride.addEventListener(WI.LocalResourceOverride.Event.DisabledChanged, this._handleLocalResourceOverrideDisabledChanged, this);
    48  
     48
    4949        WI.Frame.addEventListener(WI.Frame.Event.MainResourceDidChange, this._handleFrameMainResourceDidChange, this);
    5050
     
    9393        contextMenu.appendItem(toggleEnabledString, () => {
    9494            this._localResourceOverride.disabled = !this._localResourceOverride.disabled;
    95         });           
     95        });
    9696
    9797        contextMenu.appendItem(WI.UIString("Remove Local Override"), () => {
  • trunk/Source/WebInspectorUI/UserInterface/Views/SettingsTabContentView.js

    r249592 r249831  
    354354                        newTabs.insertAtIndex(WI.SourcesTabContentView.Type, index);
    355355                    else
    356                         newTabs.push(WI.SourcesTabContentView.Type);                   
     356                        newTabs.push(WI.SourcesTabContentView.Type);
    357357                }
    358358            }
  • trunk/Source/WebInspectorUI/UserInterface/Views/SourcesNavigationSidebarPanel.js

    r249828 r249831  
    444444
    445445        if (representedObject instanceof WI.LocalResourceOverride)
    446             return this._localResourceOverridesTreeOutline.findTreeElement(localResource);
     446            return this._localResourceOverridesTreeOutline.findTreeElement(representedObject);
    447447
    448448        if (representedObject instanceof WI.LocalResource) {
  • trunk/Source/WebInspectorUI/UserInterface/Views/TextEditor.js

    r249751 r249831  
    183183    {
    184184        let mode = this._codeMirror.getMode().name;
    185         return mode === "javascript" || mode === "css";
     185        return mode === "javascript" || mode === "css" || mode === "htmlmixed";
    186186    }
    187187
     
    894894
    895895        let mode = this._codeMirror.getMode().name;
    896         if (mode === "javascript") {
     896        switch (mode) {
     897        case "javascript": {
    897898            let sourceType = this._delegate ? this._delegate.textEditorScriptSourceType(this) : WI.Script.SourceType.Program;
    898899            const isModule = sourceType === WI.Script.SourceType.Module;
    899900            workerProxy.formatJavaScript(sourceText, isModule, indentString, includeSourceMapData, formatCallback);
    900         } else if (mode === "css")
     901            break;
     902        }
     903        case "css":
    901904            workerProxy.formatCSS(sourceText, indentString, includeSourceMapData, formatCallback);
     905            break;
     906        case "htmlmixed":
     907            workerProxy.formatHTML(sourceText, indentString, includeSourceMapData, formatCallback);
     908            break;
     909        default:
     910            console.assert(false, "Unexpected mode attempted to pretty print.");
     911            break;
     912        }
    902913    }
    903914
  • trunk/Source/WebInspectorUI/UserInterface/Views/TextResourceContentView.js

    r249504 r249831  
    6767                this._removeLocalResourceOverrideButtonNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handleRemoveLocalResourceOverride, this);
    6868                this._removeLocalResourceOverrideButtonNavigationItem.enabled = true;
    69                 this._removeLocalResourceOverrideButtonNavigationItem.visibilityPriority = WI.NavigationItem.VisibilityPriority.Low;               
     69                this._removeLocalResourceOverrideButtonNavigationItem.visibilityPriority = WI.NavigationItem.VisibilityPriority.Low;
    7070            } else {
    7171                this._localResourceOverrideBannerView = new WI.LocalResourceOverrideWarningView(resource);
     
    7474                this._createLocalResourceOverrideButtonNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handleCreateLocalResourceOverride, this);
    7575                this._createLocalResourceOverrideButtonNavigationItem.enabled = false; // Enabled when the text editor is populated with content.
    76                 this._createLocalResourceOverrideButtonNavigationItem.visibilityPriority = WI.NavigationItem.VisibilityPriority.Low;           
     76                this._createLocalResourceOverrideButtonNavigationItem.visibilityPriority = WI.NavigationItem.VisibilityPriority.Low;
    7777            }
    7878        }
  • trunk/Source/WebInspectorUI/UserInterface/Workers/Formatter/CSSFormatter.js

    r249596 r249831  
    2626CSSFormatter = class CSSFormatter
    2727{
    28     constructor(sourceText, indentString = "    ")
     28    constructor(sourceText, builder, indentString = "    ")
    2929    {
    3030        this._success = false;
     
    3232        this._sourceText = sourceText;
    3333
    34         this._builder = new FormatterContentBuilder(indentString);
    35         this._builder.setOriginalLineEndings(this._sourceText.lineEndings());
     34        this._builder = builder;
     35        if (!this._builder) {
     36            this._builder = new FormatterContentBuilder(indentString);
     37            this._builder.setOriginalLineEndings(this._sourceText.lineEndings());
     38        }
    3639
    3740        this._format();
     
    271274                }
    272275
    273                 specialSequenceText.split(`\n`).forEach((line, i, lines) => {
    274                     if (line) {
    275                         this._builder.appendToken(line, startIndex);
    276                         startIndex += line.length;
    277                     }
    278 
    279                     if (i < lines.length - 1) {
    280                         this._builder.appendNewline(true);
    281                         ++startIndex;
    282                     }
    283                 });
     276                this._builder.appendStringWithPossibleNewlines(specialSequenceText, startIndex);
    284277
    285278                i = endIndex;
  • trunk/Source/WebInspectorUI/UserInterface/Workers/Formatter/FormatterContentBuilder.js

    r249607 r249831  
    5555    // Public
    5656
    57     get originalContent()
    58     {
    59         return this._originalContent;
    60     }
     57    get indentString() { return this._indentString; }
     58    get originalContent() { return this._originalContent; }
    6159
    6260    get formattedContent()
     
    8886    }
    8987
     88    get indentLevel()
     89    {
     90        return this._indent;
     91    }
     92
    9093    get indented()
    9194    {
    9295        return this._indent > 0;
     96    }
     97
     98    get originalOffset()
     99    {
     100        return this._originalOffset;
     101    }
     102
     103    set originalOffset(offset)
     104    {
     105        this._originalOffset = offset;
    93106    }
    94107
     
    105118    }
    106119
    107     appendToken(string, originalPosition)
    108     {
     120    appendNonToken(string)
     121    {
     122        if (!string)
     123            return;
     124
    109125        if (this._startOfLine)
    110126            this._appendIndent();
    111127
     128        console.assert(!string.includes("\n"), "Appended a string with newlines. This breaks the source map.");
     129
     130        this._append(string);
     131        this._startOfLine = false;
     132        this.lastTokenWasNewline = false;
     133        this.lastTokenWasWhitespace = false;
     134    }
     135
     136    appendToken(string, originalPosition)
     137    {
     138        if (this._startOfLine)
     139            this._appendIndent();
     140
    112141        this._addMappingIfNeeded(originalPosition);
    113142
     143        console.assert(!string.includes("\n"), "Appended a string with newlines. This breaks the source map.");
     144
    114145        this._append(string);
     146        this._startOfLine = false;
     147        this.lastTokenWasNewline = false;
     148        this.lastTokenWasWhitespace = false;
     149    }
     150
     151    appendStringWithPossibleNewlines(string, originalPosition)
     152    {
     153        let currentPosition = originalPosition;
     154        let lines = string.split("\n");
     155        for (let i = 0; i < lines.length; ++i) {
     156            let line = lines[i];
     157            if (line) {
     158                this.appendToken(line, currentPosition);
     159                currentPosition += line.length;
     160            }
     161
     162            if (i < lines.length - 1) {
     163                this.appendNewline(true);
     164                currentPosition += 1;
     165            }
     166        }
     167    }
     168
     169    appendMapping(originalPosition)
     170    {
     171        if (this._startOfLine)
     172            this._appendIndent();
     173
     174        this._addMappingIfNeeded(originalPosition);
     175
    115176        this._startOfLine = false;
    116177        this.lastTokenWasNewline = false;
     
    195256    }
    196257
     258    indentToLevel(level)
     259    {
     260        if (this._indent === level)
     261            return;
     262
     263        while (this._indent < level)
     264            this.indent();
     265        while (this._indent > level)
     266            this.dedent();
     267    }
     268
    197269    addOriginalLineEnding(originalPosition)
    198270    {
     
    202274    finish()
    203275    {
     276        while (this.lastTokenWasNewline)
     277            this.removeLastNewline();
    204278        this.appendNewline();
    205279    }
     
    216290    _append(str)
    217291    {
     292        console.assert(str, "Should not append an empty string");
    218293        this._formattedContent.push(str);
    219294        this._formattedContentLength += str.length;
     
    225300        // Indent is already in the cache.
    226301        if (this._indent < this._indentCache.length) {
    227             this._append(this._indentCache[this._indent]);
     302            let indent = this._indentCache[this._indent];
     303            if (indent)
     304                this._append(indent);
    228305            return;
    229306        }
  • trunk/Source/WebInspectorUI/UserInterface/Workers/Formatter/FormatterWorker.js

    r246178 r249831  
    2626importScripts(...[
    2727    "../../External/Esprima/esprima.js",
     28    "CSSFormatter.js",
     29    "ESTreeWalker.js",
     30    "FormatterContentBuilder.js",
    2831    "FormatterUtilities.js",
    29     "FormatterContentBuilder.js",
    30     "ESTreeWalker.js",
    31     "EsprimaFormatter.js",
    32     "CSSFormatter.js",
     32    "HTMLFormatter.js",
     33    "HTMLParser.js",
     34    "HTMLTreeBuilderFormatter.js",
     35    "JSFormatter.js",
    3336]);
    3437
     
    4447    formatJavaScript(sourceText, isModule, indentString, includeSourceMapData)
    4548    {
    46         let sourceType = isModule ? EsprimaFormatter.SourceType.Module : EsprimaFormatter.SourceType.Script;
     49        let sourceType = isModule ? JSFormatter.SourceType.Module : JSFormatter.SourceType.Script;
    4750
    4851        // Format a JavaScript program.
    49         let formatter = new EsprimaFormatter(sourceText, sourceType, indentString);
     52        const builder = null;
     53        let formatter = new JSFormatter(sourceText, sourceType, builder, indentString);
    5054        if (formatter.success) {
    5155            let result = {formattedText: formatter.formattedText};
    5256            if (includeSourceMapData) {
    5357                result.sourceMapData = formatter.sourceMapData;
    54                 // NOTE: With the EsprimaFormatter, multi-line tokens, such as comments and strings,
     58                // NOTE: With the JSFormatter, multi-line tokens, such as comments and strings,
    5559                // would not have had their newlines counted properly by the builder. Rather then
    5660                // modify the formatter to check and account for newlines in every token just
     
    7882        // a valid program on its own. Wrap it in parenthesis to make it a function expression,
    7983        // which is a valid program.
    80         let invalidJSONFormatter = new EsprimaFormatter("(" + sourceText + ")", sourceType, indentString);
     84        let invalidJSONFormatter = new JSFormatter("(" + sourceText + ")", sourceType, builder, indentString);
    8185        if (invalidJSONFormatter.success) {
    8286            let formattedTextWithParens = invalidJSONFormatter.formattedText;
     
    9397    {
    9498        let result = {formattedText: null};
    95         let formatter = new CSSFormatter(sourceText, indentString);
     99        const builder = null;
     100        let formatter = new CSSFormatter(sourceText, builder, indentString);
     101        if (formatter.success) {
     102            result.formattedText = formatter.formattedText;
     103            if (includeSourceMapData)
     104                result.sourceMapData = formatter.sourceMapData;
     105        }
     106        return result;
     107    }
     108
     109    formatHTML(sourceText, indentString, includeSourceMapData)
     110    {
     111        let result = {formattedText: null};
     112        const builder = null;
     113        let formatter = new HTMLFormatter(sourceText, builder, indentString);
    96114        if (formatter.success) {
    97115            result.formattedText = formatter.formattedText;
  • trunk/Source/WebInspectorUI/UserInterface/Workers/Formatter/JSFormatter.js

    r249830 r249831  
    2828// <http://esprima.org/demo/parse.html>
    2929
    30 EsprimaFormatter = class EsprimaFormatter
     30JSFormatter = class JSFormatter
    3131{
    32     constructor(sourceText, sourceType, indentString = "    ")
     32    constructor(sourceText, sourceType, builder, indentString = "    ")
    3333    {
    3434        this._success = false;
     
    4646
    4747        this._sourceText = sourceText;
    48         this._builder = null;
    49 
    50         let walker = new ESTreeWalker(this._before.bind(this), this._after.bind(this));
    5148
    5249        this._tokens = tree.tokens;
     
    5754        this._lineEndingsIndex = 0;
    5855
    59         this._builder = new FormatterContentBuilder(indentString);
    60         this._builder.setOriginalLineEndings(this._lineEndings.slice());
    61 
     56        this._builder = builder;
     57        if (!this._builder) {
     58            this._builder = new FormatterContentBuilder(indentString);
     59            this._builder.setOriginalLineEndings(this._lineEndings.slice());
     60        }
     61
     62        let walker = new ESTreeWalker(this._before.bind(this), this._after.bind(this));
    6263        walker.walk(tree);
    6364        this._afterProgram(tree);
     
    7677    // Public
    7778
    78     get success()
    79     {
    80         return this._success;
    81     }
     79    get success() { return this._success; }
    8280
    8381    get formattedText()
     
    211209        let substring = this._sourceText.substring(from, to);
    212210        for (let i = 0; i < substring.length; ++i) {
    213             if (!EsprimaFormatter.isWhitespace(substring.charCodeAt(i)))
     211            if (!JSFormatter.isWhitespace(substring.charCodeAt(i)))
    214212                return false;
    215213        }
     
    944942};
    945943
    946 EsprimaFormatter.SourceType = {
     944JSFormatter.SourceType = {
    947945    Script: "script",
    948946    Module: "module",
Note: See TracChangeset for help on using the changeset viewer.