Referencing Google's V8 engine from a .NET app
Asked Answered
G

10

35

I'm building a .NET 3.5 application and have the need to evaluate JS code on the server - basically a user provided rule set that can work within a browser or on the server. Managed JS is not an option, because the JS code would be provided at runtime. Aptana's Jaxer is also not an option. So I was looking into using a build of the V8 engine within my app.

I built the source successfully into a DLL, but that DLL is not not a managed library and is not COM either. V8 is just plain C++.

Any ideas as to how to interop with this type of DLL in C#? Also, I'm open to other suggestions for SpiderMonkey or another JS engine.

Thanks in advance.

UPDATE:

I was able to use Ryan's solution. I just updated the references to the build for the latest from trunk. It worked great. Thanks Ryan.

Glossology answered 10/12, 2008 at 17:47 Comment(5)
As an aside, where can I get a copy of the compiled DLL? (Since I am too lazy to compile it myself, mainly because I don't have VS set up to do C++)Pollie
Ive updated my post with a link to download the test project that I created.Milan
For those who are just finding this page, there is now V8.NET at Codeplex as well.Dys
v8dotnet.codeplex.com V8.NET at CodeplexMonsignor
V8.Net is now on NuGet, and supports .Net Standard! :) (nuget.org/packages/V8.Net)Dys
M
35

I realize that this may not be an exact answer to your question, but I figured I would put my 2 cents worth in as I doubt to many people have tried this.

I got it to work by created a managed wrapper using mixed mode C++. There are other ways to do it, but I was going to attempt to make a full wrapper that could be used from any .NET language.

Getting the lib to compile in such a way that it could be included in a mixed mode project was a little bit of a challenge. I had to modify the runtime library (in the SConstruct file) used to /MD and /MDd so that it would be compatible with the /clr switch.

So far I have only simple scripts running as I have not implemented callbacks, custom methods, objects and such.

Here is a quick sample of what the usage looks like for one of my test apps:

V8DotNet.Shell shell = new V8DotNet.Shell();

shell.ExecuteScript(@"print('V8 version is: ' + version());");

It runs more complicated scripts like a base64 encoder fine as well. But for now I can only add custom items from the c++ side.

I am willing to provide more information + code if anyone is interested as I may not ever pick this project back up. But, I'm afraid it way to much code to go into a post here so we would have to find some other medium like google code or codePlex.

Edit:


OK, I've uploaded the code. I do have to put a disclaimer on this: The project is very early and I am an amateur at C++ at best so don't get your hopes up too much. Also, this project was created/done just after chrome was released so the version of v8 included may be old.

That said, here it is: http://ryanscook.com/Files/V8-DotNet.zip (21.5 MB)

In the package you'll find the following items of interest:

V8Net-Library\V8.Net\V8.Net.sln - This is the solution that has the managed C++ wrapper proj and a C# console app for testing.

Dependencies\V8 - This is my V8 code that I used to build the V8 lib.

Hope it helps!

Milan answered 10/12, 2008 at 19:29 Comment(7)
"I had to modify the runtime library (in the SConstruct file) used to /MD and /MDd so that it would be compatible with the /clr switch." - not a very hard challenge! :)Picklock
Well finding our what had to be done was. The typing is always the easy part. I guess my lack of experience with C++ added to the frustration a bit.Milan
Ryan: Thanks for the help. I'd like to do a build with the /clr switch - like what you did. I have no experience whatsoever with Scons. Mind letting me know in more detail the changes you made to SConstruct file. Particularly, where you specify the /clr switch. Also, It looks like for a shared lib, /MD is already used. Thanks in advance for your help.Glossology
To be honest I can't remember the exact details of my v8 build. The /clr is in the wrapper library. Basically I had to create a slightly modified v8.lib so I could link it to my mixed mode dll. I will try to find time today to post the projects somewhere for you to download.Milan
So now that you have it running, can you interop with it at all? (eg: have the javascript code manipulate an external .NET object somehow?)Borgerhout
Orion: Not yet. I only put a couple hours into the wrapper as a test and never went back to complete it.Milan
Ryan: See my update above. Your code works fine with the build from the latest from trunk. Thanks.Glossology
H
18

You can try Javascript .NET:

http://javascriptdotnet.codeplex.com/

It lets you create a V8 context from .NET and register CLI objects in it so you can manipulate them and call members from the Javascript code. It compiles the Javascript at runtime.

Check it out.

Housework answered 5/7, 2010 at 22:34 Comment(2)
true, pretty cool, however very unsuited for server side usage.. because the V8 engine is not thread safe. (see: javascriptdotnet.codeplex.com/workitem/7062 ) This was a bummer..Archerfish
javascriptdotnet is now threadsafe. Multiple instances (isolates) of v8 can run simultaneously, but they cannot interact.Howlet
K
13

