Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(32)

Side by Side Diff: Source/core/page/FocusController.cpp

Issue 1204213002: Avoid tail recursion to mitigate stack exhaustion (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. 2 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
3 * Copyright (C) 2008 Nuanti Ltd. 3 * Copyright (C) 2008 Nuanti Ltd.
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 361 matching lines...) Expand 10 before | Expand all | Expand 10 after
372 // @return The focus element that comes after/before start node. 372 // @return The focus element that comes after/before start node.
373 // 373 //
374 // [1] https://html.spec.whatwg.org/multipage/interaction.html#sequential-focus- navigation 374 // [1] https://html.spec.whatwg.org/multipage/interaction.html#sequential-focus- navigation
375 // [2] https://w3c.github.io/webcomponents/spec/shadow/#focus-navigation 375 // [2] https://w3c.github.io/webcomponents/spec/shadow/#focus-navigation
376 inline Element* findFocusableElementInternal(WebFocusType type, const FocusNavig ationScope& scope, Node* node) 376 inline Element* findFocusableElementInternal(WebFocusType type, const FocusNavig ationScope& scope, Node* node)
377 { 377 {
378 Element* found = (type == WebFocusTypeForward) ? nextFocusableElement(scope, node) : previousFocusableElement(scope, node); 378 Element* found = (type == WebFocusTypeForward) ? nextFocusableElement(scope, node) : previousFocusableElement(scope, node);
379 return found; 379 return found;
380 } 380 }
381 381
382 Element* findFocusableElementRecursivelyForward(const FocusNavigationScope& scop e, Node* start) 382 Element* findFocusableElementRecursivelyForward(const FocusNavigationScope& scop e, Node* start)
hayato 2015/06/25 07:31:02 The function name should be changed?
kochi 2015/06/25 07:56:32 No, this function is still recursive. (line 391, 4
hayato 2015/06/25 08:04:40 Acknowledged.
383 { 383 {
384 // Starting node is exclusive. 384 // Starting node is exclusive.
385 Element* found = findFocusableElementInternal(WebFocusTypeForward, scope, st art); 385 Element* found = findFocusableElementInternal(WebFocusTypeForward, scope, st art);
386 if (!found) 386 while (found) {
387 return nullptr; 387 if (isShadowHostDelegatesFocus(*found)) {
388 if (isShadowHostDelegatesFocus(*found)) { 388 // If tabindex is positive, find focusable node inside its shadow tr ee.
389 // If tabindex is positive, find focusable node inside its shadow tree. 389 if (found->tabIndex() >= 0 && isShadowHostWithoutCustomFocusLogic(*f ound)) {
390 if (found->tabIndex() >= 0 && isShadowHostWithoutCustomFocusLogic(*found )) { 390 FocusNavigationScope innerScope = FocusNavigationScope::ownedByS hadowHost(*found);
391 FocusNavigationScope innerScope = FocusNavigationScope::ownedByShado wHost(*found); 391 if (Element* foundInInnerFocusScope = findFocusableElementRecurs ivelyForward(innerScope, nullptr))
392 if (Element* foundInInnerFocusScope = findFocusableElementRecursivel yForward(innerScope, nullptr)) 392 return foundInInnerFocusScope;
393 return foundInInnerFocusScope; 393 }
394 // Skip to the next node in the same scope.
395 found = findFocusableElementRecursivelyForward(scope, found);
394 } 396 }
395 // Skip to the next node in the same scope. 397 if (!found || !isNonFocusableFocusScopeOwner(*found))
396 found = findFocusableElementRecursivelyForward(scope, found); 398 break;
399
400 // Now |found| is on a non focusable scope owner (either shadow host or <shadow>)
401 // Find inside the inward scope and return it if found. Otherwise contin ue searching in the same
402 // scope.
403 FocusNavigationScope innerScope = FocusNavigationScope::ownedByNonFocusa bleFocusScopeOwner(*found);
404 if (Element* foundInInnerFocusScope = findFocusableElementRecursivelyFor ward(innerScope, nullptr))
405 return foundInInnerFocusScope;
406
407 found = findFocusableElementInternal(WebFocusTypeForward, scope, found);
397 } 408 }
398 if (!found || !isNonFocusableFocusScopeOwner(*found)) 409 return found;
hayato 2015/06/25 07:31:02 return nullptr;
kochi 2015/06/25 07:56:32 No, if line 398 breaks, |found| can be non-null.
hayato 2015/06/25 08:04:40 Ops. I didn't realize it. line 398 should `return
kochi 2015/06/25 08:23:38 Done. If the code doesn't break there, line 409 s
399 return found;
400
401 // Now |found| is on a non focusable scope owner (either shadow host or <sha dow>)
402 // Find inside the inward scope and return it if found. Otherwise continue s earching in the same
403 // scope.
404 FocusNavigationScope innerScope = FocusNavigationScope::ownedByNonFocusableF ocusScopeOwner(*found);
405 if (Element* foundInInnerFocusScope = findFocusableElementRecursivelyForward (innerScope, nullptr))
406 return foundInInnerFocusScope;
407 return findFocusableElementRecursivelyForward(scope, found);
408 } 410 }
409 411
410 Element* findFocusableElementRecursivelyBackward(const FocusNavigationScope& sco pe, Node* start) 412 Element* findFocusableElementRecursivelyBackward(const FocusNavigationScope& sco pe, Node* start)
hayato 2015/06/25 07:31:02 The same.
411 { 413 {
412 // Starting node is exclusive. 414 // Starting node is exclusive.
413 Element* found = findFocusableElementInternal(WebFocusTypeBackward, scope, s tart); 415 Element* found = findFocusableElementInternal(WebFocusTypeBackward, scope, s tart);
414 if (!found) 416 while (found) {
415 return nullptr; 417 // Now |found| is on a focusable shadow host.
418 // Find inside shadow backwards. If any focusable element is found, retu rn it, otherwise return
419 // the host itself.
420 if (isKeyboardFocusableShadowHost(*found)) {
421 FocusNavigationScope innerScope = FocusNavigationScope::ownedByShado wHost(*found);
422 Element* foundInInnerFocusScope = findFocusableElementRecursivelyBac kward(innerScope, nullptr);
423 if (foundInInnerFocusScope)
424 return foundInInnerFocusScope;
425 if (isShadowHostDelegatesFocus(*found))
426 found = findFocusableElementRecursivelyBackward(scope, found);
427 break;
428 }
416 429
417 // Now |found| is on a focusable shadow host. 430 // If delegatesFocus is true and tabindex is negative, skip the whole sh adow tree under the
418 // Find inside shadow backwards. If any focusable element is found, return i t, otherwise return 431 // shadow host.
419 // the host itself. 432 if (isShadowHostDelegatesFocus(*found) && found->tabIndex() < 0)
420 if (isKeyboardFocusableShadowHost(*found)) { 433 return findFocusableElementRecursivelyBackward(scope, found);
421 FocusNavigationScope innerScope = FocusNavigationScope::ownedByShadowHos t(*found); 434
422 Element* foundInInnerFocusScope = findFocusableElementRecursivelyBackwar d(innerScope, nullptr); 435 // Now |found| is on a non focusable scope owner (either shadow host or <shadow>).
423 if (foundInInnerFocusScope) 436 // Find focusable node in descendant scope. If not found, find next focu sable node within the
424 return foundInInnerFocusScope; 437 // current scope.
425 if (isShadowHostDelegatesFocus(*found)) 438 if (isNonFocusableFocusScopeOwner(*found)) {
426 found = findFocusableElementRecursivelyBackward(scope, found); 439 FocusNavigationScope innerScope = FocusNavigationScope::ownedByNonFo cusableFocusScopeOwner(*found);
427 return found; 440 Element* foundInInnerFocusScope = findFocusableElementRecursivelyBac kward(innerScope, nullptr);
441 return foundInInnerFocusScope ? foundInInnerFocusScope : findFocusab leElementRecursivelyBackward(scope, found);
442 }
443 if (!isShadowHostDelegatesFocus(*found))
444 break;
445 found = findFocusableElementInternal(WebFocusTypeBackward, scope, found) ;
428 } 446 }
429 447 return found;
hayato 2015/06/25 07:31:02 return nullptr;
kochi 2015/06/25 07:56:32 No, if line 427 or 443 breaks, |found| is non-null
hayato 2015/06/25 08:04:40 Instead of `break`, they should `return found`.
kochi 2015/06/25 08:23:38 Done.
430 // If delegatesFocus is true and tabindex is negative, skip the whole shadow tree under the
431 // shadow host.
432 if (isShadowHostDelegatesFocus(*found) && found->tabIndex() < 0)
433 return findFocusableElementRecursivelyBackward(scope, found);
434
435 // Now |found| is on a non focusable scope owner (either shadow host or <sha dow>).
436 // Find focusable node in descendant scope. If not found, find next focusabl e node within the
437 // current scope.
438 if (isNonFocusableFocusScopeOwner(*found)) {
439 FocusNavigationScope innerScope = FocusNavigationScope::ownedByNonFocusa bleFocusScopeOwner(*found);
440 Element* foundInInnerFocusScope = findFocusableElementRecursivelyBackwar d(innerScope, nullptr);
441 return foundInInnerFocusScope ? foundInInnerFocusScope : findFocusableEl ementRecursivelyBackward(scope, found);
442 }
443
444 return !isShadowHostDelegatesFocus(*found) ? found : findFocusableElementRec ursivelyBackward(scope, found);
445 } 448 }
446 449
447 Element* findFocusableElementRecursively(WebFocusType type, const FocusNavigatio nScope& scope, Node* start) 450 Element* findFocusableElementRecursively(WebFocusType type, const FocusNavigatio nScope& scope, Node* start)
448 { 451 {
449 return (type == WebFocusTypeForward) ? 452 return (type == WebFocusTypeForward) ?
450 findFocusableElementRecursivelyForward(scope, start) : 453 findFocusableElementRecursivelyForward(scope, start) :
451 findFocusableElementRecursivelyBackward(scope, start); 454 findFocusableElementRecursivelyBackward(scope, start);
452 } 455 }
453 456
454 Element* findFocusableElementDescendingDownIntoFrameDocument(WebFocusType type, Element* element) 457 Element* findFocusableElementDescendingDownIntoFrameDocument(WebFocusType type, Element* element)
(...skipping 582 matching lines...) Expand 10 before | Expand all | Expand 10 after
1037 return consumed; 1040 return consumed;
1038 } 1041 }
1039 1042
1040 DEFINE_TRACE(FocusController) 1043 DEFINE_TRACE(FocusController)
1041 { 1044 {
1042 visitor->trace(m_page); 1045 visitor->trace(m_page);
1043 visitor->trace(m_focusedFrame); 1046 visitor->trace(m_focusedFrame);
1044 } 1047 }
1045 1048
1046 } // namespace blink 1049 } // namespace blink
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698