W3C home > Mailing lists > Public > public-script-coord@w3.org > April to June 2013

Re: APIs that overload numbers and strings

From: Allen Wirfs-Brock <allen@wirfs-brock.com>
Date: Sun, 14 Apr 2013 15:18:21 -0700
Cc: "public-script-coord@w3.org" <public-script-coord@w3.org>, Ehsan Akhgari <ehsan.akhgari@gmail.com>
Message-Id: <4B7E24C9-1AC8-4894-9ADC-EE6B3BCE2444@wirfs-brock.com>
To: Boris Zbarsky <bzbarsky@MIT.EDU>

On Apr 13, 2013, at 5:44 PM, Boris Zbarsky wrote:

> On 4/13/13 7:39 PM, Allen Wirfs-Brock wrote:
>> 
> 
>> If most of the legacy values correspond to named constant attributes
>> you may be able to respecify those constants as string values
> 
> We'd still need to handle numeric values passed in somehow, since I
> doubt consumers are consistently using the named constants....

the ES normal would be to just ToString the parameter (equivalent of calling the String(param) in actual JS code).  It really doesn't matter if a user passed in a number or even a string or number wrapper object as those would all produce the right value when ToString'ed

> 
>> Note that in  JS someArray[5] also implies an implicit number to
>> string conversion.
> 
> Quite, but engine's special-case very carefully to avoid such
> conversions.  So it's quite a different situation.

Right, and I suspect that these API calls are not as likely to be used inside tight loops.  If they are, it's easy enough for the caller to actually pass a string value.

> 
>> Idiomatic JS code that needs to distinguish numbers and strings would
>> just say typeof foo === "number" or typeof foo === "string"
> 
> As long as they ignore Number and String objects, yep.
> 
>> However, the test may no be needed at all, if the value is just going to be
>> passed on to some lower level interface that is doing its own type
>> discrimination.
> 
> We've had this discussion before; in practice type sanitization needs to happen at some trust boundary, wherever you draw that.

It might be nice to try to explicitly identify those boundaries rather than having every API function assume that it must be one.  That was one of the points I was trying to make in my os kernel vs framework blog post.

...

> 
>> Distinguishing numbers and strings is one possible discrimination, so
>> is distinguishing positive and negative numbers, and objects that
>> have a foo property from those that don't.  I don't think you can
>> generalize very much here as the "right think" to do is highly
>> situational.
> 
> Well, sure.
> 
> Let me try to be a bit more specific about the state of things.
> 
> What WebIDL gives you right now are tools to declare that you want your arguments checked and/or coerced in certain ways.   This includes some "type" coercions (ToString, ToNumber, etc), certain type checks (instance of a particular interface), some numeric range checks and some numeric range coercions.  If you don't want any of that jazz, then you can just use "any" and do whatever the heck you want with it (as IndexedDB does).
> 
> What WebIDL does NOT give you is a simple way to declare that your function should have as one of its initial steps "check that the input is a primitive string or primitive number, without doing any coercions".
> 
> _Should_ WebIDL provide some facility that allows the above?  If so, should it be restricted to primitives or should it do something with random objects (e.g. valueOf or whatnot)?

Right it really isn't that different from a function that accepts an any parameter and then doing one thing if what was passed was an string and a different thing if it was passed an Array object.  The ES I18N API spec. recently specified a bunch a methods that act like that (for locale specifies they except either a string locale id, or an array of string locale ids).

I don't think you can expect WebIDL to meaningfully be able to describe all the semantic subtleties that occur in these APIs.  Anything beyond the basics is probably going to require an accompanying prose or algorithmic specification. 

> 
> Again, this isn't about what range of behaviors are allowed.  All behaviors are always allowed with "any".  The question is what behaviors are _encouraged_ when API designers who don't care all that much about any of the edge cases consider an API where they want to differentiate between numbers and strings.

this is probably where I would fall back to recommending that all API specs include a demonstration implementation of its functions written in JS (at least of the parameter processing, it is probably ok for the semantic guts to be a stub).  If it is hard or complex in JS then it probably isn't a very good API design

Allen
Received on Sunday, 14 April 2013 22:18:49 UTC

This archive was generated by hypermail 2.3.1 : Tuesday, 6 January 2015 21:37:49 UTC