Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Supporting ECMAScript 2015 #205

Closed
lemmaa opened this issue Jun 18, 2015 · 28 comments
Closed

Supporting ECMAScript 2015 #205

lemmaa opened this issue Jun 18, 2015 · 28 comments
Labels
discussion Ongoing discussion

Comments

@lemmaa
Copy link
Contributor

lemmaa commented Jun 18, 2015

The General Assembly of Ecma International has announced the approval of ECMA-262 6th edition.

Should we need to change our target to support ES6 immediately? or keep going to finish current target first?
Please share your opinion.
Thanks!

@lemmaa lemmaa added the discussion Ongoing discussion label Jun 18, 2015
@akosthekiss
Copy link
Member

I'd argue against re-defining our target unless we are also ready to change our schedule considerably. We are somewhere halfway (a bit better than that) to ES5.1 conformance. We know (and are determined) to reach the conformant status by end of summer/early fall, however I'm sure that ES6 conformance will need quite some extra work. If we change our target now, then we may have an engine at our original deadline which is neither ES5.1 nor ES6 conformant. This will postpone the applicability of JerryScript in real use cases, which can be risky IMHO. I'd suggest going with the original target and setting up a new schedule for reaching ES6 confirmance only after ES5.1 is reached (or very close to that).

@egavrin
Copy link
Contributor

egavrin commented Jun 18, 2015

Personally, I appreciate the idea of supporting the latest standard - it's very important from any point of view. But aligning our target with ES6 will definitely require to correct our schedule - it may take time:

  • this'd require to study new specification, which is almost 2 time bigger than previous one.
  • prepare detailed work plans for our sides and setup workshop to discuss them

I suppose that we'll clarify all plans only by the end of July.

Our current deadlines are very tight and I assume that within them we won't be able to support ES6 fully. If we are not able to reassess current deadline we should continue with our current plans.
Since our final deadline is end of August, I'd consider the following plan:

  • Fix our current deadlines to end of August as it was discussed and continues our activities
  • Immediately start investigation of ES6 and start preparation of workplans
  • Setup workshop at the end of July
    • to discuss our current achievements
    • to discuss ES6 implementation plan that will start since September
    • to define "preparation list" for ES6
  • At August, both parties will stabilize their solutions and prepare them for upcoming activity

@sand1k
Copy link
Contributor

sand1k commented Jun 18, 2015

I agree with @egavrin.
If deadlines are the same, ES5.1 should be finished first.
But we should start investigation of ES6 ASAP to reasonably estimate efforts for its implementation and be ready for supporting it. 'ES6 compliant' mark sounds good for marketing :)

@zherczeg
Copy link
Member

Perhaps we should not forget our other goals, such as memory consumption, performance, binary size. And I also have another goal in my mind: making Jerry a popular JS engine. Creating something which is valuable to others.

@ruben-ayrapetyan
Copy link
Contributor

I agree that it is great to add ES6 support, starting working on it after ES5.1 support would be completed.
Currently, we could start thinking over what need to be introduced / changed to support ES6.

@lemmaa
Copy link
Contributor Author

lemmaa commented Jun 19, 2015

@akiss77 @egavrin @sand1k @zherczeg @ruben-ayrapetyan, thank you for having good feedback.
I understand that we all have same opinion, including me.

First, we have to focus our original plan, implementing ES5.1, in schedule. And we also need to start investigation of ES6.

Then let's talk about investigation of ES6.
As of now, @egavrin suggested that workshop from end of July. Is it enough for everybody?
What else we can do? What else we must do?

@egavrin
Copy link
Contributor

egavrin commented Jun 21, 2015

@lemmaa since we're going to start optimize Jerry since July, we should take into account new language features and try to avoid engine modifications that may hardener further implementation. Some of them are briefly listed here:

What we shall do:

  • Designate a person who will examine the new standard (it can be me or @zherczeg)
    • This task is quite difficult, so most likely this person will not participate in active development for about 2-3 weeks
  • Designated person should prepare detailed list of changes with rough MM estimation per each chapter or change
  • Then we'll review the report and prepare more precise estimations
  • On the workshop we'll discuss implementation details and assign responsibilities

@kenchris
Copy link

