Nov 17 meeting notes

Waldemar Horwat waldemar at google.com
Thu Nov 17 16:40:20 PST 2011


Array destructuring and length:
let [a, b, c, d, ... r] = {2: 3} <| [1, 2]
Obvious: a is 1; b is 2.
What are c, d, and r?
c = 2.
d = undefined.
r = empty.

Fixed property destructuring doesn't rely on length.
Vararg r destructuring uses length.
The semantics of length will match that of slice.

Allen: We may upgrade ToUint32 to ToInteger in various array semantics.

What should the semantics be if we allow fixed properties in the
middle of a destructuring?
[a, ... r, b] = [42]
What are the values of a, r, and b?
a = 42
r = []
b = undefined

Brendan:
[a, ... r, b] = [, 43] <| [42]
What are the values of a, r, and b?
a = 42
r = []
b = 43 or undefined?


Array.from discussion:  What happens if you subclass Array?
Subarray = Array <| function() {...}
Subarray.from(arraylike)

DaveH:
Array.from = function(x) {
  var result = new this();
  for (var i = 0, n = x.length; i < n; i++)
    result[x] = x[i];
  return result;
}

Array.of = function(... x) {
  var result = new this();
  for (var i = 0, n = x.length; i < n; i++)
    result[x] = x[i];
  return result;
}

The above should skip holes.

MarkM: Now these functions are this-sensitive and will fail if
extracted and called indirectly.
DaveH: Replace 'new this()' with 'new (this || Array)()' above.
MarkM: Of all of the static methods in ES5, not one of them is
this-sensitive.  The simple extraction of a static method fails,
thereby making static methods not be first-class.  If Math.sin did
this, you couldn't map it over an array.  With this, you can't map
Array.of over an array.
Doug: Concerned about the use of the word 'of'; confusion with for-of.
Wild debate over class hierarchies and class-side inheritance.
Deferred Array.from and Array.of due to concerns over this-sensitivity
until we figure out a proper class-side abstraction mechanism.

Array.from(a) is superfluous because it's expressed even simpler as
[... a].  DaveH withdrew it.

Array.pushAll:
Debate over whether this is a workaround for poor implementations of
using Array.push with spread or apply, or whether we should directly
have a second set of methods.
Brendan: Let's implement spread and optimize it first.  Later we can
always add pushAll if it's needed.  "This isn't ... paving cowpaths;
this is a mountain goat that went too high".

