Skip to main content

Sync API Deprecation

For many years one of the selling features of the WebdriverIO framework was its synchronous API. Especially for folks coming from more synchronous oriented languages such as Java or Ruby, it has helped to avoid race conditions when executing commands. But also people that are more familiar with Promises tend to prefer synchronous execution as it made the code easier to read and handle.

Running asynchronous commands in a synchronous way was possible with the help of the @wdio/sync package. If installed, WebdriverIO would automatically wrap the commands with utility methods that were using the fibers package to create a synchronous execution environment. It uses some internal V8 APIs to allow to jump between multiple call stacks from within a single thread. This approach also has been popular among other projects, e.g. Meteor, where most of the code is written using asynchronous APIs which causes developers to constantly start the line of code with await.

Last year the author of the Fibers package announced that he would no longer continue to maintain the project anymore. He built Fibers when JavaScript did not have any proper mechanism to handle asynchronous code other than using callbacks. With JavaScript evolving and adding APIs like Promises or Generators there is technically no reason anymore for Fibers to exist other than preference of code style. Now with the release of Node.js v16 and the update to V8 v9 Fibers stopped working due to a change in V8 that would remove some internal interfaces Fibers was using. Given that a fix for this is non trivial and the maintainer already stepped down from the project it is unlikely that we will see support for Fibers in Node.js v16 and on.

After the WebdriverIO team discovered this we immediately took action and evaluated our options. We opened an RFC to discuss with the community in which direction the project should go. I would like to thank everyone who chimed in and provided their opinion. We experimented with some alternative options, e.g. using Babel to transpile synchronous code into asynchronous but they all failed due to various reasons. The ultimate decision was made to accept the fact that synchronous command execution won't be possible moving on and rather embrace asynchronicity.

With the release of WebdriverIO v7.9 we are happy to announce that we improved our asynchronous API and matched it with the synchronous one. When chaining element command calls users had to write aweful code like this before:

await (await (await $('#foo')).$$('.bar'))[42].click()

now this got simiplified to this:

await $('#foo').$$('.bar')[42].click()

Thanks to the enormous power of the Proxy Object the API is now much more streamlined and less verbose. This will also help users migrating a project that uses the synchronous API to become asynchronous. The team will work on a codemod to help make this process as automated and easy as possible.

At this point the WebdriverIO team wants to thank Marcel Laverdet (@laverdet on GitHub) for building Fibers and maintaining it for so many years. It is time to move on and embrace all the great JavaScript language feature many people have worked hard on. While we have updated the code examples in our docs, @wdio/sync will continue to be supported until we drop support for Node.js v14 and earlier which won't happen before April 2023. You will have enough time to slowly migrate your tests using async/await.

If you have any questions on this or the migration from a framework writing with synchronous commands to asynchronous code, feel free to drop us a line in our discussion forum or on Gitter.