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

Allow Request's Headers to be created with various objects #13802

Merged
merged 4 commits into from Nov 9, 2016

Conversation

@jeenalee
Copy link
Contributor

jeenalee commented Oct 17, 2016

While Headers could be constructed correctly with an array or
object (open ended dictionary/MozMap), Request's Headers failed to be
created with non-Headers object (such as array or open ended
dictionary/MozMap).

Before, Request's Headers could be filled with only a Headers object in
Step 28. This has been expanded to accommodate array and open ended
dictionary.

Step 29 empties the Request's Headers list after it had been filled in
Step 28, thus resulting in an empty Headers object when it shouldn't
be. This step has been removed with a comment in this commit.

If a RequestInit Headers is not given, but a RequestInfo Headers is
given, RequestInfo Headers should be used to construct Request
Headers. That step has been added after Step 31.

Corresponding wpt result is updated in this commit.


  • ./mach build -d does not report any errors
  • ./mach test-tidy does not report any errors
  • These changes fix #13758 (github issue number if applicable).
  • There are tests for these changes OR
  • These changes do not require tests because _____

This change is Reviewable

While Headers could be constructed correctly with an array or
object (open ended dictionary/MozMap), Request's Headers failed to be
created with non-Headers object (such as array or open ended
dictionary/MozMap).

Before, Request's Headers could be filled with only a Headers object in
Step 28. This has been expanded to accommodate array and open ended
dictionary.

Step 29 empties the Request's Headers list after it had been filled in
Step 28, thus resulting in an empty Headers object when it shouldn't
be. This step has been removed with a comment in this commit.

If a RequestInit Headers is *not* given, but a RequestInfo Headers is
given, RequestInfo Headers should be used to construct Request
Headers. That step has been added after Step 31.

Corresponding wpt result is updated in this commit.
@highfive
Copy link

highfive commented Oct 17, 2016

Heads up! This PR modifies the following files:

  • @fitzgen: components/script/dom/request.rs
  • @KiChjang: components/script/dom/request.rs
Copy link
Member

emilio left a comment

Sorry for the huge delay @jeenalee :(. Feel free to ping me more often if you see this happens again.

}
}

// Step 29
r.Headers().empty_header_list();
// When r.Headers()'s header list is emptied,
// r.Headers that was filled in Step 28 becomes empty.

This comment has been minimized.

@emilio

emilio Oct 23, 2016

Member

This comment seems confusing to me, could you explain or rephrase it? It seems we can't empty these because otherwise we undo the stuff done above?

If that's the case, we should be doing a deep copy in step 27 then instead.

This comment has been minimized.

@jeenalee

jeenalee Oct 25, 2016

Author Contributor

That's right! Sorry for the confusing wording. We can't empty them because we would undo the stuff done above. I tried your suggestion on doing a deep copy, and got the following:

I cannot understand why, but the following approach does not make the subtest [Testing request header creations with various objects] in request-headers.html pass.
Step 27: let mut headers_copy = r.Headers().clone();
Step 28: fill in headers_copy using HeadersInit (unchanged from the original pull request)
Step 29: r.Headers().empty_header_list();
Step 30: Check whether Request Mode is NoCors (unchanged from the original pull request)
Step 31: After addressing your suggestion below this comment:

match init.headers {
            None => {
                // This is equivalent to the specification's concept of
                // "associated headers list". If an init headers is not given,
                // but an input with headers is given, set request's
                // headers as the input's Headers.
                if let RequestInfo::Request(ref input_request) = input {
                    try!(r.Headers().fill(Some(HeadersInit::Headers(input_request.Headers()))));
                }
            },
            Some(_) => try!(r.Headers().fill(Some(HeadersInit::Headers(headers_copy)))),
        }

Because we set the headers_copy to be a deep copy of r.Headers(), then fill r.Headers() with the headers_copy in Step 31, I think the subtest shouldn't fail.

When we do a deep clone in Step 27, but not empty r.Headers().empty_header_list(); in Step 29, when running wpt, Servo crashes with a message that begins with DOMRefCell<T> already borrowed: BorrowMutError. Here's the backtrace. The error occurs in Header's fill method.

I'm confused! I feel like I'm missing something. Do you have any insights?

This comment has been minimized.

@emilio

emilio Oct 26, 2016

Member

So that backtrace can come from anywhere in the constructor, so it's hard to diagnose based on that.

But a borrow error indicates that you're reading from something while writing to it in general. Something like filling r.headers() with themselves, or holding a borrow to somewhere inside the Headers object can be potential problems.

This comment has been minimized.

@jeenalee

jeenalee Oct 27, 2016

