How to add the ClearScript.V8 assemblies into GAC

Dec 1, 2013 at 12:08 PM
Hello!

Tell me how to add the ClearScript.V8 assemblies into Global Assembly Cache?
Coordinator
Dec 1, 2013 at 4:48 PM
Greetings!

ClearScript currently does not support the GAC. Its assemblies don't have keys or strong names, and its V8 assembly loading algorithm (see here) is incompatible with GAC deployment. Given that a full ClearScript installation includes normal, mixed-mode, and native assemblies, some combination of GAC and SxS deployment may be possible, but we haven't looked into it.

Cheers!
Dec 1, 2013 at 6:39 PM
I have two questions:
  1. It possible in the future make loading of V8 assemblies like NSass?
  2. It possible embed v8-ia32.dll into ClearScriptV8-32.dll, and v8-x64.dll into ClearScriptV8-64.dll (like Noesis Javascript .NET)?
Coordinator
Dec 2, 2013 at 3:07 AM
Edited Dec 3, 2013 at 3:57 AM
Hi Taritsyn,

It possible in the future make loading of V8 assemblies like NSass?

It looks like you're asking about an assembly resolver, which certainly seems like a viable alternative loading strategy. Can you tell us more about your scenario? Specifically, how would an assembly resolver for ClearScript help you reach your objective?

It possible embed v8-ia32.dll into ClearScriptV8-32.dll, and v8-x64.dll into ClearScriptV8-64.dll (like Noesis Javascript .NET)?

Yes, and we've experimented with this successfully. V8 can be built as a static library and linked into ClearScriptV8. We chose to keep V8 separate to reduce ClearScriptV8 link time, among other things, but again, we'd love to hear more about your scenario.

Thanks!
Dec 2, 2013 at 4:03 PM
Hello!

I use JavaScript engines in most modules of my open-source library - Bundle Transformer. JavaScript engines are used not directly, but through the wrapper – JavaScriptEngineSwitcher. Currently, I have a problem with using the Noesis Javascript .NET library under 64-bit version of IIS 8.X, and I see as a replacement the ClearScript.V8 library.

But there are following problems:
  1. Bundle Transformer is used in some CMS, which register all used assemblies in GAC.
  2. Bundle Transformer is used in the web projects of various types, including ASP.NET Web Pages sites. In ASP.NET Web Pages sites cannot store assemblies for different processor architectures in the root of bin directory, therefore it should be placed in subdirectories. For such cases in static constructor of the V8JsEngine class I determine and add search paths of the ClearScript.V8 assemblies. In order to be use JavaScriptEngineSwitcher.V8 in different projects types I wrote a special NuGet package.
In ClearScript.V8 it would be good to have the ability to set own assembly resolver, or at least have the ability to affect the result of V8Proxy.GetDirPaths method.

In addition, it would be good if the ClearScript assembly will be divided into 3 assemblies:
  1. ClearScript.Common - common types and utilities
  2. ClearScript.Windows - windows script engines
  3. ClearScript.V8 - V8 script engine proxy
Coordinator
Dec 3, 2013 at 4:40 AM
Hi Taritsyn,

We're not ASP.NET or CMS experts here, so please bear with us.

Bundle Transformer is used in the web projects of various types, including ASP.NET Web Pages sites. In ASP.NET Web Pages sites cannot store assemblies for different processor architectures in the root of bin directory, therefore it should be placed in subdirectories.

Our normal recommendation for ASP.NET projects is to add the V8 and ClearScriptV8 assemblies as content files at the root of the web application, where the V8Proxy loader looks for them. We've used this scheme successfully in local, on-premises, and Azure deployments. Is it not practical for you?

Bundle Transformer is used in some CMS, which register all used assemblies in GAC.

If we understand correctly, this means that ClearScript.dll would have to be in the GAC as well, but the V8 and ClearScriptV8 assemblies could still be deployed as recommended above. Do you agree?

In ClearScript.V8 it would be good to have the ability to set own assembly resolver, or at least have the ability to affect the result of V8Proxy.GetDirPaths method.

Yes, we can see how this might add some flexibility. We'll take a look at it. In the meantime, would it be possible to use AppDomainSetup.PrivateBinPath?

In addition, it would be good if the ClearScript assembly will be divided into 3 assemblies:

The ClearScript assembly is relatively small - currently about 260K - and uses late-binding to instantiate the underlying script engines. It can be deployed without the V8 assemblies if JScript/VBScript are sufficient. Why split it up?

