Title: [191135] trunk
Revision
191135
Author
commit-qu...@webkit.org
Date
2015-10-15 13:50:02 -0700 (Thu, 15 Oct 2015)

Log Message

Web Inspector: _javascript_Core should parse sourceURL and sourceMappingURL directives
https://bugs.webkit.org/show_bug.cgi?id=150096

Patch by Joseph Pecoraro <pecor...@apple.com> on 2015-10-15
Reviewed by Geoffrey Garen.

Source/_javascript_Core:

* inspector/ContentSearchUtilities.cpp:
(Inspector::ContentSearchUtilities::scriptCommentPattern): Deleted.
(Inspector::ContentSearchUtilities::findScriptSourceURL): Deleted.
(Inspector::ContentSearchUtilities::findScriptSourceMapURL): Deleted.
* inspector/ContentSearchUtilities.h:
No longer need to search script content.

* inspector/ScriptDebugServer.cpp:
(Inspector::ScriptDebugServer::dispatchDidParseSource):
Carry over the sourceURL and sourceMappingURL from the SourceProvider.

* inspector/agents/InspectorDebuggerAgent.cpp:
(Inspector::InspectorDebuggerAgent::sourceMapURLForScript):
(Inspector::InspectorDebuggerAgent::didParseSource):
No longer do content searching.

* parser/Lexer.cpp:
(JSC::Lexer<T>::setCode):
(JSC::Lexer<T>::skipWhitespace):
(JSC::Lexer<T>::parseCommentDirective):
(JSC::Lexer<T>::parseCommentDirectiveValue):
(JSC::Lexer<T>::consume):
(JSC::Lexer<T>::lex):
* parser/Lexer.h:
(JSC::Lexer::sourceURL):
(JSC::Lexer::sourceMappingURL):
(JSC::Lexer::sourceProvider): Deleted.
Give lexer the ability to detect script comment directives.
This just consumes characters in single line comments and
ultimately sets the sourceURL or sourceMappingURL found.

* parser/Parser.h:
(JSC::Parser<LexerType>::parse):
* parser/SourceProvider.h:
(JSC::SourceProvider::url):
(JSC::SourceProvider::sourceURL):
(JSC::SourceProvider::sourceMappingURL):
(JSC::SourceProvider::setSourceURL):
(JSC::SourceProvider::setSourceMappingURL):
After parsing a script, update the Source Provider with the
value of directives that may have been found in the script.

Source/WebInspectorUI:

* UserInterface/Test/InspectorProtocol.js:
(InspectorProtocol._sendMessage):
(InspectorProtocol.dispatchMessageFromBackend):
This is only used for tests, so avoid console.log
and just dump directly to the system console.

LayoutTests:

* inspector/debugger/sourceURLs-expected.txt: Added.
* inspector/debugger/sourceURLs.html: Added.
sourceURL and sourceMappingURL detection.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (191134 => 191135)


--- trunk/LayoutTests/ChangeLog	2015-10-15 20:34:10 UTC (rev 191134)
+++ trunk/LayoutTests/ChangeLog	2015-10-15 20:50:02 UTC (rev 191135)
@@ -1,3 +1,14 @@
+2015-10-15  Joseph Pecoraro  <pecor...@apple.com>
+
+        Web Inspector: _javascript_Core should parse sourceURL and sourceMappingURL directives
+        https://bugs.webkit.org/show_bug.cgi?id=150096
+
+        Reviewed by Geoffrey Garen.
+
+        * inspector/debugger/sourceURLs-expected.txt: Added.
+        * inspector/debugger/sourceURLs.html: Added.
+        sourceURL and sourceMappingURL detection.
+
 2015-10-15  Dean Jackson  <d...@apple.com>
 
         CSSKeyframesRule::appendRule is deprecated, but is actually the spec

Added: trunk/LayoutTests/inspector/debugger/sourceURLs-expected.txt (0 => 191135)


