| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
| 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
| 4 * (C) 2001 Dirk Mueller (mueller@kde.org) | 4 * (C) 2001 Dirk Mueller (mueller@kde.org) |
| 5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All r
ights reserved. | 5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All r
ights reserved. |
| 6 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) | 6 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) |
| 7 * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmo
bile.com/) | 7 * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmo
bile.com/) |
| 8 * | 8 * |
| 9 * This library is free software; you can redistribute it and/or | 9 * This library is free software; you can redistribute it and/or |
| 10 * modify it under the terms of the GNU Library General Public | 10 * modify it under the terms of the GNU Library General Public |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 149 if (node->hasRareData()) { | 149 if (node->hasRareData()) { |
| 150 ++nodesWithRareData; | 150 ++nodesWithRareData; |
| 151 if (node->isElementNode()) { | 151 if (node->isElementNode()) { |
| 152 ++elementsWithRareData; | 152 ++elementsWithRareData; |
| 153 if (toElement(node)->hasNamedNodeMap()) | 153 if (toElement(node)->hasNamedNodeMap()) |
| 154 ++elementsWithNamedNodeMap; | 154 ++elementsWithNamedNodeMap; |
| 155 } | 155 } |
| 156 } | 156 } |
| 157 | 157 |
| 158 switch (node->getNodeType()) { | 158 switch (node->getNodeType()) { |
| 159 case ELEMENT_NODE: { | 159 case kElementNode: { |
| 160 ++elementNodes; | 160 ++elementNodes; |
| 161 | 161 |
| 162 // Tag stats | 162 // Tag stats |
| 163 Element* element = toElement(node); | 163 Element* element = toElement(node); |
| 164 HashMap<String, size_t>::AddResult result = perTagCount.add(elem
ent->tagName(), 1); | 164 HashMap<String, size_t>::AddResult result = perTagCount.add(elem
ent->tagName(), 1); |
| 165 if (!result.isNewEntry) | 165 if (!result.isNewEntry) |
| 166 result.storedValue->value++; | 166 result.storedValue->value++; |
| 167 | 167 |
| 168 size_t attributeCount = element->attributesWithoutUpdate().size(
); | 168 size_t attributeCount = element->attributesWithoutUpdate().size(
); |
| 169 if (attributeCount) { | 169 if (attributeCount) { |
| 170 attributes += attributeCount; | 170 attributes += attributeCount; |
| 171 ++elementsWithAttributeStorage; | 171 ++elementsWithAttributeStorage; |
| 172 } | 172 } |
| 173 break; | 173 break; |
| 174 } | 174 } |
| 175 case ATTRIBUTE_NODE: { | 175 case kAttributeNode: { |
| 176 ++attrNodes; | 176 ++attrNodes; |
| 177 break; | 177 break; |
| 178 } | 178 } |
| 179 case TEXT_NODE: { | 179 case kTextNode: { |
| 180 ++textNodes; | 180 ++textNodes; |
| 181 break; | 181 break; |
| 182 } | 182 } |
| 183 case CDATA_SECTION_NODE: { | 183 case kCdataSectionNode: { |
| 184 ++cdataNodes; | 184 ++cdataNodes; |
| 185 break; | 185 break; |
| 186 } | 186 } |
| 187 case COMMENT_NODE: { | 187 case kCommentNode: { |
| 188 ++commentNodes; | 188 ++commentNodes; |
| 189 break; | 189 break; |
| 190 } | 190 } |
| 191 case PROCESSING_INSTRUCTION_NODE: { | 191 case kProcessingInstructionNode: { |
| 192 ++piNodes; | 192 ++piNodes; |
| 193 break; | 193 break; |
| 194 } | 194 } |
| 195 case DOCUMENT_NODE: { | 195 case kDocumentNode: { |
| 196 ++documentNodes; | 196 ++documentNodes; |
| 197 break; | 197 break; |
| 198 } | 198 } |
| 199 case DOCUMENT_TYPE_NODE: { | 199 case kDocumentTypeNode: { |
| 200 ++docTypeNodes; | 200 ++docTypeNodes; |
| 201 break; | 201 break; |
| 202 } | 202 } |
| 203 case DOCUMENT_FRAGMENT_NODE: { | 203 case kDocumentFragmentNode: { |
| 204 if (node->isShadowRoot()) | 204 if (node->isShadowRoot()) |
| 205 ++shadowRootNodes; | 205 ++shadowRootNodes; |
| 206 else | 206 else |
| 207 ++fragmentNodes; | 207 ++fragmentNodes; |
| 208 break; | 208 break; |
| 209 } | 209 } |
| 210 } | 210 } |
| 211 } | 211 } |
| 212 } | 212 } |
| 213 | 213 |
| (...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 526 // Go through the subtree beneath us, normalizing all nodes. This means that | 526 // Go through the subtree beneath us, normalizing all nodes. This means that |
| 527 // any two adjacent text nodes are merged and any empty text nodes are remov
ed. | 527 // any two adjacent text nodes are merged and any empty text nodes are remov
ed. |
| 528 | 528 |
| 529 Node* node = this; | 529 Node* node = this; |
| 530 while (Node* firstChild = node->firstChild()) | 530 while (Node* firstChild = node->firstChild()) |
| 531 node = firstChild; | 531 node = firstChild; |
| 532 while (node) { | 532 while (node) { |
| 533 if (node == this) | 533 if (node == this) |
| 534 break; | 534 break; |
| 535 | 535 |
| 536 if (node->getNodeType() == TEXT_NODE) | 536 if (node->getNodeType() == kTextNode) |
| 537 node = toText(node)->mergeNextSiblingNodesIfPossible(); | 537 node = toText(node)->mergeNextSiblingNodesIfPossible(); |
| 538 else | 538 else |
| 539 node = NodeTraversal::nextPostOrder(*node); | 539 node = NodeTraversal::nextPostOrder(*node); |
| 540 } | 540 } |
| 541 } | 541 } |
| 542 | 542 |
| 543 // TODO(yoichio): Move to core/editing | 543 // TODO(yoichio): Move to core/editing |
| 544 enum EditableLevel { Editable, RichlyEditable }; | 544 enum EditableLevel { Editable, RichlyEditable }; |
| 545 static bool hasEditableStyle(const Node&, EditableLevel); | 545 static bool hasEditableStyle(const Node&, EditableLevel); |
| 546 static bool isEditableToAccessibility(const Node&, EditableLevel); | 546 static bool isEditableToAccessibility(const Node&, EditableLevel); |
| (...skipping 698 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1245 } | 1245 } |
| 1246 | 1246 |
| 1247 return true; | 1247 return true; |
| 1248 } | 1248 } |
| 1249 | 1249 |
| 1250 bool Node::isDefaultNamespace(const AtomicString& namespaceURIMaybeEmpty) const | 1250 bool Node::isDefaultNamespace(const AtomicString& namespaceURIMaybeEmpty) const |
| 1251 { | 1251 { |
| 1252 const AtomicString& namespaceURI = namespaceURIMaybeEmpty.isEmpty() ? nullAt
om : namespaceURIMaybeEmpty; | 1252 const AtomicString& namespaceURI = namespaceURIMaybeEmpty.isEmpty() ? nullAt
om : namespaceURIMaybeEmpty; |
| 1253 | 1253 |
| 1254 switch (getNodeType()) { | 1254 switch (getNodeType()) { |
| 1255 case ELEMENT_NODE: { | 1255 case kElementNode: { |
| 1256 const Element& element = toElement(*this); | 1256 const Element& element = toElement(*this); |
| 1257 | 1257 |
| 1258 if (element.prefix().isNull()) | 1258 if (element.prefix().isNull()) |
| 1259 return element.namespaceURI() == namespaceURI; | 1259 return element.namespaceURI() == namespaceURI; |
| 1260 | 1260 |
| 1261 AttributeCollection attributes = element.attributes(); | 1261 AttributeCollection attributes = element.attributes(); |
| 1262 for (const Attribute& attr : attributes) { | 1262 for (const Attribute& attr : attributes) { |
| 1263 if (attr.localName() == xmlnsAtom) | 1263 if (attr.localName() == xmlnsAtom) |
| 1264 return attr.value() == namespaceURI; | 1264 return attr.value() == namespaceURI; |
| 1265 } | 1265 } |
| 1266 | 1266 |
| 1267 if (Element* parent = parentElement()) | 1267 if (Element* parent = parentElement()) |
| 1268 return parent->isDefaultNamespace(namespaceURI); | 1268 return parent->isDefaultNamespace(namespaceURI); |
| 1269 | 1269 |
| 1270 return false; | 1270 return false; |
| 1271 } | 1271 } |
| 1272 case DOCUMENT_NODE: | 1272 case kDocumentNode: |
| 1273 if (Element* de = toDocument(this)->documentElement()) | 1273 if (Element* de = toDocument(this)->documentElement()) |
| 1274 return de->isDefaultNamespace(namespaceURI); | 1274 return de->isDefaultNamespace(namespaceURI); |
| 1275 return false; | 1275 return false; |
| 1276 case DOCUMENT_TYPE_NODE: | 1276 case kDocumentTypeNode: |
| 1277 case DOCUMENT_FRAGMENT_NODE: | 1277 case kDocumentFragmentNode: |
| 1278 return false; | 1278 return false; |
| 1279 case ATTRIBUTE_NODE: { | 1279 case kAttributeNode: { |
| 1280 const Attr* attr = toAttr(this); | 1280 const Attr* attr = toAttr(this); |
| 1281 if (attr->ownerElement()) | 1281 if (attr->ownerElement()) |
| 1282 return attr->ownerElement()->isDefaultNamespace(namespaceURI); | 1282 return attr->ownerElement()->isDefaultNamespace(namespaceURI); |
| 1283 return false; | 1283 return false; |
| 1284 } | 1284 } |
| 1285 default: | 1285 default: |
| 1286 if (Element* parent = parentElement()) | 1286 if (Element* parent = parentElement()) |
| 1287 return parent->isDefaultNamespace(namespaceURI); | 1287 return parent->isDefaultNamespace(namespaceURI); |
| 1288 return false; | 1288 return false; |
| 1289 } | 1289 } |
| 1290 } | 1290 } |
| 1291 | 1291 |
| 1292 const AtomicString& Node::lookupPrefix(const AtomicString& namespaceURI) const | 1292 const AtomicString& Node::lookupPrefix(const AtomicString& namespaceURI) const |
| 1293 { | 1293 { |
| 1294 // Implemented according to | 1294 // Implemented according to |
| 1295 // https://dom.spec.whatwg.org/#dom-node-lookupprefix | 1295 // https://dom.spec.whatwg.org/#dom-node-lookupprefix |
| 1296 | 1296 |
| 1297 if (namespaceURI.isEmpty() || namespaceURI.isNull()) | 1297 if (namespaceURI.isEmpty() || namespaceURI.isNull()) |
| 1298 return nullAtom; | 1298 return nullAtom; |
| 1299 | 1299 |
| 1300 const Element* context; | 1300 const Element* context; |
| 1301 | 1301 |
| 1302 switch (getNodeType()) { | 1302 switch (getNodeType()) { |
| 1303 case ELEMENT_NODE: | 1303 case kElementNode: |
| 1304 context = toElement(this); | 1304 context = toElement(this); |
| 1305 break; | 1305 break; |
| 1306 case DOCUMENT_NODE: | 1306 case kDocumentNode: |
| 1307 context = toDocument(this)->documentElement(); | 1307 context = toDocument(this)->documentElement(); |
| 1308 break; | 1308 break; |
| 1309 case DOCUMENT_FRAGMENT_NODE: | 1309 case kDocumentFragmentNode: |
| 1310 case DOCUMENT_TYPE_NODE: | 1310 case kDocumentTypeNode: |
| 1311 context = nullptr; | 1311 context = nullptr; |
| 1312 break; | 1312 break; |
| 1313 // FIXME: Remove this when Attr no longer extends Node (CR305105) | 1313 // FIXME: Remove this when Attr no longer extends Node (CR305105) |
| 1314 case ATTRIBUTE_NODE: | 1314 case kAttributeNode: |
| 1315 context = toAttr(this)->ownerElement(); | 1315 context = toAttr(this)->ownerElement(); |
| 1316 break; | 1316 break; |
| 1317 default: | 1317 default: |
| 1318 context = parentElement(); | 1318 context = parentElement(); |
| 1319 break; | 1319 break; |
| 1320 } | 1320 } |
| 1321 | 1321 |
| 1322 if (!context) | 1322 if (!context) |
| 1323 return nullAtom; | 1323 return nullAtom; |
| 1324 | 1324 |
| 1325 return context->locateNamespacePrefix(namespaceURI); | 1325 return context->locateNamespacePrefix(namespaceURI); |
| 1326 } | 1326 } |
| 1327 | 1327 |
| 1328 const AtomicString& Node::lookupNamespaceURI(const String& prefix) const | 1328 const AtomicString& Node::lookupNamespaceURI(const String& prefix) const |
| 1329 { | 1329 { |
| 1330 // Implemented according to | 1330 // Implemented according to |
| 1331 // http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/namespaces-algori
thms.html#lookupNamespaceURIAlgo | 1331 // http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/namespaces-algori
thms.html#lookupNamespaceURIAlgo |
| 1332 | 1332 |
| 1333 if (!prefix.isNull() && prefix.isEmpty()) | 1333 if (!prefix.isNull() && prefix.isEmpty()) |
| 1334 return nullAtom; | 1334 return nullAtom; |
| 1335 | 1335 |
| 1336 switch (getNodeType()) { | 1336 switch (getNodeType()) { |
| 1337 case ELEMENT_NODE: { | 1337 case kElementNode: { |
| 1338 const Element& element = toElement(*this); | 1338 const Element& element = toElement(*this); |
| 1339 | 1339 |
| 1340 if (!element.namespaceURI().isNull() && element.prefix() == prefix) | 1340 if (!element.namespaceURI().isNull() && element.prefix() == prefix) |
| 1341 return element.namespaceURI(); | 1341 return element.namespaceURI(); |
| 1342 | 1342 |
| 1343 AttributeCollection attributes = element.attributes(); | 1343 AttributeCollection attributes = element.attributes(); |
| 1344 for (const Attribute& attr : attributes) { | 1344 for (const Attribute& attr : attributes) { |
| 1345 if (attr.prefix() == xmlnsAtom && attr.localName() == prefix) { | 1345 if (attr.prefix() == xmlnsAtom && attr.localName() == prefix) { |
| 1346 if (!attr.value().isEmpty()) | 1346 if (!attr.value().isEmpty()) |
| 1347 return attr.value(); | 1347 return attr.value(); |
| 1348 return nullAtom; | 1348 return nullAtom; |
| 1349 } | 1349 } |
| 1350 if (attr.localName() == xmlnsAtom && prefix.isNull()) { | 1350 if (attr.localName() == xmlnsAtom && prefix.isNull()) { |
| 1351 if (!attr.value().isEmpty()) | 1351 if (!attr.value().isEmpty()) |
| 1352 return attr.value(); | 1352 return attr.value(); |
| 1353 return nullAtom; | 1353 return nullAtom; |
| 1354 } | 1354 } |
| 1355 } | 1355 } |
| 1356 | 1356 |
| 1357 if (Element* parent = parentElement()) | 1357 if (Element* parent = parentElement()) |
| 1358 return parent->lookupNamespaceURI(prefix); | 1358 return parent->lookupNamespaceURI(prefix); |
| 1359 return nullAtom; | 1359 return nullAtom; |
| 1360 } | 1360 } |
| 1361 case DOCUMENT_NODE: | 1361 case kDocumentNode: |
| 1362 if (Element* de = toDocument(this)->documentElement()) | 1362 if (Element* de = toDocument(this)->documentElement()) |
| 1363 return de->lookupNamespaceURI(prefix); | 1363 return de->lookupNamespaceURI(prefix); |
| 1364 return nullAtom; | 1364 return nullAtom; |
| 1365 case DOCUMENT_TYPE_NODE: | 1365 case kDocumentTypeNode: |
| 1366 case DOCUMENT_FRAGMENT_NODE: | 1366 case kDocumentFragmentNode: |
| 1367 return nullAtom; | 1367 return nullAtom; |
| 1368 case ATTRIBUTE_NODE: { | 1368 case kAttributeNode: { |
| 1369 const Attr *attr = toAttr(this); | 1369 const Attr *attr = toAttr(this); |
| 1370 if (attr->ownerElement()) | 1370 if (attr->ownerElement()) |
| 1371 return attr->ownerElement()->lookupNamespaceURI(prefix); | 1371 return attr->ownerElement()->lookupNamespaceURI(prefix); |
| 1372 return nullAtom; | 1372 return nullAtom; |
| 1373 } | 1373 } |
| 1374 default: | 1374 default: |
| 1375 if (Element* parent = parentElement()) | 1375 if (Element* parent = parentElement()) |
| 1376 return parent->lookupNamespaceURI(prefix); | 1376 return parent->lookupNamespaceURI(prefix); |
| 1377 return nullAtom; | 1377 return nullAtom; |
| 1378 } | 1378 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1398 } else if (node.isTextNode()) { | 1398 } else if (node.isTextNode()) { |
| 1399 content.append(toText(node).data()); | 1399 content.append(toText(node).data()); |
| 1400 } | 1400 } |
| 1401 } | 1401 } |
| 1402 return content.toString(); | 1402 return content.toString(); |
| 1403 } | 1403 } |
| 1404 | 1404 |
| 1405 void Node::setTextContent(const String& text) | 1405 void Node::setTextContent(const String& text) |
| 1406 { | 1406 { |
| 1407 switch (getNodeType()) { | 1407 switch (getNodeType()) { |
| 1408 case TEXT_NODE: | 1408 case kTextNode: |
| 1409 case CDATA_SECTION_NODE: | 1409 case kCdataSectionNode: |
| 1410 case COMMENT_NODE: | 1410 case kCommentNode: |
| 1411 case PROCESSING_INSTRUCTION_NODE: | 1411 case kProcessingInstructionNode: |
| 1412 setNodeValue(text); | 1412 setNodeValue(text); |
| 1413 return; | 1413 return; |
| 1414 case ELEMENT_NODE: | 1414 case kElementNode: |
| 1415 case DOCUMENT_FRAGMENT_NODE: { | 1415 case kDocumentFragmentNode: { |
| 1416 // FIXME: Merge this logic into replaceChildrenWithText. | 1416 // FIXME: Merge this logic into replaceChildrenWithText. |
| 1417 ContainerNode* container = toContainerNode(this); | 1417 ContainerNode* container = toContainerNode(this); |
| 1418 | 1418 |
| 1419 // Note: This is an intentional optimization. | 1419 // Note: This is an intentional optimization. |
| 1420 // See crbug.com/352836 also. | 1420 // See crbug.com/352836 also. |
| 1421 // No need to do anything if the text is identical. | 1421 // No need to do anything if the text is identical. |
| 1422 if (container->hasOneTextChild() && toText(container->firstChild())->dat
a() == text) | 1422 if (container->hasOneTextChild() && toText(container->firstChild())->dat
a() == text) |
| 1423 return; | 1423 return; |
| 1424 | 1424 |
| 1425 ChildListMutationScope mutation(*this); | 1425 ChildListMutationScope mutation(*this); |
| 1426 // Note: This API will not insert empty text nodes: | 1426 // Note: This API will not insert empty text nodes: |
| 1427 // https://dom.spec.whatwg.org/#dom-node-textcontent | 1427 // https://dom.spec.whatwg.org/#dom-node-textcontent |
| 1428 if (text.isEmpty()) { | 1428 if (text.isEmpty()) { |
| 1429 container->removeChildren(DispatchSubtreeModifiedEvent); | 1429 container->removeChildren(DispatchSubtreeModifiedEvent); |
| 1430 } else { | 1430 } else { |
| 1431 container->removeChildren(OmitSubtreeModifiedEvent); | 1431 container->removeChildren(OmitSubtreeModifiedEvent); |
| 1432 container->appendChild(document().createTextNode(text), ASSERT_NO_EX
CEPTION); | 1432 container->appendChild(document().createTextNode(text), ASSERT_NO_EX
CEPTION); |
| 1433 } | 1433 } |
| 1434 return; | 1434 return; |
| 1435 } | 1435 } |
| 1436 case ATTRIBUTE_NODE: | 1436 case kAttributeNode: |
| 1437 case DOCUMENT_NODE: | 1437 case kDocumentNode: |
| 1438 case DOCUMENT_TYPE_NODE: | 1438 case kDocumentTypeNode: |
| 1439 // Do nothing. | 1439 // Do nothing. |
| 1440 return; | 1440 return; |
| 1441 } | 1441 } |
| 1442 ASSERT_NOT_REACHED(); | 1442 ASSERT_NOT_REACHED(); |
| 1443 } | 1443 } |
| 1444 | 1444 |
| 1445 bool Node::offsetInCharacters() const | 1445 bool Node::offsetInCharacters() const |
| 1446 { | 1446 { |
| 1447 return isCharacterDataNode(); | 1447 return isCharacterDataNode(); |
| 1448 } | 1448 } |
| 1449 | 1449 |
| 1450 unsigned short Node::compareDocumentPosition(const Node* otherNode, ShadowTreesT
reatment treatment) const | 1450 unsigned short Node::compareDocumentPosition(const Node* otherNode, ShadowTreesT
reatment treatment) const |
| 1451 { | 1451 { |
| 1452 if (otherNode == this) | 1452 if (otherNode == this) |
| 1453 return DOCUMENT_POSITION_EQUIVALENT; | 1453 return DOCUMENT_POSITION_EQUIVALENT; |
| 1454 | 1454 |
| 1455 const Attr* attr1 = getNodeType() == ATTRIBUTE_NODE ? toAttr(this) : nullptr
; | 1455 const Attr* attr1 = getNodeType() == kAttributeNode ? toAttr(this) : nullptr
; |
| 1456 const Attr* attr2 = otherNode->getNodeType() == ATTRIBUTE_NODE ? toAttr(othe
rNode) : nullptr; | 1456 const Attr* attr2 = otherNode->getNodeType() == kAttributeNode ? toAttr(othe
rNode) : nullptr; |
| 1457 | 1457 |
| 1458 const Node* start1 = attr1 ? attr1->ownerElement() : this; | 1458 const Node* start1 = attr1 ? attr1->ownerElement() : this; |
| 1459 const Node* start2 = attr2 ? attr2->ownerElement() : otherNode; | 1459 const Node* start2 = attr2 ? attr2->ownerElement() : otherNode; |
| 1460 | 1460 |
| 1461 // If either of start1 or start2 is null, then we are disconnected, since on
e of the nodes is | 1461 // If either of start1 or start2 is null, then we are disconnected, since on
e of the nodes is |
| 1462 // an orphaned attribute node. | 1462 // an orphaned attribute node. |
| 1463 if (!start1 || !start2) { | 1463 if (!start1 || !start2) { |
| 1464 unsigned short direction = (this > otherNode) ? DOCUMENT_POSITION_PRECED
ING : DOCUMENT_POSITION_FOLLOWING; | 1464 unsigned short direction = (this > otherNode) ? kDocumentPositionPrecedi
ng : kDocumentPositionFollowing; |
| 1465 return DOCUMENT_POSITION_DISCONNECTED | DOCUMENT_POSITION_IMPLEMENTATION
_SPECIFIC | direction; | 1465 return kDocumentPositionDisconnected | kDocumentPositionImplementationSp
ecific | direction; |
| 1466 } | 1466 } |
| 1467 | 1467 |
| 1468 HeapVector<Member<const Node>, 16> chain1; | 1468 HeapVector<Member<const Node>, 16> chain1; |
| 1469 HeapVector<Member<const Node>, 16> chain2; | 1469 HeapVector<Member<const Node>, 16> chain2; |
| 1470 if (attr1) | 1470 if (attr1) |
| 1471 chain1.append(attr1); | 1471 chain1.append(attr1); |
| 1472 if (attr2) | 1472 if (attr2) |
| 1473 chain2.append(attr2); | 1473 chain2.append(attr2); |
| 1474 | 1474 |
| 1475 if (attr1 && attr2 && start1 == start2 && start1) { | 1475 if (attr1 && attr2 && start1 == start2 && start1) { |
| 1476 // We are comparing two attributes on the same node. Crawl our attribute
map and see which one we hit first. | 1476 // We are comparing two attributes on the same node. Crawl our attribute
map and see which one we hit first. |
| 1477 const Element* owner1 = attr1->ownerElement(); | 1477 const Element* owner1 = attr1->ownerElement(); |
| 1478 AttributeCollection attributes = owner1->attributes(); | 1478 AttributeCollection attributes = owner1->attributes(); |
| 1479 for (const Attribute& attr : attributes) { | 1479 for (const Attribute& attr : attributes) { |
| 1480 // If neither of the two determining nodes is a child node and nodeT
ype is the same for both determining nodes, then an | 1480 // If neither of the two determining nodes is a child node and nodeT
ype is the same for both determining nodes, then an |
| 1481 // implementation-dependent order between the determining nodes is r
eturned. This order is stable as long as no nodes of | 1481 // implementation-dependent order between the determining nodes is r
eturned. This order is stable as long as no nodes of |
| 1482 // the same nodeType are inserted into or removed from the direct co
ntainer. This would be the case, for example, | 1482 // the same nodeType are inserted into or removed from the direct co
ntainer. This would be the case, for example, |
| 1483 // when comparing two attributes of the same element, and inserting
or removing additional attributes might change | 1483 // when comparing two attributes of the same element, and inserting
or removing additional attributes might change |
| 1484 // the order between existing attributes. | 1484 // the order between existing attributes. |
| 1485 if (attr1->getQualifiedName() == attr.name()) | 1485 if (attr1->getQualifiedName() == attr.name()) |
| 1486 return DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | DOCUMENT_POSI
TION_FOLLOWING; | 1486 return kDocumentPositionImplementationSpecific | kDocumentPositi
onFollowing; |
| 1487 if (attr2->getQualifiedName() == attr.name()) | 1487 if (attr2->getQualifiedName() == attr.name()) |
| 1488 return DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | DOCUMENT_POSI
TION_PRECEDING; | 1488 return kDocumentPositionImplementationSpecific | kDocumentPositi
onPreceding; |
| 1489 } | 1489 } |
| 1490 | 1490 |
| 1491 ASSERT_NOT_REACHED(); | 1491 ASSERT_NOT_REACHED(); |
| 1492 return DOCUMENT_POSITION_DISCONNECTED; | 1492 return kDocumentPositionDisconnected; |
| 1493 } | 1493 } |
| 1494 | 1494 |
| 1495 // If one node is in the document and the other is not, we must be disconnec
ted. | 1495 // If one node is in the document and the other is not, we must be disconnec
ted. |
| 1496 // If the nodes have different owning documents, they must be disconnected.
Note that we avoid | 1496 // If the nodes have different owning documents, they must be disconnected.
Note that we avoid |
| 1497 // comparing Attr nodes here, since they return false from isConnected() all
the time (which seems like a bug). | 1497 // comparing Attr nodes here, since they return false from isConnected() all
the time (which seems like a bug). |
| 1498 if (start1->isConnected() != start2->isConnected() || (treatment == TreatSha
dowTreesAsDisconnected && start1->treeScope() != start2->treeScope())) { | 1498 if (start1->isConnected() != start2->isConnected() || (treatment == TreatSha
dowTreesAsDisconnected && start1->treeScope() != start2->treeScope())) { |
| 1499 unsigned short direction = (this > otherNode) ? DOCUMENT_POSITION_PRECED
ING : DOCUMENT_POSITION_FOLLOWING; | 1499 unsigned short direction = (this > otherNode) ? kDocumentPositionPrecedi
ng : kDocumentPositionFollowing; |
| 1500 return DOCUMENT_POSITION_DISCONNECTED | DOCUMENT_POSITION_IMPLEMENTATION
_SPECIFIC | direction; | 1500 return kDocumentPositionDisconnected | kDocumentPositionImplementationSp
ecific | direction; |
| 1501 } | 1501 } |
| 1502 | 1502 |
| 1503 // We need to find a common ancestor container, and then compare the indices
of the two immediate children. | 1503 // We need to find a common ancestor container, and then compare the indices
of the two immediate children. |
| 1504 const Node* current; | 1504 const Node* current; |
| 1505 for (current = start1; current; current = current->parentOrShadowHostNode()) | 1505 for (current = start1; current; current = current->parentOrShadowHostNode()) |
| 1506 chain1.append(current); | 1506 chain1.append(current); |
| 1507 for (current = start2; current; current = current->parentOrShadowHostNode()) | 1507 for (current = start2; current; current = current->parentOrShadowHostNode()) |
| 1508 chain2.append(current); | 1508 chain2.append(current); |
| 1509 | 1509 |
| 1510 unsigned index1 = chain1.size(); | 1510 unsigned index1 = chain1.size(); |
| 1511 unsigned index2 = chain2.size(); | 1511 unsigned index2 = chain2.size(); |
| 1512 | 1512 |
| 1513 // If the two elements don't have a common root, they're not in the same tre
e. | 1513 // If the two elements don't have a common root, they're not in the same tre
e. |
| 1514 if (chain1[index1 - 1] != chain2[index2 - 1]) { | 1514 if (chain1[index1 - 1] != chain2[index2 - 1]) { |
| 1515 unsigned short direction = (this > otherNode) ? DOCUMENT_POSITION_PRECED
ING : DOCUMENT_POSITION_FOLLOWING; | 1515 unsigned short direction = (this > otherNode) ? kDocumentPositionPrecedi
ng : kDocumentPositionFollowing; |
| 1516 return DOCUMENT_POSITION_DISCONNECTED | DOCUMENT_POSITION_IMPLEMENTATION
_SPECIFIC | direction; | 1516 return kDocumentPositionDisconnected | kDocumentPositionImplementationSp
ecific | direction; |
| 1517 } | 1517 } |
| 1518 | 1518 |
| 1519 unsigned connection = start1->treeScope() != start2->treeScope() ? DOCUMENT_
POSITION_DISCONNECTED | DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC : 0; | 1519 unsigned connection = start1->treeScope() != start2->treeScope() ? kDocument
PositionDisconnected | kDocumentPositionImplementationSpecific : 0; |
| 1520 | 1520 |
| 1521 // Walk the two chains backwards and look for the first difference. | 1521 // Walk the two chains backwards and look for the first difference. |
| 1522 for (unsigned i = std::min(index1, index2); i; --i) { | 1522 for (unsigned i = std::min(index1, index2); i; --i) { |
| 1523 const Node* child1 = chain1[--index1]; | 1523 const Node* child1 = chain1[--index1]; |
| 1524 const Node* child2 = chain2[--index2]; | 1524 const Node* child2 = chain2[--index2]; |
| 1525 if (child1 != child2) { | 1525 if (child1 != child2) { |
| 1526 // If one of the children is an attribute, it wins. | 1526 // If one of the children is an attribute, it wins. |
| 1527 if (child1->getNodeType() == ATTRIBUTE_NODE) | 1527 if (child1->getNodeType() == kAttributeNode) |
| 1528 return DOCUMENT_POSITION_FOLLOWING | connection; | 1528 return kDocumentPositionFollowing | connection; |
| 1529 if (child2->getNodeType() == ATTRIBUTE_NODE) | 1529 if (child2->getNodeType() == kAttributeNode) |
| 1530 return DOCUMENT_POSITION_PRECEDING | connection; | 1530 return kDocumentPositionPreceding | connection; |
| 1531 | 1531 |
| 1532 // If one of the children is a shadow root, | 1532 // If one of the children is a shadow root, |
| 1533 if (child1->isShadowRoot() || child2->isShadowRoot()) { | 1533 if (child1->isShadowRoot() || child2->isShadowRoot()) { |
| 1534 if (!child2->isShadowRoot()) | 1534 if (!child2->isShadowRoot()) |
| 1535 return Node::DOCUMENT_POSITION_FOLLOWING | connection; | 1535 return Node::kDocumentPositionFollowing | connection; |
| 1536 if (!child1->isShadowRoot()) | 1536 if (!child1->isShadowRoot()) |
| 1537 return Node::DOCUMENT_POSITION_PRECEDING | connection; | 1537 return Node::kDocumentPositionPreceding | connection; |
| 1538 | 1538 |
| 1539 for (const ShadowRoot* child = toShadowRoot(child2)->olderShadow
Root(); child; child = child->olderShadowRoot()) { | 1539 for (const ShadowRoot* child = toShadowRoot(child2)->olderShadow
Root(); child; child = child->olderShadowRoot()) { |
| 1540 if (child == child1) { | 1540 if (child == child1) { |
| 1541 return Node::DOCUMENT_POSITION_FOLLOWING | connection; | 1541 return Node::kDocumentPositionFollowing | connection; |
| 1542 } | 1542 } |
| 1543 } | 1543 } |
| 1544 | 1544 |
| 1545 return Node::DOCUMENT_POSITION_PRECEDING | connection; | 1545 return Node::kDocumentPositionPreceding | connection; |
| 1546 } | 1546 } |
| 1547 | 1547 |
| 1548 if (!child2->nextSibling()) | 1548 if (!child2->nextSibling()) |
| 1549 return DOCUMENT_POSITION_FOLLOWING | connection; | 1549 return kDocumentPositionFollowing | connection; |
| 1550 if (!child1->nextSibling()) | 1550 if (!child1->nextSibling()) |
| 1551 return DOCUMENT_POSITION_PRECEDING | connection; | 1551 return kDocumentPositionPreceding | connection; |
| 1552 | 1552 |
| 1553 // Otherwise we need to see which node occurs first. Crawl backward
s from child2 looking for child1. | 1553 // Otherwise we need to see which node occurs first. Crawl backward
s from child2 looking for child1. |
| 1554 for (const Node* child = child2->previousSibling(); child; child = c
hild->previousSibling()) { | 1554 for (const Node* child = child2->previousSibling(); child; child = c
hild->previousSibling()) { |
| 1555 if (child == child1) | 1555 if (child == child1) |
| 1556 return DOCUMENT_POSITION_FOLLOWING | connection; | 1556 return kDocumentPositionFollowing | connection; |
| 1557 } | 1557 } |
| 1558 return DOCUMENT_POSITION_PRECEDING | connection; | 1558 return kDocumentPositionPreceding | connection; |
| 1559 } | 1559 } |
| 1560 } | 1560 } |
| 1561 | 1561 |
| 1562 // There was no difference between the two parent chains, i.e., one was a su
bset of the other. The shorter | 1562 // There was no difference between the two parent chains, i.e., one was a su
bset of the other. The shorter |
| 1563 // chain is the ancestor. | 1563 // chain is the ancestor. |
| 1564 return index1 < index2 ? | 1564 return index1 < index2 ? |
| 1565 DOCUMENT_POSITION_FOLLOWING | DOCUMENT_POSITION_CONTAINED_BY | connectio
n : | 1565 kDocumentPositionFollowing | kDocumentPositionContainedBy | connection : |
| 1566 DOCUMENT_POSITION_PRECEDING | DOCUMENT_POSITION_CONTAINS | connection; | 1566 kDocumentPositionPreceding | kDocumentPositionContains | connection; |
| 1567 } | 1567 } |
| 1568 | 1568 |
| 1569 String Node::debugName() const | 1569 String Node::debugName() const |
| 1570 { | 1570 { |
| 1571 StringBuilder name; | 1571 StringBuilder name; |
| 1572 name.append(debugNodeName()); | 1572 name.append(debugNodeName()); |
| 1573 if (isElementNode()) { | 1573 if (isElementNode()) { |
| 1574 const Element& thisElement = toElement(*this); | 1574 const Element& thisElement = toElement(*this); |
| 1575 if (thisElement.hasID()) { | 1575 if (thisElement.hasID()) { |
| 1576 name.append(" id=\'"); | 1576 name.append(" id=\'"); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1647 { | 1647 { |
| 1648 if (!prefix) | 1648 if (!prefix) |
| 1649 prefix = ""; | 1649 prefix = ""; |
| 1650 if (isTextNode()) { | 1650 if (isTextNode()) { |
| 1651 String value = nodeValue(); | 1651 String value = nodeValue(); |
| 1652 value.replace('\\', "\\\\"); | 1652 value.replace('\\', "\\\\"); |
| 1653 value.replace('\n', "\\n"); | 1653 value.replace('\n', "\\n"); |
| 1654 WTFLogAlways("%s%s\t%p \"%s\"\n", prefix, nodeName().utf8().data(), this
, value.utf8().data()); | 1654 WTFLogAlways("%s%s\t%p \"%s\"\n", prefix, nodeName().utf8().data(), this
, value.utf8().data()); |
| 1655 } else if (isDocumentTypeNode()) { | 1655 } else if (isDocumentTypeNode()) { |
| 1656 WTFLogAlways("%sDOCTYPE %s\t%p\n", prefix, nodeName().utf8().data(), thi
s); | 1656 WTFLogAlways("%sDOCTYPE %s\t%p\n", prefix, nodeName().utf8().data(), thi
s); |
| 1657 } else if (getNodeType() == PROCESSING_INSTRUCTION_NODE) { | 1657 } else if (getNodeType() == kProcessingInstructionNode) { |
| 1658 WTFLogAlways("%s?%s\t%p\n", prefix, nodeName().utf8().data(), this); | 1658 WTFLogAlways("%s?%s\t%p\n", prefix, nodeName().utf8().data(), this); |
| 1659 } else if (isShadowRoot()) { | 1659 } else if (isShadowRoot()) { |
| 1660 // nodeName of ShadowRoot is #document-fragment. It's confused with | 1660 // nodeName of ShadowRoot is #document-fragment. It's confused with |
| 1661 // DocumentFragment. | 1661 // DocumentFragment. |
| 1662 WTFLogAlways("%s#shadow-root\t%p\n", prefix, this); | 1662 WTFLogAlways("%s#shadow-root\t%p\n", prefix, this); |
| 1663 } else { | 1663 } else { |
| 1664 StringBuilder attrs; | 1664 StringBuilder attrs; |
| 1665 appendAttributeDesc(this, attrs, idAttr, " ID"); | 1665 appendAttributeDesc(this, attrs, idAttr, " ID"); |
| 1666 appendAttributeDesc(this, attrs, classAttr, " CLASS"); | 1666 appendAttributeDesc(this, attrs, classAttr, " CLASS"); |
| 1667 appendAttributeDesc(this, attrs, styleAttr, " STYLE"); | 1667 appendAttributeDesc(this, attrs, styleAttr, " STYLE"); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1695 const Node* node = chain[index - 1]; | 1695 const Node* node = chain[index - 1]; |
| 1696 if (node->isShadowRoot()) { | 1696 if (node->isShadowRoot()) { |
| 1697 int count = 0; | 1697 int count = 0; |
| 1698 for (const ShadowRoot* shadowRoot = toShadowRoot(node)->olderShadowR
oot(); shadowRoot; shadowRoot = shadowRoot->olderShadowRoot()) | 1698 for (const ShadowRoot* shadowRoot = toShadowRoot(node)->olderShadowR
oot(); shadowRoot; shadowRoot = shadowRoot->olderShadowRoot()) |
| 1699 ++count; | 1699 ++count; |
| 1700 WTFLogAlways("/#shadow-root[%d]", count); | 1700 WTFLogAlways("/#shadow-root[%d]", count); |
| 1701 continue; | 1701 continue; |
| 1702 } | 1702 } |
| 1703 | 1703 |
| 1704 switch (node->getNodeType()) { | 1704 switch (node->getNodeType()) { |
| 1705 case ELEMENT_NODE: { | 1705 case kElementNode: { |
| 1706 WTFLogAlways("/%s", node->nodeName().utf8().data()); | 1706 WTFLogAlways("/%s", node->nodeName().utf8().data()); |
| 1707 | 1707 |
| 1708 const Element* element = toElement(node); | 1708 const Element* element = toElement(node); |
| 1709 const AtomicString& idattr = element->getIdAttribute(); | 1709 const AtomicString& idattr = element->getIdAttribute(); |
| 1710 bool hasIdAttr = !idattr.isNull() && !idattr.isEmpty(); | 1710 bool hasIdAttr = !idattr.isNull() && !idattr.isEmpty(); |
| 1711 if (node->previousSibling() || node->nextSibling()) { | 1711 if (node->previousSibling() || node->nextSibling()) { |
| 1712 int count = 0; | 1712 int count = 0; |
| 1713 for (const Node* previous = node->previousSibling(); previous; p
revious = previous->previousSibling()) { | 1713 for (const Node* previous = node->previousSibling(); previous; p
revious = previous->previousSibling()) { |
| 1714 if (previous->nodeName() == node->nodeName()) { | 1714 if (previous->nodeName() == node->nodeName()) { |
| 1715 ++count; | 1715 ++count; |
| 1716 } | 1716 } |
| 1717 } | 1717 } |
| 1718 if (hasIdAttr) | 1718 if (hasIdAttr) |
| 1719 WTFLogAlways("[@id=\"%s\" and position()=%d]", idattr.utf8()
.data(), count); | 1719 WTFLogAlways("[@id=\"%s\" and position()=%d]", idattr.utf8()
.data(), count); |
| 1720 else | 1720 else |
| 1721 WTFLogAlways("[%d]", count); | 1721 WTFLogAlways("[%d]", count); |
| 1722 } else if (hasIdAttr) { | 1722 } else if (hasIdAttr) { |
| 1723 WTFLogAlways("[@id=\"%s\"]", idattr.utf8().data()); | 1723 WTFLogAlways("[@id=\"%s\"]", idattr.utf8().data()); |
| 1724 } | 1724 } |
| 1725 break; | 1725 break; |
| 1726 } | 1726 } |
| 1727 case TEXT_NODE: | 1727 case kTextNode: |
| 1728 WTFLogAlways("/text()"); | 1728 WTFLogAlways("/text()"); |
| 1729 break; | 1729 break; |
| 1730 case ATTRIBUTE_NODE: | 1730 case kAttributeNode: |
| 1731 WTFLogAlways("/@%s", node->nodeName().utf8().data()); | 1731 WTFLogAlways("/@%s", node->nodeName().utf8().data()); |
| 1732 break; | 1732 break; |
| 1733 default: | 1733 default: |
| 1734 break; | 1734 break; |
| 1735 } | 1735 } |
| 1736 } | 1736 } |
| 1737 WTFLogAlways("\n"); | 1737 WTFLogAlways("\n"); |
| 1738 } | 1738 } |
| 1739 | 1739 |
| 1740 static void traverseTreeAndMark(const String& baseIndent, const Node* rootNode,
const Node* markedNode1, const char* markedLabel1, const Node* markedNode2, cons
t char* markedLabel2) | 1740 static void traverseTreeAndMark(const String& baseIndent, const Node* rootNode,
const Node* markedNode1, const char* markedLabel1, const Node* markedNode2, cons
t char* markedLabel2) |
| (...skipping 738 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2479 visitor->traceWrappers(m_next); | 2479 visitor->traceWrappers(m_next); |
| 2480 if (hasRareData()) | 2480 if (hasRareData()) |
| 2481 visitor->traceWrappers(rareData()); | 2481 visitor->traceWrappers(rareData()); |
| 2482 EventTarget::traceWrappers(visitor); | 2482 EventTarget::traceWrappers(visitor); |
| 2483 } | 2483 } |
| 2484 | 2484 |
| 2485 unsigned Node::lengthOfContents() const | 2485 unsigned Node::lengthOfContents() const |
| 2486 { | 2486 { |
| 2487 // This switch statement must be consistent with that of Range::processConte
ntsBetweenOffsets. | 2487 // This switch statement must be consistent with that of Range::processConte
ntsBetweenOffsets. |
| 2488 switch (getNodeType()) { | 2488 switch (getNodeType()) { |
| 2489 case Node::TEXT_NODE: | 2489 case Node::kTextNode: |
| 2490 case Node::CDATA_SECTION_NODE: | 2490 case Node::kCdataSectionNode: |
| 2491 case Node::COMMENT_NODE: | 2491 case Node::kCommentNode: |
| 2492 case Node::PROCESSING_INSTRUCTION_NODE: | 2492 case Node::kProcessingInstructionNode: |
| 2493 return toCharacterData(this)->length(); | 2493 return toCharacterData(this)->length(); |
| 2494 case Node::ELEMENT_NODE: | 2494 case Node::kElementNode: |
| 2495 case Node::DOCUMENT_NODE: | 2495 case Node::kDocumentNode: |
| 2496 case Node::DOCUMENT_FRAGMENT_NODE: | 2496 case Node::kDocumentFragmentNode: |
| 2497 return toContainerNode(this)->countChildren(); | 2497 return toContainerNode(this)->countChildren(); |
| 2498 case Node::ATTRIBUTE_NODE: | 2498 case Node::kAttributeNode: |
| 2499 case Node::DOCUMENT_TYPE_NODE: | 2499 case Node::kDocumentTypeNode: |
| 2500 return 0; | 2500 return 0; |
| 2501 } | 2501 } |
| 2502 ASSERT_NOT_REACHED(); | 2502 ASSERT_NOT_REACHED(); |
| 2503 return 0; | 2503 return 0; |
| 2504 } | 2504 } |
| 2505 | 2505 |
| 2506 v8::Local<v8::Object> Node::wrap(v8::Isolate* isolate, v8::Local<v8::Object> cre
ationContext) | 2506 v8::Local<v8::Object> Node::wrap(v8::Isolate* isolate, v8::Local<v8::Object> cre
ationContext) |
| 2507 { | 2507 { |
| 2508 DCHECK(!DOMDataStore::containsWrapper(this, isolate)); | 2508 DCHECK(!DOMDataStore::containsWrapper(this, isolate)); |
| 2509 | 2509 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2544 | 2544 |
| 2545 void showNodePath(const blink::Node* node) | 2545 void showNodePath(const blink::Node* node) |
| 2546 { | 2546 { |
| 2547 if (node) | 2547 if (node) |
| 2548 node->showNodePathForThis(); | 2548 node->showNodePathForThis(); |
| 2549 else | 2549 else |
| 2550 fprintf(stderr, "Cannot showNodePath for (nil)\n"); | 2550 fprintf(stderr, "Cannot showNodePath for (nil)\n"); |
| 2551 } | 2551 } |
| 2552 | 2552 |
| 2553 #endif | 2553 #endif |
| OLD | NEW |