Home | History | Annotate | Download | only in js
      1 /*
      2  *  Copyright (C) 2001 Peter Kelly (pmk (at) 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 "JSNode.h"
     24 #include "JSNodeFilter.h"
     25 #include "NodeFilter.h"
     26 #include <runtime/Error.h>
     27 #include <runtime/JSLock.h>
     28 
     29 namespace WebCore {
     30 
     31 using namespace JSC;
     32 
     33 ASSERT_CLASS_FITS_IN_CELL(JSNodeFilterCondition);
     34 
     35 JSNodeFilterCondition::JSNodeFilterCondition(JSGlobalData& globalData, NodeFilter* owner, JSValue filter)
     36     : m_filter(globalData, filter, &m_weakOwner, owner)
     37 {
     38 }
     39 
     40 short JSNodeFilterCondition::acceptNode(JSC::ExecState* exec, Node* filterNode) const
     41 {
     42     JSLock lock(SilenceAssertionsOnly);
     43 
     44     if (!m_filter.isObject())
     45         return NodeFilter::FILTER_ACCEPT;
     46 
     47    // The exec argument here should only be null if this was called from a
     48    // non-JavaScript language, and this is a JavaScript filter, and the document
     49    // in question is not associated with the frame. In that case, we're going to
     50    // behave incorrectly, and just reject nodes instead of calling the filter function.
     51    // To fix that we'd need to come up with a way to find a suitable JavaScript
     52    // execution context for the filter function to run in.
     53     if (!exec)
     54         return NodeFilter::FILTER_REJECT;
     55 
     56     JSValue function = m_filter.get();
     57     CallData callData;
     58     CallType callType = getCallData(function, callData);
     59     if (callType == CallTypeNone) {
     60         function = m_filter.get().get(exec, Identifier(exec, "acceptNode"));
     61         callType = getCallData(function, callData);
     62         if (callType == CallTypeNone) {
     63             throwError(exec, createTypeError(exec, "NodeFilter object does not have an acceptNode function"));
     64             return NodeFilter::FILTER_REJECT;
     65         }
     66     }
     67 
     68     MarkedArgumentBuffer args;
     69     // FIXME: The node should have the prototype chain that came from its document, not
     70     // whatever prototype chain might be on the window this filter came from. Bug 27662
     71     args.append(toJS(exec, deprecatedGlobalObjectForPrototype(exec), filterNode));
     72     if (exec->hadException())
     73         return NodeFilter::FILTER_REJECT;
     74 
     75     JSValue result = JSC::call(exec, function, callType, callData, m_filter.get(), args);
     76     if (exec->hadException())
     77         return NodeFilter::FILTER_REJECT;
     78 
     79     int intResult = result.toInt32(exec);
     80     if (exec->hadException())
     81         return NodeFilter::FILTER_REJECT;
     82 
     83     return intResult;
     84 }
     85 
     86 bool JSNodeFilterCondition::WeakOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown>, void* context, MarkStack& markStack)
     87 {
     88     return markStack.containsOpaqueRoot(context);
     89 }
     90 
     91 } // namespace WebCore
     92