--- trunk/LayoutTests/inspector/debugger/sourceURLs-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/inspector/debugger/sourceURLs-expected.txt	2015-10-15 20:50:02 UTC (rev 191135)
@@ -0,0 +1,26 @@
+Tests for the Debugger.scriptParsed sourceURL and sourceMappingURL comment directive parsing.
+
+
+== Running test suite: Debugger.scriptParsed.sourceURL-directives
+-- Running test case: TestExpressionsForSourceURL
+Found Script with sourceURL 'test1.js'
+Found Script with sourceURL 'test2.js'
+Found Script with sourceURL 'test3.js'
+Found Script with sourceURL 'test4.js'
+Found Script with sourceURL 'test5.js'
+Found Script with sourceURL 'test6.js'
+Found Script with sourceURL 'test7.js'
+Found Script with sourceURL 'test8.js'
+Found Script with sourceURL 'test9.js'
+
+-- Running test case: TestExpressionsForSourceMappingURL
+Found Script with sourceMappingURL 'test1.js'
+Found Script with sourceMappingURL 'test2.js'
+Found Script with sourceMappingURL 'test3.js'
+Found Script with sourceMappingURL 'test4.js'
+Found Script with sourceMappingURL 'test5.js'
+Found Script with sourceMappingURL 'test6.js'
+Found Script with sourceMappingURL 'test7.js'
+Found Script with sourceMappingURL 'test8.js'
+Found Script with sourceMappingURL 'test9.js'
+

Added: trunk/LayoutTests/inspector/debugger/sourceURLs.html (0 => 191135)


