Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update upstream #6

Merged
merged 13 commits into from
Aug 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 29 additions & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,39 @@ jobs:
run: |
CTEST_OUTPUT_ON_FAILURE=1 ctest --test-dir cmake-build-debug -j4

test-weval:
name: Test Weval
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2

- name: Install Rust 1.77.1
run: |
rustup toolchain install 1.77.1
rustup target add wasm32-wasi --toolchain 1.77.1

- uses: actions/setup-node@v2
with:
node-version: 'lts/*'

- name: Build StarlingMonkey
run: |
cmake -S . -B cmake-build-weval -DCMAKE_BUILD_TYPE=Release -DUSE_WASM_OPT=OFF -DWEVAL=ON
cmake --build cmake-build-weval --parallel 4 --target all integration-test-server

- name: StarlingMonkey E2E & Integration Tests
run: |
CTEST_OUTPUT_ON_FAILURE=1 ctest --test-dir cmake-build-weval -j4

wpt:
name: Web Platform Tests
strategy:
matrix:
build: [release]
build: [release, debug]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
Expand Down
58 changes: 45 additions & 13 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ include("init-corrosion")
include("wasm-tools")
include("binaryen")
include("wizer")
include("weval")
include("wasmtime")

include("fmt")
Expand Down Expand Up @@ -58,29 +59,60 @@ add_executable(starling.wasm
runtime/script_loader.cpp
)

option(USE_WASM_OPT "use wasm-opt to optimize the StarlingMonkey binary" ON)

