Re: Debuggers and async/await should work together better: I have testcases.

2017-12-01 Thread Jason Orendorff
Alex,

I asked around, and our debugger folks say that stepping over await should
work in current shipping Firefox. Haven't checked out your test case yet,
but someone here will.

In any case, please do report a bug! Instead of Bugzilla, report it here:
  https://github.com/devtools-html/debugger.html/issues

If you don't mind Slack, you can hop on this one (and ping @yulia or
@jorendorff) to talk more about async debugging:
  https://devtools-html.slack.com/
  https://devtools-html-slack.herokuapp.com/  <-- to sign up

-j



On Fri, Dec 1, 2017 at 3:27 AM, Alex Vincent  wrote:

> A few minutes ago, I released version 0.8.2 of the es7-membrane project.
> [1]  I've been using Mozilla Firefox primarily to debug it as I go, and I
> find the built-in JavaScript debugger has a few quirks when asynchronous
> functions come into the mix...
>
> Most notably, when I step over an "await" statement, the debugger treats
> it as if I'm exiting the function altogether.
>
> Also, exceptions thrown within the async functions after an await tend not
> to show up when I'm stepping through the code.
>
> I know I should be filing this in Bugzilla, and I will this weekend... I'm
> posting this here for all JS engine & debugging tools teams, as a
> heads-up:  when it comes to async functions, the step-through-code user
> experience is subpar.
>
> As for tests people can step through to see what I'm talking about:  see
> [1] for the source under docs/gui/tests.  To run the tests, type |npm run
> gui-tests|.  I use Karma to implement the tests. The karma.conf.js file in
> the root directory has a "singleRun" setting that developers can change to
> false for debugging purposes (attaching breakpoints to a test, for example).
>
> If it's on a weekend, I can be available to demonstrate what I'm referring
> to, or to show people how to reproduce these behaviors.
>
> Thanks!
>
>
>
> Alex Vincent
> Hayward, CA, U.S.A.
>
> [1] https://github.com/ajvincent/es7-membrane
>
>
> --
> "The first step in confirming there is a bug in someone else's work is
> confirming there are no bugs in your own."
> -- Alexander J. Vincent, June 30, 2001
>
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Re: Toplevel 'let' binding can be left permanently uninitialized after an error

2017-11-29 Thread Jason Orendorff
On Wed, Nov 29, 2017 at 4:13 AM, pacer...@gmail.com 
wrote:

> Re "..in subscope" and "..relevant"; As repl's can be fixed by
> that---all snippets treated as curlybraced.
>

Hi everyone.

For those of you who weren't on this list three years ago, here's the rest
of the thread:
  https://esdiscuss.org/topic/toplevel-let-binding-can-be-left-permanently-
uninitialized-after-an-error

Ever-deeper-nested-blocks is one possible behavior for a repl, and it does
solve this problem by allowing you to shadow your broken `let x` with a
fresh one, after a typo. It has some other drawbacks, though; see Dave
Herman's post here:
  https://esdiscuss.org/topic/toplevel-let-binding-can-be-left-permanently-
uninitialized-after-an-error#content-12

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Help wanted: Membrane proxies + Object.freeze() == paradox

2017-05-23 Thread Jason Orendorff
I think the most straightforward thing is something like this:

https://gist.github.com/jorendorff/85d74ef7dce0118664535f84d57d6788

To restate the obvious, this is a minimal fix for your minimized test case,
not production code you can take and use. You'd need to implement all the
rest of the handler methods.


On Tue, May 23, 2017 at 11:01 AM, Alex Vincent  wrote:

> Yes, I've been using the shadow technique in my es7-membrane project for
> quite some time.  I was trying to minimize a fairly complex test case here.
>
> Obviously, I can reintroduce shadow targets into the minimal testcase, but
> then I need to figure out how to make the prototype object I'm trying to
> get consistent again... still working through the details of that in my
> head.
>
> On Tue, May 23, 2017 at 8:50 AM, Mark S. Miller 
> wrote:
>
>> Take a look at Tom's explanation of the "shadow target" technique at
>> https://research.google.com/pubs/pub40736.html
>> section 4.3
>>
>> --
>> Cheers,
>> --MarkM
>>
>
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Help wanted: Membrane proxies + Object.freeze() == paradox

2017-05-23 Thread Jason Orendorff
On Tue, May 23, 2017 at 2:44 AM, Alex Vincent  wrote:

> Full details are at https://github.com/ajvincent/es7-membrane/issues/79 ,
> which is where I'm hoping to find a solution.
>

To fix this, you must create a third object for each dry proxy, to serve as
its [[ProxyTarget]]. There's no way around it. And you're right, it's not
easy; you have to implement all of the handler methods, because none of the
defaults do the right thing anymore.

All the target checks in the design were intended to (a) allow proxies to
claim to have immutable parts; and yet (b) maintain the language's
invariants that immutable parts cannot change, even for proxies.
[[ProxyTarget]] looks like an ease-of-use feature, but it's not; it's
really in support of (a) and (b), and as you've found, it actually makes
some things harder.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ES RegExp parser

2017-03-20 Thread Jason Orendorff
> `{type: '+', expression: re}`

Sorry, I guess the real expression would be something more like:

{
  type: 'Repetition',
  expression: re,
  quantifier: {
type: '+',
greedy: true
  }
}

The point stands.

-j


On Mon, Mar 20, 2017 at 10:36 AM, Jason Orendorff  wrote:

> The second approach, hands down.
>
> 1. With the first approach, you're setting up a situation where it's very
> easy to write buggy analysis code: if you forget to check `re.quantifier`
> anywhere, your code will run, but you have a bug. Much easier to only have
> to check `re.type`.
>
> 2. If you have a regexp `re` and you want to programmatically build a
> regexp that matches one or more repetitions of it, it's much easier to
> write `{type: '+', expression: re}` than to have to examine `re.quantifier`
> and (if it's already present) figure out how to modify it.
>
> 3. With the first approach, you don't have to represent `(?:)` group in
> the AST at all (rather like how Esprima drops redundant parentheses). With
> the latter, I think you have to, because it's possible for a single regexp
> "node" to have multiple quantifiers: `/(?:\d{4,6})?/`
>
> To me this is not even a question.
>
> -j
>
>
>
> On Sun, Mar 19, 2017 at 4:52 PM, Dmitry Soshnikov <
> dmitry.soshni...@gmail.com> wrote:
>
>> I started working on a ECMAScript regular expressions parser[1] with an
>> AST format similar to Mozilla's Parser API. This might later be extended to
>> support more powerful constructs, like lookbehind assertions, multiline
>> regexes, groups naming, comments, etc.
>>
>> And while this is mostly an FYI post (probably someone will find it
>> useful for regexes analysis in source transformation tools, or source code
>> editors), I'd appreciate any feedback on the specification of AST nodes
>> (currently totally made up by myself).
>>
>> E.g. when we have a quantifier from ES spec for RegExp grammar, it
>> doesn't tell anything (and shouldn't of course) which AST node this
>> quantifier node produces.
>>
>> This leaves open questions like "whether a quantifier should be a part of
>> the parsed expression, or should it vice-versa be a main node itself, and
>> have the expression as a sub-node?":
>>
>> In other words, which format is more appropriate (taking into account AST
>> traversal tools in order to implement NFA/DFA engine for it later):
>>
>> ```
>> /a+?/
>> ```
>>
>> Char is main, quantifier is a sub-node:
>>
>> ```
>> {
>>   type: 'Char',
>>   value: 'a',
>>   quantifier: {
>> type: '+',
>> greedy: false,
>>   }
>> }
>> ```
>>
>> The quantifier is main (creating `Repetition` AST node), char is the
>> `expression` sub-node:
>>
>>
>> ```
>> {
>>   type: 'Repetition',
>>   expression: {
>> type: 'Char',
>> value: 'a'
>>   },
>>   quantifier: {
>> type: '+',
>> greedy: false,
>>   }
>> }
>> ```
>>
>> Currently I chose the second approach (with `Repetition` node) as more
>> practical when building an AST traversal -- it may have `onRepetition`
>> generic handler, and call `onChar` internally for its `expression`, instead
>> of making `onChar` (or any other node) to check, and handle its
>> `quantifier`, and do a repeat.
>>
>> Anyways, if you have any thought or feedback on AST nodes format, please
>> feel free to contact me.
>>
>> Dmitry
>>
>>  [1] https://www.npmjs.com/package/regexp-tree
>>
>> ___
>> es-discuss mailing list
>> es-discuss@mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>>
>>
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ES RegExp parser

2017-03-20 Thread Jason Orendorff
The second approach, hands down.

1. With the first approach, you're setting up a situation where it's very
easy to write buggy analysis code: if you forget to check `re.quantifier`
anywhere, your code will run, but you have a bug. Much easier to only have
to check `re.type`.