--- trunk/LayoutTests/inspector/debugger/sourceURLs.html	                        (rev 0)
+++ trunk/LayoutTests/inspector/debugger/sourceURLs.html	2015-10-15 20:50:02 UTC (rev 191135)
@@ -0,0 +1,207 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=""
+<script>
+function test()
+{
+    let suite = ProtocolTest.createAsyncSuite("Debugger.scriptParsed.sourceURL-directives");
+
+    // Because InspectorTest output causes scripts to be parsed
+    // we cannot check sourceURL per evaluation easily. Instead
+    // just run a bunch of tests for valid and invalid directives
+    // and check that the output only includes the valid results.
+
+    let expressions = [];
+    let sourceURLExpectations = [];
+    let sourceMappingURLExpectations = [];
+
+    function addInvalidTestCase(args) {
+        let {_expression_} = args;
+        expressions.push(_expression_);
+    }
+
+    function addValidTestCase(args) {
+        let {_expression_, expected} = args;
+        expressions.push(_expression_);
+        sourceURLExpectations.push(expected);
+        sourceMappingURLExpectations.push(expected);
+    }
+
+    suite.addTestCase({
+        name: "TestExpressionsForSourceURL",
+        test: (resolve, reject) => {
+            for (let _expression_ of expressions)
+                ProtocolTest.evaluateInPage(_expression_);
+
+            InspectorProtocol.eventHandler["Debugger.scriptParsed"] = function(messageObject) {
+                // Ignore named inspector internal scripts.
+                if (messageObject.params.url.startsWith("__WebInspector"))
+                    return;
+
+                // Has a sourceURL, must be one of the valid ones.
+                if (messageObject.params.hasSourceURL) {
+                    let sourceURL = messageObject.params.url;
+                    ProtocolTest.log(`Found Script with sourceURL '${sourceURL}'`);
+                    ProtocolTest.assert(sourceURLExpectations[0] === sourceURL, "Did not expect to see sourceURL: " + sourceURL);
+                    sourceURLExpectations.shift();
+                    if (!sourceURLExpectations.length)
+                        resolve();
+                }
+            }
+        }
+    });
+
+    suite.addTestCase({
+        name: "TestExpressionsForSourceMappingURL",
+        test: (resolve, reject) => {
+            // Rewrite the "sourceURL" to "sourceMappingURL" in the original expressions.
+            for (let _expression_ of expressions)
+                ProtocolTest.evaluateInPage(_expression_.replace(/sourceURL/g, "sourceMappingURL"));
+
+            InspectorProtocol.eventHandler["Debugger.scriptParsed"] = function(messageObject) {
+                // Has a sourceMapURL, must be one of the valid ones.
+                if (messageObject.params.sourceMapURL) {
+                    let sourceMappingURL = messageObject.params.sourceMapURL;
+                    ProtocolTest.log(`Found Script with sourceMappingURL '${sourceMappingURL}'`);
+                    ProtocolTest.assert(sourceMappingURLExpectations[0] === sourceMappingURL, "Did not expect to see sourceMappingURL: " + sourceMappingURL);
+                    sourceMappingURLExpectations.shift();
+                    if (!sourceMappingURLExpectations.length)
+                        resolve();
+                }
+            }
+        }
+    });
+
+    // ------
+
+    addInvalidTestCase({
+        description: "Evaluation without a SourceURL.",
+        _expression_: "eval('1')",
+    });
+
+    addInvalidTestCase({
+        description: "SourceURL missing '#'.",
+        _expression_: "eval('// sourceURL=invalid.js')",
+    });
+
+    addInvalidTestCase({
+        description: "SourceURL missing space after '#'.",
+        _expression_: "eval('//#sourceURL=invalid.js')",
+    });
+
+    addInvalidTestCase({
+        description: "SourceURL with space before '#'.",
+        _expression_: "eval('// #sourceURL=invalid.js')",
+    });
+
+    addInvalidTestCase({
+        description: "SourceURL with multiple spaces after '#'.",
+        _expression_: "eval('//#  sourceURL=invalid.js')",
+    });
+
+    addInvalidTestCase({
+        description: "SourceURL with space between name and '='.",
+        _expression_: "eval('//# sourceURL =invalid.js')",
+    });
+
+    addInvalidTestCase({
+        description: "SourceURL with quotes in value.",
+        _expression_: "eval('//# sourceURL=\\\'invalid.js\\\'')",
+    });
+
+    addInvalidTestCase({
+        description: "SourceURL value must be a single non-whitespace enclosed value.",
+        _expression_: "eval('//# sourceURL=invalid.js a')",
+    });
+
+    addInvalidTestCase({
+        description: "Unknown directive.",
+        _expression_: "eval('//# unknown=invalid.js')",
+    });
+
+    addInvalidTestCase({
+        description: "Missing parts.",
+        _expression_: "eval('//#')",
+    });
+
+    addInvalidTestCase({
+        description: "Missing parts.",
+        _expression_: "eval('//# ')",
+    });
+
+    addInvalidTestCase({
+        description: "Missing parts.",
+        _expression_: "eval('//# source')",
+    });
+
+    addInvalidTestCase({
+        description: "Missing parts.",
+        _expression_: "eval('//# sourceURL=')",
+    });
+
+    // ------
+
+    addValidTestCase({
+        description: "SourceURL basic form.",
+        _expression_: "eval('//# sourceURL=test1.js')",
+        expected: "test1.js",
+    });
+
+    addValidTestCase({
+        description: "SourceURL extra leading whitespace.",
+        _expression_: "eval('//# sourceURL=   test2.js')",
+        expected: "test2.js",
+    });
+
+    addValidTestCase({
+        description: "SourceURL extra trailing whitespace.",
+        _expression_: "eval('//# sourceURL=test3.js    ')",
+        expected: "test3.js",
+    });
+
+    addValidTestCase({
+        description: "SourceURL extra leading and trailing whitespace.",
+        _expression_: "eval('//# sourceURL=   test4.js   ')",
+        expected: "test4.js",
+    });
+
+    addValidTestCase({
+        description: "SourceURL with tabs.",
+        _expression_: "eval('//#\\tsourceURL=test5.js')",
+        expected: "test5.js",
+    });
+
+    addValidTestCase({
+        description: "SourceURLs not at the start of a line.",
+        _expression_: "eval('1 //# sourceURL=test6.js')",
+        expected: "test6.js",
+    });
+
+    addValidTestCase({
+        description: "SourceURL with deprecated '@' instead of '#'.",
+        _expression_: "eval('//@ sourceURL=test7.js   ')",
+        expected: "test7.js",
+    });
+
+    addValidTestCase({
+        description: "SourceURLs not on the first line.",
+        _expression_: "eval('\\n\\n//# sourceURL=test8.js')",
+        expected: "test8.js",
+    });
+
+    addValidTestCase({
+        description: "Multiple SourceURLs will return the first.",
+        _expression_: "eval('//# sourceURL=test9.js\\n//# sourceURL=second.js')",
+        expected: "test9.js",
+    });
+
+    InspectorProtocol.sendCommand("Debugger.enable", {});
+    suite.runTestCasesAndFinish();
+}
+</script>
+</head>
+<body _onload_="runTest()">
+<p>Tests for the Debugger.scriptParsed sourceURL and sourceMappingURL comment directive parsing.</p>
+</body>
+</html>

