LCOV - code coverage report
Current view: top level - js/xpconnect/loader - ScriptPreloader-inl.h (source / functions) Hit Total Coverage
Test: output.info Lines: 76 112 67.9 %
Date: 2017-07-14 16:53:18 Functions: 28 42 66.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*-  Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #ifndef ScriptPreloader_inl_h
       7             : #define ScriptPreloader_inl_h
       8             : 
       9             : #include "mozilla/Attributes.h"
      10             : #include "mozilla/Assertions.h"
      11             : #include "mozilla/CheckedInt.h"
      12             : #include "mozilla/EnumSet.h"
      13             : #include "mozilla/Range.h"
      14             : #include "mozilla/Result.h"
      15             : #include "mozilla/Unused.h"
      16             : #include "mozilla/dom/ScriptSettings.h"
      17             : #include "nsString.h"
      18             : #include "nsTArray.h"
      19             : 
      20             : #include <prio.h>
      21             : 
      22             : namespace mozilla {
      23             : 
      24             : // A specialization of GenericErrorResult which auto-converts to a nsresult.
      25             : // This should be removed when bug 1366511 is fixed.
      26             : template <>
      27             : class MOZ_MUST_USE_TYPE GenericErrorResult<nsresult>
      28             : {
      29             :   nsresult mErrorValue;
      30             : 
      31             :   template<typename V, typename E2> friend class Result;
      32             : 
      33             : public:
      34           0 :   explicit GenericErrorResult(nsresult aErrorValue) : mErrorValue(aErrorValue) {}
      35             : 
      36           0 :   operator nsresult() { return mErrorValue; }
      37             : };
      38             : 
      39             : namespace loader {
      40             : 
      41             : using mozilla::dom::AutoJSAPI;
      42             : 
      43           5 : struct MOZ_RAII AutoSafeJSAPI : public AutoJSAPI
      44             : {
      45           5 :     AutoSafeJSAPI() { Init(); }
      46             : };
      47             : 
      48             : static inline Result<Ok, nsresult>
      49         105 : WrapNSResult(PRStatus aRv)
      50             : {
      51         105 :     if (aRv != PR_SUCCESS) {
      52           0 :         return Err(NS_ERROR_FAILURE);
      53             :     }
      54         105 :     return Ok();
      55             : }
      56             : 
      57             : static inline Result<Ok, nsresult>
      58         115 : WrapNSResult(nsresult aRv)
      59             : {
      60         115 :     if (NS_FAILED(aRv)) {
      61           0 :         return Err(aRv);
      62             :     }
      63         115 :     return Ok();
      64             : }
      65             : 
      66             : #define NS_TRY(expr) MOZ_TRY(WrapNSResult(expr))
      67             : 
      68             : 
      69           0 : class OutputBuffer
      70             : {
      71             : public:
      72           0 :     OutputBuffer()
      73           0 :     {}
      74             : 
      75             :     uint8_t*
      76           0 :     write(size_t size)
      77             :     {
      78           0 :         auto buf = data.AppendElements(size);
      79           0 :         cursor_ += size;
      80           0 :         return buf;
      81             :     }
      82             : 
      83             :     void
      84           0 :     codeUint8(const uint8_t& val)
      85             :     {
      86           0 :         *write(sizeof val) = val;
      87           0 :     }
      88             : 
      89             :     template<typename T>
      90             :     void
      91           0 :     codeUint8(const EnumSet<T>& val)
      92             :     {
      93             :         // EnumSets are always represented as uint32_t values, so we need to
      94             :         // assert that the value actually fits in a uint8 before writing it.
      95           0 :         uint32_t value = val.serialize();
      96           0 :         codeUint8(CheckedUint8(value).value());
      97           0 :     }
      98             : 
      99             :     void
     100           0 :     codeUint16(const uint16_t& val)
     101             :     {
     102           0 :         LittleEndian::writeUint16(write(sizeof val), val);
     103           0 :     }
     104             : 
     105             :     void
     106           0 :     codeUint32(const uint32_t& val)
     107             :     {
     108           0 :         LittleEndian::writeUint32(write(sizeof val), val);
     109           0 :     }
     110             : 
     111             :     void
     112           0 :     codeString(const nsCString& str)
     113             :     {
     114           0 :         auto len = CheckedUint16(str.Length()).value();
     115             : 
     116           0 :         codeUint16(len);
     117           0 :         memcpy(write(len), str.BeginReading(), len);
     118           0 :     }
     119             : 
     120           0 :     size_t cursor() const { return cursor_; }
     121             : 
     122             : 
     123           0 :     uint8_t* Get() { return data.Elements(); }
     124             : 
     125             :     const uint8_t* Get() const { return data.Elements(); }
     126             : 
     127             : private:
     128             :     nsTArray<uint8_t> data;
     129             :     size_t cursor_ = 0;
     130             : };
     131             : 
     132             : class InputBuffer
     133             : {
     134             : public:
     135           4 :     explicit InputBuffer(const Range<uint8_t>& buffer)
     136           4 :         : data(buffer)
     137           4 :     {}
     138             : 
     139             :     const uint8_t*
     140        1428 :     read(size_t size)
     141             :     {
     142        1428 :         MOZ_ASSERT(checkCapacity(size));
     143             : 
     144        1428 :         auto buf = &data[cursor_];
     145        1428 :         cursor_ += size;
     146        1428 :         return buf;
     147             :     }
     148             : 
     149             :     bool
     150         204 :     codeUint8(uint8_t& val)
     151             :     {
     152         204 :         if (checkCapacity(sizeof val)) {
     153         204 :             val = *read(sizeof val);
     154             :         }
     155         204 :         return !error_;
     156             :     }
     157             : 
     158             :     template<typename T>
     159             :     bool
     160         204 :     codeUint8(EnumSet<T>& val)
     161             :     {
     162             :         uint8_t value;
     163         204 :         if (codeUint8(value)) {
     164         204 :             val.deserialize(value);
     165             :         }
     166         204 :         return !error_;
     167             :     }
     168             : 
     169             :     bool
     170         408 :     codeUint16(uint16_t& val)
     171             :     {
     172         408 :         if (checkCapacity(sizeof val)) {
     173         408 :             val = LittleEndian::readUint16(read(sizeof val));
     174             :         }
     175         408 :         return !error_;
     176             :     }
     177             : 
     178             :     bool
     179         408 :     codeUint32(uint32_t& val)
     180             :     {
     181         408 :         if (checkCapacity(sizeof val)) {
     182         408 :             val = LittleEndian::readUint32(read(sizeof val));
     183             :         }
     184         408 :         return !error_;
     185             :     }
     186             : 
     187             :     bool
     188         408 :     codeString(nsCString& str)
     189             :     {
     190             :         uint16_t len;
     191         408 :         if (codeUint16(len)) {
     192         408 :             if (checkCapacity(len)) {
     193         408 :                 str.SetLength(len);
     194         408 :                 memcpy(str.BeginWriting(), read(len), len);
     195             :             }
     196             :         }
     197         408 :         return !error_;
     198             :     }
     199             : 
     200           4 :     bool error() { return error_; }
     201             : 
     202         208 :     bool finished() { return error_ || !remainingCapacity(); }
     203             : 
     204        3064 :     size_t remainingCapacity() { return data.length() - cursor_; }
     205             : 
     206             :     size_t cursor() const { return cursor_; }
     207             : 
     208             :     const uint8_t* Get() const { return data.begin().get(); }
     209             : 
     210             : private:
     211             :     bool
     212        2856 :     checkCapacity(size_t size)
     213             :     {
     214        2856 :         if (size > remainingCapacity()) {
     215           0 :             error_ = true;
     216             :         }
     217        2856 :         return !error_;
     218             :     }
     219             : 
     220             :     bool error_ = false;
     221             : 
     222             : public:
     223             :     const Range<uint8_t>& data;
     224             :     size_t cursor_ = 0;
     225             : };
     226             : 
     227             : 
     228             : template <typename T> struct Matcher;
     229             : 
     230             : // Wraps the iterator for a nsTHashTable so that it may be used as a range
     231             : // iterator. Each iterator result acts as a smart pointer to the hash element,
     232             : // and has a Remove() method which will remove the element from the hash.
     233             : //
     234             : // It also accepts an optional Matcher instance against which to filter the
     235             : // elements which should be iterated over.
     236             : //
     237             : // Example:
     238             : //
     239             : //    for (auto& elem : HashElemIter<HashType>(hash)) {
     240             : //        if (elem->IsDead()) {
     241             : //            elem.Remove();
     242             : //        }
     243             : //    }
     244             : template <typename T>
     245           3 : class HashElemIter
     246             : {
     247             :     using Iterator = typename T::Iterator;
     248             :     using ElemType = typename T::UserDataType;
     249             : 
     250             :     T& hash_;
     251             :     Matcher<ElemType>* matcher_;
     252             :     Maybe<Iterator> iter_;
     253             : 
     254             : public:
     255           3 :     explicit HashElemIter(T& hash, Matcher<ElemType>* matcher = nullptr)
     256           3 :         : hash_(hash), matcher_(matcher)
     257             :     {
     258           3 :         iter_.emplace(Move(hash.Iter()));
     259           3 :     }
     260             : 
     261             :     class Elem
     262             :     {
     263             :         friend class HashElemIter<T>;
     264             : 
     265             :         HashElemIter<T>& iter_;
     266             :         bool done_;
     267             : 
     268           6 :         Elem(HashElemIter& iter, bool done)
     269           6 :             : iter_(iter), done_(done)
     270             :         {
     271           6 :             skipNonMatching();
     272           6 :         }
     273             : 
     274        1125 :         Iterator& iter() { return iter_.iter_.ref(); }
     275             : 
     276         293 :         void skipNonMatching()
     277             :         {
     278         293 :             if (iter_.matcher_) {
     279          44 :                 while (!done_ && !iter_.matcher_->Matches(get())) {
     280           0 :                     iter().Next();
     281           0 :                     done_ = iter().Done();
     282             :                 }
     283             :             }
     284         293 :         }
     285             : 
     286             :     public:
     287         287 :         Elem& operator*() { return *this; }
     288             : 
     289         557 :         ElemType get()
     290             :         {
     291         557 :           if (done_) {
     292           6 :             return nullptr;
     293             :           }
     294         551 :           return iter().Data();
     295             :         }
     296             : 
     297         509 :         ElemType operator->() { return get(); }
     298             : 
     299           0 :         operator ElemType() { return get(); }
     300             : 
     301           0 :         void Remove() { iter().Remove(); }
     302             : 
     303         287 :         Elem& operator++()
     304             :         {
     305         287 :             MOZ_ASSERT(!done_);
     306             : 
     307         287 :             iter().Next();
     308         287 :             done_ = iter().Done();
     309             : 
     310         287 :             skipNonMatching();
     311         287 :             return *this;
     312             :         }
     313             : 
     314         290 :         bool operator!=(Elem& other)
     315             :         {
     316         290 :             return done_ != other.done_ || this->get() != other.get();
     317             :         }
     318             :     };
     319             : 
     320           3 :     Elem begin() { return Elem(*this, iter_->Done()); }
     321             : 
     322           3 :     Elem end() { return Elem(*this, true); }
     323             : };
     324             : 
     325             : template <typename T>
     326           3 : HashElemIter<T> IterHash(T& hash, Matcher<typename T::UserDataType>* matcher = nullptr)
     327             : {
     328           3 :     return HashElemIter<T>(hash, matcher);
     329             : }
     330             : 
     331             : template <typename T, typename F>
     332             : bool
     333             : Find(T&& iter, F&& match)
     334             : {
     335             :     for (auto& elem : iter) {
     336             :         if (match(elem)) {
     337             :             return true;
     338             :         }
     339             :     }
     340             :     return false;
     341             : }
     342             : 
     343             : }; // namespace loader
     344             : }; // namespace mozilla
     345             : 
     346             : #endif // ScriptPreloader_inl_h

Generated by: LCOV version 1.13