/* -*- 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 // 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 struct ValueArray { Value elements[N]; void trace(JSTracer* trc) { js::TraceValueArray(trc, N, elements); } }; /** RootedValueArray roots an internal fixed-size array of Values. */ template using RootedValueArray = Rooted>; /** * 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. */ 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) : length_(1), elements_(value.address()) {} MOZ_IMPLICIT HandleValueArray(const RootedVector& values) : length_(values.length()), elements_(values.begin()) {} template MOZ_IMPLICIT HandleValueArray(const RootedValueArray& 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 operator[](size_t i) const { MOZ_ASSERT(i < length_); return Handle::fromMarkedLocation(&elements_[i]); } }; } // namespace JS namespace js { template class WrappedPtrOperations, Container> { const JS::ValueArray& array() const { return static_cast(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 class MutableWrappedPtrOperations, Container> : public WrappedPtrOperations, Container> { using Base = WrappedPtrOperations, Container>; JS::ValueArray& array() { return static_cast(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