Modified: trunk/Source/_javascript_Core/ChangeLog (191134 => 191135)


--- trunk/Source/_javascript_Core/ChangeLog	2015-10-15 20:34:10 UTC (rev 191134)
+++ trunk/Source/_javascript_Core/ChangeLog	2015-10-15 20:50:02 UTC (rev 191135)
@@ -1,3 +1,52 @@
+2015-10-15  Joseph Pecoraro  <pecor...@apple.com>
+
+        Web Inspector: _javascript_Core should parse sourceURL and sourceMappingURL directives
+        https://bugs.webkit.org/show_bug.cgi?id=150096
+
+        Reviewed by Geoffrey Garen.
+
+        * inspector/ContentSearchUtilities.cpp:
+        (Inspector::ContentSearchUtilities::scriptCommentPattern): Deleted.
+        (Inspector::ContentSearchUtilities::findScriptSourceURL): Deleted.
+        (Inspector::ContentSearchUtilities::findScriptSourceMapURL): Deleted.
+        * inspector/ContentSearchUtilities.h:
+        No longer need to search script content.
+
+        * inspector/ScriptDebugServer.cpp:
+        (Inspector::ScriptDebugServer::dispatchDidParseSource):
+        Carry over the sourceURL and sourceMappingURL from the SourceProvider.
+
+        * inspector/agents/InspectorDebuggerAgent.cpp:
+        (Inspector::InspectorDebuggerAgent::sourceMapURLForScript):
+        (Inspector::InspectorDebuggerAgent::didParseSource):
+        No longer do content searching.
+
+        * parser/Lexer.cpp:
+        (JSC::Lexer<T>::setCode):
+        (JSC::Lexer<T>::skipWhitespace):
+        (JSC::Lexer<T>::parseCommentDirective):
+        (JSC::Lexer<T>::parseCommentDirectiveValue):
+        (JSC::Lexer<T>::consume):
+        (JSC::Lexer<T>::lex):
+        * parser/Lexer.h:
+        (JSC::Lexer::sourceURL):
+        (JSC::Lexer::sourceMappingURL):
+        (JSC::Lexer::sourceProvider): Deleted.
+        Give lexer the ability to detect script comment directives.
+        This just consumes characters in single line comments and
+        ultimately sets the sourceURL or sourceMappingURL found.
+
+        * parser/Parser.h:
+        (JSC::Parser<LexerType>::parse):
+        * parser/SourceProvider.h:
+        (JSC::SourceProvider::url):
+        (JSC::SourceProvider::sourceURL):
+        (JSC::SourceProvider::sourceMappingURL):
+        (JSC::SourceProvider::setSourceURL):
+        (JSC::SourceProvider::setSourceMappingURL):
+        After parsing a script, update the Source Provider with the
+        value of directives that may have been found in the script.
+
 2015-10-15  Filip Pizlo  <fpi...@apple.com>
 
         InferredTypeTable should ref its keys

Modified: trunk/Source/_javascript_Core/inspector/ContentSearchUtilities.cpp (191134 => 191135)


--- trunk/Source/_javascript_Core/inspector/ContentSearchUtilities.cpp	2015-10-15 20:34:10 UTC (rev 191134)
+++ trunk/Source/_javascript_Core/inspector/ContentSearchUtilities.cpp	2015-10-15 20:50:02 UTC (rev 191135)
@@ -166,12 +166,6 @@
     return result;
 }
 
-static String scriptCommentPattern(const String& name)
-{
-    // "//# <name>=<value>" and deprecated "//@"
-    return "//[#@][\040\t]" + name + "=[\040\t]*([^\\s\'\"]*)[\040\t]*$";
-}
-
 static String stylesheetCommentPattern(const String& name)
 {
     // "/*# <name>=<value> */" and deprecated "/*@"
@@ -199,16 +193,6 @@
     return content.substring(matches[2], matches[3] - matches[2]);
 }
 
