2010-12-25 Peter Rybin <peter.rybin@gmail.com>
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 26 Dec 2010 01:49:06 +0000 (01:49 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 26 Dec 2010 01:49:06 +0000 (01:49 +0000)
        Reviewed by Adam Barth.

        Adds currentColumn (and currentLine) to SegmentedString. Switches
        HTMLTreeBuilder to HTMLDocumentParser::textPosition when it
        needs position for a <script> tag.

        SegmentedString should provide column position
        https://bugs.webkit.org/show_bug.cgi?id=51311

        * html/parser/HTMLDocumentParser.cpp:
        (WebCore::HTMLDocumentParser::HTMLDocumentParser):
        (WebCore::HTMLDocumentParser::textPosition):
        * html/parser/HTMLInputStream.h:
        (WebCore::HTMLInputStream::current):
        (WebCore::InsertionPointRecord::InsertionPointRecord):
        (WebCore::InsertionPointRecord::~InsertionPointRecord):
        * html/parser/HTMLTreeBuilder.cpp:
        (WebCore::HTMLTreeBuilder::HTMLTreeBuilder):
        (WebCore::HTMLTreeBuilder::processScriptStartTag):
        * html/parser/HTMLTreeBuilder.h:
        (WebCore::HTMLTreeBuilder::create):
        * platform/text/SegmentedString.cpp:
        (WebCore::SegmentedString::operator=):
        (WebCore::SegmentedString::numberOfCharactersConsumedSlow):
        (WebCore::SegmentedString::advanceSlowCase):
        (WebCore::SegmentedString::currentLine):
        (WebCore::SegmentedString::currentColumn):
        (WebCore::SegmentedString::setCurrentPosition):
        * platform/text/SegmentedString.h:
        (WebCore::SegmentedString::SegmentedString):
        (WebCore::SegmentedString::advancePastNewline):
        (WebCore::SegmentedString::advance):
        (WebCore::SegmentedString::numberOfCharactersConsumed):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@74663 268f45cc-cd09-0410-ab3c-d52691b4dbfc

WebCore/ChangeLog
WebCore/html/parser/HTMLDocumentParser.cpp
WebCore/html/parser/HTMLDocumentParser.h
WebCore/html/parser/HTMLInputStream.h
WebCore/html/parser/HTMLTreeBuilder.cpp
WebCore/html/parser/HTMLTreeBuilder.h
WebCore/platform/text/SegmentedString.cpp
WebCore/platform/text/SegmentedString.h

index 3504468..aacb440 100644 (file)
@@ -1,3 +1,39 @@
+2010-12-25  Peter Rybin  <peter.rybin@gmail.com>
+
+        Reviewed by Adam Barth.
+
+        Adds currentColumn (and currentLine) to SegmentedString. Switches
+        HTMLTreeBuilder to HTMLDocumentParser::textPosition when it
+        needs position for a <script> tag.
+
+        SegmentedString should provide column position
+        https://bugs.webkit.org/show_bug.cgi?id=51311
+
+        * html/parser/HTMLDocumentParser.cpp:
+        (WebCore::HTMLDocumentParser::HTMLDocumentParser):
+        (WebCore::HTMLDocumentParser::textPosition):
+        * html/parser/HTMLInputStream.h:
+        (WebCore::HTMLInputStream::current):
+        (WebCore::InsertionPointRecord::InsertionPointRecord):
+        (WebCore::InsertionPointRecord::~InsertionPointRecord):
+        * html/parser/HTMLTreeBuilder.cpp:
+        (WebCore::HTMLTreeBuilder::HTMLTreeBuilder):
+        (WebCore::HTMLTreeBuilder::processScriptStartTag):
+        * html/parser/HTMLTreeBuilder.h:
+        (WebCore::HTMLTreeBuilder::create):
+        * platform/text/SegmentedString.cpp:
+        (WebCore::SegmentedString::operator=):
+        (WebCore::SegmentedString::numberOfCharactersConsumedSlow):
+        (WebCore::SegmentedString::advanceSlowCase):
+        (WebCore::SegmentedString::currentLine):
+        (WebCore::SegmentedString::currentColumn):
+        (WebCore::SegmentedString::setCurrentPosition):
+        * platform/text/SegmentedString.h:
+        (WebCore::SegmentedString::SegmentedString):
+        (WebCore::SegmentedString::advancePastNewline):
+        (WebCore::SegmentedString::advance):
+        (WebCore::SegmentedString::numberOfCharactersConsumed):
+
 2010-12-25  Andreas Kling  <kling@webkit.org>
 
         Reviewed by Kenneth Rohde Christiansen.
index c32f9db..0e3a10b 100644 (file)
@@ -79,7 +79,7 @@ HTMLDocumentParser::HTMLDocumentParser(HTMLDocument* document, bool reportErrors
     : ScriptableDocumentParser(document)
     , m_tokenizer(HTMLTokenizer::create(usePreHTML5ParserQuirks(document)))
     , m_scriptRunner(HTMLScriptRunner::create(document, this))
-    , m_treeBuilder(HTMLTreeBuilder::create(m_tokenizer.get(), document, reportErrors, usePreHTML5ParserQuirks(document)))
+    , m_treeBuilder(HTMLTreeBuilder::create(this, document, reportErrors, usePreHTML5ParserQuirks(document)))
     , m_parserScheduler(HTMLParserScheduler::create(this))
     , m_endWasDelayed(false)
     , m_writeNestingLevel(0)
@@ -91,7 +91,7 @@ HTMLDocumentParser::HTMLDocumentParser(HTMLDocument* document, bool reportErrors
 HTMLDocumentParser::HTMLDocumentParser(DocumentFragment* fragment, Element* contextElement, FragmentScriptingPermission scriptingPermission)
     : ScriptableDocumentParser(fragment->document())
     , m_tokenizer(HTMLTokenizer::create(usePreHTML5ParserQuirks(fragment->document())))
-    , m_treeBuilder(HTMLTreeBuilder::create(m_tokenizer.get(), fragment, contextElement, scriptingPermission, usePreHTML5ParserQuirks(fragment->document())))
+    , m_treeBuilder(HTMLTreeBuilder::create(this, fragment, contextElement, scriptingPermission, usePreHTML5ParserQuirks(fragment->document())))
     , m_endWasDelayed(false)
     , m_writeNestingLevel(0)
 {
@@ -407,11 +407,12 @@ int HTMLDocumentParser::lineNumber() const
 
 TextPosition0 HTMLDocumentParser::textPosition() const
 {
-    int lineZeroBased = m_tokenizer->lineNumber();
-    int columnOneBased = m_tokenizer->columnNumber();
+    const SegmentedString& currentString = m_input.current();
+    WTF::ZeroBasedNumber line = currentString.currentLine();
+    WTF::ZeroBasedNumber column = currentString.currentColumn();
+    ASSERT(m_tokenizer->lineNumber() == line.zeroBasedInt());
 
-    return TextPosition0(WTF::ZeroBasedNumber::fromZeroBasedInt(lineZeroBased),
-        WTF::OneBasedNumber::fromOneBasedInt(columnOneBased).convertToZeroBased());
+    return TextPosition0(line, column);
 }
 
 bool HTMLDocumentParser::isWaitingForScripts() const
index 05053df..fca269a 100644 (file)
@@ -69,6 +69,10 @@ public:
     
     static bool usePreHTML5ParserQuirks(Document*);
 
+    HTMLTokenizer* tokenizer() const { return m_tokenizer.get(); }
+
+    virtual TextPosition0 textPosition() const;
+
 protected:
     virtual void insert(const SegmentedString&);
     virtual void append(const SegmentedString&);
@@ -77,7 +81,6 @@ protected:
     HTMLDocumentParser(HTMLDocument*, bool reportErrors);
     HTMLDocumentParser(DocumentFragment*, Element* contextElement, FragmentScriptingPermission);
 
-    HTMLTokenizer* tokenizer() const { return m_tokenizer.get(); }
     HTMLTreeBuilder* treeBuilder() const { return m_treeBuilder.get(); }
 
 private:
@@ -92,7 +95,6 @@ private:
     virtual bool isExecutingScript() const;
     virtual void executeScriptsWaitingForStylesheets();
     virtual int lineNumber() const;
-    virtual TextPosition0 textPosition() const;
 
     // HTMLScriptRunnerHost
     virtual void watchForLoad(CachedResource*);
index a709bd9..1bfbaf9 100644 (file)
@@ -94,6 +94,7 @@ public:
     }
 
     SegmentedString& current() { return m_first; }
+    const SegmentedString& current() const { return m_first; }
 
     void splitInto(SegmentedString& next)
     {
@@ -133,17 +134,29 @@ public:
     explicit InsertionPointRecord(HTMLInputStream& inputStream)
         : m_inputStream(&inputStream)
     {
+        m_line = m_inputStream->current().currentLine();
+        m_column = m_inputStream->current().currentColumn();
         m_inputStream->splitInto(m_next);
+        // We 'fork' current position and use it for the generated script part.
+        // This is a bit weird, because generated part does not have positions within an HTML document.
+        m_inputStream->current().setCurrentPosition(m_line, m_column, 0);
     }
 
     ~InsertionPointRecord()
     {
+        // Some inserted text may have remained in input stream. E.g. if script has written "&amp" or "<table",
+        // it stays in buffer because it cannot be properly tokenized before we see next part.
+        int unparsedRemainderLength = m_inputStream->current().length();
         m_inputStream->mergeFrom(m_next);
+        // We restore position for the character that goes right after unparsed remainder.
+        m_inputStream->current().setCurrentPosition(m_line, m_column, unparsedRemainderLength);
     }
 
 private:
     HTMLInputStream* m_inputStream;
     SegmentedString m_next;
+    WTF::ZeroBasedNumber m_line;
+    WTF::ZeroBasedNumber m_column;
 };
 
 }
index 3d39131..c37d6f1 100644 (file)
@@ -32,6 +32,7 @@
 #include "DocumentType.h"
 #include "Frame.h"
 #include "HTMLDocument.h"
+#include "HTMLDocumentParser.h"
 #include "HTMLElementFactory.h"
 #include "HTMLFormElement.h"
 #include "HTMLHtmlElement.h"
@@ -336,7 +337,7 @@ private:
 };
 
 
-HTMLTreeBuilder::HTMLTreeBuilder(HTMLTokenizer* tokenizer, HTMLDocument* document, bool reportErrors, bool usePreHTML5ParserQuirks)
+HTMLTreeBuilder::HTMLTreeBuilder(HTMLDocumentParser* parser, HTMLDocument* document, bool reportErrors, bool usePreHTML5ParserQuirks)
     : m_framesetOk(true)
     , m_document(document)
     , m_tree(document, FragmentScriptingAllowed, false)
@@ -344,7 +345,7 @@ HTMLTreeBuilder::HTMLTreeBuilder(HTMLTokenizer* tokenizer, HTMLDocument* documen
     , m_isPaused(false)
     , m_insertionMode(InitialMode)
     , m_originalInsertionMode(InitialMode)
-    , m_tokenizer(tokenizer)
+    , m_parser(parser)
     , m_scriptToProcessStartPosition(uninitializedPositionValue1())
     , m_lastScriptElementStartPosition(TextPosition0::belowRangePosition())
     , m_usePreHTML5ParserQuirks(usePreHTML5ParserQuirks)
@@ -354,7 +355,7 @@ HTMLTreeBuilder::HTMLTreeBuilder(HTMLTokenizer* tokenizer, HTMLDocument* documen
 
 // FIXME: Member variables should be grouped into self-initializing structs to
 // minimize code duplication between these constructors.
-HTMLTreeBuilder::HTMLTreeBuilder(HTMLTokenizer* tokenizer, DocumentFragment* fragment, Element* contextElement, FragmentScriptingPermission scriptingPermission, bool usePreHTML5ParserQuirks)
+HTMLTreeBuilder::HTMLTreeBuilder(HTMLDocumentParser* parser, DocumentFragment* fragment, Element* contextElement, FragmentScriptingPermission scriptingPermission, bool usePreHTML5ParserQuirks)
     : m_framesetOk(true)
     , m_fragmentContext(fragment, contextElement, scriptingPermission)
     , m_document(m_fragmentContext.document())
@@ -363,7 +364,7 @@ HTMLTreeBuilder::HTMLTreeBuilder(HTMLTokenizer* tokenizer, DocumentFragment* fra
     , m_isPaused(false)
     , m_insertionMode(InitialMode)
     , m_originalInsertionMode(InitialMode)
-    , m_tokenizer(tokenizer)
+    , m_parser(parser)
     , m_scriptToProcessStartPosition(uninitializedPositionValue1())
     , m_lastScriptElementStartPosition(TextPosition0::belowRangePosition())
     , m_usePreHTML5ParserQuirks(usePreHTML5ParserQuirks)
@@ -453,8 +454,8 @@ void HTMLTreeBuilder::constructTreeFromAtomicToken(AtomicHTMLToken& token)
     // Swallowing U+0000 characters isn't in the HTML5 spec, but turning all
     // the U+0000 characters into replacement characters has compatibility
     // problems.
-    m_tokenizer->setForceNullCharacterReplacement(m_insertionMode == TextMode || m_insertionMode == InForeignContentMode);
-    m_tokenizer->setShouldAllowCDATA(m_insertionMode == InForeignContentMode && m_tree.currentElement()->namespaceURI() != xhtmlNamespaceURI);
+    m_parser->tokenizer()->setForceNullCharacterReplacement(m_insertionMode == TextMode || m_insertionMode == InForeignContentMode);
+    m_parser->tokenizer()->setShouldAllowCDATA(m_insertionMode == InForeignContentMode && m_tree.currentElement()->namespaceURI() != xhtmlNamespaceURI);
 }
 
 void HTMLTreeBuilder::processToken(AtomicHTMLToken& token)
@@ -797,7 +798,7 @@ void HTMLTreeBuilder::processStartTagForInBody(AtomicHTMLToken& token)
     if (token.name() == preTag || token.name() == listingTag) {
         processFakePEndTagIfPInButtonScope();
         m_tree.insertHTMLElement(token);
-        m_tokenizer->setSkipLeadingNewLineForListing(true);
+        m_parser->tokenizer()->setSkipLeadingNewLineForListing(true);
         m_framesetOk = false;
         return;
     }
@@ -821,7 +822,7 @@ void HTMLTreeBuilder::processStartTagForInBody(AtomicHTMLToken& token)
     if (token.name() == plaintextTag) {
         processFakePEndTagIfPInButtonScope();
         m_tree.insertHTMLElement(token);
-        m_tokenizer->setState(HTMLTokenizer::PLAINTEXTState);
+        m_parser->tokenizer()->setState(HTMLTokenizer::PLAINTEXTState);
         return;
     }
     if (token.name() == buttonTag) {
@@ -918,8 +919,8 @@ void HTMLTreeBuilder::processStartTagForInBody(AtomicHTMLToken& token)
     }
     if (token.name() == textareaTag) {
         m_tree.insertHTMLElement(token);
-        m_tokenizer->setSkipLeadingNewLineForListing(true);
-        m_tokenizer->setState(HTMLTokenizer::RCDATAState);
+        m_parser->tokenizer()->setSkipLeadingNewLineForListing(true);
+        m_parser->tokenizer()->setState(HTMLTokenizer::RCDATAState);
         m_originalInsertionMode = m_insertionMode;
         m_framesetOk = false;
         setInsertionMode(TextMode);
@@ -2205,8 +2206,8 @@ void HTMLTreeBuilder::processEndTag(AtomicHTMLToken& token)
             // self-closing script tag was encountered and pre-HTML5 parser
             // quirks are enabled. We must set the tokenizer's state to
             // DataState explicitly if the tokenizer didn't have a chance to.
-            ASSERT(m_tokenizer->state() == HTMLTokenizer::DataState || m_usePreHTML5ParserQuirks);
-            m_tokenizer->setState(HTMLTokenizer::DataState);
+            ASSERT(m_parser->tokenizer()->state() == HTMLTokenizer::DataState || m_usePreHTML5ParserQuirks);
+            m_parser->tokenizer()->setState(HTMLTokenizer::DataState);
             return;
         }
         m_tree.openElements()->pop();
@@ -2755,7 +2756,7 @@ void HTMLTreeBuilder::processGenericRCDATAStartTag(AtomicHTMLToken& token)
 {
     ASSERT(token.type() == HTMLToken::StartTag);
     m_tree.insertHTMLElement(token);
-    m_tokenizer->setState(HTMLTokenizer::RCDATAState);
+    m_parser->tokenizer()->setState(HTMLTokenizer::RCDATAState);
     m_originalInsertionMode = m_insertionMode;
     setInsertionMode(TextMode);
 }
@@ -2764,7 +2765,7 @@ void HTMLTreeBuilder::processGenericRawTextStartTag(AtomicHTMLToken& token)
 {
     ASSERT(token.type() == HTMLToken::StartTag);
     m_tree.insertHTMLElement(token);
-    m_tokenizer->setState(HTMLTokenizer::RAWTEXTState);
+    m_parser->tokenizer()->setState(HTMLTokenizer::RAWTEXTState);
     m_originalInsertionMode = m_insertionMode;
     setInsertionMode(TextMode);
 }
@@ -2773,10 +2774,13 @@ void HTMLTreeBuilder::processScriptStartTag(AtomicHTMLToken& token)
 {
     ASSERT(token.type() == HTMLToken::StartTag);
     m_tree.insertScriptElement(token);
-    m_tokenizer->setState(HTMLTokenizer::ScriptDataState);
+    m_parser->tokenizer()->setState(HTMLTokenizer::ScriptDataState);
     m_originalInsertionMode = m_insertionMode;
 
-    TextPosition0 position = TextPosition0(WTF::ZeroBasedNumber::fromZeroBasedInt(m_tokenizer->lineNumber()), WTF::ZeroBasedNumber::base());
+    TextPosition0 position = m_parser->textPosition();
+
+    ASSERT(position.m_line.zeroBasedInt() == m_parser->tokenizer()->lineNumber());
+
     m_lastScriptElementStartPosition = position;
 
     setInsertionMode(TextMode);
index ebed810..17b77b7 100644 (file)
@@ -49,16 +49,17 @@ class Frame;
 class HTMLToken;
 class HTMLDocument;
 class Node;
+class HTMLDocumentParser;
 
 class HTMLTreeBuilder : public Noncopyable {
 public:
-    static PassOwnPtr<HTMLTreeBuilder> create(HTMLTokenizer* tokenizer, HTMLDocument* document, bool reportErrors, bool usePreHTML5ParserQuirks)
+    static PassOwnPtr<HTMLTreeBuilder> create(HTMLDocumentParser* parser, HTMLDocument* document, bool reportErrors, bool usePreHTML5ParserQuirks)
     {
-        return adoptPtr(new HTMLTreeBuilder(tokenizer, document, reportErrors, usePreHTML5ParserQuirks));
+        return adoptPtr(new HTMLTreeBuilder(parser, document, reportErrors, usePreHTML5ParserQuirks));
     }
-    static PassOwnPtr<HTMLTreeBuilder> create(HTMLTokenizer* tokenizer, DocumentFragment* fragment, Element* contextElement, FragmentScriptingPermission scriptingPermission, bool usePreHTML5ParserQuirks)
+    static PassOwnPtr<HTMLTreeBuilder> create(HTMLDocumentParser* parser, DocumentFragment* fragment, Element* contextElement, FragmentScriptingPermission scriptingPermission, bool usePreHTML5ParserQuirks)
     {
-        return adoptPtr(new HTMLTreeBuilder(tokenizer, fragment, contextElement, scriptingPermission, usePreHTML5ParserQuirks));
+        return adoptPtr(new HTMLTreeBuilder(parser, fragment, contextElement, scriptingPermission, usePreHTML5ParserQuirks));
     }
     ~HTMLTreeBuilder();
 
@@ -113,8 +114,8 @@ private:
         AfterAfterFramesetMode,
     };
 
-    HTMLTreeBuilder(HTMLTokenizer*, HTMLDocument*, bool reportErrors, bool usePreHTML5ParserQuirks);
-    HTMLTreeBuilder(HTMLTokenizer*, DocumentFragment*, Element* contextElement, FragmentScriptingPermission, bool usePreHTML5ParserQuirks);
+    HTMLTreeBuilder(HTMLDocumentParser* parser, HTMLDocument*, bool reportErrors, bool usePreHTML5ParserQuirks);
+    HTMLTreeBuilder(HTMLDocumentParser* parser, DocumentFragment*, Element* contextElement, FragmentScriptingPermission, bool usePreHTML5ParserQuirks);
 
     void processToken(AtomicHTMLToken&);
 
@@ -244,9 +245,9 @@ private:
     // http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#pending-table-character-tokens
     Vector<UChar> m_pendingTableCharacters;
 
-    // HTML5 spec requires that we be able to change the state of the tokenizer
-    // from within parser actions.
-    HTMLTokenizer* m_tokenizer;
+    // We access parser because HTML5 spec requires that we be able to change the state of the tokenizer
+    // from within parser actions. We also need it to track the current position.
+    HTMLDocumentParser* m_parser;
 
     RefPtr<Element> m_scriptToProcess; // <script> tag which needs processing before resuming the parser.
     TextPosition1 m_scriptToProcessStartPosition; // Starting line number of the script tag needing processing.
index b9ff503..6a26581 100644 (file)
@@ -53,6 +53,9 @@ const SegmentedString& SegmentedString::operator=(const SegmentedString &other)
         m_currentChar = other.m_currentChar;
     m_closed = other.m_closed;
     m_numberOfCharactersConsumedPriorToCurrentString = other.m_numberOfCharactersConsumedPriorToCurrentString;
+    m_numberOfCharactersConsumedPriorToCurrentLine = other.m_numberOfCharactersConsumedPriorToCurrentLine;
+    m_currentLine = other.m_currentLine;
+
     return *this;
 }
 
@@ -183,6 +186,17 @@ void SegmentedString::advanceSubstring()
     }
 }
 
+int SegmentedString::numberOfCharactersConsumedSlow() const
+{
+    int result = m_numberOfCharactersConsumedPriorToCurrentString + m_currentString.numberOfCharactersConsumed();
+    if (m_pushedChar1) {
+        --result;
+        if (m_pushedChar2)
+            --result;
+    }
+    return result;
+}
+
 String SegmentedString::toString() const
 {
     String result;
@@ -229,12 +243,32 @@ void SegmentedString::advanceSlowCase(int& lineNumber)
         m_pushedChar1 = m_pushedChar2;
         m_pushedChar2 = 0;
     } else if (m_currentString.m_current) {
-        if (*m_currentString.m_current++ == '\n' && m_currentString.doNotExcludeLineNumbers())
+        if (*m_currentString.m_current++ == '\n' && m_currentString.doNotExcludeLineNumbers()) {
             ++lineNumber;
+            ++m_currentLine;
+            m_numberOfCharactersConsumedPriorToCurrentLine = numberOfCharactersConsumed();
+        }
         if (--m_currentString.m_length == 0)
             advanceSubstring();
     }
     m_currentChar = m_pushedChar1 ? &m_pushedChar1 : m_currentString.m_current;
 }
 
