May 24-26 rough meeting notes

Waldemar
Thu May 26 16:22:13 PDT 2011
https://mail.mozilla.org/pipermail/es-discuss/2011-May/014748.html
A whole bunch of agenda reordering

Test262 report slideshow

Debate about who should host the test262 website
Deferred discussion

[For the purposes of these notes, Harmony and ES.next are synonyms.  We were
using "advanced to Harmony" to mean "advanced to ES.next".]


"RegExps match reality":
Waldemar: Omitting these error cases was deliberate in ES3.  They shouldn't
be in the base language any more than getYear or HTML string functions
should be.  If they go anywhere, it should be in Annex B.
Debate about whether these are extensions or conflicts with the spec.
MarkM: conflicts should be codified in the spec; extensions should not be
normative.
Debate about whether these are syntactic or semantic extensions and whether
they fall into the chapter 16 exemption.  Waldemar: even if they don't
currently fall under the chapter 16 extension, we could make them fall under
the chapter 16 extension.

Brendan, Allen: In the next spec we'll have an optional normative section of
web reality extensions.  Put these in that section, along with things like
getYear and compile.  Consesnsus reached on this approach for Harmony.

Lookbehind support is promoted to required normative.

Multiline regexps are out of Harmony.  There is no currently written-up
proposal.


Pragmas:
Would rather have these than string literals.  Don't require "use" to be a
reserved word.  Controversy about whether unrecognized pragmas should be
ignored (Brendan: both ways bite back), but (I think) that's an unsolvable
problem.
Consensus on moving these to Harmony.


Versioning:
<script type="application/ecmascript;version=6">  (RFC 4329)
use version 6;
module LOL {
  ...
}
</script>
There are good reasons to have the metadata both externally (in the script
tag) and internally (in the script).  External versioning allows
implementations to avoid fetching a script at all if they won't understand
it.  Internal versioning helps in the case where the external version is
detached.

Brendan's idea:
<script-if type=...>
  ...
<script-elif type=...>
  ...
<script-else>
  ...
</script>

Consensus on moving some form of versioning into Harmony.  The strawman is a
bit light at this time, so no specifics yet.


MemberExpression <| ProtoLiteral syntax:
Why can't ProtoLiteral be a variable?  Could extend the syntax to allow
expressions there, with <| doing a shallow copy.  Copy internal properties
as well?  Not clear what that would mean for some objects such as dates.

Shallow copy is problematic if right side is a proxy.  Would need a
clone-with-prototype handler.

Waldemar: <| seems too ad-hoc.  Would want a more general mechanism that
also allows for creating an object that's born sealed.

Brendan:  Object literal extension defaults seem ad-hoc.  Constants (and
maybe methods) shouldn't be configurable.

MarkM:  "Mystery Meat" problem here.  Not comfortable with Perlish
"punctuation soup".
Allen:  Words are too verbose, which was the feedback from past meetings.
Waldemar:  Improve the usability.  Would prefer to set configurability en
masse on the properties of an object rather than having to mark each one.
:= should go back to being called "const" and should come with the right
defaults so that no other modifiers are needed in the common case.

Discussion about dynamic vs. static super lookup.  When a method is
extracted, "super" used in a . (or []) expression stays bound while "this"
is dynamic.  Note that a bare "super" not in a . or [] expression means
"this".

MarkM: Gave example of why super can't have simple dynamic semantics such as
"start from the 2nd prototype".  This causes infinite loops in class
hierarchies.  More complicated semantics where both a "this" and a "super"
are passed in every call might be possible.

Brendan: super without class is too weak and causes problems in nested
functions.

MarkM: super must be in a . or [] expression.

What should super.foo = 42 mean (where super is an lvalue)?  What if foo is
not an accessor?


Private names:
Note that you now can't use the public name gotten from for-in or
getOnwPropertyNames to index into the object.
Should the name objects be reflectable via getOnwPropertyNames at all?
Waldemar:  Objects to leaking the presence of private names. Wants no
reflection on private names, with proxies doing membranes via the getI/setI
approach.
Discussion about interaction of shallow cloning with private names.
Advanced to Harmony, with the big open issue of reflecting on private names.


