2 * Copyright (C) 2003, 2006 Apple Computer, Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
28 #if ENABLE(NETSCAPE_PLUGIN_API)
30 #include "c_instance.h"
32 #include "CRuntimeObject.h"
33 #include "IdentifierRep.h"
34 #include "JSDOMBinding.h"
36 #include "c_runtime.h"
37 #include "c_utility.h"
38 #include "npruntime_impl.h"
39 #include "runtime_method.h"
40 #include "runtime_root.h"
41 #include <interpreter/CallFrame.h>
42 #include <runtime/ArgList.h>
43 #include <runtime/Error.h>
44 #include <runtime/FunctionPrototype.h>
45 #include <runtime/JSLock.h>
46 #include <runtime/PropertyNameArray.h>
47 #include <wtf/Assertions.h>
48 #include <wtf/StdLibExtras.h>
49 #include <wtf/StringExtras.h>
50 #include <wtf/Vector.h>
52 using namespace WebCore;
59 static JSC::UString& globalExceptionString()
61 DEFINE_STATIC_LOCAL(JSC::UString, exceptionStr, ());
65 void CInstance::setGlobalException(UString exception)
67 globalExceptionString() = exception;
70 void CInstance::moveGlobalExceptionToExecState(ExecState* exec)
72 if (globalExceptionString().isNull())
76 JSLock lock(SilenceAssertionsOnly);
77 throwError(exec, createError(exec, globalExceptionString()));
80 globalExceptionString() = UString();
83 CInstance::CInstance(NPObject* o, PassRefPtr<RootObject> rootObject)
84 : Instance(rootObject)
86 _object = _NPN_RetainObject(o);
90 CInstance::~CInstance()
92 _NPN_ReleaseObject(_object);
95 RuntimeObject* CInstance::newRuntimeObject(ExecState* exec)
97 return CRuntimeObject::create(exec, exec->lexicalGlobalObject(), this);
100 Class *CInstance::getClass() const
103 _class = CClass::classForIsA(_object->_class);
107 bool CInstance::supportsInvokeDefaultMethod() const
109 return _object->_class->invokeDefault;
112 class CRuntimeMethod : public RuntimeMethod {
114 typedef RuntimeMethod Base;
116 static CRuntimeMethod* create(ExecState* exec, JSGlobalObject* globalObject, const Identifier& name, Bindings::MethodList& list)
118 // FIXME: deprecatedGetDOMStructure uses the prototype off of the wrong global object
119 // We need to pass in the right global object for "i".
120 Structure* domStructure = WebCore::deprecatedGetDOMStructure<CRuntimeMethod>(exec);
121 return new (allocateCell<CRuntimeMethod>(*exec->heap())) CRuntimeMethod(exec, globalObject, domStructure, name, list);
124 static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
126 return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info);
129 static const ClassInfo s_info;
132 CRuntimeMethod(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, const Identifier& name, Bindings::MethodList& list)
133 : RuntimeMethod(globalObject, structure, list)
135 finishCreation(exec->globalData(), name);
138 void finishCreation(JSGlobalData& globalData, const Identifier& name)
140 Base::finishCreation(globalData, name);
141 ASSERT(inherits(&s_info));
146 const ClassInfo CRuntimeMethod::s_info = { "CRuntimeMethod", &RuntimeMethod::s_info, 0, 0 };
148 JSValue CInstance::getMethod(ExecState* exec, const Identifier& propertyName)
150 MethodList methodList = getClass()->methodsNamed(propertyName, this);
151 return CRuntimeMethod::create(exec, exec->lexicalGlobalObject(), propertyName, methodList);
154 JSValue CInstance::invokeMethod(ExecState* exec, RuntimeMethod* runtimeMethod)
156 if (!asObject(runtimeMethod)->inherits(&CRuntimeMethod::s_info))
157 return throwError(exec, createTypeError(exec, "Attempt to invoke non-plug-in method on plug-in object."));
159 const MethodList& methodList = *runtimeMethod->methods();
161 // Overloading methods are not allowed by NPObjects. Should only be one
162 // name match for a particular method.
163 ASSERT(methodList.size() == 1);
165 CMethod* method = static_cast<CMethod*>(methodList[0]);
167 NPIdentifier ident = method->identifier();
168 if (!_object->_class->hasMethod(_object, ident))
169 return jsUndefined();
171 unsigned count = exec->argumentCount();
172 Vector<NPVariant, 8> cArgs(count);
175 for (i = 0; i < count; i++)
176 convertValueToNPVariant(exec, exec->argument(i), &cArgs[i]);
178 // Invoke the 'C' method.
180 NPVariant resultVariant;
181 VOID_TO_NPVARIANT(resultVariant);
184 JSLock::DropAllLocks dropAllLocks(SilenceAssertionsOnly);
185 ASSERT(globalExceptionString().isNull());
186 retval = _object->_class->invoke(_object, ident, cArgs.data(), count, &resultVariant);
187 moveGlobalExceptionToExecState(exec);
191 throwError(exec, createError(exec, "Error calling method on NPObject."));
193 for (i = 0; i < count; i++)
194 _NPN_ReleaseVariantValue(&cArgs[i]);
196 JSValue resultValue = convertNPVariantToValue(exec, &resultVariant, m_rootObject.get());
197 _NPN_ReleaseVariantValue(&resultVariant);
202 JSValue CInstance::invokeDefaultMethod(ExecState* exec)
204 if (!_object->_class->invokeDefault)
205 return jsUndefined();
207 unsigned count = exec->argumentCount();
208 Vector<NPVariant, 8> cArgs(count);
211 for (i = 0; i < count; i++)
212 convertValueToNPVariant(exec, exec->argument(i), &cArgs[i]);
214 // Invoke the 'C' method.
216 NPVariant resultVariant;
217 VOID_TO_NPVARIANT(resultVariant);
219 JSLock::DropAllLocks dropAllLocks(SilenceAssertionsOnly);
220 ASSERT(globalExceptionString().isNull());
221 retval = _object->_class->invokeDefault(_object, cArgs.data(), count, &resultVariant);
222 moveGlobalExceptionToExecState(exec);
226 throwError(exec, createError(exec, "Error calling method on NPObject."));
228 for (i = 0; i < count; i++)
229 _NPN_ReleaseVariantValue(&cArgs[i]);
231 JSValue resultValue = convertNPVariantToValue(exec, &resultVariant, m_rootObject.get());
232 _NPN_ReleaseVariantValue(&resultVariant);
236 bool CInstance::supportsConstruct() const
238 return _object->_class->construct;
241 JSValue CInstance::invokeConstruct(ExecState* exec, const ArgList& args)
243 if (!_object->_class->construct)
244 return jsUndefined();
246 unsigned count = args.size();
247 Vector<NPVariant, 8> cArgs(count);
250 for (i = 0; i < count; i++)
251 convertValueToNPVariant(exec, args.at(i), &cArgs[i]);
253 // Invoke the 'C' method.
255 NPVariant resultVariant;
256 VOID_TO_NPVARIANT(resultVariant);
258 JSLock::DropAllLocks dropAllLocks(SilenceAssertionsOnly);
259 ASSERT(globalExceptionString().isNull());
260 retval = _object->_class->construct(_object, cArgs.data(), count, &resultVariant);
261 moveGlobalExceptionToExecState(exec);
265 throwError(exec, createError(exec, "Error calling method on NPObject."));
267 for (i = 0; i < count; i++)
268 _NPN_ReleaseVariantValue(&cArgs[i]);
270 JSValue resultValue = convertNPVariantToValue(exec, &resultVariant, m_rootObject.get());
271 _NPN_ReleaseVariantValue(&resultVariant);
275 JSValue CInstance::defaultValue(ExecState* exec, PreferredPrimitiveType hint) const
277 if (hint == PreferString)
278 return stringValue(exec);
279 if (hint == PreferNumber)
280 return numberValue(exec);
281 return valueOf(exec);
284 JSValue CInstance::stringValue(ExecState* exec) const
287 snprintf(buf, sizeof(buf), "NPObject %p, NPClass %p", _object, _object->_class);
288 return jsString(exec, buf);
291 JSValue CInstance::numberValue(ExecState*) const
293 // FIXME: Implement something sensible.
297 JSValue CInstance::booleanValue() const
299 // FIXME: Implement something sensible.
300 return jsBoolean(false);
303 JSValue CInstance::valueOf(ExecState* exec) const
305 return stringValue(exec);
308 void CInstance::getPropertyNames(ExecState* exec, PropertyNameArray& nameArray)
310 if (!NP_CLASS_STRUCT_VERSION_HAS_ENUM(_object->_class) || !_object->_class->enumerate)
314 NPIdentifier* identifiers;
317 JSLock::DropAllLocks dropAllLocks(SilenceAssertionsOnly);
318 ASSERT(globalExceptionString().isNull());
319 bool ok = _object->_class->enumerate(_object, &identifiers, &count);
320 moveGlobalExceptionToExecState(exec);
325 for (uint32_t i = 0; i < count; i++) {
326 IdentifierRep* identifier = static_cast<IdentifierRep*>(identifiers[i]);
328 if (identifier->isString())
329 nameArray.add(identifierFromNPIdentifier(exec, identifier->string()));
331 nameArray.add(Identifier::from(exec, identifier->number()));
334 // FIXME: This should really call NPN_MemFree but that's in WebKit
341 #endif // ENABLE(NETSCAPE_PLUGIN_API)