+WTF::ZeroBasedNumber SegmentedString::currentLine() const
+{
+    return WTF::ZeroBasedNumber::fromZeroBasedInt(m_currentLine);
+}
+
+WTF::ZeroBasedNumber SegmentedString::currentColumn() const
+{
+    int zeroBasedColumn = numberOfCharactersConsumedSlow() - m_numberOfCharactersConsumedPriorToCurrentLine;
+    return WTF::ZeroBasedNumber::fromZeroBasedInt(zeroBasedColumn);
+}
+
+void SegmentedString::setCurrentPosition(WTF::ZeroBasedNumber line, WTF::ZeroBasedNumber columnAftreProlog, int prologLength)
+{
+    m_currentLine = line.zeroBasedInt();
+    m_numberOfCharactersConsumedPriorToCurrentLine = numberOfCharactersConsumedSlow() + prologLength - columnAftreProlog.zeroBasedInt();
+}
+
 }
index 91c2cbe..5f548c7 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "PlatformString.h"
 #include <wtf/Deque.h>
+#include <wtf/text/TextPosition.h>
 
 namespace WebCore {
 
@@ -75,6 +76,8 @@ public:
         , m_pushedChar2(0)
         , m_currentChar(0)
         , m_numberOfCharactersConsumedPriorToCurrentString(0)
+        , m_numberOfCharactersConsumedPriorToCurrentLine(0)
+        , m_currentLine(0)
         , m_composite(false)
         , m_closed(false)
     {
@@ -86,6 +89,8 @@ public:
         , m_currentString(str)
         , m_currentChar(m_currentString.m_current)
         , m_numberOfCharactersConsumedPriorToCurrentString(0)
+        , m_numberOfCharactersConsumedPriorToCurrentLine(0)
+        , m_currentLine(0)
         , m_composite(false)
         , m_closed(false)
     {
@@ -155,7 +160,11 @@ public:
     {
         ASSERT(*current() == '\n');
         if (!m_pushedChar1 && m_currentString.m_length > 1) {
-            lineNumber += m_currentString.doNotExcludeLineNumbers();
+            int newLineFlag = m_currentString.doNotExcludeLineNumbers();
+            lineNumber += newLineFlag;
+            m_currentLine += newLineFlag;
+            if (newLineFlag)
+                m_numberOfCharactersConsumedPriorToCurrentLine = numberOfCharactersConsumed();
             --m_currentString.m_length;
             m_currentChar = ++m_currentString.m_current;
             return;
@@ -177,7 +186,11 @@ public:
     void advance(int& lineNumber)
     {
         if (!m_pushedChar1 && m_currentString.m_length > 1) {
-            lineNumber += (*m_currentString.m_current == '\n') & m_currentString.doNotExcludeLineNumbers();
+            int newLineFlag = (*m_currentString.m_current == '\n') & m_currentString.doNotExcludeLineNumbers();
+            lineNumber += newLineFlag;
+            m_currentLine += newLineFlag;
+            if (newLineFlag)
+                m_numberOfCharactersConsumedPriorToCurrentLine = numberOfCharactersConsumed() + 1;
             --m_currentString.m_length;
             m_currentChar = ++m_currentString.m_current;
             return;
@@ -191,18 +204,28 @@ public:
 
     bool escaped() const { return m_pushedChar1; }
 
-    int numberOfCharactersConsumed()
+    int numberOfCharactersConsumed() const
     {
         // We don't currently handle the case when there are pushed character.
         ASSERT(!m_pushedChar1);
         return m_numberOfCharactersConsumedPriorToCurrentString + m_currentString.numberOfCharactersConsumed();
     }
 
+    int numberOfCharactersConsumedSlow() const;
+
     String toString() const;
 
     const UChar& operator*() const { return *current(); }
     const UChar* operator->() const { return current(); }
     
+
+    // The method is moderately slow, comparing to currentLine method.
+    WTF::ZeroBasedNumber currentColumn() const;
+    WTF::ZeroBasedNumber currentLine() const;
+    // Sets value of line/column variables. Column is specified indirectly by a parameter columnAftreProlog
+    // which is a value of column that we should get after a prolog (first prologLength characters) has been consumed.
+    void setCurrentPosition(WTF::ZeroBasedNumber line, WTF::ZeroBasedNumber columnAftreProlog, int prologLength);
+
 private:
     void append(const SegmentedSubstring&);
     void prepend(const SegmentedSubstring&);
@@ -247,6 +270,8 @@ private:
     SegmentedSubstring m_currentString;
     const UChar* m_currentChar;
     int m_numberOfCharactersConsumedPriorToCurrentString;
+    int m_numberOfCharactersConsumedPriorToCurrentLine;
+    int m_currentLine;
     Deque<SegmentedSubstring> m_substrings;
     bool m_composite;
     bool m_closed;