2. If you have a regexp `re` and you want to programmatically build a
regexp that matches one or more repetitions of it, it's much easier to
write `{type: '+', expression: re}` than to have to examine `re.quantifier`
and (if it's already present) figure out how to modify it.

3. With the first approach, you don't have to represent `(?:)` group in the
AST at all (rather like how Esprima drops redundant parentheses). With the
latter, I think you have to, because it's possible for a single regexp
"node" to have multiple quantifiers: `/(?:\d{4,6})?/`

To me this is not even a question.

-j



On Sun, Mar 19, 2017 at 4:52 PM, Dmitry Soshnikov <
dmitry.soshni...@gmail.com> wrote:

> I started working on a ECMAScript regular expressions parser[1] with an
> AST format similar to Mozilla's Parser API. This might later be extended to
> support more powerful constructs, like lookbehind assertions, multiline
> regexes, groups naming, comments, etc.
>
> And while this is mostly an FYI post (probably someone will find it useful
> for regexes analysis in source transformation tools, or source code
> editors), I'd appreciate any feedback on the specification of AST nodes
> (currently totally made up by myself).
>
> E.g. when we have a quantifier from ES spec for RegExp grammar, it doesn't
> tell anything (and shouldn't of course) which AST node this quantifier node
> produces.
>
> This leaves open questions like "whether a quantifier should be a part of
> the parsed expression, or should it vice-versa be a main node itself, and
> have the expression as a sub-node?":
>
> In other words, which format is more appropriate (taking into account AST
> traversal tools in order to implement NFA/DFA engine for it later):
>
> ```
> /a+?/
> ```
>
> Char is main, quantifier is a sub-node:
>
> ```
> {
>   type: 'Char',
>   value: 'a',
>   quantifier: {
> type: '+',
> greedy: false,
>   }
> }
> ```
>
> The quantifier is main (creating `Repetition` AST node), char is the
> `expression` sub-node:
>
>
> ```
> {
>   type: 'Repetition',
>   expression: {
> type: 'Char',
> value: 'a'
>   },
>   quantifier: {
> type: '+',
> greedy: false,
>   }
> }
> ```
>
> Currently I chose the second approach (with `Repetition` node) as more
> practical when building an AST traversal -- it may have `onRepetition`
> generic handler, and call `onChar` internally for its `expression`, instead
> of making `onChar` (or any other node) to check, and handle its
> `quantifier`, and do a repeat.
>
> Anyways, if you have any thought or feedback on AST nodes format, please
> feel free to contact me.
>
> Dmitry
>
>  [1] https://www.npmjs.com/package/regexp-tree
>
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Array tail destructuring

2016-10-04 Thread Jason Orendorff
On Tue, Oct 4, 2016 at 7:12 AM, Cyril Auburtin 
wrote:

> I didn't understand everything discussed above, but to me, the only
> asymmetry between head and tail destructuring is for infinite iterators:
>
> `var [x] = neverEndingIterator` vs `var [...a, x] = neverEndingIterator //
> fails`
>

Read the post just before yours. Caitlin pointed out another difference.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Re: Proposal: use "One More Point" to handle async functions

2016-09-28 Thread Jason Orendorff
On Tue, Sep 27, 2016 at 10:23 AM, Li Xiaolong <898310...@outlook.com> wrote:

> 3: the async function calls identically with sync functions, makes it hard
> to check out if the function is async without jumping to the definition.
> But OMP can easily be recognized.
>

Usually, async calls will be marked with `await`, which to me seems
somewhat easier to spot.

On the other hand it's true that the function call itself is just a
function call. One nice consequence is that you can call an async function
without immediately blocking and waiting for it to finish. For example,

let p1 = start_download();// start two things at once
let p2 = start_query();
let file = await p1;// wait for results
let result = await p2;

Is that possible with OMP syntax?

In your proposal, what would happen if you called an OMP async function
(one that ends with a `.return`) using `plain.method()` call syntax? What
if you call a sync function or method using OMP call syntax?

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Extended dot notation (pick notation) proposal

2016-09-23 Thread Jason Orendorff
On Thu, Sep 22, 2016 at 1:14 PM, Bob Myers  wrote:

> Sorry for using ALL CAPS. I will not do that any more. You're right: this
> proposal DOES (oops, I meant *does*) increase the size of the spec. Is that
> the new criteria, that no proposal may increase the size of the spec?
>

This conversation has been kind of strange for me.

JO: new cognitive burden has to be justified
BM: this isn't new cognitive burden, it's removing cognitive burden
JO: that makes no sense
BM: are you saying we need to freeze js forever?

...Well, no. Obviously.

But new cognitive burden has to be justified.

TC39 didn't accept array comprehensions. They were generally well-liked,
but they didn't introduce any new capabilities and it was decided they
didn't pull their weight. That's the bar any new proposal has to get over.

Then we might as well freeze JS right now.
>
> The "extra words" you refer to are nothing more this:
>
> > You can also put deconstructing syntax following a dot after an object.
> This will result in a new object with properties determined by the
> deconstructor.
>

I think your gist is more a serious attempt at a reasonable explanation.
Don't trivialize it -- people who *don't* get the memo will have to search
StackOverflow for `.{`.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Extended dot notation (pick notation) proposal

2016-09-23 Thread Jason Orendorff
On Thu, Sep 22, 2016 at 1:14 PM, Bob Myers  wrote:

> In the proposed "pick/destructure into an object" syntax, I would use
> identical destructuring syntax
>
> ```
> obj.{foo: {bar: {qux}}}
> ```
>
> which would turn into `{qux: obj.foo.bar.qux}`.
>
> We are simply using identical destructuring syntax to destructure into an
> object instead of a variable.
>

I'm sorry, Bob, the link in your original post in this thread has a link to
the proposal; it's perfectly clear on this, and I should have gone back to
it.

OK, I  think I understand the proposal now. A few comments:

1.  The gist says:

> The syntax of the *Assignment Pattern* is identical.

I don't think this is right; I think you want all the right-hand sides
of all the properties in the tree to match PropertyName. In
AssignmentPattern, those can be any LeftHandSideExpression:

{text: f().q[13].name} = obj;

But that wouldn't make sense in pick notation:

obj.{text: f().q[13].name}  // ???

2.  I mentioned scoping earlier. What I mean is, in expressions like

obj.{[p]: p}

the two identifiers `p` mean different things (the first `p` is a
variable name, the second `p` a property name), which is new and subtle.
The same thing happens in `obj.{p = p}`, except the other way round.
Destructuring does just a touch of this in the shorthand case, but I never
found that confusing. This is.

3.  I wonder if this can be made more symmetrical -- as it stands, it
allows you to flatten a complex object:

// from a tree of 3 objects to one
let rect = corners.{
p0: {x: left, y: top},
p1: {x: right, y: bottom}
};

The reverse would be to add structure to a flat object. There's no way
to do that, right?

// turn the 1 object back into a tree of 3?
let corners = rect.{ ??? };

Likewise, it seems you can turn an array into a plain object, but not
the other way around?

let point = coords.[x, y];   // {x: coords[0], y: coords[1]}
let coords = point.{???};   // [point.x, point.y]

Honestly even the examples that do work seem ugly to me. I think pretty
much all the value in the proposal is in the simplest case,
`obj.{identifier, ...}`.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Extended dot notation (pick notation) proposal

2016-09-22 Thread Jason Orendorff
On Wed, Sep 21, 2016 at 3:39 PM, Bob Myers  wrote:

> > Some people on a web site are curious to know if they can reduce 2
> lines of JS code to 1 line
>
> Right, some people wanted to reduce 2 lines of JS code [...]
>

That is not historically how JS got destructuring.


> But it's a tiny bit more than mere syntactic sugar. Writing `obj.{p1, p2}`
> is just sugar for writing `{p1: obj.p1, p2: obj.p2}`. But I can also write
> `obj.{p1: q1, p2 = 100}` [...]
>

In destructuring, `{p1: q1} = obj` means `q1 = obj.p1`. So, do you mean for
this to say `{q1: obj.p1}`? Or perhaps `{p1: obj.q1}`; but then why is it
inconsistent with destructuring?

You mention deep picking, but I haven't seen what that would actually look
like. (Destructuring is not great for deep picking, so I'm not sure how the
new syntax requires negative effort to learn because it's all existing
parts, and yet it will also solve this problem.)

You mention computed property names. How does that work? In `obj.{[p1]}`,
does `p1` mean the variable `p1` or the property `obj.p1`? Assuming the
former, is there anyplace else in the language where adding `[]` affects
what an identifier refers to (i.e. scoping)?

How is all of this not a ton of new things for JS developers to learn?

I totally agree with Matthew Robb's comment in a separate response that
> this proposal is not imposing a new cognitive burden; it's REMOVING the
> cognitive burden of wondering why our handy deconstructing syntax cannot be
> used to pick properties into objects.
>

This argument is hopeless, and I find it a little weird because a much
stronger argument is available to you. You can just say, yes, there is some
minor complexity cost here, but it's definitely worth it because of very
common use cases X, Y, and Z.

The argument you've chosen instead won't go. None of these proposals could
actually be standardized in a way that reduces the total size of the spec.
They won't make "JavaScript: The Definitive Guide" a shorter book, either.
They all require extra words to explain, whether to implementors or to JS
devs. New syntax does not make things simpler, in the same way that up is
not down and black is not white.

Cognitive burden is a real phenomenon, where people have to spend time
puzzling out unfamiliar ideas and it's pure overhead for them vs. their
actual goal. You can't just turn the meaning of the term upside down and be
done. It actually means something.

(Also, both you and Matthew seem to think an unlikely point can be carried
with the help of allcaps. Admittedly they are very judiciously applied
allcaps, relative to the internet at large, but I still don't think this
ever works!)

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Extended dot notation (pick notation) proposal

2016-09-22 Thread Jason Orendorff
On Wed, Sep 21, 2016 at 12:33 PM, Matthew Robb 
wrote:

>
> On Wed, Sep 21, 2016 at 10:40 AM, Jason Orendorff <
> jason.orendo...@gmail.com> wrote:
>
>> Since all new syntax imposes some mental load on all language users, the
>> answer should be no unless the benefit is really dramatic, which I don't
>> think it is here.
>
>
> For the most part I can completely agree with the sentiment that all new
> syntax imposes some mental load on all language users but my question is
> how this applies when syntax RESTRICTIONS that seem counter-intuitive
> impose their OWN mental load.
>

Neither proposal can reasonably be seen as merely lifting unnecessary
restrictions. Emphasizing some words doesn't make this seem like less of a
stretch, to me.

I think the inspiration of this thread and the few before it comes from the
> fact that destructuring syntax and object literal shorthand syntax seem to
> share in a root syntax yet the two features are incompatible which makes
> the mental load of the restrictions more obvious.
>

If it were a matter of lifting restrictions, this would be a very different
conversation. I get that to you, that's all it is. But I have trouble
seeing how that is true in any objective sense. In the spec, this will look
like a bunch of new text and syntactic productions. And nobody is going to
look at `{{x, y} = obj}` and recover the meaning from previously learned
principles of the language. It's an extra thing to learn.

And of course it comes with its own "restrictions", as you put it; i.e. it
cannot do everything either. Now people will wonder if they can put some of
an object's properties in one new object and dump all the rest in another.
Or if there's a shorthand for

let obj = complicated_expression();
let result = {start: {{x, y}=obj}, size: {{w, h}=obj}};

that eliminates the temporary `obj`. And on and on forever.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Extended dot notation (pick notation) proposal

2016-09-21 Thread Jason Orendorff
On Tue, Sep 20, 2016 at 2:38 PM, Bob Myers  wrote:

> People in the real world continue to wonder why they can't
> pick/destructure from objects into objects, instead of just variables.
>
> http://stackoverflow.com/questions/39602360/es6-
> destructuring-reassignment-of-object?noredirect=1#39602360
>
> This is actually the second such question on SO in the last week.
>

Well, this not as weighty a consideration as you might think.

Some people on a web site are curious to know if they can reduce 2 lines of
JS code to 1 line. Their shared curiosity may be a coincidence; or it may
be the language's fault. Presume the latter. It doesn't follow that the
answer should be yes. Since all new syntax imposes some mental load on all
language users, the answer should be no unless the benefit is really
dramatic, which I don't think it is here.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Symbol.hasInstance and [[Get]] vs [[GetOwnProperty]]

2016-08-16 Thread Jason Orendorff
On Mon, Aug 15, 2016 at 8:45 PM, /#!/JoePea  wrote:

> It seems like using [[Get]] for looking up `@@hasInstance` can be
> confusing and requires devs to write extra code.
>

I think the emotionally loaded words in this post ("fail", "ugly",
"fragile", "break") are unhelpful. You have to make your point some other
way.

The `c instanceof B` check (arguably unintuitively) fails.
>

It doesn't "fail". B inherits behavior from its base class A. That's the
whole point of subclassing.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: How to solve this basic ES6-module circular dependency problem?

2016-08-09 Thread Jason Orendorff
On Tue, Aug 9, 2016 at 3:03 PM, /#!/JoePea  wrote:

> Why is it that the body of module C is not evaluated before the bodies of
> modules A and B?
>

The module system *does* execute all a module's dependencies before
executing that module, *except* in cases like this where there are cycles
in the dependency graph and that requirement is therefore impossible to
satisfy for all modules simultaneously.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Static `super` may cause a unwanted "memory leak".

2016-08-02 Thread Jason Orendorff
On Tue, Aug 2, 2016 at 3:09 PM, Bergi  wrote:

> Why would `tmp` be stored as the [[HomeObject]] when the function doesn't
> use `super`? In that case a [[HomeObject]] is not needed at all.
>

To clarify this: of course the JS engine knows whether the code uses
`super` or not and can decide to retain the [[HomeObject]] only when
there's some danger of its actually being needed. But do implementations
actually do this optimization in practice?

SpiderMonkey has a findPath() primitive that searches the GC heap for paths
from one object to another, handy for answering questions like this one:

js> function SomeFactory(name) {
  let tmp = {
[name]() { /* this doesn't use `super` */ }
  }
  return findPath(tmp[name], tmp);
}
js> SomeFactory("foo") === undefined
true

That is, there is no GC-path from the method back to the object; apparently
[[HomeObject]] is not being retained. What if we change the method to use
`super`?

js> function SomeFactory2(name) {
  let tmp = {
[name]() { return super[name](); }
  };
  return findPath(tmp[name], tmp);
}
js> typeof SomeFactory2("foo")
"object"
js> SomeFactory2("foo").length
1

Now there is a direct GC-reference from the method to its home object, as
expected.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleDeclarationInstantiation behaviour after failure

2016-07-15 Thread Jason Orendorff
How about this: Linking happens as eagerly as possible whenever a module
arrives off the network. This means that very often we'll be linking one
module at a time. In any case, every link set will be a strongly connected
component of ready-to-link modules in the dependency graph; and therefore
if linking fails, we should discard all the modules that we were trying to
link.

When a link error or any other error happens, we immediately discard the
failed module and everything that depends on it (potentially many modules
in various states, etc.). Implementing this efficiently means tracking, for
each module, "all the stuff that's depending/waiting on me". But the loader
has to do this anyway, right?

More complete description of this proposal, in case that's not clear:
https://gist.github.com/jorendorff/fc5bad969137402caa10bb3570b3f202

On Fri, Jul 15, 2016 at 9:32 AM, Jon Coppeard  wrote:

> Another similar approach that also uses the committed state might be to
> parse all modules as they become available and discard any uncommitted
> dependencies on instantiation error.


What I'm proposing doesn't discard in-flight dependencies, but allows them
to finish loading.

However that still has the disadvantage that too many modules are thrown
> away on error.


Agreed.


> I guess what I'd really like is some support for this simultaneous
> loading in ES.


At the least, I think it makes sense to mark Module Records for modules
that failed to parse or link as permanently bad, and assert as we go that
we are only ever working on good Module Records. It would be a nice
clarification. (I suspect TC39 would accept patches for this, even though
the status quo seems correct in every way -- it's just a matter of someone
doing the work.)

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleDeclarationInstantiation behaviour after failure

2016-07-12 Thread Jason Orendorff
On Thu, Jul 7, 2016 at 4:33 PM, Allen Wirfs-Brock 
wrote:

> The spec. Only generates errors and does try to define error recovery.
> That's up to the implementation. But I would expect implementations to
> discard any module records it created during a linking phase that throws
> errors.


That makes sense. Thanks.

This explains why I didn't understand it. Originally we specified a loader
too, and the loader's behavior on error was a little different from this.
Not necessarily better, though.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ModuleDeclarationInstantiation behaviour after failure

2016-07-07 Thread Jason Orendorff
On Thu, Jul 7, 2016 at 12:09 PM, Caridy Patiño  wrote:

> Moving step 7 to the end is not an option since the primary use of that
> step is to support circular references.
>

Not sure this is helpful, but back when I was working with Dave on this
stuff, it was supposed to work something like this:

* The loader determines when a set of new modules is ready to link. This
only happens after resolving all requested modules for the whole set.

* Check that all requested modules actually have the export bindings we
require of them. If not, it's an error.

* Linking. We create module Environments and all their bindings, including
import bindings. Observably, this is an atomic step and it can't fail. We
already checked for all possible link errors.

* Next, we evaluate module bodies, etc.

So in our design, if code ran in a module environment, that environment was
fully linked. It looks like ModuleDeclarationInstantiation does not have
this guarantee. If true, that's a serious bug.

> As for recovering from errors, this is in the realm of the loader and the
registry to prevent subsequence attempts to instantiate a source text
module record that failed already. [...]

It's fine to have an error sometimes shoot down a whole graph of modules.
The problem here is that the failed Environments can be exposed later. The
spec says you're even supposed to run code in them, right? But forging
ahead with partially-initialized data structures seems as obviously
undesirable in a spec as in running code -- that's begging for bugs -- and
it's an unreasonable implementation burden too.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Is it possible to define an array iterator that adjusts to your for-of syntax?

2016-05-23 Thread Jason Orendorff
No, it's not possible.

Oddly enough, when this functionality was first prototyped in
SpiderMonkey many years ago, the iterator protocol *did* pass a
boolean to the __iterator__ method (this was before symbols) based on
the syntax you were using to unpack the results. This feature was not
super useful in practice, and I always thought it was too subtle --
the difference in syntax was really not explicit enough to make it
clear to the programmer what was going on. I'm glad it wasn't
standardized.

-j


On Sun, May 22, 2016 at 12:55 PM, Šime Vidas  wrote:
> Say I have an array over which I need to iterate multiple times, but I need
> the index value only some of the time. Is it possible to create a custom
> iterator which auto-detects when I need the index and feeds me entries()
> instead of values() in those cases? For example:
>
> array[Symbol.iterator] = /* some magic here */
>
> for (let elem of array) { /* values() iterator is used automatically */ }
> for (let [i, elem] of array) { /* entries() iterator is used automatically
> */ }
>
>
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: extending an ES6 class using ES5 syntax?

2016-05-17 Thread Jason Orendorff
True. We have some special cases w.r.t. object literals, and I've
thought about optimizing `__proto__:` in particular. There's no
fundamental reason we couldn't do it, but so far the syntax does not
seem to be common enough to pay for it.

-j

On Mon, May 16, 2016 at 2:20 PM, Allen Wirfs-Brock
 wrote:
>
>> On May 16, 2016, at 10:31 AM, Jason Orendorff  
>> wrote:
>>
>> ...
>> `B.prototype = Object.create(A.prototype)` is less of a problem, for
>> our implementation, because objects created by constructor B later get
>> a prototype chain where every object is clean (none of them have ever
>> had their [[Prototype]] changed; so no assumptions have been
>> invalidated).
>>
>
> Jason,
>
> Do you or have you considered special casing __proto__ used in object 
> literals:
>
> ```js
>
> let p = {
>__proto__: Array.prototype,
>m1 () {…},
>m2 () {…}
> };
> ```
>
> Lots of good declarative shape information in that form.
>
> Allen
>
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: extending an ES6 class using ES5 syntax?

2016-05-16 Thread Jason Orendorff
In short, cache invalidation is hard. Standard disclaimer: everything
below is a radical simplification of what really goes on in a JS
engine...

When a property access (or equivalently, a method call) happens, the
standard says to do a lookup along the prototype chain to find out
where the property actually lives.

This takes time. So implementations cache property lookup results. But
that turns out to tricky. The next time that line of JS code runs, you
may be accessing a different object, or the object may have been
mutated somehow. How do we know the cached result still applies? Well,
there are two ways.

1. We can check each time the code runs, to make sure the object this
time is similar enough to the object last time, and the cached result
is still valid. Checking still takes time, but not as much time as a
full lookup.

2. We can say, ok, this cache entry is guaranteed to be valid as long
as X Y and Z don't happen -- we can make a list of invalidating
events, such as the property being deleted, or an unexpectedly
different kind of object being passed in to this line of code. And
then the engine has to notice when any of those things happen and
purge corresponding cache entries. This is faster than approach #1 --
but then unexpected events deoptimize your code.

Note how approach #2 turns the "cached result" into a kind of
performance *assumption*. The code runs fast until the assumption gets
broken. Such assumptions even get baked into jit code, and then
instead of "purging" a cache entry we have to throw away a bunch of
compiled machine code and start fresh with less-optimistic
assumptions. This is not even rare: it is a totally normal thing that
happens...

Anyway, the point of all that is, changing the [[Prototype]] of an
object is one of these events that can invalidate lots of cached
results at once. Neither approach to caching can cope with that and
still run at full speed.

I guess I should note that if the change happens early enough during
library setup, and then never happens again at run time, some
implementations might cope better than others. I think ours sets a bit
on the object that means "my [[Prototype]] has been changed" and
invalidates some kinds of cached results forever after, because that
is the simplest thing. We could always make more corner cases fast by
making the engine even more complicated! But if you got through all of
the above and you're thinking "well, you could just add another hack,
it's only a little hack" then maybe you are not thinking about JS
engines as software that has to be maintained for the long haul. :)

`B.prototype = Object.create(A.prototype)` is less of a problem, for
our implementation, because objects created by constructor B later get
a prototype chain where every object is clean (none of them have ever
had their [[Prototype]] changed; so no assumptions have been
invalidated).

-j


On Sun, May 15, 2016 at 9:53 AM, Michael Theriot
 wrote:
> Is there a reason Reflect.setPrototypeOf(B.prototype, A.prototype) can't be 
> optimized on class declaration the same way B.prototype = 
> Object.create(A.prototype) is?
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: extending an ES6 class using ES5 syntax?

2016-05-16 Thread Jason Orendorff
On Sun, May 15, 2016 at 3:07 AM, Andrea Giammarchi
 wrote:
> Thanks Andy, I think that bug has exact same concerns and valid answers for
> Boris too. Here it's also the only valid option to properly extend classes
> in ES5 and I can't wait for such "warning" to go away, most developers have
> been scared by the same warning by my `document.registerElement` polyfill
> but there's no other way, hence my complain.

This is another reason we killed the warning - for a lot of polyfills
there is just no other way to get the desired behavior.

Another reason - the cases where setting an object's prototype was the
right thing to do were disproportionately cases that affect library
authors, but then it's mainly the library *users* who see console
warnings. So the warning was not even being shown to the right people.

> FF should probably stop wasting
> time warning about what devs should do or not, if devs are using
> standardized practices. Deprecation is OK, scary messages without details
> are just ...yak.

Right, this is another reason we killed the warning - the way it was
worded was pointlessly scary.

In other words, we agree completely, and that's why we killed the warning.

That said, it remains true that changing an object's prototype kind of
fundamentally interferes with techniques which all fast ES
implementations use to optimize property/method access. The warning is
going away. The situation it is warning about is not going away.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: introduction of statefull functions (inspired by Scala language) - advanced specification of "operator()" for arbitrary objects

2016-05-12 Thread Jason Orendorff
The nice thing about @@symbol-named methods is that we *don't* have to
extend the Proxy API for them. They're just method calls.

This is why there's no hasInstance Proxy trap. `instanceof` basically
boils down to a method call, and we already have Proxy traps for
method calls: `get` and `apply`.

It's a good thing, too, because adding a new Proxy trap is a last
resort. Just from a conceptual standpoint, the less complicated
objects are, the better; just because there are 14 *fundamental*
operations on objects doesn't mean we're eager to add more. But
there's also an inherent compatibility issue. Whenever you add a new
trap, the deal is, all existing Proxy handlers were written without
consideration for the new operation. So old code, used in combination
with the new language feature, would tend to break.

Cheers,
-j


On Thu, May 12, 2016 at 9:42 AM, Igor Baklan  wrote:
> It would be nice to "bring sense" to expressions like "obj(a1, ... , aN) =
> val".  (like "obj(x)  = y")
> In Scala langue it defined in pretty clear and simple way:
>
>"obj(a1, ... , aN)" <==> "obj.apply(a1, ... , aN)"
>"obj(a1, ... , an) = val" <==> "obj.update(a1, ... , aN, val)"
>
> Of course this applied only to that cases when obj was not defined like
> method (in case of regular methods "mth(args) = val" will cause compile time
> error).
> So in Scala even arrays and maps are accessed and updated using "()"
> operator
>
>js( arr[index] = val ) <==> scala( arr(index) = val )
>
> (see http://www.scala-lang.org/api/2.10.0/index.html#scala.Array ,
> http://docs.scala-lang.org/overviews/collections/maps#operations-in-class-mutablemap
> , etc)
>
> So the proposals are:
>
> (1) to introduce symbols like @@apply and @@update with very similar to
> Scala meaning (for cases when 'obj.sttFunc' is not a function)
>
>   "obj.sttFunc(a1, ... , aN) = val" ==> "obj.sttFunc[Symbol.update]
> (obj.sttFunc, obj, [a1, ... , aN], val)"
>   "obj.sttFunc(a1, ... , aN)" ==> "obj.sttFunc[Symbol.apply] (obj.sttFunc,
> obj, [a1, ... , aN])"
>
> (2) to extend Prxoy object specification to support update action along with
> apply action:
>
> I would like to write something similar to
>
> var target = {
>jsApply: function(key){
>   console.log("apply: ", key);
>   return key;
>},
>jsUpdate: function(key, val){
>   console.log("update: (", key, ") = ", val);
>   return val;
>}
> };
> var sttFunc = new Proxy(target, {
>apply: function(target, thisArg, argumentsList) {
>   target.jsApply.apply(thisArg, argumentsList);
>},
>update:  function(target, thisArg, argumentsList, assignValue) {
>   target.jsApply.apply(thisArg,
> Array.from(argumentsList).concat([assignValue]));
>}
> });
>
> And then run it as following
>
>> sttFunc ("key") = "value";
>
> update: ( key ) =  value
>
>> sttFunc ("key");
>
> apply:  key
> "key"
>
>
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Take let variable out of temporal dead zone

