summaryrefslogtreecommitdiffstats
path: root/js/public/ValueArray.h
diff options
context:
space:
mode:
Diffstat (limited to 'js/public/ValueArray.h')
-rw-r--r--js/public/ValueArray.h130
1 files changed, 130 insertions, 0 deletions
diff --git a/js/public/ValueArray.h b/js/public/ValueArray.h
new file mode 100644
index 0000000000..0d520fb9b6
--- /dev/null
+++ b/js/public/ValueArray.h
@@ -0,0 +1,130 @@
+/* -*- 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()) {}
+
+ 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