Taritsyn/JavaScriptEngineSwitcher

Concurrency issue when initializing JS engine switcher in startup

Closed this issue · 4 comments

In our tests we use WebApplicationFactory from ASP.NET Core testing package to test our controllers which uses startup class to bootstrap the server used during tests. Because we run test fixtures in parallel there can be multiple separate threads running the startup code. This raised an issue where the test setup fails because of concurrency exception when JS engine switcher is being initialized.

The exception is thrown from JsEngineFactoryCollection's Add method where the same factory was added twice. However I did not dig deep enough to be sure if there might be similar issues elsewhere.

I'm not sure if this is something that is even supported, so if this is a feature rather than an bug, feel free to close the issue. We have circumvented the issue by using lock to block multiple threads from running startup initialization concurrently in our tests.

Hello, Ville!

It is assumed that registration of engines in the JavaScript Engine Switcher is performed only once at start of the application (for example, in regular tests I use a special initializer). Under normal conditions, methods of the Startup class are also called only once when the application starts. Perhaps this behavior changes when using a WebApplicationFactory and because of this the error occurs.

Internally, registration of engines in the JavaScript Engine Switcher is based not on the IServiceCollection interface, but on the JsEngineSwitcher.Current property. In fact, JavaScript Engine Switcher is a global variable. This implementation is due to the fact that this library was created before appeared .NET Core and is still used in a large number of projects written in .NET Framework.

Are you directly using a JavaScript Engine Switcher or using some library that uses it as a dependency?

We are not using the JavaScript Engine Switcher directly our self, only configuring it. It is being used by LigerShark.WebOptimizer.Sass (or more precisely, one of its dependencies).

Now that I think about it, we do not need to compile the sass in our tests and thus there should not be any need to configure JavaScript Engine Switcher in tests.

I'm closing this issue as this is not common/supported case and there are many easy ways to circumvent the problem.

Thanks for all the work you do with this library!

We are not using the JavaScript Engine Switcher directly our self, only configuring it. It is being used by LigerShark.WebOptimizer.Sass (or more precisely, one of its dependencies).

Thanks for information! I have an idea how to prevent this error.

Hello, Ville!

I tried to solve this problem in JavaScript Engine Switcher 3.24.0 and WebOptimizer.Sass 3.0.115. You need to add the following setting to the Startup.cs file:

public void ConfigureServices(IServiceCollection services)
{// Registration of JS engines
    services.AddJsEngineSwitcher(options =>
    {
        options.AllowCurrentProperty = false;
        options.DefaultEngineName = JintJsEngine.EngineName;
    })
        .AddJint()
        ;

In this case, AllowCurrentProperty property forbid access to the JsEngineSwitcher.Current property, and thus all work is done through standard ASP.NET Core DI.