2016-04-15 Thread Jason Orendorff
On Fri, Apr 15, 2016 at 12:52 PM, Oriol Bugzilla
 wrote:
> Is this behaviour intended? Is there any way to take `foo` out of the TDZ,
> so that I can assign values and read them?

Yes, the behavior is intended. I know because I raised this issue here
before the standard was finalized - search the archives.

And no, there's no standard way to fix it afterwards. You have to hit Refresh.

Firefox quietly changes the let-binding to undefined for you if you
manage to get this when you're just typing in some code in the Firefox
devtools. But it's a nonstandard hack.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Using 'this' in default parameters

2016-01-29 Thread Jason Orendorff
On Fri, Jan 29, 2016 at 8:14 AM, ` Mystery .  wrote:
> IMHO I don't think the default parameters should be evaluated within the
> context of the function being called, at least not while it's outside of
> function body's region.. Is there a specific reason to do that, or it's
> just a design preference?

Sure, there is a reason: it's about how defaults are used.

Most defaults are probably constants or empty objects. Those don't
need to refer to any variables at all, so we can set them aside.

Of the rest, I suspect *most* refer to previous parameters:

function send(sender, recip, message, onBehalfOf=sender) { ... }

or the `this` for the current method call:

class MyArray {
...
slice(start=0, stop=this.length) { ... }
}

The only way to support these is to put the arguments in scope.

(Another reason is consistency. This is how `var` initializers already
work, and have always worked: initializers are in the scope of the
bindings being initialized, and can use the values of previously
initialized bindings on the same line of code.)

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Weak Graph

2015-11-11 Thread Jason Orendorff
On Sun, Nov 8, 2015 at 4:45 AM, Jussi Kalliokoski
 wrote:
> Perhaps graph as a concept is too wide for expressing this, but it surely
> is not a linked list either. It may look like one in some cases though,
> when there's only one lineage and no branching. However that is not
> the use case here as when application state gets transformed to a view
> representation it may have various transformations applied to it, such as
> sorting, mapping or filtering.

The last sentence here doesn't seem connected to the rest. A linear
list of versions can go through a data transformation pipeline of
sorts, maps, and filters just fine.

I don't see where lineage or branching comes into any of your
examples. I can see how it could, but I think I must be missing
something here.

> On Fri, 6 Nov 2015 at 17:31 Jason Orendorff 
> wrote:
>> Then it looks a lot like a stream, in the
>> functional reactive programming sense. Let the user (in this case, the
>> renderer) buffer the diffs as needed; it knows when to reset the list.
>> And no need for fancy data structures: it could just be an Array.
>
> That misses the point, to say the least. The idea of React is that you can
> represent the UI as a declarative function of a snapshot of the state, so
> the view doesn't have to care about async. With FRP you
> subscribe/unsubscribe to asynchronous streams which, not unlike the idea
> here, can be transformed just like normal data structures and forked (to
> fork an immutable data structure is to just pass the reference). The
> difference is that streams are an inherently async structure, [...]

FRP is not inherently async. As a programming model, I'd say it's
inherently about user code not having to care about time.

Anyway, my point here is not "you should drop what you're doing and do
FRP instead" but rather "if FRP can handle this without new GC
primitives, maybe you can too".

> while what I'm
> trying to do is not. The idea being not only that the easy case of insert
> without transforms is O(1), but almost every use case can be further better
> optimized by knowing the previous state of the data structure.

Right, the state is a left fold over a series of events. Like in FRP.

> You can implement this with streams, but that will just be an unnecessary
> abstraction level offering no simplification whatsoever while making the
> concept needlessly async.

I dunno, you sort of lost me I guess. Streams come to mind because of
what you're doing: taking a series of events, transforming them, then
applying them one by one, as they arrive, to a mutable data sink.

> Another significant difference between this and
> FRP is that streams require imperative subscribe / unsubscribe, which is
> basically just sophisticated reference counting, while having the same
> issues (user after free -> update after unmount, leaks).

This is true, and I think it's your strongest point. Furthermore in
support of your side here, even without WeakGraph, I think leaks in
FRP are more wasteful than they would be in your model, because in FRP
the "deltas" are pushed through the system until somebody turns them
off, rather than pulled on demand.

Three alternative models:

1.  In Elm, the data flow graph is static. The system manages
subscriptions. Drawback: the user can't mutate the graph procedurally.

2.  A system could allow the data flow graph to change, not
*procedurally* exactly, but when a diff is applied that changes the
UI. Since the system knows about diffs, it could then automatically
manage subscriptions based on what's actually in the UI. Subscribe on
insert, unsubscribe on delete. No manual subscription management for
the end user; within the framework, you can use reference counting
etc.

3.  Implement your system using a "WeakGraph"-like object that keeps
strong references to all revisions in a fixed-sized window of recent
history. Periodically clear old patches and revisions from this cache.
Instead of `getLineage(a, b)`, we have a method `diff(a, b)` that
typically does exactly the same thing, returning an array of patches.
But `diff` may find that the user is trying to diff two versions that
are not both in the history. Then it simply does a full diff of the
two states, effectively generating a fake lineage. Note that the
performance is not *amortized* constant time: `diff()` is *always*
fast except when diffing something quite old, which shouldn't happen.
And the memory usage of the differ is more predictable than
"WeakGraph". Drawback: fake lineages. But so what?

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Weak Graph

2015-11-06 Thread Jason Orendorff
On Wed, Nov 4, 2015 at 10:09 AM, Jussi Kalliokoski
 wrote:
> I'm trying to come up with a solution to the problem of rendering lists [...]
> My idea for a solution is that the lists are immutable, contain a reference
> to their parent and a changeset / diff compared to their parent. [...]

Good problem, interesting idea.

> The biggest problem is that this will leak memory like crazy; every revision
> of the list will be preserved.

OK. Perhaps obviously, the only way around this is to mutate the list,
breaking the chain at a point where nobody cares about the rest of it
anymore.

The approach you've outlined is to have the GC tell you when to do the
mutation, but why is that a good idea? You can do it deterministically
in getLineage().

Maybe the concepts here would be clearer if we limited the graph to a
single linked list. Then it looks a lot like a stream, in the
functional reactive programming sense. Let the user (in this case, the
renderer) buffer the diffs as needed; it knows when to reset the list.
And no need for fancy data structures: it could just be an Array.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Any reason template string with empty interpolation placeholder (`${}`) throws?

2015-10-22 Thread Jason Orendorff
On Thu, Oct 22, 2015 at 7:34 PM, Caitlin Potter  wrote:
> Okay, but usability wise, this kind of sucks. There's a reason it's not what
> people expect, and why other languages with string interpolation behave
> differently.

Perl and bash both treat "${}" as a syntax error. So does Python's
string.Template().

I think it would be a mistake to sweep this kind of situation under
the rug. Pointing out a place where the programmer started to type
something but then never finished it seems like a good thing.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Re: Additional Math functions

2015-10-09 Thread Jason Orendorff
On Fri, Oct 9, 2015 at 10:26 AM, Michael McGlothlin
 wrote:
> Why include numbers at all? Some people only manipulate strings so why not
> leave numbers to a third-party library that might be better?

You can try, but I don't think sarcasm alone is going to get you there.

If you want to do something productive, write the polyfill for the API
you would like to see standardized. Make it available as a library.
Show that there is a user base for that exact thing. If it gets to be
widely used, and a native implementation really would be faster than
the pure JS version, then you can point to JSON as precedent for
standardization.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Re: Additional Math functions

2015-10-06 Thread Jason Orendorff
On Fri, Oct 2, 2015 at 6:37 PM, Alexander Jones  wrote:
> What do other languages do?

Well, Python's standard library has both a `sum()` builtin and a
statistics module. They handle floating-point weirdness differently:

>>> sum([1.0, 1e18, -1e18])
0.0
>>> import statistics
>>> statistics.mean([1.0, 1e18, -1e18])
0.

See  for statistics module
rationale. I didn't find a PEP for sum().

...But for JS, the question is: why should we think TC39 and JS
engines will be as good at satisfying this need as third-party
libraries?

I hope that users who require numerical accuracy can just crack open a
book. They should have, in JS, all the floating-point-munging tools
they need to implement a book algorithm. If they don't, let's focus on
providing those!

*Maybe* JS engine implementors can provide as-good accuracy with
better speed. But not necessarily. A standard Math.sum() may even be
slower, because TC39 is likely to specify nice, consistent, but
inconvenient behavior, such as supporting the iterator protocol or
specially handling array holes or infinities or NaN or -0. Library
authors don't have to care about this stuff. TC39 absolutely has to
care---about the risks of underspecification, at least---even at the
expense of speed.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Global lexical tier

2015-09-01 Thread Jason Orendorff
On Tue, Sep 1, 2015 at 12:03 AM, Allen Wirfs-Brock wrote:
> Both the alternative suggest by Jason and the one suggest by Saam were
> considered and rejected in these discussions. It's easy to imagine a
> different semantics. It's harder to demonstrate that it is a "better
> semantics" and to get agreement on that. [...]

This is a very thorough and fair response, Allen, thanks.

> Regarding, global declarations in a REPL.  A REPL is a extra-lingual
> features. In it not covered by the language specification.  A REPL
> implementation is certainly free to define it's own rules [...]

Well, yes, but at some cost to developers, who use the REPL to inquire
into the language's behavior, right? The more modes we have, and the
more different the REPL mode is, the more often the REPL will mislead
them.

(...to digress a bit, the SpiderMonkey JS shell currently defaults to
a nonstandard mode, for unrelated reasons. And it does mislead people.
I want to change it:
)

In any case, we're agreed that an occasional bad REPL interaction
would be no big deal on its own.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Global lexical tier

2015-09-01 Thread Jason Orendorff
On Aug 31, 2015, at 7:11 PM, Brendan Eich wrote:
>
> We are in rapid-release hell/heaven.
>
> This means errata can be issued, and engines can implement the better
> resolution for those errata, compared to what the last major-version _de
> jure_ spec mandated.

Yes. Obviously the bar is very, very high.

I'd like to hear from other implementers on whether this is worth
considering at all. I think the change would be backward-compatible
except for code that depends on redeclaration errors, or on variables
*not* being reflected on the window object.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Global lexical tier

2015-08-31 Thread Jason Orendorff
Hi everyone. Can we talk about the global lexical tier?

This was a mistake, a real blunder. We all should have known better.
An extensible intermediate scope implies dynamic scoping. The referent
of an identifier can change only once, but it can change. It's like an
implicit `with` block around *all code*.

This pattern for declaring variable in multiple scripts won't work
with let/const:

var MyES3Module = MyES3Module || {};

There's no workaround except "keep using var".

It's now possible to get a binding permanently wedged, which is bad for a REPL:

js> let z = Maht.PI;  // oops, typo
ReferenceError: Maht is not defined
js> z
ReferenceError: binding is not initialized: "z"
js> z = 1;
ReferenceError: binding is not initialized: "z"
js> delete z;
false
js> let z = 1;
SyntaxError: redeclaration of variable: "z"

For a single name to have two global bindings, both mutable, is astonishing.

All of this was unnecessary. What's the benefit to users? We ran
roughshod over existing practice, invariants, and expectations in
order to obtain a kind of self-consistency for `let` that users don't
expect or even care about.

We should have just made toplevel let/const/class create global
properties, like var. This is how it was proposed originally and how
Babel implements it today. For SpiderMonkey, switching to the worse,
less user-friendly way without regressing performance is
time-consuming.

We knew all this. We didn't evaluate it correctly. What we
particularly missed is that we already had modules as the way forward
to a nice toplevel lexical tier, and weird half measures for scripts
were pointless.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Exponentiation operator precedence

2015-08-27 Thread Jason Orendorff
Don't rely on github searches to turn up representative examples. It
doesn't work that well. Here's my educated guess as to how ** will be
used.

The most common use will be to square numbers.

a²
a**2
Math.pow(a, 2)
a.pow(2)

Currently you might write `a * a`, which is kind of lame.

So where's the benefit? If this trivial thing is the most common use
of exponentation, why bother?

The ability to look at an expression and understand it at a glance is
a big deal.

x² + y² > limit
x**2 + y**2 > limit
Math.pow(x, 2) + Math.pow(y, 2) > limit
x.pow(2) + y.pow(2) > limit

A big big deal. It's the reason we have arithmetic operators in JS in
the first place.

Exponentiation is common when computing easing functions, curves for
graphics, interest, simulations, random stuff in games. Nth roots are
fairly common too (`apr**(1/12)`). In all of these cases, the user is
doing the same thing: translating a mathematical formula they wish to
use from "math" to JS. It is not extra hard to translate such a
formula using Math.pow(), but it is harder to read once you're done.
You have to mentally translate back to "math".

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Exponentiation operator precedence

2015-08-27 Thread Jason Orendorff
On Thu, Aug 27, 2015 at 9:04 AM, Kevin Smith  wrote:
> a**b * -c**d + e

I don't think people use unary - like this very often. It's nothing to
do with exponentiation. You don't see people write:

a * -c + e

because the right-side-up way to say that is:

e - a * c

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Exponentiation operator precedence

2015-08-26 Thread Jason Orendorff
On Wed, Aug 26, 2015 at 11:09 AM, Mark S. Miller  wrote:
> I don't get it. The conflict between
>
> * the history of ** in other languages,
> * the general pattern that unary binds tighter than binary
>
> seems unresolvable. By the first bullet, -2 ** 2 would be -4. By the second,
> it would be 4. Either answer will surprise too many programmers.

I just think the danger is not so great. Who's really going to be
surprised that `-x**2` is negative? This follows not only other
mainstream programming languages but a mathematical notation that has
been in common use for hundreds of years and is taught to every high
school algebra student.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Exponentiation operator precedence

2015-08-26 Thread Jason Orendorff
On Wed, Aug 26, 2015 at 1:03 PM, Thomas  wrote:
> There's still the issue of exponentiation being right-associative. Unless ** 
> becomes an operator which behaves differently as to how it would in a high 
> school maths class, we're at an impasse.

I'm not sure I follow. Exponentiation is right-associative in math, in
the current ** proposal, and in every suggested update to it.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Exponentiation operator precedence

2015-08-26 Thread Jason Orendorff
On Tue, Aug 25, 2015 at 5:43 PM, Mark S. Miller  wrote:
> When the costs were minor, it was ok that the benefits were minor.

The costs will probably still be minor if we just let Rick look at it
and revise the proposal.

What has happened here is
- upon implementing the feature, we noticed a problem
- we thought through it together and found possible solutions
- we found other languages already use these solutions

This seems like less turbulence than average for a new ES feature,
even a minor one. Considering dropping the feature seems premature.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Exponentiation operator precedence

2015-08-24 Thread Jason Orendorff
On Mon, Aug 24, 2015 at 8:10 PM, Waldemar Horwat  wrote:
> That has different right and left precedence and is probably the closest to
> the mathematical intent.

Not to quibble, but I do want to understand:

UnaryExpression : PostfixExpression ** UnaryExpression

AdditiveExpression : AdditiveExpression + MultiplicativeExpression

We don't say binary `+` has different left and right precedence,
right? What's different with `**`, apart from being right-associative?

>  However, it does carry other surprises.  What does
> each of the following do?

Interesting:

++x ** y;  // early error: invalid operand for ++
(because it's parsed as `++(x ** y)`)
x++ ** y;  // parses as expected: (x++) ** y
x ** ++y;  // parses as expected: x ** (++y)
x ** y++;  // parses as expected: x ** (y++)

I'm OK with this. It should be rarer in practice than `-x**2`, and at
least the language won't silently assign a surprising meaning to user
code.

It could be made to parse as `(++x) ** y` by changing prefix ++ and --
to be higher precedence than the other prefix operators. I don't think
this would break any existing programs, because combinations like
`++typeof 3` are already early errors. PHP apparently does something
like this:

$ php -r '$x = 3; print(++$x**2 . "\n"); print($x . "\n");'
16
4

D doesn't. Python and Haskell don't have ++/--.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Exponentiation operator precedence

2015-08-24 Thread Jason Orendorff
On Mon, Aug 24, 2015 at 7:24 PM, Jason Orendorff
 wrote:
> What you're describing as "sometimes tighter and sometimes looser" I
> would call "the same precedence". It's even easier to specify than the
> current proposal:
>
> UnaryExpression : PostfixExpression ** UnaryExpression

P.S. Admittedly it might be a good idea to rename "UnaryExpression" if
we put a binary operator in there.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Exponentiation operator precedence

2015-08-24 Thread Jason Orendorff
On Mon, Aug 24, 2015 at 5:45 PM, Waldemar Horwat  wrote:
> Let's not.  As I said at the last meeting, making ** bind tighter than unary
> operators would break x**-2.  And making it sometimes tighter and sometimes
> looser would be too confusing and lead to other opportunities for precedence
> inversion.

Don't you think having `-x**2` mean the same thing as `x**2` is more
confusing? It seems like it will cause problems for the exact
programmers we are trying to help with this feature.

What you're describing as "sometimes tighter and sometimes looser" I
would call "the same precedence". It's even easier to specify than the
current proposal:

UnaryExpression : PostfixExpression ** UnaryExpression

An expression using both `**` and unary `-` is then parsed right-associatively:

-a ** -b ** -c ** -d
means -(a ** (-(b ** (-(c ** (-d))

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Exponentiation operator precedence

2015-08-24 Thread Jason Orendorff
In math, -x² is -(x²), not (-x)². But as proposed for JS, -x**2 is (-x)**2.

PHP, Python, Haskell, and D side with the traditional algebraic
notation, against JS. Here's PHP:

$ php -r 'print(-2 ** 2);'
-4

Python:

>>> -2 ** 2
-4

Haskell:

Prelude> -2 ^ 2
-4

The D grammar: http://dlang.org/grammar.html#UnaryExpression

Let's switch.

Another case to think about is `-2 ** -2`. In Haskell, that's a syntax
error, but the other three languages all treat it the same way, so
maybe JS should follow suit.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: System.import()?

2015-08-19 Thread Jason Orendorff
On Tue, Aug 18, 2015 at 1:36 PM, Dave Herman  wrote:
> The `System.loader.import` feature isn't ready for stabilization yet, and is
> blocked on a few other pieces of the Loader design.

Well, if it isn't ready, it isn't ready. But can you tell a little bit
more? What sort of changes are anticipated?

Apart from "System" apparently being renamed, the API doesn't seem to
have changed in the past few years.

> https://github.com/whatwg/loader/blob/master/roadmap.md

Cool. Is the intent to release a standard as each stage of work is
finished? Or will everything remain unstable until stage 3 is
completed?

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: System.import()?

2015-08-18 Thread Jason Orendorff
On Tue, Aug 18, 2015 at 12:45 PM, Bradley Meck  wrote:
> This would assume they can support the transformation hooks to do things
> like load coffeescript etc. right now, which is the main contention point.

It is a perfectly ordinary occurrence in software to ship some
capability at one point, and ways of customizing that capability
later.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: System.import()?

2015-08-18 Thread Jason Orendorff
On Tue, Aug 18, 2015 at 12:11 PM, Domenic Denicola  wrote:
>> HostResolveImportedModule is widely implemented by compilers, though
>> not by browsers. People are writing, using, and sharing ES6 modules today.
>
> So what is your proposal then? Just standardize the node module resolution 
> algorithm, since that is what transpilers are doing?

Here's what I had in mind:

*   Do not standardize the Node algorithm or any other module loading
algorithm in ECMA-262. That responsibility belongs to the Loader
standard.

*   Change the signature of HostResolveImportedModule to match
`System.import()`, which takes a this-value and two strings (name and
referrer).

*   Clarify that HostResolveImportedModule (and its existing callers
in the spec) operate asynchronously, e.g. by adding a
PromiseCapability argument, like PerformPromiseAll. (The async
functions proposal takes a different approach to specifying async
algorithms, but I'm not sure if that's final wording or what exactly.)

*   Specify a `System` builtin object.

*   Specify a builtin method System.import(name[, referrer]) that
performs these steps:

1.  Let promiseCapability be NewPromiseCapability(%Promise%).

2.  Return HostResolveImportedModule(this value, name, referrer,
promiseCapability).

Nothing terribly exciting here. Some vaguely interesting refactoring
in the second and third bullet points.

The intent with `System.import()` all along was to provide a dynamic
equivalent to the static `import` syntax. Why not go one step further
and make it official that they share an implementation? That's all
this proposal does, and that's enough to make a useful standard API
for people who are writing ES6 modules right now.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: System.import()?

2015-08-18 Thread Jason Orendorff
On Mon, Aug 17, 2015 at 9:50 PM, Bradley Meck  wrote:
> I think we all want to find a good solution to creating a Loader for ES6
> modules. I would follow WHATWG's Loader if you want to participate. There
> are a surprising number of considerations, particularly due to existing code
> bases.

I'm aware of the considerations. I helped Dave Herman hash out the
Loader design.

The opportunity here is that we can specify System.import() now
*without* having to solve all those considerations overnight.

There is nothing stopping us. We have the primitive. We have standard
syntax that uses it. All we have to do is say "...and here is a
standard API that exposes the same primitive".

Then JS programmers will have a way to call that primitive
procedurally, something they now lack.

This proposal is *not* for the immediate benefit of browsers, which
indeed need to wait for Loaders and/or 

Re: System.import()?

2015-08-18 Thread Jason Orendorff
On Mon, Aug 17, 2015 at 5:02 PM, Bradley Meck  wrote:
> The timing and extensibility is too complex to easily fit into ECMA-262, see
> some things mentioned in https://github.com/whatwg/loader/issues/54 . I vote
> no for a few years at least.

I am not calling for importing the entire loader spec into ECMA-262.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: System.import()?

2015-08-18 Thread Jason Orendorff
On Mon, Aug 17, 2015 at 5:02 PM, Domenic Denicola  wrote:
>> It's possible to make minor changes to HostResolveImportedModule and
>> then specify `System.import` in terms of that. [...]
>
> I don't understand. If it's in terms of HostResolveImportedModule, and 
> HostResolveImportedModule is not implemented or specified in any way yet, 
> introducing a new thing on top of that does not help the situation at all.

HostResolveImportedModule is widely implemented by compilers, though
not by browsers. People are writing, using, and sharing ES6 modules
today.

> In other words, it seems necessary to make `import "moduleSpec"` work before 
> even thinking about how to make `System.import("moduleSpec")` work.

It is working, and the people using it have a need for the dynamic API
to go along with the static syntax, for reasons I pointed out in the
initial post.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


System.import()?

2015-08-17 Thread Jason Orendorff
The ES6 module system is taking a real beating in the comments section
here: https://hacks.mozilla.org/2015/08/es6-in-depth-modules/

People are concerned about things like:

- There is no standard way to load any modules at all in the browser.
- There is no standard way for a module to load other modules later
(lazily, for faster initial load times).
- There is no standard way to conditionally load modules.
- There is no standard way to catch errors when module loading fails.

There's a planned feature that addresses all these use cases:
`System.import(moduleSpec, referrer)`.

It's possible to make minor changes to HostResolveImportedModule and
then specify `System.import` in terms of that. It could ship in the
existing compilation-plus-polyfill module system implementations (like
webpack) immediately. And it'd be fully compatible with the coming JS
Loader Standard.

Arguably something this fundamental to module usage belongs in ECMA-262 anyway.

What do you think?

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: function.sent beta equivalence?

2015-06-25 Thread Jason Orendorff
On Wed, Jun 24, 2015 at 3:17 PM, Mark S. Miller  wrote:
> Just showing the next method:
>
> function wrap(g, prime) {
>   let first = true;
>   return {
> next(val) {
>   if (first) {
> first = false;
> return g.next(prime);

Oh, I see. We can use an intermediate wrapper object here that's not a
generator.

OK, I don't imagine people doing this in the case where they're using
generators to implement asynchronous processes. I suppose they just
won't use function.next in that case. Which is fine.

Still, it's funny that at the language level we can't have an
"elimination form" in `yield* f(...)` that's directly dual with the
"introduction form" of `function*(...){...}`. Is there some PLT-ish
explanation for the asymmetry? Just hoping to understand a little
better the relationship between functions and generators.

I'm not sure it'll be clear what I mean by "relationship". I mean a
mathematical sort of relationship. If you think of the statements and
operators of JavaScript as combinators in some kind of algebra on
computations, both functions and generators are built up *mostly* from
the same combinators, and they have analogous behavior. That is, they
follow the same rules of execution: those rules are only specified
once, not twice. The differences are around invocation, but even
there, though you have to use slightly different syntax, some
analogies hold (as in my original post on this thread).

My sense is that function.next is outside this relationship, and it
shows as a bit of a wart every time you write abstract code about
generators. For example, Mark's flatMap on generators must pass
undefined as the first value to g2.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: function.sent beta equivalence?

2015-06-24 Thread Jason Orendorff
On Wed, Jun 24, 2015 at 2:17 PM, Brendan Eich  wrote:
> MM: Libraries could do this.
>
> yield  *  wrap(g,function.next);
>
> MM: "wrap" returns an iterator which wraps the generator which primes the
> subgenerator with the supplied value.

Thanks for finding this discussion. This is exactly what I'm
interested in. What does "wrap" look like? It seems like it would be
pretty involved.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


function.sent beta equivalence?

2015-06-24 Thread Jason Orendorff
Quick question about function.sent:

As of ES6, there's this parallel between functions and generators:

// how to wrap a function
// f2 is equivalent to f, if f doesn't use `this`.
function f(...) { ... }
function f2(...args) { return f(...args); }

// how to wrap a generator
// g2 is equivalent to g, if g doesn't use `this`.
function* g(...) { ... }
function* g2(...args) { return yield* g(...args); }

That is, λx.f(x) = f, a sort of beta-equivalence rule, and for
generators, you just need to add `yield*` to get an analogous rule. My
understanding is that this is one reason we have `yield*`. (Writing a
wrapping function/generator that also covers `this` is left as an easy
exercise.)

Given function.sent, is there still a way to "wrap" a generator?

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ES6 Proxy Function Call Trap

2015-06-09 Thread Jason Orendorff
On Tue, Jun 9, 2015 at 3:44 AM, Edwin Reynoso  wrote:
> Alright first I'll say I'm using FF to test because FF supports proxies, and
> I really don't know how to use Reflect and how it works yet. FF as well does
> not support Reflect right now. Therefore I'll look into that.

That's right. Reflect is a key tool when you're writing proxy
handlers. I'm working on implementing it in Firefox now. If you like,
you can subscribe to this bug and get updates (quiet so far):
https://bugzilla.mozilla.org/show_bug.cgi?id=987514

Here, I think the technique you're looking for might be that the proxy
handler's get() method should return a new proxy (representing an
array of methods). This new "method proxy" needs something callable as
its target. When the method proxy's .call() trap is called, it'll
receive the arguments.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Look-behind proposal

2015-05-18 Thread Jason Orendorff
On Mon, May 18, 2015 at 1:51 PM, Claude Pache  wrote:
> Another more powerful approach (which I prefer), [...]

As long as we prohibit matching groups within lookbehind assertions, I
think the approach you prefer is a strict superset of what's proposed.
So there's no opportunity cost to taking the proposal as-is: the .NET
semantics could be compatibly added later.

I imagine TC39 gives some preference to proposals that exist in a
concrete form. So if you prefer the .NET approach enough to do
anything about it, now's a great time to write some spec text.

> That said, I think there are easier missing features to be added, that are
> supported by most other RegExp flavours. I'm thinking of:
>
> * the `s`, or `.dotall` flag: the dot `.` matches every character, including
> newlines;
> * true support of Unicode, namely: escape sequences such as `\Lu` for
> uppercase letter, or `\X` for grapheme cluster.

Why not submit proposals for these?

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Look-behind proposal

2015-05-18 Thread Jason Orendorff
On Mon, May 18, 2015 at 8:50 AM, Nozomu Katō  wrote:
> I submit a proposal for adding the look-behind assertions to RegExp.

Fantastic! I'm not a TC39 member but I've been hoping this would
happen for some time.

I have often thought that the major obstacle was that no one has done
this work. I hope I was not wrong!

>  It is a Syntax Error if Disjunction contains Quantifier ::
>  QuantifierPrefix except QuantifierPrefix :: { DecimalDigits }.

Backreferences must be ruled out, too.

>   1. Let n be the exact number of the sequence of code points which
>  Disjunction matches [NOTE].

I don't think a NOTE is strong enough for spec purposes, so you can
improve the proposal by adding a "Static Semantics:" section that
formally specifies this.

The spec uses attribute grammars for dozens of things like this, where
some piece of information has to be determined from the parse tree.
See "Static Semantics: ElisionWidth" for a simple example.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: About generators

2015-05-14 Thread Jason Orendorff
On Thu, May 14, 2015 at 2:05 AM,   wrote:
> Thanks. What is the underlying concurrency framework when we use generators
> for concurrent workloads ? Does it depend on the particular VM ?

Generators aren't for concurrency.

When a generator runs, it runs in the same thread as the caller. The
order of execution is sequential and deterministic, and never
concurrent. Unlike system threads, a generator is only ever suspended
at points marked by yield in its body.

(copied from )

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Subclassing Function

2015-05-08 Thread Jason Orendorff
On Thu, May 7, 2015 at 3:25 PM, Allen Wirfs-Brock  wrote:
> On May 7, 2015, at 12:50 PM, Francisco Tolmasky wrote:
>> In the existing implementations I’ve tried, it appears I can’t do this:
>>
>> class SuperFunction extends Function { }
>
> Nope, it's supposed to work.

Agreed. We're working on it in Firefox. It's of a piece with
new.target support, so my best guess is it'll be weeks, maybe a couple
months, before it lands in Nightly.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: is an iterator allowed to reuse the same "state" object?

2015-05-01 Thread Jason Orendorff
On Wed, Apr 29, 2015 at 5:41 PM, Andreas Rossberg  wrote:
>> I'm inferring your comment about generator optimization hardship has to do
>> with a function that yields -- whose CFG has multiple entry points and whose
>> activation record must live in the heap.
>
> Yes, the biggest challenge perhaps is not even generator CFGs per se, but
> getting inlining to work with them, which is necessary to take advantage of
> escape analysis.

Since the objects to be eliminated here are not created in the body of
the generator-function, an implementation could create those objects
in an inline-able .next() method, and thus eliminate the object even
if none of the generator code can be inlined. Pseudocode:

Generator.prototype.next = function next(arg) {
var value = INTERNALS.runGenerator(this, arg);
var done = INTERNALS.generatorIsDone(this);
return {value, done};
};

But this too can interfere with other optimizations. Your broader
point about generator optimization certainly stands.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: super.prop assignment can silently overwrite non-writable properties

2015-04-20 Thread Jason Orendorff
On Mon, Apr 20, 2015 at 2:42 PM, Caitlin Potter  wrote:
> Oh — he’s right, ValidateAndApplyPropertyDescriptor won’t throw in the 
> example case, because the old descriptor is configurable. That’s kind of 
> weird.

Yes, that's it.  9.1.6.3 step 8.a says that writability is checked
only if the existing property is non-configurable.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: super.prop assignment can silently overwrite non-writable properties

2015-04-20 Thread Jason Orendorff
On Mon, Apr 20, 2015 at 12:44 PM, Allen Wirfs-Brock
 wrote:
>> In the spec, 9.1.9 step 4.d.i. is where `super.prop = 2` ends up, with
>> O=X.prototype.
>
> 4.d.1 doesn't set the property, it just comes up with the property descriptor 
> to use, if the `Receiver` does not already have a corresponding own property.
>
> 5.c+5.e checks if the corresponding own property actually exists on the 
> `Receiver`.
>
>  If it already exits then it does a [[DefineOwnProperty]] that only specifies 
> the `value` attribute. This should respect the current `writable` attribute 
> of the property and hence reject the attempt to change the value.

I agree with all of this, except I don't see where the attempt is
rejected. Since the property is configurable, I think
[[DefineOwnProperty]] succeeds.

The property is still non-writable afterwards. Only the value changes.

So this isn't breaking the object invariants: the property in question
is configurable, so it's OK (I guess) to change the value. It's just
surprising for assignment syntax to succeed in doing it.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


super.prop assignment can silently overwrite non-writable properties

2015-04-20 Thread Jason Orendorff
We're implementing `super` in Firefox, and ran across this surprising behavior:

class X {
constructor() {
Object.defineProperty(this, "prop", {
configurable: true,
writable: false,
value: 1});
}
f() {
super.prop = 2;  // overwrites non-writable property!
}
}

var x = new X();
x.f();
assertEq(x.prop, 2);  // passes

In the spec, 9.1.9 step 4.d.i. is where `super.prop = 2` ends up, with
O=X.prototype.

Options:

1. Do nothing. Allow overwriting. It's a little weird, but this code
is pretty weird.

2. (post-ES6 of course) Add more "code" in 4.d.i. to perform a
[[GetOwnProperty]] and check.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Final ES6 Draft

2015-04-17 Thread Jason Orendorff
Congratulations, everyone, on this milestone, and thanks for your
work. Looking back all the way to ES5, it's striking just how
substantial an improvement ES6 is. It'll ultimately affect almost
every line of JS code I write.

-j

On Thu, Apr 16, 2015 at 6:23 PM, Allen Wirfs-Brock
 wrote:
> The final ES6 ECMAScript 2014 specification draft has been completed and
> submitted to the Ecma GA for their consideration and review prior to their
> June vote to approve it as a standard.
>
> The final draft is available at
> http://wiki.ecmascript.org/doku.php?id=harmony:specification_drafts#final_draft
>
> The only significant technical change in this draft is some tweaks to
> completion value generation within iteration statements.  These tweaks
> ensure that unroll a loop does not change the resulting completion values.
>
> Other changes are minor editorial corrections including a few Ecma styling
> conformance issues.
>
> It will still be possible to make a few very minor editorial corrections
> before publishings the standard. So please continue to report any bugs or
> typos you find to bugs.ecmascript.org.
>
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Please volunteer to maintain the HTML version of the spec

2015-04-17 Thread Jason Orendorff
On Thu, Apr 16, 2015 at 3:35 PM, Michael Dyck  wrote:
> I'm interested.

OK, thanks. I'll get back to you next week. Unfortunately I'm not around today.

>> Each time a new revision is published, some manual steps are required
>> to map broken links to the right sections in the new document.
>
> Do you mean that old 'es6-draft.html' URLs should resolve to the
> corresponding section in the HTML version of the latest ES7+ draft? (In
> which case, the latter would need to continue to support (remap) all the old
> section-ids.) I wonder if people would find that surprising.

I hadn't considered it.

Given the use cases I know about (mostly es-discuss and in
implementations' bug-tracking databases), I think it's better to do it
the other way, so that ES6-era links continue to point to an ES6 spec.

Starting from scratch will not save a whole lot of work, though. The
work required with each revision is mostly figuring out how to
redirect section-ids that were newly changed in that revision, not
maintaining the old redirects (which is at most some
search-and-replace).

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Please volunteer to maintain the HTML version of the spec

2015-04-16 Thread Jason Orendorff
I need to free up some time to work on other things, so I will not be
creating the unofficial HTML version of the spec anymore once ES2015
is final.

If you're interested in maintaining the HTML version, let me know! If
not, I imagine Allen can use Word to generate HTML versions, so it's
not like we'll starve.


### What's involved?

Doing the conversion is *almost* a piece of cake: just run the Python
script at , using the
instructions in the README. Then publish the generated HTML file on
the Web.

But there is one more job.

Back in 2013, I committed to keeping links to sections working as the
document evolves. So if you click on a link in a very old email (<3
esdiscuss.org) and it points to:

https://people.mozilla.org/~jorendorff/es6-draft.html#sec-binary-bitwise-operators-static-semantics-isanonymousfunctiondefinition
which has since been merged with some other sections and renamed, some
JS in the page redirects you to that section:

https://people.mozilla.org/~jorendorff/es6-draft.html#sec-isanonymousfunctiondefinition

Each time a new revision is published, some manual steps are required
to map broken links to the right sections in the new document. It
can't be fully automated, though undoubtedly you could improve on what
I've been doing. Details on request.

Cheers,
-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: short-circuiting Array.prototype.reduce

2015-03-27 Thread Jason Orendorff
On Thu, Mar 26, 2015 at 8:22 PM, Kyle Simpson  wrote:
> outer = outer.filter(function filterer(inner){
>   return inner.reduce(function reducer(prev,current){
> if (prev === false || prev === current) return false;
> return current;
>   });
> });

I think you could write that like this:

outer = outer.filter(arr =>
  !arr.some((e, i) =>
i > 0 && arr[i-1] === e));

Array.prototype.some is designed to produce a boolean result and
already has early exit built in.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Converting strings to template strings

2015-03-23 Thread Jason Orendorff
On Mon, Mar 23, 2015 at 1:55 AM, Mark S. Miller  wrote:
>> String templates are not good for templates, these work only for
>> statically defined code and in place meaning you cannot grab content from a
>> DB and inject values like names or numbers as you would do with any
>> templating system.
>
> I still don't understand this. Could you give a simple example and explain
> what it is trying to do? Thanks.

Filling in templates with data is extremely useful in web development.
Many libraries do just this one thing and nothing else. [Mustache][1],
[JSRender][2], and [nano][3] are all popular. Ruby has [ERB][4]
built-in; there's [Jinja][5] for Python and a million more.

All these libraries work something like this:

// You compile a template into an object.
var t = TemplateLibrary.compile(templateFileName);
// You pass some data to the template object and it builds a string.
resultDiv.innerHTML = t.render({data: resultArray});

Each library is thus a compiler or interpreter for a template
*language*. Template languages are interesting. The best ones are
designed for simplicity and clarity. Some offer a weak safety
property: e.g. a template can't execute arbitrary JS code of its
choice and will do no worse than call getters on the objects you pass
to it. Various template languages thus have richer or poorer
expression syntax, by design. All have straightforward loop syntax.
They are, in short, superficially like ES6 template strings, but
otherwise about as different as can be. ES6 template strings are not a
replacement for template libraries.

But from the few data points I have, approximately 100% of web
developers, when they first hear "template strings are in ES6", think
that means something like Mustache in the standard library. Some
initially try to use the feature that way and get frustrated. I expect
widespread confusion on this point.

-j

[1]: https://mustache.github.io/mustache.5.html
[2]: http://www.jsviews.com/
[3]: https://github.com/trix/nano
[4]: http://www.stuartellis.eu/articles/erb/
[5]: http://jinja.pocoo.org/
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: New ES6 draft - Release Candidate 3, Rev36

2015-03-19 Thread Jason Orendorff
The HTML version is up at
.

Thanks to @caitp, "opt" and parameters (like "[?Yield]") in grammar
productions are now shown in color.

-j

On Tue, Mar 17, 2015 at 7:36 PM, Allen Wirfs-Brock
 wrote:
> Is available at:
> http://wiki.ecmascript.org/doku.php?id=harmony:specification_drafts#march_17_2015_rev_36_release_candidate_3
>
>  Changes include:
>
> Several significant fixes relating to “completion reform”
> Various formatting tweaks and minor editorial and technical bug fixes.
> Resolved bugs: 4167-4166, 4163=4154, 4151=4148, 4145-4144, 4142, 4139-4125,
> 4123-4109, 4066, 3618, 3442, 1274, 522
>
>
>
>
>
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Reflect.getOwnPropertySymbols?

2015-03-16 Thread Jason Orendorff
On Mon, Mar 16, 2015 at 11:53 AM, Allen Wirfs-Brock
 wrote:
> In ES6, the primary role of the Reflect object is to provide direct access
> to an object's essential internal methods:
> http://people.mozilla.org/~jorendorff/es6-draft.html#sec-object-internal-methods-and-internal-slots

To further elaborate on this: one way this is useful is that the 14
essential internal methods are exactly the operations you can trap
with a custom Proxy. It's useful, when writing a Proxy, to use the
Reflect methods as fallbacks:

var alertingProxy = new Proxy(obj, {
// Proxy: hook into property assignment
set(t, key, value, receiver) {
alert(`setting the ${key} property of ${t} to ${value}`);

// Reflect: do normal property assignment
return Reflect.set(t, key, value, receiver);
}
});

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Idiomatic representation of { buffer, bytesRead }

2015-03-04 Thread Jason Orendorff
On Wed, Mar 4, 2015 at 3:06 PM, Domenic Denicola  wrote:
> I thought of that. However, I found it a bit strange that passing this 
> function a view onto bytes [256, 512] of a 1024-byte buffer would detach the 
> entire 1024-byte buffer. What do you think?

It's a good point. I figured most callers will have allocated the
buffer themselves, most will only have one view into it at a time, and
most will ask for the whole thing to be filled; and by "most" I really
mean somewhere over 99.9%. Skimming your gist seemed to sort of
confirm my hunch, but don't take my word for it -- that's all the
research I did. All I know is, I've known about Python's
[file.readinto()
method](https://docs.python.org/3.5/library/io.html#io.RawIOBase.readinto)
for at least 15 years and never yet had a need for it.

Would it make it seem less strange if you specified the argument as a
"dictionary" with these properties:

{buffer:, byteOffset:, byteLength:, constructor:}

...and then casually mention that DataViews and TypedArrays both
happen to quack in just this way?

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Class double-bind

2015-03-04 Thread Jason Orendorff
I guess we are just going to disagree here. Double bindings with
mutability still seem clearly bad. I can't make sense of the rationale
that classes can cope with every external binding being mutable except
for, somehow, their own name, and we're doing users a favor by
"protecting" them from "tampering" for just this one binding in this
one place.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Fwd: Class double-bind

2015-03-04 Thread Jason Orendorff
Oops, accidentally sent this only to Allen.


-- Forwarded message --
From: Jason Orendorff 
Date: Tue, Mar 3, 2015 at 11:34 AM
Subject: Re: Class double-bind
To: Allen Wirfs-Brock 


On Mon, Mar 2, 2015 at 5:54 PM, Allen Wirfs-Brock  wrote:
>  Pretty much everyone I've seen discover the function binding equivalent  (or 
> have it explained to them for the first time) was shocked.  What! 'function 
> fact(n) {return n>1? n*fact(n-1):1}' doesn't necessarily recur on the same 
> function?  that's crazy! is the typical reaction.

Perhaps this is a little overstated? In Scheme, Python, Lua, Ruby, and
Smalltalk, code in a function/class/method that refer to it by name
refer to the external binding. That binding is mutable in all those
languages except Ruby and Smalltalk (and even in those, I think you
*can* mutate it, but the language discourages it).

So basically every language in this space has the same behavior. JS
differs only in that it has a named-function-expression syntax, which
I think the others lack.

I can't think of a language where two bindings are created and they
can then diverge. This is novel weirdness.

> Similarly, it would be crazy if:
>   class Foo {
>   static makeFoo() {return new Foo}
>   }
>
> didn't give you a factory method that created instances of Foo.

Well, you're calling every existing dynamic language with classes
crazy. I don't think that's very useful.

>> If we wanted classes to be tamper-proof, then the outer binding would
>> be immutable as well. It's not; it's mutable; yet every use case I can
>> think of for actually assigning to it is silently broken due to the
>> double binding.
>
> We needed global class bindings to be replaceable.

That makes sense.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Idiomatic representation of { buffer, bytesRead }

2015-03-04 Thread Jason Orendorff
On Mon, Mar 2, 2015 at 3:45 PM, Domenic Denicola  wrote:
> While working on lower-level byte streams we're encountering a number of 
> situations that need to return something along the lines of `{ buffer, 
> bytesRead }`. (In this setting "buffer" = ArrayBuffer.) In the most general 
> form the signature ends up being something like
>
> { sourceBuffer, offset, bytesDesired } -> { newBuffer, bytesRead }

I very much like 2 and 3 because they provide the result type that the
user wants anyway. Slightly prefer DataView.

But you can support both, like this:

pull(DataView) -> Promise
pull(TypedArrayView) -> Promise

A view argument conveniently provides just the three pieces of
information you need, plus a type.

The lower-level primitive could take an optional fourth argument:

pull(sourceBuffer, offset, bytesDesired,
resultConstructor=DataView) -> Promise

This could even be generic in resultConstructor, though it's a little
awkward because you have to divide by
resultConstructor.BYTES_PER_ELEMENT before invoking the constructor.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Class double-bind

2015-03-03 Thread Jason Orendorff
On Mon, Mar 2, 2015 at 5:54 PM, Allen Wirfs-Brock  wrote:
> I didn't take the time to come up with a real example.  But code within a 
> class body that refers to the containing class is something I have seem many 
> times.  Some of the most common places you see this is in methods (instance 
> or static) referring to "constants" defined as static properties of the 
> class.  Another place you see it is "static" methods referring to other 
> static methods of the same class or applying 'new' to their class name.  In 
> most of these cases, there are actually better ways to do the same thing 
> (referring to 'this' from within static methods, using 'this.constructor' 
> within instance3 method) but many developer still use the direct name 
> references.

Yes, we agree on all this. What's a bug is `Bar = { };`.

> Of course, using 'new this.construtor' internally would also break your 
> logging wrapper.

The wrapper could be either a subclass (which will work inasmuch as a
subclass can substitute for the base class) or a proxy (which will
work inasmuch as a proxy can substitute for its target object). Or it
could just mutate the constructor link.

> Which brings us back to what should probably be the major point..  Class are 
> supposed to be abstractions that encapsulate their internal implementation 
> details.  Expecting that sort of wrapper to work an any sort of general 
> situation is grossly violating that encapsulation.

Hmm. Usually the stronger an abstraction, the *better* wrapping works.
It's funny that it turns out not to work that way in this case.

To me, what's happening here is that the double-binding design is
just... weird. So unsurprisingly, it has weird consequences for users.
I don't think it even matters where one stands on the
classes-as-sugar/classes-as-abstraction spectrum.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss



Re: Class double-bind

2015-03-02 Thread Jason Orendorff
On Mon, Mar 2, 2015 at 4:15 PM, Allen Wirfs-Brock  wrote:
> and conversely if we have something like this:
>
> class Bar {
>constructor(n) {this.n=n}
>static get const() {return 42);
>op(x) { return new Bar(Bar.const )}
> };
>
> the inner workings of the class would get very screwed up if somebody did:
> Bar = { };

...But that would just be a bug in the program. The same thing would
happen if you overwrote any function or method anywhere with a random
object. For `new Bar` to stop working at that point is what people
will *expect*, and I don't think we do programmers any favors by
mysteriously masking certain kinds of bug for a little while.

My example was something useful, something programmers will do on
purpose, that goes silently wonky because of the double binding.

> the chain of logic I apply for arriving at the specified behavior is:
>
> 1) There are many reasons a developer may want to refer to a class from
> within it's body and the obvious way of doing so should be reliable and
> tamper-proof.

The reliability benefit is surely offset somewhat by how confusing this is.

If we wanted classes to be tamper-proof, then the outer binding would
be immutable as well. It's not; it's mutable; yet every use case I can
think of for actually assigning to it is silently broken due to the
double binding.

I favor keeping it mutable, because that's useful and JS is the sort
of language where you're allowed to hack some things. But as long as
it's mutable there should not also be a second implicit binding seen
by different code. One declaration creating two bindings + mutability
= hall of mirrors.

> 2) This behavior of function declarations is actually quite astonishing and
> if we had a do over on FunctionDeclaration we would probably give it a local
> name binding just like function expressions (we might fight about it a
> while, but I'm pretty sure that's where we would end up).

That's precisely what I thought, until I started thinking about what
it'll actually be like to use this feature as a programmer.

To me, this issue explains why functions are the way they are.

> 3) Class declarations already differ from function declarations in a number
> of other ways, so class declaration consistency with function declaration on
> this one arguably buggy behavior is not a particularly strong position.

Sure, if it were purely about matching what functions do for the sake
of matchiness, I wouldn't be here.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Class double-bind

2015-03-02 Thread Jason Orendorff
Classes are specified to have an immutable inner binding even if they
also declare a mutable lexical binding in the enclosing scope:

class Foo {
foo() {
// immutable inner binding 'Foo' is in scope here
}
}
// mutable lexical binding 'Foo' is in scope here

Having two bindings can be tricky. Suppose I then do this:

Foo = wrapConstructorWithExtraLogging(Foo);

Now the two bindings have different values. If one of Foo's methods
does `new Foo`, we don't get the extra logging.

Can we go back to having classes do what functions do? A single
function never introduces two bindings; rather a named function
expression has only the immutable inner binding and a function
declaration only declares a variable.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: iterator next method returning new object

2015-03-02 Thread Jason Orendorff
The most important things here are:

1.  Like all performance hacks, unless you've measured a speed
improvement under fairly realistic workloads, you shouldn't do this.

2.  Whenever you need a custom iterator, try writing a generator
instead. It's amazing. You can get the behavior you want in a fraction
of the developer time, with clearer and *much* smaller code.

As to your question, here are some (additional) seeds of doubt as requested:

-   Storing this object isn't entirely free. You have to create a
property (or closed-over variable, same deal, roughly) to stash it in,
and each time .next() is called, you have to access that property or
variable. Also, storing the object prevents the most-recently-iterated
value from being GC'd. (Normally this won't matter. It could matter if
you have thousands of iterators going at once, and each one is only
occasionally consulted.)

-   If the caller is a jerk, they might do something like freeze the
object (which means your .next() method will keep getting called
forever, since it can't set .done to true) or replace the .value
property with an accessor, and then perhaps your next() method would
throw or something. You probably never care about stuff like this, and
that's OK. Certain very rare users do have to care. Worse, your JS
engine's JIT does have to care.

-   The statement `return {value: v, done: false};` can't fail,
whereas `cachedObject.value = v` can fail, in the unlikely cases
described above, or can trigger a setter, and therefore may require
your JS engine to check something each time you do it. That's extra
work and it could slow things down.

-   The JS engine might be smart enough (if not now, then a year down
the road) to optimize away the temporary object created by `return
{value: v, done: false};`. If it does, then using a new object is
probably better for your JS engine's optimizer, because getting .value
or .done off of that object is *guaranteed* to produce `v` and
`false`, respectively, with no side effects and no possibility of
triggering any getters, setters, proxy traps, etc.

-j

On Sat, Feb 28, 2015 at 4:52 PM, Mark Volkmann
 wrote:
> I know there was a discussion about this recently, but I don't recall seeing 
> a reason why it would be problem for a custom iterator to return the same 
> object over and over with different values for the value and done properties. 
> I tried this in some sample code using Traceur and Babel and it works fine. 
> What are the potential problems with doing that?
>
> ---
> R. Mark Volkmann
> Object Computing, Inc.
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Automatic iterator.return() in contexts other than for and yield*

2015-01-15 Thread Jason Orendorff
On Wed, Jan 14, 2015 at 2:10 PM, Allen Wirfs-Brock
 wrote:
> Yes, there are still a couple of bugs related to this that I hope to get to 
> before the ES6 spec is totally locked down.

Great! Thanks for the quick response.

(I felt bad posting about it because I know it's come up before; but I
couldn't figure out the magic word to search for: "iterator",
"return", "for", "of", "exception" are all too common. Maybe we should
invent search keywords for each of these issues, as they come up. This
one can be #breakupprotocol. Would work in bugzilla too, if someone
cared to annotate...)

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Automatic iterator.return() in contexts other than for and yield*

2015-01-14 Thread Jason Orendorff
In some cases a `for` loop will implicitly call `iterator.return()`:

function gen() {
try { yield 0; }
finally { console.log("return was called"); }
}

for (let x of gen())
throw "fail";  // logs "return was called"

This is to support iterators that want to clean up after themselves.

Destructuring assignment doesn't call `.return()`:

let obj = {set x(v) { throw "fail"; }}
[obj.x] = gen();  // return() is not called

Neither do the Map/Set/WeakMap/WeakSet constructors:

class MySet extends Set {
add(v) { throw "fail"; }
}

let m = new MySet(gen());  // return() is not called

Anyone remember the rationale for this? It seems like we should have
just one iteration protocol, and it should be "what `for` loops do",
including `iterator.finish()`. The collection constructors should be
as mannerly as `for`, right?

Anyone remember the reasoning? Is it something to consider changing in ES7?

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Add Reflect.isConstructor and Reflect.isCallable?

2014-12-19 Thread Jason Orendorff
Having said that, I do think Reflect.isCallable and isConstructor
would be a fine addition to ES7. These places where we check if an
internal method exists feel like a sort of secret-handshake part of
the MOP; we should expose them.

Any objections?

Would someone please add it to the agenda for the next meeting?

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Add Reflect.isConstructor and Reflect.isCallable?

2014-12-19 Thread Jason Orendorff
On Tue, Dec 16, 2014 at 3:05 PM, Tom Schuster  wrote:
> Hello,
>
> right now there is no way in normal JS code to replicate the IsConstructor
> check defined in 7.2.4.

function isConstructor(obj) {
var p = new Proxy(obj, {construct() { return p; }});
try {
new p;
} catch (exc) {
return false;
}
return true;
}

This works by exposing the code in 9.5.15 ProxyCreate that's more or
less equivalent to IsConstructor.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: What would a 1JS-friendly strict mode look like?

2014-12-19 Thread Jason Orendorff
AK> I think we should either deprecate one of the modes, or officially
support multiple modes and provide a method to switch between them.

MM> Feel free to consider sloppy mode deprecated. I do.

CP> Well sure, but unfortunately it’s not going to just disappear :(

MM> See how much good deprecating it did?

...and, scene.

If I had a nickel for every time a conversation about web standards
went exactly like this, I would be All Set For Lunch. For weeks.

:)

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Removal of WeakMap/WeakSet clear

2014-12-09 Thread Jason Orendorff
On Thu, Dec 4, 2014 at 6:58 AM, David Bruant  wrote:
> Sometimes you call functions you don't have written and pass arguments to
> them. WeakMaps are new, but APIs will have functions with WeakMaps as
> arguments. I don't see what's crazy. It'd be nice if I don't have to review
> all NPM packages I use to make sure they dont use .clear when I pass a
> weakmap.

...Under what circumstance would you see yourself doing that? Do you
review all the code in NPM packages you use now?

Maybe you look at the source when there's a bug. So is calling
.clear() on an argument that's not supposed to be modified a
particularly likely bug somehow?

> If you don't want to pass the WeakMap directly, you have to create a new
> object "just in case" (cloning or wrapping) which carries its own obvious
> efficiency. Security then comes at the cost of performance while both could
> have been achieved if the same safe-by-default weakmap can be shared.

This is some rhetorical sleight of hand. Logic can't support any
meaning of "safe" here except "safe from clear (and only clear)". But
that's not the only or the most interesting mischief a function with a
reference to a WeakMap can get up to. set() and delete() are much more
interesting.

> We know ambiant authority is a bad thing, examples are endless in JS.

This much I agree with, and I think it's your best framing of the
question so far, but...

> WeakMap.prototype.clear is ambiant authority.

Here you're just asserting your conclusion. I don't see it as ambient
authority. It can only operate on the object you pass to it.

> I would return the question: can you demonstrate there are no such scenario?

It's hard to prove a negative, but certainly the same technique which
JS programmers already use to avoid having their objects mutated in
unwanted ways also works great with WeakMaps: don't pass around direct
references to them. And I can certainly demonstrate that removing
WeakMap#clear does *not* make it "safe by default" to pass a WeakMap
you care about to bad code.

I think a .freeze() or .frozenCopy() method would be a productive way
of getting the sort of guarantee you're interested in. Immutable data
structures might be even better.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Removal of WeakMap/WeakSet clear

2014-12-09 Thread Jason Orendorff
On Wed, Dec 3, 2014 at 3:54 PM, David Bruant  wrote:
>> There's something important that's implicit in this argument that I
>> still don't have yet. If you were using literally any other data
>> structure, any other object, passing a direct reference to it around
>> to untrusted code would not only be dumb, but obviously something the
>> ES spec should not try to defend against. Right? It would be goofy.
>
> Object.freeze and friends were added to the ES spec for the very purpose of
> being able to pass direct reference to an object and defend against unwanted
> mutations. à propos d'une
> Is Object.freeze goofy?

So you're saying it's *not* a security thing; you have no particular
threat model in mind. Hmm.

I really have trouble making sense of this, David. This line of
reasoning would make sense if you were arguing for (a) really
supporting immutable data structures in the stdlib; or (b) adding a
freeze() method on all the stdlib collections; or perhaps (c) making
Object.freeze somehow apply to the internal data in the new stdlib
collections. In fact all those things sound nice.

But as it stands we're talking about one mutation method on a kind of
object that already has a bunch of other mutation methods that you're
apparently OK with. I don't get it. I thought it had to do with the
invariant we were discussing before, and that's why I asked why that
particular invariant is useful... and then you didn't mention it at
all in your response.

> The ability to clear any WeakMap anytime needs to be equally justified in my
> opinion. I'm curious about plausible use cases.

Clearing a data structure is useful when your data structure is a
cache; WeakMaps are particularly useful for caches, as they do not
keep the keys in memory.

Consistency with the Map API is a separate justification. A program
migrating from Maps to WeakMaps might quite naturally end up wanting
WeakMap.prototype.clear().

> What about making 'clear' an own property of weakmaps and make it only
> capable of clearing the weakmap it's attached to?

I can't tell what this is meant to achieve.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Removal of WeakMap/WeakSet clear

2014-12-09 Thread Jason Orendorff
On Mon, Dec 8, 2014 at 3:46 PM, Tab Atkins Jr.  wrote:
> On Thu, Dec 4, 2014 at 9:46 PM, Katelyn Gadd  wrote:
>> I'm surprised to hear that JS runtimes don't necessarily have ways to
>> 'hash' a given JS value [...]
>
> JS has maps/sets that take objects natively, hiding any details about
> how a mutable object is tracked/stored as keys or values, so there's
> never been any need for such a thing.

It's not rare to want a hashmaps with compound keys. In current JS
there's no convenient, efficient way to make such a hash. If value
types are still happening, they might solve that problem.

> Explicitly exposing hash codes
> is leaking implementation details into the user-facing API.

This is certainly true and (afaik) the reason we haven't exposed this
kind of feature so far.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Removal of WeakMap/WeakSet clear

2014-12-03 Thread Jason Orendorff
On Wed, Dec 3, 2014 at 9:04 AM, David Bruant  wrote:
> A script which builds a weakmap may legitimately later assume the weakmap is
> filled. However, passing the weakmap to a mixed-trusted (malicious or buggy)
> script may result in the weakmap being cleared (and break the assumption of
> the weakmap being filled and trigger all sorts of bugs). Like all dumb
> things, at web-scale, it will happen.

OK. I read the whole thing, and I appreciate your writing it.

There's something important that's implicit in this argument that I
still don't have yet. If you were using literally any other data
structure, any other object, passing a direct reference to it around
to untrusted code would not only be dumb, but obviously something the
ES spec should not try to defend against. Right? It would be goofy.
The language just is not that hardened. Arguably, the point of a data
structure is to be useful for storing data, not to be "secure" against
code that **has a direct reference to it**. No?

So what's missing here is, I imagine you must see WeakMap, unlike all
the other builtin data structures, as a security feature.
Specifically, it must be a kind of secure data structure where
inserting or deleting particular keys and values into the WeakMap does
*not* pose a threat, but deleting them all does.

Can you explain that a bit more?

I see the invariant you're talking about, I agree it's elegant, but to
be useful it also has to line up with some plausible security use case
and threat model.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Removal of WeakMap/WeakSet clear

2014-12-03 Thread Jason Orendorff
On Wed, Dec 3, 2014 at 8:35 AM, Andreas Rossberg  wrote:
> (Back to the actual topic of this thread, you still owe me a reply
> regarding why .clear is bad for security. ;) )

I'd like to hear this too, just for education value.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Removal of WeakMap/WeakSet clear

2014-11-29 Thread Jason Orendorff
On Thu, Nov 27, 2014 at 8:58 AM, Andrea Giammarchi
 wrote:
> On Thu, Nov 27, 2014 at 2:44 PM, Andreas Rossberg 
> wrote:
>> Well, there is no functionally correct polyfill for WeakMaps that is
>> actually weak, regardless of .clear.
>
> Please bear with me so I understand your point: if you have `o1` and `o2`
> and `o1.link = o2;`, wouldn't `o2` be "free" once `o1` is not referenced
> anymore ?

Yes, but consider the other way around: o1 is still referenced, but
the WeakMap is not.

Under a polyfill, o2 would still be kept alive, even though per spec
there's not supposed to be any way to access it.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


String objects should be ordinary

2014-11-20 Thread Jason Orendorff
String objects are exotic:

http://people.mozilla.org/~jorendorff/es6-draft.html#sec-string-exotic-objects

Suppose we make them ordinary. No change in behvaior: we can make
StringCreate define all the indexed properties on every String object
as it's created, right?

Wouldn't that be better?

It seems like what these sections are trying to achieve is
conceptually simple, and expressible in terms of ordinary properties,
and so the spec should just say that... I could be missing something
though.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Map: filter/map and more

2014-10-06 Thread Jason Orendorff
On Mon, Oct 6, 2014 at 1:34 PM, Domenic Denicola
 wrote:
> This is iterables vs. iterators IMO. Iterators are inherently stateful and 
> I'd expect anything that uses them to consume them, even something named 
> "map". Iterables of course would not be.

I agree. It's inherent in the python-like design we're using for iteration.

It is not so jarring in practice, even for people with the classical
training to recognize what a farce it is. :) Many uses of itertools in
python, though blatantly stateful in implementation and operation,
still "feel" functional, because the iterator being consumed is a
temporary, something like mydict.iterkeys(). The mutation isn't
observable if there's no other reference to the iterator object.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Array.prototype.contains solutions

2014-10-01 Thread Jason Orendorff
I'd love to be able to get rid of SHADOWABLE, actually! I just
recently found out we can do it with a little rearranging. Extra
state-space in property attributes is unavoidable complexity for us.
My own preference would be not to standardize it. :)

There's also the [Replaceable] attribute in WebIDL, which arises from
similar compatibility needs. It's implemented as a setter that
redefines the property being set.

This is a bad bunch of options. I think renaming ("hasValue"?) is
probably least-worst, followed by waiting a year and trying again.

-j


On Wed, Oct 1, 2014 at 1:50 PM, Brendan Eich  wrote:
> Claude Pache wrote:
>>
>> The more I consider the issue, the more I think that the most elegant
>> solution is to complete data properties with an additional "overridable"
>> attribute, whose purpose is to refine the meaning of the "writable"
>> attribute in the manner sketched below (in opposition of having an
>> @@unscopables-like hack).
>
>
> A new attribute, per property, is safer in general (backward compatibility)
> than a per-object flag. A per-object list seems an obtuse way to encode an
> attribute, and I am quite sure implementations would prefer an attribute.
>
>> At first glance, I expect that the addition of such an attribute should
>> not trigger much BC issues, but that needs to be examined more closely.
>
>
> If it's opt-in, e.g. we define Array.prototype.contains with [[Overridable]]
> among its attributes, then at least MooTools works.
>
> What could break? Code that did not expect 'contains' to exist on
> Array.prototype, but did expect assigning to someArray.contains would make a
> non-enumerable and/or non-own property. That would seem like nonsense or
> broken code, but it could exist for some name and prototypal relation,
> you're right.
>
> Only way to find out is to implement and test at scale.
>
> It would be good to hear from implementors on the idea of an [[Overridable]]
> attribute. SpiderMonkey has something similar but more restricted (see
> http://dxr.mozilla.org/mozilla-central/source/js/src/vm/Shape.h?from=SHADOWABLE&case=true#1013).
>
> /be
>
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Throwing errors on mutating immutable bindings

2014-10-01 Thread Jason Orendorff
I think there is a way that the error could occur at runtime even in
all-strict-mode code: when a new const is added at toplevel in a
second script.


  "use strict";
  function f(value) { x = value; }


  "use strict";
  const x = 0;
  f(1);


-j


On Wed, Oct 1, 2014 at 11:15 AM, Allen Wirfs-Brock
 wrote:
>
> On Oct 1, 2014, at 9:05 AM, Mark S. Miller wrote:
>
> Good point. If we can require all such assignments to be rejected
> statically, why is a runtime assignment to a const variable even possible?
> Can't we just assert that this cannot occur?
>
>
> The runtime cases I meant are the ones you mentioned. Sloppy with or eval
> dynamically shadowing a sloppy a [[Set]] reference to a const binding.
> Can't be a early error, should be a runtime error.
>
> Allen
>
>
>
>
>
>
> On Wed, Oct 1, 2014 at 8:59 AM, Allen Wirfs-Brock 
> wrote:
>>
>>
>> On Oct 1, 2014, at 8:39 AM, Mark S. Miller wrote:
>>
>> ...
>>
>> I was with you until you got to the following point
>>
>> >
>> > If there is an intervening "with" or sloppy direct eval, then there is
>> > not a statically apparent assignment to a const variable. Since this can
>> > only occur in sloppy code anyway, it seems more consistent with the rest of
>> > sloppy mode for this failed assignment to be silent, rather than 
>> > dynamically
>> > throwing an error.
>> >
>>
>> const is a new kind of declaration unlike any declaration form that
>> previous existed in ES, so Ii don't think its handling introduces any legacy
>> consistency issues.  If somebody is using const, regard less of mode, they
>> pretty clearly expect assignments to any const bindings to be illegal.  And,
>> I don't think any body wants new silent failure errors, even in sloppy mode.
>> The most consistent thing is for runtime detected assignments to const
>> bindings to always be noisy errors.  Early where possible, at runtime in the
>> rest of the cases.
>>
>> Allen
>>
>
>
>
> --
> Cheers,
> --MarkM
>
>
>
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Having a non-enumerable Array.prototype.contains may not be web-compatible

2014-09-30 Thread Jason Orendorff
On Tue, Sep 30, 2014 at 5:35 PM, Andrea Giammarchi
 wrote:
> I'm personally against unmaintained code and/or websites but here it's not
> ES7 breaking the web, it's a library already broken (somehow) due native
> prototype pollution without a mechanism to prevent these, apparently
> historically known, problems.

Either way, you're telling me I should ship a browser that chokes on
thousands of web sites that work fine today. That would be bad for our
users, so I'm not planning on doing that.

> it is also already patched and it's also a small fix.

The 6.5% of existing web sites using JS libraries that use MooTools
have not been "already patched". Patching 3.5 million web sites is not
a "small fix" in any relevant sense. It simply will not be done
thoroughly or soon.

> If sites and developers have no reason to update code 'cause ES7 cannot
> release until they'll change a file ... why would they anyway.

Yes. You have correctly identified incentives as a problem.

That does not constitute a reductio proof that browser vendors must
ignore their users' interests and break the web. "Reductio ad
the-world-is-not-as-I-wish-it-to-be" is not a thing.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Having a non-enumerable Array.prototype.contains may not be web-compatible

2014-09-30 Thread Jason Orendorff
On Tue, Sep 30, 2014 at 1:45 PM, Michał Wadas  wrote:
> Bug in MooTools is not a reason to make any method of Array.prototype
> enumerable.

Well -- true, that would break even more sites.

We're backing out Array#contains() for now. It's disappointing to me
personally -- that was a volunteer contribution. In the long run,
perhaps renaming it is the best course? :-\

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Toplevel 'let' binding can be left permanently uninitialized after an error

2014-09-30 Thread Jason Orendorff
On Tue, Sep 30, 2014 at 12:00 PM, Rick Waldron  wrote:
> My original response questions were poorly asked. I understand the TDZ
> semantics, but I couldn't reproduce anything meaningful from your original
> example, because I don't have the SpiderMonkey build that includes the let
> updates (presumably Nightly doesn't either, because none of these can be
> reproduced there).

SpiderMonkey doesn't conform to the draft spec yet. We implemented TDZ
in functions, but not at toplevel. 'const' isn't lexical yet. There's
a lot more work to do.

> I'm trying to understand when/where/why/how the original
> example could happen and what the potential consequences are in terms of
> practical application.

Purely hypothetical for us, for now. It came up on IRC. Some engineers
were discussing the breaking changes we're going to have to make.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Toplevel 'let' binding can be left permanently uninitialized after an error

2014-09-30 Thread Jason Orendorff
I just realized this has an unfortunate implication for REPLs. Suppose
you make this typo:

js> let x = Math.cso(a)// oops, TypeError, should be Math.cos

Now x is irreparably hosed in your REPL. That seems bad.

I guess we can fix this by making the REPL bend the rules of the
language. But this is rather hard to do for REPLs implemented in JS.
Maybe the rules should just be a little more forgiving.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Toplevel 'let' binding can be left permanently uninitialized after an error

2014-09-30 Thread Jason Orendorff
On Mon, Sep 29, 2014 at 4:14 PM, Rick Waldron  wrote:
> Can you clarify "write"? Does this mean assignment?

Yes.

> Why would assignment throw?

Assigning to an uninitialized variable is an error in ES6. A
let-binding is initialized when its declaration is evaluated. So this
is OK:

let x;  // no Initializer, so it's initialized to undefined
console.log(x);  // logs undefined

but this is not:

init();
let answer;
function init() {
answer = 42;  // throws ReferenceError
}

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Maximally minimal stack trace standardization

2014-09-29 Thread Jason Orendorff
On Mon, Sep 29, 2014 at 4:06 PM, Allen Wirfs-Brock
 wrote:
> On Sep 29, 2014, at 1:41 PM, Jason Orendorff wrote:
>> Function.prototype.apply, Function.prototype.call, and Reflect.apply
>> currently call PrepareForTailCall. Is this a bug?
>
> No, I don't believe so.  Built-ins (whether implemented in ES or native) are 
> specified to have an "execution context".

Oh, I see! Thanks. (This is specified in 9.3.1 [[Call]], for anyone
following along.)

But in this case, the spec already has some non-ECMAScript functions
performing tail calls, so now I am at a loss as to what your earlier
line to Brendan could mean:

> I can't imagine what you would want be to try to say about non-EMCAScript 
> functions. Their internal "call" semantics is determined by the semantics of 
> their implementation language.

It seems like to the full extent that the current draft manages to
constrain Function.prototype.call, it could constrain bound functions
too.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Maximally minimal stack trace standardization

2014-09-29 Thread Jason Orendorff
On Mon, Sep 29, 2014 at 3:02 PM, Allen Wirfs-Brock
 wrote:
> I can't imagine what you would want be to try to say about non-EMCAScript
> functions. Their internal "call" semantics is determined by the semantics of
> their implementation language.

Function.prototype.apply, Function.prototype.call, and Reflect.apply
currently call PrepareForTailCall. Is this a bug?

I can see that the current language in 14.6.3 PrepareForTailCall only
covers "tail position calls" and "resources associated with the
currently executing function execution context", but what's wrong with
copying that sentence into 19.2.3.3 and changing it to refer to "the
internal method call in the last step of the above algorithm" and
"resources associated with the current call to
Function.prototype.call"?

The spec constrains the behavior of builtins in all kinds of ways,
regardless of what language they're written in. I don't understand
what is special about stack space usage that makes it off-limits.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Toplevel 'let' binding can be left permanently uninitialized after an error

2014-09-29 Thread Jason Orendorff
SpiderMonkey hacker Jeff Walden noticed this. Consider a web page that
loads and runs this script:

throw 0;
let x;

This leaves the binding 'x' uninitialized. There's no way to get rid
of a lexical binding or to initialize it later. The binding is just
permanently hosed; any attempt to read or write it will throw.

That by itself isn't necessarily a problem. I've never written a web
page where I wanted to recover after a toplevel script threw an
exception (or timed out). But I dunno, the impossibility of any kind
of self-healing here gives me pause.

No action required on my account; I'm posting this because we were all
surprised and it seems vaguely unaesthetic.

-j
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


  1   2   3   4   5   >