<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE bugzilla SYSTEM "https://www.w3.org/Bugs/Public/page.cgi?id=bugzilla.dtd">

<bugzilla version="5.0.4"
          urlbase="https://www.w3.org/Bugs/Public/"
          
          maintainer="sysbot+bugzilla@w3.org"
>

    <bug>
          <bug_id>26217</bug_id>
          
          <creation_ts>2014-06-27 02:01:23 +0000</creation_ts>
          <short_desc>&quot;If header does not contain two items&quot;</short_desc>
          <delta_ts>2014-06-27 21:47:55 +0000</delta_ts>
          <reporter_accessible>1</reporter_accessible>
          <cclist_accessible>1</cclist_accessible>
          <classification_id>1</classification_id>
          <classification>Unclassified</classification>
          <product>WHATWG</product>
          <component>Fetch</component>
          <version>unspecified</version>
          <rep_platform>PC</rep_platform>
          <op_sys>Linux</op_sys>
          <bug_status>RESOLVED</bug_status>
          <resolution>FIXED</resolution>
          
          
          <bug_file_loc></bug_file_loc>
          <status_whiteboard></status_whiteboard>
          <keywords></keywords>
          <priority>P2</priority>
          <bug_severity>normal</bug_severity>
          <target_milestone>Unsorted</target_milestone>
          
          
          <everconfirmed>1</everconfirmed>
          <reporter name="Matt Falkenhagen">falken</reporter>
          <assigned_to name="Anne">annevk</assigned_to>
          <cc>bkelly</cc>
    
    <cc>bzbarsky</cc>
    
    <cc>d</cc>
    
    <cc>jaffathecake</cc>
    
    <cc>mike</cc>
          
          <qa_contact>sideshowbarker+fetchspec</qa_contact>

      

      

      

          <comment_sort_order>oldest_to_newest</comment_sort_order>  
          <long_desc isprivate="0" >
    <commentid>108409</commentid>
    <comment_count>0</comment_count>
    <who name="Matt Falkenhagen">falken</who>
    <bug_when>2014-06-27 02:01:23 +0000</bug_when>
    <thetext>http://fetch.spec.whatwg.org/#headers-class

[[
If header does not contain two items
]]

Does this mean &quot;exactly two items&quot; or &quot;at least two items&quot;?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>108414</commentid>
    <comment_count>1</comment_count>
    <who name="Anne">annevk</who>
    <bug_when>2014-06-27 06:55:08 +0000</bug_when>
    <thetext>I meant exactly two when I wrote it, but now I&apos;m thinking that being somewhat forgiving might be okay too.

Opinions anyone?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>108425</commentid>
    <comment_count>2</comment_count>
    <who name="Ben Kelly">bkelly</who>
    <bug_when>2014-06-27 15:39:57 +0000</bug_when>
    <thetext>I read it as exactly two.  Personally I think this is ok as filling the header from the constructor is a convenience and it doesn&apos;t seem critical if it cannot handle all cases.

I also think allowing more than two could confuse some people as they might start wondering, is it this:

  new Headers([
    [&quot;name&quot;, &quot;value1&quot;, &quot;value2&quot;]
  ]);

Or this:

  new Headers([
    [&quot;name, [&quot;value1&quot;, &quot;value2&quot;]]
  ]);

Which I don&apos;t think is possible with sequence&lt;sequence&lt;ByteString&gt;&gt; in webidl.

So my vote is to keep it as exactly two.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>108429</commentid>
    <comment_count>3</comment_count>
    <who name="Domenic Denicola">d</who>
    <bug_when>2014-06-27 17:22:39 +0000</bug_when>
    <thetext>This isn&apos;t working like a normal Map does, which IMO is bad.

Normal Map: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-map-iterable

Summarized:

for (var x of iterable) {
  var [k, v] = x;
  this.set(k, v);
}

Note that it only throws if x is not an object. If x is [], it will add (undefined, undefined). If x is [1, 2, 3], it will add (1, 2). If x is { 0: &quot;foo&quot;, 1: &quot;bar&quot; }, it will add (&quot;foo&quot;, &quot;bar&quot;).

