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
35 nullptr, // hasInstance
40 /*static */ const JSClass
StencilObject::class_
= {
42 JSCLASS_HAS_RESERVED_SLOTS(StencilObject::ReservedSlots
) |
43 JSCLASS_BACKGROUND_FINALIZE
,
44 &StencilObject::classOps_
};
46 bool StencilObject::hasStencil() const {
47 // The stencil may not be present yet if we GC during initialization.
48 return !getReservedSlot(StencilSlot
).isUndefined();
51 JS::Stencil
* StencilObject::stencil() const {
52 void* ptr
= getReservedSlot(StencilSlot
).toPrivate();
54 return static_cast<JS::Stencil
*>(ptr
);
57 /* static */ StencilObject
* StencilObject::create(JSContext
* cx
,
58 RefPtr
<JS::Stencil
> stencil
) {
59 JS::Rooted
<JSObject
*> obj(cx
, JS_NewObject(cx
, &class_
));
64 obj
->as
<StencilObject
>().setReservedSlot(
65 StencilSlot
, PrivateValue(stencil
.forget().take()));
67 return &obj
->as
<StencilObject
>();
70 /* static */ void StencilObject::finalize(JSFreeOp
* fop
, JSObject
* obj
) {
71 if (obj
->as
<StencilObject
>().hasStencil()) {
72 JS::StencilRelease(obj
->as
<StencilObject
>().stencil());
76 /*static */ const JSClassOps
StencilXDRBufferObject::classOps_
= {
77 nullptr, // addProperty
78 nullptr, // delProperty
80 nullptr, // newEnumerate
82 nullptr, // mayResolve
83 StencilXDRBufferObject::finalize
, // finalize
85 nullptr, // hasInstance
90 /*static */ const JSClass
StencilXDRBufferObject::class_
= {
91 "StencilXDRBufferObject",
92 JSCLASS_HAS_RESERVED_SLOTS(StencilXDRBufferObject::ReservedSlots
) |
93 JSCLASS_BACKGROUND_FINALIZE
,
94 &StencilXDRBufferObject::classOps_
};
96 bool StencilXDRBufferObject::hasBuffer() const {
97 // The stencil may not be present yet if we GC during initialization.
98 return !getReservedSlot(BufferSlot
).isUndefined();
101 const uint8_t* StencilXDRBufferObject::buffer() const {
102 void* ptr
= getReservedSlot(BufferSlot
).toPrivate();
104 return static_cast<const uint8_t*>(ptr
);
107 uint8_t* StencilXDRBufferObject::writableBuffer() {
108 void* ptr
= getReservedSlot(BufferSlot
).toPrivate();
110 return static_cast<uint8_t*>(ptr
);
113 size_t StencilXDRBufferObject::bufferLength() const {
114 return getReservedSlot(LengthSlot
).toInt32();
117 /* static */ StencilXDRBufferObject
* StencilXDRBufferObject::create(
118 JSContext
* cx
, uint8_t* buffer
, size_t length
) {
119 if (length
>= INT32_MAX
) {
120 JS_ReportErrorASCII(cx
, "XDR buffer is too long");
124 JS::Rooted
<JSObject
*> obj(cx
, JS_NewObject(cx
, &class_
));
129 auto ownedBuffer
= cx
->make_pod_array
<uint8_t>(length
);
134 mozilla::PodCopy(ownedBuffer
.get(), buffer
, length
);
136 obj
->as
<StencilXDRBufferObject
>().setReservedSlot(
137 BufferSlot
, PrivateValue(ownedBuffer
.release()));
138 obj
->as
<StencilXDRBufferObject
>().setReservedSlot(LengthSlot
,
141 return &obj
->as
<StencilXDRBufferObject
>();
144 /* static */ void StencilXDRBufferObject::finalize(JSFreeOp
* fop
,
146 if (obj
->as
<StencilXDRBufferObject
>().hasBuffer()) {
147 js_free(obj
->as
<StencilXDRBufferObject
>().writableBuffer());