OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2012 Google Inc. All rights reserved. | 2 * Copyright (C) 2012 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * 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 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 27 matching lines...) Expand all Loading... |
38 #include "Document.h" | 38 #include "Document.h" |
39 #include "DocumentFragment.h" | 39 #include "DocumentFragment.h" |
40 #include "HTMLDocument.h" | 40 #include "HTMLDocument.h" |
41 #include "HTMLDocumentParser.h" | 41 #include "HTMLDocumentParser.h" |
42 #include "HTMLElement.h" | 42 #include "HTMLElement.h" |
43 #include "HTMLHeadElement.h" | 43 #include "HTMLHeadElement.h" |
44 #include "HTMLNames.h" | 44 #include "HTMLNames.h" |
45 #include "Node.h" | 45 #include "Node.h" |
46 | 46 |
47 #include <wtf/Deque.h> | 47 #include <wtf/Deque.h> |
| 48 #include <wtf/HashTraits.h> |
48 #include <wtf/RefPtr.h> | 49 #include <wtf/RefPtr.h> |
49 #include <wtf/SHA1.h> | 50 #include <wtf/SHA1.h> |
50 #include <wtf/text/CString.h> | 51 #include <wtf/text/CString.h> |
51 | 52 |
52 using namespace std; | 53 using namespace std; |
53 | 54 |
54 namespace WebCore { | 55 namespace WebCore { |
55 | 56 |
56 using HTMLNames::bodyTag; | 57 using HTMLNames::bodyTag; |
57 using HTMLNames::headTag; | 58 using HTMLNames::headTag; |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
252 if (!newMap[i].first || newMap[i - 1].first || newMap[i].second <= 0) | 253 if (!newMap[i].first || newMap[i - 1].first || newMap[i].second <= 0) |
253 continue; | 254 continue; |
254 | 255 |
255 size_t j = newMap[i].second - 1; | 256 size_t j = newMap[i].second - 1; |
256 if (!oldMap[j].first && newList[i - 1]->m_sha1 == oldList[j]->m_sha1) { | 257 if (!oldMap[j].first && newList[i - 1]->m_sha1 == oldList[j]->m_sha1) { |
257 newMap[i - 1] = make_pair(newList[i - 1].get(), j); | 258 newMap[i - 1] = make_pair(newList[i - 1].get(), j); |
258 oldMap[j] = make_pair(oldList[j].get(), i - 1); | 259 oldMap[j] = make_pair(oldList[j].get(), i - 1); |
259 } | 260 } |
260 } | 261 } |
261 | 262 |
| 263 #ifdef DEBUG_DOM_EDITOR |
| 264 dumpMap(oldMap, "OLD"); |
| 265 dumpMap(newMap, "NEW"); |
| 266 #endif |
| 267 |
262 return make_pair(oldMap, newMap); | 268 return make_pair(oldMap, newMap); |
263 } | 269 } |
264 | 270 |
265 void DOMEditor::innerPatchChildren(ContainerNode* parentNode, const Vector<OwnPt
r<Digest> >& oldList, const Vector<OwnPtr<Digest> >& newList, ExceptionCode& ec) | 271 void DOMEditor::innerPatchChildren(ContainerNode* parentNode, const Vector<OwnPt
r<Digest> >& oldList, const Vector<OwnPtr<Digest> >& newList, ExceptionCode& ec) |
266 { | 272 { |
267 pair<ResultMap, ResultMap> resultMaps = diff(oldList, newList); | 273 pair<ResultMap, ResultMap> resultMaps = diff(oldList, newList); |
268 ResultMap& oldMap = resultMaps.first; | 274 ResultMap& oldMap = resultMaps.first; |
269 ResultMap& newMap = resultMaps.second; | 275 ResultMap& newMap = resultMaps.second; |
270 | 276 |
271 Digest* oldHead = 0; | 277 Digest* oldHead = 0; |
272 Digest* oldBody = 0; | 278 Digest* oldBody = 0; |
273 | 279 |
274 // 1. First strip everything except for the nodes that retain. Collect pendi
ng merges. | 280 // 1. First strip everything except for the nodes that retain. Collect pendi
ng merges. |
275 HashMap<Digest*, Digest*> merges; | 281 HashMap<Digest*, Digest*> merges; |
| 282 HashSet<size_t, WTF::IntHash<size_t>, WTF::UnsignedWithZeroKeyHashTraits<siz
e_t> > usedNewOrdinals; |
276 for (size_t i = 0; i < oldList.size(); ++i) { | 283 for (size_t i = 0; i < oldList.size(); ++i) { |
277 if (oldMap[i].first) | 284 if (oldMap[i].first) { |
278 continue; | 285 if (!usedNewOrdinals.contains(oldMap[i].second)) { |
| 286 usedNewOrdinals.add(oldMap[i].second); |
| 287 continue; |
| 288 } |
| 289 oldMap[i].first = 0; |
| 290 oldMap[i].second = 0; |
| 291 } |
279 | 292 |
280 // Always match <head> and <body> tags with each other - we can't remove
them from the DOM | 293 // Always match <head> and <body> tags with each other - we can't remove
them from the DOM |
281 // upon patching. | 294 // upon patching. |
282 if (oldList[i]->m_node->hasTagName(headTag)) { | 295 if (oldList[i]->m_node->hasTagName(headTag)) { |
283 oldHead = oldList[i].get(); | 296 oldHead = oldList[i].get(); |
284 continue; | 297 continue; |
285 } | 298 } |
286 if (oldList[i]->m_node->hasTagName(bodyTag)) { | 299 if (oldList[i]->m_node->hasTagName(bodyTag)) { |
287 oldBody = oldList[i].get(); | 300 oldBody = oldList[i].get(); |
288 continue; | 301 continue; |
(...skipping 10 matching lines...) Expand all Loading... |
299 if (ec) | 312 if (ec) |
300 return; | 313 return; |
301 } | 314 } |
302 } else { | 315 } else { |
303 removeChild(oldList[i].get(), ec); | 316 removeChild(oldList[i].get(), ec); |
304 if (ec) | 317 if (ec) |
305 return; | 318 return; |
306 } | 319 } |
307 } | 320 } |
308 | 321 |
309 // Mark retained nodes as used. | 322 // Mark retained nodes as used, do not reuse node more than once. |
| 323 HashSet<size_t, WTF::IntHash<size_t>, WTF::UnsignedWithZeroKeyHashTraits<siz
e_t> > usedOldOrdinals; |
310 for (size_t i = 0; i < newList.size(); ++i) { | 324 for (size_t i = 0; i < newList.size(); ++i) { |
311 if (newMap[i].first) | 325 if (!newMap[i].first) |
312 markNodeAsUsed(newMap[i].first); | 326 continue; |
| 327 size_t oldOrdinal = newMap[i].second; |
| 328 if (usedOldOrdinals.contains(oldOrdinal)) { |
| 329 // Do not map node more than once |
| 330 newMap[i].first = 0; |
| 331 newMap[i].second = 0; |
| 332 continue; |
| 333 } |
| 334 usedOldOrdinals.add(oldOrdinal); |
| 335 markNodeAsUsed(newMap[i].first); |
313 } | 336 } |
314 | 337 |
315 // Mark <head> and <body> nodes for merge. | 338 // Mark <head> and <body> nodes for merge. |
316 if (oldHead || oldBody) { | 339 if (oldHead || oldBody) { |
317 for (size_t i = 0; i < newList.size(); ++i) { | 340 for (size_t i = 0; i < newList.size(); ++i) { |
318 if (oldHead && newList[i]->m_node->hasTagName(headTag)) | 341 if (oldHead && newList[i]->m_node->hasTagName(headTag)) |
319 merges.set(newList[i].get(), oldHead); | 342 merges.set(newList[i].get(), oldHead); |
320 if (oldBody && newList[i]->m_node->hasTagName(bodyTag)) | 343 if (oldBody && newList[i]->m_node->hasTagName(bodyTag)) |
321 merges.set(newList[i].get(), oldBody); | 344 merges.set(newList[i].get(), oldBody); |
322 } | 345 } |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
444 Deque<Digest*> queue; | 467 Deque<Digest*> queue; |
445 queue.append(digest); | 468 queue.append(digest); |
446 while (!queue.isEmpty()) { | 469 while (!queue.isEmpty()) { |
447 Digest* first = queue.takeFirst(); | 470 Digest* first = queue.takeFirst(); |
448 m_unusedNodesMap.remove(first->m_sha1); | 471 m_unusedNodesMap.remove(first->m_sha1); |
449 for (size_t i = 0; i < first->m_children.size(); ++i) | 472 for (size_t i = 0; i < first->m_children.size(); ++i) |
450 queue.append(first->m_children[i].get()); | 473 queue.append(first->m_children[i].get()); |
451 } | 474 } |
452 } | 475 } |
453 | 476 |
| 477 #ifdef DEBUG_DOM_EDITOR |
| 478 static String nodeName(Node* node) |
| 479 { |
| 480 if (node->document()->isXHTMLDocument()) |
| 481 return node->nodeName(); |
| 482 return node->nodeName().lower(); |
| 483 } |
| 484 |
| 485 void DOMEditor::dumpMap(const ResultMap& map, const String& name) |
| 486 { |
| 487 fprintf(stderr, "\n\n"); |
| 488 for (size_t i = 0; i < map.size(); ++i) |
| 489 fprintf(stderr, "%s[%lu]: %s (%p) - [%lu]\n", name.utf8().data(), i, map
[i].first ? nodeName(map[i].first->m_node).utf8().data() : "", map[i].first, map
[i].second); |
| 490 } |
| 491 #endif |
| 492 |
454 } // namespace WebCore | 493 } // namespace WebCore |
455 | 494 |
456 #endif // ENABLE(INSPECTOR) | 495 #endif // ENABLE(INSPECTOR) |
OLD | NEW |