Re: try/catch/else

2018-02-13 Thread Alan Plum
Oops, you're right. I agree that `else` might not be the best keyword for this 
all things considering.

On Tue, Feb 13, 2018, at 1:48 PM, T.J. Crowder wrote:
> On Tue, Feb 13, 2018 at 12:37 PM, Alan Plum  wrote:
> > Not quite.
> 
> You appear to have missed my message three minutes later, after I'd
> realized that:
> https://esdiscuss.org/topic/try-catch-else#content-16
> 
> -- T.J. Crowder
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: try/catch/else

2018-02-13 Thread T.J. Crowder
On Tue, Feb 13, 2018 at 12:37 PM, Alan Plum  wrote:
> Not quite.

You appear to have missed my message three minutes later, after I'd
realized that:
https://esdiscuss.org/topic/try-catch-else#content-16

-- T.J. Crowder
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: try/catch/else

2018-02-13 Thread Alan Plum
Not quite. If the `else` (or `nocatch`, whatever) block throws, it would
bypass the `catch` block but still hit the `finally` block the same way
an exception in the `catch` block would:
* if `a` doesn't throw: a, b, d
* if `a` throws: a, c, d
* if `b` throws: a, b, d
* if `a` and `c` throw: a, c, d

This is analogous to this promise equivalent:

```
console.log("a");
a()
.then(() => {
console.log("b");
return b();
}, () => {
console.log("c");
return c();
})
.finally(() => {
console.log("d");
})
```

(note the use of both arguments to `then`)

Your reading wouldn't really provide anything that can't be done by
simply moving the else block's content into the try block.
--
  Alan Plum
  m...@pluma.io



On Tue, Feb 13, 2018, at 12:54 PM, T.J. Crowder wrote:
> On Tue, Feb 13, 2018 at 11:30 AM, Isiah Meadows
>  wrote:> >
> > If you did `else` before `catch`/`finally`, that'd solve your
> > problem. ;-)> >
> > The catch with `finally` (no pun intended) is this: does/should it
> > execute *before* or *after* else?
> 
> Logically it makes sense `finally` would be after, so putting the
> `else` after `try` and before `catch`/`finally` makes sense for that
> reason as well:> 
> ```js
> try {
> console.log('a');
> a();
> } else {
> console.log('b');
> b();
> } catch (e) {
> console.log('c');
> c();
> } finally {
> console.log('d');
> d();
> }
> ```
> 
> Then
> 
> * If `a` doesn't throw: a, b, d.
> * If `a` throws: a, c, d.
> * If `b` throws: a, b, c, d
> * If `a` and `c` both throw: a, c, d
> * If `b` and `c` both throw: a, b, c, d
> 
> `else` doesn't make sense in English terms anymore, though. `then`
> would though, and on first blush would be consistent with what the
> promise version of this would look like:> 
> ```js
> console.log("a");
> a()
> .then(() => {
> console.log("b");
> return b();
> })
> .catch(() => {
> console.log("c");
> return c();
> })
> .finally(() => {
> console.log("d");
> })
> ```
> 
> -- T.J. Crowder

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


Re: try/catch/else

2018-02-13 Thread T.J. Crowder
On Tue, Feb 13, 2018 at 11:54 AM, T.J. Crowder
 wrote:
>
> Then
>
> * If `a` doesn't throw: a, b, d.
> * If `a` throws: a, c, d.
> * If `b` throws: a, b, c, d
> * If `a` and `c` both throw: a, c, d
> * If `b` and `c` both throw: a, b, c, d

Gah, I forgot that you don't want the `else` block subject to the
`catch`. So ignore that, and it no longer resembles the promise
version.

Don't like `else` in front of `catch` if exceptions from the code in
the `else` isn't caught.

-- T.J. Crowder
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: try/catch/else

2018-02-13 Thread T.J. Crowder
On Tue, Feb 13, 2018 at 11:30 AM, Isiah Meadows 
wrote:
>
> If you did `else` before `catch`/`finally`, that'd solve your problem. ;-)
>
> The catch with `finally` (no pun intended) is this: does/should it
> execute *before* or *after* else?

Logically it makes sense `finally` would be after, so putting the `else`
after `try` and before `catch`/`finally` makes sense for that reason as
well:

```js
try {
console.log('a');
a();
} else {
console.log('b');
b();
} catch (e) {
console.log('c');
c();
} finally {
console.log('d');
d();
}
```

Then

