W3C home > Mailing lists > Public > public-script-coord@w3.org > October to December 2011

no longer treating explicit undefined as a missing, optional argument

From: Cameron McCormack <cam@mcc.id.au>
Date: Fri, 23 Dec 2011 12:38:36 +1100
Message-ID: <4EF3DB9C.4080401@mcc.id.au>
To: "public-script-coord@w3.org" <public-script-coord@w3.org>
CC: Jonas Sicking <jonas@sicking.cc>, Boris Zbarsky <bzbarsky@mit.edu>, Lachlan Hunt <lachlan.hunt@lachy.id.au>, Allen Wirfs-Brock <allen@wirfs-brock.com>, Anne van Kesteren <annevk@opera.com>, Brendan Eich <brendan@mozilla.org>
In the thread beginning at 
http://www.w3.org/mid/4E2580C8.6050106@lachy.id.au we came to the 
conclusion that we would make explicit undefined values passed as 
optional arguments be treated the same as if the argument was not 
actually passed.

So with

   void f(long x, optional long y);

calling f(0, undefined) would be the same as just calling f(0).  There 
were two arguments for doing this: one was that some thought it better 
to check against undefined for missing argument values rather than 
looking at arguments.length, the other was that it was needed to solve 
problems with querySelector() from the Selectors API and with 
XMLHttpRequest.open().

For the querySelector() case, the spec used to say something like:

   NodeList querySelector(DOMString a, Element b);
   NodeList querySelector(DOMString a, optional sequence<Node>? b);

Before the recent overloading model changes, passing undefined as the 
second argument would result in a TypeError being thrown, because 
undefined wasn't considered to be an exact match of either of those two 
types.  Allowing undefined to be treated as the lack of a specified 
argument solved that problem.  Now, though, I have made undefined match 
nullable types, so treating undefined as an omitted argument is not 
necessary.

For XHR.open(), we need to treat calls like

   xhr.open(method, url, async, undefined, undefined);

the same as

   xhr.open(method, url, async);

since some content relies on this.  If we stop treating undefined as an 
omitted argument, then the only way you could write this in IDL would be:

   void open(DOMString method, DOMString url, optional boolean async,
             optional any user, optional any password);

and to then handle in prose the user/password arguments so that 
undefined means "don't override the user/password from the url", which 
is what null means.  Otherwise, we could introduce a new 
[TreatUndefinedAs=MissingArgument] extended attribute.

I am not aware of any other APIs that require this.

There are a few reasons why I'd like to reverse the undefined treatment:

   * Erik Arvidsson's point[1] that ES6 default argument values will not
     be treating explicit undefined as an omitted argument.

   * The complications it brings to the overloading model compared to
     only checking for arguments.length, which is already done in the
     overload resolution algorithm anyway.

   * The fact that the behaviour is different from various other places
     where undefined is handled (non-optional arguments, and conversion
     of JS values to IDL values in general).

I think there was a fine balance of arguments for versus the convenience 
of being able to make calls like:

   function f(options) {
     xhr.open("get", options.url, true, options.user, options.password);
   }

I feel like the alignment with ES6 default arguments tips the balance 
the other way.  I will make this change soon unless there are strong 
arguments for keeping the status quo.

Thanks,

Cameron

[1] 
http://www.w3.org/mid/CAJ8+GoikEne_g4DnHa4ihdROfXy+xqq6mC2aDTB=Co1aj0KDnw@mail.gmail.com
Received on Friday, 23 December 2011 01:39:17 UTC

This archive was generated by hypermail 2.3.1 : Wednesday, 8 May 2013 19:30:05 UTC