Author Contributor

Hmm. I realized I wasn't making a deep copy. I had to do r.Headers.r().clone() in order to actually make a deep copy.

With this approach though, because r.Headers() is a Root<T>, it becomes difficult to make a mutable reference to r.Headers(). Without the mutable reference, we cannot set r.Headers() to be the deep copied headers in Step 27.

I want to suggest we leave the comment more descriptive (as you wrote above), but not make a deep copy in Step 27.

// "associated headers list". If an init headers is not given,
// but an input with headers is given, set request's
// headers as the input's Headers.
if let None = init.headers {

This comment has been minimized.

@emilio

emilio Oct 23, 2016

Member

nit: if init.headers.is_none(), though this can probably be more legible with a match statement combined with the above if let.

if let RequestInfo::Request(ref input_request) = input {
headers_copy = input_request.Headers();
}

// Step 28

This comment has been minimized.

@emilio

emilio Oct 23, 2016

Member

The step numbers seem to have changed (though that's probably my fault!), feel free to update them if you feel like it :).

This comment has been minimized.

@jeenalee

jeenalee Oct 27, 2016

Author Contributor

I'll leave them as it is for now! It's probably more straightforward to fix them when we update Request Constructor to match the spec :)

@jeenalee
Copy link
Contributor Author

jeenalee commented Oct 24, 2016

@emilio Thanks Emilio! I realized that the Fetch spec has been updated, but our request constructor has not yet. The changes in this PR were based on the older Fetch spec version. Will it make more sense to close this PR, and update the request constructor to match the current Fetch spec first?

@jdm
Copy link
Member

jdm commented Oct 24, 2016

Updating the numbers in a separate commit in the same PR is fine; or doing it separately after. I doubt it's necessary to close this one though.

// `r.Headers()` is a `Root<T>`, and therefore it is difficult
// to obtain a mutable reference to `r.Headers()`. Without the
// mutable reference, we cannot mutate `r.Headers()` to be the
// deep copied headers in Step 27.

This comment has been minimized.

@KiChjang

KiChjang Oct 27, 2016

Member

Does r.headers.set(headers_copy) not work? If so, then you can just create pub fn set_headers(&self, headers: Headers) in impl Request.

This comment has been minimized.

@jeenalee

jeenalee Oct 28, 2016

Author Contributor

Good idea! Hmm, though while it compiles, more tests fail with that change. I'm not sure why.

This comment has been minimized.

@emilio

emilio Oct 28, 2016

Member

Hmmm... So it seems to me we'd need to add a method to Request that creates a new Request with a clone of the inner hyper list, is that right?

I'm totally fine doing it as a followup if @jdm agrees.

@jeenalee
Copy link
Contributor Author

jeenalee commented Oct 28, 2016

I thought this would be a small change until the request Constructor gets updated to match the Fetch spec. While this patch isn't the perfect fix, I feel like we're starting to go down the rabbit hole... I'd say we move forward with the not-perfect fix, or I can close this pull request and focus on updating the constructor!

@emilio
emilio approved these changes Oct 28, 2016
Copy link
Member

emilio left a comment

The rest looks ok to me, thanks for looking into this @jeenalee! :)

// `r.Headers()` is a `Root<T>`, and therefore it is difficult
// to obtain a mutable reference to `r.Headers()`. Without the
// mutable reference, we cannot mutate `r.Headers()` to be the
// deep copied headers in Step 27.

This comment has been minimized.

@emilio

emilio Oct 28, 2016

Member

Hmmm... So it seems to me we'd need to add a method to Request that creates a new Request with a clone of the inner hyper list, is that right?

I'm totally fine doing it as a followup if @jdm agrees.

@jeenalee
Copy link
Contributor Author

jeenalee commented Nov 7, 2016

Hi! Just checking in with this PR. Please let me know if there's anything I can do :)

@jdm
Copy link
Member

jdm commented Nov 7, 2016

Whoops, I didn't realize this was waiting on my input. I'm not thrilled with either the before or after code (or the spec, for that matter), but I don't have concrete suggestions for how to improve any of those pieces. Let's merge this and move on!

@bors-servo: r=emilio

@bors-servo
Copy link
Contributor

bors-servo commented Nov 7, 2016

📌 Commit e821da8 has been approved by emilio

@bors-servo
Copy link
Contributor

bors-servo commented Nov 7, 2016

Testing commit e821da8 with merge 4fc283e...

bors-servo added a commit that referenced this pull request Nov 7, 2016
Allow Request's Headers to be created with various objects

<!-- Please describe your changes on the following line: -->