Note also that it explicitly calls `this.set`, which is important and should be preserved.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>108431</commentid>
    <comment_count>4</comment_count>
    <who name="Anne">annevk</who>
    <bug_when>2014-06-27 19:29:49 +0000</bug_when>
    <thetext>Domenic, I recommend filing a bug on IDL. If we are going to ship a first iteration by Q3 that is not going to be fixed that way.

I fixed comment 0 per comment 2 meanwhile:

https://github.com/whatwg/fetch/commit/fb8df66cdd69e5a5afcdd7e213875ec8cd299b10</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>108432</commentid>
    <comment_count>5</comment_count>
    <who name="Boris Zbarsky">bzbarsky</who>
    <bug_when>2014-06-27 19:42:40 +0000</bug_when>
    <thetext>&gt;  var [k, v] = x;
&gt;  Note that it only throws if x is not an object.

Are you sure?  http://people.mozilla.org/~jorendorff/es6-draft.html#sec-runtime-semantics-destructuringassignmentevaluation says the RHS gets iterated, albeit only as many times as there are things in the brackets on the LHS, which is subtly different from what sequence&lt;&gt; will do.

It may be good to have an explicit way in IDL of expressing &quot;iterator, get N values from it&quot; for use here.

Note that UAs don&apos;t necessarily implement the spec here yet, though they&apos;re working on it.  e.g. see https://bugzilla.mozilla.org/show_bug.cgi?id=933276

&gt; Note also that it explicitly calls `this.set`, which is important and should be
&gt; preserved.

That&apos;s important if you want to allow subclassing and specifically want to allow subclasses to hook this constructor algorithm via overriding set(), correct?  This is not the only obviously viable API design choice, fwiw.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>108433</commentid>
    <comment_count>6</comment_count>
    <who name="Boris Zbarsky">bzbarsky</who>
    <bug_when>2014-06-27 19:44:15 +0000</bug_when>
    <thetext>Oh, and I think requiring exactly two items in this case for now is not totally unreasonable so people don&apos;t start to depend on other behaviors while we sort this out.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>108434</commentid>
    <comment_count>7</comment_count>
    <who name="Domenic Denicola">d</who>
    <bug_when>2014-06-27 19:53:51 +0000</bug_when>
    <thetext>&gt; Are you sure?  http://people.mozilla.org/~jorendorff/es6-draft.html#sec-runtime-semantics-destructuringassignmentevaluation says the RHS gets iterated, albeit only as many times as there are things in the brackets on the LHS, which is subtly different from what sequence&lt;&gt; will do.

You are right; destructuring was being too clever. It&apos;s really just

var k = x[0];
var v = x[1];

&gt; It may be good to have an explicit way in IDL of expressing &quot;iterator, get N values from it&quot; for use here.

My plan is to add the following to WebIDL:

AddMapElementsFromIterable(iterableInput, dest, adder)

so that this algorithm would do

AddMapElementsFromIterable(init, this, &quot;append&quot;).

I am forking WebIDL and working on a pull request right now, although I am temporarily stymied by the XSLT and the un-Windows-friendly Makefile @_@.

&gt; That&apos;s important if you want to allow subclassing and specifically want to allow subclasses to hook this constructor algorithm via overriding set(), correct?

Yes, or instrumentation, or other aspect oriented programming.

&gt; This is not the only obviously viable API design choice, fwiw.

I agree, but I see no reason to deviate from ES semantics here.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>108435</commentid>
    <comment_count>8</comment_count>
    <who name="Boris Zbarsky">bzbarsky</who>
    <bug_when>2014-06-27 20:03:53 +0000</bug_when>
    <thetext>Having some generic thing to initialize maps makes sense

Note that this:

  for (var x of iterable) {
    var [k, v] = x;
    this.set(k, v);
  }

