Skip to content

Instantly share code, notes, and snippets.

@chrisber
Last active August 29, 2015 14:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save chrisber/894c6e06201bec6e5b57 to your computer and use it in GitHub Desktop.
Save chrisber/894c6e06201bec6e5b57 to your computer and use it in GitHub Desktop.
#v8dotnet acccess the function of a global object in javascript and return an object from it .
// This is the correct solution provided by jamesnw
// https://gist.github.com/rjamesnw/5ee5a0a2a769b321e1d0
// I added my solution based on his at the bottom.
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"
}
};
}
}
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. ;)
}
}
}
//solution
public static CompletionInfo RunMemberCompletionScript( string filename, int offset, bool membercompliton)
{
try
{
Handle filenameHandle = v8Engine.CreateValue(filename);
Handle positionHandle = v8Engine.CreateValue(offset);
Handle isMemberCompletionHandle = v8Engine.CreateValue(membercompliton);
var ls = v8Engine.GlobalObject.GetProperty("ls");
var resultHandle = ls.Call("getCompletionsAtPosition", null,filenameHandle,positionHandle,isMemberCompletionHandle);
bool isMemberCompletion = resultHandle.GetProperty("isMemberCompletion");
ObjectHandle entriesHandle = resultHandle.GetProperty("entries");
int arrayLength = entriesHandle.ArrayLength;
CompletionEntry[] entries = new CompletionEntry[arrayLength];
for (int i = 0; i < arrayLength; i++)
{
entries[i] = new CompletionEntry(
entriesHandle.GetProperty(i).GetProperty("name"),
entriesHandle.GetProperty(i).GetProperty("kind"),
entriesHandle.GetProperty(i).GetProperty("kindModifiers")
);
}
return new CompletionInfo(isMemberCompletion, entries);
}
catch (Exception e)
{
log(e.ToString());
}
return null;
}
}
@chrisber
Copy link
Author

The correct solution can be found here:

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