While Headers could be constructed correctly with an array or
object (open ended dictionary/MozMap), Request's Headers failed to be
created with non-Headers object (such as array or open ended
dictionary/MozMap).

Before, Request's Headers could be filled with only a Headers object in
Step 28. This has been expanded to accommodate array and open ended
dictionary.

Step 29 empties the Request's Headers list after it had been filled in
Step 28, thus resulting in an empty Headers object when it shouldn't
be. This step has been removed with a comment in this commit.

If a RequestInit Headers is _not_ given, but a RequestInfo Headers is
given, RequestInfo Headers should be used to construct Request
Headers. That step has been added after Step 31.

Corresponding wpt result is updated in this commit.
---

<!-- 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 #13758 (github issue number if applicable).

<!-- Either: -->
- [X] There are tests for these changes OR
- [ ] These changes do not require tests because _____

<!-- 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/13802)

<!-- Reviewable:end -->
@bors-servo
Copy link
Contributor

bors-servo commented Nov 8, 2016

💔 Test failed - linux-rel-wpt

@jdm
Copy link
Member

jdm commented Nov 8, 2016

Those are some very unhappy tests! One clear problem:

  ▶ CRASH [expected OK] /fetch/api/request/request-consume.html
  │ 
  │ VMware, Inc.
  │ Gallium 0.4 on softpipe
  │ 3.3 (Core Profile) Mesa 12.0.1
  │ DOMRefCell<T> already borrowed: BorrowMutError (thread ScriptThread PipelineId { namespace_id: PipelineNamespaceId(0), index: PipelineIndex(1) }, at ../src/libcore/result.rs:837)
  │ stack backtrace:
  │    0:     0x7fb63064eafd - backtrace::backtrace::trace::h16372ee7bf1517e5
  │    1:     0x7fb63064f192 - backtrace::capture::Backtrace::new::hcc43c50c4b11c693
  │    2:     0x7fb62f3b00fd - servo::main::_{{closure}}::h8e9c5971861a4720
  │    3:     0x7fb631015b24 - std::panicking::rust_panic_with_hook
  │                         at /buildslave/rust-buildbot/slave/nightly-dist-rustc-linux/build/obj/../src/libstd/panicking.rs:452
  │    4:     0x7fb6310159e4 - std::panicking::begin_panic<collections::string::String>
  │                         at /buildslave/rust-buildbot/slave/nightly-dist-rustc-linux/build/obj/../src/libstd/panicking.rs:413
  │    5:     0x7fb631015909 - std::panicking::begin_panic_fmt
  │                         at /buildslave/rust-buildbot/slave/nightly-dist-rustc-linux/build/obj/../src/libstd/panicking.rs:397
  │    6:     0x7fb631015897 - std::panicking::rust_begin_panic
  │                         at /buildslave/rust-buildbot/slave/nightly-dist-rustc-linux/build/obj/../src/libstd/panicking.rs:373
  │    7:     0x7fb6310522fd - core::panicking::panic_fmt
  │                         at /buildslave/rust-buildbot/slave/nightly-dist-rustc-linux/build/obj/../src/libcore/panicking.rs:69
  │    8:     0x7fb62f9a5035 - core::result::unwrap_failed::h643f371f836203d8
  │    9:     0x7fb62fb348e6 - _<script..dom..headers..Headers as script..dom..bindings..codegen..Bindings..HeadersBinding..HeadersBinding..HeadersMethods>::Append::h1c59f2b40c66fb7e
  │   10:     0x7fb62fb356ce - script::dom::headers::Headers::fill::hd3324ebf20b36137
  │   11:     0x7fb62fbce43f - script::dom::request::Request::Constructor::h3329b257fb1e6789
  │   12:     0x7fb62f896371 - std::panicking::try::do_call::h6e04d3e7d58d6235

I suspect this is the case where headers_copy is both the object being used to fill the new request's headers and the headers being filled - we'll be calling borrow_mut on one and borrow on the other, which won't work.

Instead of filling request's headers whenever a `HeadersInit` is given, this
patch fills request's headers only when `HeadersInit` with a type of
`Headers` is given. Previously, the constructor tried to fill request's headers
with itself, causing Servo to crash.
@jeenalee
Copy link
Contributor Author

jeenalee commented Nov 8, 2016

Oopsies, that's bad! The latest commit should fix that crash.

@KiChjang
Copy link
Member

KiChjang commented Nov 8, 2016

@bors-servo
Copy link
Contributor

bors-servo commented Nov 8, 2016

Trying commit bfd999f with merge 21bc4e0...

bors-servo added a commit that referenced this pull request Nov 8, 2016
Allow Request's Headers to be created with various objects

