summaryrefslogtreecommitdiffstats
path: root/js/src/wasm/WasmAnyRef.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/wasm/WasmAnyRef.cpp')
-rw-r--r--js/src/wasm/WasmAnyRef.cpp126
1 files changed, 126 insertions, 0 deletions
diff --git a/js/src/wasm/WasmAnyRef.cpp b/js/src/wasm/WasmAnyRef.cpp
new file mode 100644
index 0000000000..8e3f716d41
--- /dev/null
+++ b/js/src/wasm/WasmAnyRef.cpp
@@ -0,0 +1,126 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: set ts=8 sts=2 et sw=2 tw=80:
+ *
+ * Copyright 2023 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "wasm/WasmAnyRef.h"
+
+#include "vm/JSContext.h"
+#include "vm/JSObject.h"
+#include "vm/NativeObject.h"
+
+#include "vm/JSObject-inl.h"
+
+using namespace js;
+using namespace js::wasm;
+
+class WasmValueBox : public NativeObject {
+ public:
+ static const unsigned VALUE_SLOT = 0;
+ static const unsigned RESERVED_SLOTS = 1;
+ static const JSClass class_;
+
+ static WasmValueBox* create(JSContext* cx, HandleValue value);
+ Value value() const { return getFixedSlot(VALUE_SLOT); }
+};
+
+const JSClass WasmValueBox::class_ = {
+ "WasmValueBox", JSCLASS_HAS_RESERVED_SLOTS(RESERVED_SLOTS)};
+
+WasmValueBox* WasmValueBox::create(JSContext* cx, HandleValue value) {
+ WasmValueBox* obj = NewObjectWithGivenProto<WasmValueBox>(cx, nullptr);
+ if (!obj) {
+ return nullptr;
+ }
+ obj->setFixedSlot(VALUE_SLOT, value);
+ return obj;
+}
+
+const JSClass* AnyRef::valueBoxClass() { return &WasmValueBox::class_; }
+
+size_t AnyRef::valueBoxOffsetOfValue() {
+ return NativeObject::getFixedSlotOffset(WasmValueBox::VALUE_SLOT);
+}
+
+bool AnyRef::fromJSValue(JSContext* cx, HandleValue value,
+ MutableHandleAnyRef result) {
+ if (value.isNull()) {
+ result.set(AnyRef::null());
+ return true;
+ }
+
+ if (value.isString()) {
+ JSString* string = value.toString();
+ result.set(AnyRef::fromJSString(string));
+ return true;
+ }
+
+ if (value.isObject()) {
+ JSObject& obj = value.toObject();
+ MOZ_ASSERT(!obj.is<WasmValueBox>());
+ MOZ_ASSERT(obj.compartment() == cx->compartment());
+ result.set(AnyRef::fromJSObject(obj));
+ return true;
+ }
+
+ if (value.isInt32() && !int32NeedsBoxing(value.toInt32())) {
+ result.set(AnyRef::fromInt32(value.toInt32()));
+ return true;
+ }
+
+ if (value.isDouble()) {
+ double doubleValue = value.toDouble();
+ int32_t intValue;
+ if (mozilla::NumberIsInt32(doubleValue, &intValue) &&
+ !int32NeedsBoxing(intValue)) {
+ result.set(AnyRef::fromInt32(intValue));
+ return true;
+ }
+ }
+
+ JSObject* box = AnyRef::boxValue(cx, value);
+ if (!box) {
+ return false;
+ }
+ result.set(AnyRef::fromJSObject(*box));
+ return true;
+}
+
+JSObject* AnyRef::boxValue(JSContext* cx, HandleValue value) {
+ MOZ_ASSERT(AnyRef::valueNeedsBoxing(value));
+ return WasmValueBox::create(cx, value);
+}
+
+Value wasm::AnyRef::toJSValue() const {
+ // If toJSValue needs to allocate then we need a more complicated API, and
+ // we need to root the value in the callers, see comments in callExport().
+ Value value;
+ if (isNull()) {
+ value.setNull();
+ } else if (isJSString()) {
+ value.setString(toJSString());
+ } else if (isI31()) {
+ value.setInt32(toI31());
+ } else {
+ JSObject& obj = toJSObject();
+ if (obj.is<WasmValueBox>()) {
+ value = obj.as<WasmValueBox>().value();
+ } else {
+ value.setObject(obj);
+ }
+ }
+ return value;
+}