c_instance.cpp revision 5f1ab04193ad0130ca8204aadaceae083aca9881
1/* 2 * Copyright (C) 2003, 2006 Apple Computer, 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 28#if ENABLE(NETSCAPE_PLUGIN_API) 29 30#include "c_instance.h" 31 32#include "c_class.h" 33#include "c_runtime.h" 34#include "c_utility.h" 35#include "IdentifierRep.h" 36#include "npruntime_impl.h" 37#include "runtime_root.h" 38#include <runtime/ArgList.h> 39#include <runtime/Error.h> 40#include <interpreter/CallFrame.h> 41#include <runtime/JSLock.h> 42#include <runtime/JSNumberCell.h> 43#include <runtime/PropertyNameArray.h> 44#include <wtf/Assertions.h> 45#include <wtf/StdLibExtras.h> 46#include <wtf/StringExtras.h> 47#include <wtf/Vector.h> 48 49using namespace WebCore; 50 51namespace JSC { 52namespace Bindings { 53 54using JSC::UString; 55 56static JSC::UString& globalExceptionString() 57{ 58 DEFINE_STATIC_LOCAL(JSC::UString, exceptionStr, ()); 59 return exceptionStr; 60} 61 62void CInstance::setGlobalException(UString exception) 63{ 64 globalExceptionString() = exception; 65} 66 67void CInstance::moveGlobalExceptionToExecState(ExecState* exec) 68{ 69 if (globalExceptionString().isNull()) 70 return; 71 72 { 73 JSLock lock(false); 74 throwError(exec, GeneralError, globalExceptionString()); 75 } 76 77 globalExceptionString() = UString(); 78} 79 80CInstance::CInstance(NPObject* o, PassRefPtr<RootObject> rootObject) 81 : Instance(rootObject) 82{ 83 _object = _NPN_RetainObject(o); 84 _class = 0; 85} 86 87CInstance::~CInstance() 88{ 89 _NPN_ReleaseObject(_object); 90} 91 92Class *CInstance::getClass() const 93{ 94 if (!_class) 95 _class = CClass::classForIsA(_object->_class); 96 return _class; 97} 98 99bool CInstance::supportsInvokeDefaultMethod() const 100{ 101 return _object->_class->invokeDefault; 102} 103 104JSValue CInstance::invokeMethod(ExecState* exec, const MethodList& methodList, const ArgList& args) 105{ 106 // Overloading methods are not allowed by NPObjects. Should only be one 107 // name match for a particular method. 108 ASSERT(methodList.size() == 1); 109 110 CMethod* method = static_cast<CMethod*>(methodList[0]); 111 112 NPIdentifier ident = method->identifier(); 113 if (!_object->_class->hasMethod(_object, ident)) 114 return jsUndefined(); 115 116 unsigned count = args.size(); 117 Vector<NPVariant, 8> cArgs(count); 118 119 unsigned i; 120 for (i = 0; i < count; i++) 121 convertValueToNPVariant(exec, args.at(i), &cArgs[i]); 122 123 // Invoke the 'C' method. 124#ifdef ANDROID_NPN_SETEXCEPTION 125 SetGlobalException(0); 126#endif 127 NPVariant resultVariant; 128 VOID_TO_NPVARIANT(resultVariant); 129 130 { 131 JSLock::DropAllLocks dropAllLocks(false); 132 ASSERT(globalExceptionString().isNull()); 133 _object->_class->invoke(_object, ident, cArgs.data(), count, &resultVariant); 134 moveGlobalExceptionToExecState(exec); 135 } 136 137 for (i = 0; i < count; i++) 138 _NPN_ReleaseVariantValue(&cArgs[i]); 139 140 JSValue resultValue = convertNPVariantToValue(exec, &resultVariant, _rootObject.get()); 141 _NPN_ReleaseVariantValue(&resultVariant); 142#ifdef ANDROID_NPN_SETEXCEPTION 143 MoveGlobalExceptionToExecState(exec); 144#endif 145 return resultValue; 146} 147 148 149JSValue CInstance::invokeDefaultMethod(ExecState* exec, const ArgList& args) 150{ 151 if (!_object->_class->invokeDefault) 152 return jsUndefined(); 153 154 unsigned count = args.size(); 155 Vector<NPVariant, 8> cArgs(count); 156 157 unsigned i; 158 for (i = 0; i < count; i++) 159 convertValueToNPVariant(exec, args.at(i), &cArgs[i]); 160 161 // Invoke the 'C' method. 162#ifdef ANDROID_NPN_SETEXCEPTION 163 SetGlobalException(0); 164#endif 165 NPVariant resultVariant; 166 VOID_TO_NPVARIANT(resultVariant); 167 { 168 JSLock::DropAllLocks dropAllLocks(false); 169 ASSERT(globalExceptionString().isNull()); 170 _object->_class->invokeDefault(_object, cArgs.data(), count, &resultVariant); 171 moveGlobalExceptionToExecState(exec); 172 } 173 174 for (i = 0; i < count; i++) 175 _NPN_ReleaseVariantValue(&cArgs[i]); 176 177 JSValue resultValue = convertNPVariantToValue(exec, &resultVariant, _rootObject.get()); 178 _NPN_ReleaseVariantValue(&resultVariant); 179#ifdef ANDROID_NPN_SETEXCEPTION 180 MoveGlobalExceptionToExecState(exec); 181#endif 182 return resultValue; 183} 184 185bool CInstance::supportsConstruct() const 186{ 187 return _object->_class->construct; 188} 189 190JSValue CInstance::invokeConstruct(ExecState* exec, const ArgList& args) 191{ 192 if (!_object->_class->construct) 193 return jsUndefined(); 194 195 unsigned count = args.size(); 196 Vector<NPVariant, 8> cArgs(count); 197 198 unsigned i; 199 for (i = 0; i < count; i++) 200 convertValueToNPVariant(exec, args.at(i), &cArgs[i]); 201 202 // Invoke the 'C' method. 203 NPVariant resultVariant; 204 VOID_TO_NPVARIANT(resultVariant); 205 { 206 JSLock::DropAllLocks dropAllLocks(false); 207 ASSERT(globalExceptionString().isNull()); 208 _object->_class->construct(_object, cArgs.data(), count, &resultVariant); 209 moveGlobalExceptionToExecState(exec); 210 } 211 212 for (i = 0; i < count; i++) 213 _NPN_ReleaseVariantValue(&cArgs[i]); 214 215 JSValue resultValue = convertNPVariantToValue(exec, &resultVariant, _rootObject.get()); 216 _NPN_ReleaseVariantValue(&resultVariant); 217 return resultValue; 218} 219 220JSValue CInstance::defaultValue(ExecState* exec, PreferredPrimitiveType hint) const 221{ 222 if (hint == PreferString) 223 return stringValue(exec); 224 if (hint == PreferNumber) 225 return numberValue(exec); 226 return valueOf(exec); 227} 228 229JSValue CInstance::stringValue(ExecState* exec) const 230{ 231 char buf[1024]; 232 snprintf(buf, sizeof(buf), "NPObject %p, NPClass %p", _object, _object->_class); 233 return jsString(exec, buf); 234} 235 236JSValue CInstance::numberValue(ExecState* exec) const 237{ 238 // FIXME: Implement something sensible. 239 return jsNumber(exec, 0); 240} 241 242JSValue CInstance::booleanValue() const 243{ 244 // FIXME: Implement something sensible. 245 return jsBoolean(false); 246} 247 248JSValue CInstance::valueOf(ExecState* exec) const 249{ 250 return stringValue(exec); 251} 252 253void CInstance::getPropertyNames(ExecState* exec, PropertyNameArray& nameArray) 254{ 255 if (!NP_CLASS_STRUCT_VERSION_HAS_ENUM(_object->_class) || !_object->_class->enumerate) 256 return; 257 258 uint32_t count; 259 NPIdentifier* identifiers; 260 261 { 262 JSLock::DropAllLocks dropAllLocks(false); 263 ASSERT(globalExceptionString().isNull()); 264 bool ok = _object->_class->enumerate(_object, &identifiers, &count); 265 moveGlobalExceptionToExecState(exec); 266 if (!ok) 267 return; 268 } 269 270 for (uint32_t i = 0; i < count; i++) { 271 IdentifierRep* identifier = static_cast<IdentifierRep*>(identifiers[i]); 272 273 if (identifier->isString()) 274 nameArray.add(identifierFromNPIdentifier(identifier->string())); 275 else 276 nameArray.add(Identifier::from(exec, identifier->number())); 277 } 278 279 // FIXME: This should really call NPN_MemFree but that's in WebKit 280 free(identifiers); 281} 282 283} 284} 285 286#endif // ENABLE(NETSCAPE_PLUGIN_API) 287