Async await polyfills used since 3.2.0 because transpile target is ES2015

Since the move to typescript with 3.2.0 a polyfill is used for async/await which looks like this:

var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(; } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());

Reason is that target ES2015 is used (see

I think at least target ES2017 should be used to ensure that native async/await is used because all LTS versions of Node.js support it and previous versions used also native await.
I have not done any measurements but I assume the polyfill adds unneeded overhead and may even result in different behavior in some cases.

Thanks @Flarna , @brett19 / @ericb any input ?

One noticeable difference is for example the return type of cluster.query.
in Couchbase 3.1.x it was a “plain” Promise as async functions always return a Promise.
In 3.2.x the user gets an instance of StreamableRowPromise.

It’s not really wrong as StreamableRowPromise is a thenable and as a result usable for await but it leaks internal details.

Hey @Flarna,

This is not actually “leaking” internal details, it’s an intentional design decision as the StreamableRowPromise implements the Promise spec (which allows you to use await directly), while also enabling you to stream the individual rows rather than needing to cache them entirely in memory as is the case with Promises’s.

Cheers, Brett


ah ok. I just noticed that cluster.queryis no longer async like in 3.1.3 instead it’s a normal function returning a StreamableRowPromise. So it was actually incorrect in 3.1.3 and fixed via JSCBC-707

But I still think that ES2017 would be a better target for typescript to avoid the await polyfills at places where await is still used.


Is it also intended that a Promise is returned if a callback is passed. wrapAsync() no longer returns undefined in the cb case (see

Hey @Flarna,

The handling of promises is a sort of careful balance we are trying to keep for backwards compatibility reasons (and will likely be removed in the next major release of the SDK, although there is no current plans for that). The primary behaviour that’s important for us to maintain is such that rejected promises don’t emit an unhandled promise rejection, which I don’t believe they do with the current setup since a callback being set is actually registered with the promise.

In terms of the polyfilling. I have filed the issue below to track this, and there is a patchset available under it which will be included in 3.2.3 which adjusts our tsconfig to match with our minimum supported Node version (10). This also bumps us up to ES2018.

Cheers, Brett