Skip to content

Instantly share code, notes, and snippets.

@rjamesnw
Forked from chrisber/V8dotnetTest.cs
Last active April 30, 2019 21:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rjamesnw/5ee5a0a2a769b321e1d0 to your computer and use it in GitHub Desktop.
Save rjamesnw/5ee5a0a2a769b321e1d0 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using V8.Net;
namespace TestReturnValue
{
public class CompletionEntry1 : V8NativeObject
{
public string name { get { return GetProperty("name"); } set { SetProperty("name", value); } }
public string kind { get { return GetProperty("kind"); } set { SetProperty("kind", value); } }
public string kindModifiers { get { return GetProperty("kindModifiers"); } set { SetProperty("kindModifiers", value); } }
}
public class CompletionInfo1 : V8NativeObject
{
public bool isMemberCompletion { return GetProperty("isMemberCompletion").AsBool; } set { SetProperty("isMemberCompletion", value); } }
public CompletionEntry1[] entries;
}
public class CompletionEntry2 // NOTE: Inheriting from V8NativeObject not required here (though still allowed).
{
public string name { get; set; }
public string kind { get; set; }
public string kindModifiers { get; set; }
}
public class CompletionInfo2 // NOTE: Inheriting from V8NativeObject not required here (though still allowed).
{
public bool isMemberCompletion { get; set; }
public CompletionEntry2[] entries;
public CompletionInfo2(string a, string b, string c)
{
isMemberCompletion = true;
entries = new CompletionEntry2[3] {
new CompletionEntry2 {
name = "start_"+a,
kind = "method",
kindModifiers = "public"
},
new CompletionEntry2 {
name ="drive_"+b,
kind ="method",
kindModifiers = "public"
},
new CompletionEntry2 {
name = "getPosition",
kind = "method_"+c,
kindModifiers = "public"
}
};
}
public InternalHandle AddOne(int i, V8Engine engine) // JS call example: "new CompletionInfo2().AddOne(1) // returns 2"
=> engine.CreateValue(i + 1);
// (the binding system will pass in the engine automatically; InternalHandle parameter types also allowed)
}
class Program
{
static void Main(string[] args)
{
V8Engine v8Engine = new V8Engine();
var result = v8Engine.Execute(
@"var TypescriptService = (function () {
function TypescriptService() {
}
TypescriptService.prototype.getCompletionsAtPosition = function (a, b, c) {
var entries = [
{
'name': 'start_'+a,
'kind': 'method',
'kindModifiers': 'public'
},
{
'name': 'drive_'+b,
'kind': 'method',
'kindModifiers': 'public'
},
{
'name': 'getPosition',
'kind': 'method_'+c,
'kindModifiers': 'public'
}
];
var result = {
'isMemberCompletion': true,
'entries': entries
};
return result;
};
return TypescriptService;
})();
var ls = new TypescriptService();" // NOTE: 'result' WILL ALWAYS BE "undefined" BECAUSE OF "var ..."
);
//create parameter
Handle filename = v8Engine.CreateValue("a");
Handle position = v8Engine.CreateValue("b");
Handle isMemberCompletion = v8Engine.CreateValue("c");
var ls = v8Engine.GlobalObject.GetProperty("ls");
var resultHandle = ls.Call("getCompletionsAtPosition", null, filename, position, isMemberCompletion); // NOTE: The object context is already known, so pass 'null' for '_this'.
CompletionInfo1 completion = v8Engine.GetObject<CompletionInfo1>(resultHandle);
//examine result
var test0 = resultHandle.GetProperty("isMemberCompletion");
ObjectHandle test1 = resultHandle.GetProperty("entries"); // NOTE: "ObjectHandle" is a special handle for objects (which also obviously includes arrays, etc.).
var arrayLength = test1.ArrayLength;
ObjectHandle arrayItem1 = test1.GetProperty(0);
var arrayItem1_name = arrayItem1.GetProperty("name");
var arrayItem1_kind = arrayItem1.GetProperty("kind");
var arrayItem1_kindModifiers = arrayItem1.GetProperty("kindModifiers");
ObjectHandle arrayItem2 = test1.GetProperty(1); // (arrays are treated same as objects here)
ObjectHandle arrayItem3 = test1.GetProperty(2); // (arrays are treated same as objects here)
// ==================================================================== OR ====================================================================
v8Engine.RegisterType<CompletionInfo2>(null, true, ScriptMemberSecurity.Locked);
v8Engine.GlobalObject.SetProperty(typeof(CompletionInfo2)); // <= THIS IS IMPORTANT! It sets the type on the global object (though you can put this anywhere like any property)
var ls2 = (ObjectHandle)(InternalHandle)v8Engine.Execute(
@"var TypescriptService = (function () {
function TypescriptService() {
}
TypescriptService.prototype.getCompletionsAtPosition = function (a, b, c) {
return new CompletionInfo2(a, b, c);
};
return TypescriptService;
})();
new TypescriptService();" // NOTE: result2 is not a handle to the service.
);
var resultHandle2 = ls2.Call("getCompletionsAtPosition", null, filename, position, isMemberCompletion); // NOTE: The object context is already known, so pass 'null' for '_this'.
var objectBindingModeIfNeeded = resultHandle2.BindingMode;
var ce2 = (CompletionInfo2)resultHandle2.BoundObject; // (when a CLR class is bound, it is tracked by the handle in a special way)
// =============================================================================================================================================
// Take your pick. ;)
}
}
}
@chrisber
Copy link

Thank you James for the solution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment