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 DOM headers `append` and `delete` #13004

Merged
merged 2 commits into from Sep 12, 2016
Merged

Conversation

@jeenalee
Copy link
Contributor

jeenalee commented Aug 23, 2016

Two changes are included in this PR:

  1. A resolved TODO comment in delete is removed.
  2. append method adds a space after a comma when combining header values. Expected wpt results are updated with this change.

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

This change is Reviewable

The confusion around step 4 of `delete` method has been resolved through whatwg/fetch#372.
@highfive
Copy link

highfive commented Aug 23, 2016

Heads up! This PR modifies the following files:

  • @KiChjang: components/script/dom/headers.rs
@jeenalee
Copy link
Contributor Author

jeenalee commented Aug 23, 2016

r? @jdm

@highfive highfive assigned jdm and unassigned SimonSapin Aug 23, 2016
@@ -86,6 +86,7 @@ impl HeadersMethods for Headers {
if let Some(v) = self.header_list.borrow().get_raw(&valid_name) {
combined_value = v[0].clone();
combined_value.push(b","[0]);
combined_value.push(b" "[0]);

This comment has been minimized.

@Ms2ger

Ms2ger Aug 24, 2016

Contributor

b' ' with single quotes would work; perhaps you want .extend_from_slice(b", "), though.

This comment has been minimized.

@nox

nox Aug 24, 2016

Member

@jeenalee Are you sure this is what should be done here? According to the spec, "append" is not the same as "combine".

This comment has been minimized.

@malisas

malisas Aug 24, 2016

Contributor

The underlying hyper::header::Headers's HashMap insert method overwrites entries instead of appending. As a result of this, for a given header name there is at most one value in the inner "header list"/HashMap. I recall that we were debating whether to re-write hyper::header::Headers or re-write our Append function. We ended up going with the latter. Therefore we ended up combining all the values for a given name together. (I changed the append function to reflect that in this PR).

This comment has been minimized.

@jeenalee

jeenalee Aug 24, 2016

Author Contributor

@nox I'll add a comment so that it doesn't cause confusion in the future.

This comment has been minimized.

@jeenalee

jeenalee Aug 24, 2016

Author Contributor

@Ms2ger That's a really good point! I was wondering how we can compress those two lines into one.

This comment has been minimized.

@nox

nox Aug 24, 2016

Member

I think each element in the raw vector corresponds to a single header value, so instead of doing v[0].clone() it seems to me like a new vector should be pushed in v, unfortunately it's just a slice and not the underlaying vector. Cc @seanmonstar.

This comment has been minimized.

@jeenalee

jeenalee Aug 24, 2016

Author Contributor

@nox @seanmonstar Here is a snippet of the irc conversation in regards to append and combine.

This comment has been minimized.

@seanmonstar

seanmonstar Aug 24, 2016

Contributor

I wasn't aware that you were working with the raw bytes of the Header. In that case, it's likely more according to the spec to add a new 'line'. It seems that there is missing method to do this, get_raw_mut, but it would otherwise look like this:

match headers.get_raw_mut("foo") {
    Some(mut raw) => raw.push(value),
    None => headers.set_raw("foo", vec![value])
}
@jdm
Copy link
Member

jdm commented Aug 24, 2016

Commit 2 is interesting, since the specification does not mention adding a space. We should either modify the specification or modify the tests before proceeding.

@jeenalee
Copy link
Contributor Author

jeenalee commented Aug 24, 2016

@@ -85,7 +85,7 @@ impl HeadersMethods for Headers {
let mut combined_value: Vec<u8> = vec![];
if let Some(v) = self.header_list.borrow().get_raw(&valid_name) {

This comment has been minimized.

@KiChjang

KiChjang Aug 24, 2016

Member

I highly suspect that we can do something fancy here, such as filter_map on the header_list iterator.

@KiChjang
Copy link
Member

KiChjang commented Aug 24, 2016

I recall having this conversation with @seanmonstar before, on whether OWS should be present or not when converting Hyper types into string representation (Hyper does not "remember" OWS). The conclusion IIRC was to do exactly what this PR is doing - by stringizing every Header and appending commas and OWS as we see fit, in order to pass our WPT tests.

Also see web-platform-tests/wpt#2807 for prior discussions in modifying WPT expected values to match normalized formats.

@jdm
Copy link
Member

jdm commented Aug 24, 2016

I don't believe OWS is an issue here. The Fetch specification says that combined header values should be separated by a , (no space); that's unrelated to the actual header content.

@jdm
Copy link
Member

jdm commented Aug 24, 2016

Oh, and to be clear on what I'm looking for here - let's take a survey of the various browsers that implement the Headers API (Firefox and Chrome, at minimum) and see what their behaviour is here, then we can decide whether we should be filing a spec issue to resolve this.

@jeenalee jeenalee mentioned this pull request Sep 1, 2016
@jdm
Copy link
Member

jdm commented Sep 1, 2016

@jeenalee Have you investigated what other browsers do with respect to returning combined header values and the separating character?

@jeenalee
Copy link
Contributor Author

jeenalee commented Sep 2, 2016

@jdm Malisa and I just spent some time figuring this out.

I'm confused because MDN's definition of Headers.get() is different from the Fetch spec link MDN lists in the bottom of the page. According to MDN, the get() method returns the first value of a given header, while Fetch states that get() returns the combined value. MDN writes that Headers.getAll would return an array containing all values.

Chrome and Firefox seem to follow MDN's definition. I tried out one of the failing headers/headers-combine.html wpt subtests:

  • Firefox:
> var headerSeqCombine = [["single", "singleValue"],
                          ["double", "doubleValue1"],
                          ["double", "doubleValue2"],
                          ["triple", "tripleValue1"],
                          ["triple", "tripleValue2"],
                          ["triple", "tripleValue3"]
                         ];
undefined
> var headers = new Headers(headerSeqCombine);
undefined
> headers.get("double")
"doubleValue1"
> headers.getAll("double")
Array [ "doubleValue1", "doubleValue2" ]
  • Chrome:
> var headerSeqCombine = [["single", "singleValue"],
                          ["double", "doubleValue1"],
                          ["double", "doubleValue2"],
                          ["triple", "tripleValue1"],
                          ["triple", "tripleValue2"],
                          ["triple", "tripleValue3"]
                         ];
undefined
> var headers = new Headers(headerSeqCombine);
undefined
> headers.get("double")
"doubleValue1"
> headers.getAll("double")
["doubleValue1", "doubleValue2"]

Also, this line in another failing headers-combine.html subtest caught my attention. When (value + ", " + "newSingleValue") is changed to (value + "," + "newSingleValue"), the subtest passes.

Trying the failing subtest on Firefox and Chrome makes me think they did not implement Headers that conform to the Fetch spec. If they were to run the headers-combine.html tests, they would fail because get() will return only one value, and no combining will happen. And the fact that Firefox and Chrome's getAll() return an array of multiple elements makes us believe they aren't combining values at all, which is different from the Fetch spec.

The confusion around get and getAll aside, I can think of two options:

  1. Add a space after comma when appending values (in Servo). This will make tests pass, and the spec will have to be changed.
  2. Tests are modified (no more space), and the spec stays the same. It's difficult to compare our current implementation to Firefox and Chrome's so I'm not sure if this will make Servo's Headers behave more or less similar to theirs.

Finally, it seems like Firefox and Chrome might in fact internally store header values as a vector of u8-vectors, in which each header value is its own vector. So we might want to implement the get_raw_mut function @seanmonstar suggested.

@jdm
Copy link
Member

jdm commented Sep 2, 2016

The Fetch spec changed since get/getAll were implemented in Firefox, so https://bugzilla.mozilla.org/show_bug.cgi?id=1278275 will be very relevant. Fun times!

@jdm
Copy link
Member

jdm commented Sep 6, 2016

Since #3646 merged, you can revert the change to add spaces to the combined header values. The tests will start passing after we update our local copy of the upstream repository.

@seanmonstar
Copy link
Contributor

seanmonstar commented Sep 6, 2016

@jdm is that the correct issue linked?

Instead of creating an array with length of 1 of `b','`, then pushing
the first element of that array to `combined_value`, push a `b','`
directly to `combined_value`.

The web platform test for combining headers has been updated to reflect
the Fetch
spec (web-platform-tests/wpt#3646). The expected
web platform test results that will be affected by this change are updated.
@jeenalee jeenalee force-pushed the jeenalee:combine-headers branch from 7fc4d85 to 8946a65 Sep 6, 2016
@jeenalee
Copy link
Contributor Author

jeenalee commented Sep 7, 2016

@jdm
Copy link
Member

jdm commented Sep 12, 2016

@bors-servo
Copy link
Contributor

bors-servo commented Sep 12, 2016

📌 Commit 8946a65 has been approved by jdm

@bors-servo
Copy link
Contributor

bors-servo commented Sep 12, 2016

Testing commit 8946a65 with merge 7264592...

bors-servo added a commit that referenced this pull request Sep 12, 2016
Update DOM headers `append` and `delete`

<!-- Please describe your changes on the following line: -->
Two changes are included in this PR:
1. A resolved TODO comment in `delete` is removed.
2. `append` method adds a space after a comma when combining header values. Expected wpt results are updated with this change.

---
<!-- 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
- [ ] These changes fix #__ (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/13004)
<!-- Reviewable:end -->
@bors-servo
Copy link
Contributor

bors-servo commented Sep 12, 2016

@bors-servo bors-servo merged commit 8946a65 into servo:master Sep 12, 2016
3 checks passed
3 checks passed
continuous-integration/appveyor/pr AppVeyor build succeeded
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.

None yet

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