1 /*
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  * Copyright (C) 2000 Frederik Holljen (frederik.holljen@hig.no)
4  * Copyright (C) 2001 Peter Kelly (pmk@post.com)
5  * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
6  * Copyright (C) 2004, 2008 Apple Inc. All rights reserved.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public License
19  * along with this library; see the file COPYING.LIB.  If not, write to
20  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  *
23  */
24 
25 #include "third_party/blink/renderer/core/dom/node_iterator_base.h"
26 
27 #include "third_party/blink/renderer/bindings/core/v8/v8_node_filter.h"
28 #include "third_party/blink/renderer/core/dom/node.h"
29 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
30 #include "third_party/blink/renderer/core/frame/web_feature.h"
31 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
32 #include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
33 
34 namespace blink {
35 
NodeIteratorBase(Node * root_node,unsigned what_to_show,V8NodeFilter * node_filter)36 NodeIteratorBase::NodeIteratorBase(Node* root_node,
37                                    unsigned what_to_show,
38                                    V8NodeFilter* node_filter)
39     : root_(root_node), what_to_show_(what_to_show), filter_(node_filter) {}
40 
AcceptNode(Node * node,ExceptionState & exception_state)41 unsigned NodeIteratorBase::AcceptNode(Node* node,
42                                       ExceptionState& exception_state) {
43   // DOM 6. Traversal
44   // https://dom.spec.whatwg.org/#traversal
45   // Each NodeIterator and TreeWalker object has an associated active flag to
46   // avoid recursive invocations.
47   if (active_flag_) {
48     // 1. If the active flag is set, then throw an "InvalidStateError"
49     // DOMException.
50     exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
51                                       "Filter function can't be recursive");
52     return V8NodeFilter::FILTER_REJECT;
53   }
54 
55   // 2. Let n be node’s nodeType attribute value minus 1.
56   // 3. If the nth bit (where 0 is the least significant bit) of whatToShow is
57   // not set, then return FILTER_SKIP.
58   //
59   // The bit twiddling here is done to map DOM node types, which are given as
60   // integers from 1 through 14, to whatToShow bit masks.
61   if (!(((1 << (node->getNodeType() - 1)) & what_to_show_)))
62     return V8NodeFilter::FILTER_SKIP;
63 
64   // 4. If filter is null, then return FILTER_ACCEPT.
65   if (!filter_)
66     return V8NodeFilter::FILTER_ACCEPT;
67 
68   // 5. Set the active flag.
69   base::AutoReset<bool> set_active_flag(&active_flag_, true);
70 
71   // 6. Let result be the return value of call a user object’s operation with
72   // filter, "acceptNode", and « node ». If this throws an exception, then unset
73   // the active flag and rethrow the exception.
74   v8::TryCatch try_catch(filter_->GetIsolate());
75   uint16_t result = 0;
76   if (!filter_->acceptNode(nullptr, node).To(&result)) {
77     exception_state.RethrowV8Exception(try_catch.Exception());
78     return 0;
79   }
80 
81   UseCounter::Count(
82       ExecutionContext::From(filter_->CallbackRelevantScriptState()),
83       filter_->IsCallbackObjectCallableForNodeIteratorBase()
84           ? WebFeature::kNodeFilterIsFunction
85           : WebFeature::kNodeFilterIsObject);
86 
87   // 7. Unset the active flag.
88   // 8. Return result.
89   return result;
90 }
91 
Trace(Visitor * visitor)92 void NodeIteratorBase::Trace(Visitor* visitor) {
93   visitor->Trace(root_);
94   visitor->Trace(filter_);
95 }
96 
97 }  // namespace blink
98