DaveH: Very opposed to .{ .

Cut 'fine points of for-of' from this meeting due to time.

Batch assignment:
Is this ES6 or ES7?  This is new, not discussed in May.
Can't discuss batch assignment without also discussing .{ .
Was .{ part of the May object literal proposal?
MarkM: Two kinds of .{ collisions to worry about.  The object literal
just statically disallows them.  .{ can have run-time property
collisions.
DaveH: Like the functionality but not the .{ syntax.

Example from .= page:

let element = document.querySelector('...');
element.{
  textContent: 'Hello world'
}.{
  style.{
    color: 'red',
    backgroundColor: 'pink'
  }
}.{  // back on element
  onclick: alert
};

Waldemar: Can you replace }.{'s with commas?  Brendan: Not in general.
 }.{'s do property redefinitions on property name conflicts, while
commas produce errors on conflicts.
Waldemar: Can you distribute the middle section above into the following?
}.{
  style.{color: 'red'},
  style.{backgroundColor: 'pink'}
}.{  // back on element
Answer: Maybe.

DaveH: Bind operator syntax strawman.
softBind strawman.
[A bunch of different discussions going on simultaneously, which I
couldn't track.]


Direct Proxies slide show.

Discussion about what hidden or implementation properties are passed
from the target through a direct proxy and how a proxy handler would
find out about all of them.  The author of a proxy needs to keep up to
date about picking the correct target as we add hidden properties.
For example, to make an Array-like proxy object, a proxy should start
with an Array instance as the proxy target.  Same with Date, etc.
Allen: There's no way to bootstrap -- can't define an Array-like proxy
if you don't have an Array target to start with.
Discussion about proxying the [[class]] name.

No more fundamental vs. derived traps.  (Almost) all traps default to
the target object's behavior if not overridden.  An exception is the
construct trap, which by default calls the call trap instead of
forwarding to the target object.
Allen: Should just pass through to the target.
Allen worried about other derived traps.
Waldemar: Always defaulting to the target will prevent us from ever
defining new non-leaf traps in the future, as that would break
existing proxies.  For example, if we have a current trap API where
the proxy defines only the trap GET, and we later wish to evolve the
language to refactor the API to call the derived trap HAS followed by
GET, where an object's HAS is defined in terms of GET, then defaulting
to the target will break proxies because HAS will invoke the target's
GET instead of the proxy's GET.
MarkM: This is forwarding vs. delegation.  The issue applies to many
traps, not just call.  All non-leaf traps should be resolved in the
same way.
Allen: Get rid of non-leaf traps (i.e. make them nonoverridable,
allowing proxies to override only the leaf traps into which the
non-leaf traps decompose).
MarkM: Why?
Waldemar: Are there any derived traps that have additional
intelligence not expressible via the leaf traps which they call?
Allen: Future-proofing is not important because we're unlikely to
change the proxy API in the future.
Waldemar: Counterexamples: Classes (if they're not just sugar),
guards, value proxies, ...
Sam, MarkM: The language provides a prototype handler with reasonable
defaults for derived traps. Proxy handlers derive their handlers from
that prototype. When the language evolves to create new traps, the
language's prototype handler evolves in lockstep to keep existing
proxies working.
Discussion about double-lifting (making the proxy handler also be a
proxy so it can abstract over the proxy trap API) and future-proofing
membranes.

Make target always be the first handler parameter instead of always
being the last?  That would make it match the Reflect API.
What does receiver do in Reflect.get/set/call(target, receiver, ...)?
Make target first and receiver last in the handler API.  The Reflect
API can drop the extraneous receiver parameter.
MarkM: That doesn't make sense for Reflect.call.  The order should be
Reflect.call(target, receiver, args), not Reflect.call(target, args,
receiver).  Note that args is an array, not a spread list of
arguments.
Discussion about what Reflect.call should be called.  The name
"invoke" was invoked.  "apply" might also apply here.

Object.preventExtensions is a leaf trap and calls
handler.protect('preventExtensions').
Object.seal and Object.freeze: Should these call
handler.protect('seal') and handler.protect('freeze')?  Replace them
with separate handler traps?  Replace them with calls to a large
number of separate traps that individually seal or freeze properties?

MarkM: Why not define call behavior as target function behavior
instead of having a call trap?
Waldemar: That would break double lifting.

Nonconfigurability invariants:

Waldemar: get/set can still get and set own properties even on frozen
objects with fully frozen prototype chains.
Sam, MarkM: True.  Unfortunately it's too hard to enforce this invariant.

Tom: Use a null target to indicate a permanently "virtual" object.
Brendan: Proxy.DonJuan

Tom: Replace synchronization actions with throws if the
synchronization actions would make any modifications to the target
object.

Discussion of __proto__.
Brendan: It's a real use case in object literals.

Proxy.stopTrapping:
Can approximate this by deleting all handler bindings from the handler.
MarkM: Swap arrow by making the proxy be the target and target be a proxy?
Consensus: Dropped stopTrapping

Refactoring prototype climbing in the spec.
Refactoring:
Brendan: Don't get rid of Object.getPropertyDescriptor and
Object.getPropertyNames even if they aren't traps.

Bikeshedding Proxy.for and Proxy.create names.
Why isn't Proxy a module?
if it's a module, can't use Proxy.for unqualified because it's a keyword.

Tom: Direct proxy refactoring takes care of the set/put/canPut chaining problem.

Should we have a defaultValue trap?
Brendan: Leave it out for now.  Revisit when we do value proxies.

Attach:
If target is a proxy, call a new trap.
Tie ability to attach to object extensibility.
Waldemar: Won't work for host objects that need to be both secure and
extensible.
MarkM: This is especially evil in capturing function arguments.  If
Alice gives Bob and Cathy a plain ES5 function, Cathy can't peek at
the arguments Bob passes to the function when he calls it.  With
Attach, Cathy can intercept Bob's calls to Alice's function and,
worse, make the function do something different for Bob.
Discussion about whether this should be done.  A number of us want
value observers and feel that proxies are less useful without them.
DaveH: There are many things that are wanted that didn't make the ES.next cut.

Consensus: Direct proxies (other than startTrapping/attach) accepted
for ES.next to replace older proxies proposals and strawmen.


2012 meetings:
Jan 18-19 at Yahoo
Mar 28-29 Google
May 23-24 Northeastern University, Boston
Jul 25-26 Microsoft Redmond
Sep 24-25 Mozilla
Nov 28-29 Apple


More information about the es-discuss mailing list