tor-browser

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

WasmAnyRef.cpp (3557B)


      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 *
      4 * Copyright 2023 Mozilla Foundation
      5 *
      6 * Licensed under the Apache License, Version 2.0 (the "License");
      7 * you may not use this file except in compliance with the License.
      8 * You may obtain a copy of the License at
      9 *
     10 *     http://www.apache.org/licenses/LICENSE-2.0
     11 *
     12 * Unless required by applicable law or agreed to in writing, software
     13 * distributed under the License is distributed on an "AS IS" BASIS,
     14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     15 * See the License for the specific language governing permissions and
     16 * limitations under the License.
     17 */
     18 
     19 #include "wasm/WasmAnyRef.h"
     20 
     21 #include "vm/JSContext.h"
     22 #include "vm/JSObject.h"
     23 #include "vm/NativeObject.h"
     24 
     25 #include "vm/JSObject-inl.h"
     26 
     27 using namespace js;
     28 using namespace js::wasm;
     29 
     30 class WasmValueBox : public NativeObject {
     31 public:
     32  static const unsigned VALUE_SLOT = 0;
     33  static const unsigned RESERVED_SLOTS = 1;
     34  static const JSClass class_;
     35 
     36  static WasmValueBox* create(JSContext* cx, HandleValue value);
     37  Value value() const { return getFixedSlot(VALUE_SLOT); }
     38 };
     39 
     40 const JSClass WasmValueBox::class_ = {
     41    "WasmValueBox",
     42    JSCLASS_HAS_RESERVED_SLOTS(RESERVED_SLOTS),
     43 };
     44 
     45 WasmValueBox* WasmValueBox::create(JSContext* cx, HandleValue value) {
     46  WasmValueBox* obj = NewObjectWithGivenProto<WasmValueBox>(cx, nullptr);
     47  if (!obj) {
     48    return nullptr;
     49  }
     50  obj->initFixedSlot(VALUE_SLOT, value);
     51  return obj;
     52 }
     53 
     54 const JSClass* AnyRef::valueBoxClass() { return &WasmValueBox::class_; }
     55 
     56 size_t AnyRef::valueBoxOffsetOfValue() {
     57  return NativeObject::getFixedSlotOffset(WasmValueBox::VALUE_SLOT);
     58 }
     59 
     60 bool AnyRef::fromJSValue(JSContext* cx, HandleValue value,
     61                         MutableHandleAnyRef result) {
     62  if (value.isNull()) {
     63    result.set(AnyRef::null());
     64    return true;
     65  }
     66 
     67  if (value.isString()) {
     68    JSString* string = value.toString();
     69    result.set(AnyRef::fromJSString(string));
     70    return true;
     71  }
     72 
     73  if (value.isObject()) {
     74    JSObject& obj = value.toObject();
     75    MOZ_ASSERT(!obj.is<WasmValueBox>());
     76    MOZ_ASSERT(obj.compartment() == cx->compartment());
     77    result.set(AnyRef::fromJSObject(obj));
     78    return true;
     79  }
     80 
     81  if (value.isInt32() && !int32NeedsBoxing(value.toInt32())) {
     82    result.set(AnyRef::fromInt32(value.toInt32()));
     83    return true;
     84  }
     85 
     86  if (value.isDouble()) {
     87    double doubleValue = value.toDouble();
     88    int32_t intValue;
     89    if (mozilla::NumberEqualsInt32(doubleValue, &intValue) &&
     90        !int32NeedsBoxing(intValue)) {
     91      result.set(AnyRef::fromInt32(intValue));
     92      return true;
     93    }
     94  }
     95 
     96  JSObject* box = AnyRef::boxValue(cx, value);
     97  if (!box) {
     98    return false;
     99  }
    100  result.set(AnyRef::fromJSObject(*box));
    101  return true;
    102 }
    103 
    104 JSObject* AnyRef::boxValue(JSContext* cx, HandleValue value) {
    105  MOZ_ASSERT(AnyRef::valueNeedsBoxing(value));
    106  return WasmValueBox::create(cx, value);
    107 }
    108 
    109 Value wasm::AnyRef::toJSValue() const {
    110  // If toJSValue needs to allocate then we need a more complicated API, and
    111  // we need to root the value in the callers, see comments in callExport().
    112  Value value;
    113  if (isNull()) {
    114    value.setNull();
    115  } else if (isJSString()) {
    116    value.setString(toJSString());
    117  } else if (isI31()) {
    118    value.setInt32(toI31());
    119  } else {
    120    JSObject& obj = toJSObject();
    121    if (obj.is<WasmValueBox>()) {
    122      value = obj.as<WasmValueBox>().value();
    123    } else {
    124      value.setObject(obj);
    125    }
    126  }
    127  return value;
    128 }