| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2010 Google, Inc. All Rights Reserved. | 2 * Copyright (C) 2010 Google, Inc. All Rights Reserved. |
| 3 * Copyright (C) 2011 Apple Inc. All rights reserved. | 3 * Copyright (C) 2011 Apple Inc. All rights reserved. |
| 4 * | 4 * |
| 5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
| 6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
| 7 * are met: | 7 * are met: |
| 8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
| (...skipping 14 matching lines...) Expand all Loading... |
| 25 */ | 25 */ |
| 26 | 26 |
| 27 #include "config.h" | 27 #include "config.h" |
| 28 #include "core/html/parser/HTMLElementStack.h" | 28 #include "core/html/parser/HTMLElementStack.h" |
| 29 | 29 |
| 30 #include "core/dom/Element.h" | 30 #include "core/dom/Element.h" |
| 31 #include "core/html/HTMLElement.h" | 31 #include "core/html/HTMLElement.h" |
| 32 | 32 |
| 33 namespace blink { | 33 namespace blink { |
| 34 | 34 |
| 35 HTMLElementStack::ElementRecord::ElementRecord(PassRefPtrWillBeRawPtr<HTMLStackI
tem> item, PassOwnPtrWillBeRawPtr<ElementRecord> next) | 35 HTMLElementStack::ElementRecord::ElementRecord(PassRefPtr<ContainerNode> node, P
assOwnPtr<ElementRecord> next) |
| 36 : m_item(item) | 36 : m_node(node) |
| 37 , m_next(next) | 37 , m_next(next) |
| 38 { | 38 { |
| 39 ASSERT(m_item); | 39 ASSERT(m_node); |
| 40 } | 40 } |
| 41 | 41 |
| 42 #if !ENABLE(OILPAN) | |
| 43 HTMLElementStack::ElementRecord::~ElementRecord() | 42 HTMLElementStack::ElementRecord::~ElementRecord() |
| 44 { | 43 { |
| 45 } | 44 } |
| 46 #endif | |
| 47 | |
| 48 void HTMLElementStack::ElementRecord::trace(Visitor* visitor) | |
| 49 { | |
| 50 #if ENABLE(OILPAN) | |
| 51 visitor->trace(m_item); | |
| 52 visitor->trace(m_next); | |
| 53 #endif | |
| 54 } | |
| 55 | 45 |
| 56 HTMLElementStack::HTMLElementStack() | 46 HTMLElementStack::HTMLElementStack() |
| 57 : m_rootNode(nullptr) | 47 : m_rootNode(nullptr) |
| 58 , m_stackDepth(0) | 48 , m_stackDepth(0) |
| 59 { | 49 { |
| 60 } | 50 } |
| 61 | 51 |
| 62 HTMLElementStack::~HTMLElementStack() | 52 HTMLElementStack::~HTMLElementStack() |
| 63 { | 53 { |
| 64 } | 54 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 78 toElement(node).finishParsingChildren(); | 68 toElement(node).finishParsingChildren(); |
| 79 m_top = m_top->releaseNext(); | 69 m_top = m_top->releaseNext(); |
| 80 } | 70 } |
| 81 } | 71 } |
| 82 | 72 |
| 83 void HTMLElementStack::pop() | 73 void HTMLElementStack::pop() |
| 84 { | 74 { |
| 85 popCommon(); | 75 popCommon(); |
| 86 } | 76 } |
| 87 | 77 |
| 88 void HTMLElementStack::popUntil(const AtomicString& tagName) | |
| 89 { | |
| 90 while (!topStackItem()->hasLocalName(tagName)) { | |
| 91 // pop() will ASSERT if a <body>, <head> or <html> will be popped. | |
| 92 pop(); | |
| 93 } | |
| 94 } | |
| 95 | |
| 96 void HTMLElementStack::popUntil(Element* element) | 78 void HTMLElementStack::popUntil(Element* element) |
| 97 { | 79 { |
| 98 while (top() != element) | 80 while (top() != element) |
| 99 pop(); | 81 pop(); |
| 100 } | 82 } |
| 101 | 83 |
| 102 void HTMLElementStack::popUntilPopped(Element* element) | 84 void HTMLElementStack::popUntilPopped(Element* element) |
| 103 { | 85 { |
| 104 popUntil(element); | 86 popUntil(element); |
| 105 pop(); | 87 pop(); |
| 106 } | 88 } |
| 107 | 89 |
| 108 void HTMLElementStack::pushRootNode(PassRefPtrWillBeRawPtr<HTMLStackItem> rootIt
em) | 90 void HTMLElementStack::pushRootNode(PassRefPtr<ContainerNode> root) |
| 109 { | 91 { |
| 110 ASSERT(!m_top); | 92 ASSERT(!m_top); |
| 111 ASSERT(!m_rootNode); | 93 ASSERT(!m_rootNode); |
| 112 m_rootNode = rootItem->node(); | 94 m_rootNode = root.get(); |
| 113 pushCommon(rootItem); | 95 pushCommon(root); |
| 114 } | 96 } |
| 115 | 97 |
| 116 void HTMLElementStack::push(PassRefPtrWillBeRawPtr<HTMLStackItem> item) | 98 void HTMLElementStack::push(PassRefPtr<ContainerNode> node) |
| 117 { | 99 { |
| 118 ASSERT(m_rootNode); | 100 ASSERT(m_rootNode); |
| 119 pushCommon(item); | 101 pushCommon(node); |
| 120 } | |
| 121 | |
| 122 void HTMLElementStack::insertAbove(PassRefPtrWillBeRawPtr<HTMLStackItem> item, E
lementRecord* recordBelow) | |
| 123 { | |
| 124 ASSERT(item); | |
| 125 ASSERT(recordBelow); | |
| 126 ASSERT(m_top); | |
| 127 ASSERT(m_rootNode); | |
| 128 if (recordBelow == m_top) { | |
| 129 push(item); | |
| 130 return; | |
| 131 } | |
| 132 | |
| 133 for (ElementRecord* recordAbove = m_top.get(); recordAbove; recordAbove = re
cordAbove->next()) { | |
| 134 if (recordAbove->next() != recordBelow) | |
| 135 continue; | |
| 136 | |
| 137 m_stackDepth++; | |
| 138 recordAbove->setNext(adoptPtrWillBeNoop(new ElementRecord(item, recordAb
ove->releaseNext()))); | |
| 139 recordAbove->next()->element()->beginParsingChildren(); | |
| 140 return; | |
| 141 } | |
| 142 ASSERT_NOT_REACHED(); | |
| 143 } | 102 } |
| 144 | 103 |
| 145 HTMLElementStack::ElementRecord* HTMLElementStack::topRecord() const | 104 HTMLElementStack::ElementRecord* HTMLElementStack::topRecord() const |
| 146 { | 105 { |
| 147 ASSERT(m_top); | 106 ASSERT(m_top); |
| 148 return m_top.get(); | 107 return m_top.get(); |
| 149 } | 108 } |
| 150 | 109 |
| 151 HTMLStackItem* HTMLElementStack::oneBelowTop() const | |
| 152 { | |
| 153 // We should never call this if there are fewer than 2 elements on the stack
. | |
| 154 ASSERT(m_top); | |
| 155 ASSERT(m_top->next()); | |
| 156 if (m_top->next()->stackItem()->isElementNode()) | |
| 157 return m_top->next()->stackItem().get(); | |
| 158 return 0; | |
| 159 } | |
| 160 | |
| 161 void HTMLElementStack::remove(Element* element) | |
| 162 { | |
| 163 if (m_top->element() == element) { | |
| 164 pop(); | |
| 165 return; | |
| 166 } | |
| 167 removeNonTopCommon(element); | |
| 168 } | |
| 169 | |
| 170 HTMLElementStack::ElementRecord* HTMLElementStack::find(Element* element) const | |
| 171 { | |
| 172 for (ElementRecord* pos = m_top.get(); pos; pos = pos->next()) { | |
| 173 if (pos->node() == element) | |
| 174 return pos; | |
| 175 } | |
| 176 return 0; | |
| 177 } | |
| 178 | |
| 179 HTMLElementStack::ElementRecord* HTMLElementStack::topmost(const AtomicString& t
agName) const | |
| 180 { | |
| 181 for (ElementRecord* pos = m_top.get(); pos; pos = pos->next()) { | |
| 182 if (pos->stackItem()->hasLocalName(tagName)) | |
| 183 return pos; | |
| 184 } | |
| 185 return 0; | |
| 186 } | |
| 187 | |
| 188 bool HTMLElementStack::contains(Element* element) const | |
| 189 { | |
| 190 return !!find(element); | |
| 191 } | |
| 192 | |
| 193 bool HTMLElementStack::contains(const AtomicString& tagName) const | |
| 194 { | |
| 195 return !!topmost(tagName); | |
| 196 } | |
| 197 | |
| 198 template <bool isMarker(HTMLStackItem*)> | |
| 199 bool inScopeCommon(HTMLElementStack::ElementRecord* top, const AtomicString& tar
getTag) | |
| 200 { | |
| 201 for (HTMLElementStack::ElementRecord* pos = top; pos; pos = pos->next()) { | |
| 202 HTMLStackItem* item = pos->stackItem().get(); | |
| 203 if (item->hasLocalName(targetTag)) | |
| 204 return true; | |
| 205 if (isMarker(item)) | |
| 206 return false; | |
| 207 } | |
| 208 ASSERT_NOT_REACHED(); // <html> is always on the stack and is a scope marker
. | |
| 209 return false; | |
| 210 } | |
| 211 | |
| 212 bool HTMLElementStack::inScope(Element* targetElement) const | |
| 213 { | |
| 214 for (ElementRecord* pos = m_top.get(); pos; pos = pos->next()) { | |
| 215 HTMLStackItem* item = pos->stackItem().get(); | |
| 216 if (item->node() == targetElement) | |
| 217 return true; | |
| 218 } | |
| 219 ASSERT_NOT_REACHED(); // <html> is always on the stack and is a scope marker
. | |
| 220 return false; | |
| 221 } | |
| 222 | |
| 223 ContainerNode* HTMLElementStack::rootNode() const | 110 ContainerNode* HTMLElementStack::rootNode() const |
| 224 { | 111 { |
| 225 ASSERT(m_rootNode); | 112 ASSERT(m_rootNode); |
| 226 return m_rootNode; | 113 return m_rootNode; |
| 227 } | 114 } |
| 228 | 115 |
| 229 void HTMLElementStack::pushCommon(PassRefPtrWillBeRawPtr<HTMLStackItem> item) | 116 void HTMLElementStack::pushCommon(PassRefPtr<ContainerNode> node) |
| 230 { | 117 { |
| 231 ASSERT(m_rootNode); | 118 ASSERT(m_rootNode); |
| 232 | 119 |
| 233 m_stackDepth++; | 120 m_stackDepth++; |
| 234 m_top = adoptPtrWillBeNoop(new ElementRecord(item, m_top.release())); | 121 m_top = adoptPtr(new ElementRecord(node, m_top.release())); |
| 235 } | 122 } |
| 236 | 123 |
| 237 void HTMLElementStack::popCommon() | 124 void HTMLElementStack::popCommon() |
| 238 { | 125 { |
| 239 top()->finishParsingChildren(); | 126 top()->finishParsingChildren(); |
| 240 m_top = m_top->releaseNext(); | 127 m_top = m_top->releaseNext(); |
| 241 m_stackDepth--; | 128 m_stackDepth--; |
| 242 } | 129 } |
| 243 | 130 |
| 244 void HTMLElementStack::removeNonTopCommon(Element* element) | 131 void HTMLElementStack::removeNonTopCommon(Element* element) |
| 245 { | 132 { |
| 246 ASSERT(top() != element); | 133 ASSERT(top() != element); |
| 247 for (ElementRecord* pos = m_top.get(); pos; pos = pos->next()) { | 134 for (ElementRecord* pos = m_top.get(); pos; pos = pos->next()) { |
| 248 if (pos->next()->element() == element) { | 135 if (pos->next()->element() == element) { |
| 249 // FIXME: Is it OK to call finishParsingChildren() | 136 // FIXME: Is it OK to call finishParsingChildren() |
| 250 // when the children aren't actually finished? | 137 // when the children aren't actually finished? |
| 251 element->finishParsingChildren(); | 138 element->finishParsingChildren(); |
| 252 pos->setNext(pos->next()->releaseNext()); | 139 pos->setNext(pos->next()->releaseNext()); |
| 253 m_stackDepth--; | 140 m_stackDepth--; |
| 254 return; | 141 return; |
| 255 } | 142 } |
| 256 } | 143 } |
| 257 ASSERT_NOT_REACHED(); | 144 ASSERT_NOT_REACHED(); |
| 258 } | 145 } |
| 259 | 146 |
| 260 void HTMLElementStack::trace(Visitor* visitor) | |
| 261 { | |
| 262 visitor->trace(m_top); | |
| 263 visitor->trace(m_rootNode); | |
| 264 } | |
| 265 | |
| 266 #ifndef NDEBUG | 147 #ifndef NDEBUG |
| 267 | 148 |
| 268 void HTMLElementStack::show() | 149 void HTMLElementStack::show() |
| 269 { | 150 { |
| 270 for (ElementRecord* record = m_top.get(); record; record = record->next()) | 151 for (ElementRecord* record = m_top.get(); record; record = record->next()) |
| 271 record->element()->showNode(); | 152 record->element()->showNode(); |
| 272 } | 153 } |
| 273 | 154 |
| 274 #endif | 155 #endif |
| 275 | 156 |
| 276 } | 157 } |
| OLD | NEW |