Skip to content

Commit 59f8590

Browse files
committed
Bug 1719795 part 5 - Change JSCLASS_PRIVATE_IS_NSISUPPORTS JSClasses to use a reserved slot instead. r=mccr8,jonco
This is a step towards removing object private slots. Classes with JSCLASS_PRIVATE_IS_NSISUPPORTS now use JSCLASS_SLOT0_IS_NSISUPPORTS instead. For most classes this means we need to add an extra reserved slot and remove the private slot. Global objects (SimpleGlobalObject and the XPConnect BackstagePass and Sandbox globals) however can use the JSCLASS_GLOBAL_APPLICATION_SLOTS already there. These slots were only used for WebIDL DOM globals until now. Differential Revision: https://phabricator.services.mozilla.com/D119502
1 parent 5285ac8 commit 59f8590

20 files changed

+117
-73
lines changed

dom/bindings/SimpleGlobalObject.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
#include "jsapi.h"
1010
#include "js/Class.h"
11-
#include "js/Object.h" // JS::GetClass, JS::GetPrivate, JS::SetPrivate
11+
#include "js/Object.h" // JS::GetClass, JS::GetObjectISupports, JS::SetObjectISupports
1212

1313
#include "nsJSPrincipals.h"
1414
#include "nsThreadUtils.h"
@@ -76,9 +76,12 @@ static const JSClassOps SimpleGlobalClassOps = {
7676
static const js::ClassExtension SimpleGlobalClassExtension = {
7777
SimpleGlobal_moved};
7878

79+
static_assert(JSCLASS_GLOBAL_APPLICATION_SLOTS > 0,
80+
"Need at least one slot for JSCLASS_SLOT0_IS_NSISUPPORTS");
81+
7982
const JSClass SimpleGlobalClass = {"",
80-
JSCLASS_GLOBAL_FLAGS | JSCLASS_HAS_PRIVATE |
81-
JSCLASS_PRIVATE_IS_NSISUPPORTS |
83+
JSCLASS_GLOBAL_FLAGS |
84+
JSCLASS_SLOT0_IS_NSISUPPORTS |
8285
JSCLASS_FOREGROUND_FINALIZE,
8386
&SimpleGlobalClassOps,
8487
JS_NULL_CLASS_SPEC,
@@ -88,7 +91,7 @@ const JSClass SimpleGlobalClass = {"",
8891
static SimpleGlobalObject* GetSimpleGlobal(JSObject* global) {
8992
MOZ_ASSERT(JS::GetClass(global) == &SimpleGlobalClass);
9093

91-
return static_cast<SimpleGlobalObject*>(JS::GetPrivate(global));
94+
return JS::GetObjectISupports<SimpleGlobalObject>(global);
9295
}
9396

9497
// static
@@ -139,7 +142,7 @@ JSObject* SimpleGlobalObject::Create(GlobalType globalType,
139142
new SimpleGlobalObject(global, globalType);
140143

141144
// Pass on ownership of globalObject to |global|.
142-
JS::SetPrivate(global, globalObject.forget().take());
145+
JS::SetObjectISupports(global, globalObject.forget().take());
143146

144147
if (proto.isObjectOrNull()) {
145148
JS::Rooted<JSObject*> protoObj(cx, proto.toObjectOrNull());

js/public/Class.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -500,8 +500,8 @@ static const uint32_t JSCLASS_DELAY_METADATA_BUILDER = 1 << 1;
500500
// disposal mechanism.
501501
static const uint32_t JSCLASS_IS_WRAPPED_NATIVE = 1 << 2;
502502

503-
// Private is `nsISupports*`.
504-
static const uint32_t JSCLASS_PRIVATE_IS_NSISUPPORTS = 1 << 3;
503+
// First reserved slot is `PrivateValue(nsISupports*)` or `UndefinedValue`.
504+
static constexpr uint32_t JSCLASS_SLOT0_IS_NSISUPPORTS = 1 << 3;
505505

506506
// Objects are DOM.
507507
static const uint32_t JSCLASS_IS_DOMJSCLASS = 1 << 4;
@@ -706,6 +706,8 @@ struct alignas(js::gc::JSClassAlignBytes) JSClass {
706706

707707
bool isWrappedNative() const { return flags & JSCLASS_IS_WRAPPED_NATIVE; }
708708

709+
bool slot0IsISupports() const { return flags & JSCLASS_SLOT0_IS_NSISUPPORTS; }
710+
709711
static size_t offsetOfFlags() { return offsetof(JSClass, flags); }
710712

711713
// Internal / friend API accessors:

js/public/Object.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,31 @@ inline void SetReservedSlot(JSObject* obj, size_t slot, const Value& value) {
112112
}
113113
}
114114

115+
/**
116+
* Helper function to get the pointer value (or nullptr if not set) from the
117+
* object's first reserved slot. Must only be used for objects with a JSClass
118+
* that has the JSCLASS_SLOT0_IS_NSISUPPORTS flag.
119+
*/
120+
template <typename T>
121+
inline T* GetObjectISupports(JSObject* obj) {
122+
MOZ_ASSERT(GetClass(obj)->slot0IsISupports());
123+
Value v = GetReservedSlot(obj, 0);
124+
return v.isUndefined() ? nullptr : static_cast<T*>(v.toPrivate());
125+
}
126+
127+
/**
128+
* Helper function to store |PrivateValue(nsISupportsValue)| in the object's
129+
* first reserved slot. Must only be used for objects with a JSClass that has
130+
* the JSCLASS_SLOT0_IS_NSISUPPORTS flag.
131+
*
132+
* Note: the pointer is opaque to the JS engine (including the GC) so it's the
133+
* embedding's responsibility to trace or free this value.
134+
*/
135+
inline void SetObjectISupports(JSObject* obj, void* nsISupportsValue) {
136+
MOZ_ASSERT(GetClass(obj)->slot0IsISupports());
137+
SetReservedSlot(obj, 0, PrivateValue(nsISupportsValue));
138+
}
139+
115140
} // namespace JS
116141

117142
#endif // js_public_Object_h

js/src/builtin/streams/ReadableStream.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
#include "builtin/streams/ReadableStreamReader.h" // js::CreateReadableStream{BYOB,Default}Reader, js::ForAuthorCodeBool
2424
#include "builtin/streams/WritableStream.h" // js::WritableStream
2525
#include "js/CallArgs.h" // JS::CallArgs{,FromVp}
26-
#include "js/Class.h" // JSCLASS_PRIVATE_IS_NSISUPPORTS, JSCLASS_HAS_PRIVATE, JS_NULL_CLASS_OPS
26+
#include "js/Class.h" // JSCLASS_SLOT0_IS_NSISUPPORTS, JSCLASS_HAS_PRIVATE, JS_NULL_CLASS_OPS
2727
#include "js/Conversions.h" // JS::ToBoolean
2828
#include "js/friend/ErrorMessages.h" // js::GetErrorMessage, JSMSG_*
2929
#include "js/PropertySpec.h" // JS{Function,Property}Spec, JS_FN, JS_PSG, JS_{FS,PS}_END
@@ -543,7 +543,7 @@ static bool FinishReadableStreamClassInit(JSContext* cx, Handle<JSObject*> ctor,
543543
// This function and everything below should be replaced with
544544
//
545545
// JS_STREAMS_CLASS_SPEC(ReadableStream, 0, SlotCount, 0,
546-
// JSCLASS_PRIVATE_IS_NSISUPPORTS | JSCLASS_HAS_PRIVATE,
546+
// JSCLASS_SLOT0_IS_NSISUPPORTS,
547547
// JS_NULL_CLASS_OPS);
548548
//
549549
// when "pipeTo" is always enabled.
@@ -575,7 +575,7 @@ const JSClass ReadableStream::class_ = {
575575
"ReadableStream",
576576
JSCLASS_HAS_RESERVED_SLOTS(ReadableStream::SlotCount) |
577577
JSCLASS_HAS_CACHED_PROTO(JSProto_ReadableStream) |
578-
JSCLASS_PRIVATE_IS_NSISUPPORTS | JSCLASS_HAS_PRIVATE,
578+
JSCLASS_SLOT0_IS_NSISUPPORTS,
579579
JS_NULL_CLASS_OPS, &ReadableStream::classSpec_};
580580

581581
const JSClass ReadableStream::protoClass_ = {

js/src/builtin/streams/ReadableStream.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ class ReadableStream : public NativeObject {
4343
* stream's constructor and thus cannot be in a different compartment.
4444
*/
4545
enum Slots {
46+
/**
47+
* Optional pointer to make the stream participate in Gecko's cycle
48+
* collection. See also JSCLASS_SLOT0_IS_NSISUPPORTS.
49+
*/
50+
Slot_ISupports,
51+
4652
Slot_Controller,
4753
Slot_Reader,
4854
Slot_State,

js/src/builtin/streams/ReadableStreamOperations.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,9 @@ using JS::Value;
135135
return nullptr;
136136
}
137137

138-
stream->setPrivate(nsISupportsObject_alreadyAddreffed);
138+
static_assert(Slot_ISupports == 0,
139+
"Must use right slot for JSCLASS_SLOT0_IS_NSISUPPORTS");
140+
JS::SetObjectISupports(stream, nsISupportsObject_alreadyAddreffed);
139141

140142
// Step 1: Set stream.[[state]] to "readable".
141143
stream->initStateBits(Readable);

js/src/builtin/streams/StreamAPI.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
#include "js/experimental/TypedData.h" // JS_GetArrayBufferViewData, JS_NewUint8Array
2727
#include "js/friend/ErrorMessages.h" // js::GetErrorMessage, JSMSG_*
2828
#include "js/GCAPI.h" // JS::AutoCheckCannotGC, JS::AutoSuppressGCAnalysis
29-
#include "js/Object.h" // JS::SetPrivate
29+
#include "js/Object.h" // JS::SetObjectISupports
3030
#include "js/RootingAPI.h" // JS::{,Mutable}Handle, JS::Rooted
3131
#include "js/Stream.h" // JS::ReadableStreamUnderlyingSource
3232
#include "js/Value.h" // JS::{,Object,Undefined}Value
@@ -399,7 +399,7 @@ JS_PUBLIC_API bool JS::ReadableStreamUpdateDataAvailableFromSource(
399399

400400
JS_PUBLIC_API void JS::ReadableStreamReleaseCCObject(JSObject* streamObj) {
401401
MOZ_ASSERT(JS::IsReadableStream(streamObj));
402-
JS::SetPrivate(streamObj, nullptr);
402+
JS::SetObjectISupports(streamObj, nullptr);
403403
}
404404

405405
JS_PUBLIC_API bool JS::ReadableStreamTee(JSContext* cx,

js/src/builtin/streams/WritableStream.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
#include "builtin/streams/WritableStreamDefaultWriter.h" // js::CreateWritableStreamDefaultWriter
2020
#include "builtin/streams/WritableStreamOperations.h" // js::WritableStream{Abort,Close{,QueuedOrInFlight}}
2121
#include "js/CallArgs.h" // JS::CallArgs{,FromVp}
22-
#include "js/Class.h" // JS{Function,Property}Spec, JS_{FS,PS}_END, JSCLASS_PRIVATE_IS_NSISUPPORTS, JSCLASS_HAS_PRIVATE, JS_NULL_CLASS_OPS
22+
#include "js/Class.h" // JS{Function,Property}Spec, JS_{FS,PS}_END, JSCLASS_SLOT0_IS_NSISUPPORTS, JSCLASS_HAS_PRIVATE, JS_NULL_CLASS_OPS
2323
#include "js/friend/ErrorMessages.h" // js::GetErrorMessage, JSMSG_*
2424
#include "js/RealmOptions.h" // JS::RealmCreationOptions
2525
#include "js/RootingAPI.h" // JS::Handle, JS::Rooted
@@ -277,5 +277,4 @@ static const JSPropertySpec WritableStream_properties[] = {
277277
JS_PSG("locked", WritableStream_locked, 0), JS_PS_END};
278278

279279
JS_STREAMS_CLASS_SPEC(WritableStream, 0, SlotCount, 0,
280-
JSCLASS_PRIVATE_IS_NSISUPPORTS | JSCLASS_HAS_PRIVATE,
281-
JS_NULL_CLASS_OPS);
280+
JSCLASS_SLOT0_IS_NSISUPPORTS, JS_NULL_CLASS_OPS);

js/src/builtin/streams/WritableStream.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ class WritableStreamDefaultWriter;
3333
class WritableStream : public NativeObject {
3434
public:
3535
enum Slots {
36+
/**
37+
* Optional pointer to make the stream participate in Gecko's cycle
38+
* collection. See also JSCLASS_SLOT0_IS_NSISUPPORTS.
39+
*/
40+
Slot_ISupports,
41+
3642
/**
3743
* A WritableStream's associated controller is always created from under the
3844
* stream's constructor and thus cannot be in a different compartment.

js/src/builtin/streams/WritableStreamOperations.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,9 @@ using JS::Value;
7676
return nullptr;
7777
}
7878

79-
stream->setPrivate(nsISupportsObject_alreadyAddreffed);
79+
static_assert(Slot_ISupports == 0,
80+
"Must use right slot for JSCLASS_SLOT0_IS_NSISUPPORTS");
81+
JS::SetObjectISupports(stream, nsISupportsObject_alreadyAddreffed);
8082

8183
stream->initWritableState();
8284

0 commit comments

Comments
 (0)