ObjectWithStashedPointer.h (2491B)
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 #ifndef js_public_ObjectWithStashedPointer_h 8 #define js_public_ObjectWithStashedPointer_h 9 10 #include "jstypes.h" // JS_PUBLIC_API 11 12 #include "js/RootingAPI.h" // JS::Handle 13 14 struct JS_PUBLIC_API JSContext; 15 class JS_PUBLIC_API JSObject; 16 17 namespace JS { 18 19 namespace detail { 20 using UntypedFreeFunction = void (*)(void*); 21 22 extern JS_PUBLIC_API JSObject* NewObjectWithUntypedStashedPointer( 23 JSContext* cx, void* ptr, UntypedFreeFunction freeFunc); 24 25 extern JS_PUBLIC_API void* ObjectGetUntypedStashedPointer(JSContext* cx, 26 JSObject* obj); 27 } // namespace detail 28 29 /** 30 * Convenience function for creating a JS object that has an embedder C++ 31 * pointer stashed in it. The JS object assumes ownership of the pointer. When 32 * the JS object is finalized, freeFunc will be called on the pointer to free 33 * it. 34 * 35 * The pointer is not known to the garbage collector, and not traced. If it 36 * points to a GC thing, the embedder is responsible for tracing it manually. 37 * 38 * freeFunc must not call any JSAPI functions that could cause a garbage 39 * collection. 40 */ 41 template <typename T, typename F> 42 inline JSObject* NewObjectWithStashedPointer(JSContext* cx, T* ptr, 43 F freeFunc) { 44 using FreeFunction = void (*)(T*); 45 static_assert(std::is_convertible_v<F, FreeFunction>, 46 "free function is not of a compatible type"); 47 return detail::NewObjectWithUntypedStashedPointer( 48 cx, ptr, 49 reinterpret_cast<detail::UntypedFreeFunction>( 50 static_cast<FreeFunction>(freeFunc))); 51 } 52 53 /** 54 * As above, but without a free function for the pointer. 55 */ 56 template <typename T> 57 inline JSObject* NewObjectWithStashedPointer(JSContext* cx, T* ptr) { 58 return detail::NewObjectWithUntypedStashedPointer(cx, ptr, nullptr); 59 } 60 61 /** 62 * Retrieve the stashed pointer from an object created using 63 * NewObjectWithStashedPointer(). 64 */ 65 template <typename T> 66 inline T* ObjectGetStashedPointer(JSContext* cx, JSObject* obj) { 67 return static_cast<T*>(detail::ObjectGetUntypedStashedPointer(cx, obj)); 68 } 69 70 } // namespace JS 71 72 #endif // js_public_ObjectWithStashedPointer_h