ObjectWithStashedPointer.cpp (2418B)
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 #include "js/ObjectWithStashedPointer.h" 8 #include "jsapi.h" // JS_NewObject 9 #include "vm/JSContext.h" // CHECK_THREAD 10 11 namespace JS::detail { 12 13 static const size_t DATA_SLOT = 0; 14 static const size_t FREE_FUNC_SLOT = 1; 15 16 static void ObjectWithUntypedStashedPointerFinalize(JS::GCContext*, 17 JSObject* obj) { 18 AutoAssertNoGC nogc; 19 20 void* freeFunc = GetMaybePtrFromReservedSlot<void>(obj, FREE_FUNC_SLOT); 21 void* data = GetMaybePtrFromReservedSlot<void>(obj, DATA_SLOT); 22 23 reinterpret_cast<UntypedFreeFunction>(freeFunc)(data); 24 } 25 26 static const JSClassOps classOps = { 27 nullptr, // addProperty 28 nullptr, // delProperty 29 nullptr, // enumerate 30 nullptr, // newEnumerate 31 nullptr, // resolve 32 nullptr, // mayResolve 33 ObjectWithUntypedStashedPointerFinalize, 34 nullptr, // call 35 nullptr, // construct 36 nullptr, // trace 37 }; 38 39 static const JSClass DataOnlyClass = { 40 "Object", 41 JSCLASS_HAS_RESERVED_SLOTS(1), 42 }; 43 44 static const JSClass FreeFuncClass = { 45 "Object", 46 JSCLASS_HAS_RESERVED_SLOTS(2) | JSCLASS_FOREGROUND_FINALIZE, 47 &classOps, 48 }; 49 50 JSObject* NewObjectWithUntypedStashedPointer(JSContext* cx, void* ptr, 51 UntypedFreeFunction freeFunc) { 52 if (!freeFunc) { 53 JSObject* retval = JS_NewObject(cx, &DataOnlyClass); 54 if (!retval) { 55 return nullptr; 56 } 57 JS::SetReservedSlot(retval, DATA_SLOT, JS::PrivateValue(ptr)); 58 return retval; 59 } 60 61 JSObject* retval = JS_NewObject(cx, &FreeFuncClass); 62 if (!retval) { 63 return nullptr; 64 } 65 JS::SetReservedSlot(retval, DATA_SLOT, JS::PrivateValue(ptr)); 66 JS::SetReservedSlot(retval, FREE_FUNC_SLOT, 67 JS::PrivateValue(reinterpret_cast<void*>(freeFunc))); 68 return retval; 69 } 70 71 void* ObjectGetUntypedStashedPointer(JSContext* cx, JSObject* obj) { 72 MOZ_ASSERT( 73 obj->getClass() == &FreeFuncClass || obj->getClass() == &DataOnlyClass, 74 "wrong type of object"); 75 return JS::GetMaybePtrFromReservedSlot<void>(obj, DATA_SLOT); 76 } 77 78 } // namespace JS::detail