[Author: playmobil]
[google-gears.git] / gears / base / common / js_types.h
blob81727d2389845f88c483018429f6a3a953226ce4
1 // Copyright 2007, Google Inc.
2 //
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are met:
5 //
6 // 1. Redistributions of source code must retain the above copyright notice,
7 // this list of conditions and the following disclaimer.
8 // 2. Redistributions in binary form must reproduce the above copyright notice,
9 // this list of conditions and the following disclaimer in the documentation
10 // and/or other materials provided with the distribution.
11 // 3. Neither the name of Google Inc. nor the names of its contributors may be
12 // used to endorse or promote products derived from this software without
13 // specific prior written permission.
15 // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
16 // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
17 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
18 // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21 // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
24 // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 #ifndef GEARS_BASE_COMMON_JS_TYPES_H__
27 #define GEARS_BASE_COMMON_JS_TYPES_H__
29 #include <assert.h>
30 #include "gears/base/common/common.h" // for DISALLOW_EVIL_CONSTRUCTORS
31 #include "gears/base/common/string16.h" // for string16
33 #if BROWSER_FF
35 #include <gecko_sdk/include/nsCOMPtr.h> // for JsParamFetcher
36 #include <gecko_internal/jsapi.h>
37 #include <gecko_internal/nsIXPConnect.h> // for JsParamFetcher
39 // Abstracted types for values used with JavaScript engines.
40 typedef jsval JsToken;
41 typedef jsval JsScopedToken; // unneeded in FF, see comment on JsArray
42 typedef JSContext* JsContextPtr;
43 typedef nsresult JsNativeMethodRetval;
45 // interface required for COM objects exposed in JS
46 typedef nsISupports IScriptable;
48 #elif BROWSER_IE
50 #include <windows.h>
51 // no "base_interface_ie.h" because IE doesn't require a COM base interface
53 // Abstracted types for values used with JavaScript engines.
54 typedef VARIANT JsToken;
55 typedef CComVariant JsScopedToken;
56 typedef void* JsContextPtr; // unused in IE
57 typedef HRESULT JsNativeMethodRetval;
59 // interface required for COM objects exposed in JS
60 typedef IDispatch IScriptable;
62 #elif BROWSER_WEBKIT
64 #include <WebKit/npapi.h>
65 #include <WebKit/npfunctions.h>
66 #include <WebKit/npruntime.h>
68 #elif BROWSER_NPAPI
70 #include "gecko_sdk/include/npapi.h"
71 #include "gecko_sdk/include/npupp.h"
73 #endif
75 #if BROWSER_NPAPI || BROWSER_WEBKIT
76 // Abstracted types for values used with JavaScript engines.
77 typedef NPVariant JsToken;
78 typedef NPP JsContextPtr;
79 typedef NPError JsNativeMethodRetval;
81 // Not used in NPAPI or WEBKIT at the moment
82 typedef void* IScriptable;
84 #endif // BROWSER_NPAPI || BROWSER_WEBKIT
86 class JsRootedToken;
87 typedef JsRootedToken JsRootedCallback;
89 // Utility functions to convert JsToken to various primitives.
90 // TODO(aa): Add coercion to these functions (since they include the word "to")
91 // and add new functions to determine what the token really is.
92 bool JsTokenToBool(JsToken t, JsContextPtr cx, bool *out);
93 bool JsTokenToInt(JsToken t, JsContextPtr cx, int *out);
94 bool JsTokenToString(JsToken t, JsContextPtr cx, std::string16 *out);
95 bool JsTokenToDouble(JsToken t, JsContextPtr cx, double *out);
96 bool JsTokenToNewCallback(JsToken t, JsContextPtr cx, JsRootedCallback **out);
98 // Utility function to check for the JavaScript values null and undefined. We
99 // usually treat these two identically to prevent confusion.
100 bool JsTokenIsNullOrUndefined(JsToken t);
102 // Utility function to tell if a given token is a JavaScript object. This
103 // function returns true for all JavaScript objects, including things like
104 // functions and Date objects. It returns false for all primitive values
105 // including null and undefined.
106 bool JsTokenIsObject(JsToken t);
108 #if BROWSER_FF
110 // A JsToken that won't get GC'd out from under you.
111 class JsRootedToken {
112 public:
113 JsRootedToken(JsContextPtr context, JsToken token)
114 : context_(context), token_(token) {
115 if (JSVAL_IS_GCTHING(token_)) {
116 JS_AddRoot(context_, &token_);
120 ~JsRootedToken() {
121 if (JSVAL_IS_GCTHING(token_)) {
122 JS_RemoveRoot(context_, &token_);
126 JsToken token() const { return token_; }
127 JsContextPtr context() const { return context_; }
129 bool GetAsBool(bool *out) const {
130 return JsTokenToBool(token_, context_, out);
133 // TODO(aa): GetAsString(), etc. But needs restructuring first. See note below
134 // above IE implementation.
136 private:
137 JsContextPtr context_;
138 JsToken token_;
139 DISALLOW_EVIL_CONSTRUCTORS(JsRootedToken);
142 #elif BROWSER_IE
144 // A JsToken that won't get GC'd out from under you.
145 // TODO(aa): This leaks for things like strings and arrays. We need to correctly
146 // handle lifetime. Also need to think of different requirements for when token
147 // is an input parameter vs a return value.
148 class JsRootedToken {
149 public:
150 JsRootedToken(JsContextPtr context, JsToken token)
151 : token_(token) { // IE doesn't use JsContextPtr
152 if (token_.vt == VT_DISPATCH) {
153 token_.pdispVal->AddRef();
157 ~JsRootedToken() {
158 if (token_.vt == VT_DISPATCH) {
159 token_.pdispVal->Release();
163 JsToken token() const { return token_; }
164 JsContextPtr context() const { return NULL; }
166 bool GetAsBool(bool *out) const {
167 return JsTokenToBool(token_, NULL, out);
170 private:
171 JsToken token_;
172 DISALLOW_EVIL_CONSTRUCTORS(JsRootedToken);
175 // Implementations of boilerplate code.
176 // - We don't currently need GetNativeBaseClass on IE.
178 #elif BROWSER_NPAPI
180 // An NPVariant that takes ownership of its value and releases it when it goes
181 // out of scope.
182 class ScopedNPVariant : public NPVariant {
183 public:
184 ScopedNPVariant() { VOID_TO_NPVARIANT(*this); }
185 template<class T>
186 explicit ScopedNPVariant(T value) { VOID_TO_NPVARIANT(*this); Reset(value); }
188 ~ScopedNPVariant() { Reset(); }
190 // This is necessary for API transparency.
191 ScopedNPVariant& operator=(const NPVariant &value) {
192 Reset(value);
193 return *this;
196 // Frees the old value and replaces it with the new value. Strings are
197 // copied, and objects are retained.
198 void Reset();
199 void Reset(int value);
200 void Reset(double value);
201 void Reset(const char *value);
202 void Reset(const char16 *value);
203 void Reset(NPObject *value);
204 void Reset(const NPVariant &value);
206 // Gives up ownership of this variant, without freeing or releasing the
207 // underyling object. The variant will be VOID after this call.
208 void Release();
211 typedef ScopedNPVariant JsScopedToken;
213 // A JsToken that won't get GC'd out from under you.
214 class JsRootedToken {
215 public:
216 JsRootedToken(JsContextPtr context, JsToken token)
217 : context_(context), token_(token) { }
219 const JsToken& token() const { return token_; }
220 JsContextPtr context() const { return context_; }
222 bool GetAsBool(bool *out) const {
223 return JsTokenToBool(token_, context_, out);
226 private:
227 JsContextPtr context_; // TODO(mpcomplete): figure out if this is necessary
228 JsScopedToken token_;
229 DISALLOW_EVIL_CONSTRUCTORS(JsRootedToken);
232 #elif BROWSER_SAFARI
234 // Just placeholder values for Safari since the created workers use a separate
235 // process for JS execution.
236 typedef void JsToken;
237 typedef void JsScopedToken;
238 typedef void* JsContextPtr;
239 typedef void JsNativeMethodRetval;
241 #endif // BROWSER_xyz
243 // JsArray and JsObject make use of a JsScopedToken, which is a token that
244 // releases any references it has when it goes out of scope. This is necessary
245 // in IE and NPAPI, because getting an array element or object property
246 // increases the reference count, and we need a way to release that reference
247 // *after* we're done using the object. In Firefox, JsToken == JsScopedToken
248 // because Firefox only gives us a weak pointer to the value.
250 class JsObject;
251 struct JsParamToSend;
252 class ModuleImplBaseClass;
254 class JsArray {
255 public:
256 JsArray();
257 ~JsArray();
259 bool SetArray(JsToken value, JsContextPtr context);
261 bool GetLength(int *length) const;
263 // use the same syntax as JsRootedToken
264 const JsScopedToken& token() const;
266 bool GetElement(int index, JsScopedToken *out) const;
267 bool GetElementAsBool(int index, bool *out) const;
268 bool GetElementAsInt(int index, int *out) const;
269 bool GetElementAsDouble(int index, double *out) const;
270 bool GetElementAsString(int index, std::string16 *out) const;
271 bool GetElementAsArray(int index, JsArray *out) const;
272 bool GetElementAsObject(int index, JsObject *out) const;
273 bool GetElementAsFunction(int index, JsRootedCallback **out) const;
275 bool SetElement(int index, const JsScopedToken& value);
276 bool SetElementBool(int index, bool value);
277 bool SetElementInt(int index, int value);
278 bool SetElementDouble(int index, double value);
279 bool SetElementString(int index, const std::string16& value);
280 bool SetElementArray(int index, JsArray* value);
281 bool SetElementObject(int index, JsObject* value);
282 bool SetElementFunction(int index, JsRootedCallback* value);
283 bool SetElementModule(int index, IScriptable* value);
285 private:
286 // Needs access to the raw JsToken.
287 friend void ConvertJsParamToToken(const JsParamToSend &param,
288 JsContextPtr context,
289 JsScopedToken *token);
290 JsContextPtr js_context_;
291 JsScopedToken array_;
294 class JsObject {
295 public:
296 JsObject();
297 ~JsObject();
298 bool GetProperty(const std::string16 &name, JsScopedToken *value) const;
299 bool SetObject(JsToken value, JsContextPtr context);
300 bool GetPropertyAsBool(const std::string16 &name, bool *out) const;
301 bool GetPropertyAsInt(const std::string16 &name, int *out) const;
302 bool GetPropertyAsDouble(const std::string16 &name, double *out) const;
303 bool GetPropertyAsString(const std::string16 &name, std::string16 *out) const;
304 bool GetPropertyAsArray(const std::string16 &name, JsArray *out) const;
305 bool GetPropertyAsObject(const std::string16 &name, JsObject *out) const;
306 bool GetPropertyAsFunction(const std::string16 &name,
307 JsRootedCallback **out) const;
309 // SetProperty*() overwrites the existing named property or adds a new one if
310 // none exists.
311 bool SetPropertyBool(const std::string16& name, bool value);
312 bool SetPropertyInt(const std::string16 &name, int value);
313 bool SetPropertyDouble(const std::string16& name, double value);
314 bool SetPropertyString(const std::string16 &name, const std::string16 &value);
315 bool SetPropertyArray(const std::string16& name, JsArray* value);
316 bool SetPropertyObject(const std::string16& name, JsObject* value);
317 bool SetPropertyFunction(const std::string16& name, JsRootedCallback* value);
318 bool SetPropertyModule(const std::string16& name, IScriptable* value);
320 private:
321 // Need access to the raw JsToken.
322 friend class JsRunnerBase;
323 friend class JsArray;
324 friend void ConvertJsParamToToken(const JsParamToSend &param,
325 JsContextPtr context,
326 JsScopedToken *token);
327 friend JsNativeMethodRetval JsSetException(const ModuleImplBaseClass *obj,
328 const char16 *message);
330 bool SetProperty(const std::string16 &name, const JsToken &value);
332 JsContextPtr js_context_;
333 JsScopedToken js_object_;
336 // The JsParam* types define values for sending and receiving JS parameters.
337 enum JsParamType {
338 JSPARAM_BOOL,
339 JSPARAM_INT, // TODO(mpcomplete): deprecate in favor of double?
340 JSPARAM_DOUBLE,
341 JSPARAM_STRING16,
342 JSPARAM_OBJECT,
343 JSPARAM_ARRAY,
344 JSPARAM_FUNCTION,
345 JSPARAM_MODULE,
346 JSPARAM_NULL,
349 enum JsParamRequirement {
350 JSPARAM_OPTIONAL,
351 JSPARAM_REQUIRED,
354 struct JsParamToSend {
355 JsParamType type;
356 const void *value_ptr;
359 struct JsParamToRecv {
360 JsParamType type;
361 void *value_ptr;
364 struct JsArgument {
365 JsParamRequirement requirement;
366 JsParamType type;
367 void* value_ptr;
371 class ModuleImplBaseClass;
373 // This class provides an interface for a property or method access on a native
374 // object from JavaScript. It allows consumers to retrieve what arguments were
375 // passed in, and return a value or exception back to the caller. Any native
376 // property or method handler should take an instance of this object as a
377 // parameter.
378 class JsCallContext {
379 public:
380 // Only browser-specific wrapper code should need to instantiate this object.
381 #if BROWSER_NPAPI
382 JsCallContext(JsContextPtr js_context, NPObject *object,
383 int argc, const JsToken *argv, JsToken *retval)
384 : js_context_(js_context), object_(object),
385 argc_(argc), argv_(argv), retval_(retval),
386 is_exception_set_(false) {}
387 #elif BROWSER_IE
388 JsCallContext(DISPPARAMS FAR *disp_params, VARIANT FAR *retval,
389 EXCEPINFO FAR *excep_info)
390 : disp_params_(disp_params), retval_(retval), exception_info_(excep_info),
391 is_exception_set_(false) {}
392 #elif BROWSER_FF
393 explicit JsCallContext(ModuleImplBaseClass* obj);
394 #else
395 // TODO: browser_xyz
396 #endif
398 // Get the arguments a JavaScript caller has passed into a scriptable method
399 // of a native object. Returns the number of arguments successfully read
400 // (will bail at the first invalid argument).
401 int GetArguments(int argc, JsArgument *argv);
403 // Sets the value to be returned to the calling JavaScript.
405 // The ModuleImplBaseClass* version should only be used when returning a
406 // JSPARAM_MODULE. It exists because passing a derived class through a void*
407 // and then casting to the base class is not safe - the compiler won't be able
408 // to correctly adjust the pointer offset.
410 // The int version is for use with JSPARAM_NULL, to avoid conflicting with the
411 // ModuleImplBaseClass version (works because NULL is defined as 0).
412 void SetReturnValue(JsParamType type, const void *value_ptr);
413 void SetReturnValue(JsParamType type, const ModuleImplBaseClass *value_ptr) {
414 assert(type == JSPARAM_MODULE);
415 SetReturnValue(type, reinterpret_cast<const void*>(value_ptr));
417 void SetReturnValue(JsParamType type, int) {
418 assert(type == JSPARAM_NULL);
419 SetReturnValue(type, reinterpret_cast<const void*>(NULL));
422 // Sets an exception to be thrown to the calling JavaScript. Setting an
423 // exception overrides any previous exception and any return values.
424 void SetException(const std::string16 &message);
426 JsContextPtr js_context() { return js_context_; }
427 bool is_exception_set() { return is_exception_set_; }
429 private:
430 JsContextPtr js_context_;
431 bool is_exception_set_;
432 #if BROWSER_NPAPI
433 NPObject *object_;
434 int argc_;
435 const JsToken *argv_;
436 JsToken *retval_;
437 #elif BROWSER_IE
438 DISPPARAMS FAR *disp_params_;
439 VARIANT FAR *retval_;
440 EXCEPINFO FAR *exception_info_;
441 #elif BROWSER_FF
442 int argc_;
443 JsToken* argv_;
444 nsCOMPtr<nsIXPConnect> xpc_;
445 nsCOMPtr<nsIXPCNativeCallContext> ncc_;
446 ModuleImplBaseClass* obj_;
447 #else
448 // TODO: browser_xyz
449 #endif
453 // Given a JsParamToSend, extract it into a JsScopedToken. Resulting token
454 // increases the reference count for objects.
455 void ConvertJsParamToToken(const JsParamToSend &param,
456 JsContextPtr context, JsScopedToken *token);
458 //-----------------------------------------------------------------------------
459 #if BROWSER_FF // the rest of this file only applies to Firefox, for now
461 // Helper class to extract JavaScript parameters (including optional params
462 // and varargs), in a way that hides differences between main-thread and
463 // worker-thread environments.
464 class JsParamFetcher {
465 public:
466 explicit JsParamFetcher(ModuleImplBaseClass *obj);
468 JsContextPtr GetContextPtr() { return js_context_; }
469 int GetCount(bool has_mysterious_retval) {
470 return has_mysterious_retval ? js_argc_ - 1 : js_argc_;
472 // In Firefox, set has_string_retval iff method has a string return value.
473 bool IsOptionalParamPresent(int i, bool has_string_retval);
475 // All functions check the type of the requested value, and they will return
476 // false on a mismatch.
477 bool GetAsInt(int i, int *out);
478 bool GetAsString(int i, std::string16 *out);
479 bool GetAsArray(int i, JsArray *out);
480 bool GetAsObject(int i, JsObject *out);
481 bool GetAsNewRootedCallback(int i, JsRootedCallback **out);
483 private:
484 JsContextPtr js_context_;
485 int js_argc_;
486 JsToken *js_argv_;
488 #if BROWSER_FF
489 nsCOMPtr<nsIXPConnect> xpc_;
490 nsCOMPtr<nsIXPCNativeCallContext> ncc_;
491 #elif BROWSER_IE
492 #endif
496 // Sets JavaScript exceptions, in a way that hides differences
497 // between main-thread and worker-thread environments.
498 // Returns the value the caller should return to the JavaScript host engine.
499 JsNativeMethodRetval JsSetException(const ModuleImplBaseClass *obj,
500 const char16 *message);
502 // Garbage collection helper functions
503 bool RootJsToken(JsContextPtr cx, JsToken t);
506 #endif // BROWSER_FF
507 //-----------------------------------------------------------------------------
510 #endif // GEARS_BASE_COMMON_JS_TYPES_H__