LCOV - code coverage report
Current view: top level - dom/base - nsJSUtils.h (source / functions) Hit Total Coverage
Test: output.info Lines: 20 36 55.6 %
Date: 2017-07-14 16:53:18 Functions: 11 14 78.6 %
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
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #ifndef nsJSUtils_h__
       8             : #define nsJSUtils_h__
       9             : 
      10             : /**
      11             :  * This is not a generated file. It contains common utility functions
      12             :  * invoked from the JavaScript code generated from IDL interfaces.
      13             :  * The goal of the utility functions is to cut down on the size of
      14             :  * the generated code itself.
      15             :  */
      16             : 
      17             : #include "mozilla/Assertions.h"
      18             : 
      19             : #include "GeckoProfiler.h"
      20             : #include "jsapi.h"
      21             : #include "jsfriendapi.h"
      22             : #include "js/Conversions.h"
      23             : #include "nsString.h"
      24             : 
      25             : class nsIScriptContext;
      26             : class nsIScriptGlobalObject;
      27             : 
      28             : namespace mozilla {
      29             : namespace dom {
      30             : class AutoJSAPI;
      31             : class Element;
      32             : } // namespace dom
      33             : } // namespace mozilla
      34             : 
      35             : class nsJSUtils
      36             : {
      37             : public:
      38             :   static bool GetCallingLocation(JSContext* aContext, nsACString& aFilename,
      39             :                                  uint32_t* aLineno = nullptr,
      40             :                                  uint32_t* aColumn = nullptr);
      41             :   static bool GetCallingLocation(JSContext* aContext, nsAString& aFilename,
      42             :                                  uint32_t* aLineno = nullptr,
      43             :                                  uint32_t* aColumn = nullptr);
      44             : 
      45             :   static nsIScriptGlobalObject *GetStaticScriptGlobal(JSObject* aObj);
      46             : 
      47             :   static nsIScriptContext *GetStaticScriptContext(JSObject* aObj);
      48             : 
      49             :   /**
      50             :    * Retrieve the inner window ID based on the given JSContext.
      51             :    *
      52             :    * @param JSContext aContext
      53             :    *        The JSContext from which you want to find the inner window ID.
      54             :    *
      55             :    * @returns uint64_t the inner window ID.
      56             :    */
      57             :   static uint64_t GetCurrentlyRunningCodeInnerWindowID(JSContext *aContext);
      58             : 
      59             :   static nsresult CompileFunction(mozilla::dom::AutoJSAPI& jsapi,
      60             :                                   JS::AutoObjectVector& aScopeChain,
      61             :                                   JS::CompileOptions& aOptions,
      62             :                                   const nsACString& aName,
      63             :                                   uint32_t aArgCount,
      64             :                                   const char** aArgArray,
      65             :                                   const nsAString& aBody,
      66             :                                   JSObject** aFunctionObject);
      67             : 
      68             : 
      69             :   // ExecutionContext is used to switch compartment.
      70             :   class MOZ_STACK_CLASS ExecutionContext {
      71             :     // Register stack annotations for the Gecko profiler.
      72             :     mozilla::AutoProfilerLabel mAutoProfilerLabel;
      73             : 
      74             :     JSContext* mCx;
      75             : 
      76             :     // Handles switching to our global's compartment.
      77             :     JSAutoCompartment mCompartment;
      78             : 
      79             :     // Set to a valid handle if a return value is expected.
      80             :     JS::Rooted<JS::Value> mRetValue;
      81             : 
      82             :     // Scope chain in which the execution takes place.
      83             :     JS::AutoObjectVector mScopeChain;
      84             : 
      85             :     // returned value forwarded when we have to interupt the execution eagerly
      86             :     // with mSkip.
      87             :     nsresult mRv;
      88             : 
      89             :     // Used to skip upcoming phases in case of a failure.  In such case the
      90             :     // result is carried by mRv.
      91             :     bool mSkip;
      92             : 
      93             :     // Should the result be serialized before being returned.
      94             :     bool mCoerceToString;
      95             : 
      96             :     // Encode the bytecode before it is being executed.
      97             :     bool mEncodeBytecode;
      98             : 
      99             : #ifdef DEBUG
     100             :     // Should we set the return value.
     101             :     bool mWantsReturnValue;
     102             : 
     103             :     bool mExpectScopeChain;
     104             : #endif
     105             : 
     106             :    public:
     107             : 
     108             :     // Enter compartment in which the code would be executed.  The JSContext
     109             :     // must come from an AutoEntryScript that has had
     110             :     // TakeOwnershipOfErrorReporting() called on it.
     111             :     ExecutionContext(JSContext* aCx, JS::Handle<JSObject*> aGlobal);
     112             : 
     113             :     ExecutionContext(const ExecutionContext&) = delete;
     114             :     ExecutionContext(ExecutionContext&&) = delete;
     115             : 
     116         234 :     ~ExecutionContext() {
     117             :       // This flag is resetted, when the returned value is extracted.
     118         117 :       MOZ_ASSERT(!mWantsReturnValue);
     119         117 :     }
     120             : 
     121             :     // The returned value would be converted to a string if the
     122             :     // |aCoerceToString| is flag set.
     123           0 :     ExecutionContext& SetCoerceToString(bool aCoerceToString) {
     124           0 :       mCoerceToString = aCoerceToString;
     125           0 :       return *this;
     126             :     }
     127             : 
     128             :     // When set, this flag records and encodes the bytecode as soon as it is
     129             :     // being compiled, and before it is being executed. The bytecode can then be
     130             :     // requested by using |JS::FinishIncrementalEncoding| with the mutable
     131             :     // handle |aScript| argument of |CompileAndExec| or |JoinAndExec|.
     132           5 :     ExecutionContext& SetEncodeBytecode(bool aEncodeBytecode) {
     133           5 :       mEncodeBytecode = aEncodeBytecode;
     134           5 :       return *this;
     135             :     }
     136             : 
     137             :     // Set the scope chain in which the code should be executed.
     138             :     void SetScopeChain(const JS::AutoObjectVector& aScopeChain);
     139             : 
     140             :     // Copy the returned value in the mutable handle argument, in case of a
     141             :     // evaluation failure either during the execution or the conversion of the
     142             :     // result to a string, the nsresult would be set to the corresponding result
     143             :     // code, and the mutable handle argument would remain unchanged.
     144             :     //
     145             :     // The value returned in the mutable handle argument is part of the
     146             :     // compartment given as argument to the ExecutionContext constructor. If the
     147             :     // caller is in a different compartment, then the out-param value should be
     148             :     // wrapped by calling |JS_WrapValue|.
     149             :     MOZ_MUST_USE nsresult
     150             :     ExtractReturnValue(JS::MutableHandle<JS::Value> aRetValue);
     151             : 
     152             :     // After getting a notification that an off-thread compilation terminated,
     153             :     // this function will take the result of the parser by moving it to the main
     154             :     // thread before starting the execution of the script.
     155             :     //
     156             :     // The compiled script would be returned in the |aScript| out-param.
     157             :     MOZ_MUST_USE nsresult JoinAndExec(void **aOffThreadToken,
     158             :                                       JS::MutableHandle<JSScript*> aScript);
     159             : 
     160             :     // Compile a script contained in a SourceBuffer, and execute it.
     161             :     nsresult CompileAndExec(JS::CompileOptions& aCompileOptions,
     162             :                             JS::SourceBufferHolder& aSrcBuf,
     163             :                             JS::MutableHandle<JSScript*> aScript);
     164             : 
     165             :     // Compile a script contained in a string, and execute it.
     166             :     nsresult CompileAndExec(JS::CompileOptions& aCompileOptions,
     167             :                             const nsAString& aScript);
     168             : 
     169             :     // Decode a script contained in a buffer, and execute it.
     170             :     MOZ_MUST_USE nsresult DecodeAndExec(JS::CompileOptions& aCompileOptions,
     171             :                                         mozilla::Vector<uint8_t>& aBytecodeBuf,
     172             :                                         size_t aBytecodeIndex);
     173             : 
     174             :     // After getting a notification that an off-thread decoding terminated, this
     175             :     // function will get the result of the decoder by moving it to the main
     176             :     // thread before starting the execution of the script.
     177             :     MOZ_MUST_USE nsresult DecodeJoinAndExec(void **aOffThreadToken);
     178             :   };
     179             : 
     180             :   static nsresult CompileModule(JSContext* aCx,
     181             :                                 JS::SourceBufferHolder& aSrcBuf,
     182             :                                 JS::Handle<JSObject*> aEvaluationGlobal,
     183             :                                 JS::CompileOptions &aCompileOptions,
     184             :                                 JS::MutableHandle<JSObject*> aModule);
     185             : 
     186             :   static nsresult ModuleDeclarationInstantiation(JSContext* aCx,
     187             :                                                  JS::Handle<JSObject*> aModule);
     188             : 
     189             :   static nsresult ModuleEvaluation(JSContext* aCx,
     190             :                                    JS::Handle<JSObject*> aModule);
     191             : 
     192             :   // Returns false if an exception got thrown on aCx.  Passing a null
     193             :   // aElement is allowed; that wil produce an empty aScopeChain.
     194             :   static bool GetScopeChainForElement(JSContext* aCx,
     195             :                                       mozilla::dom::Element* aElement,
     196             :                                       JS::AutoObjectVector& aScopeChain);
     197             : 
     198             :   static void ResetTimeZone();
     199             : };
     200             : 
     201             : template<typename T>
     202             : inline bool
     203        6326 : AssignJSString(JSContext *cx, T &dest, JSString *s)
     204             : {
     205        6326 :   size_t len = js::GetStringLength(s);
     206             :   static_assert(js::MaxStringLength < (1 << 28),
     207             :                 "Shouldn't overflow here or in SetCapacity");
     208        6326 :   if (MOZ_UNLIKELY(!dest.SetLength(len, mozilla::fallible))) {
     209           0 :     JS_ReportOutOfMemory(cx);
     210           0 :     return false;
     211             :   }
     212        6326 :   return js::CopyStringChars(cx, dest.BeginWriting(), s, len);
     213             : }
     214             : 
     215             : inline void
     216           0 : AssignJSFlatString(nsAString &dest, JSFlatString *s)
     217             : {
     218           0 :   size_t len = js::GetFlatStringLength(s);
     219             :   static_assert(js::MaxStringLength < (1 << 28),
     220             :                 "Shouldn't overflow here or in SetCapacity");
     221           0 :   dest.SetLength(len);
     222           0 :   js::CopyFlatStringChars(dest.BeginWriting(), s, len);
     223           0 : }
     224             : 
     225             : class nsAutoJSString : public nsAutoString
     226             : {
     227             : public:
     228             : 
     229             :   /**
     230             :    * nsAutoJSString should be default constructed, which leaves it empty
     231             :    * (this->IsEmpty()), and initialized with one of the init() methods below.
     232             :    */
     233        3671 :   nsAutoJSString() {}
     234             : 
     235        3671 :   bool init(JSContext* aContext, JSString* str)
     236             :   {
     237        3671 :     return AssignJSString(aContext, *this, str);
     238             :   }
     239             : 
     240          24 :   bool init(JSContext* aContext, const JS::Value &v)
     241             :   {
     242          24 :     if (v.isString()) {
     243          24 :       return init(aContext, v.toString());
     244             :     }
     245             : 
     246             :     // Stringify, making sure not to run script.
     247           0 :     JS::Rooted<JSString*> str(aContext);
     248           0 :     if (v.isObject()) {
     249           0 :       str = JS_NewStringCopyZ(aContext, "[Object]");
     250             :     } else {
     251           0 :       JS::Rooted<JS::Value> rootedVal(aContext, v);
     252           0 :       str = JS::ToString(aContext, rootedVal);
     253             :     }
     254             : 
     255           0 :     return str && init(aContext, str);
     256             :   }
     257             : 
     258          18 :   bool init(JSContext* aContext, jsid id)
     259             :   {
     260          36 :     JS::Rooted<JS::Value> v(aContext);
     261          36 :     return JS_IdToValue(aContext, id, &v) && init(aContext, v);
     262             :   }
     263             : 
     264             :   bool init(const JS::Value &v);
     265             : 
     266        3671 :   ~nsAutoJSString() {}
     267             : };
     268             : 
     269             : #endif /* nsJSUtils_h__ */

Generated by: LCOV version 1.13