Thanks!
Dec 3, 2013 at 8:21 AM
Edited Dec 3, 2013 at 8:29 AM
Our normal recommendation for ASP.NET projects is to add the V8 and ClearScriptV8 assemblies as content files at
the root of the web application, where the V8Proxy loader looks for them. We've used this scheme successfully in local, on-premises, and Azure deployments. Is it not practical for you?
It seems to me that this is not correct. It is suitable for WebMatrix sites, but not for ASP.NET web applications.
If we understand correctly, this means that ClearScript.dll would have to be in the GAC as well, but the V8 and ClearScriptV8 assemblies could still be deployed as recommended above. Do you agree?
​OK
Yes, we can see how this might add some flexibility. We'll take a look at it. In the meantime, would it be possible to use AppDomainSetup.PrivateBinPath?
Unfortunately, the AppDomainSetup.PrivateBinPath property cannot be changed for the current AppDomain. Now I use the following decision:
/// <summary>
/// Sets a path under the base directory where the assembly resolver should probe for private assemblies
/// </summary>
static V8JsEngine()
{
    var currentDomain = AppDomain.CurrentDomain;

    string binDirectoryPath = currentDomain.SetupInformation.PrivateBinPath;
    if (string.IsNullOrEmpty(binDirectoryPath))
    {
        // `PrivateBinPath` property is empty in test scenarios, so
        // need to use the `BaseDirectory` property
        binDirectoryPath = currentDomain.BaseDirectory;
    }

    string assemblyDirectoryPath = Path.Combine(binDirectoryPath, ASSEMBLY_DIRECTORY_NAME);
    if (!Directory.Exists(assemblyDirectoryPath) && HttpContext.Current != null)
    {
        // Fix for WebMatrix
        string applicationRootPath = HttpContext.Current.Server.MapPath("~");
        assemblyDirectoryPath = Path.Combine(applicationRootPath, ASSEMBLY_DIRECTORY_NAME);
    }

    currentDomain.AppendPrivatePath(assemblyDirectoryPath);
}
But the AppendPrivatePath method is deprecated. I would like to have some solution at the level of ClearScript.V8.
The ClearScript assembly is relatively small - currently about 260K - and uses late-binding to instantiate the underlying script engines. It can be deployed without the V8 assemblies if JScript/VBScript are sufficient. Why split it up?
Problem is not the size of assembly. Simply divide to 3 assemblies, it would be more correct (from the point of view of creating NuGet packages). In future will be easier to add a new script engines (for example, Chakra or SpiderMonkey).

Thanks!
Coordinator
Dec 3, 2013 at 3:39 PM
Hi Taritsyn,

It seems to me that this is not correct. It is suitable for WebMatrix sites, but not for ASP.NET web applications.

We've received confirmation from others (e.g., here, here, and here) that it does work. The V8Proxy loader supports this setup by attempting to load the V8 and ClearScriptV8 assemblies from AppDomain.BaseDirectory.

Unfortunately, the AppDomainSetup.PrivateBinPath property cannot be changed for the current AppDomain.

Ah, that is indeed unfortunate. We'll investigate the assembly resolver option. To be honest, we have yet to understand the ramifications; e.g., the behavior when multiple resolvers are installed.

Problem is not the size of assembly. Simply divide to 3 assemblies, it would be more correct (from the point of view of creating NuGet packages). In future will be easier to add a new script engines (for example, Chakra or SpiderMonkey).

Yes, that's a good point. There are advantages to a minimal assembly count - deployment simplicity and startup performance - but they're diminished in ASP.NET environments. In any case, we probably won't do any major refactoring until we add support for more script engines.

Thanks again for your input!
Coordinator
Dec 13, 2013 at 1:18 PM
Hi again!

To enable ClearScriptV8 assembly loading via AppDomain.AssemblyResolve, we'd like to propose the following new code at the top of V8Proxy.LoadAssembly:
try
{
    assembly = Assembly.Load("ClearScriptV8");
    return;
}
catch (FileNotFoundException)
{
}
This should allow hosts to override ClearScript's loading process via the event.

We'd love to hear your thoughts!
Dec 13, 2013 at 1:29 PM
Hello!

I do not understand how to use it. Give an example of use.
Coordinator
Dec 13, 2013 at 2:55 PM
If we made the change above, the host could do something like this to override ClearScript's V8 loading process:
AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
{
    if (args.Name == "ClearScriptV8")
    {
        return Assembly.LoadFrom(@"C:\Custom\Path\To\ClearScriptV8-64.dll");
    }

    return null;
};
Would that provide the flexibility you were looking for?
Dec 13, 2013 at 3:34 PM
I think this is a good option.

Thanks!