[Author: zork]
[google-gears.git] / gears / base / common / js_types.h
blobabdee0724a412e77944d6cb09d67068da7b86458
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 class JsContextWrapper;
41 // Abstracted types for values used with JavaScript engines.
42 typedef jsval JsToken;
43 typedef jsval JsScopedToken; // unneeded in FF, see comment on JsArray
44 typedef JSContext* JsContextPtr;
45 typedef JsContextWrapper* JsContextWrapperPtr;
46 typedef nsresult JsNativeMethodRetval;
48 // interface required for COM objects exposed in JS
49 typedef nsISupports IScriptable;
51 #elif BROWSER_IE
53 #include <windows.h>
54 // no "base_interface_ie.h" because IE doesn't require a COM base interface
56 // Abstracted types for values used with JavaScript engines.
57 typedef VARIANT JsToken;
58 typedef CComVariant JsScopedToken;
59 typedef void* JsContextPtr; // unused in IE
60 typedef void* JsContextWrapperPtr; // unused in IE
61 typedef HRESULT JsNativeMethodRetval;
63 // interface required for COM objects exposed in JS
64 typedef IDispatch IScriptable;
66 #elif BROWSER_WEBKIT
68 #include <WebKit/npapi.h>
69 #include <WebKit/npfunctions.h>
70 #include <WebKit/npruntime.h>
72 #elif BROWSER_NPAPI
74 #include "gecko_sdk/include/npapi.h"
75 #include "gecko_sdk/include/npupp.h"
77 #endif
79 #if BROWSER_NPAPI || BROWSER_WEBKIT
80 // Abstracted types for values used with JavaScript engines.
81 typedef NPVariant JsToken;
82 typedef NPP JsContextPtr;
83 typedef void* JsContextWrapperPtr; // unused in NPAPI
84 typedef NPError JsNativeMethodRetval;
86 // Not used in NPAPI or WEBKIT at the moment
87 typedef void* IScriptable;
89 #endif // BROWSER_NPAPI || BROWSER_WEBKIT
91 class JsRootedToken;
92 typedef JsRootedToken JsRootedCallback;
94 // The JsParam* types define values for sending and receiving JS parameters.
95 enum JsParamType {
96 JSPARAM_BOOL,
97 JSPARAM_INT,
98 JSPARAM_DOUBLE,
99 JSPARAM_STRING16,
100 JSPARAM_OBJECT,
101 JSPARAM_ARRAY,
102 JSPARAM_FUNCTION,
103 JSPARAM_MODULE,
104 JSPARAM_NULL,
105 JSPARAM_UNDEFINED,
106 JSPARAM_UNKNOWN,
109 enum JsParamRequirement {
110 JSPARAM_OPTIONAL,
111 JSPARAM_REQUIRED,
114 struct JsParamToSend {
115 JsParamType type;
116 const void *value_ptr;
119 struct JsParamToRecv {
120 JsParamType type;
121 void *value_ptr;
124 struct JsArgument {
125 JsParamRequirement requirement;
126 JsParamType type;
127 void* value_ptr;
130 // Utility functions to convert JsToken to various primitives. These
131 // functions will try to coerce the JsToken to the required type. null or
132 // undefined are never coerced and these functions will return false in
133 // that case.
134 // TODO(oshlack): implement coercion for NPAPI.
135 bool JsTokenToBool(JsToken t, JsContextPtr cx, bool *out);
136 bool JsTokenToInt(JsToken t, JsContextPtr cx, int *out);
137 bool JsTokenToString(JsToken t, JsContextPtr cx, std::string16 *out);
138 bool JsTokenToDouble(JsToken t, JsContextPtr cx, double *out);
139 bool JsTokenToNewCallback(JsToken t, JsContextPtr cx, JsRootedCallback **out);
141 // Utility function to determine the type of a JsToken.
142 JsParamType JsTokenGetType(JsToken t, JsContextPtr cx);
144 // Utility function to tell if a given token is a JavaScript function.
145 bool JsTokenIsCallback(JsToken t, JsContextPtr cx);
147 // Utility function to tell if a given token is a JavaScript array.
148 bool JsTokenIsArray(JsToken t, JsContextPtr cx);
150 // Utility function to tell if a given token is a JavaScript object. This
151 // function returns true for all JavaScript objects, including things like
152 // functions and Date objects. It returns false for all primitive values
153 // including null and undefined.
154 bool JsTokenIsObject(JsToken t);
156 // Utility function to check for the JavaScript values null and undefined. We
157 // usually treat these two identically to prevent confusion.
158 bool JsTokenIsNullOrUndefined(JsToken t);
160 #if BROWSER_FF
162 // A JsToken that won't get GC'd out from under you.
163 class JsRootedToken {
164 public:
165 JsRootedToken(JsContextPtr context, JsToken token)
166 : context_(context), token_(token) {
167 if (JSVAL_IS_GCTHING(token_)) {
168 JS_AddRoot(context_, &token_);
172 ~JsRootedToken() {
173 if (JSVAL_IS_GCTHING(token_)) {
174 JS_RemoveRoot(context_, &token_);
178 JsToken token() const { return token_; }
179 JsContextPtr context() const { return context_; }
181 bool GetAsBool(bool *out) const {
182 return JsTokenToBool(token_, context_, out);
185 // TODO(aa): GetAsString(), etc. But needs restructuring first. See note below
186 // above IE implementation.
188 private:
189 JsContextPtr context_;
190 JsToken token_;
191 DISALLOW_EVIL_CONSTRUCTORS(JsRootedToken);
194 #elif BROWSER_IE
196 // A JsToken that won't get GC'd out from under you.
197 // TODO(aa): This leaks for things like strings and arrays. We need to correctly
198 // handle lifetime. Also need to think of different requirements for when token
199 // is an input parameter vs a return value.
200 class JsRootedToken {
201 public:
202 JsRootedToken(JsContextPtr context, JsToken token)
203 : token_(token) { // IE doesn't use JsContextPtr
204 if (token_.vt == VT_DISPATCH) {
205 token_.pdispVal->AddRef();
209 ~JsRootedToken() {
210 if (token_.vt == VT_DISPATCH) {
211 token_.pdispVal->Release();
215 JsToken token() const { return token_; }
216 JsContextPtr context() const { return NULL; }
218 bool GetAsBool(bool *out) const {
219 return JsTokenToBool(token_, NULL, out);
222 private:
223 JsToken token_;
224 DISALLOW_EVIL_CONSTRUCTORS(JsRootedToken);
227 // Implementations of boilerplate code.
228 // - We don't currently need GetNativeBaseClass on IE.
230 #elif BROWSER_NPAPI
232 // An NPVariant that takes ownership of its value and releases it when it goes
233 // out of scope.
234 class ScopedNPVariant : public NPVariant {
235 public:
236 ScopedNPVariant() { VOID_TO_NPVARIANT(*this); }
237 template<class T>
238 explicit ScopedNPVariant(T value) { VOID_TO_NPVARIANT(*this); Reset(value); }
240 ~ScopedNPVariant() { Reset(); }
242 // This is necessary for API transparency.
243 ScopedNPVariant& operator=(const NPVariant &value) {
244 Reset(value);
245 return *this;
248 // Frees the old value and replaces it with the new value. Strings are
249 // copied, and objects are retained.
250 void Reset();
251 void Reset(int value);
252 void Reset(double value);
253 void Reset(const char *value);
254 void Reset(const char16 *value);
255 void Reset(NPObject *value);
256 void Reset(const NPVariant &value);
258 // Gives up ownership of this variant, without freeing or releasing the
259 // underyling object. The variant will be VOID after this call.
260 void Release();
263 typedef ScopedNPVariant JsScopedToken;
265 // A JsToken that won't get GC'd out from under you.
266 class JsRootedToken {
267 public:
268 JsRootedToken(JsContextPtr context, JsToken token)
269 : context_(context), token_(token) { }
271 const JsToken& token() const { return token_; }
272 JsContextPtr context() const { return context_; }
274 bool GetAsBool(bool *out) const {
275 return JsTokenToBool(token_, context_, out);
278 private:
279 JsContextPtr context_; // TODO(mpcomplete): figure out if this is necessary
280 JsScopedToken token_;
281 DISALLOW_EVIL_CONSTRUCTORS(JsRootedToken);
284 #elif BROWSER_SAFARI
286 // Just placeholder values for Safari since the created workers use a separate
287 // process for JS execution.
288 typedef void JsToken;
289 typedef void JsScopedToken;
290 typedef void* JsContextPtr;
291 typedef void JsNativeMethodRetval;
293 #endif // BROWSER_xyz
295 // JsArray and JsObject make use of a JsScopedToken, which is a token that
296 // releases any references it has when it goes out of scope. This is necessary
297 // in IE and NPAPI, because getting an array element or object property
298 // increases the reference count, and we need a way to release that reference
299 // *after* we're done using the object. In Firefox, JsToken == JsScopedToken
300 // because Firefox only gives us a weak pointer to the value.
302 class JsObject;
303 struct JsParamToSend;
304 class JsRunnerInterface;
305 class ModuleImplBaseClass;
307 class JsArray {
308 public:
309 JsArray();
310 ~JsArray();
312 bool SetArray(JsToken value, JsContextPtr context);
314 bool GetLength(int *length) const;
316 // use the same syntax as JsRootedToken
317 const JsScopedToken &token() const { return array_; }
318 const JsContextPtr &context() const { return js_context_; }
321 bool GetElement(int index, JsScopedToken *out) const;
323 // These functions coerce values using the JsTokenTo*() functions.
324 bool GetElementAsBool(int index, bool *out) const;
325 bool GetElementAsInt(int index, int *out) const;
326 bool GetElementAsDouble(int index, double *out) const;
327 bool GetElementAsString(int index, std::string16 *out) const;
328 bool GetElementAsArray(int index, JsArray *out) const;
329 bool GetElementAsObject(int index, JsObject *out) const;
330 bool GetElementAsFunction(int index, JsRootedCallback **out) const;
332 // Method to get the type of an element
333 JsParamType GetElementType(int index) const;
335 bool SetElement(int index, const JsScopedToken& value);
336 bool SetElementBool(int index, bool value);
337 bool SetElementInt(int index, int value);
338 bool SetElementDouble(int index, double value);
339 bool SetElementString(int index, const std::string16& value);
340 bool SetElementArray(int index, JsArray* value);
341 bool SetElementObject(int index, JsObject* value);
342 bool SetElementFunction(int index, JsRootedCallback* value);
343 bool SetElementModule(int index, IScriptable* value);
345 private:
346 JsContextPtr js_context_;
347 JsScopedToken array_;
350 class JsObject {
351 public:
352 JsObject();
353 ~JsObject();
354 bool GetProperty(const std::string16 &name, JsScopedToken *value) const;
355 bool SetObject(JsToken value, JsContextPtr context);
357 // These functions coerce values using the JsTokenTo*() functions.
358 bool GetPropertyAsBool(const std::string16 &name, bool *out) const;
359 bool GetPropertyAsInt(const std::string16 &name, int *out) const;
360 bool GetPropertyAsDouble(const std::string16 &name, double *out) const;
361 bool GetPropertyAsString(const std::string16 &name, std::string16 *out) const;
362 bool GetPropertyAsArray(const std::string16 &name, JsArray *out) const;
363 bool GetPropertyAsObject(const std::string16 &name, JsObject *out) const;
364 bool GetPropertyAsFunction(const std::string16 &name,
365 JsRootedCallback **out) const;
367 // Method to get the type of a property
368 JsParamType GetPropertyType(const std::string16 &name) const;
370 // SetProperty*() overwrites the existing named property or adds a new one if
371 // none exists.
372 bool SetPropertyBool(const std::string16& name, bool value);
373 bool SetPropertyInt(const std::string16 &name, int value);
374 bool SetPropertyDouble(const std::string16& name, double value);
375 bool SetPropertyString(const std::string16 &name, const std::string16 &value);
376 bool SetPropertyArray(const std::string16& name, JsArray* value);
377 bool SetPropertyObject(const std::string16& name, JsObject* value);
378 bool SetPropertyFunction(const std::string16& name, JsRootedCallback* value);
379 bool SetPropertyModule(const std::string16& name, IScriptable* value);
381 const JsScopedToken &token() const { return js_object_; }
382 const JsContextPtr &context() const { return js_context_; }
384 private:
385 bool SetProperty(const std::string16 &name, const JsToken &value);
387 JsContextPtr js_context_;
388 JsScopedToken js_object_;
391 class ModuleImplBaseClass;
392 class JsRunnerInterface;
394 // This class provides an interface for a property or method access on a native
395 // object from JavaScript. It allows consumers to retrieve what arguments were
396 // passed in, and return a value or exception back to the caller. Any native
397 // property or method handler should take an instance of this object as a
398 // parameter.
399 class JsCallContext {
400 public:
401 // Only browser-specific wrapper code should need to instantiate this object.
402 #if BROWSER_NPAPI
403 JsCallContext(JsContextPtr js_context, NPObject *object,
404 int argc, const JsToken *argv, JsToken *retval)
405 : js_context_(js_context), object_(object),
406 argc_(argc), argv_(argv), retval_(retval),
407 is_exception_set_(false) {}
408 #elif BROWSER_IE
409 JsCallContext(DISPPARAMS FAR *disp_params, VARIANT FAR *retval,
410 EXCEPINFO FAR *excep_info)
411 : disp_params_(disp_params), retval_(retval), exception_info_(excep_info),
412 is_exception_set_(false) {}
413 #elif BROWSER_FF
414 JsCallContext(JsContextPtr cx, JsRunnerInterface *js_runner,
415 int argc, JsToken *argv, JsToken *retval);
416 #else
417 // TODO: browser_xyz
418 #endif
420 // Get the arguments a JavaScript caller has passed into a scriptable method
421 // of a native object. Returns the number of arguments successfully read
422 // (will bail at the first invalid argument).
423 int GetArguments(int argc, JsArgument *argv);
425 // Get the type of an argument that was passed in.
426 JsParamType GetArgumentType(int i);
428 // Sets the value to be returned to the calling JavaScript.
430 // The ModuleImplBaseClass* version should only be used when returning a
431 // JSPARAM_MODULE. It exists because passing a derived class through a void*
432 // and then casting to the base class is not safe - the compiler won't be able
433 // to correctly adjust the pointer offset.
435 // The int version is for use with JSPARAM_NULL, to avoid conflicting with the
436 // ModuleImplBaseClass version (works because NULL is defined as 0).
437 void SetReturnValue(JsParamType type, const void *value_ptr);
438 void SetReturnValue(JsParamType type, const ModuleImplBaseClass *value_ptr) {
439 assert(type == JSPARAM_MODULE);
440 SetReturnValue(type, reinterpret_cast<const void*>(value_ptr));
442 void SetReturnValue(JsParamType type, int) {
443 assert(type == JSPARAM_NULL);
444 SetReturnValue(type, reinterpret_cast<const void*>(NULL));
447 // Sets an exception to be thrown to the calling JavaScript. Setting an
448 // exception overrides any previous exception and any return values.
449 void SetException(const std::string16 &message);
451 JsContextPtr js_context() { return js_context_; }
452 bool is_exception_set() { return is_exception_set_; }
454 private:
455 JsContextPtr js_context_;
456 bool is_exception_set_;
457 #if BROWSER_NPAPI
458 NPObject *object_;
459 int argc_;
460 const JsToken *argv_;
461 JsToken *retval_;
462 #elif BROWSER_IE
463 DISPPARAMS FAR *disp_params_;
464 VARIANT FAR *retval_;
465 EXCEPINFO FAR *exception_info_;
466 #elif BROWSER_FF
467 int argc_;
468 JsToken *argv_;
469 JsToken *retval_;
470 JsRunnerInterface *js_runner_;
471 nsCOMPtr<nsIXPConnect> xpc_;
472 nsCOMPtr<nsIXPCNativeCallContext> ncc_;
473 #else
474 // TODO: browser_xyz
475 #endif
479 // Given a JsParamToSend, extract it into a JsScopedToken. Resulting token
480 // increases the reference count for objects.
481 void ConvertJsParamToToken(const JsParamToSend &param,
482 JsContextPtr context, JsScopedToken *token);
484 //-----------------------------------------------------------------------------
485 #if BROWSER_FF // the rest of this file only applies to Firefox, for now
487 // Helper class to extract JavaScript parameters (including optional params
488 // and varargs), in a way that hides differences between main-thread and
489 // worker-thread environments.
490 class JsParamFetcher {
491 public:
492 explicit JsParamFetcher(ModuleImplBaseClass *obj);
494 JsContextPtr GetContextPtr() { return js_context_; }
495 int GetCount(bool has_mysterious_retval) {
496 return has_mysterious_retval ? js_argc_ - 1 : js_argc_;
498 // In Firefox, set has_string_retval iff method has a string return value.
499 bool IsOptionalParamPresent(int i, bool has_string_retval);
501 // These functions coerce values using the JsTokenTo*() functions.
502 bool GetAsInt(int i, int *out);
503 bool GetAsString(int i, std::string16 *out);
504 bool GetAsBool(int i, bool *out);
505 bool GetAsDouble(int i, double *out);
506 bool GetAsArray(int i, JsArray *out);
507 bool GetAsObject(int i, JsObject *out);
509 // TODO(kevinww): Currently doesn't work in a worker thread because it uses
510 // XPConnect
511 bool GetAsModule(int i, nsISupports **out);
513 bool GetAsNewRootedCallback(int i, JsRootedCallback **out);
515 // Method to get the type of a parameter
516 JsParamType GetType(int i);
518 void SetReturnValue(JsToken retval);
520 private:
521 JsContextPtr js_context_;
522 int js_argc_;
523 JsToken *js_argv_;
524 JsToken *js_retval_;
526 nsCOMPtr<nsIXPConnect> xpc_;
527 nsCOMPtr<nsIXPCNativeCallContext> ncc_;
531 // Sets JavaScript exceptions, in a way that hides differences
532 // between main-thread and worker-thread environments.
533 // Returns the value the caller should return to the JavaScript host engine.
534 JsNativeMethodRetval JsSetException(JsContextPtr cx,
535 JsRunnerInterface *js_runner,
536 const char16 *message,
537 bool notify_native_call_context);
539 // Garbage collection helper functions
540 bool RootJsToken(JsContextPtr cx, JsToken t);
543 #endif // BROWSER_FF
544 //-----------------------------------------------------------------------------
547 #endif // GEARS_BASE_COMMON_JS_TYPES_H__