Check out v8sharp. It supports executing JS inside of a .NET application. It also allows you to register .NET types with the v8 engine so that your JS code can interact with your .NET code. I am in the process of adding support for hooking function/delegate support.

Kellie answered 30/6, 2010 at 2:54 Comment(1)
v8sharp is greate,I have used in my project.Bunkmate
P
2

Since this question was posted a while ago I thought I'd give a bit of an update.

Microsoft has made the ClearScript scripting engine, which supports V8, JScript and VBScript.

You can easily add C# types like the Console and use it inside your script. Adding a WPF button type and creating one is no problem either. There are some great examples in the github so I suggest anyone reading this to take a quick look.

Pornography answered 4/12, 2020 at 15:5 Comment(0)
B
1

Microsoft are building a real javascript - not "JScript" - runtime (along with IronPython, IronRuby, and VB10) on the CLR using the DLR, but I can't find any downloads or content for it. Perhaps this will arrive with C# 4?

Borgerhout answered 10/12, 2008 at 20:13 Comment(3)
Yeah, I had heard about the JS DLR implementation a while back, so I first looked into that. But, unfortunately MSFT doesn't seem to have released anything for JS yet, just IronPython. Bummer.Glossology
Managed JavaScript on the DLR is dead. See this answer: code.google.com/apis/v8/design.htmlLongeron
I don't understand how the V8 design docs have anything to do with Javascript on the DLR? The point of javascript on the DLR wouldn't be just for pure speed (although that'd be a nice bonus), but to interop cleanly with the existing .NET ecosystem, which V8 doesn't doBorgerhout
D
1

You can try V8.NET as well.

https://www.nuget.org/packages/V8.Net/

It allows you to easily integrate code with V8 at a lower level than many other wrappers. It also supports .Net 4.6.1+ and .Net Standard 2.0+ (.Net Core).

Dys answered 1/6, 2013 at 19:50 Comment(0)
N
0

From what I hear compiling it with IJW (Managed C++) should just work - but I may be really wrong, I have never touch MC++.

Nathalia answered 10/12, 2008 at 19:48 Comment(0)
S
0

I guess gatapia has replaced js.net with jish

Serafina answered 5/5, 2012 at 17:59 Comment(0)
M
0

Necromancing.
As per 2018 and .NET Core 2.0+
you can use vroomjs-core

Execute some Javascript:

using (var engine = new JsEngine())
{
    using (var context = engine.CreateContext())
    {
        var x = (double)context.Execute("3.14159+2.71828");
        Console.WriteLine(x);  // prints 5.85987
    }
}

Create and return a Javascript object, then call a method on it:

using (JsEngine js = new JsEngine(4, 32))
{
    using (JsContext context = js.CreateContext())
    {
        // Create a global variable on the JS side.
        context.Execute("var x = {'answer':42, 'tellme':function (x) { return x+' '+this.answer; }}");
        // Get it and use "dynamic" to tell the compiler to use runtime binding.
        dynamic x = context.GetVariable("x");
        // Call the method and print the result. This will print:
        // "What is the answer to ...? 42"
        Console.WriteLine(x.tellme("What is the answer to ...?"));
    }
}

Access properties and call methods on CLR objects from Javascript:

class Test
{
    public int Value { get; set; }
    public void PrintValue(string msg)
    {
        Console.WriteLine(msg+" "+Value);
    }
}

using (JsEngine js = new JsEngine(4, 32))
{
    using (JsContext context = js.CreateContext())
    {
        context.SetVariable("m", new Test());
        // Sets the property from Javascript.
        context.Execute("m.Value = 42");
        // Call a method on the CLR object from Javascript. This prints:
        // "And the answer is (again!): 42"
        context.Execute("m.PrintValue('And the answer is (again!):')");
    }
}
Monanthous answered 22/7, 2018 at 19:31 Comment(0)
I
0

Disclaimer: I am author of YantraJS,

This answer is relevant to this question because the question is very old and now more alternatives are available in 2023. Following JavaScript Engines are available in 2023.

  1. JInt (Managed)
  2. Jurassic.Net (Managed)
  3. YantraJS (Managed)
  4. NilJS (Managed)

You can also check https://github.com/sebastienros/jint/tree/main/Jint.Benchmark to see the performances of various engines. All these engines are pure .NET Assemblies and can probably work on any platform easily without any COM or special permissions.

I am author of YantraJS, which supports all ES6 and various new features including Async/Await, and it has modules support along with CSX Modules where in you can also utilize C# modules in JavaScript.

Ingar answered 16/12, 2023 at 7:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.