* If `a` doesn't throw: a, b, d.
* If `a` throws: a, c, d.
* If `b` throws: a, b, c, d
* If `a` and `c` both throw: a, c, d
* If `b` and `c` both throw: a, b, c, d

`else` doesn't make sense in English terms anymore, though. `then` would
though, and on first blush would be consistent with what the promise
version of this would look like:

```js
console.log("a");
a()
.then(() => {
console.log("b");
return b();
})
.catch(() => {
console.log("c");
return c();
})
.finally(() => {
console.log("d");
})
```

-- T.J. Crowder
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: try/catch/else

2018-02-13 Thread Alan Plum
Going with python's semantics, finally should execute after else because else 
behaves analogous to catch. It's basically a "nocatch".

On Tue, Feb 13, 2018, at 12:30 PM, Isiah Meadows wrote:
> If you did `else` before `catch`/`finally`, that'd solve your problem. ;-)
> 
> The catch with `finally` (no pun intended) is this: does/should it
> execute *before* or *after* else?
> -
> 
> Isiah Meadows
> m...@isiahmeadows.com
> 
> Looking for web consulting? Or a new website?
> Send me an email and we can get started.
> www.isiahmeadows.com
> 
> 
> On Tue, Feb 13, 2018 at 4:48 AM, Alan Plum  wrote:
> > Yikes, thanks for pointing that out. I guess this could be resolved by 
> > having a lower precedence for `catch/else` than `if/else` or by enforcing 
> > the sequence `try/else/catch` (as `try` without `catch` or `finally` is a 
> > syntax error).
> >
> >
> > On Tue, Feb 13, 2018, at 2:06 AM, Waldemar Horwat wrote:
> >> On 02/08/2018 06:50, Alan Plum wrote:
> >> > I realise there is some ambiguity in using the else keyword for this 
> >> > (though I can't think of a meaningful opposite of "catch" either).
> >>
> >> Indeed.  You can't use 'else' without breaking existing behavior.  For 
> >> example:
> >>
> >> if (foo) try {...} catch (e) {...} else {...}
> >>
> >>  Waldemar
> > ___
> > 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: try/catch/else

2018-02-13 Thread Isiah Meadows
If you did `else` before `catch`/`finally`, that'd solve your problem. ;-)

The catch with `finally` (no pun intended) is this: does/should it
execute *before* or *after* else?
-

Isiah Meadows
m...@isiahmeadows.com

Looking for web consulting? Or a new website?
Send me an email and we can get started.
www.isiahmeadows.com


On Tue, Feb 13, 2018 at 4:48 AM, Alan Plum  wrote:
> Yikes, thanks for pointing that out. I guess this could be resolved by having 
> a lower precedence for `catch/else` than `if/else` or by enforcing the 
> sequence `try/else/catch` (as `try` without `catch` or `finally` is a syntax 
> error).
>
>
> On Tue, Feb 13, 2018, at 2:06 AM, Waldemar Horwat wrote:
>> On 02/08/2018 06:50, Alan Plum wrote:
>> > I realise there is some ambiguity in using the else keyword for this 
>> > (though I can't think of a meaningful opposite of "catch" either).
>>
>> Indeed.  You can't use 'else' without breaking existing behavior.  For 
>> example:
>>
>> if (foo) try {...} catch (e) {...} else {...}
>>
>>  Waldemar
> ___
> 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: try/catch/else

2018-02-13 Thread Alan Plum
Yikes, thanks for pointing that out. I guess this could be resolved by having a 
lower precedence for `catch/else` than `if/else` or by enforcing the sequence 
`try/else/catch` (as `try` without `catch` or `finally` is a syntax error).


On Tue, Feb 13, 2018, at 2:06 AM, Waldemar Horwat wrote:
> On 02/08/2018 06:50, Alan Plum wrote:
> > I realise there is some ambiguity in using the else keyword for this 
> > (though I can't think of a meaningful opposite of "catch" either).
> 
> Indeed.  You can't use 'else' without breaking existing behavior.  For 
> example:
> 
> if (foo) try {...} catch (e) {...} else {...}
> 
>  Waldemar
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: try/catch/else

2018-02-12 Thread Waldemar Horwat

On 02/08/2018 06:50, Alan Plum wrote:

I realise there is some ambiguity in using the else keyword for this (though I can't 
think of a meaningful opposite of "catch" either).


Indeed.  You can't use 'else' without breaking existing behavior.  For example:

if (foo) try {...} catch (e) {...} else {...}

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


Re: try/catch/else

2018-02-09 Thread Alan Plum
The idea isn't to make the second call's exceptions silent, it's not to catch them (i.e. let them propagate).On 9 Feb 2018 2:46 p.m., Augusto Moura  wrote:I see this operator quite confusing, in my opinion it's a best practice treat the functions (and errors) separately. If you want to ignore the second error you can even create a `silent` helper.```jsconst treatedShowSuggestions = (suggs) => {  try {    showSuggestions(suggs);  } catch (e) {    // treat error};try {  const suggestions = await fetchSuggestions();  treatedShowSuggestions(suggestions);} catch (e) {  alert('Failed to load suggestions');}```or```jsconst silent = (fn) => {  try {    fn();  } catch (e) {}};try {  const suggestions = await fetchSuggestions();  silent(() => showSuggestions(suggestions));} catch (e) {  alert('Failed to load suggestions');}```This isn't even a workaround, it's just the right approach for what you want. If you wanna to evict the separated functions you can just inline the try/catch in the main function.-- Augusto Moura
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: try/catch/else

2018-02-09 Thread Augusto Moura
I see this operator quite confusing, in my opinion it's a best practice
treat the functions (and errors) separately. If you want to ignore the
second error you can even create a `silent` helper.

```js
const treatedShowSuggestions = (suggs) => {
  try {
showSuggestions(suggs);
  } catch (e) {
// treat error
};

try {
  const suggestions = await fetchSuggestions();
  treatedShowSuggestions(suggestions);
} catch (e) {
  alert('Failed to load suggestions');
}
```
or
```js
const silent = (fn) => {
  try {
fn();
  } catch (e) {}
};

try {
  const suggestions = await fetchSuggestions();
  silent(() => showSuggestions(suggestions));
} catch (e) {
  alert('Failed to load suggestions');
}
```

This isn't even a workaround, it's just the right approach for what you
want. If you wanna to evict the separated functions you can just inline the
try/catch in the main function.
-- 
Augusto Moura
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: try/catch/else

2018-02-09 Thread Claude Pache


> Le 9 févr. 2018 à 00:19, Peter van der Zee  a écrit :
> 
>>> On Thu, Feb 8, 2018 at 10:13 AM, Claude Pache 
>>> wrote:
 
 What about the following pattern (labelled block + break)?
 
 ```js
 processSuggestions: {
let suggestions;
try {
  suggestions = await fetchSuggestions();
} catch (e) {
  alert('Failed to load suggestions');
  break processSuggestions;
}
showSuggestions(suggestions);
 }
 ```
> 
> I don't mean to hijack this tread. I'm mostly curious why you opt or
> even suggest for that over putting it in a function and an early
> return? Like;
> 
> ```
> function processSuggestions() {
>  let suggestions
>  try {
>suggestions = await fetchSuggestions();
>  } catch (e) {
>return alert('Failed to load suggestions');
>  }
>  showSuggestions(suggestions);
> }
> ```
> 
> This is almost identical, especially the way the example was written.
> I understand the differences, I don't think they're a problem for by
> far most cases where you'd want this.

A function is strictly more complex than a block because you have to define it 
first, then to invoke it. As a consequence, it is more code to write and read. 
Unless you have a good reason for it (which is not suggested by the original 
problem), why would you prefer the more complex way?

—Claude

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


Re: try/catch/else

2018-02-09 Thread Alan Plum
I think the best argument for having try/catch/else is that it makes it trivial 
to translate promises into async/await. Consider this:

```
let result = a()
.then(b, c)
.catch(d);
```

If we want to translate this 1:1 to try/catch/else in an async function we'll 
end up with something like this:

```
try {
  let x, y;
  try {
x = await a();
  } catch (e) {
y = await c(e);
  } else {
y = await b(x);
  }
  return y;
} catch (e) {
  return await d(e);
}
```

Doing this without `else` would require one of the workarounds suggested 
upthread.

On Thu, Feb 8, 2018, at 7:13 PM, Claude Pache wrote:
> What about the following pattern (labelled block + break)?
> 
> ```js
> processSuggestions: {
> let suggestions;
> try {
>   suggestions = await fetchSuggestions();
> } catch (e) {
>   alert('Failed to load suggestions');
>   break processSuggestions;
> }
> showSuggestions(suggestions);
> }
> ```
> 
> —Claude
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: try/catch/else

2018-02-08 Thread Peter van der Zee
>> On Thu, Feb 8, 2018 at 10:13 AM, Claude Pache 
>> wrote:
>>>
>>> What about the following pattern (labelled block + break)?
>>>
>>> ```js
>>> processSuggestions: {
>>> let suggestions;
>>> try {
>>>   suggestions = await fetchSuggestions();
>>> } catch (e) {
>>>   alert('Failed to load suggestions');
>>>   break processSuggestions;
>>> }
>>> showSuggestions(suggestions);
>>> }
>>> ```

I don't mean to hijack this tread. I'm mostly curious why you opt or
even suggest for that over putting it in a function and an early
return? Like;

```
function processSuggestions() {
  let suggestions
  try {
suggestions = await fetchSuggestions();
  } catch (e) {
return alert('Failed to load suggestions');
  }
  showSuggestions(suggestions);
}
```

This is almost identical, especially the way the example was written.
I understand the differences, I don't think they're a problem for by
far most cases where you'd want this.

That said I wouldn't mind seeing try/catch/else/finally because the
pattern(s) above still leads to awkward code in the real world.

One could bikeshed on how "else" implies the attempt ("try") to have
failed rather than succeeded. On the other hand making it
try/then/catch/finally is also going to be confusing so whatever :)

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


Re: try/catch/else

2018-02-08 Thread Isiah Meadows
I honestly wish engines (read: V8) didn't jave so much issue optimizing
that. But yes, it's a very useful pattern.

On Thu, Feb 8, 2018, 14:35 Mark Miller  wrote:

> Hi Claude, that's nice. Whenever I faced this issue I always turned to the
> boolean flag variable. But this is strictly better. I expect to use it from
> now on. Thanks!
>
>
> On Thu, Feb 8, 2018 at 10:13 AM, Claude Pache 
> wrote:
>
>> What about the following pattern (labelled block + break)?
>>
>> ```js
>> processSuggestions: {
>> let suggestions;
>> try {
>>   suggestions = await fetchSuggestions();
>> } catch (e) {
>>   alert('Failed to load suggestions');
>>   break processSuggestions;
>> }
>> showSuggestions(suggestions);
>> }
>> ```
>>
>> —Claude
>> ___
>> es-discuss mailing list
>> es-discuss@mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>>
>
>
>
> --
>   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: try/catch/else

2018-02-08 Thread Mark Miller
Hi Claude, that's nice. Whenever I faced this issue I always turned to the
boolean flag variable. But this is strictly better. I expect to use it from
now on. Thanks!


On Thu, Feb 8, 2018 at 10:13 AM, Claude Pache 
wrote:

> What about the following pattern (labelled block + break)?
>
> ```js
> processSuggestions: {
> let suggestions;
> try {
>   suggestions = await fetchSuggestions();
> } catch (e) {
>   alert('Failed to load suggestions');
>   break processSuggestions;
> }
> showSuggestions(suggestions);
> }
> ```
>
> —Claude
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>



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


Re: try/catch/else

2018-02-08 Thread Claude Pache
What about the following pattern (labelled block + break)?

```js
processSuggestions: {
let suggestions;
try {
  suggestions = await fetchSuggestions();
} catch (e) {
  alert('Failed to load suggestions');
  break processSuggestions;
}
showSuggestions(suggestions);
}
```

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


Re: try/catch/else

2018-02-08 Thread Alan Plum
Sounds good in principle but I think the name is misleading.

Actually try/catch/else is the synchronous equivalent of
tryFn().then(elseFn, catchFn) but then has other implications (it
returns a new promise and the then method actually takes two functions).
Calling it then would imply it's equivalent to
tryFn().then(thenFn).catch(catchFn) which is actually just the same as
the first example, not the try/catch/else.
I also think having the else after the catch makes the intention clearer
(just like finally comes after catch and else).

On Thu, Feb 8, 2018, at 4:20 PM, Michael Luder-Rosefield wrote:
> Well, since promise.then(/**blah**/).catch(/**blah**/) is already a
> thing, why not stick with that?> 
> try {
>  // blah
> } then(val) {
>   // blah
> } catch {
>  // blah
> } finally {
>  // blah
> }
> 
> I added `val` to the then since we might want to pass something from
> `try` to it, just as promises do. Best way to do that might be for
> `try` to act as an expression block and implicitly return the last
> thing in it.> 
> On Thu, 8 Feb 2018 at 14:50 Alan Plum  wrote:
>> __
>> Hi everyone,
>> 
>> I'm hoping this is the right medium to ask this but I would like to
>> propose a language feature called try/catch/else.>> 
>> Conditional try/catch seems to be all the rage right now but in many
>> cases the problem it really wants to solve seems to be code like the
>> following:>> 
>> try {
>>   const suggestions = await fetchSuggestions();
>>   showSuggestions(suggestions);
>> } catch (e) {
>>   alert('Failed to load suggestions');
>>   // Oops, we also swallow errors from showSuggestions
>> }
>> // now do something else
>> 
>> Having a more fine-grained catch wouldn't necessarily help here
>> because both functions might throw the same kind of error but what
>> we're really interested in is discerning the *source* of the error.
>> So instead some people resort to something like this:>> 
>> let suggestions;
>> try {
>>   suggestions = await fetchSuggestions();
>> } catch (e) {
>>   alert('Failed to load suggestions');
>>   return;
>> }
>> showSuggestions(suggestions);
>> // now do something else - unless we failed to load
>> 
>> Note how we're forced to add a return to explicitly abort the control
>> flow. Unlike the change from const to let this isn't something an IDE
>> would point out while refactoring, so this actually introduces
>> potential for bugs. If we don't actually want to bail out completely
>> this often leads to noisy status booleans (e.g. didNotThrow) or error-
>> prone checks (e.g. !suggestions is a bug if the async function really
>> didn't return anything).>> 
>> I'm not sure about other languages but Python has a solution for this
>> by adding an else clause:>> 
>> let suggestions;
>> try {
>>   suggestions = await fetchSuggestions();
>> } catch (e) {
>>   alert('Failed to load suggestions');
>> } else {
>>   showSuggestions(suggestions);
>> }
>> // now do something else
>> 
>> The semantics are pretty straightforward: if the try block did not
>> throw, the else block is executed next (before the finally block if
>> any). If the try block does throw, the else block is ignored (like a
>> conditional catch that doesn't match).>> 
>> I realise there is some ambiguity in using the else keyword for this
>> (though I can't think of a meaningful opposite of "catch" either).
>> There is also some overlap with conditional try/catch but I think
>> this language feature is useful even if conditional try/catch exists.>> 
>> 
>> Cheers,
>> 
>> Alan Plum
>> ___
>>  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: try/catch/else

2018-02-08 Thread Michael Luder-Rosefield
Well, since promise.then(/**blah**/).catch(/**blah**/) is already a thing,
why not stick with that?

try {
 // blah
} then(val) {
  // blah
} catch {
 // blah
} finally {
 // blah
}

I added `val` to the then since we might want to pass something from `try`
to it, just as promises do. Best way to do that might be for `try` to act
as an expression block and implicitly return the last thing in it.

On Thu, 8 Feb 2018 at 14:50 Alan Plum  wrote:

> Hi everyone,
>
> I'm hoping this is the right medium to ask this but I would like to
> propose a language feature called try/catch/else.
>
> Conditional try/catch seems to be all the rage right now but in many cases
> the problem it really wants to solve seems to be code like the following:
>
> try {
>   const suggestions = await fetchSuggestions();
>   showSuggestions(suggestions);
> } catch (e) {
>   alert('Failed to load suggestions');
>   // Oops, we also swallow errors from showSuggestions
> }
> // now do something else
>
> Having a more fine-grained catch wouldn't necessarily help here because
> both functions might throw the same kind of error but what we're really
> interested in is discerning the *source* of the error. So instead some
> people resort to something like this:
>
> let suggestions;
> try {
>   suggestions = await fetchSuggestions();
> } catch (e) {
>   alert('Failed to load suggestions');
>   return;
> }
> showSuggestions(suggestions);
> // now do something else - unless we failed to load
>
> Note how we're forced to add a return to explicitly abort the control
> flow. Unlike the change from const to let this isn't something an IDE would
> point out while refactoring, so this actually introduces potential for
> bugs. If we don't actually want to bail out completely this often leads to
> noisy status booleans (e.g. didNotThrow) or error-prone checks (e.g.
> !suggestions is a bug if the async function really didn't return
> anything).
>
> I'm not sure about other languages but Python has a solution for this by
> adding an else clause:
>
> let suggestions;
> try {
>   suggestions = await fetchSuggestions();
> } catch (e) {
>   alert('Failed to load suggestions');
> } else {
>   showSuggestions(suggestions);
> }
> // now do something else
>
> The semantics are pretty straightforward: if the try block did not throw,
> the else block is executed next (before the finally block if any). If the
> try block does throw, the else block is ignored (like a conditional catch
> that doesn't match).
>
> I realise there is some ambiguity in using the else keyword for this
> (though I can't think of a meaningful opposite of "catch" either). There is
> also some overlap with conditional try/catch but I think this language
> feature is useful even if conditional try/catch exists.
>
>
> Cheers,
>
> Alan Plum
> ___
> 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