<!-- Please describe your changes on the following line: -->

While Headers could be constructed correctly with an array or
object (open ended dictionary/MozMap), Request's Headers failed to be
created with non-Headers object (such as array or open ended
dictionary/MozMap).

Before, Request's Headers could be filled with only a Headers object in
Step 28. This has been expanded to accommodate array and open ended
dictionary.

Step 29 empties the Request's Headers list after it had been filled in
Step 28, thus resulting in an empty Headers object when it shouldn't
be. This step has been removed with a comment in this commit.

If a RequestInit Headers is _not_ given, but a RequestInfo Headers is
given, RequestInfo Headers should be used to construct Request
Headers. That step has been added after Step 31.

Corresponding wpt result is updated in this commit.
---

<!-- 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 #13758 (github issue number if applicable).

<!-- Either: -->
- [X] There are tests for these changes OR
- [ ] These changes do not require tests because _____

<!-- 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/13802)

<!-- Reviewable:end -->
@bors-servo
Copy link
Contributor

bors-servo commented Nov 8, 2016

💔 Test failed - linux-rel-wpt

@highfive
Copy link

highfive commented Nov 8, 2016

  ▶ FAIL [expected PASS] /_mozilla/css/inline_block_opacity_change.html
  └   → /_mozilla/css/inline_block_opacity_change.html aed6845267bba6c52d3aa69c4889449b454d8117
/_mozilla/css/inline_block_opacity_change_ref.html febec1b4730afab195f280694dad47200b09ea3c
Testing aed6845267bba6c52d3aa69c4889449b454d8117 == febec1b4730afab195f280694dad47200b09ea3c
@emilio
Copy link
Member

emilio commented Nov 9, 2016

@bors-servo
Copy link
Contributor

bors-servo commented Nov 9, 2016

📌 Commit bfd999f has been approved by emilio

@KiChjang
Copy link
Member

KiChjang commented Nov 9, 2016

@bors-servo retry clean

@jdm
Copy link
Member

jdm commented Nov 9, 2016

@bors-servo: r-
Hold on, I just want to make sure I understand the implications of the latest code change.

@jdm
Copy link
Member

jdm commented Nov 9, 2016

@bors-servo: r+
Ok, I understand how it works.

@bors-servo
Copy link
Contributor

bors-servo commented Nov 9, 2016

📌 Commit bfd999f has been approved by jdm

@highfive highfive assigned jdm and unassigned emilio Nov 9, 2016
bors-servo added a commit that referenced this pull request Nov 9, 2016
Allow Request's Headers to be created with various objects

<!-- Please describe your changes on the following line: -->

While Headers could be constructed correctly with an array or
object (open ended dictionary/MozMap), Request's Headers failed to be
created with non-Headers object (such as array or open ended
dictionary/MozMap).

Before, Request's Headers could be filled with only a Headers object in
Step 28. This has been expanded to accommodate array and open ended
dictionary.

Step 29 empties the Request's Headers list after it had been filled in
Step 28, thus resulting in an empty Headers object when it shouldn't
be. This step has been removed with a comment in this commit.

If a RequestInit Headers is _not_ given, but a RequestInfo Headers is
given, RequestInfo Headers should be used to construct Request
Headers. That step has been added after Step 31.

Corresponding wpt result is updated in this commit.
---

<!-- 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 #13758 (github issue number if applicable).

<!-- Either: -->
- [X] There are tests for these changes OR
- [ ] These changes do not require tests because _____

<!-- 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/13802)

<!-- Reviewable:end -->
@bors-servo
Copy link
Contributor

bors-servo commented Nov 9, 2016

Testing commit bfd999f with merge 9a7559f...

@bors-servo
Copy link
Contributor

bors-servo commented Nov 9, 2016

The build was interrupted to prioritize another pull request.

@bors-servo
Copy link
Contributor

bors-servo commented Nov 9, 2016

Previous build results for mac-dev-unit are reusable. Rebuilding only arm32, arm64, linux-dev, linux-rel-css, linux-rel-wpt, mac-rel-css, mac-rel-wpt1, mac-rel-wpt2, windows-dev...

@bors-servo
Copy link
Contributor

bors-servo commented Nov 9, 2016

@bors-servo bors-servo merged commit bfd999f into servo:master Nov 9, 2016
2 of 3 checks passed
2 of 3 checks passed
continuous-integration/appveyor/pr AppVeyor build failed
Details
continuous-integration/travis-ci/pr The Travis CI build passed
Details
homu Test successful
Details
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked issues

Successfully merging this pull request may close these issues.

6 participants
You can’t perform that action at this time.