tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

StencilObject.cpp (4950B)


      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 "vm/StencilObject.h"
      8 
      9 #include "mozilla/Assertions.h"     // MOZ_ASSERT
     10 #include "mozilla/PodOperations.h"  // mozilla::PodCopy
     11 
     12 #include <stddef.h>  // size_t
     13 #include <stdint.h>  // uint8_t, INT32_MAX
     14 
     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/Utility.h"                 // js_free
     20 #include "vm/JSContext.h"               // JSContext
     21 #include "vm/JSObject.h"                // JSObject
     22 
     23 #include "vm/JSObject-inl.h"  // NewBuiltinClassInstance
     24 
     25 using namespace js;
     26 
     27 /*static */ const JSClassOps StencilObject::classOps_ = {
     28    nullptr,                  // addProperty
     29    nullptr,                  // delProperty
     30    nullptr,                  // enumerate
     31    nullptr,                  // newEnumerate
     32    nullptr,                  // resolve
     33    nullptr,                  // mayResolve
     34    StencilObject::finalize,  // finalize
     35    nullptr,                  // call
     36    nullptr,                  // construct
     37    nullptr,                  // trace
     38 };
     39 
     40 /*static */ const JSClass StencilObject::class_ = {
     41    "StencilObject",
     42    JSCLASS_HAS_RESERVED_SLOTS(StencilObject::ReservedSlots) |
     43        JSCLASS_BACKGROUND_FINALIZE,
     44    &StencilObject::classOps_,
     45 };
     46 
     47 bool StencilObject::hasStencil() const {
     48  // The stencil may not be present yet if we GC during initialization.
     49  return !getReservedSlot(StencilSlot).isUndefined();
     50 }
     51 
     52 JS::Stencil* StencilObject::stencil() const {
     53  void* ptr = getReservedSlot(StencilSlot).toPrivate();
     54  MOZ_ASSERT(ptr);
     55  return static_cast<JS::Stencil*>(ptr);
     56 }
     57 
     58 /* static */ StencilObject* StencilObject::create(JSContext* cx,
     59                                                  RefPtr<JS::Stencil> stencil) {
     60  auto* obj = NewBuiltinClassInstance<StencilObject>(cx);
     61  if (!obj) {
     62    return nullptr;
     63  }
     64 
     65  obj->setReservedSlot(StencilSlot, PrivateValue(stencil.forget().take()));
     66 
     67  return obj;
     68 }
     69 
     70 /* static */ void StencilObject::finalize(JS::GCContext* gcx, JSObject* obj) {
     71  if (obj->as<StencilObject>().hasStencil()) {
     72    JS::StencilRelease(obj->as<StencilObject>().stencil());
     73  }
     74 }
     75 
     76 /*static */ const JSClassOps StencilXDRBufferObject::classOps_ = {
     77    nullptr,                           // addProperty
     78    nullptr,                           // delProperty
     79    nullptr,                           // enumerate
     80    nullptr,                           // newEnumerate
     81    nullptr,                           // resolve
     82    nullptr,                           // mayResolve
     83    StencilXDRBufferObject::finalize,  // finalize
     84    nullptr,                           // call
     85    nullptr,                           // construct
     86    nullptr,                           // trace
     87 };
     88 
     89 /*static */ const JSClass StencilXDRBufferObject::class_ = {
     90    "StencilXDRBufferObject",
     91    JSCLASS_HAS_RESERVED_SLOTS(StencilXDRBufferObject::ReservedSlots) |
     92        JSCLASS_BACKGROUND_FINALIZE,
     93    &StencilXDRBufferObject::classOps_,
     94 };
     95 
     96 bool StencilXDRBufferObject::hasBuffer() const {
     97  // The stencil may not be present yet if we GC during initialization.
     98  return !getReservedSlot(BufferSlot).isUndefined();
     99 }
    100 
    101 const uint8_t* StencilXDRBufferObject::buffer() const {
    102  void* ptr = getReservedSlot(BufferSlot).toPrivate();
    103  MOZ_ASSERT(ptr);
    104  return static_cast<const uint8_t*>(ptr);
    105 }
    106 
    107 uint8_t* StencilXDRBufferObject::writableBuffer() {
    108  void* ptr = getReservedSlot(BufferSlot).toPrivate();
    109  MOZ_ASSERT(ptr);
    110  return static_cast<uint8_t*>(ptr);
    111 }
    112 
    113 size_t StencilXDRBufferObject::bufferLength() const {
    114  return getReservedSlot(LengthSlot).toInt32();
    115 }
    116 
    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");
    121    return nullptr;
    122  }
    123 
    124  auto* obj = NewBuiltinClassInstance<StencilXDRBufferObject>(cx);
    125  if (!obj) {
    126    return nullptr;
    127  }
    128 
    129  auto ownedBuffer = cx->make_pod_array<uint8_t>(length);
    130  if (!ownedBuffer) {
    131    return nullptr;
    132  }
    133 
    134  mozilla::PodCopy(ownedBuffer.get(), buffer, length);
    135 
    136  obj->setReservedSlot(BufferSlot, PrivateValue(ownedBuffer.release()));
    137  obj->setReservedSlot(LengthSlot, Int32Value(length));
    138 
    139  return obj;
    140 }
    141 
    142 /* static */ void StencilXDRBufferObject::finalize(JS::GCContext* gcx,
    143                                                   JSObject* obj) {
    144  if (obj->as<StencilXDRBufferObject>().hasBuffer()) {
    145    js_free(obj->as<StencilXDRBufferObject>().writableBuffer());
    146  }
    147 }