Also doesn&apos;t match what Map does in ES6.  What it does is actually pretty nasty to express in JS.  It goes more like this, afaict:

  var iterGetter = iterable[Symbol.iterator];
  if (typeof(iterGetter) != &quot;function&quot;) throw new TypeError;

  var iter = iterGetter.call(iterable);
  if (typeof(iter) != &quot;object&quot; || !iter) throw new TypeError;

  var adder = this.set;
  if (typeof(adder) != &quot;function&quot;) throw new TypeError;
  
  // it then checks that &quot;iter&quot; is not undefined, which seems superfluous
  while (true) {
    var val = GetNextValue(iter); // Not going to inline this, complete with the
                                  // break on no more values.
    var k = val[0];
    var v = val[1];
    adder.call(this, k, v);
  }

or so.  Idiomatic JS it&apos;s not.  ;)</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>108436</commentid>
    <comment_count>9</comment_count>
    <who name="Boris Zbarsky">bzbarsky</who>
    <bug_when>2014-06-27 20:04:47 +0000</bug_when>
    <thetext>&gt;  // it then checks that &quot;iter&quot; is not undefined, which seems superfluous

Oh, nevermind, that can happen if the argument is undefined or null.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>108437</commentid>
    <comment_count>10</comment_count>
    <who name="Domenic Denicola">d</who>
    <bug_when>2014-06-27 20:07:06 +0000</bug_when>
    <thetext>What you&apos;re missing is that for-of basically does all those steps for you :). I agree I omitted the typeof check on adder, but it&apos;s not really any different.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>108438</commentid>
    <comment_count>11</comment_count>
    <who name="Boris Zbarsky">bzbarsky</who>
    <bug_when>2014-06-27 20:21:14 +0000</bug_when>
    <thetext>My point is that the ES6 spec for Map and your for-of loop have observably different behavior in all sorts of situations.  Starting with the one where Object.getOwnPropertyDescriptor(this, &quot;set&quot;) is an accessor descriptor with a non-idempotent getter.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>108439</commentid>
    <comment_count>12</comment_count>
    <who name="Boris Zbarsky">bzbarsky</who>
    <bug_when>2014-06-27 20:24:09 +0000</bug_when>
    <thetext>And in particular, the ordering in the spec, where the maybe-iterable&apos;s iterator-creating function is called before the get of this.set but this.set is gotten (once) before starting to actually invoke .next() on the iterator means that there is no way to express that algorithm as a for-of loop as far as I can tell.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>108444</commentid>
    <comment_count>13</comment_count>
    <who name="Domenic Denicola">d</who>
    <bug_when>2014-06-27 21:15:07 +0000</bug_when>
    <thetext>I believe this is black-box indistinguishable, assuming the code loads early enough to get access to unpolluted Function prototype.

var call = uncurryThis(Function.prototype.call);

var adder = dest[adder];
if (typeof adder !== &quot;function&quot;) {
  throw new TypeError;
}

for (var x of iterable) {
  var k = iterable[0];
  var v = iterable[1];
  call(adder, dest, k, v);
}

The ordering of the errors would be different from the spec, but that is not black-box indistinguishable since the error text is unspecified.

Anyway, pull-requested: https://github.com/heycam/webidl/pull/13</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>108448</commentid>
    <comment_count>14</comment_count>
    <who name="Boris Zbarsky">bzbarsky</who>
    <bug_when>2014-06-27 21:36:01 +0000</bug_when>
    <thetext>&gt; I believe this is black-box indistinguishable

In cases when both the getter for the &quot;adder&quot; property on dest and the value of iterable[Symbol.iterator] are functions with side effects this code will result in the side effects occurring in the opposite order from the spec&apos;s current algorithm.

Maybe the spec should be adjusted, of course.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>108449</commentid>
    <comment_count>15</comment_count>
    <who name="Domenic Denicola">d</who>
    <bug_when>2014-06-27 21:47:55 +0000</bug_when>
    <thetext>Ah good call, thanks, you are of course right. Filed on ES6, since I imagine self-hosting implementations will want this fixed anyway: https://bugs.ecmascript.org/show_bug.cgi?id=3000</thetext>
  </long_desc>
      
      

    </bug>

</bugzilla>