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/. */
7 #include "vm/StencilObject.h"
9 #include "mozilla/Assertions.h" // MOZ_ASSERT
10 #include "mozilla/PodOperations.h" // mozilla::PodCopy
12 #include <stddef.h> // size_t
13 #include <stdint.h> // uint8_t, INT32_MAX
15 #include "jsapi.h" // JS_NewObject
16 #include "js/Class.h" // JSClassOps, JSClass, JSCLASS_*
17 #include "js/ErrorReport.h" // JS_ReportErrorASCII
18 #include "js/experimental/JSStencil.h" // JS::Stencil, JS::StencilAddRef, JS::StencilRelease
19 #include "js/RootingAPI.h" // JS::Rooted
20 #include "js/Utility.h" // js_free
21 #include "vm/JSContext.h" // JSContext
22 #include "vm/JSObject.h" // JSObject
26 /*static */ const JSClassOps
StencilObject::classOps_
= {
27 nullptr, // addProperty
28 nullptr, // delProperty
30 nullptr, // newEnumerate
32 nullptr, // mayResolve
33 StencilObject::finalize
, // finalize
39 /*static */ const JSClass
StencilObject::class_
= {
41 JSCLASS_HAS_RESERVED_SLOTS(StencilObject::ReservedSlots
) |
42 JSCLASS_BACKGROUND_FINALIZE
,
43 &StencilObject::classOps_
};
45 bool StencilObject::hasStencil() const {
46 // The stencil may not be present yet if we GC during initialization.
47 return !getReservedSlot(StencilSlot
).isUndefined();
50 JS::Stencil
* StencilObject::stencil() const {
51 void* ptr
= getReservedSlot(StencilSlot
).toPrivate();
53 return static_cast<JS::Stencil
*>(ptr
);
56 /* static */ StencilObject
* StencilObject::create(JSContext
* cx
,
57 RefPtr
<JS::Stencil
> stencil
) {
58 JS::Rooted
<JSObject
*> obj(cx
, JS_NewObject(cx
, &class_
));
63 obj
->as
<StencilObject
>().setReservedSlot(
64 StencilSlot
, PrivateValue(stencil
.forget().take()));
66 return &obj
->as
<StencilObject
>();
69 /* static */ void StencilObject::finalize(JS::GCContext
* gcx
, JSObject
* obj
) {
70 if (obj
->as
<StencilObject
>().hasStencil()) {
71 JS::StencilRelease(obj
->as
<StencilObject
>().stencil());
75 /*static */ const JSClassOps
StencilXDRBufferObject::classOps_
= {
76 nullptr, // addProperty
77 nullptr, // delProperty
79 nullptr, // newEnumerate
81 nullptr, // mayResolve
82 StencilXDRBufferObject::finalize
, // finalize
88 /*static */ const JSClass
StencilXDRBufferObject::class_
= {
89 "StencilXDRBufferObject",
90 JSCLASS_HAS_RESERVED_SLOTS(StencilXDRBufferObject::ReservedSlots
) |
91 JSCLASS_BACKGROUND_FINALIZE
,
92 &StencilXDRBufferObject::classOps_
};
94 bool StencilXDRBufferObject::hasBuffer() const {
95 // The stencil may not be present yet if we GC during initialization.
96 return !getReservedSlot(BufferSlot
).isUndefined();
99 const uint8_t* StencilXDRBufferObject::buffer() const {
100 void* ptr
= getReservedSlot(BufferSlot
).toPrivate();
102 return static_cast<const uint8_t*>(ptr
);
105 uint8_t* StencilXDRBufferObject::writableBuffer() {
106 void* ptr
= getReservedSlot(BufferSlot
).toPrivate();
108 return static_cast<uint8_t*>(ptr
);
111 size_t StencilXDRBufferObject::bufferLength() const {
112 return getReservedSlot(LengthSlot
).toInt32();
115 /* static */ StencilXDRBufferObject
* StencilXDRBufferObject::create(
116 JSContext
* cx
, uint8_t* buffer
, size_t length
) {
117 if (length
>= INT32_MAX
) {
118 JS_ReportErrorASCII(cx
, "XDR buffer is too long");
122 JS::Rooted
<JSObject
*> obj(cx
, JS_NewObject(cx
, &class_
));
127 auto ownedBuffer
= cx
->make_pod_array
<uint8_t>(length
);
132 mozilla::PodCopy(ownedBuffer
.get(), buffer
, length
);
134 obj
->as
<StencilXDRBufferObject
>().setReservedSlot(
135 BufferSlot
, PrivateValue(ownedBuffer
.release()));
136 obj
->as
<StencilXDRBufferObject
>().setReservedSlot(LengthSlot
,
139 return &obj
->as
<StencilXDRBufferObject
>();
142 /* static */ void StencilXDRBufferObject::finalize(JS::GCContext
* gcx
,
144 if (obj
->as
<StencilXDRBufferObject
>().hasBuffer()) {
145 js_free(obj
->as
<StencilXDRBufferObject
>().writableBuffer());