Skip to content

Commit 0b8af04

Browse files
authored
Merge branch 'main' into jake/subtlecrypto-verify
2 parents 63f6e8d + dce1b68 commit 0b8af04

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+4743
-4316
lines changed

c-dependencies/js-compute-runtime/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@
44

55
/js-compute-runtime*.wasm
66
/build
7+
/shared

c-dependencies/js-compute-runtime/Makefile

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ WIT_BINDGEN ?= $(shell which wit-bindgen)
3434
OPT_FLAGS ?= -O2
3535

3636
# Command helpers for making nice build output.
37-
include commands.mk
37+
include mk/commands.mk
3838

3939
# Derived configuration ########################################################
4040

@@ -148,6 +148,15 @@ $(OBJ_DIR)/builtins:
148148
$(OBJ_DIR)/builtins/shared:
149149
$(call cmd,mkdir,$@)
150150

151+
$(OBJ_DIR)/core:
152+
$(call cmd,mkdir,$@)
153+
154+
$(OBJ_DIR)/host_interface:
155+
$(call cmd,mkdir,$@)
156+
157+
shared:
158+
$(call cmd,mkdir,$@)
159+
151160
# Downloaded dependencies ######################################################
152161

153162
$(BUILD)/openssl-$(OPENSSL_VERSION).tar.gz: URL=https://www.openssl.org/source/openssl-$(OPENSSL_VERSION).tar.gz
@@ -165,10 +174,10 @@ wasi_snapshot_preview1.wasm:
165174
openssl: $(BUILD)/openssl/token
166175

167176
# Extract and prepare the openssl build directory.
168-
$(BUILD)/openssl-$(OPENSSL_VERSION)/token: $(BUILD)/openssl-$(OPENSSL_VERSION).tar.gz $(FSM_SRC)/getuid.patch
177+
$(BUILD)/openssl-$(OPENSSL_VERSION)/token: $(BUILD)/openssl-$(OPENSSL_VERSION).tar.gz $(FSM_SRC)/third_party/getuid.patch
169178
$Q tar -C $(BUILD) -xf $<
170-
$Q patch -d $(BUILD)/openssl-$(OPENSSL_VERSION) -p1 < $(FSM_SRC)/getuid.patch
171-
$Q patch -d $(BUILD)/openssl-$(OPENSSL_VERSION) -p1 < $(FSM_SRC)/rand.patch
179+
$Q patch -d $(BUILD)/openssl-$(OPENSSL_VERSION) -p1 < $(FSM_SRC)/third_party/getuid.patch
180+
$Q patch -d $(BUILD)/openssl-$(OPENSSL_VERSION) -p1 < $(FSM_SRC)/third_party/rand.patch
172181
$Q touch $@
173182

