2 * Copyright (C) 2004, 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_API)
30 #include "NP_jsobject.h"
32 #include "JSGlobalObject.h"
33 #include "PropertyNameArray.h"
34 #include "c_utility.h"
35 #include "interpreter.h"
36 #include "npruntime_impl.h"
37 #include "npruntime_priv.h"
39 #include "runtime_root.h"
42 using namespace KJS::Bindings
;
44 static void getListFromVariantArgs(ExecState
* exec
, const NPVariant
* args
, unsigned argCount
, RootObject
* rootObject
, List
& aList
)
46 for (unsigned i
= 0; i
< argCount
; i
++)
47 aList
.append(convertNPVariantToValue(exec
, &args
[i
], rootObject
));
50 static NPObject
* jsAllocate(NPP
, NPClass
*)
52 return (NPObject
*)malloc(sizeof(JavaScriptObject
));
55 static void jsDeallocate(NPObject
* npObj
)
57 JavaScriptObject
* obj
= (JavaScriptObject
*)npObj
;
59 if (obj
->rootObject
&& obj
->rootObject
->isValid())
60 obj
->rootObject
->gcUnprotect(obj
->imp
);
63 obj
->rootObject
->deref();
68 static NPClass javascriptClass
= { 1, jsAllocate
, jsDeallocate
, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
69 static NPClass noScriptClass
= { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
71 NPClass
* NPScriptObjectClass
= &javascriptClass
;
72 static NPClass
* NPNoScriptObjectClass
= &noScriptClass
;
74 NPObject
* _NPN_CreateScriptObject(NPP npp
, JSObject
* imp
, PassRefPtr
<RootObject
> rootObject
)
76 JavaScriptObject
* obj
= (JavaScriptObject
*)_NPN_CreateObject(npp
, NPScriptObjectClass
);
78 obj
->rootObject
= rootObject
.releaseRef();
81 obj
->rootObject
->gcProtect(imp
);
84 return (NPObject
*)obj
;
87 NPObject
*_NPN_CreateNoScriptObject(void)
89 return _NPN_CreateObject(0, NPNoScriptObjectClass
);
92 bool _NPN_InvokeDefault(NPP
, NPObject
* o
, const NPVariant
* args
, uint32_t argCount
, NPVariant
* result
)
94 if (o
->_class
== NPScriptObjectClass
) {
95 JavaScriptObject
* obj
= (JavaScriptObject
*)o
;
97 VOID_TO_NPVARIANT(*result
);
99 // Lookup the function object.
100 RootObject
* rootObject
= obj
->rootObject
;
101 if (!rootObject
|| !rootObject
->isValid())
104 ExecState
* exec
= rootObject
->globalObject()->globalExec();
107 // Call the function object.
108 JSObject
*funcImp
= static_cast<JSObject
*>(obj
->imp
);
109 if (!funcImp
->implementsCall())
113 getListFromVariantArgs(exec
, args
, argCount
, rootObject
, argList
);
114 rootObject
->globalObject()->startTimeoutCheck();
115 JSValue
*resultV
= funcImp
->call (exec
, funcImp
, argList
);
116 rootObject
->globalObject()->stopTimeoutCheck();
118 // Convert and return the result of the function call.
119 convertValueToNPVariant(exec
, resultV
, result
);
123 if (o
->_class
->invokeDefault
)
124 return o
->_class
->invokeDefault(o
, args
, argCount
, result
);
125 VOID_TO_NPVARIANT(*result
);
129 bool _NPN_Invoke(NPP npp
, NPObject
* o
, NPIdentifier methodName
, const NPVariant
* args
, uint32_t argCount
, NPVariant
* result
)
131 if (o
->_class
== NPScriptObjectClass
) {
132 JavaScriptObject
* obj
= (JavaScriptObject
*)o
;
134 PrivateIdentifier
* i
= (PrivateIdentifier
*)methodName
;
138 // Special case the "eval" method.
139 if (methodName
== _NPN_GetStringIdentifier("eval")) {
142 if (args
[0].type
!= NPVariantType_String
)
144 return _NPN_Evaluate(npp
, o
, (NPString
*)&args
[0].value
.stringValue
, result
);
147 // Lookup the function object.
148 RootObject
* rootObject
= obj
->rootObject
;
149 if (!rootObject
|| !rootObject
->isValid())
152 ExecState
* exec
= rootObject
->globalObject()->globalExec();
154 JSValue
* func
= obj
->imp
->get(exec
, identifierFromNPIdentifier(i
->value
.string
));
155 if (func
->isNull()) {
156 NULL_TO_NPVARIANT(*result
);
159 if (func
->isUndefined()) {
160 VOID_TO_NPVARIANT(*result
);
163 // Call the function object.
164 JSObject
*funcImp
= static_cast<JSObject
*>(func
);
165 JSObject
*thisObj
= const_cast<JSObject
*>(obj
->imp
);
167 getListFromVariantArgs(exec
, args
, argCount
, rootObject
, argList
);
168 rootObject
->globalObject()->startTimeoutCheck();
169 JSValue
*resultV
= funcImp
->call (exec
, thisObj
, argList
);
170 rootObject
->globalObject()->stopTimeoutCheck();
172 // Convert and return the result of the function call.
173 convertValueToNPVariant(exec
, resultV
, result
);
177 if (o
->_class
->invoke
)
178 return o
->_class
->invoke(o
, methodName
, args
, argCount
, result
);
180 VOID_TO_NPVARIANT(*result
);
184 bool _NPN_Evaluate(NPP
, NPObject
* o
, NPString
* s
, NPVariant
* variant
)
186 if (o
->_class
== NPScriptObjectClass
) {
187 JavaScriptObject
* obj
= (JavaScriptObject
*)o
;
189 RootObject
* rootObject
= obj
->rootObject
;
190 if (!rootObject
|| !rootObject
->isValid())
193 ExecState
* exec
= rootObject
->globalObject()->globalExec();
196 NPUTF16
* scriptString
;
197 unsigned int UTF16Length
;
198 convertNPStringToUTF16(s
, &scriptString
, &UTF16Length
); // requires free() of returned memory
199 rootObject
->globalObject()->startTimeoutCheck();
200 Completion completion
= Interpreter::evaluate(rootObject
->globalObject()->globalExec(), UString(), 0, UString(reinterpret_cast<const UChar
*>(scriptString
), UTF16Length
));
201 rootObject
->globalObject()->stopTimeoutCheck();
202 ComplType type
= completion
.complType();
205 if (type
== Normal
) {
206 result
= completion
.value();
208 result
= jsUndefined();
210 result
= jsUndefined();
214 convertValueToNPVariant(exec
, result
, variant
);
219 VOID_TO_NPVARIANT(*variant
);
223 bool _NPN_GetProperty(NPP
, NPObject
* o
, NPIdentifier propertyName
, NPVariant
* variant
)
225 if (o
->_class
== NPScriptObjectClass
) {
226 JavaScriptObject
* obj
= (JavaScriptObject
*)o
;
228 RootObject
* rootObject
= obj
->rootObject
;
229 if (!rootObject
|| !rootObject
->isValid())
232 ExecState
* exec
= rootObject
->globalObject()->globalExec();
233 PrivateIdentifier
* i
= (PrivateIdentifier
*)propertyName
;
238 result
= obj
->imp
->get(exec
, identifierFromNPIdentifier(i
->value
.string
));
240 result
= obj
->imp
->get(exec
, i
->value
.number
);
242 convertValueToNPVariant(exec
, result
, variant
);
246 if (o
->_class
->hasProperty
&& o
->_class
->getProperty
) {
247 if (o
->_class
->hasProperty(o
, propertyName
))
248 return o
->_class
->getProperty(o
, propertyName
, variant
);
252 VOID_TO_NPVARIANT(*variant
);
256 bool _NPN_SetProperty(NPP
, NPObject
* o
, NPIdentifier propertyName
, const NPVariant
* variant
)
258 if (o
->_class
== NPScriptObjectClass
) {
259 JavaScriptObject
* obj
= (JavaScriptObject
*)o
;
261 RootObject
* rootObject
= obj
->rootObject
;
262 if (!rootObject
|| !rootObject
->isValid())
265 ExecState
* exec
= rootObject
->globalObject()->globalExec();
267 PrivateIdentifier
* i
= (PrivateIdentifier
*)propertyName
;
269 obj
->imp
->put(exec
, identifierFromNPIdentifier(i
->value
.string
), convertNPVariantToValue(exec
, variant
, rootObject
));
271 obj
->imp
->put(exec
, i
->value
.number
, convertNPVariantToValue(exec
, variant
, rootObject
));
275 if (o
->_class
->setProperty
)
276 return o
->_class
->setProperty(o
, propertyName
, variant
);
281 bool _NPN_RemoveProperty(NPP
, NPObject
* o
, NPIdentifier propertyName
)
283 if (o
->_class
== NPScriptObjectClass
) {
284 JavaScriptObject
* obj
= (JavaScriptObject
*)o
;
286 RootObject
* rootObject
= obj
->rootObject
;
287 if (!rootObject
|| !rootObject
->isValid())
290 ExecState
* exec
= rootObject
->globalObject()->globalExec();
291 PrivateIdentifier
* i
= (PrivateIdentifier
*)propertyName
;
293 if (!obj
->imp
->hasProperty(exec
, identifierFromNPIdentifier(i
->value
.string
)))
296 if (!obj
->imp
->hasProperty(exec
, i
->value
.number
))
302 obj
->imp
->deleteProperty(exec
, identifierFromNPIdentifier(i
->value
.string
));
304 obj
->imp
->deleteProperty(exec
, i
->value
.number
);
311 bool _NPN_HasProperty(NPP
, NPObject
* o
, NPIdentifier propertyName
)
313 if (o
->_class
== NPScriptObjectClass
) {
314 JavaScriptObject
* obj
= (JavaScriptObject
*)o
;
316 RootObject
* rootObject
= obj
->rootObject
;
317 if (!rootObject
|| !rootObject
->isValid())
320 ExecState
* exec
= rootObject
->globalObject()->globalExec();
321 PrivateIdentifier
* i
= (PrivateIdentifier
*)propertyName
;
324 return obj
->imp
->hasProperty(exec
, identifierFromNPIdentifier(i
->value
.string
));
325 return obj
->imp
->hasProperty(exec
, i
->value
.number
);
328 if (o
->_class
->hasProperty
)
329 return o
->_class
->hasProperty(o
, propertyName
);
334 bool _NPN_HasMethod(NPP
, NPObject
* o
, NPIdentifier methodName
)
336 if (o
->_class
== NPScriptObjectClass
) {
337 JavaScriptObject
* obj
= (JavaScriptObject
*)o
;
339 PrivateIdentifier
* i
= (PrivateIdentifier
*)methodName
;
343 RootObject
* rootObject
= obj
->rootObject
;
344 if (!rootObject
|| !rootObject
->isValid())
347 ExecState
* exec
= rootObject
->globalObject()->globalExec();
349 JSValue
* func
= obj
->imp
->get(exec
, identifierFromNPIdentifier(i
->value
.string
));
350 return !func
->isUndefined();
353 if (o
->_class
->hasMethod
)
354 return o
->_class
->hasMethod(o
, methodName
);
359 void _NPN_SetException(NPObject
* o
, const NPUTF8
* message
)
361 if (o
->_class
== NPScriptObjectClass
) {
362 JavaScriptObject
* obj
= (JavaScriptObject
*)o
;
363 RootObject
* rootObject
= obj
->rootObject
;
364 if (!rootObject
|| !rootObject
->isValid())
367 ExecState
* exec
= rootObject
->globalObject()->globalExec();
369 throwError(exec
, GeneralError
, message
);
373 bool _NPN_Enumerate(NPP
, NPObject
*o
, NPIdentifier
**identifier
, uint32_t *count
)
375 if (o
->_class
== NPScriptObjectClass
) {
376 JavaScriptObject
* obj
= (JavaScriptObject
*)o
;
378 RootObject
* rootObject
= obj
->rootObject
;
379 if (!rootObject
|| !rootObject
->isValid())
382 ExecState
* exec
= rootObject
->globalObject()->globalExec();
384 PropertyNameArray propertyNames
;
386 obj
->imp
->getPropertyNames(exec
, propertyNames
);
387 unsigned size
= static_cast<unsigned>(propertyNames
.size());
388 // FIXME: This should really call NPN_MemAlloc but that's in WebKit
389 NPIdentifier
*identifiers
= static_cast<NPIdentifier
*>(malloc(sizeof(NPIdentifier
) * size
));
391 for (unsigned i
= 0; i
< size
; i
++)
392 identifiers
[i
] = _NPN_GetStringIdentifier(propertyNames
[i
].ustring().UTF8String().c_str());
394 *identifier
= identifiers
;
400 if (NP_CLASS_STRUCT_VERSION_HAS_ENUM(o
->_class
) && o
->_class
->enumerate
)
401 return o
->_class
->enumerate(o
, identifier
, count
);
406 #endif // ENABLE(NETSCAPE_API)