| OLD | NEW |
| 1 /* | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 * Copyright (C) 2010 Google, Inc. All Rights Reserved. | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 * | 3 // found in the LICENSE file. |
| 4 * Redistribution and use in source and binary forms, with or without | |
| 5 * modification, are permitted provided that the following conditions | |
| 6 * are met: | |
| 7 * 1. Redistributions of source code must retain the above copyright | |
| 8 * notice, this list of conditions and the following disclaimer. | |
| 9 * 2. Redistributions in binary form must reproduce the above copyright | |
| 10 * notice, this list of conditions and the following disclaimer in the | |
| 11 * documentation and/or other materials provided with the distribution. | |
| 12 * | |
| 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY | |
| 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
| 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
| 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR | |
| 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
| 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
| 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
| 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | |
| 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 24 */ | |
| 25 | 4 |
| 26 #ifndef HTMLInputStream_h | 5 #ifndef HTMLInputStream_h |
| 27 #define HTMLInputStream_h | 6 #define HTMLInputStream_h |
| 28 | 7 |
| 29 #include "core/html/parser/InputStreamPreprocessor.h" | 8 #include "core/html/parser/InputStreamPreprocessor.h" |
| 30 #include "platform/text/SegmentedString.h" | 9 #include "platform/text/SegmentedString.h" |
| 31 | 10 |
| 32 namespace blink { | 11 namespace blink { |
| 33 | 12 |
| 34 // The InputStream is made up of a sequence of SegmentedStrings: | |
| 35 // | |
| 36 // [--current--][--next--][--next--] ... [--next--] | |
| 37 // /\ (also called m_last) | |
| 38 // L_ current insertion point | |
| 39 // | |
| 40 // The current segmented string is stored in InputStream. Each of the | |
| 41 // afterInsertionPoint buffers are stored in InsertionPointRecords on the | |
| 42 // stack. | |
| 43 // | |
| 44 // We remove characters from the "current" string in the InputStream. | |
| 45 // document.write() will add characters at the current insertion point, | |
| 46 // which appends them to the "current" string. | |
| 47 // | |
| 48 // m_last is a pointer to the last of the afterInsertionPoint strings. | |
| 49 // The network adds data at the end of the InputStream, which appends | |
| 50 // them to the "last" string. | |
| 51 class HTMLInputStream { | 13 class HTMLInputStream { |
| 52 WTF_MAKE_NONCOPYABLE(HTMLInputStream); | 14 WTF_MAKE_NONCOPYABLE(HTMLInputStream); |
| 53 public: | 15 public: |
| 54 HTMLInputStream() | 16 HTMLInputStream() { } |
| 55 : m_last(&m_first) | |
| 56 { | |
| 57 } | |
| 58 | 17 |
| 59 void appendToEnd(const SegmentedString& string) | 18 void appendToEnd(const SegmentedString& string) |
| 60 { | 19 { |
| 61 m_last->append(string); | 20 m_string.append(string); |
| 62 } | |
| 63 | |
| 64 void insertAtCurrentInsertionPoint(const SegmentedString& string) | |
| 65 { | |
| 66 m_first.append(string); | |
| 67 } | |
| 68 | |
| 69 bool hasInsertionPoint() const | |
| 70 { | |
| 71 return &m_first != m_last; | |
| 72 } | 21 } |
| 73 | 22 |
| 74 void markEndOfFile() | 23 void markEndOfFile() |
| 75 { | 24 { |
| 76 m_last->append(SegmentedString(String(&kEndOfFileMarker, 1))); | 25 m_string.append(SegmentedString(String(&kEndOfFileMarker, 1))); |
| 77 m_last->close(); | 26 m_string.close(); |
| 78 } | 27 } |
| 79 | 28 |
| 80 void closeWithoutMarkingEndOfFile() | 29 SegmentedString& current() { return m_string; } |
| 81 { | 30 const SegmentedString& current() const { return m_string; } |
| 82 m_last->close(); | |
| 83 } | |
| 84 | |
| 85 bool haveSeenEndOfFile() const | |
| 86 { | |
| 87 return m_last->isClosed(); | |
| 88 } | |
| 89 | |
| 90 SegmentedString& current() { return m_first; } | |
| 91 const SegmentedString& current() const { return m_first; } | |
| 92 | |
| 93 void splitInto(SegmentedString& next) | |
| 94 { | |
| 95 next = m_first; | |
| 96 m_first = SegmentedString(); | |
| 97 if (m_last == &m_first) { | |
| 98 // We used to only have one SegmentedString in the InputStream | |
| 99 // but now we have two. That means m_first is no longer also | |
| 100 // the m_last string, |next| is now the last one. | |
| 101 m_last = &next; | |
| 102 } | |
| 103 } | |
| 104 | |
| 105 void mergeFrom(SegmentedString& next) | |
| 106 { | |
| 107 m_first.append(next); | |
| 108 if (m_last == &next) { | |
| 109 // The string |next| used to be the last SegmentedString in | |
| 110 // the InputStream. Now that it's been merged into m_first, | |
| 111 // that makes m_first the last one. | |
| 112 m_last = &m_first; | |
| 113 } | |
| 114 if (next.isClosed()) { | |
| 115 // We also need to merge the "closed" state from next to | |
| 116 // m_first. Arguably, this work could be done in append(). | |
| 117 m_first.close(); | |
| 118 } | |
| 119 } | |
| 120 | 31 |
| 121 private: | 32 private: |
| 122 SegmentedString m_first; | 33 SegmentedString m_string; |
| 123 SegmentedString* m_last; | |
| 124 }; | |
| 125 | |
| 126 class InsertionPointRecord { | |
| 127 WTF_MAKE_NONCOPYABLE(InsertionPointRecord); | |
| 128 public: | |
| 129 explicit InsertionPointRecord(HTMLInputStream& inputStream) | |
| 130 : m_inputStream(&inputStream) | |
| 131 { | |
| 132 m_line = m_inputStream->current().currentLine(); | |
| 133 m_column = m_inputStream->current().currentColumn(); | |
| 134 m_inputStream->splitInto(m_next); | |
| 135 // We 'fork' current position and use it for the generated script part. | |
| 136 // This is a bit weird, because generated part does not have positions w
ithin an HTML document. | |
| 137 m_inputStream->current().setCurrentPosition(m_line, m_column, 0); | |
| 138 } | |
| 139 | |
| 140 ~InsertionPointRecord() | |
| 141 { | |
| 142 // Some inserted text may have remained in input stream. E.g. if script
has written "&" or "<table", | |
| 143 // it stays in buffer because it cannot be properly tokenized before we
see next part. | |
| 144 int unparsedRemainderLength = m_inputStream->current().length(); | |
| 145 m_inputStream->mergeFrom(m_next); | |
| 146 // We restore position for the character that goes right after unparsed
remainder. | |
| 147 m_inputStream->current().setCurrentPosition(m_line, m_column, unparsedRe
mainderLength); | |
| 148 } | |
| 149 | |
| 150 private: | |
| 151 HTMLInputStream* m_inputStream; | |
| 152 SegmentedString m_next; | |
| 153 OrdinalNumber m_line; | |
| 154 OrdinalNumber m_column; | |
| 155 }; | 34 }; |
| 156 | 35 |
| 157 } | 36 } |
| 158 | 37 |
| 159 #endif | 38 #endif |
| OLD | NEW |