ValueArray.h (4266B)
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 /** GC-safe representations of consecutive JS::Value in memory. */ 8 9 #ifndef js_ValueArray_h 10 #define js_ValueArray_h 11 12 #include "mozilla/Assertions.h" // MOZ_ASSERT 13 #include "mozilla/Attributes.h" // MOZ_IMPLICIT, MOZ_RAII 14 15 #include "js/CallArgs.h" // JS::CallArgs 16 #include "js/GCVector.h" // JS::RootedVector 17 #include "js/RootingAPI.h" // JS::AutoGCRooter, JS::{,Mutable}Handle 18 #include "js/Value.h" // JS::Value 19 20 namespace js { 21 JS_PUBLIC_API void TraceValueArray(JSTracer* trc, size_t length, 22 JS::Value* elements); 23 } // namespace js 24 25 namespace JS { 26 27 /* A fixed-size array of values, for use inside Rooted<>. */ 28 template <size_t N> 29 struct ValueArray { 30 Value elements[N]; 31 void trace(JSTracer* trc) { js::TraceValueArray(trc, N, elements); } 32 }; 33 34 /** RootedValueArray roots an internal fixed-size array of Values. */ 35 template <size_t N> 36 using RootedValueArray = Rooted<ValueArray<N>>; 37 38 /** 39 * A generic handle to an array of rooted values. 40 * 41 * The rooted array refernced can take several forms, therfore this is not the 42 * same as Handle<js::ValueArray>. 43 */ 44 class HandleValueArray { 45 const size_t length_; 46 const Value* const elements_; 47 48 HandleValueArray(size_t len, const Value* elements) 49 : length_(len), elements_(elements) {} 50 51 public: 52 explicit HandleValueArray(Handle<Value> value) 53 : length_(1), elements_(value.address()) {} 54 55 MOZ_IMPLICIT HandleValueArray(const RootedVector<Value>& values) 56 : length_(values.length()), elements_(values.begin()) {} 57 58 MOZ_IMPLICIT HandleValueArray(const PersistentRootedVector<Value>& values) 59 : length_(values.length()), elements_(values.begin()) {} 60 61 template <size_t N> 62 MOZ_IMPLICIT HandleValueArray(const RootedValueArray<N>& values) 63 : length_(N), elements_(values.begin()) {} 64 65 /** CallArgs must already be rooted somewhere up the stack. */ 66 MOZ_IMPLICIT HandleValueArray(const JS::CallArgs& args) 67 : length_(args.length()), elements_(args.array()) {} 68 69 /** Use with care! Only call this if the data is guaranteed to be marked. */ 70 static HandleValueArray fromMarkedLocation(size_t len, 71 const Value* elements) { 72 return HandleValueArray(len, elements); 73 } 74 75 static HandleValueArray subarray(const HandleValueArray& values, 76 size_t startIndex, size_t len) { 77 MOZ_ASSERT(startIndex + len <= values.length()); 78 return HandleValueArray(len, values.begin() + startIndex); 79 } 80 81 static HandleValueArray empty() { return HandleValueArray(0, nullptr); } 82 83 size_t length() const { return length_; } 84 const Value* begin() const { return elements_; } 85 86 Handle<Value> operator[](size_t i) const { 87 MOZ_ASSERT(i < length_); 88 return Handle<Value>::fromMarkedLocation(&elements_[i]); 89 } 90 }; 91 92 } // namespace JS 93 94 namespace js { 95 96 template <size_t N, typename Container> 97 class WrappedPtrOperations<JS::ValueArray<N>, Container> { 98 const JS::ValueArray<N>& array() const { 99 return static_cast<const Container*>(this)->get(); 100 } 101 102 public: 103 size_t length() const { return N; } 104 const JS::Value* begin() const { return array().elements; } 105 106 JS::HandleValue operator[](size_t i) const { 107 MOZ_ASSERT(i < N); 108 return JS::HandleValue::fromMarkedLocation(&array().elements[i]); 109 } 110 }; 111 112 template <size_t N, typename Container> 113 class MutableWrappedPtrOperations<JS::ValueArray<N>, Container> 114 : public WrappedPtrOperations<JS::ValueArray<N>, Container> { 115 using Base = WrappedPtrOperations<JS::ValueArray<N>, Container>; 116 JS::ValueArray<N>& array() { return static_cast<Container*>(this)->get(); } 117 118 public: 119 using Base::begin; 120 JS::Value* begin() { return array().elements; } 121 122 using Base::operator[]; 123 JS::MutableHandleValue operator[](size_t i) { 124 MOZ_ASSERT(i < N); 125 return JS::MutableHandleValue::fromMarkedLocation(&array().elements[i]); 126 } 127 }; 128 129 } // namespace js 130 131 #endif // js_ValueArray_h