1 /* 2 * Copyright (C) 2003, 2008 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include "config.h" 27 #include "runtime_method.h" 28 29 #include "JSDOMBinding.h" 30 #include "runtime_object.h" 31 #include <runtime/Error.h> 32 #include <runtime/FunctionPrototype.h> 33 34 using namespace WebCore; 35 36 namespace JSC { 37 38 using namespace Bindings; 39 40 ASSERT_CLASS_FITS_IN_CELL(RuntimeMethod); 41 42 const ClassInfo RuntimeMethod::s_info = { "RuntimeMethod", 0, 0, 0 }; 43 44 RuntimeMethod::RuntimeMethod(ExecState* exec, const Identifier& ident, Bindings::MethodList& m) 45 // FIXME: deprecatedGetDOMStructure uses the prototype off of the wrong global object 46 // exec-globalData() is also likely wrong. 47 // Callers will need to pass in the right global object corresponding to this native object "m". 48 : InternalFunction(&exec->globalData(), deprecatedGetDOMStructure<RuntimeMethod>(exec), ident) 49 , _methodList(new MethodList(m)) 50 { 51 } 52 53 JSValue RuntimeMethod::lengthGetter(ExecState* exec, const Identifier&, const PropertySlot& slot) 54 { 55 RuntimeMethod* thisObj = static_cast<RuntimeMethod*>(asObject(slot.slotBase())); 56 57 // Ick! There may be more than one method with this name. Arbitrarily 58 // just pick the first method. The fundamental problem here is that 59 // JavaScript doesn't have the notion of method overloading and 60 // Java does. 61 // FIXME: a better solution might be to give the maximum number of parameters 62 // of any method 63 return jsNumber(exec, thisObj->_methodList->at(0)->numParameters()); 64 } 65 66 bool RuntimeMethod::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot &slot) 67 { 68 if (propertyName == exec->propertyNames().length) { 69 slot.setCustom(this, lengthGetter); 70 return true; 71 } 72 73 return InternalFunction::getOwnPropertySlot(exec, propertyName, slot); 74 } 75 76 bool RuntimeMethod::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor &descriptor) 77 { 78 if (propertyName == exec->propertyNames().length) { 79 PropertySlot slot; 80 slot.setCustom(this, lengthGetter); 81 descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum); 82 return true; 83 } 84 85 return InternalFunction::getOwnPropertyDescriptor(exec, propertyName, descriptor); 86 } 87 88 static JSValue JSC_HOST_CALL callRuntimeMethod(ExecState* exec, JSObject* function, JSValue thisValue, const ArgList& args) 89 { 90 RuntimeMethod* method = static_cast<RuntimeMethod*>(function); 91 92 if (method->methods()->isEmpty()) 93 return jsUndefined(); 94 95 RuntimeObjectImp* imp; 96 97 if (thisValue.inherits(&RuntimeObjectImp::s_info)) { 98 imp = static_cast<RuntimeObjectImp*>(asObject(thisValue)); 99 } else { 100 // If thisObj is the DOM object for a plugin, get the corresponding 101 // runtime object from the DOM object. 102 JSValue value = thisValue.get(exec, Identifier(exec, "__apple_runtime_object")); 103 if (value.inherits(&RuntimeObjectImp::s_info)) 104 imp = static_cast<RuntimeObjectImp*>(asObject(value)); 105 else 106 return throwError(exec, TypeError); 107 } 108 109 RefPtr<Instance> instance = imp->getInternalInstance(); 110 if (!instance) 111 return RuntimeObjectImp::throwInvalidAccessError(exec); 112 113 instance->begin(); 114 JSValue result = instance->invokeMethod(exec, *method->methods(), args); 115 instance->end(); 116 return result; 117 } 118 119 CallType RuntimeMethod::getCallData(CallData& callData) 120 { 121 callData.native.function = callRuntimeMethod; 122 return CallTypeHost; 123 } 124 125 } 126