Add support for private names
[WebKit-https.git] / Source / WebCore / bridge / c / c_instance.cpp
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 "CRuntimeObject.h"
33 #include "IdentifierRep.h"
34 #include "JSDOMBinding.h"
35 #include "c_class.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>
51
52 using namespace WebCore;
53
54 namespace JSC {
55 namespace Bindings {
56
57 using JSC::UString;
58
59 static JSC::UString& globalExceptionString()
60 {
61     DEFINE_STATIC_LOCAL(JSC::UString, exceptionStr, ());
62     return exceptionStr;
63 }
64
65 void CInstance::setGlobalException(UString exception)
66 {
67     globalExceptionString() = exception;
68 }
69
70 void CInstance::moveGlobalExceptionToExecState(ExecState* exec)
71 {
72     if (globalExceptionString().isNull())
73         return;
74
75     {
76         JSLock lock(SilenceAssertionsOnly);
77         throwError(exec, createError(exec, globalExceptionString()));
78     }
79
80     globalExceptionString() = UString();
81 }
82
83 CInstance::CInstance(NPObject* o, PassRefPtr<RootObject> rootObject)
84     : Instance(rootObject)
85 {
86     _object = _NPN_RetainObject(o);
87     _class = 0;
88 }
89
90 CInstance::~CInstance() 
91 {
92     _NPN_ReleaseObject(_object);
93 }
94
95 RuntimeObject* CInstance::newRuntimeObject(ExecState* exec)
96 {
97     return CRuntimeObject::create(exec, exec->lexicalGlobalObject(), this);
98 }
99
100 Class *CInstance::getClass() const
101 {
102     if (!_class)
103         _class = CClass::classForIsA(_object->_class);
104     return _class;
105 }
106
107 bool CInstance::supportsInvokeDefaultMethod() const
108 {
109     return _object->_class->invokeDefault;
110 }
111
112 class CRuntimeMethod : public RuntimeMethod {
113 public:
114     typedef RuntimeMethod Base;
115
116     static CRuntimeMethod* create(ExecState* exec, JSGlobalObject* globalObject, const UString& name, Bindings::MethodList& list)
117     {
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         CRuntimeMethod* method = new (NotNull, allocateCell<CRuntimeMethod>(*exec->heap())) CRuntimeMethod(globalObject, domStructure, list);
122         method->finishCreation(exec->globalData(), name);
123         return method;
124     }
125
126     static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
127     {
128         return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info);
129     }
130
131     static const ClassInfo s_info;
132
133 private:
134     CRuntimeMethod(JSGlobalObject* globalObject, Structure* structure, Bindings::MethodList& list)
135         : RuntimeMethod(globalObject, structure, list)
136     {
137     }
138
139     void finishCreation(JSGlobalData& globalData, const UString& name)
140     {
141         Base::finishCreation(globalData, name);
142         ASSERT(inherits(&s_info));
143     }
144
145 };
146
147 const ClassInfo CRuntimeMethod::s_info = { "CRuntimeMethod", &RuntimeMethod::s_info, 0, 0, CREATE_METHOD_TABLE(CRuntimeMethod) };
148
149 JSValue CInstance::getMethod(ExecState* exec, PropertyName propertyName)
150 {
151     MethodList methodList = getClass()->methodsNamed(propertyName, this);
152     return CRuntimeMethod::create(exec, exec->lexicalGlobalObject(), propertyName.publicName(), methodList);
153 }
154
155 JSValue CInstance::invokeMethod(ExecState* exec, RuntimeMethod* runtimeMethod)
156 {
157     if (!asObject(runtimeMethod)->inherits(&CRuntimeMethod::s_info))
158         return throwError(exec, createTypeError(exec, "Attempt to invoke non-plug-in method on plug-in object."));
159
160     const MethodList& methodList = *runtimeMethod->methods();
161
162     // Overloading methods are not allowed by NPObjects.  Should only be one
163     // name match for a particular method.
164     ASSERT(methodList.size() == 1);
165
166     CMethod* method = static_cast<CMethod*>(methodList[0]);
167
168     NPIdentifier ident = method->identifier();
169     if (!_object->_class->hasMethod(_object, ident))
170         return jsUndefined();
171
172     unsigned count = exec->argumentCount();
173     Vector<NPVariant, 8> cArgs(count);
174
175     unsigned i;
176     for (i = 0; i < count; i++)
177         convertValueToNPVariant(exec, exec->argument(i), &cArgs[i]);
178
179     // Invoke the 'C' method.
180     bool retval = true;
181     NPVariant resultVariant;
182     VOID_TO_NPVARIANT(resultVariant);
183
184     {
185         JSLock::DropAllLocks dropAllLocks(SilenceAssertionsOnly);
186         ASSERT(globalExceptionString().isNull());
187         retval = _object->_class->invoke(_object, ident, cArgs.data(), count, &resultVariant);
188         moveGlobalExceptionToExecState(exec);
189     }
190     
191     if (!retval)
192         throwError(exec, createError(exec, "Error calling method on NPObject."));
193
194     for (i = 0; i < count; i++)
195         _NPN_ReleaseVariantValue(&cArgs[i]);
196
197     JSValue resultValue = convertNPVariantToValue(exec, &resultVariant, m_rootObject.get());
198     _NPN_ReleaseVariantValue(&resultVariant);
199     return resultValue;
200 }
201
202
203 JSValue CInstance::invokeDefaultMethod(ExecState* exec)
204 {
205     if (!_object->_class->invokeDefault)
206         return jsUndefined();
207
208     unsigned count = exec->argumentCount();
209     Vector<NPVariant, 8> cArgs(count);
210
211     unsigned i;
212     for (i = 0; i < count; i++)
213         convertValueToNPVariant(exec, exec->argument(i), &cArgs[i]);
214
215     // Invoke the 'C' method.
216     bool retval = true;
217     NPVariant resultVariant;
218     VOID_TO_NPVARIANT(resultVariant);
219     {
220         JSLock::DropAllLocks dropAllLocks(SilenceAssertionsOnly);
221         ASSERT(globalExceptionString().isNull());
222         retval = _object->_class->invokeDefault(_object, cArgs.data(), count, &resultVariant);
223         moveGlobalExceptionToExecState(exec);
224     }
225     
226     if (!retval)
227         throwError(exec, createError(exec, "Error calling method on NPObject."));
228
229     for (i = 0; i < count; i++)
230         _NPN_ReleaseVariantValue(&cArgs[i]);
231
232     JSValue resultValue = convertNPVariantToValue(exec, &resultVariant, m_rootObject.get());
233     _NPN_ReleaseVariantValue(&resultVariant);
234     return resultValue;
235 }
236
237 bool CInstance::supportsConstruct() const
238 {
239     return _object->_class->construct;
240 }
241     
242 JSValue CInstance::invokeConstruct(ExecState* exec, const ArgList& args)
243 {
244     if (!_object->_class->construct)
245         return jsUndefined();
246
247     unsigned count = args.size();
248     Vector<NPVariant, 8> cArgs(count);
249
250     unsigned i;
251     for (i = 0; i < count; i++)
252         convertValueToNPVariant(exec, args.at(i), &cArgs[i]);
253
254     // Invoke the 'C' method.
255     bool retval = true;
256     NPVariant resultVariant;
257     VOID_TO_NPVARIANT(resultVariant);
258     {
259         JSLock::DropAllLocks dropAllLocks(SilenceAssertionsOnly);
260         ASSERT(globalExceptionString().isNull());
261         retval = _object->_class->construct(_object, cArgs.data(), count, &resultVariant);
262         moveGlobalExceptionToExecState(exec);
263     }
264     
265     if (!retval)
266         throwError(exec, createError(exec, "Error calling method on NPObject."));
267
268     for (i = 0; i < count; i++)
269         _NPN_ReleaseVariantValue(&cArgs[i]);
270
271     JSValue resultValue = convertNPVariantToValue(exec, &resultVariant, m_rootObject.get());
272     _NPN_ReleaseVariantValue(&resultVariant);
273     return resultValue;
274 }
275
276 JSValue CInstance::defaultValue(ExecState* exec, PreferredPrimitiveType hint) const
277 {
278     if (hint == PreferString)
279         return stringValue(exec);
280     if (hint == PreferNumber)
281         return numberValue(exec);
282     return valueOf(exec);
283 }
284
285 JSValue CInstance::stringValue(ExecState* exec) const
286 {
287     char buf[1024];
288     snprintf(buf, sizeof(buf), "NPObject %p, NPClass %p", _object, _object->_class);
289     return jsString(exec, buf);
290 }
291
292 JSValue CInstance::numberValue(ExecState*) const
293 {
294     // FIXME: Implement something sensible.
295     return jsNumber(0);
296 }
297
298 JSValue CInstance::booleanValue() const
299 {
300     // FIXME: Implement something sensible.
301     return jsBoolean(false);
302 }
303
304 JSValue CInstance::valueOf(ExecState* exec) const 
305 {
306     return stringValue(exec);
307 }
308
309 void CInstance::getPropertyNames(ExecState* exec, PropertyNameArray& nameArray)
310 {
311     if (!NP_CLASS_STRUCT_VERSION_HAS_ENUM(_object->_class) || !_object->_class->enumerate)
312         return;
313
314     uint32_t count;
315     NPIdentifier* identifiers;
316
317     {
318         JSLock::DropAllLocks dropAllLocks(SilenceAssertionsOnly);
319         ASSERT(globalExceptionString().isNull());
320         bool ok = _object->_class->enumerate(_object, &identifiers, &count);
321         moveGlobalExceptionToExecState(exec);
322         if (!ok)
323             return;
324     }
325
326     for (uint32_t i = 0; i < count; i++) {
327         IdentifierRep* identifier = static_cast<IdentifierRep*>(identifiers[i]);
328
329         if (identifier->isString())
330             nameArray.add(identifierFromNPIdentifier(exec, identifier->string()));
331         else
332             nameArray.add(Identifier::from(exec, identifier->number()));
333     }
334
335     // FIXME: This should really call NPN_MemFree but that's in WebKit
336     free(identifiers);
337 }
338
339 }
340 }
341
342 #endif // ENABLE(NETSCAPE_PLUGIN_API)