Skip to content

feat(fetch): Add Response.redirect() and Response.json() statics#5044

Closed
RajdeepKushwaha5 wants to merge 6 commits intoboa-dev:mainfrom
RajdeepKushwaha5:fix/issue-5042-response-redirect-json
Closed

feat(fetch): Add Response.redirect() and Response.json() statics#5044
RajdeepKushwaha5 wants to merge 6 commits intoboa-dev:mainfrom
RajdeepKushwaha5:fix/issue-5042-response-redirect-json

Conversation

@RajdeepKushwaha5
Copy link

@RajdeepKushwaha5 RajdeepKushwaha5 commented Mar 13, 2026

Resolves #5042

Description:

This PR implements the missing static properties on the Response fetch object (Response.redirect() and Response.json()).

  • Response.redirect(url, status): Maps the arguments directly. Validates standard HTTP status bounds handling 301, 302, 303, 307, and 308, defaulting dynamically to 302. Adds the necessary Location assignment directly onto the payload mapping of JsHeaders. Throws an engine RangeError if the status code isn't supported.
  • Response.json(data, init): Evaluates JSON parsing intrinsically through JS using stringify.call(...) directly interfacing the Context namespace. Ensures that the static wrapper safely binds the payload type of "application/json" unless explicitly manipulated through HTTP arguments internally!

Coverage: Evaluated core/runtime/src/fetch/tests testing both .json(data, init) overriding states alongside validating JS .redirect() responses against RangeError failures safely.

Signed-off-by: Rajdeep Singh youremail@example.com

Checklist:
-Passed cargo fmt --all and cargo clippy --all --all-features.
-Conforms to ECMAScript and WHATWG Fetch spec implementations.
-Passes native component testing via cargo test -p boa_runtime.

Rajdeep Singh and others added 5 commits March 13, 2026 12:55
Implements proper iterator support for Headers.prototype.entries(), keys(), and values() methods following the WHATWG Fetch specification.

Changes:
- Created HeadersIterator struct to manage iteration state
- Implements entries(), keys(), and values() as proper iterator methods using #[boa(method)]
- Fixed Symbol.iterator binding to call entries() method dynamically
- Headers iterators now properly return [Symbol.iterator] result objects with done/value properties
- Removed invalid downcast pattern from Symbol.iterator handler

Fixes: #4989
This resolves issue #5042.

- Implemented Response.redirect(url, status). Default status is 302. Throws RangeError on invalid status code according to spec.
- Implemented Response.json(data, init). It converts data to JSON using engine's JSON.stringify, and constructs a new Response. Enforces Content-Type: application/json unless overridden in init.headers.
- Added unit tests to core/runtime/src/fetch/tests/response.rs to validate behaviors.
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds missing Fetch Response static constructors to the runtime, extending the existing fetch implementation and its JS interop tests.

Changes:

  • Implement Response.redirect(url, status) and Response.json(data, init) statics on Response.
  • Update Headers iteration to return iterator objects for entries()/keys()/values() and adjust [Symbol.iterator] wiring.
  • Add a runtime loop-iteration limit guard to String.prototype.repeat, plus a regression test.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
core/runtime/src/fetch/response.rs Adds Response.redirect() and Response.json() static constructors.
core/runtime/src/fetch/tests/response.rs Adds JS-level tests for Response.redirect() and Response.json().
core/runtime/src/fetch/mod.rs Changes Headers.prototype[Symbol.iterator] implementation to call entries() via JS property access.
core/runtime/src/fetch/headers.rs Reworks Headers.entries()/keys()/values() to return iterator objects; adds iterator plumbing.
core/engine/src/builtins/string/mod.rs Adds runtime loop-iteration limit guarding to String.prototype.repeat.
core/engine/src/builtins/string/tests.rs Adds a test ensuring repeat() respects the loop runtime limit.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +740 to +744
// Runtime limit guard for native loops inside this builtin.
let previous_iteration_count = context.vm.frame().loop_iteration_count;
let max_iteration_count = context.vm.runtime_limits.loop_iteration_limit();
let loop_iteration_count = previous_iteration_count.saturating_add(n);

Comment on lines +271 to 275
#[boa(method)]
pub fn entries(this: JsClass<Self>, context: &mut Context) -> JsValue {
let iterator = HeadersIterator::new(this.clone_inner(), HeadersIteratorKind::Entries);
create_headers_iterator_object(iterator, context)
}
Comment on lines +172 to +176
fn redirect(url: JsString, status: Option<u16>, _context: &mut Context) -> JsResult<Self> {
let status = status.unwrap_or(302);

if !matches!(status, 301 | 302 | 303 | 307 | 308) {
return Err(JsNativeError::range()
Comment on lines +204 to +213
let json = context.global_object().get(js_string!("JSON"), context)?;
let stringify = json
.as_object()
.ok_or_else(|| JsNativeError::typ().with_message("JSON is not an object"))?
.get(js_string!("stringify"), context)?;

let text = stringify
.as_callable()
.ok_or_else(|| JsNativeError::typ().with_message("stringify is not a function"))?
.call(&json, &[data], context)?;
Comment on lines +214 to +218
// Get the entries method from the prototype and call it
let entries_fn = this_object
.get(js_string!("entries"), context)?;

entries_fn.as_function()
Comment on lines +142 to +151
#[allow(let_underscore_drop)]
let _ = iterator_obj.define_property_or_throw(
js_string!("next"),
PropertyDescriptor::builder()
.value(next_fn)
.writable(true)
.enumerable(false)
.configurable(true),
context,
);
Comment on lines +63 to +66
fn next(&mut self, context: &mut Context) -> JsResult<JsValue> {
let headers_data = self.headers.headers.borrow();
let headers_vec: Vec<_> = headers_data.iter().collect();

@github-actions
Copy link

github-actions bot commented Mar 13, 2026

Test262 conformance changes

Test result main count PR count difference
Total 52,963 52,963 0
Passed 49,935 49,932 -3
Ignored 2,207 2,210 +3
Failed 821 821 0
Panics 0 0 0
Conformance 94.28% 94.28% -0.01%

Tested main commit: f5ae9f7385337d34f68fa9969054efe8c0161305
Tested PR commit: c1c25673592158ac882406d45d5414c80d9153df
Compare commits: f5ae9f7...c1c2567

@codecov
Copy link

codecov bot commented Mar 13, 2026

Codecov Report

❌ Patch coverage is 97.60000% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 59.31%. Comparing base (6ddc2b4) to head (c1c2567).
⚠️ Report is 845 commits behind head on main.

Files with missing lines Patch % Lines
core/runtime/src/fetch/response.rs 93.02% 3 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##             main    #5044       +/-   ##
===========================================
+ Coverage   47.24%   59.31%   +12.06%     
===========================================
  Files         476      563       +87     
  Lines       46892    62612    +15720     
===========================================
+ Hits        22154    37136    +14982     
- Misses      24738    25476      +738     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@jedel1043 jedel1043 closed this Mar 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add Response.redirect() and Response.json() static constructors to fetch runtime

3 participants