kenchris commented Aug 6, 2016

I would say at least supporting Promises should be considered, as it is a requirement for most new Web APIs as defined by W3C, WHATWG etc. It is also heavily used by the Generic Sensor API which we would love to support node.js at some point, instead of just web browsers.

Wouldn't supporting "let" instead of just "var", potentially be able to improve memory usage?

@zherczeg
Copy link
Member

zherczeg commented Aug 6, 2016

Supporting promises is probably possible at some point.

Supporting let is very challenging but we might try to do it sometimes.. Lots of engine changes will be required, heavy binary size increase, memory consumption increase, performance drop is expected, so the costs might outweight the gain at the end. So this is not a high priority for us at the moment.

@zherczeg
Copy link
Member

zherczeg commented Aug 7, 2016

I think it is worth discussing the ""let" problem, because somebody might have a good idea to do it efficiently.

In ES5.1, you can simulate "let" in the following way:

// this is the same as: let a = f();
try {
  throw f();
} catch(a) {
}

The catch creates a new lexical environment, which only has one binding, the "a" symbol. This symbol shadows the "var a" symbol (if exists). Hence a new object is created and added it to the lexical environment, which consumes memory and makes resolving slower. You cannot really avoid this because:

function f() {
  var a = 5;
  g = function () { print(a); }
  {
    let a = 6;
    g();
    print(a);
  }
}

This prints 5 and 6.

The other problem is control flow. Statements such as try, with, and for-in create contexts which needs to be destroyed when these statements are finished. Furthermore break/continue/throw/return statements can also abort these contexts. This is done by context breaker gotos whose are much more costly than normal gotos.

Since try, etc. statements are rare, they don't really slow down Jerry at this moment. However, I would assume that people would use "let" much more frequently than those others which would add a lot of context management and would cause considerable slowdown. Telling people that you have "let" but don't use it does not makes much sense.

Hence there are two issues needs to be solved:

  • avoid creating extra lexical environments (extra memory for lexical objects, slower resolve)
  • increased context management costs (extra memory for contexts, creating/destroying them frequently lowers perofrmance)

And there is a third: we don't have AST and enough time to do complex code analysis. So the solution must be lightweight and must work with little available information.

Let is know if anybody has a clever idea. Otherwise I don't think it is worth supporting "let".

@kenchris
Copy link

kenchris commented Aug 7, 2016

try/catch might become more popular in ES2017 where async/await are expected for making common promise based code easier to write. This is already in Edge and Chrome (behind flags, I believe)

Btw, the best place to see what goes into future versions is here:

https://github.com/tc39/proposals/blob/master/finished-proposals.md

ES2016: http://www.ecma-international.org/ecma-262/7.0/
ES2017 (WIP): https://tc39.github.io/ecma262/

@kenchris
Copy link

As good async support is quite interesting for IoT (AIO might for instance be on another core, like on the Arduino 101), what I would like the most from > ES5.1 would be

  • promises
  • async/await, which probably depends on generators (can at least be emulated/polyfilled using it)

Did anyone look at how hard it would be supporting these?

@zherczeg
Copy link
Member

Even more interesting example for let:

function f() {
  var a = [];
  for (var i = 0; i < 5; i++) {
    let x = i;
    a[i] = function() { print(x); }
  }
  for (var i = 0; i < 5; i++)
    a[i]();
}
f()

This prints numbers from 0 to 4. Lexical environment magic.

I think the implementation difficulty depends on the standard. Does promises has ES5 implementation? If so, implementing it should not be too hard since no engine rework is needed. Generators require suspending execution which means the call stack needs to be saved (or they need a separate call stack allocator) somewhere. Nesting generators could have some interesting corner cases if the standard allows it. And also the combination of features could be interesting. E.g. with, eval, and function declaration is easy in theory but if you do:

with (obj) eval("res = function (){ return g; }");

Doing that properly is challenging. Mix this with declaring generators.

Anyway, these could be useful for long term plans. Probably will be challenging but not impossible.

@kenchris
Copy link

That seems a bit like magic indeed.

Promises were done before ES2015 and originally in the HTML/DOM spec and then moved to JS, so it should not depend on anything else, but they did introduce the notion of micro-tasks though.