Classes:
"constructor" is a contextually reserved word.
Waldemar:  Classes as an abstraction should have a clear way of (preferably
enforceably) documenting the shape of instances:  what properties they have,
what they are (getters/setters/guard), etc.  This proposal is too weak here.
Waldemar:  A const class must define its instance properties; otherwise the
constructor won't be able to create them.
MarkM:  Instances aren't sealed until the constructor finishes.
Waldemar:  If it's the local constructor, that won't work.  If it's the
entire chain of constructors, then that can be indefinitely later, and the
derived classes can muck with the unfrozen/unsealed contents of the
instance.  For example, if the attributes like const don't take effect until
all constructors finish then a derived class can alter the value of this
class's const instance fields.

MarkM:  Wants clarity about scope and time of evaluation.
Brendan:
class C {
  get x() {return 42}
  x = [];
  static x = [];
}
Issue about puttig a mutable x = [] on the prototype and the instances
colliding because they all try to insert elements into the same array rather
than each instance having its own array.

Waldemar:  Don't like the subversion of const away from its semantics in the
rest of the language, where it means write-once-by-definition with a read
barrier before the definition.  Here a const field can be mutated many times
even after the constructor finishes.  That won't work for guards.

Brendan:  Proposed correction:
constructor(x, y) = {
  x: x|| default_x,
  y: ...
}
MarkM:  Had earlier declarative instance construction proposal, but Allen
convinced him that the imperative style is the most familiar to ECMAScript
programmers.
Allen:  No I didn't.  Declarative construction is important.
Waldemar:  There's someplace you need to specify instance attribute
properties, and some of them can only be specified at the time the property
is created.
Also, need to be able to interleave declarative initialization of instance
properties with computation of temporaries so declarative initializations
can share work.

Discussion of older, closures-based version of the class proposal, which
have a simple declarative syntax:
http://wiki.ecmascript.org/doku.php?id=strawman:classes_with_trait_composition&rev=1299750065
This one is simple but defines properties only on class instances, not on
the class constructor or prototype.

Mixed proposal:
http://wiki.ecmascript.org/doku.php?id=strawman:classes_with_trait_composition&rev=1305428366
This one is more complicated because it allows definition of properties both
on class instances and on the class constructor and prototype.

MarkM wrote a table comparing the three proposals:

                         Closures       Mixed             Separate
Class properties         none           static in class   static in class
Prototype properties     none           public in class   decl in class
Instance private         lexical capture (in all)
Class private inst       private decl   private in ctor   expando only
Public inst properties   public decl    public in ctor    expando only
Return override          none           none              optional
Constructor code         yes            yes               yes
Class code               no             yes               no

expandos are dynamically created properties:  this.foo=42

MarkM's preference is Closures (best), Mixed (middle), Separate (worst).

Group trying to come up with a variant of the Mixed proposal.

Brendan:  What's the order of initialization in a class hierarchy?
Declarative instance initialization should be able to rely on super instance
initialization having run once they call the superconstructor.


Scoped Object Extensions:
Waldemar: These use the same mechanisms as early ES4 namespaces.
What happens when extensions conflict with each other?  Can't be a
compile-time error.  Run-time error.
Extension "objects" (perhaps better called Extension records) are themselves
not extendable.
Waldemar: What happens when you write to an extension property?  Delete
one?  Proxy one?
Peter: Make them immutable.
Alex: Won't work. Such things in the prototype will inhibit shadowing.
Peter: Make them writable but nonconfigurable.
Waldemar: What happens when you have an extension A.count, and then code
does A.count++?  In the current semantics this creates an invisible
non-extension property on A and doesn't work.
Peter: You shouldn't be writing to extensions.
Waldemar: We've already ruled out the immutable model.  Can't change the get
rule without also changing the put and related rules.
DaveH: Let's look for alternatives. Could this be layered on top of private
names or such?
Waldemar: No.
Debated extensions vs. private.
Lexical restriction of extensions is a blessing as well as a curse. If a
module extends Tree with a where method, that module can't call a Tree
utility in another module that relies on "where".
Waldemar: Membranes don't work. The proxy would need to get a hold of the
lexical scope.
getOwnProperties won't see extension properties because it's a function.
Freezing won't work -- won't see extension properties because it's a
function.
DaveH: Agree that this solves an important problem, but the issues of the
implications on the object model are severe.
Sam: We'll need to reify GetOwnProperty for proxies to take lexical scopes
as arguments.
Brendan: Not just proxies.  Proxies and put are sub-problems of the larger
problem of making a significant change to the metaobject protocol.
Luke: There are other things already promoted to Harmony that are as
underspecified and cross-cutting as this.
Brendan: The issue is that this proposal is so new.
Waldemar: The issue is that this probosal is not new; over the years we've
ran against deep problems when working in this area in the context of
namespaces.
Debate about the Harmony process.
Brendan's summary of consensus: We'll try to get into ES.next but not
promoted to Harmony yet.  Need to address the problems with semantics and
get some code experience.


