Skip to content

Commit

Permalink
feat!: compute runtime component build (#326)
Browse files Browse the repository at this point in the history
  • Loading branch information
guybedford committed Dec 9, 2022
1 parent e7386b7 commit 197504c
Show file tree
Hide file tree
Showing 24 changed files with 5,571 additions and 676 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -12,6 +12,7 @@ node_modules/
/rusturl/
# compiler_flags
/js-compute-runtime.wasm
/c-dependencies/js-compute-runtime/obj
tests/wpt-harness/wpt-test-runner.js
wpt-runtime.wasm
docs-app/bin/main.wasm
Expand Down
44 changes: 35 additions & 9 deletions c-dependencies/js-compute-runtime/Makefile
Expand Up @@ -25,13 +25,22 @@ SM_OBJ += $(SM_SRC)lib/*.a
FSM_SRC := $(ROOT_SRC)/js-compute-runtime/

WASI_CXX ?= $(WASI_SDK)/bin/clang++
WASI_CC ?= $(WASI_SDK)/bin/clang

WIT_BINDGEN := $(shell which wit-bindgen)

ifndef WIT_BINDGEN
WIT_BINDGEN = $(error No wit-bindgen in PATH, consider doing cargo install --git https://github.com/bytecodealliance/wit-bindgen wit-bindgen-cli)
endif

CXX_FLAGS := -std=gnu++17 -Wall -Werror -Qunused-arguments
CXX_FLAGS += -fno-sized-deallocation -fno-aligned-new -mthread-model single
CXX_FLAGS += -fPIC -fno-rtti -fno-exceptions -fno-math-errno -pipe
CXX_FLAGS += -fno-omit-frame-pointer -funwind-tables -I$(FSM_SRC)
CXX_FLAGS += --sysroot=$(WASI_SDK)/share/wasi-sysroot

CFLAGS := -Wall -Werror -Wno-unknown-attributes -Wno-pointer-to-int-cast -Wno-int-to-pointer-cast

LD_FLAGS := -Wl,-z,noexecstack -Wl,-z,text -Wl,-z,relro -Wl,-z,nocopyreloc
LD_FLAGS += -Wl,-z,stack-size=1048576 -Wl,--stack-first -lwasi-emulated-getpid

Expand All @@ -54,9 +63,10 @@ WASM_STRIP = wasm-opt --strip-debug -o $1 $1
endif
endif

OBJ_DIR := obj/
FSM_CPP := $(wildcard $(FSM_SRC)*.cpp) $(wildcard $(FSM_SRC)builtins/*.cpp)
FSM_DEP := $(patsubst $(FSM_SRC)%.cpp,$(OBJDIR)%.d,$(FSM_CPP))
FSM_OBJ := $(patsubst $(FSM_SRC)%.cpp,$(OBJDIR)%.o,$(FSM_CPP))
FSM_DEP := $(patsubst $(FSM_SRC)%.cpp,$(OBJ_DIR)%.d,$(FSM_CPP))
FSM_OBJ := $(patsubst $(FSM_SRC)%.cpp,$(OBJ_DIR)%.o,$(FSM_CPP))
RUST_URL_SRC := $(FSM_SRC)rust-url
RUST_URL_RS_FILES := $(shell find $(RUST_URL_SRC)/src -name '*.rs')
RUST_URL_LIB := rusturl/wasm32-wasi/$(MODE)/librust_url.a
Expand All @@ -67,27 +77,43 @@ $(RUST_URL_LIB): $(RUST_URL_RS_FILES) $(RUST_URL_SRC)/Cargo.toml $(RUST_URL_SRC)
cd $(RUST_URL_SRC) && cbindgen --output rust-url.h
cargo build --manifest-path $(RUST_URL_SRC)/Cargo.toml --target-dir ./rusturl --target=wasm32-wasi $(CARGO_FLAG)

%.o: $(FSM_SRC)%.cpp $(FSM_SRC)Makefile $(RUST_URL_LIB) compiler_flags
obj:
$Q mkdir -p $(OBJ_DIR)builtins $(OBJ_DIR)xqd-world

$(OBJ_DIR)%.o: $(FSM_SRC)%.cpp $(FSM_SRC)Makefile $(RUST_URL_LIB) compiler_flags | obj
$(WASI_CXX) $(CXX_FLAGS) $(CXX_OPT) $(DEFINES) -I $(SM_SRC)include -MMD -MP -c -o $@ $<

$(OBJ_DIR)builtins/%.o: $(FSM_SRC)builtins/%.cpp $(FSM_SRC)Makefile $(RUST_URL_LIB) compiler_flags | obj
$(WASI_CXX) $(CXX_FLAGS) $(CXX_OPT) $(DEFINES) -I $(SM_SRC)include -MMD -MP -c -o $@ $<

builtins:
$Q mkdir -p builtins
$(OBJ_DIR)xqd-world/xqd_world.o: $(FSM_SRC)xqd-world/xqd_world.c $(FSM_SRC)Makefile compiler_flags
$(WASI_CC) $(CFLAGS) $(CXX_OPT) $(DEFINES) -I $(SM_SRC)include -MMD -MP -c -o $@ $<

builtins/%.o: $(FSM_SRC)builtins/%.cpp $(FSM_SRC)Makefile $(RUST_URL_LIB) compiler_flags | builtins
$(OBJ_DIR)xqd-world/xqd_world_adapter.o: $(FSM_SRC)xqd-world/xqd_world_adapter.cpp $(FSM_SRC)Makefile compiler_flags
$(WASI_CXX) $(CXX_FLAGS) $(CXX_OPT) $(DEFINES) -I $(SM_SRC)include -MMD -MP -c -o $@ $<

js-compute-runtime.wasm: $(FSM_OBJ) $(SM_OBJ) $(RUST_URL_LIB)
$(OBJ_DIR)xqd-world/xqd_world_adapter_component.o: $(FSM_SRC)xqd-world/xqd_world_adapter.cpp $(FSM_SRC)Makefile compiler_flags
$(WASI_CXX) $(CXX_FLAGS) $(CXX_OPT) $(DEFINES) -DCOMPONENT -I $(SM_SRC)include -MMD -MP -c -o $@ $<

js-compute-runtime.wasm: $(FSM_OBJ) $(SM_OBJ) $(OBJ_DIR)xqd-world/xqd_world.o $(OBJ_DIR)xqd-world/xqd_world_adapter.o $(RUST_URL_LIB)
$(WASI_CXX) $(CXX_FLAGS) $(CXX_OPT) $(DEFINES) $(LD_FLAGS) -o $@ $^
$(call WASM_STRIP,$@)

js-compute-runtime-component.wasm: $(FSM_OBJ) $(OBJ_DIR)xqd-world/xqd_world.o $(OBJ_DIR)xqd-world/xqd_world_adapter_component.o $(SM_OBJ) $(RUST_URL_LIB)
$(WASI_CXX) $(CXX_FLAGS) $(CXX_OPT) $(DEFINES) $(LD_FLAGS) -o $@ $^
$(call WASM_STRIP,$@)

install: js-compute-runtime.wasm
install -m 444 -Dt $(DESTDIR)/dist js-compute-runtime.wasm

regenerate-world:
$(WIT_BINDGEN) guest c xqd.wit --no-helpers --out-dir xqd-world

clean:
$(RM) compile_commands.json $(FSM_OBJ)
$(RM) compile_commands.json $(FSM_OBJ) xqd-world/xqd_world_component_type.o

distclean: clean
$(RM) $(FSM_DEP) compiler_flags
$(RM) $(FSM_DEP) $(FSM_DEP_COMPONENT) $(OBJ_DIR)xqd-world/*.o compiler_flags

.PHONY: compile_commands.json
compile_commands.json:
Expand Down
134 changes: 53 additions & 81 deletions c-dependencies/js-compute-runtime/builtins/backend.cpp
Expand Up @@ -120,138 +120,110 @@ namespace builtins {
JS::Result<mozilla::Ok> Backend::register_dynamic_backend(JSContext *cx, JS::HandleObject backend) {
MOZ_ASSERT(is_instance(backend));

DynamicBackendConfig definition;
std::memset(&definition, 0, sizeof(definition));
xqd_world_string_t name_str;
JS::RootedString name(cx, JS::GetReservedSlot(backend, Backend::Slots::Name).toString());
JS::UniqueChars nameChars = encode(cx, name, &name_str.len);
name_str.ptr = nameChars.get();

xqd_world_string_t target_str;
JS::RootedString target(cx, JS::GetReservedSlot(backend, Backend::Slots::Target).toString());
JS::UniqueChars targetChars = encode(cx, target, &target_str.len);
target_str.ptr = targetChars.get();

unsigned int backend_config_mask = 0u;
fastly_dynamic_backend_config_t backend_config;
std::memset(&backend_config, 0, sizeof(backend_config));

std::optional<std::string> hostOverride;
std::string hostOverride;
auto hostOverrideSlot = JS::GetReservedSlot(backend, Backend::Slots::HostOverride);
if (!hostOverrideSlot.isNullOrUndefined()) {
if ((backend_config.host_override.is_some = !hostOverrideSlot.isNullOrUndefined())) {
JS::RootedString hostOverrideString(cx, hostOverrideSlot.toString());
size_t hostOverride_len;
JS::UniqueChars hostOverrideChars = encode(cx, hostOverrideString, &hostOverride_len);
hostOverride = std::string(hostOverrideChars.get(), hostOverride_len);
backend_config.host_override.val.ptr = const_cast<char *>(hostOverride.c_str());
backend_config.host_override.val.len = hostOverride.length();
}

auto connectTimeoutSlot = JS::GetReservedSlot(backend, Backend::Slots::ConnectTimeout);
if (!connectTimeoutSlot.isNullOrUndefined()) {
definition.connect_timeout_ms = connectTimeoutSlot.toInt32();
backend_config_mask |= BACKEND_CONFIG_CONNECT_TIMEOUT;
} else {
definition.connect_timeout_ms = 0;
if ((backend_config.connect_timeout.is_some = !connectTimeoutSlot.isNullOrUndefined())) {
backend_config.connect_timeout.val = connectTimeoutSlot.toInt32();
}

auto firstByteTimeoutSlot = JS::GetReservedSlot(backend, Backend::Slots::FirstByteTimeout);
if (!firstByteTimeoutSlot.isNullOrUndefined()) {
definition.first_byte_timeout_ms = firstByteTimeoutSlot.toInt32();
backend_config_mask |= BACKEND_CONFIG_FIRST_BYTE_TIMEOUT;
} else {
definition.first_byte_timeout_ms = 0;
if ((backend_config.first_byte_timeout.is_some = !firstByteTimeoutSlot.isNullOrUndefined())) {
backend_config.first_byte_timeout.val = firstByteTimeoutSlot.toInt32();
}

auto betweenBytesTimeoutSlot = JS::GetReservedSlot(backend, Backend::Slots::BetweenBytesTimeout);
if (!betweenBytesTimeoutSlot.isNullOrUndefined()) {
definition.between_bytes_timeout_ms = betweenBytesTimeoutSlot.toInt32();
backend_config_mask |= BACKEND_CONFIG_BETWEEN_BYTES_TIMEOUT;
} else {
definition.between_bytes_timeout_ms = 0;
if ((backend_config.between_bytes_timeout.is_some =
!betweenBytesTimeoutSlot.isNullOrUndefined())) {
backend_config.between_bytes_timeout.val = betweenBytesTimeoutSlot.toInt32();
}

auto useSslSlot = JS::GetReservedSlot(backend, Backend::Slots::UseSsl);
if ((backend_config.use_ssl.is_some = !useSslSlot.isNullOrUndefined())) {
backend_config.use_ssl.val = useSslSlot.toBoolean();
}

auto tlsMinVersion = JS::GetReservedSlot(backend, Backend::Slots::TlsMinVersion);
if (!tlsMinVersion.isNullOrUndefined()) {
definition.ssl_min_version = tlsMinVersion.toInt32();
backend_config_mask |= BACKEND_CONFIG_SSL_MIN_VERSION;
} else {
definition.ssl_min_version = 0;
if ((backend_config.ssl_min_version.is_some = !tlsMinVersion.isNullOrUndefined())) {
backend_config.ssl_min_version.val = (int8_t)tlsMinVersion.toInt32();
}

auto tlsMaxVersion = JS::GetReservedSlot(backend, Backend::Slots::TlsMaxVersion);
if (!tlsMaxVersion.isNullOrUndefined()) {
definition.ssl_max_version = tlsMaxVersion.toInt32();
backend_config_mask |= BACKEND_CONFIG_SSL_MAX_VERSION;
} else {
definition.ssl_max_version = 0;
if ((backend_config.ssl_max_version.is_some = !tlsMaxVersion.isNullOrUndefined())) {
backend_config.ssl_max_version.val = (int8_t)tlsMaxVersion.toInt32();
}

std::optional<std::string> certificateHostname;
std::string certificateHostname;
auto certificateHostnameSlot = JS::GetReservedSlot(backend, Backend::Slots::CertificateHostname);
if (!certificateHostnameSlot.isNullOrUndefined()) {
if ((backend_config.cert_hostname.is_some = !certificateHostnameSlot.isNullOrUndefined())) {
JS::RootedString certificateHostnameString(cx, certificateHostnameSlot.toString());
size_t certificateHostname_len;
JS::UniqueChars certificateHostnameChars =
encode(cx, certificateHostnameString, &certificateHostname_len);
certificateHostname = std::string(certificateHostnameChars.get(), certificateHostname_len);
backend_config.cert_hostname.val.ptr = const_cast<char *>(certificateHostname.c_str());
backend_config.cert_hostname.val.len = certificateHostname.length();
}

std::optional<std::string> caCertificate;
std::string caCertificate;
auto caCertificateSlot = JS::GetReservedSlot(backend, Backend::Slots::CaCertificate);
if (!caCertificateSlot.isNullOrUndefined()) {
if ((backend_config.ca_cert.is_some = !caCertificateSlot.isNullOrUndefined())) {
JS::RootedString caCertificateString(cx, caCertificateSlot.toString());
size_t caCertificate_len;
JS::UniqueChars caCertificateChars = encode(cx, caCertificateString, &caCertificate_len);
caCertificate = std::string(caCertificateChars.get(), caCertificate_len);
backend_config.ca_cert.val.ptr = const_cast<char *>(caCertificate.c_str());
backend_config.ca_cert.val.len = caCertificate.length();
}

std::optional<std::string> ciphers;
std::string ciphers;
auto ciphersSlot = JS::GetReservedSlot(backend, Backend::Slots::Ciphers);
if (!ciphersSlot.isNullOrUndefined()) {
if ((backend_config.ciphers.is_some = !ciphersSlot.isNullOrUndefined())) {
JS::RootedString ciphersString(cx, ciphersSlot.toString());
size_t ciphers_len;
JS::UniqueChars ciphersChars = encode(cx, ciphersString, &ciphers_len);
ciphers = std::string(ciphersChars.get(), ciphers_len);
backend_config.ciphers.val.ptr = const_cast<char *>(ciphers.c_str());
backend_config.ciphers.val.len = ciphers.length();
}

std::optional<std::string> sniHostname;
std::string sniHostname;
auto sniHostnameSlot = JS::GetReservedSlot(backend, Backend::Slots::SniHostname);
if (!sniHostnameSlot.isNullOrUndefined()) {
if ((backend_config.sni_hostname.is_some = !sniHostnameSlot.isNullOrUndefined())) {
JS::RootedString sniHostnameString(cx, sniHostnameSlot.toString());
size_t sniHostname_len;
JS::UniqueChars sniHostnameChars = encode(cx, sniHostnameString, &sniHostname_len);
sniHostname = std::string(sniHostnameChars.get(), sniHostname_len);
backend_config.sni_hostname.val.ptr = const_cast<char *>(sniHostname.c_str());
backend_config.sni_hostname.val.len = sniHostname.length();
}

auto useSslSlot = JS::GetReservedSlot(backend, Backend::Slots::UseSsl);
if (!useSslSlot.isNullOrUndefined() && useSslSlot.toBoolean()) {
backend_config_mask |= BACKEND_CONFIG_USE_SSL;
}

JS::RootedString name(cx, JS::GetReservedSlot(backend, Backend::Slots::Name).toString());
size_t name_len;
JS::UniqueChars nameChars = encode(cx, name, &name_len);
auto name_cstr = nameChars.get();

JS::RootedString target(cx, JS::GetReservedSlot(backend, Backend::Slots::Target).toString());
size_t target_len;
JS::UniqueChars targetChars = encode(cx, target, &target_len);
auto target_cstr = targetChars.get();
if (hostOverride.has_value()) {
backend_config_mask |= BACKEND_CONFIG_HOST_OVERRIDE;
definition.host_override = hostOverride.value().c_str();
definition.host_override_len = hostOverride.value().length();
}
if (certificateHostname.has_value()) {
backend_config_mask |= BACKEND_CONFIG_CERT_HOSTNAME;
definition.cert_hostname = certificateHostname.value().c_str();
definition.cert_hostname_len = certificateHostname.value().length();
}
if (caCertificate.has_value()) {
backend_config_mask |= BACKEND_CONFIG_CA_CERT;
definition.ca_cert = caCertificate.value().c_str();
definition.ca_cert_len = caCertificate.value().length();
}
if (ciphers.has_value()) {
backend_config_mask |= BACKEND_CONFIG_CIPHERS;
definition.ciphers = ciphers.value().c_str();
definition.ciphers_len = ciphers.value().length();
}
if (sniHostname.has_value()) {
backend_config_mask |= BACKEND_CONFIG_SNI_HOSTNAME;
definition.sni_hostname = sniHostname.value().c_str();
definition.sni_hostname_len = sniHostname.value().length();
}

auto result = xqd_req_register_dynamic_backend(name_cstr, name_len, target_cstr, target_len,
backend_config_mask, &definition);
if (!HANDLE_RESULT(cx, result)) {
fastly_error_t err;
auto result =
xqd_fastly_http_req_register_dynamic_backend(&name_str, &target_str, &backend_config, &err);
if (!HANDLE_RESULT(cx, result, err)) {
return JS::Result<mozilla::Ok>(JS::Error());
} else {
return mozilla::Ok();
Expand Down
14 changes: 7 additions & 7 deletions c-dependencies/js-compute-runtime/builtins/cache-override.cpp
Expand Up @@ -64,22 +64,22 @@ void CacheOverride::set_pci(JSObject *self, bool pci) {
JS::SetReservedSlot(self, CacheOverride::Slots::PCI, JS::BooleanValue(pci));
}

uint32_t CacheOverride::abi_tag(JSObject *self) {
uint8_t CacheOverride::abi_tag(JSObject *self) {
switch (CacheOverride::mode(self)) {
case CacheOverride::CacheOverrideMode::None:
return (uint32_t)CacheOverrideTag::None;
return (uint8_t)CacheOverrideTag::None;
case CacheOverride::CacheOverrideMode::Pass:
return (uint32_t)CacheOverrideTag::Pass;
return (uint8_t)CacheOverrideTag::Pass;
default:;
}

uint32_t tag = 0;
uint8_t tag = 0;
if (!ttl(self).isUndefined())
tag |= (uint32_t)CacheOverrideTag::TTL;
tag |= (uint8_t)CacheOverrideTag::TTL;
if (!swr(self).isUndefined())
tag |= (uint32_t)CacheOverrideTag::SWR;
tag |= (uint8_t)CacheOverrideTag::SWR;
if (!pci(self).isUndefined())
tag |= (uint32_t)CacheOverrideTag::PCI;
tag |= (uint8_t)CacheOverrideTag::PCI;

return tag;
}
Expand Down
Expand Up @@ -41,7 +41,7 @@ class CacheOverride : public BuiltinImpl<CacheOverride> {

static const JSFunctionSpec methods[];
static const JSPropertySpec properties[];
static uint32_t abi_tag(JSObject *self);
static uint8_t abi_tag(JSObject *self);
static JS::Value ttl(JSObject *self);
static void set_ttl(JSObject *self, uint32_t ttl);
static JS::Value swr(JSObject *self);
Expand Down

0 comments on commit 197504c

Please sign in to comment.