-String findScriptSourceURL(const String& content)
-{
-    return findMagicComment(content, scriptCommentPattern(ASCIILiteral("sourceURL")));
-}
-
-String findScriptSourceMapURL(const String& content)
-{
-    return findMagicComment(content, scriptCommentPattern(ASCIILiteral("sourceMappingURL")));
-}
-
 String findStylesheetSourceMapURL(const String& content)
 {
     return findMagicComment(content, stylesheetCommentPattern(ASCIILiteral("sourceMappingURL")));

Modified: trunk/Source/_javascript_Core/inspector/ContentSearchUtilities.h (191134 => 191135)


--- trunk/Source/_javascript_Core/inspector/ContentSearchUtilities.h	2015-10-15 20:34:10 UTC (rev 191134)
+++ trunk/Source/_javascript_Core/inspector/ContentSearchUtilities.h	2015-10-15 20:50:02 UTC (rev 191135)
@@ -48,8 +48,6 @@
 JS_EXPORT_PRIVATE TextPosition textPositionFromOffset(size_t offset, const Vector<size_t>& lineEndings);
 JS_EXPORT_PRIVATE std::unique_ptr<Vector<size_t>> lineEndings(const String&);
 
-JS_EXPORT_PRIVATE String findScriptSourceURL(const String& content);
-JS_EXPORT_PRIVATE String findScriptSourceMapURL(const String& content);
 JS_EXPORT_PRIVATE String findStylesheetSourceMapURL(const String& content);
 
 } // namespace ContentSearchUtilities

Modified: trunk/Source/_javascript_Core/inspector/ScriptDebugServer.cpp (191134 => 191135)


--- trunk/Source/_javascript_Core/inspector/ScriptDebugServer.cpp	2015-10-15 20:34:10 UTC (rev 191134)
+++ trunk/Source/_javascript_Core/inspector/ScriptDebugServer.cpp	2015-10-15 20:50:02 UTC (rev 191135)
@@ -207,6 +207,8 @@
     script.startLine = sourceProvider->startPosition().m_line.zeroBasedInt();
     script.startColumn = sourceProvider->startPosition().m_column.zeroBasedInt();
     script.isContentScript = isContentScript;
+    script.sourceURL = sourceProvider->sourceURL();
+    script.sourceMappingURL = sourceProvider->sourceMappingURL();
 
     int sourceLength = script.source.length();
     int lineCount = 1;

Modified: trunk/Source/_javascript_Core/inspector/agents/InspectorDebuggerAgent.cpp (191134 => 191135)


--- trunk/Source/_javascript_Core/inspector/agents/InspectorDebuggerAgent.cpp	2015-10-15 20:34:10 UTC (rev 191134)
+++ trunk/Source/_javascript_Core/inspector/agents/InspectorDebuggerAgent.cpp	2015-10-15 20:50:02 UTC (rev 191135)
@@ -604,20 +604,16 @@
 
 String InspectorDebuggerAgent::sourceMapURLForScript(const Script& script)
 {
-    return ContentSearchUtilities::findScriptSourceMapURL(script.source);
+    return script.sourceMappingURL;
 }
 
