RE: Removing the concept of "optional any"

I think in general functions that treat not-passed as different from undefined are *very* surprising and un-JavaScript-ey; I feel like we've discussed this on this list many times before. `arguments.length` is the only way to create such functions, and that will be even less possible in ES6 given the function forms for which `arguments` is not present.

I don't know what behavior is most appropriate for `postMessage()` but it should be the same as the behavior for `postMessage(undefined)`.
________________________________________
From: Jonas Sicking <jonas@sicking.cc>
Sent: Wednesday, February 19, 2014 15:11
To: Boris Zbarsky
Cc: Mark S. Miller; public-script-coord@w3.org
Subject: Re: Removing the concept of "optional any"

On Wed, Feb 19, 2014 at 9:01 AM, Boris Zbarsky <bzbarsky@mit.edu> wrote:
> For the record, the full set of
> standards-track things (so excluding gecko-specific stuff) affected by that
> change in Gecko is:
>
> 1)  DedicatedWorkerGlobalScope.postMessage.  Right now it requires
> explicitly passing a message, but with the change you could pass undefined
> by passing no arguments.
> 2)  IDBCursor.update.

I think there are two separate questions here: "what behavior do we
want" and "what WebIDL syntax should we use". I think agreement on the
first question is needed before we can usefully debate the second
question.

Right now various objects have a `obj.postMessage(x)` method. The
value of the first argument is what is sent as a message to the
receiver.

Do we want `obj.postMessage()` to send the value `undefined`? It seems
a bit surprising to me that that doesn't throw an exception.

The argument that we've used in the past for treating `undefined` as
not-passed is to avoid people having to write code like:

function func(optArg1, optArg2) {
  if (optArg1 === undefined) {
    otherFunc1();
  }
  else {
    otherFunc1(optArg1);
  }

  if (optArg2 === undefined) {
    otherFunc2();
  }
  else {
    otherFunc2(optArg2);
  }
}

and instead write

function func(optArg1, optArg2) {
  otherFunc1(optArg1);
  otherFunc2(optArg2);
}

However the same argument doesn't seem to argue that
`obj.postMessage()` should be treated as `obj.postMessage(undefined)`.
I.e. you could still write

function func(optArg1, optArg2) {
  obj.postMessage(optArg1);
  otherObj.postMessage(optArg2);
}

Also, I don't think we'll ever have the invariant that not-passed is
always equivalent to `undefined` given functions like

function func(args...) {
  return args.length;
}

So is it really intuitive that `postMessage()` sends the value
`undefined`? Or that `cursor.update()` writes the value `undefined` to
the database?

All that said, if someone were to implement postMessage or
cursor.update in JS rather than C++ the code would likely look
something like

function postMessage(data, otherArg) {
  verifyData(data);
  var s = serialize(data, otherArg);
  _receiver.acceptSerializedData(s);
}

which means that calling `postMessage()` would be equivalent to
`postMessage(undefined)`. I.e. you could definitely argue that
treating not-passed and `undefined` as equivalent would be more
"javascripty".

Interested in hearing others' thoughts.

/ Jonas


Received on Wednesday, 19 February 2014 20:18:12 UTC