Trademarks/guards:
[didn't take detailed notes because I was driving discussion]
Very long debate about merits and process.
Not promoted to a proposal for Harmony.  Dave:  Insufficient time to
experiment with this before 2013.


Random:  First paragraph accepted, second not.


Quasis:
Backslash sequences are not interpreted when passing to the quasitag
function.  The default is join, so:
`foo=${void 0}\n` evaluates to "foo=\\n".
`\u1234` evaluates to "\\u1234".
`$\u1234` evaluates to "\u1234".
Allen: Worried about yet another escaping syntax.
Waldemar: Also unhappy about confusion of escaping syntax overlap.  Example:
`foo = \$`.  RexExps containing $ characters would be misinterpreted.
Waldemar: Alternate proposal:  Use only the regular \ syntax for escaping.
An unescaped $ followed by an identifier would turn into a substitution. All
other $'s would be passed through literally. Also, it should be up to the
quasi parser whether it gets the escaped or raw text (with the default being
escaped).  The quasi parser function could specify its desire via a property
on the function.
Devate about what could go into substitution bodies.
Waldemar: Grammar is not lexable via the same kind of lexer technology used
for the rest of the language; lexer is not a state machine any more.  OK
with allowing only sequences of dot-separated identifiers.

String formatting: Not on agenda, so not in Harmony.
Brendan: We haven't got it together yet. It doesn't address injection
attacks.


Classes and privacy revisited:
- Return allowed?
- Verbose repetition of public/private prefixes
- One or two namespaces for instance variables
- Require a prefix like "public" to define prototype data properties
- Private proto-properties
- private(this) vs. alternatives
- Attribute controls
- Half-override of get/set pair

Return allowed?  No consensus.  Return is useful for migrating current code
and memoizing but conflicts with inheritance.

Verbose repetition of public/private prefixes:  Agreed to solve this by
allowing comma-separated declarations:  public x=3, y=5;

One or two namespaces:  Consensus on two.

Require a prefix like "public" to define prototype data properties:
Consensus on yes.

Private proto-properties:  Consensus on yes.

Long discussion about private instance variable access syntax.
private(expr).x is ok as a long form for an arbitrary expression, but we
need a shorthand for private(this).x.  No consensus on which shorthand to
use.
Waldemar:  Use just x as the shorthand (every private instance variable x
would also join the lexical scope as sugar for private(this).x)?

Attribute controls:  Allen has a proposal.

Half-override of get/set pair:  Allen has a proposal.


Categorization:
No review, no advance:
Unicode
Concurrency
Enumeration
Simple module functions

No review, advance:
Multiple Globals
Maps and Sets
Math enhancements
Function.toString
Name property of functions

Review, advance:
String Extras
Array Comprehensions
Completion Reform
Classes
Extended Object Literals (the goals were advanced, the syntax used by the
strawman was not)
Quasis

Review, no advance:
Soft Fields
Object Change Notifications
Deferred Functions
Guard Syntax
Paren-Free
Arrow Function/Block


Completion reform:
This is a breaking change.  There's no way to specify a language version for
eval code, short of a pragma.

Extended Object Literals: Waldemar and others objected to most aspects of
the current syntax; it produces a punctuation soup and possibly conflicts
with guards.

Object Change Notifications:
Luke: We tried and failed to make proxies work for this use case (as well as
for copy-on-write).
Waldemar: Why can't this be done using proxies?  I understand why proxies
can't support the API proposed for object change notifications, but why
can't they solve the larger user need here?
Luke: Too inefficient and would require full membranes to support object
identity.
Allen: This allows people to break into abstractions by putting observers on
objects they don't own.
DaveH: Proxies are deliberately less powerful than this in that they don't
allow you to attach behaviors to arbitrary objects that you don't own.
MarkM: Notification happening synchronously is a security problem.
Observers can run at times when code doesn't expect malicious changes.
Waldemar: The same argument applies to getters, setters, and proxies.  You
need to lock things down to guard against those anyway, and the same
lockdown would presumably apply to observers.
Cormac: Just hand around *only* the proxied versions of observable objects.
No need for membranes.
Sam: This would let you observe private names.
Luke: No it wouldn't. It would only show alterations to properties whose
names you can see via getOwnPropertyNames.
MarkM: This could be done by turning the current true/false extensibility
property into a tri-state true/false/observe property. Existing properties
can be replaced with getter/setter pairs. The extensibility hook would be
notified when new properties are created.
Waldemar: This won't notify you of property deletes. A delete will delete a
configurable getter/setter pair without notifying any observers.
MarkM: Is observing deletion needed?
Luke: Yes, particularly for arrays.
Discussion about deferred vs. immediate notifications. Immediate is
preferred.
Brendan: This might be a better "watch".
Cormac: There is a lot of overlap between this and proxies. Is there a way
to do some synthesis?
MarkM: This has a lot of open research issues.
Cormac: Proxies may have flaws that this would fix.
MarkM: We should work on this in parallel, so that this informs proxies.
Not advanced to Harmony.

Quasis:
`$\u0061` is a reference to the variable <a>, not the string constant "a".
Waldemar: Why do we need variables with unguessable names?
Resolved: Don't name these variables at all. They're still created at the
top-level scope but don't have lexical scope names.
Waldemar: What happens when you have an invalid escape sequence so you can't
generate a decoded string to pass to the function (even though the function
is only interested in the raw string)?
Resolved: Modified the proposal to remove the interleaved arguments and
instead put both the raw and the decoded strings on the frozen identity
object. Decoded strings are missing if they don't decode.
Advanced to Harmony.

Deferred functions:
Discussion (and lots of confusion) about the semantics of the proposal.  The
Q class is not part of the proposal.  Continuations are meant to be
one-shot, possibly with reusing the same continuation object across calls.
MarkM: There is also an error-handler in addition to the then-handler.
MarkM: Issue with chaining values.
Peter: Every time a function that contains an await statement is called, it
returns an new Deferred object.  The semantics of Deferred are built into
the language.

class Deferred {
  then(callback) {this.callbacks.push(callback)}
  constructor() {
    this.callbacks = [];
  }
  callback(result) {
    for (var v: this.callbacks) {
      v(result);
    }
    this.callbacks = [];
  }
}

Cormac: "then" never returns anything interesting.
Waldemar: How do you await multiple things concurrently?  A sequence of
await statements will wait to launch the second until the first one is done.
Peter: Call these multiple things without using await and then use a
combinator to wait for all of the results.
MarkM: This requires separate turns.
Brendan: This is a syntax full of library choices that could be done in
other ways that we should not be specifying yet.  (Examples: Form of
Deferred objects, turn issue.)
Deferred implemented using Generators?  Need a top-level dispatch function.
Also generators don't let you return a value.
DaveH and Brendan: Deferred is coexpressive with generators.  However, there
are policies underneath Deferred (scheduling etc.) that are premature to
standardize.  Solve this problem using generators as they are.
Luke: Concerned that things we're shooting down have more value than things
we've adopted.
DaveH: Need to keep the pipeline going.
Waldemar: How do you simulate return values using generators?
DaveH: Use the last yield to pass the return value.  The caller will then
close the generator.
Not advanced to Harmony.


Guard Syntax:
Technical aspects ok, but some are worried about the effects of this change
on the ECMAScript style.  Cormac's student Tim will work with DaveH to
prototype this this summer.
Not advanced to Harmony, pending more user experience.


Paren-free:
Compatibility issue with:
  if (cond) a = b;
catch, for, for-in heads must not be parenthesized.
MarkM: Cost of incompatibility is too high, particularly for things like
for(;;) heads.  Would prefer to have full upwards compatibility, including
old semantics for for(a in b).
Several others: Don't want significnt parentheses.
MarkM: We must not make it impossible to write code that runs on both old
and new syntax.
Not advanced to Harmony.


Arrow Function/Block:
function f() {
  a.forEach({| | return 3});
}
The return will return out of f.  Note also that the implementation of
forEach could have a try-finally statement that catches and revokes the
return.  This kind of cross-function return catching is new.
The cage around block lambda is too tight.
Luke: Concern about call syntax strangeness.  This kind of syntax only works
if it's designed holistically.
Debate about completion value leaks.
Waldemar: Use of | conflicts with common use of trademarks.
Alex: Objects to new "little pieces of cleverness". Too many things to teach
to people.
Not advanced to Harmony.


Next meeting two days Jul 27-28.

More information about the es-discuss mailing list