9a0a6edb834a6b7521530df907b280278976348a
[WebKit-https.git] / Source / WebCore / bindings / js / JSNodeFilterCondition.cpp
1 /*
2  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
3  *  Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
4  *
5  *  This library is free software; you can redistribute it and/or
6  *  modify it under the terms of the GNU Lesser General Public
7  *  License as published by the Free Software Foundation; either
8  *  version 2 of the License, or (at your option) any later version.
9  *
10  *  This library is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  *  Lesser General Public License for more details.
14  *
15  *  You should have received a copy of the GNU Lesser General Public
16  *  License along with this library; if not, write to the Free Software
17  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18  */
19
20 #include "config.h"
21 #include "JSNodeFilterCondition.h"
22
23 #include "JSMainThreadExecState.h"
24 #include "JSNode.h"
25 #include "JSNodeFilter.h"
26 #include "NodeFilter.h"
27 #include <runtime/Error.h>
28 #include <runtime/JSLock.h>
29
30 namespace WebCore {
31
32 using namespace JSC;
33
34 JSNodeFilterCondition::JSNodeFilterCondition(VM&, NodeFilter* owner, JSValue filter)
35     : m_filter(filter.isObject() ? PassWeak<JSObject>(jsCast<JSObject*>(filter), &m_weakOwner, owner) : nullptr)
36 {
37 }
38
39 short JSNodeFilterCondition::acceptNode(JSC::ExecState* exec, Node* filterNode) const
40 {
41     JSLockHolder lock(exec);
42
43     if (!m_filter)
44         return NodeFilter::FILTER_ACCEPT;
45
46     // Exec is null if we've been called from a non-JavaScript language and the document
47     // is no longer able to run JavaScript (e.g., it's disconnected from its frame).
48     if (!exec)
49         return NodeFilter::FILTER_REJECT;
50
51     JSValue filter = m_filter.get();
52     CallData callData;
53     CallType callType = getCallData(filter, callData);
54     if (callType == CallTypeNone) {
55         filter = filter.get(exec, Identifier(exec, "acceptNode"));
56         callType = getCallData(filter, callData);
57         if (callType == CallTypeNone) {
58             throwError(exec, createTypeError(exec, "NodeFilter object does not have an acceptNode function"));
59             return NodeFilter::FILTER_REJECT;
60         }
61     }
62
63     MarkedArgumentBuffer args;
64     // FIXME: The node should have the prototype chain that came from its document, not
65     // whatever prototype chain might be on the window this filter came from. Bug 27662
66     args.append(toJS(exec, deprecatedGlobalObjectForPrototype(exec), filterNode));
67     if (exec->hadException())
68         return NodeFilter::FILTER_REJECT;
69
70     JSValue result = JSMainThreadExecState::call(exec, filter, callType, callData, m_filter.get(), args);
71     if (exec->hadException())
72         return NodeFilter::FILTER_REJECT;
73
74     int intResult = result.toInt32(exec);
75     if (exec->hadException())
76         return NodeFilter::FILTER_REJECT;
77
78     return intResult;
79 }
80
81 bool JSNodeFilterCondition::WeakOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown>, void* context, SlotVisitor& visitor)
82 {
83     return visitor.containsOpaqueRoot(context);
84 }
85
86 } // namespace WebCore