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