summaryrefslogtreecommitdiffstats
path: root/js/src/vm/StencilObject.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--js/src/vm/StencilObject.cpp147
1 files changed, 147 insertions, 0 deletions
diff --git a/js/src/vm/StencilObject.cpp b/js/src/vm/StencilObject.cpp
new file mode 100644
index 0000000000..da8a144e81
--- /dev/null
+++ b/js/src/vm/StencilObject.cpp
@@ -0,0 +1,147 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: set ts=8 sts=2 et sw=2 tw=80:
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "vm/StencilObject.h"
+
+#include "mozilla/Assertions.h" // MOZ_ASSERT
+#include "mozilla/PodOperations.h" // mozilla::PodCopy
+
+#include <stddef.h> // size_t
+#include <stdint.h> // uint8_t, INT32_MAX
+
+#include "jsapi.h" // JS_NewObject
+#include "js/Class.h" // JSClassOps, JSClass, JSCLASS_*
+#include "js/ErrorReport.h" // JS_ReportErrorASCII
+#include "js/experimental/JSStencil.h" // JS::Stencil, JS::StencilAddRef, JS::StencilRelease
+#include "js/RootingAPI.h" // JS::Rooted
+#include "js/Utility.h" // js_free
+#include "vm/JSContext.h" // JSContext
+#include "vm/JSObject.h" // JSObject
+
+using namespace js;
+
+/*static */ const JSClassOps StencilObject::classOps_ = {
+ nullptr, // addProperty
+ nullptr, // delProperty
+ nullptr, // enumerate
+ nullptr, // newEnumerate
+ nullptr, // resolve
+ nullptr, // mayResolve
+ StencilObject::finalize, // finalize
+ nullptr, // call
+ nullptr, // construct
+ nullptr, // trace
+};
+
+/*static */ const JSClass StencilObject::class_ = {
+ "StencilObject",
+ JSCLASS_HAS_RESERVED_SLOTS(StencilObject::ReservedSlots) |
+ JSCLASS_BACKGROUND_FINALIZE,
+ &StencilObject::classOps_};
+
+bool StencilObject::hasStencil() const {
+ // The stencil may not be present yet if we GC during initialization.
+ return !getReservedSlot(StencilSlot).isUndefined();
+}
+
+JS::Stencil* StencilObject::stencil() const {
+ void* ptr = getReservedSlot(StencilSlot).toPrivate();
+ MOZ_ASSERT(ptr);
+ return static_cast<JS::Stencil*>(ptr);
+}
+
+/* static */ StencilObject* StencilObject::create(JSContext* cx,
+ RefPtr<JS::Stencil> stencil) {
+ JS::Rooted<JSObject*> obj(cx, JS_NewObject(cx, &class_));
+ if (!obj) {
+ return nullptr;
+ }
+
+ obj->as<StencilObject>().setReservedSlot(
+ StencilSlot, PrivateValue(stencil.forget().take()));
+
+ return &obj->as<StencilObject>();
+}
+
+/* static */ void StencilObject::finalize(JS::GCContext* gcx, JSObject* obj) {
+ if (obj->as<StencilObject>().hasStencil()) {
+ JS::StencilRelease(obj->as<StencilObject>().stencil());
+ }
+}
+
+/*static */ const JSClassOps StencilXDRBufferObject::classOps_ = {
+ nullptr, // addProperty
+ nullptr, // delProperty
+ nullptr, // enumerate
+ nullptr, // newEnumerate
+ nullptr, // resolve
+ nullptr, // mayResolve
+ StencilXDRBufferObject::finalize, // finalize
+ nullptr, // call
+ nullptr, // construct
+ nullptr, // trace
+};
+
+/*static */ const JSClass StencilXDRBufferObject::class_ = {
+ "StencilXDRBufferObject",
+ JSCLASS_HAS_RESERVED_SLOTS(StencilXDRBufferObject::ReservedSlots) |
+ JSCLASS_BACKGROUND_FINALIZE,
+ &StencilXDRBufferObject::classOps_};
+
+bool StencilXDRBufferObject::hasBuffer() const {
+ // The stencil may not be present yet if we GC during initialization.
+ return !getReservedSlot(BufferSlot).isUndefined();
+}
+
+const uint8_t* StencilXDRBufferObject::buffer() const {
+ void* ptr = getReservedSlot(BufferSlot).toPrivate();
+ MOZ_ASSERT(ptr);
+ return static_cast<const uint8_t*>(ptr);
+}
+
+uint8_t* StencilXDRBufferObject::writableBuffer() {
+ void* ptr = getReservedSlot(BufferSlot).toPrivate();
+ MOZ_ASSERT(ptr);
+ return static_cast<uint8_t*>(ptr);
+}
+
+size_t StencilXDRBufferObject::bufferLength() const {
+ return getReservedSlot(LengthSlot).toInt32();
+}
+
+/* static */ StencilXDRBufferObject* StencilXDRBufferObject::create(
+ JSContext* cx, uint8_t* buffer, size_t length) {
+ if (length >= INT32_MAX) {
+ JS_ReportErrorASCII(cx, "XDR buffer is too long");
+ return nullptr;
+ }
+
+ JS::Rooted<JSObject*> obj(cx, JS_NewObject(cx, &class_));
+ if (!obj) {
+ return nullptr;
+ }
+
+ auto ownedBuffer = cx->make_pod_array<uint8_t>(length);
+ if (!ownedBuffer) {
+ return nullptr;
+ }
+
+ mozilla::PodCopy(ownedBuffer.get(), buffer, length);
+
+ obj->as<StencilXDRBufferObject>().setReservedSlot(
+ BufferSlot, PrivateValue(ownedBuffer.release()));
+ obj->as<StencilXDRBufferObject>().setReservedSlot(LengthSlot,
+ Int32Value(length));
+
+ return &obj->as<StencilXDRBufferObject>();
+}
+
+/* static */ void StencilXDRBufferObject::finalize(JS::GCContext* gcx,
+ JSObject* obj) {
+ if (obj->as<StencilXDRBufferObject>().hasBuffer()) {
+ js_free(obj->as<StencilXDRBufferObject>().writableBuffer());
+ }
+}