-void InspectorDebuggerAgent::didParseSource(JSC::SourceID sourceID, const Script& inScript)
+void InspectorDebuggerAgent::didParseSource(JSC::SourceID sourceID, const Script& script)
 {
-    Script script = inScript;
-    if (script.startLine <= 0 && !script.startColumn)
-        script.sourceURL = ContentSearchUtilities::findScriptSourceURL(script.source);
-    script.sourceMappingURL = sourceMapURLForScript(script);
-
     bool hasSourceURL = !script.sourceURL.isEmpty();
     String scriptURL = hasSourceURL ? script.sourceURL : script.url;
     bool* hasSourceURLParam = hasSourceURL ? &hasSourceURL : nullptr;
-    String* sourceMapURLParam = script.sourceMappingURL.isNull() ? nullptr : &script.sourceMappingURL;
+    String sourceMappingURL = sourceMapURLForScript(script);
+    String* sourceMapURLParam = sourceMappingURL.isNull() ? nullptr : &sourceMappingURL;
     const bool* isContentScript = script.isContentScript ? &script.isContentScript : nullptr;
     String scriptIDStr = String::number(sourceID);
     m_frontendDispatcher->scriptParsed(scriptIDStr, scriptURL, script.startLine, script.startColumn, script.endLine, script.endColumn, isContentScript, sourceMapURLParam, hasSourceURLParam);

Modified: trunk/Source/_javascript_Core/parser/Lexer.cpp (191134 => 191135)


--- trunk/Source/_javascript_Core/parser/Lexer.cpp	2015-10-15 20:34:10 UTC (rev 191134)
+++ trunk/Source/_javascript_Core/parser/Lexer.cpp	2015-10-15 20:50:02 UTC (rev 191135)
@@ -25,23 +25,21 @@
 #include "config.h"
 #include "Lexer.h"
 
+#include "BuiltinNames.h"
+#include "Identifier.h"
+#include "JSCInlines.h"
 #include "JSFunctionInlines.h"
-
-#include "BuiltinNames.h"
 #include "JSGlobalObjectFunctions.h"
-#include "Identifier.h"
+#include "KeywordLookup.h"
+#include "Lexer.lut.h"
 #include "Nodes.h"
-#include "JSCInlines.h"
-#include <wtf/dtoa.h>
+#include "Parser.h"
 #include <ctype.h>
 #include <limits.h>
 #include <string.h>
 #include <wtf/Assertions.h>
+#include <wtf/dtoa.h>
 
-#include "KeywordLookup.h"
-#include "Lexer.lut.h"
-#include "Parser.h"
-
 namespace JSC {
 
 bool isLexerKeyword(const Identifier& identifier)
@@ -565,6 +563,8 @@
     m_atLineStart = true;
     m_lineStart = m_code;
     m_lexErrorMessage = String();
+    m_sourceURL = String();
+    m_sourceMappingURL = String();
     
     m_buffer8.reserveInitialCapacity(initialReadBufferCapacity);
     m_buffer16.reserveInitialCapacity((m_codeEnd - m_code) / 2);
@@ -688,6 +688,13 @@
     return m_lastToken == CONTINUE || m_lastToken == BREAK || m_lastToken == RETURN || m_lastToken == THROW;
 }
 
+template <typename T>
+ALWAYS_INLINE void Lexer<T>::skipWhitespace()
+{
+    while (isWhiteSpace(m_current))
+        shift();
+}
+
 static NEVER_INLINE bool isNonLatin1IdentStart(UChar c)
 {
     return U_GET_GC_MASK(c) & U_GC_L_MASK;
@@ -1705,6 +1712,58 @@
 }
 
 template <typename T>
+ALWAYS_INLINE void Lexer<T>::parseCommentDirective()
+{
+    // sourceURL and sourceMappingURL directives.
+    if (!consume("source"))
+        return;
+
+    if (consume("URL="" {
+        if (!m_sourceURL.isEmpty())
+            return;
+        m_sourceURL = parseCommentDirectiveValue();
+        return;
+    }
+
+    if (consume("MappingURL=")) {
+        if (!m_sourceMappingURL.isEmpty())
+            return;
+        m_sourceMappingURL = parseCommentDirectiveValue();
+        return;
+    }
+}
+
+template <typename T>
+ALWAYS_INLINE String Lexer<T>::parseCommentDirectiveValue()
+{
+    skipWhitespace();
+    const T* stringStart = currentSourcePtr();
+    while (!isWhiteSpace(m_current) && !isLineTerminator(m_current) && m_current != '"' && m_current != '\'' && !atEnd())
+        shift();
+    const T* stringEnd = currentSourcePtr();
+    skipWhitespace();
+
+    if (!isLineTerminator(m_current) && !atEnd())
+        return String();
+
+    append8(stringStart, stringEnd - stringStart);
+    return String(m_buffer8.data(), m_buffer8.size());
+}
+
+template <typename T>
+template <unsigned length>
+ALWAYS_INLINE bool Lexer<T>::consume(const char (&input)[length])
+{
+    unsigned lengthToCheck = length - 1; // Ignore the ending NUL byte in the string literal.
+
+    unsigned i = 0;
+    for (; i < lengthToCheck && m_current == input[i]; i++)
+        shift();
+
+    return i == lengthToCheck;
+}
+
+template <typename T>
 bool Lexer<T>::nextTokenIsColon()
 {
     const T* code = m_code;
@@ -1739,8 +1798,7 @@
     m_terminator = false;
 
 start:
-    while (isWhiteSpace(m_current))
-        shift();
+    skipWhitespace();
 
     if (atEnd())
         return EOFTOK;
@@ -1898,7 +1956,7 @@
         shift();
         if (m_current == '/') {
             shift();
-            goto inSingleLineComment;
+            goto inSingleLineCommentCheckForDirectives;
         }
         if (m_current == '*') {
             shift();
@@ -2203,6 +2261,15 @@
     m_atLineStart = false;
     goto returnToken;
 
+inSingleLineCommentCheckForDirectives:
+    // Script comment directives like "//# sourceURL=test.js".
+    if (UNLIKELY((m_current == '#' || m_current == '@') && isWhiteSpace(peek(1)))) {
+        shift();
+        shift();
+        parseCommentDirective();
+    }
+    // Fall through to complete single line comment parsing.
+
 inSingleLineComment:
     while (!isLineTerminator(m_current)) {
         if (atEnd())

Modified: trunk/Source/_javascript_Core/parser/Lexer.h (191134 => 191135)


--- trunk/Source/_javascript_Core/parser/Lexer.h	2015-10-15 20:34:10 UTC (rev 191134)
+++ trunk/Source/_javascript_Core/parser/Lexer.h	2015-10-15 20:50:02 UTC (rev 191135)
@@ -88,6 +88,8 @@
     // Functions for use after parsing.
     bool sawError() const { return m_error; }
     String getErrorMessage() const { return m_lexErrorMessage; }
+    String sourceURL() const { return m_sourceURL; }
+    String sourceMappingURL() const { return m_sourceMappingURL; }
     void clear();
     void setOffset(int offset, int lineStartOffset)
     {
@@ -114,8 +116,6 @@
         m_terminator = terminator;
     }
 
-    SourceProvider* sourceProvider() const { return m_source->provider(); }
-
     JSTokenType lexExpectIdentifier(JSToken*, unsigned, bool strictMode);
 
 private:
@@ -152,6 +152,8 @@
     ALWAYS_INLINE const Identifier* makeEmptyIdentifier();
 
     ALWAYS_INLINE bool lastTokenWasRestrKeyword() const;
+    
+    ALWAYS_INLINE void skipWhitespace();
 
     template <int shiftAmount> void internalShift();
     template <bool shouldCreateIdentifier> ALWAYS_INLINE JSTokenType parseKeyword(JSTokenData*);
@@ -178,6 +180,12 @@
     ALWAYS_INLINE bool parseNumberAfterExponentIndicator();
     ALWAYS_INLINE bool parseMultilineComment();
 
+    ALWAYS_INLINE void parseCommentDirective();
+    ALWAYS_INLINE String parseCommentDirectiveValue();
+
+    template <unsigned length>
+    ALWAYS_INLINE bool consume(const char (&input)[length]);
+
     static const size_t initialReadBufferCapacity = 32;
 
     int m_lineNumber;
@@ -203,6 +211,9 @@
     bool m_error;
     String m_lexErrorMessage;
 
+    String m_sourceURL;
+    String m_sourceMappingURL;
+
     T m_current;
 
     IdentifierArena* m_arena;

Modified: trunk/Source/_javascript_Core/parser/Parser.h (191134 => 191135)


--- trunk/Source/_javascript_Core/parser/Parser.h	2015-10-15 20:34:10 UTC (rev 191134)
+++ trunk/Source/_javascript_Core/parser/Parser.h	2015-10-15 20:50:02 UTC (rev 191135)
@@ -1329,6 +1329,9 @@
                                     m_numConstants);
         result->setLoc(m_source->firstLine(), m_lexer->lineNumber(), m_lexer->currentOffset(), m_lexer->currentLineStartOffset());
         result->setEndOffset(m_lexer->currentOffset());
+
+        m_source->provider()->setSourceURL(m_lexer->sourceURL());
+        m_source->provider()->setSourceMappingURL(m_lexer->sourceMappingURL());
     } else {
         // We can never see a syntax error when reparsing a function, since we should have
         // reported the error when parsing the containing program or eval code. So if we're

Modified: trunk/Source/_javascript_Core/parser/SourceProvider.h (191134 => 191135)


--- trunk/Source/_javascript_Core/parser/SourceProvider.h	2015-10-15 20:34:10 UTC (rev 191134)
+++ trunk/Source/_javascript_Core/parser/SourceProvider.h	2015-10-15 20:50:02 UTC (rev 191135)
@@ -49,7 +49,10 @@
             return source().substringSharingImpl(start, end - start);
         }
 
-        const String& url() { return m_url; }
+        const String& url() const { return m_url; }
+        const String& sourceURL() const { return m_sourceURL; }
+        const String& sourceMappingURL() const { return m_sourceMappingURL; }
+
         TextPosition startPosition() const { return m_startPosition; }
         intptr_t asID()
         {
@@ -62,11 +65,17 @@
         void setValid() { m_validated = true; }
 
     private:
+        template <typename T> friend class Parser;
 
+        void setSourceURL(const String& sourceURL) { m_sourceURL = sourceURL; }
+        void setSourceMappingURL(const String& sourceMappingURL) { m_sourceMappingURL = sourceMappingURL; }
+
         JS_EXPORT_PRIVATE void getID();
         Vector<size_t>& lineStarts();
 
         String m_url;
+        String m_sourceURL;
+        String m_sourceMappingURL;
         TextPosition m_startPosition;
         bool m_validated : 1;
         uintptr_t m_id : sizeof(uintptr_t) * 8 - 1;

Modified: trunk/Source/WebInspectorUI/ChangeLog (191134 => 191135)


--- trunk/Source/WebInspectorUI/ChangeLog	2015-10-15 20:34:10 UTC (rev 191134)
+++ trunk/Source/WebInspectorUI/ChangeLog	2015-10-15 20:50:02 UTC (rev 191135)
@@ -1,3 +1,16 @@
+2015-10-15  Joseph Pecoraro  <pecor...@apple.com>
+
+        Web Inspector: _javascript_Core should parse sourceURL and sourceMappingURL directives
+        https://bugs.webkit.org/show_bug.cgi?id=150096
+
+        Reviewed by Geoffrey Garen.
+
+        * UserInterface/Test/InspectorProtocol.js:
+        (InspectorProtocol._sendMessage):
+        (InspectorProtocol.dispatchMessageFromBackend):
+        This is only used for tests, so avoid console.log
+        and just dump directly to the system console.
+
 2015-10-13  João Oliveira  <he...@jxs.pt>
 
         Web Inspector: Console SearchBar should work more like ContentBrowser FindBanner

Modified: trunk/Source/WebInspectorUI/UserInterface/Test/InspectorProtocol.js (191134 => 191135)


--- trunk/Source/WebInspectorUI/UserInterface/Test/InspectorProtocol.js	2015-10-15 20:34:10 UTC (rev 191134)
+++ trunk/Source/WebInspectorUI/UserInterface/Test/InspectorProtocol.js	2015-10-15 20:50:02 UTC (rev 191135)
@@ -89,7 +89,7 @@
     let messageString = typeof messageObject !== "string" ? JSON.stringify(messageObject) : messageObject;
 
     if (ProtocolTest.dumpInspectorProtocolMessages)
-        console.log(`frontend: ${messageString}`);
+        InspectorFrontendHost.unbufferedLog(`frontend: ${messageString}`);
 
     InspectorFrontendHost.sendMessageToBackend(messageString);
 }
@@ -134,7 +134,7 @@
     // This matches the debug dumping in InspectorBackend, which is bypassed
     // by InspectorProtocol. Return messages should be dumped by InspectorBackend.
     if (ProtocolTest.dumpInspectorProtocolMessages)
-        console.log("backend: " + JSON.stringify(messageObject));
+        InspectorFrontendHost.unbufferedLog("backend: " + JSON.stringify(messageObject));
 
     // If the message has an id, then it is a reply to a command.
     let messageId = messageObject.id;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to