LCOV - code coverage report
Current view: top level - dom/bindings - ToJSValue.h (source / functions) Hit Total Coverage
Test: output.info Lines: 10 53 18.9 %
Date: 2018-08-07 16:35:00 Functions: 0 0 -
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
       5             :  * You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #ifndef mozilla_dom_ToJSValue_h
       8             : #define mozilla_dom_ToJSValue_h
       9             : 
      10             : #include "mozilla/TypeTraits.h"
      11             : #include "mozilla/Assertions.h"
      12             : #include "mozilla/UniquePtr.h"
      13             : #include "mozilla/dom/BindingUtils.h"
      14             : #include "mozilla/dom/NonRefcountedDOMObject.h"
      15             : #include "mozilla/dom/TypedArray.h"
      16             : #include "jsapi.h"
      17             : #include "nsISupports.h"
      18             : #include "nsTArray.h"
      19             : #include "nsWrapperCache.h"
      20             : #include "nsAutoPtr.h"
      21             : 
      22             : namespace mozilla {
      23             : namespace dom {
      24             : 
      25             : class Promise;
      26             : 
      27             : // If ToJSValue returns false, it must set an exception on the
      28             : // JSContext.
      29             : 
      30             : // Accept strings.
      31             : MOZ_MUST_USE bool
      32             : ToJSValue(JSContext* aCx,
      33             :           const nsAString& aArgument,
      34             :           JS::MutableHandle<JS::Value> aValue);
      35             : 
      36             : // Accept booleans.  But be careful here: if we just have a function that takes
      37             : // a boolean argument, then any pointer that doesn't match one of our other
      38             : // signatures/templates will get treated as a boolean, which is clearly not
      39             : // desirable.  So make this a template that only gets used if the argument type
      40             : // is actually boolean
      41             : template<typename T>
      42             : MOZ_MUST_USE
      43             : typename EnableIf<IsSame<T, bool>::value, bool>::Type
      44           0 : ToJSValue(JSContext* aCx,
      45             :           T aArgument,
      46             :           JS::MutableHandle<JS::Value> aValue)
      47             : {
      48             :   // Make sure we're called in a compartment
      49           0 :   MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx));
      50             : 
      51           0 :   aValue.setBoolean(aArgument);
      52           0 :   return true;
      53             : }
      54             : 
      55             : // Accept integer types
      56             : inline bool
      57           0 : ToJSValue(JSContext* aCx,
      58             :           int32_t aArgument,
      59             :           JS::MutableHandle<JS::Value> aValue)
      60             : {
      61             :   // Make sure we're called in a compartment
      62           0 :   MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx));
      63             : 
      64           0 :   aValue.setInt32(aArgument);
      65           0 :   return true;
      66             : }
      67             : 
      68             : inline bool
      69           0 : ToJSValue(JSContext* aCx,
      70             :           uint32_t aArgument,
      71             :           JS::MutableHandle<JS::Value> aValue)
      72             : {
      73             :   // Make sure we're called in a compartment
      74           0 :   MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx));
      75             : 
      76           0 :   aValue.setNumber(aArgument);
      77           0 :   return true;
      78             : }
      79             : 
      80             : inline bool
      81             : ToJSValue(JSContext* aCx,
      82             :           int64_t aArgument,
      83             :           JS::MutableHandle<JS::Value> aValue)
      84             : {
      85             :   // Make sure we're called in a compartment
      86             :   MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx));
      87             : 
      88             :   aValue.setNumber(double(aArgument));
      89             :   return true;
      90             : }
      91             : 
      92             : inline bool
      93             : ToJSValue(JSContext* aCx,
      94             :           uint64_t aArgument,
      95             :           JS::MutableHandle<JS::Value> aValue)
      96             : {
      97             :   // Make sure we're called in a compartment
      98             :   MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx));
      99             : 
     100             :   aValue.setNumber(double(aArgument));
     101             :   return true;
     102             : }
     103             : 
     104             : // accept floating point types
     105             : inline bool
     106             : ToJSValue(JSContext* aCx,
     107             :           float aArgument,
     108             :           JS::MutableHandle<JS::Value> aValue)
     109             : {
     110             :   // Make sure we're called in a compartment
     111             :   MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx));
     112             : 
     113             :   aValue.setNumber(aArgument);
     114             :   return true;
     115             : }
     116             : 
     117             : inline bool
     118           0 : ToJSValue(JSContext* aCx,
     119             :           double aArgument,
     120             :           JS::MutableHandle<JS::Value> aValue)
     121             : {
     122             :   // Make sure we're called in a compartment
     123           0 :   MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx));
     124             : 
     125           0 :   aValue.setNumber(aArgument);
     126           0 :   return true;
     127             : }
     128             : 
     129             : // Accept CallbackObjects
     130             : MOZ_MUST_USE inline bool
     131             : ToJSValue(JSContext* aCx,
     132             :           CallbackObject& aArgument,
     133             :           JS::MutableHandle<JS::Value> aValue)
     134             : {
     135             :   // Make sure we're called in a compartment
     136             :   MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx));
     137             : 
     138             :   aValue.setObjectOrNull(aArgument.Callback(aCx));
     139             : 
     140             :   return MaybeWrapValue(aCx, aValue);
     141             : }
     142             : 
     143             : // Accept objects that inherit from nsWrapperCache (e.g. most
     144             : // DOM objects).
     145             : template <class T>
     146             : MOZ_MUST_USE
     147             : typename EnableIf<IsBaseOf<nsWrapperCache, T>::value, bool>::Type
     148         210 : ToJSValue(JSContext* aCx,
     149             :           T& aArgument,
     150             :           JS::MutableHandle<JS::Value> aValue)
     151             : {
     152             :   // Make sure we're called in a compartment
     153         210 :   MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx));
     154             : 
     155         420 :   return GetOrCreateDOMReflector(aCx, aArgument, aValue);
     156             : }
     157             : 
     158             : // Accept non-refcounted DOM objects that do not inherit from
     159             : // nsWrapperCache.  Refcounted ones would be too much of a footgun:
     160             : // you could convert them to JS twice and get two different objects.
     161             : namespace binding_detail {
     162             : template<class T>
     163             : MOZ_MUST_USE
     164             : typename EnableIf<IsBaseOf<NonRefcountedDOMObject, T>::value, bool>::Type
     165             : ToJSValueFromPointerHelper(JSContext* aCx,
     166             :                            T* aArgument,
     167             :                            JS::MutableHandle<JS::Value> aValue)
     168             : {
     169             :   // Make sure we're called in a compartment
     170             :   MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx));
     171             : 
     172             :   // This is a cut-down version of
     173             :   // WrapNewBindingNonWrapperCachedObject that doesn't need to deal
     174             :   // with nearly as many cases.
     175             :   if (!aArgument) {
     176             :     aValue.setNull();
     177             :     return true;
     178             :   }
     179             : 
     180             :   JS::Rooted<JSObject*> obj(aCx);
     181             :   if (!aArgument->WrapObject(aCx, nullptr, &obj)) {
     182             :     return false;
     183             :   }
     184             : 
     185             :   aValue.setObject(*obj);
     186             :   return true;
     187             : }
     188             : } // namespace binding_detail
     189             : 
     190             : // We can take a non-refcounted non-wrapper-cached DOM object that lives in an
     191             : // nsAutoPtr.
     192             : template<class T>
     193             : MOZ_MUST_USE
     194             : typename EnableIf<IsBaseOf<NonRefcountedDOMObject, T>::value, bool>::Type
     195             : ToJSValue(JSContext* aCx,
     196             :           nsAutoPtr<T>&& aArgument,
     197             :           JS::MutableHandle<JS::Value> aValue)
     198             : {
     199             :   if (!binding_detail::ToJSValueFromPointerHelper(aCx, aArgument.get(), aValue)) {
     200             :     return false;
     201             :   }
     202             : 
     203             :   // JS object took ownership
     204             :   aArgument.forget();
     205             :   return true;
     206             : }
     207             : 
     208             : // We can take a non-refcounted non-wrapper-cached DOM object that lives in a
     209             : // UniquePtr.
     210             : template<class T>
     211             : MOZ_MUST_USE
     212             : typename EnableIf<IsBaseOf<NonRefcountedDOMObject, T>::value, bool>::Type
     213             : ToJSValue(JSContext* aCx,
     214             :           UniquePtr<T>&& aArgument,
     215             :           JS::MutableHandle<JS::Value> aValue)
     216             : {
     217             :   if (!binding_detail::ToJSValueFromPointerHelper(aCx, aArgument.get(), aValue)) {
     218             :     return false;
     219             :   }
     220             : 
     221             :   // JS object took ownership
     222             :   Unused << aArgument.release();
     223             :   return true;
     224             : }
     225             : 
     226             : // Accept typed arrays built from appropriate nsTArray values
     227             : template<typename T>
     228             : MOZ_MUST_USE
     229             : typename EnableIf<IsBaseOf<AllTypedArraysBase, T>::value, bool>::Type
     230           0 : ToJSValue(JSContext* aCx,
     231             :           const TypedArrayCreator<T>& aArgument,
     232             :           JS::MutableHandle<JS::Value> aValue)
     233             : {
     234             :   // Make sure we're called in a compartment
     235           0 :   MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx));
     236             : 
     237           0 :   JSObject* obj = aArgument.Create(aCx);
     238           0 :   if (!obj) {
     239             :     return false;
     240             :   }
     241           0 :   aValue.setObject(*obj);
     242           0 :   return true;
     243             : }
     244             : 
     245             : // Accept objects that inherit from nsISupports but not nsWrapperCache (e.g.
     246             : // DOM File).
     247             : template <class T>
     248             : MOZ_MUST_USE
     249             : typename EnableIf<!IsBaseOf<nsWrapperCache, T>::value &&
     250             :                   !IsBaseOf<CallbackObject, T>::value &&
     251             :                   IsBaseOf<nsISupports, T>::value, bool>::Type
     252          61 : ToJSValue(JSContext* aCx,
     253             :           T& aArgument,
     254             :           JS::MutableHandle<JS::Value> aValue)
     255             : {
     256             :   // Make sure we're called in a compartment
     257          61 :   MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx));
     258             : 
     259           0 :   xpcObjectHelper helper(ToSupports(&aArgument));
     260         122 :   JS::Rooted<JSObject*> scope(aCx, JS::CurrentGlobalOrNull(aCx));
     261         122 :   return XPCOMObjectToJsval(aCx, scope, helper, nullptr, true, aValue);
     262             : }
     263             : 
     264             : // Accept nsRefPtr/nsCOMPtr
     265             : template <typename T>
     266             : MOZ_MUST_USE bool
     267           0 : ToJSValue(JSContext* aCx,
     268             :           const nsCOMPtr<T>& aArgument,
     269             :           JS::MutableHandle<JS::Value> aValue)
     270             : {
     271           0 :   return ToJSValue(aCx, *aArgument.get(), aValue);
     272             : }
     273             : 
     274             : template <typename T>
     275             : MOZ_MUST_USE bool
     276          79 : ToJSValue(JSContext* aCx,
     277             :           const RefPtr<T>& aArgument,
     278             :           JS::MutableHandle<JS::Value> aValue)
     279             : {
     280          79 :   return ToJSValue(aCx, *aArgument.get(), aValue);
     281             : }
     282             : 
     283             : template <typename T>
     284             : MOZ_MUST_USE bool
     285           0 : ToJSValue(JSContext* aCx,
     286             :           const NonNull<T>& aArgument,
     287             :           JS::MutableHandle<JS::Value> aValue)
     288             : {
     289           0 :   return ToJSValue(aCx, *aArgument.get(), aValue);
     290             : }
     291             : 
     292             : // Accept WebIDL dictionaries
     293             : template <class T>
     294             : MOZ_MUST_USE
     295             : typename EnableIf<IsBaseOf<DictionaryBase, T>::value, bool>::Type
     296             : ToJSValue(JSContext* aCx,
     297             :           const T& aArgument,
     298             :           JS::MutableHandle<JS::Value> aValue)
     299             : {
     300           0 :   return aArgument.ToObjectInternal(aCx, aValue);
     301             : }
     302             : 
     303             : // Accept existing JS values (which may not be same-compartment with us
     304             : MOZ_MUST_USE inline bool
     305             : ToJSValue(JSContext* aCx, const JS::Value& aArgument,
     306             :           JS::MutableHandle<JS::Value> aValue)
     307             : {
     308             :   aValue.set(aArgument);
     309             :   return MaybeWrapValue(aCx, aValue);
     310             : }
     311             : MOZ_MUST_USE inline bool
     312           0 : ToJSValue(JSContext* aCx, JS::Handle<JS::Value> aArgument,
     313             :           JS::MutableHandle<JS::Value> aValue)
     314             : {
     315           0 :   aValue.set(aArgument);
     316           0 :   return MaybeWrapValue(aCx, aValue);
     317             : }
     318             : 
     319             : // Accept existing JS values on the Heap (which may not be same-compartment with us
     320             : MOZ_MUST_USE inline bool
     321           0 : ToJSValue(JSContext* aCx, const JS::Heap<JS::Value>& aArgument,
     322             :           JS::MutableHandle<JS::Value> aValue)
     323             : {
     324           0 :   aValue.set(aArgument);
     325           0 :   return MaybeWrapValue(aCx, aValue);
     326             : }
     327             : 
     328             : // Accept existing rooted JS values (which may not be same-compartment with us
     329             : MOZ_MUST_USE inline bool
     330           0 : ToJSValue(JSContext* aCx, const JS::Rooted<JS::Value>& aArgument,
     331             :           JS::MutableHandle<JS::Value> aValue)
     332             : {
     333          50 :   aValue.set(aArgument);
     334           0 :   return MaybeWrapValue(aCx, aValue);
     335             : }
     336             : 
     337             : // Accept existing rooted JS objects (which may not be same-compartment with
     338             : // us).
     339             : MOZ_MUST_USE inline bool
     340           0 : ToJSValue(JSContext* aCx, const JS::Rooted<JSObject*>& aArgument,
     341             :           JS::MutableHandle<JS::Value> aValue)
     342             : {
     343           0 :   aValue.setObjectOrNull(aArgument);
     344           0 :   return MaybeWrapObjectOrNullValue(aCx, aValue);
     345             : }
     346             : 
     347             : // Accept nsresult, for use in rejections, and create an XPCOM
     348             : // exception object representing that nsresult.
     349             : MOZ_MUST_USE bool
     350             : ToJSValue(JSContext* aCx,
     351             :           nsresult aArgument,
     352             :           JS::MutableHandle<JS::Value> aValue);
     353             : 
     354             : // Accept ErrorResult, for use in rejections, and create an exception
     355             : // representing the failure.  Note, the ErrorResult must indicate a failure
     356             : // with aArgument.Failure() returning true.
     357             : MOZ_MUST_USE bool
     358             : ToJSValue(JSContext* aCx,
     359             :           ErrorResult& aArgument,
     360             :           JS::MutableHandle<JS::Value> aValue);
     361             : 
     362             : // Accept owning WebIDL unions.
     363             : template <typename T>
     364             : MOZ_MUST_USE
     365             : typename EnableIf<IsBaseOf<AllOwningUnionBase, T>::value, bool>::Type
     366           0 : ToJSValue(JSContext* aCx,
     367             :           const T& aArgument,
     368             :           JS::MutableHandle<JS::Value> aValue)
     369             : {
     370           0 :   JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));
     371           0 :   return aArgument.ToJSVal(aCx, global, aValue);
     372             : }
     373             : 
     374             : // Accept pointers to other things we accept
     375             : template <typename T>
     376             : MOZ_MUST_USE
     377             : typename EnableIf<IsPointer<T>::value, bool>::Type
     378             : ToJSValue(JSContext* aCx,
     379             :           T aArgument,
     380             :           JS::MutableHandle<JS::Value> aValue)
     381             : {
     382           0 :   return ToJSValue(aCx, *aArgument, aValue);
     383             : }
     384             : 
     385             : // Accept Promise objects, which need special handling.
     386             : MOZ_MUST_USE bool
     387             : ToJSValue(JSContext* aCx,
     388             :           Promise& aArgument,
     389             :           JS::MutableHandle<JS::Value> aValue);
     390             : 
     391             : // Accept arrays (and nested arrays) of other things we accept
     392             : template <typename T>
     393             : MOZ_MUST_USE bool
     394             : ToJSValue(JSContext* aCx,
     395             :           T* aArguments,
     396             :           size_t aLength,
     397             :           JS::MutableHandle<JS::Value> aValue);
     398             : 
     399             : template <typename T>
     400             : MOZ_MUST_USE bool
     401             : ToJSValue(JSContext* aCx,
     402             :           const nsTArray<T>& aArgument,
     403             :           JS::MutableHandle<JS::Value> aValue)
     404             : {
     405             :   return ToJSValue(aCx, aArgument.Elements(),
     406             :                    aArgument.Length(), aValue);
     407             : }
     408             : 
     409             : template <typename T>
     410             : MOZ_MUST_USE bool
     411             : ToJSValue(JSContext* aCx,
     412             :           const FallibleTArray<T>& aArgument,
     413             :           JS::MutableHandle<JS::Value> aValue)
     414             : {
     415             :   return ToJSValue(aCx, aArgument.Elements(),
     416             :                    aArgument.Length(), aValue);
     417             : }
     418             : 
     419             : template <typename T, int N>
     420             : MOZ_MUST_USE bool
     421             : ToJSValue(JSContext* aCx,
     422             :           const T(&aArgument)[N],
     423             :           JS::MutableHandle<JS::Value> aValue)
     424             : {
     425             :   return ToJSValue(aCx, aArgument, N, aValue);
     426             : }
     427             : 
     428             : // Accept arrays of other things we accept
     429             : template <typename T>
     430             : MOZ_MUST_USE bool
     431             : ToJSValue(JSContext* aCx,
     432             :           T* aArguments,
     433             :           size_t aLength,
     434             :           JS::MutableHandle<JS::Value> aValue)
     435             : {
     436             :   // Make sure we're called in a compartment
     437             :   MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx));
     438             : 
     439             :   JS::AutoValueVector v(aCx);
     440             :   if (!v.resize(aLength)) {
     441             :     return false;
     442             :   }
     443             :   for (size_t i = 0; i < aLength; ++i) {
     444             :     if (!ToJSValue(aCx, aArguments[i], v[i])) {
     445             :       return false;
     446             :     }
     447             :   }
     448             :   JSObject* arrayObj = JS_NewArrayObject(aCx, v);
     449             :   if (!arrayObj) {
     450             :     return false;
     451             :   }
     452             :   aValue.setObject(*arrayObj);
     453             :   return true;
     454             : }
     455             : 
     456             : } // namespace dom
     457             : } // namespace mozilla
     458             : 
     459             : #endif /* mozilla_dom_ToJSValue_h */

Generated by: LCOV version 1.13-14-ga5dd952