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 "SourceCode.h"
35 #include "c_utility.h"
36 #include "interpreter.h"
37 #include "npruntime_impl.h"
38 #include "npruntime_priv.h"
40 #include "runtime_root.h"
43 using namespace KJS::Bindings
;
45 static void getListFromVariantArgs(ExecState
* exec
, const NPVariant
* args
, unsigned argCount
, RootObject
* rootObject
, List
& aList
)
47 for (unsigned i
= 0; i
< argCount
; i
++)
48 aList
.append(convertNPVariantToValue(exec
, &args
[i
], rootObject
));
51 static NPObject
* jsAllocate(NPP
, NPClass
*)
53 return (NPObject
*)malloc(sizeof(JavaScriptObject
));
56 static void jsDeallocate(NPObject
* npObj
)
58 JavaScriptObject
* obj
= (JavaScriptObject
*)npObj
;
60 if (obj
->rootObject
&& obj
->rootObject
->isValid())
61 obj
->rootObject
->gcUnprotect(obj
->imp
);
64 obj
->rootObject
->deref();
69 static NPClass javascriptClass
= { 1, jsAllocate
, jsDeallocate
, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
70 static NPClass noScriptClass
= { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
72 NPClass
* NPScriptObjectClass
= &javascriptClass
;
73 static NPClass
* NPNoScriptObjectClass
= &noScriptClass
;
75 NPObject
* _NPN_CreateScriptObject(NPP npp
, JSObject
* imp
, PassRefPtr
<RootObject
> rootObject
)
77 JavaScriptObject
* obj
= (JavaScriptObject
*)_NPN_CreateObject(npp
, NPScriptObjectClass
);
79 obj
->rootObject
= rootObject
.releaseRef();
82 obj
->rootObject
->gcProtect(imp
);
85 return (NPObject
*)obj
;
88 NPObject
*_NPN_CreateNoScriptObject(void)
90 return _NPN_CreateObject(0, NPNoScriptObjectClass
);
93 bool _NPN_InvokeDefault(NPP
, NPObject
* o
, const NPVariant
* args
, uint32_t argCount
, NPVariant
* result
)
95 if (o
->_class
== NPScriptObjectClass
) {
96 JavaScriptObject
* obj
= (JavaScriptObject
*)o
;
98 VOID_TO_NPVARIANT(*result
);
100 // Lookup the function object.
101 RootObject
* rootObject
= obj
->rootObject
;
102 if (!rootObject
|| !rootObject
->isValid())
105 ExecState
* exec
= rootObject
->globalObject()->globalExec();
108 // Call the function object.
109 JSObject
*funcImp
= static_cast<JSObject
*>(obj
->imp
);
110 if (!funcImp
->implementsCall())
114 getListFromVariantArgs(exec
, args
, argCount
, rootObject
, argList
);
115 rootObject
->globalObject()->startTimeoutCheck();
116 JSValue
*resultV
= funcImp
->call (exec
, funcImp
, argList
);
117 rootObject
->globalObject()->stopTimeoutCheck();
119 // Convert and return the result of the function call.
120 convertValueToNPVariant(exec
, resultV
, result
);
124 if (o
->_class
->invokeDefault
)
125 return o
->_class
->invokeDefault(o
, args
, argCount
, result
);
126 VOID_TO_NPVARIANT(*result
);
130 bool _NPN_Invoke(NPP npp
, NPObject
* o
, NPIdentifier methodName
, const NPVariant
* args
, uint32_t argCount
, NPVariant
* result
)
132 if (o
->_class
== NPScriptObjectClass
) {
133 JavaScriptObject
* obj
= (JavaScriptObject
*)o
;
135 PrivateIdentifier
* i
= (PrivateIdentifier
*)methodName
;
139 // Special case the "eval" method.
140 if (methodName
== _NPN_GetStringIdentifier("eval")) {
143 if (args
[0].type
!= NPVariantType_String
)
145 return _NPN_Evaluate(npp
, o
, (NPString
*)&args
[0].value
.stringValue
, result
);
148 // Lookup the function object.
149 RootObject
* rootObject
= obj
->rootObject
;
150 if (!rootObject
|| !rootObject
->isValid())
153 ExecState
* exec
= rootObject
->globalObject()->globalExec();
155 JSValue
* func
= obj
->imp
->get(exec
, identifierFromNPIdentifier(i
->value
.string
));
156 if (func
->isNull()) {
157 NULL_TO_NPVARIANT(*result
);
160 if (func
->isUndefined()) {
161 VOID_TO_NPVARIANT(*result
);
164 // Call the function object.
165 JSObject
*funcImp
= static_cast<JSObject
*>(func
);
166 JSObject
*thisObj
= const_cast<JSObject
*>(obj
->imp
);
168 getListFromVariantArgs(exec
, args
, argCount
, rootObject
, argList
);
169 rootObject
->globalObject()->startTimeoutCheck();
170 JSValue
*resultV
= funcImp
->call (exec
, thisObj
, argList
);
171 rootObject
->globalObject()->stopTimeoutCheck();
173 // Convert and return the result of the function call.
174 convertValueToNPVariant(exec
, resultV
, result
);
178 if (o
->_class
->invoke
)
179 return o
->_class
->invoke(o
, methodName
, args
, argCount
, result
);
181 VOID_TO_NPVARIANT(*result
);
185 bool _NPN_Evaluate(NPP
, NPObject
* o
, NPString
* s
, NPVariant
* variant
)
187 if (o
->_class
== NPScriptObjectClass
) {
188 JavaScriptObject
* obj
= (JavaScriptObject
*)o
;
190 RootObject
* rootObject
= obj
->rootObject
;
191 if (!rootObject
|| !rootObject
->isValid())
194 ExecState
* exec
= rootObject
->globalObject()->globalExec();
197 NPUTF16
* scriptString
;
198 unsigned int UTF16Length
;
199 convertNPStringToUTF16(s
, &scriptString
, &UTF16Length
); // requires free() of returned memory
200 rootObject
->globalObject()->startTimeoutCheck();
202 SourceCode source
= makeSource(UString(reinterpret_cast<const UChar
*>(scriptString
), UTF16Length
), UString());
203 Completion completion
= Interpreter::evaluate(rootObject
->globalObject()->globalExec(), source
);
204 rootObject
->globalObject()->stopTimeoutCheck();
205 ComplType type
= completion
.complType();
208 if (type
== Normal
) {
209 result
= completion
.value();
211 result
= jsUndefined();
213 result
= jsUndefined();
217 convertValueToNPVariant(exec
, result
, variant
);
222 VOID_TO_NPVARIANT(*variant
);
226 bool _NPN_GetProperty(NPP
, NPObject
* o
, NPIdentifier propertyName
, NPVariant
* variant
)
228 if (o
->_class
== NPScriptObjectClass
) {
229 JavaScriptObject
* obj
= (JavaScriptObject
*)o
;
231 RootObject
* rootObject
= obj
->rootObject
;
232 if (!rootObject
|| !rootObject
->isValid())
235 ExecState
* exec
= rootObject
->globalObject()->globalExec();
236 PrivateIdentifier
* i
= (PrivateIdentifier
*)propertyName
;
241 result
= obj
->imp
->get(exec
, identifierFromNPIdentifier(i
->value
.string
));
243 result
= obj
->imp
->get(exec
, i
->value
.number
);
245 convertValueToNPVariant(exec
, result
, variant
);
249 if (o
->_class
->hasProperty
&& o
->_class
->getProperty
) {
250 if (o
->_class
->hasProperty(o
, propertyName
))
251 return o
->_class
->getProperty(o
, propertyName
, variant
);
255 VOID_TO_NPVARIANT(*variant
);
259 bool _NPN_SetProperty(NPP
, NPObject
* o
, NPIdentifier propertyName
, const NPVariant
* variant
)
261 if (o
->_class
== NPScriptObjectClass
) {
262 JavaScriptObject
* obj
= (JavaScriptObject
*)o
;
264 RootObject
* rootObject
= obj
->rootObject
;
265 if (!rootObject
|| !rootObject
->isValid())
268 ExecState
* exec
= rootObject
->globalObject()->globalExec();
270 PrivateIdentifier
* i
= (PrivateIdentifier
*)propertyName
;
272 obj
->imp
->put(exec
, identifierFromNPIdentifier(i
->value
.string
), convertNPVariantToValue(exec
, variant
, rootObject
));
274 obj
->imp
->put(exec
, i
->value
.number
, convertNPVariantToValue(exec
, variant
, rootObject
));
278 if (o
->_class
->setProperty
)
279 return o
->_class
->setProperty(o
, propertyName
, variant
);
284 bool _NPN_RemoveProperty(NPP
, NPObject
* o
, NPIdentifier propertyName
)
286 if (o
->_class
== NPScriptObjectClass
) {
287 JavaScriptObject
* obj
= (JavaScriptObject
*)o
;
289 RootObject
* rootObject
= obj
->rootObject
;
290 if (!rootObject
|| !rootObject
->isValid())
293 ExecState
* exec
= rootObject
->globalObject()->globalExec();
294 PrivateIdentifier
* i
= (PrivateIdentifier
*)propertyName
;
296 if (!obj
->imp
->hasProperty(exec
, identifierFromNPIdentifier(i
->value
.string
)))
299 if (!obj
->imp
->hasProperty(exec
, i
->value
.number
))
305 obj
->imp
->deleteProperty(exec
, identifierFromNPIdentifier(i
->value
.string
));
307 obj
->imp
->deleteProperty(exec
, i
->value
.number
);
314 bool _NPN_HasProperty(NPP
, NPObject
* o
, NPIdentifier propertyName
)
316 if (o
->_class
== NPScriptObjectClass
) {
317 JavaScriptObject
* obj
= (JavaScriptObject
*)o
;
319 RootObject
* rootObject
= obj
->rootObject
;
320 if (!rootObject
|| !rootObject
->isValid())
323 ExecState
* exec
= rootObject
->globalObject()->globalExec();
324 PrivateIdentifier
* i
= (PrivateIdentifier
*)propertyName
;
327 return obj
->imp
->hasProperty(exec
, identifierFromNPIdentifier(i
->value
.string
));
328 return obj
->imp
->hasProperty(exec
, i
->value
.number
);
331 if (o
->_class
->hasProperty
)
332 return o
->_class
->hasProperty(o
, propertyName
);
337 bool _NPN_HasMethod(NPP
, NPObject
* o
, NPIdentifier methodName
)
339 if (o
->_class
== NPScriptObjectClass
) {
340 JavaScriptObject
* obj
= (JavaScriptObject
*)o
;
342 PrivateIdentifier
* i
= (PrivateIdentifier
*)methodName
;
346 RootObject
* rootObject
= obj
->rootObject
;
347 if (!rootObject
|| !rootObject
->isValid())
350 ExecState
* exec
= rootObject
->globalObject()->globalExec();
352 JSValue
* func
= obj
->imp
->get(exec
, identifierFromNPIdentifier(i
->value
.string
));
353 return !func
->isUndefined();
356 if (o
->_class
->hasMethod
)
357 return o
->_class
->hasMethod(o
, methodName
);
362 void _NPN_SetException(NPObject
* o
, const NPUTF8
* message
)
364 if (o
->_class
== NPScriptObjectClass
) {
365 JavaScriptObject
* obj
= (JavaScriptObject
*)o
;
366 RootObject
* rootObject
= obj
->rootObject
;
367 if (!rootObject
|| !rootObject
->isValid())
370 ExecState
* exec
= rootObject
->globalObject()->globalExec();
372 throwError(exec
, GeneralError
, message
);
376 bool _NPN_Enumerate(NPP
, NPObject
*o
, NPIdentifier
**identifier
, uint32_t *count
)
378 if (o
->_class
== NPScriptObjectClass
) {
379 JavaScriptObject
* obj
= (JavaScriptObject
*)o
;
381 RootObject
* rootObject
= obj
->rootObject
;
382 if (!rootObject
|| !rootObject
->isValid())
385 ExecState
* exec
= rootObject
->globalObject()->globalExec();
387 PropertyNameArray propertyNames
;
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
));
394 for (unsigned i
= 0; i
< size
; i
++)
395 identifiers
[i
] = _NPN_GetStringIdentifier(propertyNames
[i
].ustring().UTF8String().c_str());
397 *identifier
= identifiers
;
403 if (NP_CLASS_STRUCT_VERSION_HAS_ENUM(o
->_class
) && o
->_class
->enumerate
)
404 return o
->_class
->enumerate(o
, identifier
, count
);
409 #endif // ENABLE(NETSCAPE_API)