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
feat(fetch): accept arraybuffer in consume_body #20406
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Your code was doing the right thing, just not in the most efficient way. All of the tests that now pass are tests that were either directly testing the arrayBuffer() behaviour or relying on arrayBuffer() to test the behaviour of the Fetch API, so this is a great result!
components/script/body.rs
Outdated
} | ||
|
||
pub enum FetchedData { | ||
Text(String), | ||
Json(JSValue), | ||
BlobData(DomRoot<Blob>), | ||
FormData(DomRoot<FormData>), | ||
ArrayBuffer(Heap<JSVal>), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To ensure this code is GC-safe, we should use RootedTraceableBox<Heap<JSVal>>
, and use it for the Json variant as well.
components/script/body.rs
Outdated
} | ||
|
||
// https://fetch.spec.whatwg.org/#concept-body-consume-body | ||
#[allow(unrooted_must_root)] | ||
pub fn consume_body<T: BodyOperations + DomObject>(object: &T, body_type: BodyType) -> Rc<Promise> { | ||
let promise = Promise::new(&object.global()); | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: remove this blank line.
components/script/body.rs
Outdated
@@ -166,6 +176,26 @@ fn run_form_data_algorithm(root: &GlobalScope, bytes: Vec<u8>, mime: &[u8]) -> F | |||
} | |||
} | |||
|
|||
#[allow(unsafe_code)] | |||
fn run_array_buffer_data_algorithm(cx: *mut JSContext, bytes: Vec<u8>) -> Fallible<FetchedData> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function should be marked unsafe, since it accepts a raw pointer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
New errors are fine; we can add #[allow(unsafe_code)] on the containing functions. We want to avoid declaring functions as safe when it is trivially possible to pass an invalid pointer that would trigger a crash.
components/script/body.rs
Outdated
unsafe { | ||
match ArrayBuffer::create(cx, CreateWith::Slice(&bytes), array_buffer_ptr.handle_mut()) { | ||
Ok(_) => { | ||
let mut arraybuffer = Some(FetchedData::ArrayBuffer(Heap::default())); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This part is a bit jumbled, but the basic idea is correct. What about:
rooted!(in(cx) let mut array_buffer_ptr = ptr::null_mut::<JSObject>());
let arraybuffer = ArrayBuffer::create(cx, CreateWith::Slice(&bytes), array_buffer_ptr.handle_mut());
if arraybuffer.is_err() {
return Err(Error::JSFailed);
}
let rooted_heap = RootedTraceableBox::from_box(Heap::boxed(array_buffer_ptr.get()));
Ok(FetchedData::ArrayBuffer(rooted_heap))
2a12369
to
f2b0cd4
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jdm Appreciate for taking time to review! 🙇♂️ I tried to update code as much as suggested, and left few question / comments around changes.
components/script/body.rs
Outdated
@@ -166,6 +176,26 @@ fn run_form_data_algorithm(root: &GlobalScope, bytes: Vec<u8>, mime: &[u8]) -> F | |||
} | |||
} | |||
|
|||
#[allow(unsafe_code)] | |||
fn run_array_buffer_data_algorithm(cx: *mut JSContext, bytes: Vec<u8>) -> Fallible<FetchedData> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
components/script/body.rs
Outdated
if arraybuffer.is_err() { | ||
return Err(Error::JSFailed); | ||
} | ||
let rooted_heap = RootedTraceableBox::from_box(Heap::boxed(jsval::ObjectValue(array_buffer_ptr.get()))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
appreciate for suggestion and tried to update code as suggested, except creating boxed heap using ObjectValue - since type of ArrayBuffer is RootedTraceableBox<Heap<JSVal>>
, using ptr directly creates RootedTraceableBox<Heap<mut *JSObject>>
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, let's make it a bit cleaner then - store RootedTraceableBox<Heap<*mut JSObject>>
and get rid of the jsval::ObjectValue
.
components/script/body.rs
Outdated
} | ||
|
||
pub enum FetchedData { | ||
Text(String), | ||
Json(JSValue), | ||
BlobData(DomRoot<Blob>), | ||
FormData(DomRoot<FormData>), | ||
ArrayBuffer(RootedTraceableBox<Heap<JSVal>>), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm bit unsure if I understood #20406 (comment) fully around use it for the Json variant as well.
- would you mind elaborate bit more?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean that the existing Json(JSValue)
is similarly GC-unsafe, and it should store a RootedTraceableBox<Heap<JSVal>>
instead.
f2b0cd4
to
80304a1
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jdm now type for Arraybuffer updated to Heap<*mut JSObect>
, also added commit for updating types for JSON as well.
} | ||
|
||
pub enum FetchedData { | ||
Text(String), | ||
Json(JSValue), | ||
Json(RootedTraceableBox<Heap<JSValue>>), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated Json to store RootedTraceableBox<Heap>
as suggested. Still it stores JSValue
instead of JSVal
, by JSVal
doesn't meet trait bounds for RootedTraceableBox
.
@@ -104,6 +112,9 @@ fn run_package_data_algorithm<T: BodyOperations + DomObject>(object: &T, | |||
BodyType::Json => run_json_data_algorithm(cx, bytes), | |||
BodyType::Blob => run_blob_data_algorithm(&global, bytes, mime), | |||
BodyType::FormData => run_form_data_algorithm(&global, bytes, mime), | |||
BodyType::ArrayBuffer => unsafe { | |||
run_array_buffer_data_algorithm(cx, bytes) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
now run_array_buffer_data_algorithm
is declared as unsafe fn, and this match arm uses unsafe scope.
@bors-servo r+ |
📌 Commit 80304a1 has been approved by |
@@ -1,5 +1,3 @@ | |||
[response-stream-disturbed-5.html] | |||
type: testharness | |||
[Getting a body reader after consuming as arrayBuffer] | |||
expected: FAIL |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this file be deleted altogether?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It will be automatically in the future.
feat(fetch): accept arraybuffer in consume_body <!-- Please describe your changes on the following line: --> Related to #20346. I realized I am not sufficiently knowledgeable about codebases and have high confidence this PR is not ready to be accepted. Raising it as PR early to possibly ask some suggestions around codebases. If this PR seems unrecoverable by code review, please feel freely close and unassign me from issue 🙏 This PR tries to implement #20346, updating `Body` idl and implements corresponding implementation in `body.rs` for `fetch`. Criteria for changes may includes - does `run_array_buffer_data_algorithm` implementation is legit for allocating arraybuffer? (probably not) - does `run_array_buffer_data_algorithm` implementation is acceptable for handling error, by naively returning `Error::JSFailed`? - there are some number of wpt test started to PASS with this PR. Is this legit side effect, or something incorrect by current implementation? - etcs, vice versa --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors - [x] These changes fix #20346 (github issue number if applicable). <!-- Either: --> - [ ] There are tests for these changes OR - [ ] These changes do not require tests because _____ - wpt test has changed in PR, need to be reviewed. <!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.--> <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/20406) <!-- Reviewable:end -->
☀️ Test successful - android, arm32, arm64, linux-dev, linux-rel-css, linux-rel-wpt, mac-dev-unit, mac-rel-css1, mac-rel-css2, mac-rel-wpt1, mac-rel-wpt2, mac-rel-wpt3, mac-rel-wpt4, windows-msvc-dev |
Related to #20346.
I realized I am not sufficiently knowledgeable about codebases and have high confidence this PR is not ready to be accepted. Raising it as PR early to possibly ask some suggestions around codebases.
If this PR seems unrecoverable by code review, please feel freely close and unassign me from issue 🙏
This PR tries to implement #20346, updating
Body
idl and implements corresponding implementation inbody.rs
forfetch
. Criteria for changes may includesrun_array_buffer_data_algorithm
implementation is legit for allocating arraybuffer? (probably not)run_array_buffer_data_algorithm
implementation is acceptable for handling error, by naively returningError::JSFailed
?./mach build -d
does not report any errors./mach test-tidy
does not report any errorsThis change is