174183
OPENSSL_OPTS := -static -no-sock -no-asm -no-ui-console -no-egd
@@ -246,6 +255,8 @@ endif
246255
FSM_CPP := $(wildcard $(FSM_SRC)/*.cpp)
247256
FSM_CPP += $(wildcard $(FSM_SRC)/builtins/*.cpp)
248257
FSM_CPP += $(wildcard $(FSM_SRC)/builtins/shared/*.cpp)
258+
FSM_CPP += $(wildcard $(FSM_SRC)/core/*.cpp)
259+
FSM_CPP += $(wildcard $(FSM_SRC)/host_interface/*.cpp)
249260
FSM_OBJ := $(patsubst $(FSM_SRC)/%.cpp,$(OBJ_DIR)/%.o,$(FSM_CPP))
250261

251262
# Build all the above object files
@@ -277,12 +288,15 @@ $(OBJ_DIR)/js-compute-runtime-component.wasm: $(OBJ_DIR)/xqd-world/xqd_world_ada
277288
$(WASI_CXX) $(LD_FLAGS) $(OPENSSL_LIBS) -o $@ $^
278289
$(call cmd_format,WASM_STRIP,$@) $(call WASM_STRIP,$@)
279290

280-
# The subset of javascript builtins that are reusable across other runtimes.
281-
shared-builtins.a: $(OBJ_DIR)/shared-builtins.a
282-
$(call cmd,cp,$@)
291+
# Shared builtins build
292+
293+
shared-builtins: shared/builtins.a shared/librust_url.a
283294

284-
$(OBJ_DIR)/shared-builtins.a: $(OBJ_DIR)/builtins/shared/console.o $(OBJ_DIR)/builtin.o
285-
$(call cmd,wasi_ar,$@)
295+
shared/builtins.a: $(OBJ_DIR)/builtins/shared/*.o $(OBJ_DIR)/builtin.o | shared
296+
$(call cmd,wasi_ar,$^)
297+
298+
shared/librust_url.a: $(RUST_URL_LIB) | shared
299+
$(call cmd,cp,$@)
286300

287301
# These two rules copy the built artifacts into the $(FSM_SRC) directory, and
288302
# are both marked phony as we need to do the right thing when running the

c-dependencies/js-compute-runtime/builtin-error-numbers.msg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,5 @@ MSG_DEF(JSMSG_BUILTIN_CTOR_NO_NEW, 1, JSEXN_TYPEERR,
4444
MSG_DEF(JSMSG_ILLEGAL_CTOR, 0, JSEXN_TYPEERR, "Illegal constructor")
4545
MSG_DEF(JSMSG_INVALID_INTERFACE, 2, JSEXN_TYPEERR, "'{0}' called on an object that does not implement interface {1}")
4646
MSG_DEF(JSMSG_INCOMPATIBLE_INSTANCE, 2, JSEXN_TYPEERR, "Method {0} called on receiver that's not an instance of {1}")
47+
MSG_DEF(JSMSG_INVALID_BUFFER_ARG, 2, JSEXN_TYPEERR, "{0} must be of type ArrayBuffer or ArrayBufferView but got \"{1}\"")
4748
//clang-format on

c-dependencies/js-compute-runtime/builtin.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,29 @@ const JSErrorFormatString *GetErrorMessageBuiltin(void *userRef, unsigned errorN
88
return nullptr;
99
}
1010

11+
std::optional<std::span<uint8_t>> value_to_buffer(JSContext *cx, JS::HandleValue val,
12+
const char *val_desc) {
13+
if (!val.isObject() ||
14+
!(JS_IsArrayBufferViewObject(&val.toObject()) || JS::IsArrayBufferObject(&val.toObject()))) {
15+
JS_ReportErrorNumberUTF8(cx, GetErrorMessageBuiltin, nullptr, JSMSG_INVALID_BUFFER_ARG,
16+
val_desc, val.type());
17+
return std::nullopt;
18+
}
19+
20+
JS::RootedObject input(cx, &val.toObject());
21+
uint8_t *data;
22+
bool is_shared;
23+
size_t len = 0;
24+
25+
if (JS_IsArrayBufferViewObject(input)) {
26+
js::GetArrayBufferViewLengthAndData(input, &len, &is_shared, &data);
27+
} else {
28+
JS::GetArrayBufferLengthAndData(input, &len, &is_shared, &data);
29+
}
30+
31+
return std::span(data, len);
32+
}
33+
1134
JS::UniqueChars encode(JSContext *cx, JS::HandleString str, size_t *encoded_len) {
1235
JS::UniqueChars text = JS_EncodeStringToUTF8(cx, str);
1336
if (!text)

c-dependencies/js-compute-runtime/builtin.h

Lines changed: 7 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,22 @@
77
#pragma clang diagnostic push
88
#pragma clang diagnostic ignored "-Winvalid-offsetof"
99
#pragma clang diagnostic ignored "-Wdeprecated-enum-enum-conversion"
10+
#include "js/ArrayBuffer.h"
1011
#include "js/Conversions.h"
1112
#include "js/ForOfIterator.h"
1213
#include "js/Object.h"
1314
#include "js/Promise.h"
15+
#include "js/experimental/TypedData.h"
1416
#include "jsapi.h"
1517
#include "jsfriendapi.h"
1618
#include "rust-url/rust-url.h"
19+
#include <span>
1720

1821
#pragma clang diagnostic pop
1922

23+
std::optional<std::span<uint8_t>> value_to_buffer(JSContext *cx, JS::HandleValue val,
24+
const char *val_desc);
25+
2026
// TODO(performance): introduce a version that writes into an existing buffer, and use that
2127
// with the hostcall buffer where possible.
2228
// https://github.com/fastly/js-compute-runtime/issues/215
@@ -67,53 +73,6 @@ const JSErrorFormatString *GetErrorMessageBuiltin(void *userRef, unsigned errorN
6773
cursor = (uint32_t)ending_cursor; \
6874
}
6975

70-
#define CLASS_BOILERPLATE_CUSTOM_INIT(cls) \
71-
constexpr const JSClassOps class_ops = {}; \
72-
const uint32_t class_flags = 0; \
73-
\
74-
const JSClass class_ = {#cls, JSCLASS_HAS_RESERVED_SLOTS(Slots::Count) | class_flags, \
75-
&class_ops}; \
76-
JS::PersistentRooted<JSObject *> proto_obj; \
77-
\
78-
bool is_instance(JSObject *obj) { return !!obj && JS::GetClass(obj) == &class_; } \
79-
\
80-
bool is_instance(JS::Value val) { return val.isObject() && is_instance(&val.toObject()); } \
81-
\
82-
bool check_receiver(JSContext *cx, JS::HandleValue receiver, const char *method_name) { \
83-
if (!is_instance(receiver)) { \
84-
JS_ReportErrorNumberASCII(cx, GetErrorMessageBuiltin, nullptr, JSMSG_INCOMPATIBLE_INSTANCE, \
85-
method_name, class_.name); \
86-
return false; \
87-
} \
88-
return true; \
89-
}; \
90-
\
91-
bool init_class_impl(JSContext *cx, JS::HandleObject global, \
92-
JS::HandleObject parent_proto = nullptr) { \
93-
proto_obj.init(cx, JS_InitClass(cx, global, &class_, parent_proto, #cls, constructor, \
94-
ctor_length, properties, methods, nullptr, nullptr)); \
95-
return proto_obj; \
96-
};
97-
98-
#define CLASS_BOILERPLATE(cls) \
99-
CLASS_BOILERPLATE_CUSTOM_INIT(cls) \
100-
\
101-
bool init_class(JSContext *cx, JS::HandleObject global) { return init_class_impl(cx, global); }
102-
103-
#define CLASS_BOILERPLATE_NO_CTOR(cls) \
104-
bool constructor(JSContext *cx, unsigned argc, JS::Value *vp) { \
105-
JS_ReportErrorUTF8(cx, #cls " can't be instantiated directly"); \
106-
return false; \
107-
} \
108-
\
109-
CLASS_BOILERPLATE_CUSTOM_INIT(cls) \
110-
\
111-
bool init_class(JSContext *cx, JS::HandleObject global) { \
112-
/* Right now, deleting the ctor from the global object after class \
113-
initialization seems to be the best we can do. Not ideal, but works. */ \
114-
return init_class_impl(cx, global) && JS_DeleteProperty(cx, global, class_.name); \
115-
}
116-
11776
// Define this to make most methods print their name to stderr when invoked.
11877
// #define TRACE_METHOD_CALLS
11978

@@ -181,7 +140,7 @@ template <typename Impl> class BuiltinImpl {
181140
public:
182141
static constexpr JSClass class_{
183142
Impl::class_name,
184-
JSCLASS_HAS_RESERVED_SLOTS(Impl::Slots::Count) | class_flags,
143+
JSCLASS_HAS_RESERVED_SLOTS(static_cast<uint32_t>(Impl::Slots::Count)) | class_flags,
185144
&class_ops,
186145
};
187146