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:
4 * Copyright 2023 Mozilla Foundation
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include "wasm/WasmAnyRef.h"
21 #include "vm/JSContext.h"
22 #include "vm/JSObject.h"
23 #include "vm/NativeObject.h"
25 #include "vm/JSObject-inl.h"
28 using namespace js::wasm
;
30 class WasmValueBox
: public NativeObject
{
32 static const unsigned VALUE_SLOT
= 0;
33 static const unsigned RESERVED_SLOTS
= 1;
34 static const JSClass class_
;
36 static WasmValueBox
* create(JSContext
* cx
, HandleValue value
);
37 Value
value() const { return getFixedSlot(VALUE_SLOT
); }
40 const JSClass
WasmValueBox::class_
= {
41 "WasmValueBox", JSCLASS_HAS_RESERVED_SLOTS(RESERVED_SLOTS
)};
43 WasmValueBox
* WasmValueBox::create(JSContext
* cx
, HandleValue value
) {
44 WasmValueBox
* obj
= NewObjectWithGivenProto
<WasmValueBox
>(cx
, nullptr);
48 obj
->setFixedSlot(VALUE_SLOT
, value
);
52 const JSClass
* AnyRef::valueBoxClass() { return &WasmValueBox::class_
; }
54 size_t AnyRef::valueBoxOffsetOfValue() {
55 return NativeObject::getFixedSlotOffset(WasmValueBox::VALUE_SLOT
);
58 bool AnyRef::fromJSValue(JSContext
* cx
, HandleValue value
,
59 MutableHandleAnyRef result
) {
61 result
.set(AnyRef::null());
65 if (value
.isString()) {
66 JSString
* string
= value
.toString();
67 result
.set(AnyRef::fromJSString(string
));
71 if (value
.isObject()) {
72 JSObject
& obj
= value
.toObject();
73 MOZ_ASSERT(!obj
.is
<WasmValueBox
>());
74 MOZ_ASSERT(obj
.compartment() == cx
->compartment());
75 result
.set(AnyRef::fromJSObject(obj
));
79 if (value
.isInt32() && !int32NeedsBoxing(value
.toInt32())) {
80 result
.set(AnyRef::fromInt32(value
.toInt32()));
84 if (value
.isDouble()) {
85 double doubleValue
= value
.toDouble();
87 if (mozilla::NumberIsInt32(doubleValue
, &intValue
) &&
88 !int32NeedsBoxing(intValue
)) {
89 result
.set(AnyRef::fromInt32(intValue
));
94 JSObject
* box
= AnyRef::boxValue(cx
, value
);
98 result
.set(AnyRef::fromJSObject(*box
));
102 JSObject
* AnyRef::boxValue(JSContext
* cx
, HandleValue value
) {
103 MOZ_ASSERT(AnyRef::valueNeedsBoxing(value
));
104 return WasmValueBox::create(cx
, value
);
107 Value
wasm::AnyRef::toJSValue() const {
108 // If toJSValue needs to allocate then we need a more complicated API, and
109 // we need to root the value in the callers, see comments in callExport().
113 } else if (isJSString()) {
114 value
.setString(toJSString());
115 } else if (isI31()) {
116 value
.setInt32(toI31());
118 JSObject
& obj
= toJSObject();
119 if (obj
.is
<WasmValueBox
>()) {
120 value
= obj
.as
<WasmValueBox
>().value();
122 value
.setObject(obj
);