Skip to content

Commit 857f6fa

Browse files
authored
feat: StarlingMonkey update (#1067)
1 parent c160c4a commit 857f6fa

Some content is hidden

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

45 files changed

+1529
-13781
lines changed

integration-tests/js-compute/fixtures/app/src/response.js

+5
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,11 @@ routes.set('/response/request-body-init', async () => {
7575
return postResp;
7676
});
7777

78+
routes.set('/response/blob', async () => {
79+
const blob = new Blob(['<h1>blob</h1>'], { type: 'text/html' });
80+
return new Response(blob);
81+
});
82+
7883
function iteratableToStream(iterable) {
7984
return new ReadableStream({
8085
async pull(controller) {

integration-tests/js-compute/fixtures/app/tests.json

+8
Original file line numberDiff line numberDiff line change
@@ -1095,6 +1095,14 @@
10951095
"GET /request/clone/called-unbound": {},
10961096
"GET /request/clone/valid": {},
10971097
"GET /request/clone/invalid": {},
1098+
"GET /response/blob": {
1099+
"environments": ["<disabled for now>"],
1100+
"downstream_response": {
1101+
"status": 200,
1102+
"headers": { "content-type": "text/html" },
1103+
"body": ["<h1>blob</h1>"]
1104+
}
1105+
},
10981106
"GET /response/stall": {
10991107
"body_streaming": "none"
11001108
},

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
"test:cli": "brittle --bail integration-tests/cli/**.test.js",
3232
"test:integration": "node ./integration-tests/js-compute/test.js",
3333
"test:wpt": "tests/wpt-harness/build-wpt-runtime.sh && node ./tests/wpt-harness/run-wpt.mjs -vv",
34-
"test:wpt:debug": "tests/wpt-harness/build-wpt-runtime.sh --debug-build && node ./tests/wpt-harness/run-wpt.mjs --starlingmonkey -vv",
34+
"test:wpt:debug": "tests/wpt-harness/build-wpt-runtime.sh --debug-build && node ./tests/wpt-harness/run-wpt.mjs -vv",
3535
"test:types": "tsd",
3636
"build": "./runtime/fastly/build-release.sh",
3737
"build:debug": "./runtime/fastly/build-debug.sh",

runtime/StarlingMonkey

Submodule StarlingMonkey updated 59 files

runtime/fastly/builtins/cache-core.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -638,7 +638,7 @@ bool CacheEntry::body(JSContext *cx, unsigned argc, JS::Value *vp) {
638638
// pull. With the default HWM of 1.0, the streams implementation causes a
639639
// pull, which means we enqueue a read from the host handle, which we quite
640640
// often have no interest in at all.
641-
JS::RootedObject body_stream(cx, JS::NewReadableDefaultStreamObject(cx, source, nullptr, 0.0));
641+
JS::RootedObject body_stream(cx, NativeStreamSource::stream(source));
642642
if (!body_stream) {
643643
return false;
644644
}

runtime/fastly/builtins/fetch/request-response.cpp

+72-24
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "request-response.h"
22
#include "../../../StarlingMonkey/builtins/web/base64.h"
3+
// #include "../../../StarlingMonkey/builtins/web/blob.h"
34
#include "../../../StarlingMonkey/builtins/web/dom-exception.h"
45
#include "../../../StarlingMonkey/builtins/web/streams/native-stream-source.h"
56
#include "../../../StarlingMonkey/builtins/web/streams/transform-stream.h"
@@ -33,6 +34,8 @@
3334
#pragma clang diagnostic pop
3435

3536
using builtins::web::base64::valueToJSByteString;
37+
// using builtins::web::blob::Blob;
38+
// using builtins::web::blob::BlobReader;
3639
using builtins::web::dom_exception::DOMException;
3740

3841
// We use the StarlingMonkey Headers implementation, despite it supporting features that we do
@@ -65,10 +68,6 @@ using fastly::kv_store::KVStoreEntry;
6568

6669
namespace builtins::web::streams {
6770

68-
JSObject *NativeStreamSource::stream(JSObject *self) {
69-
return fastly::fetch::RequestOrResponse::body_stream(owner(self));
70-
}
71-
7271
bool NativeStreamSource::stream_is_body(JSContext *cx, JS::HandleObject stream) {
7372
JSObject *stream_source = get_stream_source(cx, stream);
7473
return NativeStreamSource::is_instance(stream_source) &&
@@ -80,16 +79,15 @@ bool NativeStreamSource::stream_is_body(JSContext *cx, JS::HandleObject stream)
8079
namespace fastly::fetch {
8180

8281
namespace {
83-
bool error_stream_controller_with_pending_exception(JSContext *cx, JS::HandleObject controller) {
82+
bool error_stream_controller_with_pending_exception(JSContext *cx, JS::HandleObject stream) {
8483
JS::RootedValue exn(cx);
8584
if (!JS_GetPendingException(cx, &exn))
8685
return false;
8786
JS_ClearPendingException(cx);
8887

89-
JS::RootedValueArray<1> args(cx);
90-
args[0].set(exn);
91-
JS::RootedValue r(cx);
92-
return JS::Call(cx, controller, "error", args, &r);
88+
RootedValue args(cx);
89+
args.set(exn);
90+
return JS::ReadableStreamError(cx, stream, args);
9391
}
9492

9593
constexpr size_t HANDLE_READ_CHUNK_SIZE = 8192;
@@ -101,18 +99,18 @@ bool process_body_read(JSContext *cx, host_api::HttpBody::Handle handle, JS::Han
10199
MOZ_ASSERT(NativeStreamSource::is_instance(streamSource));
102100
host_api::HttpBody body(handle);
103101
JS::RootedObject owner(cx, NativeStreamSource::owner(streamSource));
104-
JS::RootedObject controller(cx, NativeStreamSource::controller(streamSource));
102+
JS::RootedObject stream(cx, NativeStreamSource::stream(streamSource));
105103

106104
auto read_res = body.read(HANDLE_READ_CHUNK_SIZE);
107105
if (auto *err = read_res.to_err()) {
108106
HANDLE_ERROR(cx, *err);
109-
return error_stream_controller_with_pending_exception(cx, controller);
107+
return error_stream_controller_with_pending_exception(cx, stream);
110108
}
111109

112110
auto &chunk = read_res.unwrap();
113111
if (chunk.len == 0) {
114112
JS::RootedValue r(cx);
115-
return JS::Call(cx, controller, "close", JS::HandleValueArray::empty(), &r);
113+
return JS::ReadableStreamClose(cx, stream);
116114
}
117115

118116
// We don't release control of chunk's data until after we've checked that the array buffer
@@ -122,7 +120,7 @@ bool process_body_read(JSContext *cx, host_api::HttpBody::Handle handle, JS::Han
122120
cx, JS::NewArrayBufferWithContents(cx, chunk.len, chunk.ptr.get(),
123121
JS::NewArrayBufferOutOfMemory::CallerMustFreeMemory));
124122
if (!buffer) {
125-
return error_stream_controller_with_pending_exception(cx, controller);
123+
return error_stream_controller_with_pending_exception(cx, stream);
126124
}
127125

128126
// At this point `buffer` has taken full ownership of the chunk's data.
@@ -133,11 +131,10 @@ bool process_body_read(JSContext *cx, host_api::HttpBody::Handle handle, JS::Han
133131
return false;
134132
}
135133

136-
JS::RootedValueArray<1> enqueue_args(cx);
137-
enqueue_args[0].setObject(*byte_array);
138-
JS::RootedValue r(cx);
139-
if (!JS::Call(cx, controller, "enqueue", enqueue_args, &r)) {
140-
return error_stream_controller_with_pending_exception(cx, controller);
134+
RootedValue enqueue_val(cx);
135+
enqueue_val.setObject(*byte_array);
136+
if (!JS::ReadableStreamEnqueue(cx, stream, enqueue_val)) {
137+
return error_stream_controller_with_pending_exception(cx, stream);
141138
}
142139

143140
return true;
@@ -349,6 +346,7 @@ bool RequestOrResponse::extract_body(JSContext *cx, JS::HandleObject self,
349346
const char *content_type = nullptr;
350347

351348
// We currently support five types of body inputs:
349+
// - Blob
352350
// - byte sequence
353351
// - buffer source
354352
// - USV strings
@@ -360,6 +358,45 @@ bool RequestOrResponse::extract_body(JSContext *cx, JS::HandleObject self,
360358

361359
JS::RootedObject body_obj(cx, body_val.isObject() ? &body_val.toObject() : nullptr);
362360

361+
host_api::HostString host_type_str;
362+
363+
// Blob support disabled pending bug fix in test
364+
// /override-content-length/request/init/object-literal/true
365+
/*if (body_obj && Blob::is_instance(body_obj)) {
366+
auto native_stream = NativeStreamSource::create(cx, body_obj, JS::UndefinedHandleValue,
367+
Blob::stream_pull, Blob::stream_cancel);
368+
if (!native_stream) {
369+
return false;
370+
}
371+
372+
JS::RootedObject source(cx, native_stream);
373+
if (!source) {
374+
return false;
375+
}
376+
377+
auto readers = Blob::readers(body_obj);
378+
auto blob = Blob::blob(body_obj);
379+
auto span = std::span<uint8_t>(blob->begin(), blob->length());
380+
381+
if (!readers->put(source, BlobReader(span))) {
382+
return false;
383+
}
384+
385+
JS::RootedObject stream(cx, NativeStreamSource::stream(native_stream));
386+
if (!stream) {
387+
return false;
388+
}
389+
390+
JS_SetReservedSlot(self, static_cast<uint32_t>(RequestOrResponse::Slots::BodyStream),
391+
JS::ObjectValue(*stream));
392+
393+
JS::RootedString type_str(cx, Blob::type(body_obj));
394+
if (JS::GetStringLength(type_str) > 0) {
395+
host_type_str = core::encode(cx, type_str);
396+
MOZ_ASSERT(host_type_str);
397+
content_type = host_type_str.ptr.get();
398+
}
399+
} else */
363400
if (body_obj && JS::IsReadableStream(body_obj)) {
364401
if (RequestOrResponse::body_unusable(cx, body_obj)) {
365402
JS_ReportErrorNumberLatin1(cx, FastlyGetErrorMessage, nullptr,
@@ -547,7 +584,19 @@ bool RequestOrResponse::parse_body(JSContext *cx, JS::HandleObject self, JS::Uni
547584
}
548585
static_cast<void>(buf.release());
549586
result.setObject(*array_buffer);
550-
} else {
587+
}
588+
// TODO: Blob support disabled pending bug fix
589+
/* else if constexpr (result_type == RequestOrResponse::BodyReadResult::Blob) {
590+
JS::RootedString contentType(cx, JS_GetEmptyString(cx));
591+
JS::RootedObject blob(cx, Blob::create(cx, std::move(buf), len, contentType));
592+
593+
if (!blob) {
594+
return RejectPromiseWithPendingError(cx, result_promise);
595+
}
596+
597+
result.setObject(*blob);
598+
} */
599+
else {
551600
JS::RootedString text(cx, JS_NewStringCopyUTF8N(cx, JS::UTF8Chars(buf.get(), len)));
552601
if (!text) {
553602
return RejectPromiseWithPendingError(cx, result_promise);
@@ -1185,11 +1234,7 @@ JSObject *RequestOrResponse::create_body_stream(JSContext *cx, JS::HandleObject
11851234
if (!source)
11861235
return nullptr;
11871236

1188-
// Create a readable stream with a highwater mark of 0.0 to prevent an eager
1189-
// pull. With the default HWM of 1.0, the streams implementation causes a
1190-
// pull, which means we enqueue a read from the host handle, which we quite
1191-
// often have no interest in at all.
1192-
JS::RootedObject body_stream(cx, JS::NewReadableDefaultStreamObject(cx, source, nullptr, 0.0));
1237+
JS::RootedObject body_stream(cx, NativeStreamSource::stream(source));
11931238
if (!body_stream) {
11941239
return nullptr;
11951240
}
@@ -1647,6 +1692,8 @@ const JSPropertySpec Request::static_properties[] = {
16471692
const JSFunctionSpec Request::methods[] = {
16481693
JS_FN("arrayBuffer", Request::bodyAll<RequestOrResponse::BodyReadResult::ArrayBuffer>, 0,
16491694
JSPROP_ENUMERATE),
1695+
// JS_FN("blob", Request::bodyAll<RequestOrResponse::BodyReadResult::Blob>, 0,
1696+
// JSPROP_ENUMERATE),
16501697
JS_FN("json", Request::bodyAll<RequestOrResponse::BodyReadResult::JSON>, 0, JSPROP_ENUMERATE),
16511698
JS_FN("text", Request::bodyAll<RequestOrResponse::BodyReadResult::Text>, 0, JSPROP_ENUMERATE),
16521699
JS_FN("setCacheOverride", Request::setCacheOverride, 3, JSPROP_ENUMERATE),
@@ -2900,6 +2947,7 @@ const JSPropertySpec Response::static_properties[] = {
29002947
const JSFunctionSpec Response::methods[] = {
29012948
JS_FN("arrayBuffer", bodyAll<RequestOrResponse::BodyReadResult::ArrayBuffer>, 0,
29022949
JSPROP_ENUMERATE),
2950+
// JS_FN("blob", bodyAll<RequestOrResponse::BodyReadResult::Blob>, 0, JSPROP_ENUMERATE),
29032951
JS_FN("json", bodyAll<RequestOrResponse::BodyReadResult::JSON>, 0, JSPROP_ENUMERATE),
29042952
JS_FN("text", bodyAll<RequestOrResponse::BodyReadResult::Text>, 0, JSPROP_ENUMERATE),
29052953
JS_FN("setManualFramingHeaders", Response::setManualFramingHeaders, 1, JSPROP_ENUMERATE),

runtime/fastly/builtins/fetch/request-response.h

+2
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ class RequestOrResponse final {
5757

5858
enum class BodyReadResult {
5959
ArrayBuffer,
60+
Blob,
6061
JSON,
6162
Text,
6263
};
@@ -214,6 +215,7 @@ class Response final : public builtins::BuiltinImpl<Response> {
214215
HasBody = static_cast<int>(RequestOrResponse::Slots::HasBody),
215216
BodyUsed = static_cast<int>(RequestOrResponse::Slots::BodyUsed),
216217
Headers = static_cast<int>(RequestOrResponse::Slots::Headers),
218+
URL = static_cast<int>(RequestOrResponse::Slots::Headers),
217219
ManualFramingHeaders = static_cast<int>(RequestOrResponse::Slots::ManualFramingHeaders),
218220
Backend = static_cast<int>(RequestOrResponse::Slots::Backend),
219221
IsUpstream = static_cast<int>(RequestOrResponse::Slots::Count),

0 commit comments

Comments
 (0)