2 * Copyright (C) 2004 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.
25 #include <NP_jsobject.h>
27 #include <JavaScriptCore/npruntime.h>
28 #include <JavaScriptCore/c_utility.h>
29 #include <JavaScriptCore/npruntime_impl.h>
30 #include <JavaScriptCore/npruntime_priv.h>
33 using namespace KJS::Bindings;
36 static KJS::List listFromVariantArgs(KJS::ExecState *exec, const NPVariant *args, unsigned argCount)
40 const NPVariant *v = args;
42 for (i = 0; i < argCount; i++) {
43 aList.append (convertNPVariantToValue (exec, v));
50 static NPObject *jsAllocate(NPP npp, NPClass *aClass)
52 return (NPObject *)malloc(sizeof(JavaScriptObject));
55 static void jsDeallocate (JavaScriptObject *obj)
60 static NPClass _javascriptClass = {
63 (NPDeallocateFunctionPtr)jsDeallocate,
74 NPClass *NPScriptObjectClass = &_javascriptClass;
76 Identifier identiferFromNPIdentifier(const NPUTF8 *name)
79 unsigned int UTF16Length;
81 convertUTF8ToUTF16 (name, -1, &methodName, &UTF16Length); // requires free() of returned memory.
82 Identifier identifier ((const KJS::UChar*)methodName, UTF16Length);
83 free ((void *)methodName);
88 NPObject *_NPN_CreateScriptObject (NPP npp, KJS::ObjectImp *imp, KJS::Bindings::RootObject *root)
90 JavaScriptObject *obj = (JavaScriptObject *)_NPN_CreateObject(npp, NPScriptObjectClass);
95 addNativeReference (root, imp);
97 return (NPObject *)obj;
100 bool _NPN_InvokeDefault (NPP npp, NPObject *o, const NPVariant *args, uint32_t argCount, NPVariant *result)
102 if (o->_class == NPScriptObjectClass) {
103 // No notion of a default function on JS objects. Just return false, can't handle.
107 if (o->_class->invokeDefault) {
108 return o->_class->invokeDefault (o, args, argCount, result);
115 bool _NPN_Invoke (NPP npp, NPObject *o, NPIdentifier methodName, const NPVariant *args, uint32_t argCount, NPVariant *result)
117 if (o->_class == NPScriptObjectClass) {
118 JavaScriptObject *obj = (JavaScriptObject *)o;
120 PrivateIdentifier *i = (PrivateIdentifier *)methodName;
124 // Lookup the function object.
125 ExecState *exec = obj->root->interpreter()->globalExec();
127 Value func = obj->imp->get (exec, identiferFromNPIdentifier(i->value.string));
128 Interpreter::unlock();
131 NPN_InitializeVariantAsNull(result);
134 else if ( func.type() == UndefinedType) {
135 NPN_InitializeVariantAsUndefined(result);
139 // Call the function object.
140 ObjectImp *funcImp = static_cast<ObjectImp*>(func.imp());
141 Object thisObj = Object(const_cast<ObjectImp*>(obj->imp));
142 List argList = listFromVariantArgs(exec, args, argCount);
144 Value resultV = funcImp->call (exec, thisObj, argList);
145 Interpreter::unlock();
147 // Convert and return the result of the function call.
148 convertValueToNPVariant(exec, resultV, result);
153 if (o->_class->invoke) {
154 return o->_class->invoke (o, methodName, args, argCount, result);
161 bool _NPN_Evaluate (NPP npp, NPObject *o, NPString *s, NPVariant *variant)
163 if (o->_class == NPScriptObjectClass) {
164 JavaScriptObject *obj = (JavaScriptObject *)o;
166 ExecState *exec = obj->root->interpreter()->globalExec();
167 Object thisObj = Object(const_cast<ObjectImp*>(obj->imp));
171 NPUTF16 *scriptString;
172 unsigned int UTF16Length;
173 convertNPStringToUTF16 (s, &scriptString, &UTF16Length); // requires free() of returned memory.
174 Completion completion = obj->root->interpreter()->evaluate(UString(), 0, UString((const UChar *)scriptString,UTF16Length));
175 ComplType type = completion.complType();
177 if (type == Normal) {
178 result = completion.value();
179 if (result.isNull()) {
180 result = Undefined();
184 result = Undefined();
186 Interpreter::unlock();
188 free ((void *)scriptString);
190 convertValueToNPVariant(exec, result, variant);
197 bool _NPN_GetProperty (NPP npp, NPObject *o, NPIdentifier propertyName, NPVariant *variant)
199 if (o->_class == NPScriptObjectClass) {
200 JavaScriptObject *obj = (JavaScriptObject *)o;
201 ExecState *exec = obj->root->interpreter()->globalExec();
203 PrivateIdentifier *i = (PrivateIdentifier *)propertyName;
205 if (!obj->imp->hasProperty (exec, identiferFromNPIdentifier(i->value.string))) {
206 NPN_InitializeVariantAsNull(variant);
211 if (!obj->imp->hasProperty (exec, i->value.number)) {
212 NPN_InitializeVariantAsNull(variant);
220 result = obj->imp->get (exec, identiferFromNPIdentifier(i->value.string));
223 result = obj->imp->get (exec, i->value.number);
225 Interpreter::unlock();
227 if (result.isNull()) {
228 NPN_InitializeVariantAsNull(variant);
231 else if (result.type() == UndefinedType) {
232 NPN_InitializeVariantAsUndefined(variant);
236 convertValueToNPVariant(exec, result, variant);
241 else if (o->_class->hasProperty && o->_class->getProperty) {
242 if (o->_class->hasProperty (o, propertyName)) {
243 return o->_class->getProperty (o, propertyName, variant);
252 bool _NPN_SetProperty (NPP npp, NPObject *o, NPIdentifier propertyName, const NPVariant *variant)
254 if (o->_class == NPScriptObjectClass) {
255 JavaScriptObject *obj = (JavaScriptObject *)o;
257 ExecState *exec = obj->root->interpreter()->globalExec();
260 PrivateIdentifier *i = (PrivateIdentifier *)propertyName;
262 obj->imp->put (exec, identiferFromNPIdentifier(i->value.string), convertNPVariantToValue(exec, variant));
265 obj->imp->put (exec, i->value.number, convertNPVariantToValue(exec, variant));
267 Interpreter::unlock();
271 else if (o->_class->setProperty) {
272 return o->_class->setProperty (o, propertyName, variant);
277 bool _NPN_RemoveProperty (NPP npp, NPObject *o, NPIdentifier propertyName)
279 if (o->_class == NPScriptObjectClass) {
280 JavaScriptObject *obj = (JavaScriptObject *)o;
281 ExecState *exec = obj->root->interpreter()->globalExec();
283 PrivateIdentifier *i = (PrivateIdentifier *)propertyName;
285 if (!obj->imp->hasProperty (exec, identiferFromNPIdentifier(i->value.string))) {
290 if (!obj->imp->hasProperty (exec, i->value.number)) {
297 obj->imp->deleteProperty (exec, identiferFromNPIdentifier(i->value.string));
300 obj->imp->deleteProperty (exec, i->value.number);
302 Interpreter::unlock();
309 bool _NPN_HasProperty(NPP npp, NPObject *o, NPIdentifier propertyName)
311 if (o->_class == NPScriptObjectClass) {
312 JavaScriptObject *obj = (JavaScriptObject *)o;
313 ExecState *exec = obj->root->interpreter()->globalExec();
315 PrivateIdentifier *i = (PrivateIdentifier *)propertyName;
316 // String identifier?
318 ExecState *exec = obj->root->interpreter()->globalExec();
320 bool result = obj->imp->hasProperty (exec, identiferFromNPIdentifier(i->value.string));
321 Interpreter::unlock();
327 bool result = obj->imp->hasProperty (exec, i->value.number);
328 Interpreter::unlock();
331 else if (o->_class->hasProperty) {
332 return o->_class->hasProperty (o, propertyName);
338 bool _NPN_HasMethod(NPP npp, NPObject *o, NPIdentifier methodName)
340 if (o->_class == NPScriptObjectClass) {
341 JavaScriptObject *obj = (JavaScriptObject *)o;
343 PrivateIdentifier *i = (PrivateIdentifier *)methodName;
347 // Lookup the function object.
348 ExecState *exec = obj->root->interpreter()->globalExec();
350 Value func = obj->imp->get (exec, identiferFromNPIdentifier(i->value.string));
351 Interpreter::unlock();
353 if (func.isNull() || func.type() == UndefinedType) {
360 else if (o->_class->hasMethod) {
361 return o->_class->hasMethod (o, methodName);
367 void _NPN_SetException (NPObject *o, NPString *message)
369 if (o->_class == NPScriptObjectClass) {
370 JavaScriptObject *obj = (JavaScriptObject *)o;
371 ExecState *exec = obj->root->interpreter()->globalExec();
373 char *msg = (char *)malloc (message->UTF8Length + 1);
374 strncpy (msg, message->UTF8Characters, message->UTF8Length);
375 msg[message->UTF8Length] = 0;
376 Object err = Error::create(exec, GeneralError, msg);
378 exec->setException (err);
379 Interpreter::unlock();