http://www.ecma-international.org/ecma-262/7.0/#sec-promise-constructor
https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/

I don't think that I have ever seen any examples of nested generators, and eval is pretty much discouraged today :-)

http://www.2ality.com/2015/03/es6-generators.html

@kenchris
Copy link

kenchris commented Aug 10, 2016

By nesting do you mean

function* gen1() {
  yield 1;
  yield 2;
  yield 3;
}

function* gen2() { 
  var gen = gen1();
  var old = 1;
  for (var res = gen.next(); !res.done; res = gen.next()) {
    yield res.value;
    old = res.value;
  } 
}

That seems to work in Chrome

> var test = gen2();
undefined
> test.next()
Object {value: 1, done: false}
> test.next()
Object {value: 2, done: false}
> test.next()
Object {value: 6, done: false}
> test.next()
Object {value: undefined, done: true}

@zherczeg
Copy link
Member

Yes. Even if it is unlikely that people use such thing if we implement generators we need to support every possible corner case. This is the bulk of the work.

@kenchris
Copy link

kenchris commented Aug 10, 2016

But if this is to serve as the implementation of async/await (without exposing the generator support to devs) would that be the same amount of work?

The implementation of async/await on top of generators, can be seen here:

https://tc39.github.io/ecmascript-asyncawait/#desugaring

@zherczeg
Copy link
Member

Do you mean implement async without generators? That is probably possible. And later extend the implementation to support generators if needed.

@kenchris
Copy link

kenchris commented Aug 10, 2016

Yes, or just the parts of generators (without exposing it) that are needed in order to implement and expose async/await.

I expect that async/await will be enabled by default soon in most browsers and it will probably make promises even more popular, while making async code much easier to write and read.

I mean, 'let', generators etc and lot of other things in ES2015+ are pretty cool, but for IoT, the biggest pain point right now with JS is async code, which promises and async/await could really help with. That combined with newer Web APIs requiring promises and well as users asking for similar APIs across Web and Node.js, makes it a very welcome feature.

@zherczeg
Copy link
Member

function helper() {
  yield 1;
  yield 2;
  yield 3;
}

function* gen() { 
  helper();
}

var g = gen2(); 
print(g.next()); // Object { value: undefined, done: true }

It seems this is not working, which is great news, since generators can use the normal call stack when calling other functions. Only their own call frame needs to be allocated in the memory, which simplify heavily the complexity of this task. Is this true?

@kenchris
Copy link

kenchris commented Aug 11, 2016

I would say that is correct, YieldExpression : is only handled inside http://www.ecma-international.org/ecma-262/6.0/#sec-generator-function-definitions-runtime-semantics-evaluation

yield seems to be only allowed inside generator functions, but then of course in many places of the grammar, like return (a == b) ? yield a : ....

@zherczeg
Copy link
Member

Yes, yield is some kind of unary operator with a unique precedence (still much easier than the arrow operator, which requires look-ahead operation in an AST less parser).

Anyway at least we don't need to support cases where a generator calls a native function, and that calls a JS callback function, which yields something. This is a huge simplification. So we just need to allocate a call frame for the generator function only, and we can simply suspend the execution at the point of yield. This is quite easy to do in jerry.

So it is likely these two features can be implemented in jerry without much trouble. However it is still a lot of new code, so it definitely takes time.

@kenchris
Copy link

Yes, that is expected :-) but it would be very nice if you considered it next time you do plannings. Is JerryScript already 100% ES5.1 compliant?

@zherczeg
Copy link
Member

Yes, except internalization support. (Note: ES6 is not fully backward compatible)

@brianjjones
Copy link

Hi,

I was curious if there were plans to eventually implement ES6 module support in JerryScript?

@lygstate
Copy link
Contributor

I suggest do not implement the full es6 standard, but implement those are not easily or properly to be implement by polyfill or transpiler

@zherczeg
Copy link
Member

Intel has already started to implement typed arrays. Promises might be the next. So this is underway.

@martijnthe
Copy link
Contributor

JFYI, tracking ES6 Promise support separately over here:
#1675

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
discussion Ongoing discussion
Projects
None yet
Development

No branches or pull requests

10 participants