Skip to content

How to upgrade applications to version 3.X

Andrey Taritsyn edited this page Jun 12, 2018 · 11 revisions

Breaking changes

Core

IJsEngineSwitcher interface

Now you can implement your own version of the JsEngineSwitcher class. To do this, you must create a class, that implements the IJsEngineSwitcher interface and assign an instance of this class to the Current property (this property should be used instead of the Instance property) of JsEngineSwitcher class:

JsEngineSwitcher.Current = new MyJsEngineSwitcher();

In ASP.NET Core applications where the JavaScriptEngineSwitcher.Extensions.MsDependencyInjection package is installed, this is done as follows:

public class Startup
{public void ConfigureServices(IServiceCollection services)
	{services.AddJsEngineSwitcher(new MyJsEngineSwitcher(), options =>);}}

Because of appearance of this feature, you need to make changes in the source code of your applications: change the type of variables, parameters or properties from JsEngineSwitcher to IJsEngineSwitcher.

Reorganization of exceptions

During reorganization of exceptions, the following changes were made:

  1. Format of the error messages was unified.
  2. Created a new exception classes: JsCompilationException, JsEngineException, JsFatalException, JsInterruptedException, JsTimeoutException and JsUsageException. These exceptions are responsible for handling errors, some of which were previously handled by the JsRuntimeException class.
  3. In the JsException class was added two new properties: Category and Description.
  4. From the JsRuntimeException class was removed one property - ErrorCode.
  5. In the JsRuntimeException class was added three new properties: Type, DocumentName and CallStack.
  6. JsEngineLoadException class now is inherited from the JsEngineException class.
  7. Removed a EmptyValueException class.
  8. Format method of the JsErrorHelpers class was renamed to the GenerateErrorDetails.

Now exception hierarchy looks like this:

  • JsException
    • JsEngineException
      • JsEngineLoadException
    • JsFatalException
    • JsScriptException
      • JsCompilationException
      • JsRuntimeException
        • JsInterruptedException
        • JsTimeoutException
    • JsUsageException
  • JsEngineNotFoundException

Script pre-compilation

In IJsEngine interface was added SupportsScriptPrecompilation property and three new methods: Precompile, PrecompileFile and PrecompileResource.

Precompile, PrecompileFile and PrecompileResource methods create an object, that implements the IPrecompiledScript interface. This object is a pre-compiled script, that can be used by different instances of JS engine (an overloaded version of the Execute method is used for this). This approach allows you to save time when you initialize multiple instances of JS engine by the same script.

const string sourceCode = @"function declensionOfNumerals(number, titles) {
	var result,
		titleIndex,
		cases = [2, 0, 1, 1, 1, 2],
		caseIndex
		;

	if (number % 100 > 4 && number % 100 < 20) {
		titleIndex = 2;
	}
	else {
		caseIndex = number % 10 < 5 ? number % 10 : 5;
		titleIndex = cases[caseIndex];
	}

	result = titles[titleIndex];

	return result;
}

function declinationOfSeconds(number) {
	return declensionOfNumerals(number, ['секунда', 'секунды', 'секунд']);
}";
const string functionName = "declinationOfSeconds";

IJsEngineSwitcher engineSwitcher = JsEngineSwitcher.Current;
IPrecompiledScript precompiledCode = null;

using (var engine = engineSwitcher.CreateDefaultEngine())
{
	precompiledCode = engine.Precompile(sourceCode, "declinationOfSeconds.js");
	engine.Execute(precompiledCode);

	const int input0 = 0;
	string output0 = engine.CallFunction<string>(functionName, input0);

	Console.WriteLine("{0} {1}", input0, output0);
}

using (var firstEngine = engineSwitcher.CreateDefaultEngine())
{
	firstEngine.Execute(precompiledCode);

	const int input1 = 1;
	string output1 = firstEngine.CallFunction<string>(functionName, input1);

	Console.WriteLine("{0} {1}", input1, output1);
}

using (var secondEngine = engineSwitcher.CreateDefaultEngine())
{
	secondEngine.Execute(precompiledCode);

	const int input2 = 42;
	string output2 = secondEngine.CallFunction<string>(functionName, input2);

	Console.WriteLine("{0} {1}", input2, output2);
}

using (var thirdEngine = engineSwitcher.CreateDefaultEngine())
{
	thirdEngine.Execute(precompiledCode);

	const int input3 = 600;
	string output3 = thirdEngine.CallFunction<string>(functionName, input3);

	Console.WriteLine("{0} {1}", input3, output3);
}

Since not all JS engines support ability to pre-compile scripts, then before creating and executing pre-compiled scripts should always check the value of SupportsScriptPrecompilation property.

Script interruption

In IJsEngine interface was added SupportsScriptInterruption property and Interrupt method. Since not all JS engines support ability to interrupt execution of the script, then before calling of Interrupt method should always check the value of SupportsScriptInterruption property:

if (engine.SupportsScriptInterruption)
{
	engine.Interrupt();
}

After calling of the Interrupt method, execution of scripts ends with an error, therefore you should catch the JsInterruptedException exception.

V8

Microsoft ClearScript.V8 and JavaScriptEngineSwitcher.V8 now requires .NET Framework 4.5+ and the Microsoft Visual C++ Redistributable for Visual Studio 2017.

MaxExecutableSize configuration property became obsolete.

Jint

Timeout configuration property has been replaced by the TimeoutInterval property (default TimeSpan.Zero).

ChakraCore

Now the ChakraCore for Windows requires the Microsoft Visual C++ Redistributable for Visual Studio 2017.