Coroutines

Duktape has a support for simple coroutines. Execution is strictly nesting: coroutine A resumes or initiates coroutine B, coroutine B runs until it yields or finishes (either successfully or through an uncaught error), after which coroutine A continues execution with the yield result.

Coroutines are created with new Duktape.Thread(), which gets as its sole argument the initial function where the new coroutine begins execution on its first resume. The resume argument becomes the initial function's first (and only) argument value.

A coroutine is resumed using Duktape.Thread.resume() which takes the following arguments: the coroutine to resume, the resume value, and (optionally) a flag indicating whether the resume value is an ordinary value or an error to be injected into the target coroutine. Injecting an error means that the resume value will be "thrown" at the site of the target coroutine's last yield operation. In other words, instead of returning with an ordinary value, the yield will seemingly throw an error.

A coroutine yields its current execution using Duktape.Thread.yield() which takes as its arguments: the value to yield, and (optionally) a flag indicating whether the yield value is an ordinary value or an error to be thrown in the context of the resuming coroutine. In other words, an error value causes the resume operation to seemingly throw an error instead of returning an ordinary value.

If a coroutine exists successfully, i.e. the initial function finishes by returning a value, it is handled similarly to a yield with the return value. If a coroutine exists because of an uncaught error, it is handled similarly to a yield with the error: the resume operation will rethrow that error in the resuming coroutine's context. In either case the coroutine which has finished can no longer be resumed; attempt to do so will cause a TypeError.

There are currently strict limitations on when a yield is possible. In short, a coroutine can only yield if its entire active call stack consists of plain Ecmascript-to-Ecmascript calls. The following prevent a yield if they are present anywhere in the yielding coroutine's call stack:

See How to use coroutines for examples.