2

In ES6, there is a new concept called 'Generator'. It provides a method to iterate something and pause until consumer requests next data.

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

const gen_ = gen() 
gen_.next() // return 1

After gen_.next() it pauses until consumer gen_ requests next data '2'. Then, where the data inside of generator stays?

Summary)

What thing are actually happening inside V8 engine? How can pause it until consumer request next data? and where those next data stays?

nujabes
  • 891
  • 2
  • 8
  • 17
  • @JuanCaicedo Nothing to do with the question – CertainPerformance May 27 '18 at 06:27
  • You can look to see how Babel currently transpiles it, but it uses `regeneratorRuntime`, which is very long. – CertainPerformance May 27 '18 at 06:29
  • So if the next data doesn't stay in memory, where's the instruction stays? when gen_.next() called, how it provides next data '2' to consumer? So where is the place next data '2' exists? – nujabes May 27 '18 at 06:33
  • A generator function has persistent state about where to resume execution the next time it's called. A yield returns a value from the function and sets some internal function state about where to start execution the next time its called. And it isn't a normal function return either because it saves the current scope variables too so they are preserved when it is called again and execution resumes at the saved point. – jfriend00 May 27 '18 at 06:35
  • Check out ["How are generators and async/await implemented in V8?"](https://www.reddit.com/r/javascript/comments/44b6y9/question_how_are_generators_and_asyncawait/) (reddit) The context object is taken off the stack and saved, and put back on the stack when the function is resumed. Event loop is not involved. Maybe related: https://stackoverflow.com/questions/46908575/async-await-native-implementations – Mörre May 27 '18 at 08:50

1 Answers1

4

When calling a generator function, an iterator object is created and returned (in your code example referenced by "gen_"). No generator function code is executed.

This iterator object is used to control the generator function and keeps alive the execution context of the generator function. The iterator object exposes a [[GeneratorLocation]] property which I assume keeps track of where the program execution of the generator is paused.

Through this reference of the iterator object to the generator context, the data of the generator is kept alive whereas normally after finishing program execution of a normal function, this data would be discarded through garbage collection (because nothing would point to it).

Upon your first .next() call on your iterator, the generator executes code until it reaches a yield statement. Then it returns a new object with (in your code example) {value: 1, done: false}. Because done is set to false, the iterator object knows that work is not completed yet so the generator data is kept alive.

When program execution is paused, the generator is non-blocking by taking the generator execution context off the call stack. It is however not discarded because the reference of the iterator object to the generator context keeps the generator data alive.

When calling .next() on the iterator what happens is that the execution context of the generator function is again placed on top of the call stack, continuing the execution where it left off until it reaches no more yield statements, returning an object with {value: undefined, done: true}. Now the iterator object won't point to the generator anymore and the generator function is discarded from memory.

Guus
  • 86
  • 6
  • Are there any official references confirming this behaviour? I consider it to be true, but some link to `v8` documentation would be great if it happens to exist... – Klesun Feb 25 '21 at 11:54
  • 1
    I interpreted it like this from the book: Secrets of the Javascript Ninja - Resig, Bibeault, Maras - 2nd edition. Section 6.2.4. Perhaps the ECMAScript 2015 specification [section 25.3.3.1](https://262.ecma-international.org/6.0/#sec-generatorstart) is what you are looking for? If the v8 engine adheres to this specification, it is how it should work. – Guus Feb 26 '21 at 16:44
  • I'm not super adept in C++. Is there an actual corresponding generator function in C++ that C++ can "re-enter"? – z0d14c Feb 28 '23 at 19:57