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 and apply fetch rework #2

Closed
wants to merge 60 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
3ccefb2
fix fetch attempt
nicoburniske Apr 30, 2024
2d29ef5
fix fetch test by locking stream
nicoburniske Apr 30, 2024
d2636ec
enable all tests again
nicoburniske Apr 30, 2024
0473061
remove obsolete comment
nicoburniske Apr 30, 2024
fe217ce
fetch test body ReadableStream
nicoburniske Apr 30, 2024
98bf330
add post test (failing)
nicoburniske Apr 30, 2024
ba679d5
comment out headers only body post test
nicoburniske Apr 30, 2024
7975f3b
debugging fetch-3
nicoburniske May 1, 2024
6347825
add header logs
nicoburniske May 8, 2024
9bdfce6
Merge remote-tracking branch 'origin/main' into fetch-fix-updated
nicoburniske May 8, 2024
2e883a7
Debug and fix attempts
vigoo May 13, 2024
b509286
attempt to extract value before subscribing
nicoburniske May 13, 2024
a1df1ba
update fetch-3 unit test
nicoburniske May 13, 2024
0de1f11
More debug and fixes
vigoo May 13, 2024
ef48a6e
add async stream fetch test 4
nicoburniske May 20, 2024
383f138
remove debug stderror logs
nicoburniske May 20, 2024
717c191
Merge pull request #1 from nicoburniske/fetch-fix-updated
nicoburniske May 20, 2024
0ee4e92
Merge branch 'bytecodealliance:main' into main
nicoburniske May 20, 2024
b101905
small clean up
nicoburniske May 20, 2024
f666d6d
clean up
nicoburniske May 20, 2024
76f5f40
small cleanup
nicoburniske May 20, 2024
c9b42e4
small cleanup
nicoburniske May 20, 2024
62ea77d
more cleanup
nicoburniske May 20, 2024
d0bb3bf
remove fetch-4 test
nicoburniske May 20, 2024
f7aacf1
remove clean_test.sh
nicoburniske May 20, 2024
62acc86
Merge pull request #1 from golemcloud/fetch-fixes
vigoo May 24, 2024
34cf1ef
Use SpiderMonkey's encoding_c instead of our own crate
tschneidereit May 29, 2024
0d02283
Change WPT support to use a CMake option instead of an env var
tschneidereit Apr 18, 2024
bfe3158
WIP: rework headers
tschneidereit Mar 13, 2024
86db17e
WIP: rework headers
tschneidereit Mar 22, 2024
d4e43db
Immediately lock reified body stream when the underlying body has alr…
tschneidereit Apr 6, 2024
dae6953
More headers rework!
tschneidereit Apr 10, 2024
aa5a32c
Use `string_view` instead of `HostString in core::decode`
tschneidereit Apr 29, 2024
d1984e9
Adjust namespace of wpt support functionality
tschneidereit Apr 29, 2024
ca335a7
And yet more headers rework—along with an overhaul of lots of the hos…
tschneidereit Apr 29, 2024
3bb6b5d
Support creating a component without evaluating a top-level script du…
tschneidereit May 28, 2024
c8cf151
Slight improvements to the WPT harness
tschneidereit May 28, 2024
c44b816
Substantially more reworking of the fetch related host API surface
tschneidereit May 28, 2024
2d68405
fix: release build on fetch rework (#54)
guybedford May 29, 2024
3027305
feat: single-tick non-tracking event loop runner
guybedford May 29, 2024
2e23c54
fixup
guybedford May 29, 2024
5bdb946
fixup
guybedford May 29, 2024
55566e9
fix event loop interest handling
guybedford May 29, 2024
4b3f9f5
simplify single tick
guybedford May 29, 2024
1d17ace
simpler loop
guybedford May 30, 2024
6a8ae9e
fixup return paths
guybedford May 30, 2024
2bad18a
Use a templated WASIHandle class to represent handles for WASI 0.2.0
tschneidereit Jun 1, 2024
ec28998
Fix bugs in runtime-evaluation
tschneidereit Jun 2, 2024
429daec
Fix bugs in headers handling
tschneidereit Jun 2, 2024
a0781f0
Make the `extract body` spec operation work for outgoing requests and…
tschneidereit Jun 2, 2024
7f4ba5a
Lock request/response body when consuming it for `.text()`, `.arrayBu…
tschneidereit Jun 2, 2024
e2f3b37
Fix handling of various value types when extracting request/response …
tschneidereit Jun 2, 2024
2d7fc1b
Revert "Merge pull request #1 from golemcloud/fetch-fixes"
noise64 Jun 3, 2024
895fab7
Merge remote-tracking branch 'upstream/main'
noise64 Jun 3, 2024
b48d4b1
Merge remote-tracking branch 'upstream/fetch-rework' into update-upst…
noise64 Jun 3, 2024
4820fdf
Remove some outdated comments and TODOs
tschneidereit Jun 3, 2024
f992afe
Ensure that the `ResponseFutureTask` is enqueued for streaming requests
tschneidereit Jun 3, 2024
f40bafb
Fix streaming of outgoing bodies and setting their content-length header
tschneidereit Jun 3, 2024
e8870ef
Merge remote-tracking branch 'refs/remotes/upstream/fetch-rework' int…
noise64 Jun 4, 2024
25bb72d
Merge remote-tracking branch 'upstream/single-tick' into update-upstr…
noise64 Jun 5, 2024
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
9 changes: 6 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,20 +36,22 @@ include("openssl")
include("host_api")
include("build-crates")

add_library(extension_api INTERFACE include/extension-api.h runtime/encode.h)
add_library(extension_api INTERFACE include/extension-api.h runtime/encode.h runtime/decode.h)
target_link_libraries(extension_api INTERFACE rust-url spidermonkey)
target_include_directories(extension_api INTERFACE include deps/include runtime)

include("builtins")

if (DEFINED ENV{WPT})
option(ENABLE_WPT "Enable WPT harness support" OFF)
if (ENABLE_WPT)
include("tests/wpt-harness/wpt.cmake")
endif()

add_executable(starling.wasm
runtime/js.cpp
runtime/allocator.cpp
runtime/encode.cpp
runtime/decode.cpp
runtime/engine.cpp
runtime/event_loop.cpp
runtime/builtin.cpp
Expand Down Expand Up @@ -94,13 +96,14 @@ function(componentize OUTPUT)
add_custom_command(
OUTPUT ${OUTPUT}.wasm
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMAND ${CMAKE_COMMAND} -E env "PATH=${WASM_TOOLS_DIR};${WIZER_DIR};$ENV{PATH}" ${RUNTIME_DIR}/componentize.sh ${SOURCES} ${OUTPUT}.wasm
COMMAND ${CMAKE_COMMAND} -E env "PATH=${WASM_TOOLS_DIR};${WIZER_DIR};$ENV{PATH}" ${RUNTIME_DIR}/componentize.sh ${SOURCES} -o ${OUTPUT}.wasm
DEPENDS ${ARG_SOURCES} ${RUNTIME_DIR}/componentize.sh starling.wasm
VERBATIM
)
add_custom_target(${OUTPUT} DEPENDS ${OUTPUT}.wasm)
endfunction()

componentize(smoke-test SOURCES tests/cases/smoke/smoke.js)
componentize(runtime-eval)

include("tests/tests.cmake")
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,12 @@ StarlingMonkey includes a test runner for the [Web Platform Tests](https://web-p

### Requirements

The WPT runner requires `Node.js` to be installed, and during build configuration the environment variable `WPT` must be defined.
The WPT runner requires `Node.js` to be installed, and during build configuration the option `ENABLE_WPT:BOOL=ON` must be set.

When running the test, `WPT_ROOT` must be set to the path of a checkout of the WPT suite at revision `1014eae5e66f8f334610d5a1521756f7a2fb769f`:

```bash
WPT=1 WPT_ROOT=[path to your WPT checkout] cmake -S . -B cmake-build-debug -DCMAKE_BUILD_TYPE=Debug
WPT_ROOT=[path to your WPT checkout] cmake -S . -B cmake-build-debug -DENABLE_WPT:BOOL=ON -DCMAKE_BUILD_TYPE=Debug
cmake --build cmake-build-debug --parallel 8 --target wpt-runtime
cd cmake-build-debug
ctest --verbose # Note: some of the tests run fairly slowly in debug builds, so be patient
Expand Down
124 changes: 54 additions & 70 deletions builtins/web/fetch/fetch-api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,67 +3,13 @@
#include "headers.h"
#include "request-response.h"

namespace builtins::web::fetch {

static api::Engine *ENGINE;

class ResponseFutureTask final : public api::AsyncTask {
Heap<JSObject *> request_;
host_api::FutureHttpIncomingResponse *future_;

public:
explicit ResponseFutureTask(const HandleObject request,
host_api::FutureHttpIncomingResponse *future)
: request_(request), future_(future) {
auto res = future->subscribe();
MOZ_ASSERT(!res.is_err(), "Subscribing to a future should never fail");
handle_ = res.unwrap();
}

[[nodiscard]] bool run(api::Engine *engine) override {
// MOZ_ASSERT(ready());
JSContext *cx = engine->cx();

const RootedObject request(cx, request_);
RootedObject response_promise(cx, Request::response_promise(request));

auto res = future_->maybe_response();
if (res.is_err()) {
JS_ReportErrorUTF8(cx, "NetworkError when attempting to fetch resource.");
return RejectPromiseWithPendingError(cx, response_promise);
}

auto maybe_response = res.unwrap();
MOZ_ASSERT(maybe_response.has_value());
auto response = maybe_response.value();
RootedObject response_obj(
cx, JS_NewObjectWithGivenProto(cx, &Response::class_, Response::proto_obj));
if (!response_obj) {
return false;
}

response_obj = Response::create(cx, response_obj, response);
if (!response_obj) {
return false;
}

RequestOrResponse::set_url(response_obj, RequestOrResponse::url(request));
RootedValue response_val(cx, ObjectValue(*response_obj));
if (!ResolvePromise(cx, response_promise, response_val)) {
return false;
}
#include <encode.h>

return cancel(engine);
}
#include <memory>

[[nodiscard]] bool cancel(api::Engine *engine) override {
// TODO(TS): implement
handle_ = -1;
return true;
}
namespace builtins::web::fetch {

void trace(JSTracer *trc) override { TraceEdge(trc, &request_, "Request for response future"); }
};
static api::Engine *ENGINE;

// TODO: throw in all Request methods/getters that rely on host calls once a
// request has been sent. The host won't let us act on them anymore anyway.
Expand All @@ -80,30 +26,66 @@ bool fetch(JSContext *cx, unsigned argc, Value *vp) {
return ReturnPromiseRejectedWithPendingError(cx, args);
}

RootedObject requestInstance(
RootedObject request_obj(
cx, JS_NewObjectWithGivenProto(cx, &Request::class_, Request::proto_obj));
if (!requestInstance)
return false;
if (!request_obj) {
return ReturnPromiseRejectedWithPendingError(cx, args);
}

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

RootedObject request(cx, Request::create(cx, requestInstance, args[0], args.get(1)));
if (!request) {
RootedString method_str(cx, Request::method(cx, request_obj));
if (!method_str) {
return ReturnPromiseRejectedWithPendingError(cx, args);
}

host_api::HostString method = core::encode(cx, method_str);
if (!method.ptr) {
return ReturnPromiseRejectedWithPendingError(cx, args);
}

RootedValue url_val(cx, RequestOrResponse::url(request_obj));
host_api::HostString url = core::encode(cx, url_val);
if (!url.ptr) {
return ReturnPromiseRejectedWithPendingError(cx, args);
}

unique_ptr<host_api::HttpHeaders> headers;
RootedObject headers_obj(cx, RequestOrResponse::maybe_headers(request_obj));
if (headers_obj) {
headers = Headers::handle_clone(cx, headers_obj);
} else {
headers = std::make_unique<host_api::HttpHeaders>();
}

if (!headers) {
return ReturnPromiseRejectedWithPendingError(cx, args);
}

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));

RootedObject response_promise(cx, JS::NewPromiseObject(cx, nullptr));
if (!response_promise)
return ReturnPromiseRejectedWithPendingError(cx, args);

bool streaming = false;
if (!RequestOrResponse::maybe_stream_body(cx, request, &streaming)) {
if (!RequestOrResponse::maybe_stream_body(cx, request_obj, &streaming)) {
return false;
}
if (streaming) {
// Ensure that the body handle is stored before making the request handle invalid by sending it.
request->body();
}

host_api::FutureHttpIncomingResponse *pending_handle;
{
auto request_handle = Request::outgoing_handle(request);
auto res = request_handle->send();

auto res = request->send();
if (auto *err = res.to_err()) {
HANDLE_ERROR(cx, *err);
return ReturnPromiseRejectedWithPendingError(cx, args);
Expand All @@ -115,11 +97,13 @@ bool fetch(JSContext *cx, unsigned argc, Value *vp) {
// If the request body is streamed, we need to wait for streaming to complete
// before marking the request as pending.
if (!streaming) {
ENGINE->queue_async_task(new ResponseFutureTask(request, pending_handle));
ENGINE->queue_async_task(new ResponseFutureTask(request_obj, pending_handle));
}

JS::SetReservedSlot(request, static_cast<uint32_t>(Request::Slots::ResponsePromise),
JS::ObjectValue(*response_promise));
SetReservedSlot(request_obj, static_cast<uint32_t>(Request::Slots::ResponsePromise),
ObjectValue(*response_promise));
SetReservedSlot(request_obj, static_cast<uint32_t>(Request::Slots::PendingResponseHandle),
PrivateValue(pending_handle));

args.rval().setObject(*response_promise);
return true;
Expand Down
Loading
Loading