]> git.saurik.com Git - apple/javascriptcore.git/blame - bindings/NP_jsobject.cpp
JavaScriptCore-466.1.6.tar.gz
[apple/javascriptcore.git] / bindings / NP_jsobject.cpp
CommitLineData
b37bf2e1
A
1/*
2 * Copyright (C) 2004, 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_API)
29
30#include "NP_jsobject.h"
31
32#include "JSGlobalObject.h"
33#include "PropertyNameArray.h"
b5422865 34#include "SourceCode.h"
b37bf2e1
A
35#include "c_utility.h"
36#include "interpreter.h"
37#include "npruntime_impl.h"
38#include "npruntime_priv.h"
39#include "object.h"
40#include "runtime_root.h"
41
42using namespace KJS;
43using namespace KJS::Bindings;
44
45static void getListFromVariantArgs(ExecState* exec, const NPVariant* args, unsigned argCount, RootObject* rootObject, List& aList)
46{
47 for (unsigned i = 0; i < argCount; i++)
48 aList.append(convertNPVariantToValue(exec, &args[i], rootObject));
49}
50
51static NPObject* jsAllocate(NPP, NPClass*)
52{
53 return (NPObject*)malloc(sizeof(JavaScriptObject));
54}
55
56static void jsDeallocate(NPObject* npObj)
57{
58 JavaScriptObject* obj = (JavaScriptObject*)npObj;
59
60 if (obj->rootObject && obj->rootObject->isValid())
61 obj->rootObject->gcUnprotect(obj->imp);
62
63 if (obj->rootObject)
64 obj->rootObject->deref();
65
66 free(obj);
67}
68
69static NPClass javascriptClass = { 1, jsAllocate, jsDeallocate, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
70static NPClass noScriptClass = { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
71
72NPClass* NPScriptObjectClass = &javascriptClass;
73static NPClass* NPNoScriptObjectClass = &noScriptClass;
74
75NPObject* _NPN_CreateScriptObject(NPP npp, JSObject* imp, PassRefPtr<RootObject> rootObject)
76{
77 JavaScriptObject* obj = (JavaScriptObject*)_NPN_CreateObject(npp, NPScriptObjectClass);
78
79 obj->rootObject = rootObject.releaseRef();
80
81 if (obj->rootObject)
82 obj->rootObject->gcProtect(imp);
83 obj->imp = imp;
84
85 return (NPObject*)obj;
86}
87
88NPObject *_NPN_CreateNoScriptObject(void)
89{
90 return _NPN_CreateObject(0, NPNoScriptObjectClass);
91}
92
93bool _NPN_InvokeDefault(NPP, NPObject* o, const NPVariant* args, uint32_t argCount, NPVariant* result)
94{
95 if (o->_class == NPScriptObjectClass) {
96 JavaScriptObject* obj = (JavaScriptObject*)o;
97
98 VOID_TO_NPVARIANT(*result);
99
100 // Lookup the function object.
101 RootObject* rootObject = obj->rootObject;
102 if (!rootObject || !rootObject->isValid())
103 return false;
104
105 ExecState* exec = rootObject->globalObject()->globalExec();
106 JSLock lock;
107
108 // Call the function object.
109 JSObject *funcImp = static_cast<JSObject*>(obj->imp);
110 if (!funcImp->implementsCall())
111 return false;
112
113 List argList;
114 getListFromVariantArgs(exec, args, argCount, rootObject, argList);
115 rootObject->globalObject()->startTimeoutCheck();
116 JSValue *resultV = funcImp->call (exec, funcImp, argList);
117 rootObject->globalObject()->stopTimeoutCheck();
118
119 // Convert and return the result of the function call.
120 convertValueToNPVariant(exec, resultV, result);
121 return true;
122 }
123
124 if (o->_class->invokeDefault)
125 return o->_class->invokeDefault(o, args, argCount, result);
126 VOID_TO_NPVARIANT(*result);
127 return true;
128}
129
130bool _NPN_Invoke(NPP npp, NPObject* o, NPIdentifier methodName, const NPVariant* args, uint32_t argCount, NPVariant* result)
131{
132 if (o->_class == NPScriptObjectClass) {
133 JavaScriptObject* obj = (JavaScriptObject*)o;
134
135 PrivateIdentifier* i = (PrivateIdentifier*)methodName;
136 if (!i->isString)
137 return false;
138
139 // Special case the "eval" method.
140 if (methodName == _NPN_GetStringIdentifier("eval")) {
141 if (argCount != 1)
142 return false;
143 if (args[0].type != NPVariantType_String)
144 return false;
145 return _NPN_Evaluate(npp, o, (NPString *)&args[0].value.stringValue, result);
146 }
147
148 // Lookup the function object.
149 RootObject* rootObject = obj->rootObject;
150 if (!rootObject || !rootObject->isValid())
151 return false;
152
153 ExecState* exec = rootObject->globalObject()->globalExec();
154 JSLock lock;
155 JSValue* func = obj->imp->get(exec, identifierFromNPIdentifier(i->value.string));
156 if (func->isNull()) {
157 NULL_TO_NPVARIANT(*result);
158 return false;
159 }
160 if (func->isUndefined()) {
161 VOID_TO_NPVARIANT(*result);
162 return false;
163 }
164 // Call the function object.
165 JSObject *funcImp = static_cast<JSObject*>(func);
166 JSObject *thisObj = const_cast<JSObject*>(obj->imp);
167 List argList;
168 getListFromVariantArgs(exec, args, argCount, rootObject, argList);
169 rootObject->globalObject()->startTimeoutCheck();
170 JSValue *resultV = funcImp->call (exec, thisObj, argList);
171 rootObject->globalObject()->stopTimeoutCheck();
172
173 // Convert and return the result of the function call.
174 convertValueToNPVariant(exec, resultV, result);
175 return true;
176 }
177
178 if (o->_class->invoke)
179 return o->_class->invoke(o, methodName, args, argCount, result);
180
181 VOID_TO_NPVARIANT(*result);
182 return true;
183}
184
185bool _NPN_Evaluate(NPP, NPObject* o, NPString* s, NPVariant* variant)
186{
187 if (o->_class == NPScriptObjectClass) {
188 JavaScriptObject* obj = (JavaScriptObject*)o;
189
190 RootObject* rootObject = obj->rootObject;
191 if (!rootObject || !rootObject->isValid())
192 return false;
193
194 ExecState* exec = rootObject->globalObject()->globalExec();
195
196 JSLock lock;
197 NPUTF16* scriptString;
198 unsigned int UTF16Length;
199 convertNPStringToUTF16(s, &scriptString, &UTF16Length); // requires free() of returned memory
200 rootObject->globalObject()->startTimeoutCheck();
b5422865
A
201
202 SourceCode source = makeSource(UString(reinterpret_cast<const UChar*>(scriptString), UTF16Length), UString());
203 Completion completion = Interpreter::evaluate(rootObject->globalObject()->globalExec(), source);
b37bf2e1
A
204 rootObject->globalObject()->stopTimeoutCheck();
205 ComplType type = completion.complType();
206
207 JSValue* result;
208 if (type == Normal) {
209 result = completion.value();
210 if (!result)
211 result = jsUndefined();
212 } else
213 result = jsUndefined();
214
215 free(scriptString);
216
217 convertValueToNPVariant(exec, result, variant);
218
219 return true;
220 }
221
222 VOID_TO_NPVARIANT(*variant);
223 return false;
224}
225
226bool _NPN_GetProperty(NPP, NPObject* o, NPIdentifier propertyName, NPVariant* variant)
227{
228 if (o->_class == NPScriptObjectClass) {
229 JavaScriptObject* obj = (JavaScriptObject*)o;
230
231 RootObject* rootObject = obj->rootObject;
232 if (!rootObject || !rootObject->isValid())
233 return false;
234
235 ExecState* exec = rootObject->globalObject()->globalExec();
236 PrivateIdentifier* i = (PrivateIdentifier*)propertyName;
237
238 JSLock lock;
239 JSValue *result;
240 if (i->isString)
241 result = obj->imp->get(exec, identifierFromNPIdentifier(i->value.string));
242 else
243 result = obj->imp->get(exec, i->value.number);
244
245 convertValueToNPVariant(exec, result, variant);
246 return true;
247 }
248
249 if (o->_class->hasProperty && o->_class->getProperty) {
250 if (o->_class->hasProperty(o, propertyName))
251 return o->_class->getProperty(o, propertyName, variant);
252 return false;
253 }
254
255 VOID_TO_NPVARIANT(*variant);
256 return false;
257}
258
259bool _NPN_SetProperty(NPP, NPObject* o, NPIdentifier propertyName, const NPVariant* variant)
260{
261 if (o->_class == NPScriptObjectClass) {
262 JavaScriptObject* obj = (JavaScriptObject*)o;
263
264 RootObject* rootObject = obj->rootObject;
265 if (!rootObject || !rootObject->isValid())
266 return false;
267
268 ExecState* exec = rootObject->globalObject()->globalExec();
269 JSLock lock;
270 PrivateIdentifier* i = (PrivateIdentifier*)propertyName;
271 if (i->isString)
272 obj->imp->put(exec, identifierFromNPIdentifier(i->value.string), convertNPVariantToValue(exec, variant, rootObject));
273 else
274 obj->imp->put(exec, i->value.number, convertNPVariantToValue(exec, variant, rootObject));
275 return true;
276 }
277
278 if (o->_class->setProperty)
279 return o->_class->setProperty(o, propertyName, variant);
280
281 return false;
282}
283
284bool _NPN_RemoveProperty(NPP, NPObject* o, NPIdentifier propertyName)
285{
286 if (o->_class == NPScriptObjectClass) {
287 JavaScriptObject* obj = (JavaScriptObject*)o;
288
289 RootObject* rootObject = obj->rootObject;
290 if (!rootObject || !rootObject->isValid())
291 return false;
292
293 ExecState* exec = rootObject->globalObject()->globalExec();
294 PrivateIdentifier* i = (PrivateIdentifier*)propertyName;
295 if (i->isString) {
296 if (!obj->imp->hasProperty(exec, identifierFromNPIdentifier(i->value.string)))
297 return false;
298 } else {
299 if (!obj->imp->hasProperty(exec, i->value.number))
300 return false;
301 }
302
303 JSLock lock;
304 if (i->isString)
305 obj->imp->deleteProperty(exec, identifierFromNPIdentifier(i->value.string));
306 else
307 obj->imp->deleteProperty(exec, i->value.number);
308
309 return true;
310 }
311 return false;
312}
313
314bool _NPN_HasProperty(NPP, NPObject* o, NPIdentifier propertyName)
315{
316 if (o->_class == NPScriptObjectClass) {
317 JavaScriptObject* obj = (JavaScriptObject*)o;
318
319 RootObject* rootObject = obj->rootObject;
320 if (!rootObject || !rootObject->isValid())
321 return false;
322
323 ExecState* exec = rootObject->globalObject()->globalExec();
324 PrivateIdentifier* i = (PrivateIdentifier*)propertyName;
325 JSLock lock;
326 if (i->isString)
327 return obj->imp->hasProperty(exec, identifierFromNPIdentifier(i->value.string));
328 return obj->imp->hasProperty(exec, i->value.number);
329 }
330
331 if (o->_class->hasProperty)
332 return o->_class->hasProperty(o, propertyName);
333
334 return false;
335}
336
337bool _NPN_HasMethod(NPP, NPObject* o, NPIdentifier methodName)
338{
339 if (o->_class == NPScriptObjectClass) {
340 JavaScriptObject* obj = (JavaScriptObject*)o;
341
342 PrivateIdentifier* i = (PrivateIdentifier*)methodName;
343 if (!i->isString)
344 return false;
345
346 RootObject* rootObject = obj->rootObject;
347 if (!rootObject || !rootObject->isValid())
348 return false;
349
350 ExecState* exec = rootObject->globalObject()->globalExec();
351 JSLock lock;
352 JSValue* func = obj->imp->get(exec, identifierFromNPIdentifier(i->value.string));
353 return !func->isUndefined();
354 }
355
356 if (o->_class->hasMethod)
357 return o->_class->hasMethod(o, methodName);
358
359 return false;
360}
361
362void _NPN_SetException(NPObject* o, const NPUTF8* message)
363{
364 if (o->_class == NPScriptObjectClass) {
365 JavaScriptObject* obj = (JavaScriptObject*)o;
366 RootObject* rootObject = obj->rootObject;
367 if (!rootObject || !rootObject->isValid())
368 return;
369
370 ExecState* exec = rootObject->globalObject()->globalExec();
371 JSLock lock;
372 throwError(exec, GeneralError, message);
373 }
374}
375
376bool _NPN_Enumerate(NPP, NPObject *o, NPIdentifier **identifier, uint32_t *count)
377{
378 if (o->_class == NPScriptObjectClass) {
379 JavaScriptObject* obj = (JavaScriptObject*)o;
380
381 RootObject* rootObject = obj->rootObject;
382 if (!rootObject || !rootObject->isValid())
383 return false;
384
385 ExecState* exec = rootObject->globalObject()->globalExec();
386 JSLock lock;
387 PropertyNameArray propertyNames;
388
389 obj->imp->getPropertyNames(exec, propertyNames);
390 unsigned size = static_cast<unsigned>(propertyNames.size());
391 // FIXME: This should really call NPN_MemAlloc but that's in WebKit
392 NPIdentifier *identifiers = static_cast<NPIdentifier*>(malloc(sizeof(NPIdentifier) * size));
393
394 for (unsigned i = 0; i < size; i++)
395 identifiers[i] = _NPN_GetStringIdentifier(propertyNames[i].ustring().UTF8String().c_str());
396
397 *identifier = identifiers;
398 *count = size;
399
400 return true;
401 }
402
403 if (NP_CLASS_STRUCT_VERSION_HAS_ENUM(o->_class) && o->_class->enumerate)
404 return o->_class->enumerate(o, identifier, count);
405
406 return false;
407}
408
409#endif // ENABLE(NETSCAPE_API)