September TC39 meeting notes
2008/10/3 Waldemar Horwat <waldemar at google.com>:
An open issue is whether const violations should be compile or run-time errors. Clearly some of them are undecidable and can only be reported at run-time, but what about the clear-cut cases?
{ a = x; const x = 2; }
It would be nice if a compilation error is reported for
const x = x + 1;
This way ECMAScript can beat C++ where
const int i = i + 1;
is syntactically valid and the language does not require any diagnostic from the implementation.
, Igor
Igor Bukanov wrote:
2008/10/3 Waldemar Horwat <waldemar at google.com>:
An open issue is whether const violations should be compile or run-time errors. Clearly some of them are undecidable and can only be reported at run-time, but what about the clear-cut cases?
{ a = x; const x = 2; }
It would be nice if a compilation error is reported for
const x = x + 1;
This way ECMAScript can beat C++ where
const int i = i + 1;
is syntactically valid and the language does not require any diagnostic from the implementation.
, Igor
It definitely won't be as bad as C++'s behavior here (gcc accepts some of these without warning and simply leaves i uninitialized in the sequel of the code).
const x = x + 1;
will be at least a run-time error. Whether it should be a compile-time error is open for discussion.
Waldemar
2008/10/4 Waldemar Horwat <waldemar at google.com>:
const x = x + 1;
will be at least a run-time error. Whether it should be a compile-time error is open for discussion.
After some considerations I think any static rule would be unsatisfactory as it can be trivially subverted with eval.
, Igor
Sept 22 2015 Meeting Notes
Allen Wirfs-Brock (AWB), Sebastian Markbage (SM), Jafar Husain (JH), Eric Farriauolo (EF), Caridy Patino (CP), Mark Miller (MM), Adam Klein (AK), Michael Ficarra (MF), Peter Jensen (PJ), Domenic Denicola (DD), Jordan Harband (JHD), Chip Morningstar (CM), Brian Terlson (BT), John Neumann (JN), Dave Herman (DH), Brendan Eich (BE), Rick Waldron (RW), Yehuda Katz (YK), Jeff Morrison (JM), Lee Byron (LB), Daniel Ehrenberg (DE), Ben Smith (BS), Lars Hansen (LH), Nagy Hostafa (NH), Michael Saboff (MS), John Buchanan (JB), Gorkem Yakin (GY), Stefan Penner (SP)
On the phone: Mark Miller (MM), Dan Gohmann (DG), John McCutchan (JMC)
(Need attendance list)
1. Opening Items
JN: (Introduction)
JN: Agenda is tc39/agendas/blob/master/2015/09.md
YK: Post ES6, do we want to break up days into plenary and presentation.
AWB: An agenda item?
BE/YK: Add to agenda
Suggest:
- morning plenary groups
- afternoon discussion
LS: (facilities)
Adoption of Agenda
AWB: Future agendas should avoid being specific about the version
BE: Helpful for me to know which features are on track
Conclusion/Resolution
- Change agenda "Proposal for future editions of ECMA-262"
- Agenda approved
4. Secretariat Report
JN: 1 o'clock on Thursday
5.1 Shared memory and atomics
(Lars T Hansen, Mozilla)
lars-t-hansen/ecmascript_sharedmem
lars-t-hansen.github.io/ecmascript_sharedmem/shmem.html
Need slides
LH: Work in progress at Mozilla, Google, etc.
Use Cases
asm.js
- pthreads in translated C/C++ code
- Support for safe threaded languages
"Plain" ES
- Shareed state and multicore computation
- Fast communcation through shared memory
Use cases conflict:
- asm.js has flat memory, no gc, string types
- plain ES is object based GC'd weak types
Compromise?
...
Approach
Provide low-level facilities
- SharedArrayBuffer + TypedArray
- Atomic Operations
- Concurrent agents (introducing)
- Agent sleep/wakeup operations
Build Higher Level facilities
- Locals ... (need slides)
API: Shared Memory
A new data type:
var sab = new SharedArrayBuffer(size);
(need slides)
Views on Shared Memory
var sab = new SharedArrayBuffer(size);
var ia = new Int32Array(sab);
var fa = new Float64Array(sab, 8, 10);
(need slides)
API: Atomic Operations
...
API: Agent Sleep and Wakeup
Modeled on the Linux "futex" (fast user space mutex)
Atomics.futexWait(i32c, loc, expect, timeout);
Atomics.futexWake(i32c, loc, expect, timeout);
- Minimal assumptions, very flexible (need slides)
Example: mutex lock()
Lock.
// get code from slide
Discussion re: scheduling and execution.
DH: tasks can be scheduled, but not executed
CM: Understanding there would never be shared state threads in JS. This appears to be that.
(Discuss after presentation, Moving on)
LH:
Agent Model
- Need a model for concurrency in ES
- Define concurrency in termsn of agents
- Define agents in terms of ES6 jobs
- Give jobs a forward progress guarantee
Agent Mapping
-
In a browser, an agent could be a web worker
-
SAB sharing is by postMessage,
-
WebWorker semantics need work, nearly useless today.
-
In a non-browser setting (SpiderMonkey shell)
-
concurrent thread, separate global environment
-
mailbox mechanism for sharing memory
AWB: Can imagine request for generalized model
DD: A different group could approach to define generic
AWB: Dont want a mechanism that will only work in a browser.
LH: (Confirms)
Implementation Concerns
- Trick to block on the main thread in browsers?
- Subcontracting, main browser thread actus on behalf of worker
- Possible to deadlock if main thread is waiting
- Make workers not truly concurrent
- Where's the bug?
- Subcontracting for UI and other things are also problematic
DD: An early version of this proposal said that these APIs were not on the main thread
YK: Scary to have locks on the main thread
LH: Not that scary, it's no different than a loop
YK: Async functions are the solution that has evolved
AWB: Are the workers multiplexed?
LH: If JS on main thread creates a worker and waits on the location, it will hang because the worker doesnt get started.
AWB: Semantically observable?
LH: Can observe remotely (a corner case)
Memory Model (1)
- Atomics in the program are totally oridered
- Conventional "happens-before" relation on events:
- Program order (intra-agent)
- Atomic-write, atomic-read (intra-agent)
- futexWake called -> futexWait returns (intra-agent)
- postMessage -> event callback (intra-agent)
- transitivity, irreflexivity
Discussion: clarification of consistency model
Memory Model (2)
- Reads only see writes that happen before them (and only the last of those writes)
- Unordered accesses where at least one... (need slides)
Memory Model (3)
- Races are safe, programs don't blow up
- Races are unpredictable, a race poisons the memory by writing garbage
- A race affacts... (need slides)
DH: Say there is a non deterministic collection of memory bits in location
YK: What happens when you read the garbage?
LH: Currently will get the garbage
Memory Model (4)
Complications:
- Aliased arrays and cells thar are not exclusively atomic
- Weakly ordered memory (ARM, MIPS, Power)
C11, C++11 have similar issues, mildly unsound?
Java Better? But complex and subtle
DH: if mem model says data structure, behavior localized to data structure. integration with rest of language impacts jit compilers, spec semantics (how deep). Not sure what the biggest risk is... limited to array buffer and only in specific case? Invariants in loads and stores
LH: optimization to load value from typed array, use it for something, eg. function call. If not affected, can reload.
DH: Already know typed array, can assume not shared array buffer. Cases where I don't know the backing store, nervous
AWB: Typed array accesses with brackets
Limit concerns to optimizations re: Typed Array cases.
DH: Concerns: How much does this leap into the current spec. How much does it affect the lower level operations?
AWB: Typed Array access get turned into operations on their bufffer. Buffer operations become polymorphic (unshared, shared). A common operation that occurs, with slightly different behavior.
Other Memory Model Issues
- No "relaxed" atomics, we problam ant them but they are complicated
- No "acquire-release" atomics, ditto though weaker use case
- Shared memory can be used to implement high-precision timers (you just count), which can be used to simplif cache sniffing attacks
- Slight security concern
- Misc minor issues, see github repo
BE: Like mips load, link (re: "acquire-release")
LH: (state of "acquire-release" on current platforms)
Status
- Spec is stable, memory model is being refined
- Firefox Nightly since Q1 2015, demo level code for asm.js, plain JS is running
- Google have committed publicaly, at least in part (need slides)
CM: This is terrifying. Can see cases for use in libraries for communicating internally, but as soon as this is exposed to random web developers... The nightmare is people that don't know how to code in this paradigm. Likely a majority. Now can write highly insecure programs, introducing the problems that JS rid us of
YK: What about other high level languages, Ruby? It exposes pthreads. Then developers write better higher level abstractions
CM: Nothing to protect from authors of page and script running in it.
YK: Concerns is third party scripts?
CM: Yes.
YK: Could mitigate
DD: sandbox?
CM: Could design the things you might make with this, then codify into language...
YK: Verification?
CM: No, if the facilities don't exist, then safe.
BE: Agree, most web developers should not be tempted, even able to write shared memory programs. We need to talk about what goes wrong. Cannot have shared memory without races? We have demand for this.
Why Not Just for asm.js?
-
Some tasks are best/only done in JS callouts
-
I/O
-
Thread Management
-
Runtime tasks in general
-
JS has data structures, easier to program
-
The callout needs at least some shmem access
LH: need to satisfy both use cases
DE: Any program can already get into an infinite loop, unresponsive.
CM:
BE: If we don't do something like this, there will be a bigger gap for webassembly stuff.
YK: Shared memory is not inherently unsafe, only in raw form. We can provide safe access.
(Mark joins on phone)
YK: Need to more concretely address the constraints
MM: Will read emails from waldemar:
- Introducing a high bandwidth side-channel
- Even if only computation with coarse granularity, the ability to access shared memory seems fatal.
LH: Only fatal if you can prove it's not already possible
MM: No way to do high-bandwidth side channels, such as cache attacks
MM: Timing attack is: shared array buffer with self.
BS: Issue is using the shared array buffer as a timer, you just read it and allows cache attacks
MM: If attacker can create two threads that can communicate, you can create high resolution timer attacks
BE: There's been demonstrations of not-as-high resolution timer attacks that already exist. This is not the first high resolution timer attack.
MM: Waldemar believes this is a bad vulnerability
BE: www.theregister.co.uk/2013/08/05/html5_timing_attacks
DE: Any further conserns?
MM: Delayed weak refs because of
-
JS has become mostly deterministic
-
Plat
-
bits in nan are platform dependency, not generatl non-determinism
-
for-in iteration order is platform dependency, not generatl non-determinism
MM: On whatwg, proposed System object. System is not distinct from the ES built-ins. Grants
MM: perhaps the non-determinism comes from creating the Worker in the first place? Thinking out loud
Where does one get access to the SharedArrayBuffer constructor
Either from global or imported from module.
AWB: How do you gain access to an already existing SAB created in another Worker?
MM: Creating an SAB alone is safe.
BE: The
( www.theregister.co.uk/2015/04/21/cache_creeps_can_spy_on_web_histories_for_80_of_net_users) / arxiv.org/pdf/1502.07373v2.pdf
LH: the resolution of performance.now has been reduced to help prevent the caching attack
DD: not concerned about the paternalistic argument, rather the actual security concerns?
YK/CM: Concerned about the programmer shooting themselves in the foot
MM: Concerned about security attack, more than programmer
CM: concerned about DOS attacks from third parties ...concerns are directly related
YK: Right way: expose async futexWait
LH: Originally had an async futexWait
CM: Proposing non-blocking-but-blocking?
YK: No, want to express sequencing in a local way. This will be done with async function ... want same solution, async futexWait
MM: Q: motivation for SAB proposal: conventional c/c++ pthreads code can be compiled through asm.js can still fnction?
LH: That's one of the case
YK: Shared Memory is a useful primitive.
MM: Want to separate:
- Compile old legacy pthread code
- Make good use of hardware parallelism
BE: legacy?
DH: Tried to build higher level primitives to give deterministic parallelusm to JS. Challenging. Meanwhile the extensible web strategy proves every time. Expose better, high performance, multi-core parallelism primitives.
YK: Should give 0.01% more credit (like authors of gzip, etc)
LH: first thing I did when I finished the prototype
MM: fan of the Rust/Pony approach, low-level, universal. Arrived independently at a similar result.
YK: Easily imagine a Rust-like model, b/w dynamic checks
DH: Rust has Shared Memory concurrency, static type system and library design that statically guarantees ...best of performance and programming model. Can't be added directly to JS, maybe with APIs and DSLs that have some speed tradeoffs, don't know what will win in the end
BE: MM mentioned Pony, which has similar design
BE/DH: Cannot evolve JS into Rust.
MM: not what I'm proposing. I'm proposing investigating building on TypedArray safely parallel memory system with ownership transfer of region, capitalizing on Rust/Pony development
DE: how do we solve the compile from C++ problem?
BE: circles back to earlier point: don't have time to find SAB alternatives, without exposing shared memory needs of C++. If we do nothing, then other "bad stuff" will happen. If we do this, then other people can experiment to find a better solution
MM: The potential show stopper: the side channel. I want to see some real analysis of this danger and why we should be confident that the danger is minimal, before we proceed.
LH: we have security people working on that, we can try to expedite.
- danger is that page load, you think its safe. Allows to fork off a worker with shared memory, and there's the attack.
YK: Might want restrictions on the main thread, so ads can't own your site
LH: is this appropriate for the language or the browser embedding?
LH: whole thing with service workers/shared workers is tricky.
YK: Thing is (oksoclap disconnected on me, notes lost)
LH: fundamental constraints with blocking on the main thread? Or can the browser implementations work around this.
YK: is this a fundamental C++ problem?
- fetch in browser: fork off a thread, do the work, wait for response.
LH: depends on which web APIs are avai
- want to update webgl
"shared" or "transferrable" canvas
DH: Concern, if growing API, implementation burden to find ways to share with workers? maybe WebIDL?
AK: More clarification on urgency?
BE: if we do nothing, it is a bigger jump to WebAssembly, or somebody else will do it anway to compete. Can't polyfill Unreal engine 4.
DH: Jeopardize adoption of web assembly.
AK: Is this going to be a problem with wasm features for time to come?
BE: maybe in the future JS will not be serving the cross-compilation master, but not right now
YK: constraingts: what dynamic checks do you need to make SAB work?
BE: if we have web assembly in all the browsers, why would we need these in JS?
MM: Memory model discussion?
LH: we talked about that.
BE: If we say out of bounds "no and forever", something else will happen (see: flash, java). We need to work towards something.
YK: concrete example: VLC in the browser, don't want to write C, write JS, chunk up the screen
AK: Can't use argument of "needs" c/c++ pthreads.
LH: (pre lunch summary)
- This feature has cost
- sophisticated shared memory given to those that don't know how to use it
YK: better to allow the ecosystem to help us design the higher level sync operations than try to design ourselves
LH/MM: discussion of burden of proof of timing channel attacks
BE: hard to choose between higher-level and lower-level primitives
YK: quarantining helps that problem. Have to deal with timing channel attack.
CM: not sure quarantining is sufficient, what are the modes of vulnerability. Ecosystem of mutually distrustful components, run the risk of someone not paying attention, leaving the barn doors open
YK: orthogonal to the primitive, access to the primitive
AK: depends on the primitive
YK: actually, yeah.
(Lunch)
BT: True that impl. shared array buffers in wasm is easier than normal JS?
LH: Different, not easy ...Optimizing generics atomics, backend implementation
BT: SAB in wasm have same security concerns?
LH: Yes.
BT: Need a sense, wasm is a ways out.
BE: something will happen if we don't act
LH: thought about having it only in asm.js, not sufficient. runtime and IO services need accesses to shared memory and atomics. some of it could be moved into asm.js, but not all of it. to do so asm.js would need access to DOM APIs.
DH: Value? Same potential security concerns. Same access from JS. Also brought in requirement to standard another thing. If done in asm, then need to standardize all of asm.
BT: what about WebAsm only? I don't think polyfills are critical. asm.js is great because it is a subset, sound great as a marketing story, but haven't seen a real example
DH: Important that it was a subset, was adopted.
BT: asm.js compiled stuff doesn't work when asm.js is turned off. Games will not run in wasm
YK: gzip.js?
BE: you're saying that things don't work well outside of optimized asm.js?
BT: wasm polyfill has no value to game developers. Unreal Engine running against this polyfill will not work.
DH: asm.js exists today! Polyfill WebAssembly to asm.js, it will run well.
BT: asm.js apps running without asm, don't run.
DH: two different stories: asm.js as a subset of JS is to break out of a deadlock. Disagreement between browsers about how to port C++ apps to the web. Competitive pressure created excitement. Kickstarting the process.
BE: (shows zombie chicken killing example in browser) compiled to asm.js, running in browser. (He's playing this next to me and I'm really more interested in that than the current discussion. - RW)
DH: WebAssembly is in a different place -- not about disagreement between browser vendors, there is agreement. The polyfill here is about making sure that browsers that haven't yet implemented features can still run, and people can ship functionality.
BT: wasm polyfilled ontop of asm will be a useable experience?
BE: Yes, I'm playing right now.
BT: the polyfill burden for asm.js is too much, you can probably get better performance without asm.js. Kind of a side tangent
DH: this is super important! Need to keep our eye on the ball for polyfill for WebAssembly. Still have a couple of years before wasm, maybe more years before all browsers have the functionality, maybe timeline is off, but the polyfill story helps mitigate the risk of shipping wasm features.
BT: if I'm Epic, I need two codebases to support asm.js and non-asm.js browsers
YK: long tail of things that benefit from asm.js, but still work without
BE: spoke with Apple about this, they think they don't need to specialize for asm.js, can generate good code without detecting "use asm"
BT: Why polyfill?
BE: Can run code sooner than later.
BT: Browsers that don't support asm or wasm will be gone soon?
BE: That support asm, but don't support wasm.
YK:
BT: I think I can understand the value of the polyfill
BE: But do we want to add it to JavaScript for all time? Maybe that's not the right argument, what about Rust to JS, Pony to JS, etc.
BT: But you can still do that from wasm, right?
LH: we need to make sure we support both use cases, compile to asm.js and data parallel in JS. Much more useful to have both than not
BT: I agree we shouldn't be telling JavaScript devs that they can't use these features, but do we save anything but focusing only on asm.js? It sounds like no
LH: I don't think the extra burden to the JS dev is very big
AWB: It doesn't seem like it would be optimized very well if we force JS devs to communicate through asm.js for this feature
BT: If there is strong motivation to add for all time, then I'm fine. As long as not just for a polyfill.
DH: I see this as a building block for the long term
BE: we need to reach consensus, but we don't have to say this is going to be in JS forever just yet
LH: Request Stage 1, with a list of things to investigate.
MM: w/r to SAB, discussed extensively that burden of proof to show cache sniffing vulnerability is on the champion
... memory model is not contained. This will bleed into anything that touches the SAB. We need to try to find a way to contain it.
LH: sounds reasonable
AWB: Object to Stage 1?
MM: no problem moving to stage 1
YK/SM: What restrictions do we want, who do they work? Difference between global and local.
CM: All concerns are stated.
Conclusion/Resolution
The committee agrees that those wishing to advance shared array buffers must explicitly address the following before further advance is considered:
- To what degree might shared array buffers exacerbate the side channel problem that web browsers suffer from?
- The issue is the potential increase in vulnerability over the status quo.
- How bad might this new side channel be?
- How can we be confident that it is not worse than that?
- How bad is the status quo?
- How much less bad could the status quo implementation be without breaking the web?
Cite: lars-t-hansen/ecmascript_sharedmem#1
[Waldemar: I couldn't attend the meeting because of an injury accident but was asked to share my concerns about how bad this can be. Here's a paper demonstrating how one AWS virtual machine has been able to practically break 2048-bit RSA by snooping into a different virtual machine using the same kind of shared cache timing attack. These were both running on unmodified public AWS, and much of the challenge was figuring out when the attacker was co-located with the victim since AWS runs a lot of other users' stuff. This attack would be far easier in shared-memory ECMAScript, where you have a much better idea of what else is running on the browser and the machine (at least in part because you can trigger it via other APIs).
eprint.iacr.org/2015/898.pdf ]
- To what degree can normal JavaScript code be insulated from the complexity of modern memory models?
- For code that does not itself touch a shared array buffer, but for example, merely calls something that does, it is not reasonable to disrupt the programmer's understanding of the JavaScript program in terms of naive sequential consistency.
- Of course, one can do that at the price of fine-grain synchronization and/or avoiding all interesting compiler reordering like common subexpression elimination. But such approaches are likely to kill the performance that motivates this proposal in the first place.
5.2 SIMD.js Stage 3 proposal
(Daniel Ehrenberg, John McCutchan, Peter Jensen, Dan Gohman)
DE: (update)
(Copy from slide)
AWB: do you mean they are not canonicalized in a SIMD.js operation or when you extract? lumping load/store w/ extracting
DE: canonicalized at extraction
- Interfacing between SIMD and TypedArrays, never creating a JS scalar
AWB: don't think you need to say this
DE: consensus among implementors was to specify.
AWB: I don't think this is observable. It is no more observable than normal number arithmetic, you can tell with two values but not necessarily that a third is the same
DE: change makes spec more strict.
DH: observable.
AWB: TypedArray, have a signaling NaN. SIMD signals on signalling NaN, if the SIMD unit processes, you must get exception thrown.
DE: Yes, I think that's what should happen, but we also removed the feature in another case. It's not really in use
AWB: Read from TypedArray a f64, allow that to continue being a signalling NaN.
DE: We were trying to make the change on the writing side, but we changed to not care about that
AWB: concern that implementation will have to change to allow for signalling NaN. Saying that the implementation cannot change that to a non-signalling NaN.
AWB: Do any known implementations treat signaling as non-signaling?
PJ: x86 doesn't, it just uses the default control register
DE: We don't allow people to turn that on from JS anyway
DE: Suggested to make lane an argument to load/store
BE: case wants constant. (lane argument)
(Copy from slide "changes")
DH: (question about partial staging?)
BE: Seems better than going back to zero
DE: Diff in how hardware works, between ARM and x86. Proposal to have opaque type for this case
BE: Don't know how to fix this without support from hardware?
DG: We have a proposal that works, but we don't have enough confidence. Current proposal doesn't use an intermediate type
(Copy from slide "questiosn raised by reviewers")
- SIMD as a built in module (now, global object)?
- Methods on wrappers (now, static functions)?
- Class hierarchy to reduce duplication?
- Equality semantics?
- Motivation for certain operations?
DH: agree, modules should not be a blocking depedency
AWB: Possible to define as module, but also not be a blocking dependency ...Issue is the size (500 intrinsics) relative to the actual use.
DE: down to 300 now, signed vs. unsigned added an additional 100 or so
AWB: Didn't have to.
DE: targeting asm style compilers and normal JS JITs
AWB: One possibility: build heirarchy. eg. All the integer types can share an add method. You need to check the arguments anyway.
BE: this is class-side inheritance
AWB: confirmed. ...Type check -> type dispatch. ...add method can check type of value
BE: you're saying that implementations need to optimize down to functions with typed arguments
Discussion re: overall design.
AWB: remaining concern: huge API surface area
DE: Still don't think it's a major concern.
whiteboard...
SIMD.Int32x4.fromInt16x8Bits();
Could be:
SIMD.Int32x4.fromBits();
Because type check must be done anyway.
JMC: Doing that loses the static knowability
DE: Big difference between optimizing for a completely unknown case and just deoptimizing for disallowed types.
JMC: in terms of RTTI you don't lose anything, but in static case you do
static types give us hints, otherwise we...
AWB: a hint is just a hint, still have to handle the general case
DE: we can propagate the type infomration in asm.js
AWB: this is a general type inference propagation problem
BE: Full JITs do that, but asm.js doesn't. This is not a simple API
DE: Not usable by people who don't know what type they're working with ahead of time
BE: SIMD programmers must now the exact types, they'll write by hand. Nobody is calling for the frombits case except you (AWB). JMC, do you agree?
JMC: people will write this code by hand. people know the types, every SIMD program is completely typed. Nobody cares for a generic conversion, they know the types, it's been propagated the whole way through
AWB: That's generally true for most code that people write in most application domains. You just don't redundantly annotate the operations with the types
BE: I don't think frombits is a user concern
DH: This is a JavaScript DSL
RW: when you have uglifiers, like closure, it will alias builtins
PJ: that's OK, the declaration needs to be in the same context. if you look at asm.js code, that's how it works currently
RW: my question was about the static knowability, WRT to JMC's point
DH: (explains how optimizer can determine that builtin is aliased)
BE: seems like the remaining complaint is too many methods
AWB: is there some fundamental API design that can reduce the number of methods?
DH: I don't think counting the number of methods will lead to better design.
... The overall problem domain is affected by the combinatorics. It's a large domain.
JMC: you're asking is there some alternate API design we could have? We have as a group collectively tried to accomplish this, and we don't think there is.
BE: signed vs. unsigned operators
JMC: feedback we got is that the API would be better with explicit types. It goes against another constraint, lets have fewer functions.
AWB: my argument is have multiple types, but share functions between those types
DE: Doesn't work in asm
AWB: short term trade off
BE: Explicit type instructions that map to hardware instructions ...SIMD is only about hardware instructions
DE: equality semantics... should -0 === 0
wanted to generalize to value
types, is this what we want? should it be SameValue?
AWB: if you have Float32(0, 0, 0, 0) === Float32(-0, -0, -0, -0)
, how
should those be compared?
DE: we don't think this will be useful for devs at all, it just needs to be defined. Simplest definition I could think of, and implementable
AWB: ===
gets applied to each of the elements?
DE: Correct.
AWB: Same issues that come up with scalar numbers in JS
positive and negative zero are equal, but NaNs aren't necessarily
DE: Could be that ===
is considered a "legacy"
AWB: I don't have the solution...
MM: Find deep equality with SameValue attractive
AWB: possibly, but I'm concerned about maps and sets. using a map for memoization, key is a SIMD vector. you want to memoize float32x4 differently with +0 vs -0
let m = new Map();
m.set(Float32(0, 0, 0, 0), 1);
m.get(Float32(-0, -0, -0, -0)); // 1?
DE: Don't think anyone will do that.
MM: memoization is a strong argument
DE: I don't think memoization is useful for SIMD vectors
BE: used for constants.
MM: memoization is broken if you don't distinguish +0 and -0, e.g. dividing by this produces positive or negative inf ... Any NaN contained, must be not equal.
DE: you already have to do that with floats.
MM: not if we say that === is non-reflixive with the values
DE: Impemented in some browsers, seem convenient to us.
MM: strong preference. when it is applied to anything other than direct application to a scalar, mathematical equivalence class must be reflexive
Discussion of ===
and ==
semantics.
DE: I wouldn't want to make different behavior for ==
AK: This is more appropriate for Brian to deal with; DE said it's not important to SIMD.
DH: Is problematic for me that NaN !== NaN
, except for when it's in a
SIMD value, eg. Float32(NaN, 0, 0, 0) === Float32(NaN, 0, 0, 0)
... Only reasonable semantics: component-wise ===
, respect NaN
BE: it seems like we'll break with IEEE754
AWB: it seems logical that === should propagate out through the components for value types
BE: Do SIMD programmers want all NaNs to not equal?
JMC: Yes
BE: Do SIMD programmers want -0 to equal 0?
JMC: Yes
MM: Understand -0/+0, by why NaN semantics?
AWB: my only concern with the present design is WRT maps and sets. we decided to use SameValueZero
let m = new Map();
m.set(Float32(0, 0, 0, 0), 1);
m.get(Float32(-0, -0, -0, -0)); // 1?
AWB: we could define SameValueZero for vectors to not distinguish + and - zero.
DH: we want SameValueZero and === to be recursively defined
DH: nobody expects 0 and -0 to be different in a set, nor do they expect NaN to be different
RW: And has, get will behave accordingly:
let m = new Map();
m.set(NaN, 1);
m.has(NaN); // true
m.get(NaN); // 1
// even though NaNs are not `===` equal.
DE: we assume that SIMD users are more clever and will not be confused by this?
MM: we all agree that SameValue recursively does SameValue. My preference is that all of them recur with SameValue. Next... (missed the specifics here, sorry)
... in order to implement SameValue, if x != x && y != y then return true; else ... it knows that NaN is a bizarre case, and it tests for it explicitly. It knows that 0 and -0 are weird and test for it explicitly. That coding pattern is copied a lot
BE: this won't get any better with this
MM: I'm not suggesting that SIMD.js diverge, just for value types
DE: Brian, do you have an opinion?
BT: I'm in Dave Camps
MM: I'm going to register an objection, but if no one else agrees, then I'll let all these recur on themselves.
AWB: that's how value types should work, still concerned about maps. Maybe we should revisit for maps an explicit comparison function.
rwaldron/tc39-notes/blob/master/es6/2013-01/jan-31.md#mapset-comparator
rwaldron/tc39-notes/blob/master/es6/2013-11/nov-20.md#reconsidering-the-map-custom-comparator-api
BE: We have unfinished business with map
DE: We have an objection registered, but consensus on the current equality spec
Discussion of min/max vs minnum maxnum. Defined by IEEE754, related to NaN behavior. minnum/maxnum will return the other value if one is a NaN
JMC: confirms that IEEE754 defines min num, max num
AWB:
discussion about including length in SIMD operations
MS: Resolution on built-in module?
DH: Need module loading completed
AWB: Don't need this
YK: Signed up for this previously, can restart work on it.
DH: Browser vendors are blocked on loader api
AWB: we should as a matter of policy, call an end to adding new globals
DD: I don't agree, the global object is where you put these things
DH: aspirational, but not there yet
AWB: Stage 3 means API is frozen.
DE: There is an outstanding API question re: {load|store}[123]
(load1(...)
, load2(...)
), that needs to be investigated. Potential
performance cliff.
YK: TLDR here is if you still want to make this change, you need to signal to the implementors that this is what stage 3 means
DE: Can decide now that we're not going to do this change.
PJ: problem is that we want people to use constants for accesing the lane, but they don't have to, and that needs to work
JHD: how hard would it be to split the load/store methods into stage 2, and the others move to stage 3. Does it work without those methods?
AWB: you could code the equivalent, not as efficiently
BE: will we learn more to help us decide?
JMC: this is a relatively new suggestion. I don't think we'll learn anything new performance-wise. If compiler cannot be sure that it is a constant, it can choose not to optimize. Let's just make a call
DG: difference from extract lane: there are indexes in bounds that we can't be sure to make fast. Slow and tricky to implement
DE: behavior is strange to have operation throw if it would be slow
AWB: Still alot to work on in the spec. Is it at API freeze state or not?
BT: to the best of our knowledge, no changes.
AWB: enough thorough review of this large and complex addition to the language?
BE: SIMD seems stable. it's funky but its gone through the paces for stage 3. We wanted it for 262 because it blazes the trail for value types
AWB: more comfortable in another spec
Conclusion/Resolution
- Stage 3 Approval
{load|store}[123]
- Consensus on existing
- Equality Semantics
- Consensus on existing
- An Objection from MM
- Work to do on Maps and Sets
10 Tooling Update
(Brian Terlson)
BT: All proposals are now using ecmarkup
- 402 Complete
- 262 In progress
CM: Need improved workflow documentation.
AWB: Concerns about general public review; diffs not ideal
YK/DD: will review visual, structural diffing tools to add to workflow
Conclusion/Resolution
- Write up workflow documentation.
- Review and recommend visual, structural diffing tools to add to workflow
- Move 262 to Ecmarkup
5.4 Updates on class-properties proposal
(Jeff Morrison)
JM: (updating)
YK: Decorator interop, with this proposal, needs reflection
JM: Don't decorators operate on the instance?
YK: Unrelated, decorators are described in terms of descriptors.
MM: How do class instance properties interop with decorators?
... Revisiting the proposal semantics.
MM: Expression itself is evaluated once per instantiation?
YK/JM: Yes
AWB: How does inheritance work?
JM: Each property and expression is evaluated in top down order as a result
of super()
in constructor() {}
YK: Mark suggests that these go in the constructor
BE: Problematic:
class C {
ha = eval(args)
}
var args = "arguments";
var huh = new C();
console.log(huh.ha); // ?
JM: as written, the this
binding is the object that's been instantiated.
DD: This is an issue, the lexical scope is unclear
BE: But there is a "secret" thunk scope
JM: Users have been using this in Babel without any confusion about the expression being delayed or defered.
Discussion about arguments
and this
MM: How is this an improvement over jeffmo/es-class-properties#2 ?
DH: (responding to alt proposal) the syntax isn't good.
- The class body is for declarative parts of the object template
- The constructor body is for imperative initialization parts
Easy to get caught up in semantics and lose sight of syntax.
MM: Disagree. Convention to follow: always begin a class by putting the constructor first and in the constructor, properties declared, then blacnk line (for organization).
RW/AWB: Where does super go?
MM: This is an open question. Depends on what you need to do with instance properties and when
Discussion comparing:
class Point {
constructor(x, y) {
public this.x = x;
public this.y = y;
}
}
vs.
class Point {
public this.x = x;
public this.y = y;
constructor(x, y) {
// ...
}
}
x
and y
not in scope.
JM:
class Stuff {
autoBound = () => {
console.log(this);
};
id = getId();
}
DD: This SHOULD be written in the constructor.
RW: Completely agree, and also concerned with:
class Stuff {
a = () => {
console.log(this);
};
b() {
}
}
AWB: And what is arguments
in that arrow?
JM: Same as arguments immediately before the class declaration:
function foo() {
arguments; // same
class Bar {
a = () => {
arguments; // same
};
}
}
...
Discussion comparing the merits of Mark's proposal vs. Jeff's proposal.
MM: These declarations should result in non-configurable properties.
YK: Disagree.
Conclusion/Resolution
- Move to stage 1
- Jeff will follow up with Mark to further discuss his counter-proposal, and Allen to further discuss his thoughts on private properties
- Jeff will update proposal to store property declarations in slots (rather than container on prototype)
- Jeff will include reflection API for introspecting/reflecting declared properties
Sept 23 2015 Meeting Notes
Allen Wirfs-Brock (AWB), Sebastian Markbage (SM), Jafar Husain (JH), Eric Farriauolo (EF), Caridy Patino (CP), Mark Miller (MM), Adam Klein (AK), Michael Ficarra (MF), Peter Jensen (PJ), Domenic Denicola (DD), Jordan Harband (JHD), Chip Morningstar (CM), Brian Terlson (BT), John Neumann (JN), Dave Herman (DH), Brendan Eich (BE), Rick Waldron (RW), Yehuda Katz (YK), Jeff Morrison (JM), Lee Byron (LB), Daniel Ehrenberg (DE), Ben Smith (BS), Lars Hansen (LH), Nagy Hostafa (NH), Michael Saboff (MS), John Buchanan (JB), Gorkem Yakin (GY), Stefan Penner (SP)
5.5 Decorators Update
(Yehuda Katz)
wycats/javascript-decorators/tree/big-picture
YK: Consider this an exploration in several cross cutting features that are in development.
class Person {
@reader _first = "Andreas";
@reader _last = "Rossberg";
}
let andreas = new Person();
andreas.first // "Andreas"
andreas.last // "Rossberg"
The @reader
decorator has created the getters for first
and last
. ie.
class Person {
@reader _first = "Andreas";
@reader _last = "Rossberg";
}
// Actually produces...
class Person {
_first = "Andreas";
_last = "Rossberg";
get first() { return this._first; }
get last() { return this._last; }
}
Assume @reader
is defined as:
function reader(target, descriptor) {
let { enumerable, configurable, property: { name, get }, hint } =
descriptor;
// extractPublicName('_first') === 'first'
let publicName = extractPublicName(name() /* extract computed property
*/);
// define a public accessor: get first() { return this._first; }
Object.defineProperty(target, publicName, {
// give the public reader the same enumerability and configurability
// as the property it's decorating
enumerable, configurable, get: function() { return get(this, name); }
});
}
function extractPublicName(name) {
// Symbol(first) -> first
if (typeof name === 'symbol') return String(name).slice(7, -1);
// _first -> first
return name.slice(1);
}
AWB: How is super
treated, when encountered?
YK: Not yet considered, avoiding entanglement with yet to exist features, trying to stay future proof to account for them.
Moving on to: wycats/javascript-decorators/blob/big-picture/interop/reusability.md#basic-rules-of-decorators
DH: Decorators vs. macros: staging. Decorators good next step
YK: Consider decorators a meta programming facilities.
Basic Rules of Decorators:
- Decorators always operate on a particular syntactic element, providing a hook into the runtime semantics for that syntax.
- If the runtime semantics for the syntax include
let x be the result of evaluating SomeExpression
, that expression is passed into the decorator as a function that, when called, evaluates the expression (a "thunk"). - Decorators are not macros: they cannot introduce new bindings into the scope and cannot see any downstream syntax. They are restricted to operating on a local declaration using reflection tools.
AWB: Why not capture the property key, could be computed property
YK: Don't want to make that policy decision, but can revisit.
AWB:
YK: general open question about whether a decorator function has to return a descriptor or not. alternatives like "false => cancel property creation"
or "undefined" to keep going untouched, etc ...explanation of "decorate" implementation in the appendix, which is semantics, but not API.
DH: question about if decorators have to be identifiers, or LHS
YK: (explaining how computed and uninitialized property decorators would work the same)
YK: static properties would be treated the same as object literal properties, as type "property" instead of type "field"
Discussion re: static @reader
vs. @reader static
YK: you have to decide where to put the decorator, I've always put it to the right. Usually modifying the builtin thing
AWB: I've always thought of it as modifying the declaration
question about shadowing symbol bindings in Methods example, update function
YK: easy to create shadowing hazards with symbols and function args
(explanation of decoration on properties in object literals using shorthand syntax)
DH: basically the hint is a tag to explain to the decorator function the context being used
YK: yes, this is a motivating example
AWB: ambiguity here? can't tell whether the user wants to initialize to null vs. normal shorthand syntax
YK: it's up to the decorator to decide the semantics
YK: simplest solution is to say that you have to type @reader _first: undefined directly
YK: but my suggestion is to allow decorator to decide
(describing how the motivating example would look in MM's syntax)
public @reader this._first = first;
YK: feel less strongly about how in-constructor declaration is bad. Moving @reader to the right of public
DH: I don't think that's the issue. more important that properties are at the toplevel of class
YK: not arguing one way or the other for "initialization in constructors or not" but trying to demonstrate that that question is orthogonal to this topic
MM: accept that this is orthogonal
YK: showing syntax alternatives for privates, not trying to bikeshed
YK: in this hypothetical privates scenario, subclasses would not have access to superclasses' "private" fields, ie, lexical scope
YK: no reflection API to get at privates outside of lexical class body, and Proxies do not allow access to it
DH: if you want to think of it like weak map...
YK: that's not the programming model or representation. Reflect.construct is a difference
DH: doesn't affact intercession
YK: from semantics perspective, very similar
Discussion of observable differences between weakmap and this
MM: only becomes observably different in the future were it could be reified
YK: I agree. My proposal doesn't make it a weakmap, but from a programmer perspective, you could see it that way
AWB: difference: a mirror of private state needs to be presented to decorator, mirror is presented at class definition time not instantiation time…
YK: there's one difference, it's a read only WeakMap - you aren't allowed to set the fields
MM: about mirror: mirror is reflecting on the class...
AWB: no instance-level reflection
MM: why does the reification of the field name as part of the reification of the class need to be able to give read access to the instance value
AWB: it doesn't
YK: TL;DR new metaproperty called class.slots, effectively a limited subset of the weakmap API. only operation I care about is class.slots.for, gives dictionary with private fields
MM: some reification of the name of the private fields?
YK: just the ones that are lexically available to the class definition. Gives keys and values of properties declared
MM: why give the ability to read the instance value, but not to set the intsance value
YK: sorry, imprecise. You can set private slots, cannot replace dictionary. Think of it as non-configurable
MM: ok, good. reification is not quite a weak map, doesn't have ability to delete. Violates the fixed shape constraint
AWB: agree details need to be figured out, but big picture sounds good
YK: (describing syntax class.slotsof)
MM: class.slotsof is a special form
YK: refers to a lexical binding, not value. wanted for ergonomic reasons, if you need to do things on the class outside of the class definition lexical scope
AWB/YK: better to try to move this inside the class definition, perhaps with a static { ... } block inside the class definition
(discussion of accessing parent's slots from nested inner class)
DH: for this case, just use a local variable in parent scope, can be accessed by inner class. maybe let bindings in class definition?
YK: class.slots reification mechanism is 90% sugar
DH: (example of let binding of class.slots in class toplevel so binding can be accessed by inner class)
AWB: if you have this you have less need for static private slots
YK: static method that you invoke and delete immediately has same behavior
(discussion of private statics)
MM: thing that makes private statics different, for an instance, all contributions are collected into one instance, in static it is spread out over the prototype chain... should be able to let the prototype chain do it's work
AWB: don't think so, what if you make an instance count static. now define subclasses, don't they get their own instance count?
MM: but they can't access it
YK: (getting back to presentation)
YK: (explaining how slots.for is abstraction for get/set in decorator for public vs. private properties)
(come back to field, slot, property distinction)
BE notes:
- class elements define properties of the class prototype, class statics of the constructor
- JM's property declarations specify something else: instructions to run
from
[[Construct]]
before the constructor call - this suggests using "field" as jargon for JM's public property declarations and YK's private slot declarations
- field: instance property instruction specified by declarative new kind of class element, public or private
- slot private field AWB recalls ARB's V8 self-hosted JS has private slots, want them to pack in instance storage
DD: cannot be allowed to run synchronous operations arbitrarily in all constructor (HTML Elements, etc.)
YK: Agree, lock down reflection APIs
AWB: Any new reflection APIs should be reviewed by Mark for security
(lunch)
YK: Summary...
- Decorators on methods
- Decorators on object literal properties
Neither rely on some other proposal
DE: previous proposal mentioned function decorators
YK: Issues
- Staging
- Where does decorator go? It's clear with class and object literal, not with function decl.
AWB: TDZ?
// TDZ on access vs invocation
addEventListener("error", onerror);
@metadata("foo");
function onerror(...args) {
}
Unclear what this does.
DH: The decorator is not wrapping, is mutating existing object.
- not calling the decorator later.
- An identity decorator should be equivalent to not having a decorator at all
- Becomes the one place a decorator is not wrapping.
Angular use case: want to decorate function declarations for unit testing.
DH: factor out function declaration decorators. Rather have an imperfect decorator than none at all.
YK: Not actually proposing this.
MM: Happy with this at stage 1, no controversy.
YK: Important change: If expression, thunk on it. (thunking in lieu of quoting)
AWB: is there specifically a name parameter that is that thunk?
YK: yes.
AWB: trying to understand various binding contexts where wouldnt want to evaluate ...
YK: not confident that there is no case to defer evaluation
AWB: concerned about expressions not being evaluated
Discussion, re: effect on computed and non-computed properties
JM: VM authors lose the ability to understand the shape?
YK: No
AWB: requires analysis at runtime, rather than compilation.
AK: might lose runtime fast path
DH: can't be any worse than existing policy of looking at the shape after the constructor is done.
AK: Once you see decorator in literal, the VM gives up until sometime later.
YK: Doesn't mean it's slow
AK: In the short term, maybe.
DH: need to udnerstand challenges:
- already ahave machinery to analyze and find optimizations
- accept that decorators may have a slow first implementation
- why can't you then immediately optimize with existing machinery?
YK: Request moving presented today and "privates" (abstractly) to stage 1. Want to think about future additions in terms of being decoratable.
DD: Not enough discussion re: decorating shorthand properties.
AWB: This is just part of feature design details.
AK: Don't understand the "bundle".
YK: Form a champion group to work forward these features as a group.
JM: Do something outside of committee.
- Private state
- Decorators
- Decoratable object literal properties
Conclusion/Resolution
- Remains at Stage 1 with all changes presented
5.3 Async Functions
(Brian Terlson)
BT: Stage 3 proposal?
- Waldemar has reviewed, changes in place.
- Yehuda and I agree on cancelation
- Believe that cancelation can be done later
YK: If you don't type return
in your async function, no way to the return
path. May have written some finalization, but no way to guarantee
BT: Can write async that assumes some finalization, that might not happen.
YK: In the absence of cancelation, if there are no upstream promises to reject...
DD:
async function foo() {
setup();
await delay(5000);
cleanup();
}
const p = foo();
p.cancel();
// Would need to be...
async function foo() {
setup();
try {
await delay(5000);
} finally {
cleanup();
}
}
const p = foo();
p.cancel();
If async functions forever stay non-cancelable, no issue. If all async functions become cancelable, the hazard is introduced.
BT: async functions must be cancelable. We won't add them unless they are.
- fulfilled: normal completion
- rejected: throw abrupt completion
- canceled: return abrupt completion
- ???: continue/break abrupt completion
JHD: q. about synchronous "return abrupt completion"
YK: Generator, call return()
"Return Abrupt Completion" is for any kind of return from current execution
BT: case where promise returned by async function, awaiting 5 promises? A promise is canceled, reasonable to handle that promuse and move onto the next thing—otherwise have to nest 5 try/finally deep.
Discussion of return, cancelation and recovery.
AWB: A new type of completion?
YK/BT: Yes
JHD: Clarify need for cancelation?
BT: Cancelation important, widely wanted, they will come to Promises, and will not be able to use async functions for that. So needed for async.
Discussion re: promise cancelation, how to introduce it.
CM: clarification between the two main uses of a cancelation.
YK: Promises should be allowed to represent themselves as cancelable
CM: No disagreement.
JHD: maybe cancel is just the wrong name?
YK: cancel impacted design, want to make sure that adding cancel to async function in the future wont pown them.
BT: haven't found significant issues with cancelation for async functions
- Subtle to add to Promises, but work needed
- No obvious issue to add to async function
Hazard:
async function foo() {
setup();
await delay(5000);
cleanup(); // <-- not called if canceled.
}
...
DE: Changes since last update?
BT: No relevant.
AK: Async arrows?
BT: Waldemar reported no issues.
DD: Should use try/finally to guarantee cleanup. Strictly a hazard if
someone starts calling cancel()
on your promises.
BE: Does this push up need for finally method?
BT: Need more work there.
YK: finally
is a handler, doesn't correspond to a completion record
change, but a cluster of completion records
DD:
async function foo() {
setup();
try {
await promise;
} catch cancel {
// recover and continue?
} finally {
cleanup();
}
}
promise.cancel();
BE: Add cancel to Promises, then ok for async/await
BT: finally is being conflated with cancelation
This is stage 0.
SP: A future where finally is important, if code written to expect, then ok.
BE: Should use try/finally, regardless of await
...
BT: Chakra has implemented async/await on Edge. SpiderMonkey may have implementation? In Babel, TypeScript, Flow.
DH: Confirmed active development in SpiderMonkey
JHD: (some q about try/finally)
SP: assume code written indefensively might fail.
More totally useful, important, completely clear and not repetitive discussion about how bad code might fuck up if promises are canceled.
Conclusion/Resolution
- Stage 3 Approval
ECMA 402 Update
RW: blah blah blah
AWB: A lot of proposals, what is the criteria for new additions
EF: Paving cow paths, otherwise remain in library code. Working on proposals for plural and relative-time formatting.
CP: For ES2016, we will focus on exposing low level apis for existing abstract methods. New features will probably arrive in ES2017.
DD: FirefoxOS devs discovered real needs that are being reported.
EF: Getting the locale data (e.g. CLDR data) into/accessible-by the runtimes is a focus because it avoids haivng to transfer larges amounts of data over the network. NumberFormat and DateTimeFormat have large amounts of locale data to back their APIs; looking to do something similar for plural and relative-time formatting proposals.
Conclusion/Resolution
- Send new HTML to Ecma
5.10 Proposal: String#padLeft / String#padRight
(Jordan Harband, Rick Waldron)
ljharb/proposal-string-pad-left-right
JHD: (run through history of proposal)
- min length vs. max length semantics? min length semantics with repeat. max length is the desired functionality.
AWB: re: min length and max length, concerning unicode characters, code points.
JHD: Issues will exist in any string apis. This API doesn't use code points, can be changed to do so. Length property wouldn't be useful. If filler is a surrogate pair, I can use a multiple of it's length...
- Max length is in code points?
DH: re: terminal output, do control characters count against length?
JHD: Yes, always.
Discussion, re: code points vs. latin centric characters
BT: This API is no different than existing APIs
JHD: really want to solve this? Change everything to use graphemes
AWB: interpret "length" as simply: "number of occurrences of your fill character"
DD: assumes the rest of your string is Emoji. Never going to get the width correct.
AWB: if it doesn't do the right thing in the real world, why?
BT: Trying to do things beyond the simplest use case is just untenable.
RW: Intl could adopt responsibility for a non-latin character set handling?
BT: Agree.
Derailed into discussion about what gets to go in the standard library and what gets defined in a standard module.
DH: (To Rick) Not cool to attack other specs when inclusion of proposal is questioned.
Note: I made a comment that if two string methods are "too much", then we should revisit SIMD for the same concerns.
Back to padLeft, padRight...
DH: Clearly important if implementers are agreeing to implement before other features.
Discussion re: stage 1 or 2?
AWB: For stage 2, controversy resolved.
JHD: Then stage 1.
Conclusion/Resolution
- Stage 1
- Reviewers to be assigned.
5.11 Proposal: Object.values / Object.entries
(Jordan Harband)
ljharb/proposal-object-values-entries
JHD: Need is obvious.
Question about return: iterable or array? Spec wants to be an array.
DH: Confirm, when array you get a snapshot. If an iterator, then updates
would be shown, which breaks from keys
Conclusion/Resolution
- Stage 2 Approval
5.12 Proposal: String#matchAll
(Jordan Harband)
ljharb/String.prototype.matchAll
JHD: pass a regex, returns an iterator, each yield returns what exec would.
Notable:
- doesn't accept a string, not coercion
- always adds the "g" flag
- makes a "copy" of regexp to avoid mutating
BE: reason for not including string?
JHD: Enforces a better practice
AWB/BE: valid, but creates an inconsistency, should be updated to include string.
JHD: Will update then.
AWB: Needs to work with RegExp subclass as well.
DE: Will call RegExp.prototype.exec, can leak the RegExp.
Confirmed.
Specify as @@matchAll
AWB: Default impl of @@matchAll
, see default @@match
DD: Not a lot of "library" code
BE: Won't find it there, it's generally in "open code". Steve Levithan wrote about this.
YK: Ruby has a scan method, which I use frequently.
DD: an alternate: add another flag that avoid global state
nah.
DE: Still leaks.
Can we avoid the observable "cloning"?
BE: Take back to work through this
Discussion of algorithm approaches.
YK: Missing? A thing that's like exec, but gives you back the lastIndex?
AWB: exec()
could grow an additional argument for start position.
The name stinks, but nothing really better.
matchEach
? It produces an iterator... (some agreement)
nah.
Conclusion/Resolution
- Stage 1 approval
- Accept strings
- Allow RegExp subclass
- Default impl of
@@matchAll
, see default@@match
5.9 Trailing commas in function parameter lists
(Jeff Morrison)
JM: Updates since previous...
MF: Change arity? Object, array...
RW: No, ignored.
YK: Symmetry with arrays? Holes on the call side?
nah.
BE: (revisit C issues with trailing commas)
AWB:
Missing:
- evaluation rules
- static semantics rules
BT: Don't need to block on this, can be delivered later.
Quick run through trailing comma in parenthetical expressions
nah.
Conclusion/Resolution
- Stage 2
- Reviewers?
- Michael Ficarra
- Brian Terlson
Process Discussion
- A plenary day
- Two presentation and discussion days
Exponentiation Operator
RW: Precedence issues:
BE (On whiteboard): -x^y in math and every other language means -(x^y)
Old spec is (-x)^y
AWB: Does the potential confusion of this (whichever way it happens to be decided) suggest we should pull it out?
BE: No, math and every other programming language do it this way...
AWB: I agree if there is an exponentiation operator the precedence should be followed going back to math. Since this potential confusion has been identified, we have a perfectly good way to do this...
RW: This is a case of the new process working as it should - implementers gave feedback, proposal is now better.
YK: Arguing for -5 ** 2 being (-5) ** 2 because people will think that's how it works.
YK: I think minus is kind of an edge case and I'm happy with this either way. Is my intuition wrong? If everyone else thinks the answer of what the proposal is now, then fine.
BE: Problem is people thinking minus is part of the literal.
DH: For math it seems obvious that -5^2. But for -5 ** 2, because of the whitespace around the infix operator. Even without space, - seems to be part of the literal.
BT: Python docs says don't use space.
YK: Doesn't JS precedence win over all other precedence?
RW: Jason's intution matches that of all other programming languages that has intuition operator.
YK: This is cargo culting.
BE: Let's say that fortran did it to be mathy and everyone copied it. There's still a precedence argument.
YK: I'm a rubyist. I had to look up what is in ruby. People don't know ow it works.
DH: We are operating in the context of an industry that gets expectation from historical context or JavaScript operators?
BE: You should be parenthesizing.
RW: Coffee's ** operator matches Python and Math and Ruby.
JH: Will value types complicate this? Will people copy/paste from C programs or other things? JS is eating the world. This will cause friction if we break historical precedence.
YK: I don't copy/paste code from other languages.
BE: Options: 1) wall of confusion, do nothing. 2) math/programming language precedence. 3) Javascript/dave/unary minus binds tighter people.
RW: Mark advocates for abandon/withdraw (1)
BE: Let's vote...
1: 4, 2: 15, 3: 2 (including MM virtual vote)
DH: Let's be clear - people might copy code I guess, but effectively zero people have an intutition about this from other languages. Agree people have an itutition that ** is the exponentiation operator. But people usually try to avoid dark corners so they never develop an intuition for negative bases.
I also reject that we must do what math does.
DD: I disagree.
BE: New option: 4 - it is an error to combine ** with unary minus. Code you port doesn't have this almost for sure.
No consensus... people are leaving.
Sept 24 2015 Meeting Notes
Allen Wirfs-Brock (AWB), Sebastian Markbage (SM), Jafar Husain (JH), Eric Farriauolo (EF), Caridy Patino (CP), Mark Miller (MM), Adam Klein (AK), Michael Ficarra (MF), Peter Jensen (PJ), Jordan Harband (JHD), Chip Morningstar (CM), Brian Terlson (BT), John Neumann (JN), Dave Herman (DH), Rick Waldron (RW), Yehuda Katz (YK), Jeff Morrison (JM), Lee Byron (LB), Daniel Ehrenberg (DE), Ben Smith (BS), Lars Hansen (LH), Nagy Hostafa (NH), Michael Saboff (MS), John Buchanan (JB), Gorkem Yakin (GY), Stefan Penner (SP)
On the phone: Mark Miller (MM), Istvan Sebastian (IS)
Exponentiation Operator
RW: BE suggested option 4 yesterday (throw when unary negative is used without parens)
(whiteboard)
// Ok
let z = K - x ** y;
// No Ok
let z = -x ** y; // Syntax Error
// Must be:
-(x ** y)
// Enforced by grammar change, just a SyntaxError
RW: BE wrote up option 4 and a summary and emailed to esdiscuss
RW: similar to TDZ: an error when something ambiguous happens
RW: AWB + MM switches 1 vote to 4, RW switches 2 vote to 4.
RW: question to group: do we have consensus on stage 3 with option 4?
AK: i think this sucks for users
RW: only when the user does something ambiguous
AK: we already have Math.pow which is unambiguous. why add another way that has ambiguity concerns? it looks confusing to me as a user.
AWB: it requires that you put in parens, what a careful developer would already put in parens
RW: considering your feedback (a syntax error would be a bummer) are you willing to block consensus?
DH: I will push spidermonkey team to display a better error in this case
AK: i think it's just fine to choose one (ie option 2 or 3) and i chose option 2
DH: that's just going to be a bug farm
BT: like it is in every other language?
DH: yes.
YK: there's bugs in every other language, but we don't have to copy those bugs into JS
RW: this is sufficiently useful to the end-developer
DH: Here's another way of looking at it: there is a natural ambiguity between two historical precedents, reasonable to expect it to go one way or the other. Don't just pick one because it will confuse people who expect the other. Making it an early error to avoid the ambiguity is good software engineering practice
AK: why do you think other langs (with exp operator) don't make this an error?
YK: they cargo-culted it.
AWB: some of them actually have negative numeric literals (option 3) baked in to the language.
DH: so -1 actually ends up doing the right thing...
AK: I'm not the only one who thinks this, Waldemar might think this too
RW: I don't think so; Waldemar supported requiring parens early on
DH: very recent precedent for exactly this kind of decision when andreas proposed that "use strict" implications for parameter lists were ambiguous; we decided to make all of the ambiguous cases SyntaxErrors to avoid confusing people one way or another. That was a good decision, this is similar. Let's not knowingly create an ambiguity where both are reasonable interpretations.
MM: in agreement with Dave, avoid misinterpration where the consequence is the program proceeding without diagnostic that defies user expectation
MM: ... proceeds without a diagnostic that violates user expectations.
AWB: if we're wrong about this and get tons of complaints, we can always remove the SyntaxError and select options 2 or 3 later.
DH: Oh, python has the same error... -1**2 == -1
AWB: maybe Matlab...
RW: concerns enough to block consensus?
MS: i agree with AK; i don't like option 4. we'll implement the spec but I think it's unnecessary complications given other languages.
BT: I think it is unnecessary, but I don't care
YK: Do you agree, if we pick 2 or 3 there are some users who will pick the wrong one
BT: yes, but that's true for everything that includes precedence. We don't make all things an error where precedence is ambiguous.
YK: there are different kinds of confusion, mixing operator classes is an especially bad kind of confusion
AK: use strict in parameter list is different -- had implementor concern as well (discussion of "use strict" w/ parameter list, comparison with this case)
YK: BT, your point about general operator precedence is valid. I wondre why the difference from the normal precedence... why is changing the precedence in a precedence class not a red flag?
BT: I'm not sure people talk about operators in terms of precedence classes
DH: I think people do -- I do. I don't remember factoring rules for BNF, I think of it terms of whitespace and "tightness" or "looseness"
AK: it was useful to see the thoughts yesterday. another straw poll would help me see if i'm an outlier or not.
YK: option 5 of "i don't care" please
RW/YK: let's say: 1 is "do nothing". inaction.
BT: I violently don't care
MF: let me remind the room; option 4 doesn't prevent options 2 or 3 later.
[poll]
-
Dropped 0
-
Hold @ current proposal (-5 ** 2 => 25) 3
-
Orig Proposal (-5 ** 2 => -25) 0
-
BE syntax 11
-
IDGAF 3
RW: we can still relax the syntax error
AK: rare enough case that it likely won't happen
DH: I'll prototype a good error in my own parser
Conclusion/Resolution
- Stage 3, with the provision that option 4 goes in
- jsbin.com/baquqokujo/1/edit?output
8. Test262 Update
(Gorkem Yakin)
GY: (General update on status of ES6/ES2015 support in test262)
BT: previously we decided it was important to have clear delineation between test artifacts at specific spec versions, but that's hard.
YK: It stops making so much sense now. Can I suggest a feature flag thing? (discussion about how to handle old tests that break with a new version)
YK: at any point in time, take a snapshot of all stage 4 features and that's what we give to ECMA
AWB: strictly speaking, only yearly releases approved by GA that are final
AWB: nothing becomes stage 4 until version of the spec they're in is approved (more discussion about stage 4 vs. stage 5)
BT: I see it this way. for implementors, there is value in having tests checked in to test262 when they're working on the features, ~ stage 2/3. Only consideration here is what implemetors find useful
YK: ok stage 3 seems fine
BT: if things break, git has tools for this. going forward let's not have branches, just say test262 is living
AK: I say stage 3
(RW agree, this aligns with implementation step)
YK: I think stage 2 criteria is test262 tests. For me, as spec author this is valuable
AWB: during stage 2, I expect these to change a lot. These are part of the artifacts
DE: for the SIMD tests, we went through a lot of churn. it makes sense to have them outside of test262, now we're stage 3, we're ok with test262
YK: I think that implementors should have commit access to test262 while they're working on it
BT: difficulty mentioned by DE is real
YK: not intractable to make this frictionless
BT: I don't think this is too bad, having written thousands myself. Not frictionless, but surmountable
YK: this sounds like a real blocker. proposal: I think you should be able to put all tests for a feature in a file, people who are working on stage2 and up features should have commit access
BT/DE: we should use pull request model
AK: nice for implementor to know these are stable, stage 3 is nice
(discussing whether we need to use pull requests vs. direct commit access)
DE: problem with stage 2 is that the API is not stable, so it doesn't provide value
DH: having tests are similar to having spec, helpful to make it clear to people how the feature works
AK: we have automated process pulling test262, we don't want to have to triage unstable changes
YK: feature flags should solve this problem
BT: difficulty is that numerous different test262 harnesses, I understand Google has their own
_ general agreement that test262 tests should be stage 3 _
DE: YK and others are going to look into adding feature flags to implementors test262 harnesses
BT: difficult to test features in isolation, they are often cross-cutting
_ discussion about difficulty of implementing feature flags _
AWB: what is the plan of record for user-facing test page?
BT: someone has to fund this work. Someone in Microsoft working part-time on this, build scripts to package the tests into a site. Maybe get UI guy to spend some time on it
MF: why do we want this?
BT: useful as a marketing feature, show how accurate your browser is
AWB: original motivation: valuable to have vendor-independent neutral test, not subject to gaming
JHD: easy to test in browser with a web link, harder with a harness
AWB: if we think it's valuable to have a website where users can run tests against multiple browsers, then some members have to step up and do the work or foot the bill. Otherwise take away the website
BT: money problem right now. accomplished webdev, about a month of effort
Conclusion/Resolution
- Test262 is "living"
5.6 Proposal: call constructor
(Yehuda Katz)
YK: (from proposal)
- ES5 constructors had a dual-purpose: they got invoked both when the
constructor was newed (
[[Construct]]
) and when it was called ([[Call]]
). This made it possible to use a single constructor for both purposes, but required constructor writers to defend against consumers accidentally[[Call]]
ing the constructor. - ES6 classes do not support
[[Call]]
ing the constructor at all, which means that classes do not need to defend themselves against being inadvertantly[[Call]]
ed. - In ES6, if you want to implement a constructor that can be both
[[Call]]
ed and[[Construct]]
ed, you can write the constructor as an ES5 function, and usenew.target
to differentiate between the two cases.
Motivating Example
The "callable constructor" pattern is very common in JavaScript itself, so
I will use Date
to illustrate how you can use an ES5 function to
implement a reliable callable constructor in ES6.
// these functions are defined in the appendix
import { initializeDate, ToDateString } from './date-implementation';
export function Date(...args) {
if (new.target) {
// [[Construct]] branch
initializeDate(this, ...args);
} else {
// [[Call]] branch
return ToDateString(clockGetTime());
}
}
This works fine, but it has two problems:
- It requires the use of ES5 function as constructors. In an ideal world, new classes would be written using class syntax.
- It uses a meta-property,
new.target
to disambiguate the two paths, but its meaning is not apparent to those not familiar with the meta-property.
This proposal proposes new syntax that allows you to express "callable constructor" in class syntax.
Semantics
- The presence of a
call constructor
in a class body installs the call constructor function in the[[Call]]
slot of the constructed class. - It does not affect subclasses, which means that subclasses still have a
throwing
[[Call]]
, unless they explicitly define their own call constructor (subclasses do not inherit calling behavior by default). - As in methods,
super()
in a call constructor is a static error, future-proofing us for a potential context-sensitivesuper()
proposal.
import { initializeDate, ToDateString } from './date-implementation';
class Date {
constructor(...args) {
initializeDate(super(), ...args);
}
call constructor() {
return ToDateString(clockGetTime());
}
}
AWB: This is an exceptional example, most cases just defer to new
, where
this goes off on some other operation.
RW:
class A {
constructor() {
this.aProp = 1;
}
}
class B extends A {
constructor() {
this.bProp = 1;
}
call constructor() {
return new B();
}
}
class C extends B {
constructor() {
this.cProp = 1;
}
}
let b = B();
b.aProp === 1; // true
b.bProp === 1; // true
let c = C(); // throws! there is no call constructor here
AWB: Think about it, not as a property added to the prototype, but as an
alternative to the constructor
MM: interaction with Proxy call trap?
AWB: class with a call constructor get a distinct [[Call]]
that knows how
to dispatch to the user defined behavior.
...no proposal yet for reflection
...no toString yet.
MM: toString the constructor, you get the entire class
JHD: currently unspecified in ES6; some engines give the "class", some give the constructor, some give a function that has no indication it was a "class"
YK: Then it would be included.
YK: shows call constructor() {}
vs () {}
inside a "class"
Mark's Alternative:
import { initializeDate, ToDateString } from './date-implementation';
class Date {
constructor(...args) {
initializeDate(super(), ...args);
}
() {
return ToDateString(clockGetTime());
}
}
AWB: i don't like it because you could forget the method name
YK: also conflicting with square bracket syntax and arrow functions lots of agreement that this is confusing
MM: happy to drop it; glad to have a reaction.
DH: only thing that gives me pause is Stroustrup's principle: new stuff, people want long syntax; later, people want short syntax.
MF: May want a decorator augmenting a call constructor (Michael, I missed the tail end of this, can you fill in?)
YK:
MS: would this allow you to omit the constructor
?
YK: class would create a default constructor
, but otherwise behave like a
function
discussion about callable non-constructable classes; general consensus is that you should use a function for this
DH: Like this b/c it matches built-ins and defines a clear separation of semantics
AWB: discussing built-ins that create wrappers ... Don't need to add sloppy mode semantics for built-ins, eg. SIMD
JHD: it's an axiom that Object(x) === x
if it's an object, and not if
it's a primitive. This must be preserved.
MM: Object.prototype.toValue, auto-wraps this
.
AWB: Then unwraps
JHD: Every JS value must be wrapped when pass through Object
.
AWB: Not saying "no wrapper", needs wrapper to do method lookup
DE: Sounds like two versions of ToObject?
JHD: in a sloppy mode function, if i do this.foo = "bar";
, and this
isn't undefined
, it always sets the property such that this.foo
can
be retrieved immediately after. If this
is a primitive, this isn't the
case. If we change the auto-wrapping behavior of "this" in sloppy mode, for
any value, then this will break existing code.
AK: Not going to add reflection here?
YK: No, but reflection is needed.
AK: Will it "grow" reflection?
AWB: We hope to advance this to ES2016
YK: Reflection is needed along side decorators and this proposal, but don't want to block this on decorators.
AWB: No reflective way to change a function with toString, but can see it's whole body. ...tweak toString, for class with a call constructor, include it in the toString representation
MM: Should be the entire class definition
DH: ??
AWB: That position is contraversial
MM: Thought we agreed?
YK: Bigger toString issue.
AWB: For 2016, toString should at least include call constructor body
MF: Want added restrictions before 2016, we can limit the reform proposal to buy time.
This can be implemented in terms of new.target
.
AWB: Nec. in support of decorators:
- If you want decorators to be able to create call constructors, there needs to be some reflective way to install them.
AK/BT: discussion potential implementation details
Conclusion/Resolution
- Stage 1 Approval
- toString includes call constructor body in output
- Goal for Stage 3 next meeting.
Secretariat
IS:
- Only Ecma-404 will be fast tracked.
- Bugs in Ecma-402 need to be addressed.
- ES2016, 17, 18, etc. might cause issues?
I can't really understand most of what's being said over the polycom.
Sounds like ES6 has a lot of downloads
Meeting Schedule
JN:
- November 17 - 19, 2015 (San Jose - Paypal)
- January 26 - 28, 2016 (San Francisco - Salesforce)
- March 29-31, 2016 (San Francisco - Google)
- May 24 - 26, 2016 (Europe)
- July 26 - 28, 2016 (Redmond - Microsoft)
- September 27 - 29, 2016 (Los Gatos - Netflix)
- November 29 - 30 - December 1, 2016 (Menlo Park - Facebook)
Conclusion/Resolution
- Need to confirm Munich in May
- Rick, Dave will figure out March
5.13 Updates on rest properties proposal
(Sebastian Markbage)
sebmarkbage/ecmascript-rest-spread
SM:
sebmarkbage/ecmascript-rest-spread/commit/f4cb9c0ff9f4509854d5d30f4517a23b1a7d7e98
var o = Object.create({ x: 1, y: 2 });
o.z = 3;
var x, y, z;
// Destructuring assignment allows nested object
({ x, ...{ y, z } } = o);
x; // 1
y; // undefined
z; // 3
AWB: Object pattern destructuring doesn't check enumerability, just goes by property name
DH: The ...
means "I'm enumerating the names"
SM: ie. getting the keys
AK: What about in the binding case?
SM: Consistency. The BindingRestElement only allows an identifier.
SM: I will write a proposal to fix BindingRestElement to allow nested BindingPatterns.
Conclusion/Resolution
- No stage change
6. Updates on Loader
(Dave Herman)
whatwg/loader, whatwg/loader/blob/master/roadmap.md
DH: introduction
BT: crass question: will we have something to implement soon?
DH: all you need to get started implementing is a basic understanding of what the really core name resolution is going to look like.
BT: and that's done?
DH: it's done enough that you could be hacking on this now. not written in the spec yet.
BT: Concerns that if spec is not written and we implement, it might be useless. Stuck in holding pattern.
DH: Should start hacking on this.
DH: we will get you stage 0 stuff written as soon as we can.
BT: (wants estimate to communicate to Edge team)
DH: We can promise name resolution drafted in the spec by the next TC39 meeting.
JM: How are relative urls resolved? Relative to what? (toplevel document? importing module url?)
DH: "referrer" used for relative, "/"?
DH: explains how "module src" will respect base url, but imports inside the module will not
MM: Loader constructor has no concept of URLs, just name resolution.
DH: Loader class is generic. Specific default Loader has to be host specific, there is a spec.
AK: Who are the experts working on the Loader spec? Anne? Dimitri (Glazkov)?
DH: Both have reached out. Let's have a meeting with those people.
AK: Dimitri is quite busy, so...
YK: I think it's important for Anne to be involved here.
DH: script type = module should have roughly defer semantics, asynchronous but ordered.
YK: before doc ready, content loaded
DH: We have to asynchronously load the deps, do we have to complete the compile phase of first script type = module, or ... execution phase as well
YK: argument for deferring evaluation at all, first is ... if you move on to second, your script didn't get a chance to configure...
... you cannot start download script type = module imports before ...
AK: this is all about what script tags do right now
YK: you need to have one block. this block is for configuring my loader, I don't want any scripts to load before this is done. Not good to block loading modules before all scripts are loaded
DH: if semantics of type=module is only that one has to precede the compilation of the other, forces you to use legacy script.
YK: there's a worse problem, path for legacy script => legacy blocking
script, or use legacy defer script, and now you have to decide order between them. Another option is loader config, that has to run before, but not other scripts
DH: a narrow case? Could have a syntax instead of reusing form?
YK: if you try to make other scripts ordered, you have to speculate whether one is a loader
DH: Another Q: Allow completed subgraphs to execute early? Hold the line on deterministic top level execution.
Issue: module system forces sequentiality
Ie.
- download
- get deps
- download
- then start compiling
Probs
- May create latency
- Could a subgraph that was completed start executing?
MM: what would be the definition of a completed subgraph that distinguishes it?
DH: for example, toplevel module main, requires foo and bar, foo requires jquery, bar requires 100 modules. While bar is downloading dependencies, foo is downloaded jquery, waiting to compile and run. In that case, schedule foo and jquery's top levels to run, more concurrent semantics, less deterministic
MM: makes sense, introduces new element. optionally breaking toplevel module execution into separate turns. multiple modules part of 1 dependency graph may be executed in separate turns
YK: middle ground: start executing subgraphs in the order they've been specified. gives you determinstic ordering
AWB: in terms of modules, there is only one syntactially type of module. two types written: script type modules, root of execution, import other things. OTOH, module-like modules have exports and imports and logically are doing useful work if people import them. I thought that module-like module would never be initialized if someone didn't import it. In theory, a script tag that names a module-like module, doesn't have to be executed unless a script-like module imports a module-like module.
DH: no interest in inline-named modules
AWB: not relevant to this discussion.
AWB: script-like module: used like a script, doesn't have exports, does have imports, written for effect
DH: either are there, b/c in a script tag, or not.
AWB: so you write a script tag, name a script-like module, that needs to execute as soon as the deps are available.
JM: has to wait for deps?
AWB: it can't run until it's script is available. Here is code I want to execute. If you name the script whose exist to export it, but nobody uses it. What does a module script tag mean, this gets to the deferred semantics. Here is the script, I want to evaluate this, even if nobody depends on it.
DH: No. Cannnot express the former in HTML. The module doesn't have name, cannot be depended on.
DH/YK: they have source but they don't have name.
AWB: Anything in a script tag is the root, execute directly. Assume ordered?
DH: confirms. Intentional order of execution. Code directly or indirectly depended on has to execute immediately. Does all that have to happen in a single event turn? Or across several? If the subgraph has completed, can execute?
MM: bottom-up execution constraint. clearly doesn't imply any type of suspended caller. If all module execution is executed in single turn, then starts and ends with empty stack. implementations can do whatever they feel like to do other jobs
DH: (explaining options between single job vs. multi-job loading. if multi-job, then decision between total ordering and partial ordering)
- single job 2.a. total ordering of modules N jobs 2.b. partial ordering of modules
YK: module imports are declarative, so gives clear dependency order, effectively a set of jobs, deterministic. Another set of jobs exist...
...modules want to initialize state, using set of promises. dependency ordering that is opaque to module execution order, benefit of that is we can have synchronous 1-shot path through module execution...
YK: problem with 2.a...
JM: we've used 2.a. for a long time and it has worked well
YK: ... other things in the dependency graph is opaque, to repair that, we need toplevel await
AWB: my concern with 2a. only comes up with circular module deps, a set of dependent modules isn't fully initialized until you circle around, each module has been given a chance to initialize and execute through entire body. If you start doing other jobs, somewhere along that path, are there going to be potential observable....
DH: difference between observable and likely. We shouldn't care about reflectively being able to observe that things are complete. Ignoring the reflective stuff, just declarative, initializing these in dep order, outside of cycles you can't have a problem. Even within a cycle, early reference to something that hasn't executed yet, but that can happen synchronously too.
YK: there is a toplevel cycle problem already
MM: I think there is an adjustment to 2a and 2b to avoid cycle problem. adjustment is strongly-connected cycle is atomic, if we allow interleavings, only between strongly connected cycles.
AWB: then you'd have to identify these
...
discussion about N job module loading -> toplevel await
DH: describing the problem with toplevel await and node.js ... people want to use synchronous functions in module initialization, but this forks functionality between async/sync variants... ... toplevel await gives you a way to prevent module use before initialization. in node.js currently people often just race between initialization and use.
MM: question: node modules is loaded via require? If someone calls require in a later turn, the module is loaded later. [ everyone confirms ] so toplevel modules can already be run over multiple turns? [ confirms ]
YK: their concern is that introducing await for require will change the behavior of require in a confusing way
JM: But it's backward compatibile and not a breaking change, right?
no
MM: why isn't toplevel await something that can be written already?
YK: you can desugar that already, but they still don't want it
AK: They just don't want the feature.
SP: Bad experience when tried to do this the first time.
confirmed
YK: they say, once you start using async, everything leaks. And that's true
DH: sounds bad, but there is a reasonable solution. allow toplevel await, asynchronous loader spec, and node won't use it. any modules that have toplevel await will be incompatible with node
YK: syntax errors, or run to first await
and done
DH: they can do whatever they want here, if it becomes popular on the web, maybe that will change their opinion
MM: If toplevel await is equivalent to something users can write anyway...
YK: I just realized that it is plausible to do what async function does, if await appears at toplevel the export is a promise
DH: Yes.
- require is zalgo-ish
- may block severely
MM: that to me, disqualifies it. But we're not talking about require, but import
DH: all node packages expect to start with toplevel synchronous main and require
MM: would expect to interface between two systems, what you obtain is a require immediately returns
DH: two things that you want for evolutionary path: require an es6 module that awaits, thing you get back is a promise rather than module. Other part is an alternative entry point for node: execution semantics at toplevel is es6 loader program, everything runs through async pipeline, with imports instead of require
YK: await, import at toplevel could trigger that
DH: maybe inferred rather than opt-in
MM: i don't see how this forces you to require as suspension point for caller
YK: browser does not want require that sometimes returns value, sometimes promise. legacy purposes, require returns value.
MM: require has to return what the required module exports
DH: could say: all ES6 modules provide a promise
- Agreement on 2A semantics
2A: Modules execute in the order that they appear textually (same order as ES6 semantics), but may run across multiple turns.
Moving on.
DH: Need stage 0 for module metadata
gist.github.com/dherman/c35e968991b67ae98423
MM: there's a defacto spec in JS: source maps. very specific about what type of information is mappable. I think this corresponds to filename/dirname...
( discussion of import.context ) EF: why import and not export? (module would be better, but it isn't a keyword)
DH: import.context.lineno, callno?
MM: my point is: if template strings actually created a sourcemap on the template object, as part of the extended definition, you'd have all the information by that mechanism, including where the individual thing in the source ...
DH: the competition here is __filename, __dirname, etc. import.context ergonomics is pretty close, are you talking about something worse?
MM: there is an overlap of functionality with sourcemaps and template strings -- we should coordinate these.
( question about this exposing a new execution context for module system )
DH: this was always the case with modules.
MM: can't you just create an error, throw and catch it to get the information for the filename, line, etc. how is the info on import.context different?
CP: just one concern about import.context compared to import local from this module;
proposal, we need a new way/channel to ask loader for such as
information, before it was just a synthetic module that relying on the
loader semantics to do the bindings.
extended discussion about what information would be stored on import.context -- is it source name, dir name? or is this too node-specific?
Dynamic Relative Loading
- Dynamically load a relative module when it's only needed rarely:
// lib/index.js
configButton.onclick = async function() {
// corresponds to: `import { readFile, writeFile } from 'fs';`
let { readFile, writeFile } = await import.named('fs');
// corresponds to: `import config from './config.js';`
let config = await import('./config.js');
// ...
};
DH: Dynamic scope tricks you into thinking that you can abstract normally (say, by moving outside), but you can't
Need: static syntax to communicate information so that we can dfkjnsdkfbjv ;skdfjblskdjfnbvlksdjfbsdfv
discussion about import(...) and import.named(...) being meta operators
AWB: make it not an operator: meta property whose value is a closure
MM: could be closed over the data from import.context
discussion about ambiguity of syntax
DH: syntax needs work, not complete/final
MS: because dynamic, needs a new API. Don't like the properties on keywords.
DH: re-explains everything that lead to current design
Discussion re: import(...
DH: "out of band" in a subexpression and need additional data
AK: Assumed import dynamically, methods on a loader instance?
DH: Missing ability to do relative dynamic loading, needs context otherwise need to write information in your code about where the file lives.
AK: need some syntax that says "where am i?"
DH: we want the smallest number of constructs, there is benefit to users for this. However, inband vs. outband is real ergonomics issue. Ability to correspond syntatic forms between declarative and imperative forms has value
DH: Moving on. Need global APIs here, reflective API for dynically creating a module instance. I want Reflect.Module (or something living under Reflect), DD wants...
tl;dr: Spec defines a module namespace exotic object, need a way to create these. Custom loaders need to make these.
AWB: can other modules import those? [ others say yes]
DH: reflective vs. source text module objects...
- Module Records, not Module Namespace Exotic Object
- need something for that
- needs to go somewhere
- DD says WHATWG shouldn't be monkey patching onto Reflect object
- Loader spec lives on a bridge
- Not specific to WhatWG
- Belongs in Reflect
Agreement
MM: talking about System
DH: This will block stages of Loader.
AK/DH: Milestone 0, not Stage 0
DH: milestone 0 doesn't depend on this syntax, but milestone 1 does, and we don't want to hold that up, so people can start building the ecosystem
Conclusion/Resolution
- Stage 0 granted for dynamic relative loading
- Module Record thing goes in Reflect, full-stop. ("Reflect.Module", perhaps)
Reflect.Loader
,Reflect.Module
Not sure if anything like this exists yet, but for a better reading experience, here's a quick snippet to collapse all sections and make them expandable on click.
Much easier to navigate through this way.
gist.github.com/kangax/84c88034af043a46c0e3#file-readability-js
Can be run in console when looking at "compiled" markdown; such as on that same gist page.
Since no one else has posted notes, I will. This is not meant to be a complete summary; it's just the notable items that I happened to write down. These are not minutes of the meeting.
The current plan is to submit ES3.1 to a vote at the June 2009 ECMA General Assembly. The successor is ES-Harmony and will come later. A suggestion was made to insert another version in between ES3.1 and ES-Harmony which would be essentially equivalent to ES3.1 in behavior but written in a more formal spec language. This would not have much of a benefit to the users of the standard and the suggestion was rescinded.
We're still agreed that we will want two independent implementations of ES3.1 before submitting the standard to a vote. Mozilla will likely have one. MarkM will ask the Chrome guys about implementing it.
Test suite: The Mozilla test suite is used by Mozilla, V8, and others. It's MPL-licensed which Microsoft doesn't like. Mozilla will look into what it will take to relicensing it to an MIT-style license. One approach to avert political problems would be for some or all of the test suite to become an ECMA document to make it easier for Microsoft can read it.
We pretty much agree on the ES3.1 features, but the writeup in the document is still buggy and needs work, particularly chapters 8 and 10.
In strict mode there is a strong desire to prohibit uses of <F.caller> and <F.arguments> where <F> is a Function object of a function that has an active stack frame, as well as uses of <arguments.caller>. It creates an interesting dilemma in that these features are not in the ES3 spec, so how does one remove something that doesn't officially exist? One possibility is to state that implementations don't do this, which was Waldemar's preferred position, but the committee thought that this was not strong enough because code that tried to access these would read <undefined> instead of throwing an exception. We reached consensus on requiring implementations to define on strict functions <F.caller>, <F.arguments>, and <arguments.caller> with non-deletable, non-writable properties that have getters that throw exceptions when read. An open question is what happens if one uses the reflection API to extract the exception-throwing getters: are they all == to each other?
Is the Array <length> property a getter when viewed via the reflection API? If it is, are the different getters == to each other? Not clear at this point. Allen doesn't care, MarkM wants it fully specified, Waldemar wants closure joining back iff it is unspecified and the committee was sympathetic to that.
Minor Date language cleanup issues. Wording changes. Agreed to the <now> method. Agreed to require that methods that return the current time return non-decreasing values under normal operation (i.e. if someone doesn't manually change the machine clock).
We briefly reopened the discussion of whether <const> is in the language. The resolution was that it is in (unless of course nobody does the work to include it in the spec). We agreed that <const> should be written at the point of initialization rather than have write-once semantics; the latter could be subverted as in:
{ ... const x=2; function f() { return x; } function g() { // possibly x = 5; } } If g() runs first, then f() might return something other than 2!
An open issue is whether const violations should be compile or run-time errors. Clearly some of them are undecidable and can only be reported at run-time, but what about the clear-cut cases?
{ a = x; const x = 2; }
<Object.clone> was proposed. Waldemar shot it down due to various technical deficiencies and the committee agreed.
A syntactic rule was proposed to disallow any statement following a <return>, <break>, <continue>, or <throw> statement in order to cut down on errors. Waldemar pointed out that this would fire for non-dead code such as:
if (x) ... else return z; foo();
where foo() isn't dead at all. Other legitimate places to have statements are after a <break> in a <switch>. There wasn't much desire to change its semantics so that it would look for dead code (that would require specifying whether ... can proceed or not), so it was dropped.
We were wondering why ES4 had a version of <eval> that did not capture the enclosing scope. This does not appear to be permitted by ES3, which requires that <eval> either evaluate in the current scope or throw an EvalError.
The contained <statement> inside a labeled statement should be a <substatement> in the grammar.
In strict mode, a variable reference inside a nested scope must not evaluate to a Reference whose base is null rather than a Reference to a property of the global object. The latter would prohibit legitimate references to Window.foo inside a function.
Discussion about syntax of <use strict> directive. Most favored option is the string literal "use strict" or "use strict,xxxxx" where xxxxx are arbitrary characters at the beginning of the program.
The semantics of Function.bind were essentially broken and need to be rewritten. We also changed its semantics so that bind works exactly as though the additional arguments were supplied at the point of the call, which means that you can use bound functions with both function calls and the <new> operator and have them behave as expected.
Dropped efforts to reflect the names of parameters. Many of the ones in the ES3.1 spec have names that are convenient for the algorithm writeups but don't make sense otherwise: <Object.defineProperty> would have the parameters ["O", "P", "Attributes"]. This also wouldn't extend to the rest parameters that we'll introduce in ES-Harmony, so it's premature to standardize it now.
11.9.3: Step 15 on is dead code. Step 19 is dead code.
15.13.1.1: What's a 34 digit integer? For example, 7 is not a 34 digit integer.
15.12.1: What does it mean to parse 1?
15.12.2: What does it mean to contain cycles? What if the cycle is filtered out? What if the object modifies itself as it's being read (due to getters or side effects from toJSON routines)?
DECIMAL AND IEEE 754-2008
Mike Cowlishaw gave a presentation about Decimal and the IEEE 754-2008 standard which replaces IEEE 754-1985. New things in there (most of which apply to both binary and decimal floating-point values) include:
Most of the above are mandatory. Making things mandatory even where they don't necessarily apply seems to be the culture of the IEEE 754 committee.
Deleted from IEEE 754:
Mike Cowlishaw published a decFloats C package under an MIT-style open source license: speleotrove.com/decimal
Mike Cowlishaw's preferred semantics of Decimal keeps track of trailing zeroes in some ways that several in the committee consider bizarre:
1.00 + 1 --> 2.00 1e12 - 1e12 --> 0e12 5 + 5 --> 10 1/.1 --> 1e1 1/3 - 1/3 --> 0e-34
The values 10 and 1e1 are operationally different. This causes problems for array lookups where the index is converted to a string: a[1e4] and a[100*100] would refer to different elements. IBM gave in on this point and we all agreed to not track trailing zeros (i.e. distinguish among cohort members) at all in ECMAScript.
The "m" decimal literal suffix is in for ES3.1. It's the only non-downwards-compatible-with-existing-browsers syntax change in that spec. The spec needs to be updated to include it.
We discussed and agreed that four of the Math routines (min, max, abs, round) should work on both binary and decimal floats in the natural way. The other ones can coerce to and return only binary floats.
Sam is implementing Decimal in V8 (and Mozilla?).
Waldemar reviewed the current writeup of Decimal and struggled to understand it. We now agree on what the behavior should be, but pretty much every section of the writeup needs to be corrected or rewritten. Sam will do the work and Waldemar will review.
ES-HARMONY
We spent most of Friday on ES-Harmony, with a long discussion about the role of types. We agreed that having types be symbols or badges ("interfaces") that some classes can export and can be used to annotate variables and parameters would be a good direction to follow. We got at least tentative agreement on:
UPCOMING MEETINGS
(I assume that the first day of each meeting is for the secure scripting subgroup.)
Nov 18-20, Royal Kona Resort, Hawaii (heh, in today's economy the hotels there are cheaper than in Redmond) Jan 27-29, Google Mountain View Mar 24-26, Washington DC
Waldemar