# For release builds, use wasm-opt to optimize the generated wasm file.
if (CMAKE_BUILD_TYPE STREQUAL "Release")
add_custom_command(
TARGET starling.wasm
POST_BUILD
COMMAND ${WASM_OPT} --strip-debug -O3 -o starling.wasm starling.wasm
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
)
elseif (CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
add_custom_command(
if (USE_WASM_OPT)
if (CMAKE_BUILD_TYPE STREQUAL "Release")
add_custom_command(
TARGET starling.wasm
POST_BUILD
COMMAND ${WASM_OPT} --strip-debug -O3 -o starling.wasm starling.wasm
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
)
elseif (CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
add_custom_command(
TARGET starling.wasm
POST_BUILD
COMMAND ${WASM_OPT} -O3 -o starling.wasm starling.wasm
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
)
endif()
else()
if (CMAKE_BUILD_TYPE STREQUAL "Release")
add_custom_command(
TARGET starling.wasm
POST_BUILD
COMMAND ${WASM_OPT} -O3 -o starling.wasm starling.wasm
COMMAND ${WASM_OPT} --strip-debug -O0 -o starling.wasm starling.wasm
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
)
)
endif()
endif()


target_link_libraries(starling.wasm PRIVATE host_api extension_api builtins spidermonkey rust-url)

# build a compilation cache of ICs
if(WEVAL)
include("weval")
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/null.js "function main() {}")
add_custom_target(
starling-ics.wevalcache
ALL
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMAND rm -f starling-ics.wevalcache
COMMAND echo ./null.js | ${WEVAL_BIN} weval --dir . --show-stats --cache starling-ics.wevalcache -w -i starling.wasm -o /dev/null
DEPENDS starling.wasm
VERBATIM
)
set(WEVAL_CACHE_FILE "starling-ics.wevalcache")
set(AOT 1)
else()
set(AOT 0)
endif()

set(RUNTIME_FILE "starling.wasm")
set(ADAPTER_FILE "preview1-adapter.wasm")
configure_file("componentize.sh" "${CMAKE_CURRENT_BINARY_DIR}/componentize.sh" COPYONLY)
configure_file("componentize.sh" "${CMAKE_CURRENT_BINARY_DIR}/componentize.sh" @ONLY)
configure_file(${ADAPTER} "${CMAKE_CURRENT_BINARY_DIR}/${ADAPTER_FILE}" COPYONLY)
configure_file(spin.toml spin.toml COPYONLY)

Expand Down
52 changes: 52 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,3 +160,55 @@ name of one of the directories. Currently, only an implementation in terms of [w
(host-apis/wasi-0.2.0) is provided, and used by default.

To provide a custom host API implementation, you can set `HOST_API` to the (absolute) path of a directory containing that implementation.

## Developing Changes to SpiderMonkey

StarlingMonkey uses SpiderMonkey as its underlying JS engine, and by default,
downloads build artifacts from [a wrapper
repository](https://github.com/bytecodealliance/spidermonkey-wasi-embedding)
around [our local SpiderMonkey
tree](https://github.com/bytecodealliance/gecko-dev). That wrapper repository
contains a SpiderMonkey commit-hash in a file, and its CI jobs build the
artifacts that StarlingMonkey downloads during its build.

This flow is optimized for ease of development of StarlingMonkey, and avoiding
the need to build SpiderMonkey locally, which requires some additional tools
and is resource-intensive. However, sometimes it is necessary or desirable to
make modifications to SpiderMonkey directly, whether to make fixes or optimize
performance.

In order to do so, first clone the above two repositories, with `gecko-dev`
(SpiderMonkey itself) as a subdirectory to `spidermonkey-wasi-embedding`:

```shell
git clone https://github.com/bytecodealliance/spidermonkey-wasi-embedding
cd spidermonkey-wasi-embedding/
git clone https://github.com/bytecodealliance/gecko-dev
```

and switch to the commit that we are currently using:

```shell
git checkout `cat ../gecko-revision`
# now edit the source
```

Then make changes as necessary, eventually rebuilding from the
`spidermonkey-wasi-embedding` root:

```shell
cd ../ # back to spidermonkey-wasi-embedding
./rebuild.sh release
```

This will produce a `release/` directory with artifacts of the same form
normally downloaded by StarlingMonkey. So, finally, from within StarlingMonkey,
set an environment variable `SPIDERMONKEY_BINARIES`:

```shell
export SPIDERMONKEY_BINARIES=/path/to/spidermonkey-wasi-embedding/release
cmake -S . -B cmake-build-release -DCMAKE_BUILD_TYPE=Release
cmake --build cmake-build-release --parallel 8
```

and use/test as above.
18 changes: 8 additions & 10 deletions builtins/web/fetch/fetch-api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

#include <memory>

using builtins::web::fetch::Headers;

namespace builtins::web::fetch {

static api::Engine *ENGINE;
Expand All @@ -31,15 +33,12 @@ bool fetch(JSContext *cx, unsigned argc, Value *vp) {
return ReturnPromiseRejectedWithPendingError(cx, args);
}

if (!Request::initialize(cx, request_obj, args[0], args.get(1))) {
return ReturnPromiseRejectedWithPendingError(cx, args);
}

RootedString method_str(cx, Request::method(cx, request_obj));
if (!method_str) {
if (!Request::initialize(cx, request_obj, args[0], args.get(1),
Headers::HeadersGuard::Immutable)) {
return ReturnPromiseRejectedWithPendingError(cx, args);
}

RootedString method_str(cx, Request::method(request_obj));
host_api::HostString method = core::encode(cx, method_str);
if (!method.ptr) {
return ReturnPromiseRejectedWithPendingError(cx, args);
Expand All @@ -51,14 +50,13 @@ bool fetch(JSContext *cx, unsigned argc, Value *vp) {
return ReturnPromiseRejectedWithPendingError(cx, args);
}

unique_ptr<host_api::HttpHeaders> headers = RequestOrResponse::headers_handle_clone(cx,
request_obj, host_api::HttpHeadersGuard::Request);
unique_ptr<host_api::HttpHeaders> headers =
RequestOrResponse::headers_handle_clone(cx, request_obj);
if (!headers) {
return ReturnPromiseRejectedWithPendingError(cx, args);
}

auto request = host_api::HttpOutgoingRequest::make(method, std::move(url),
std::move(headers));
auto request = host_api::HttpOutgoingRequest::make(method, std::move(url), std::move(headers));
MOZ_RELEASE_ASSERT(request);
JS_SetReservedSlot(request_obj, static_cast<uint32_t>(Request::Slots::Request),
PrivateValue(request));
Expand Down
2 changes: 2 additions & 0 deletions builtins/web/fetch/fetch-errors.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ DEF_ERR(InvalidInitArg, JSEXN_TYPEERR, "{0}: |init| parameter can't be converted
DEF_ERR(NonBodyRequestWithBody, JSEXN_TYPEERR, "Request constructor: HEAD or GET Request cannot have a body", 0)
DEF_ERR(NonBodyResponseWithBody, JSEXN_TYPEERR, "Response constructor: response with status {0} cannot have a body", 1)
DEF_ERR(BodyStreamUnusable, JSEXN_TYPEERR, "Can't use a ReadableStream that's locked or has ever been read from or canceled", 0)
DEF_ERR(BodyStreamTeeingFailed, JSEXN_ERR, "Cloning body stream failed", 0)
DEF_ERR(InvalidStatus, JSEXN_RANGEERR, "{0}: invalid status {1}", 2)
DEF_ERR(InvalidStreamChunk, JSEXN_TYPEERR, "ReadableStream used as a Request or Response body must produce Uint8Array values", 0)
DEF_ERR(EmptyHeaderName, JSEXN_TYPEERR, "{0}: Header name can't be empty", 1)
DEF_ERR(InvalidHeaderName, JSEXN_TYPEERR, "{0}: Invalid header name \"{1}\"", 2)
DEF_ERR(InvalidHeaderValue, JSEXN_TYPEERR, "{0}: Invalid header value \"{1}\"", 2)
DEF_ERR(HeadersCloningFailed, JSEXN_ERR, "Failed to clone headers", 0)
DEF_ERR(HeadersImmutable, JSEXN_TYPEERR, "{0}: Headers are immutable", 1)
}; // namespace FetchErrors

#endif // FETCH_ERRORS_H
30 changes: 11 additions & 19 deletions builtins/web/fetch/fetch_event.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,8 +167,7 @@ bool send_response(host_api::HttpOutgoingResponse *response, JS::HandleObject se

bool start_response(JSContext *cx, JS::HandleObject response_obj) {
auto status = Response::status(response_obj);
auto headers = RequestOrResponse::headers_handle_clone(cx, response_obj,
host_api::HttpHeadersGuard::Response);
auto headers = RequestOrResponse::headers_handle_clone(cx, response_obj);
if (!headers) {
return false;
}
Expand Down Expand Up @@ -252,16 +251,15 @@ bool FetchEvent::respondWith(JSContext *cx, unsigned argc, JS::Value *vp) {

// Step 2
if (!is_dispatching(self)) {
return dom_exception::DOMException::raise(cx,
"FetchEvent#respondWith must be called synchronously from within a FetchEvent handler",
"InvalidStateError");
return dom_exception::DOMException::raise(
cx, "FetchEvent#respondWith must be called synchronously from within a FetchEvent handler",
"InvalidStateError");
}

// Step 3
if (state(self) != State::unhandled) {
return dom_exception::DOMException::raise(cx,
"FetchEvent#respondWith can't be called twice on the same event",
"InvalidStateError");
return dom_exception::DOMException::raise(
cx, "FetchEvent#respondWith can't be called twice on the same event", "InvalidStateError");
}

// Step 4
Expand Down Expand Up @@ -293,7 +291,7 @@ bool FetchEvent::respondWith(JSContext *cx, unsigned argc, JS::Value *vp) {
bool FetchEvent::respondWithError(JSContext *cx, JS::HandleObject self) {
MOZ_RELEASE_ASSERT(state(self) == State::unhandled || state(self) == State::waitToRespond);

auto headers = std::make_unique<host_api::HttpHeaders>(host_api::HttpHeadersGuard::Response);
auto headers = std::make_unique<host_api::HttpHeaders>();
auto *response = host_api::HttpOutgoingResponse::make(500, std::move(headers));

auto body_res = response->body();
Expand Down Expand Up @@ -331,9 +329,7 @@ bool FetchEvent::waitUntil(JSContext *cx, unsigned argc, JS::Value *vp) {
// Step 2
if (!is_active(self)) {
return dom_exception::DOMException::raise(
cx,
"waitUntil called on a FetchEvent that isn't active anymore",
"InvalidStateError");
cx, "waitUntil called on a FetchEvent that isn't active anymore", "InvalidStateError");
}

// Steps 3-4
Expand All @@ -345,13 +341,9 @@ bool FetchEvent::waitUntil(JSContext *cx, unsigned argc, JS::Value *vp) {
return true;
}

void FetchEvent::increase_interest() {
inc_pending_promise_count(INSTANCE);
}
void FetchEvent::increase_interest() { inc_pending_promise_count(INSTANCE); }

void FetchEvent::decrease_interest() {
dec_pending_promise_count(INSTANCE);
}
void FetchEvent::decrease_interest() { dec_pending_promise_count(INSTANCE); }

const JSFunctionSpec FetchEvent::static_methods[] = {
JS_FS_END,
Expand Down Expand Up @@ -571,7 +563,7 @@ bool eval_request_body(host_api::HttpIncomingRequest *request) {
return true;
}

bool handle_incoming_request(host_api::HttpIncomingRequest * request) {
bool handle_incoming_request(host_api::HttpIncomingRequest *request) {
#ifdef DEBUG
fprintf(stderr, "Warning: Using a DEBUG build. Expect things to be SLOW.\n");
#endif
Expand Down
Loading
Loading