tjanczuk / edge Goto Github PK
View Code? Open in Web Editor NEWRun .NET and Node.js code in-process on Windows, MacOS, and Linux
Home Page: http://tjanczuk.github.io/edge
License: Other
Run .NET and Node.js code in-process on Windows, MacOS, and Linux
Home Page: http://tjanczuk.github.io/edge
License: Other
This is to take the SQL sample first file, second file and turn it into edge-sql, a brand new module that builds on top of edge.js and uses async ADO .NET to provide fully featured access to MS SQL from node.js.
Currently functions exported from JS to C# can only be called till the Task returned by C# Func<object,Task> has completed. They are garbage collected afterwards.
I was thinking about the callbacks from C# to node.js some more. I think there is an uncomplicated way of allowing such calls even after the Task has completed, as long as these JavaScript functions can be specified at the time of calling edge.func
rather than invoking the function itself, e.g.:
var myFunc = edge.func({
csx: ‘ async (input) => { … }’,
exports: {
myJavaScriptFunc: function (data, callback) { … }
}
}
This pattern makes it easy to export global JS functions but somehow harder to provide per-call closures to C#.
I understand this may not be a high priority, but many open source .NET frameworks and potential owin hosts want to ensure their frameworks and libraries work cross-platform.
I'm assuming there's going to be a bit of win specific bits, but it'd be nice if the parts that can be re-usable across platform can easily be decoupled and re-used from the bits that aren't.
Is there any reason why I couldn't build a node-webkit application and use edge to provide access to windows .NET functions?
This is to add a one-file sample showing encryption and decryption of data using DPAPI on Windows
We need this if CLR calls into Node after the CLR function has ended (typically in event listeners). This will prevent Node from exiting. Need to provide the API in a way that clients of it understand the power of the API.
I found a little bug installing edge on a folder name with spaces. No problem installing edge from a folder without spaces.
Opened a dos window in:
C:\Program Files\nodejsApps\edge
executed:
npm install edge
result: install fails (se 159 error cmd "/c" "tools\\install.bat"
failed with 8)
Thanks for your awesome projects!
Marco
npm-debug.log:
0 info it worked if it ends with ok
1 verbose cli [ 'C:\Program Files\nodejs\node.exe',
1 verbose cli 'C:\Program Files\nodejs\node_modules\npm\bin\npm-cli.js',
1 verbose cli 'install',
1 verbose cli 'edge' ]
2 info using [email protected]
3 info using [email protected]
4 verbose node symlink C:\Program Files\nodejs\node.exe
5 verbose read json C:\Program Files\nodejsApps\edge\package.json
6 verbose read json C:\Program Files\nodejsApps\edge\package.json
7 verbose cache add [ 'edge', null ]
8 verbose cache add name=undefined spec="edge" args=["edge",null]
9 verbose parsed url { protocol: null,
9 verbose parsed url slashes: null,
9 verbose parsed url auth: null,
9 verbose parsed url host: null,
9 verbose parsed url port: null,
9 verbose parsed url hostname: null,
9 verbose parsed url hash: null,
9 verbose parsed url search: null,
9 verbose parsed url query: null,
9 verbose parsed url pathname: 'edge',
9 verbose parsed url path: 'edge',
9 verbose parsed url href: 'edge' }
10 silly lockFile a0f2c69a-edge edge
11 verbose lock edge C:\Users\mag.NEWNECSY\AppData\Roaming\npm-cache\a0f2c69a-edge.lock
12 silly lockFile a0f2c69a-edge edge
13 silly lockFile a0f2c69a-edge edge
14 verbose addNamed [ 'edge', '' ]
15 verbose addNamed [ null, '' ]
16 silly lockFile c79c9872-edge edge@
17 verbose lock edge@ C:\Users\mag.NEWNECSY\AppData\Roaming\npm-cache\c79c9872-edge.lock
18 silly addNameRange { name: 'edge', range: '', hasData: false }
19 verbose url raw edge
20 verbose url resolving [ 'https://registry.npmjs.org/', './edge' ]
21 verbose url resolved https://registry.npmjs.org/edge
22 info trying registry request attempt 1 at 12:19:44
23 verbose etag "CQFVTVL6JKMIWJ9SI7HOGXU2I"
24 http GET https://registry.npmjs.org/edge
25 http 304 https://registry.npmjs.org/edge
26 silly registry.get cb [ 304,
26 silly registry.get { server: 'CouchDB/1.2.1 (Erlang OTP/R15B03)',
26 silly registry.get etag: '"CQFVTVL6JKMIWJ9SI7HOGXU2I"',
26 silly registry.get date: 'Tue, 19 Mar 2013 11:19:46 GMT',
26 silly registry.get 'content-length': '0' } ]
27 verbose etag edge from cache
28 silly addNameRange number 2 { name: 'edge', range: '', hasData: true }
29 silly addNameRange versions [ 'edge', [ '0.7.0', '0.7.1' ] ]
30 verbose addNamed [ 'edge', '0.7.1' ]
31 verbose addNamed [ '0.7.1', '0.7.1' ]
32 silly lockFile 0ba9522a-edge-0-7-1 [email protected]
33 verbose lock [email protected] C:\Users\mag.NEWNECSY\AppData\Roaming\npm-cache\0ba9522a-edge-0-7-1.lock
34 verbose read json C:\Users\mag.NEWNECSY\AppData\Roaming\npm-cache\edge\0.7.1\package\package.json
35 silly lockFile 0ba9522a-edge-0-7-1 [email protected]
36 silly lockFile 0ba9522a-edge-0-7-1 [email protected]
37 silly lockFile c79c9872-edge edge@
38 silly lockFile c79c9872-edge edge@
39 silly resolved [ { name: 'edge',
39 silly resolved author:
39 silly resolved { name: 'Tomasz Janczuk',
39 silly resolved email: '[email protected]',
39 silly resolved url: 'http://tomasz.janczuk.org' },
39 silly resolved version: '0.7.1',
39 silly resolved description: 'Edge.js: run .NET and node.js code in-process',
39 silly resolved tags: [ 'owin', 'edge', 'net', 'clr', 'c#', 'managed', '.net' ],
39 silly resolved main: './lib/edge.js',
39 silly resolved engines: { node: '0.8.x || 0.10.x' },
39 silly resolved licenses: [ [Object] ],
39 silly resolved dependencies: {},
39 silly resolved devDependencies: { mocha: '1.8.1' },
39 silly resolved homepage: 'https://github.com/tjanczuk/edge',
39 silly resolved repository: { type: 'git', url: '[email protected]:tjanczuk/edge.git' },
39 silly resolved bugs: { url: 'http://github.com/tjanczuk/edge/issues' },
39 silly resolved scripts: { install: 'tools\install.bat', test: 'test\test.bat' },
39 silly resolved readme: 'Edge.js: run .NET and node.js code in-process\r\n====\r\n\r\nAn edge connects two nodes. This edge connects node.js and .NET.\r\n\r\n## Before you dive in\r\n\r\nSee the Edge.js overview.\r\n\r\n## Introduction \r\n\r\nEdge.js allows you to run .NET and node.js code in one process. You can call .NET functions from node.js and node.js functions from .NET. Edge.js takes care of marshaling data between CLR and V8. Edge.js also reconciles threading models of single threaded V8 and multi-threaded CLR. The .NET code can be pre-compiled or specified as C# source: edge.js can compile C# script at runtime.\r\n\r\n\r\n\r\nEdge.js provides a basic, prescriptive model and implementation for interoperability between .NET and node.js in-process. You can built upon and extended this basic mechanism to support more specific scenarios, for example:\r\n* implementing express.js handlers and connect middleware for node.js application using .NET 4.5 (read more), \r\n* implementing CPU-bound computations in .NET and running them in-process with node.js application without blocking the event loop (read more), \r\n* using C# and .NET instead of writing native node.js extensions in C/C++ and Win32 to access Windows specific functionality from a node.js application (read more). \r\n\r\nEdge.js is a native node.js module for Windows. It bridges between JavaScript, native, and CLR/.NET code (think C#). The module takes care of marshaling data between V8 and CLR heaps as well as reconciling threading models. The .NET code is running in-process either asynchronously or on CLR threads while the node.js event loop remains unblocked. The .NET code can be integrated into a node.js application as C# script that will be automatically compiled, or as a pre-compiled CLR assembly.\r\n\r\nRead more about the background and motivations of the project here. \r\n\r\nFollow @tjanczuk for updates related to the module. \r\n\r\n## What you need\r\n\r\n* Windows\r\n* node.js 0.10.x or 0.8.x (developed and tested with v0.8.22 and v0.10.0, both x32 and x64 architectures) \r\n* .NET 4.5 \r\n\r\n## How to: hello, world\r\n\r\nInstall edge:\r\n\r\n
\r\nnpm install edge\r\n
\r\n\r\nIn your server.js:\r\n\r\njavascript\r\nvar edge = require(\'edge\');\r\n\r\nvar helloWorld = edge.func(\'async (input) => { return ".NET Welcomes " + input.ToString(); }\');\r\n\r\nhelloWorld(\'JavaScript\', function (error, result) {\r\n if (error) throw error;\r\n console.log(result);\r\n});\r\n
\r\n\r\nRun and enjoy:\r\n\r\n\r\nC:\\projects\\barebones>node server.js\r\n.NET welcomes JavaScript\r\n
\r\n\r\n## How to: integrate C# code into node.js code\r\n\r\nEdge provies several ways to integrate C# code into a node.js application. Regardless of the way you choose, the entry point into the .NET code is normalized to a Func<object,Task<object>>
delegate. This allows node.js code to call .NET asynchronoulsy and avoid blocking the node.js event loop. \r\n\r\nEdge provides a function that accepts a reference to C# code in one of the supported representations, and returns a node.js function which acts as a JavaScript proxy to the Func<object,Task<object>>
.NET delegate:\r\n\r\njavascript\r\nvar edge = require(\'edge\');\r\n\r\nvar myFunction = edge.func(...);\r\n
\r\n\r\nThe function proxy can then be called from node.js like any asynchronous function:\r\n\r\njavascript\r\nmyFunction(\'Some input\', function (error, result) {\r\n //...\r\n});\r\n
\r\n\r\nIn one representation, you can embed C# code inside node.js code by providing a C# literal representing a .NET async lambda expression of Func<object,Task<object>>
type:\r\n\r\njavascript\r\nvar add7 = edge.func(\'async (input) => { return (int)input + 7; }\');\r\n
\r\n\r\nIn antoher representation, you can embed multi-line C# source code by providing a function with a body containing a multi-line comment. Edge extracts the C# code from the function body using regular expressions:\r\n\r\njavascript\r\nvar add7 = edge.func(function() {/*\r\n async (input) => {\r\n return (int)input + 7;\r\n }\r\n*/});\r\n
\r\n\r\nIf your C# code is more involved than a simple lambda, you can specify entire class definition. By convention, the class must be named Startup
and it must have an Invoke
method that matches the Func<object,Task<object>>
delegate signature. This method is useful if you need to factor your code into multiple methods:\r\n\r\njavascript\r\nvar add7 = edge.func(function() {/*\r\n using System.Threading.Tasks;\r\n\r\n public class Startup\r\n {\r\n public async Task<object> Invoke(object input)\r\n {\r\n int v = (int)input;\r\n return Helper::AddSeven(v);\r\n }\r\n }\r\n\r\n static class Helper\r\n {\r\n public static int AddSeven(int v) \r\n {\r\n return v + 7;\r\n }\r\n }\r\n*/});\r\n
\r\n\r\nIf your C# code grows substantially, it is useful to keep it in a separate file. You can save it to a file with *.csx
or *.cs
extension, and then reference from your node.js application:\r\n\r\njavascript\r\nvar add7 = edge.func(__dirname + \'/add7.csx\');\r\n
\r\n\r\nIf you integrate C# code into your node.js application by specifying C# source using one of he methods above, edge will compile the code on the fly. If you prefer to pre-compile your C# sources to a CLR assembly, or if your C# component is already pre-compiled, you can reference a CLR assembly from your node.js code. In the most generic form, you can specify the assembly file name, the type name, and the method name when creating a node.js proxy to a .NET method:\r\n\r\njavascript\r\nvar clrMethod = edge.func({\r\n assemblyFile: \'My.Edge.Samples.dll\',\r\n typeName: \'Samples.FooBar.MyType\',\r\n methodName: \'MyMethod\'\r\n});\r\n
\r\n\r\nIf you don't specify methodName, Invoke
is assumed. If you don't specify typeName, a type name is constucted by assuming the class called Startup
in the namespace equal to the assembly file name (without the .dll
). In the example above, if typeName was not specified, it would default to My.Edge.Samples.Startup
.\r\n\r\nThe assemblyFile is relative to the working directory. If you want to locate your assembly in a fixed location relative to your node.js application, it is useful to constuct the assemblyFile using __dirname
. \r\n\r\nYou can also create node.js proxies to .NET functions specifying just the assembly name as a parameter:\r\n\r\njavascript\r\nvar clrMethod = edge.func(\'My.Edge.Samples.dll\');\r\n
\r\n\r\nIn that case the default typeName of My.Edge.Samples.Startup
and methodName of Invoke
is assumed as explained above. \r\n\r\n## How to: specify additional CLR assembly references\r\n\r\nWhen you provide C# source code and let edge compile it for you at runtime, edge will by default reference only mscorlib.dll and System.dll assemblies. In applications that require additional assemblies you can specify them in C# code using a special comment pattern. For example, to use ADO.NET you must reference System.Data.dll:\r\n\r\njavascript\r\nvar add7 = edge.func(function() {/*\r\n\r\n //#r "System.Data.dll"\r\n\r\n using System.Data;\r\n using System.Threading.Tasks;\r\n\r\n public class Startup\r\n {\r\n public async Task<object> Invoke(object input)\r\n {\r\n // ...\r\n }\r\n }\r\n*/});\r\n
\r\n\r\nIf you prefer, instead of using comments you can specify references by providing options to the edge.func
call:\r\n\r\njavascript\r\nvar add7 = edge.func({\r\n csx: function() {/*\r\n\r\n using System.Data;\r\n using System.Threading.Tasks;\r\n\r\n public class Startup\r\n {\r\n public async Task<object> Invoke(object input)\r\n {\r\n // ...\r\n }\r\n }\r\n */},\r\n references: [ \'System.Data.dll\' ]\r\n);\r\n
\r\n\r\n## How to: marshal data\r\n\r\nEdge module can marhshal any JSON-serializable value between .NET and node.js. Edge also supports marshaling between node.js Buffer
instance and a .NET byte[]
array to help you efficiently pass binary data.\r\n\r\nYou can call .NET from node.js and pass in a complex JavaScript object as follows:\r\n\r\njavascript\r\nvar dotNetFunction = edge.func(\'Edge.Sample.dll\');\r\n\r\nvar payload = {\r\n anInteger: 1,\r\n aNumber: 3.1415,\r\n aString: \'foo\',\r\n aBoolean: true,\r\n aBuffer: new Buffer(10),\r\n anArray: [ 1, \'foo\' ],\r\n anObject: { a: \'foo\', b: 12 }\r\n};\r\n\r\ndotNetFunction(payload, function (error, result) { });\r\n
\r\n\r\nIn .NET, JavaScript objects are represented as IDictionary<string,object>
, JavaScript arrays as object[]
, and JavaScript Buffer
as byte[]
. Scalar JavaScript values have their corresponding .NET types (int
, double
, bool
, string
). Here is how you can acces the data in .NET:\r\n\r\nc#\r\nusing System.Collections.Generic;\r\nusing System.Threading.Tasks;\r\n\r\nnamespace Edge.Sample\r\n{\r\n public class Startup\r\n {\r\n public async Task<object> Invoke(object input)\r\n {\r\n IDictionary<string, object> payload = (IDictionary<string,object>)input;\r\n int anInteger = (int)payload["anInteger"];\r\n double aNumber = (double)payload["aNumber"];\r\n string aString = (string)payload["aString"];\r\n bool aBoolean = (bool)payload["aBoolean"];\r\n byte[] aBuffer = (byte[])payload["aBuffer"];\r\n object[] anArray = (object[])payload["anArray"];\r\n IDictionary<string, object> anObject = (IDictionary<string,object>)payload["anObject"];\r\n\r\n return null;\r\n }\r\n }\r\n}\r\n
\r\n\r\nSimilar type marshaling is applied when .NET code passes data back to node.js code. In .NET code you can provide an instance of any JSON-serializable CLR type, including domain specific types like Person
or anonymous objects. For example:\r\n\r\nc#\r\nusing System.Threading.Tasks;\r\n\r\nnamespace Edge.Sample\r\n{\r\n public class Person\r\n {\r\n public int anInteger = 1;\r\n public double aNumber = 3.1415;\r\n public string aString = "foo";\r\n public bool aBoolean = true;\r\n public byte[] aBuffer = new byte[10];\r\n public object[] anArray = new object[] { 1, "foo" };\r\n public object anObject = new { a = "foo", b = 12 };\r\n }\r\n\r\n public class Startup\r\n {\r\n public async Task<object> Invoke(object input)\r\n {\r\n Person person = new Person();\r\n return person;\r\n }\r\n }\r\n}\r\n
\r\n\r\nIn your node.js code that invokes this .NET method you can display the result object that the callback method receives:\r\n\r\njavascript\r\nvar edge = require(\'edge\');\r\n\r\nvar getData = edge.func(\'Edge.Sample.dll\');\r\n\r\ngetData(null, function (error, result) {\r\n if (error) throw error;\r\n console.log(result);\r\n});\r\n
\r\n\r\nPassing this .NET object to node.js generates a JavaScript object as follows:\r\n\r\n\r\nC:\\projects\\barebones>node sample.js\r\n{ anInteger: 1,\r\n aNumber: 3.1415,\r\n aString: \'foo\',\r\n aBoolean: true,\r\n aBuffer: <Buffer 00 00 00 00 00 00 00 00 00 00>,\r\n anArray: [ 1, \'foo\' ],\r\n anObject: { a: \'foo\', b: 12 } }\r\n
\r\n\r\n## How to: call node.js from .NET\r\n\r\nIn addition to marshaling data, edge can marshal proxies to JavaScript functions when invoking .NET code from node.js. This allows .NET code to call back into node.js. \r\n\r\nSuppose the node.js application passes an add
function to the .NET code as a property of an object. The function receives two numbers and returns the sum of them via the provided callback:\r\n\r\njavascript\r\nvar edge = require(\'edge\');\r\n\r\nvar multiplyBy2 = edge.func(\'Edge.Sample.dll\');\r\n\r\nvar payload = {\r\n someParameter: \'arbitrary parameter\',\r\n add: function (data, callback) {\r\n callback(null, data.a + data.b);\r\n }\r\n};\r\n\r\nmultiplyBy2(payload, function (error, result) {\r\n if (error) throw error;\r\n console.log(result);\r\n});\r\n
\r\n\r\nThe .NET code implements the multiplyBy2 function. It generates two numbers, calls back into the add
function exported from node.js to add them, multiples the result by 2 in .NET, and returns the result back to node.js:\r\n\r\nc#\r\nusing System;\r\nusing System.Collections.Generic;\r\nusing System.Threading.Tasks;\r\n\r\nnamespace Edge.Sample\r\n{\r\n public class Startup\r\n {\r\n public async Task<object> Invoke(object input)\r\n {\r\n IDictionary<string, object> payload = (IDictionary<string, object>)input;\r\n Func<object, Task<object>> add = (Func<object, Task<object>>)payload["add"];\r\n var twoNumbers = new { a = 2, b = 3 };\r\n var addResult = (int)await add(twoNumbers);\r\n return addResult * 2;\r\n }\r\n }\r\n}\r\n
\r\n\r\nThe node.js function exported from node.js to .NET must follow the prescriptive async pattern of accepting two parameters: payload and a callback. The callback function accepts two parametrs. The first one is the error, if any, and the second the result of the operation:\r\n\r\njavasctipt\r\nfunction (payload, callback) {\r\n var error; // must be null or undefined in the absence of error\r\n var result; \r\n\r\n // do something\r\n\r\n callback(error, result);\r\n}\r\n
\r\n\r\nThe proxy to that function in .NET has the following signature:\r\n\r\nc#\r\nFunc<object,Task<object>>\r\n
\r\n\r\nUsin TPL in CLR to provide a proxy to an asynchronous node.js function allows the .NET code to use the convenience of the await
keyword when invoking the node.js functionality. The example above shows the use of the await
keyword when calling the proxy of the node.js add
method. \r\n\r\n## How to: exceptions\r\n\r\nEdge.js marshals node.js errors and exceptions to .NET as well as .NET exceptions to node.js. \r\n\r\nCLR exceptions thrown in .NET code invoked from node.js are marshaled as the error
parameter to the node.js callback function. Consider this .NET code:\r\n\r\nc#\r\npublic Task<object> Invoke(object input)\r\n{\r\n throw new Exception("Sample .NET exception");\r\n}\r\n
\r\n\r\nAnd the node.js code that invokes this .NET function and re-throws the error
parameter passed to the JavaScript callback function:\r\n\r\njavascript\r\nvar edge = require(\'edge\');\r\n\r\nvar clrFunc = edge.func(\'Edge.Sample.dll\');\r\n\r\nclrFunc(null, function (error, result) {\r\n if (error) throw error;\r\n});\r\n
\r\n\r\nRunning this node.js application shows that the CLR exception was indeed received by the node.js callback. The error
parameter contains the full stack trace including the CLR code path:\r\n\r\n\r\nC:\\projects\\barebones>node sample.js\r\n\r\nc:\\projects\\edge\\lib\\edge.js:58\r\n edge.callClrFunc(appId, data, callback);\r\n ^\r\nSystem.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.Excep\r\ntion: Sample .NET exception\r\n at Edge.Sample.Startup.Invoke(Object input) in c:\\projects\\barebones\\sample.cs:line 12\r\n
\r\n\r\nJavaScript exceptions thrown in node.js code invoked from .NET are wrapped in a CLR exception and cause the asynchronous Task<object>
to complete with a failure. Errors passed by node.js code invoked from .NET code to the callback function's error
parameter have the same effect. \r\n\r\nThis node.js code invokes a .NET routine and exports the aFunctionThatThrows
JavaScript function to it:\r\n\r\njavascript\r\nvar edge = require(\'edge.js\');\r\nvar multiplyBy2 = edge.func(\'Edge.Sample.dll\');\r\n\r\nvar payload = {\r\n someParameter: \'arbitrary parameter\',\r\n aFunctionThatThrows: function (data, callback) {\r\n throw new Error(\'Sample JavaScript error\');\r\n }\r\n};\r\n\r\nmultiplyBy2(payload, function (error, result) {\r\n if (error) throw error;\r\n console.log(result);\r\n});\r\n
\r\n\r\nThe .NET code calls the node.js function, catches any resulting CLR exceptions, and displays them:\r\n\r\nc#\r\npublic async Task<object> Invoke(object input)\r\n{\r\n IDictionary<string, object> payload = (IDictionary<string, object>)input;\r\n Func<object, Task<object>> aFunctionThatThrows = (Func<object, Task<object>>)payload["aFunctionThatThrows"];\r\n try {\r\n var aResult = await aFunctionThatThrows(null);\r\n }\r\n catch(Exception e)\r\n {\r\n Console.WriteLine(e);\r\n }\r\n\r\n return null;\r\n}\r\n
\r\n\r\nRunning the code shows the .NET code receiving a CLR exception as a result of the node.js function throwing a JavaScript error. The exception shows the complete stack trace, including the part that executed in the node.js code:\r\n\r\n\r\nC:\\projects\\barebones>node sample.js\r\nSystem.Exception: Error: Sample JavaScript error\r\n at payload.aFunctionThatThrows (C:\\projects\\barebones\\sample.js:7:11)\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at Edge.Sample.Startup.<Invoke>d__0.MoveNext()\r\n
\r\n\r\n## How to: debugging\r\n\r\nYou can debug the .NET code running as part of your node.js application by attaching a managed code debugger (e.g. Visual Studio) to node.exe. This method is currently only available if you integrated a pre-compiled CLR assembly with node.js as opposed to embedding C# literals in the application. Since the node.exe process runs both native and managed code, make sure to select the appropriate language to target:\r\n\r\n\r\n\r\n## Building\r\n\r\nYou must have Visual Studio 2012 toolset as well as Python 2.7.x installed for building.\r\n\r\nTo build one of the versions of node.js officially released by node.js, do the following:\r\n\r\n
\r\ncd tools\r\nbuild.bat release 0.10.0\r\ncd ..\r\nnpm install\r\n
\r\n\r\nNote: the node.js version number you provide must be version number corresponding to one of the subdirectories of http://nodejs.org/dist. The command will build both x32 and x63 architectures (assuming you use x64 machine). The command will also copy the edge.node executables to appropriate locations under lib\native directory where they are looked up from at runtime. The npm install
step copies the C standard library shared DLL to the location of the edge.node for the ocmponent to be ready to go.\r\n\r\nTo build the C++\CLI native extension using the version of node.js installed on your machine, issue the followig command:\r\n\r\n\r\nnpm install -g node-gyp\r\nnode-gyp configure --msvs_version=2012\r\nnode-gyp build -debug\r\n
\r\n\r\nYou can then set the EDGE_NATIVE environment variable to the fully qualified file name of the built edge.node binary. It is useful during development, for example:\r\n\r\n\r\nset EDGE_NATIVE=C:\\projects\\edge\\build\\Debug\\edge.node\r\n
\r\n\r\nYou can also set the EDGE_DEBUG
environment variable to 1 to have the edge module generate debug traces to the console when it runs.\r\n\r\n## Running tests\r\n\r\nYou must run tests from a place that has csc.exe
to VS 2012 tooset on the PATH, for example the VS 2012 developer command prompt. To run the tests using the version node.js installed you your system:\r\n\r\n\r\nnpm test\r\n
\r\n\r\nThis first builds a CLR assembly in C# that contains the .NET code of the tests, and then runs the tests with mocha.\r\n\r\nIf you want to run tests after building against a specific version of node.js that one of the previous builds used, issue the following command:\r\n\r\n\r\ncd test\r\ntest.bat ia32 0.10.0\r\n
\r\n\r\nWhich will run the tests using node.js x86 v0.1.0. Similarly:\r\n\r\n\r\ncd test\r\ntest.bat x64 0.8.22\r\n
\r\n\r\nWould run tests agsinst node.js 0.8.22 on x64 architecture.\r\n\r\n## Contribution and derived work\r\n\r\nI do welcome contributions via pull request and derived work. \r\n\r\nThe edge module is intended to remain a very small component with core functionality that supports interop between .NET and node.js. Domain specific functionality (e.g. access to SQL, writing to ETW, writing connect middleware in .NET) should be implemented as separate modules with a dependency on edge. When you have a notable derived work, I would love to know about it to include a pointer here. \r\n\r\n## More\r\n\r\nIssues? Feedback? You know what to do. Pull requests welcome.\r\n',
39 silly resolved readmeFilename: 'README.md',
39 silly resolved _id: '[email protected]',
39 silly resolved _from: 'edge@' } ]
40 info install [email protected] into C:\Program Files\nodejsApps\edge
41 info installOne [email protected]
42 verbose from cache C:\Users\mag.NEWNECSY\AppData\Roaming\npm-cache\edge\0.7.1\package\package.json
43 info C:\Program Files\nodejsApps\edge\node_modules\edge unbuild
44 verbose read json C:\Program Files\nodejsApps\edge\node_modules\edge\package.json
45 verbose tar unpack C:\Users\mag.NEWNECSY\AppData\Roaming\npm-cache\edge\0.7.1\package.tgz
46 silly lockFile b4325955-odejsApps-edge-node-modules-edge C:\Program Files\nodejsApps\edge\node_modules\edge
47 verbose lock C:\Program Files\nodejsApps\edge\node_modules\edge C:\Users\mag.NEWNECSY\AppData\Roaming\npm-cache\b4325955-odejsApps-edge-node-modules-edge.lock
48 silly lockFile aaffca0d-npm-cache-edge-0-7-1-package-tgz C:\Users\mag.NEWNECSY\AppData\Roaming\npm-cache\edge\0.7.1\package.tgz
49 verbose lock C:\Users\mag.NEWNECSY\AppData\Roaming\npm-cache\edge\0.7.1\package.tgz C:\Users\mag.NEWNECSY\AppData\Roaming\npm-cache\aaffca0d-npm-cache-edge-0-7-1-package-tgz.lock
50 silly gunzTarPerm modes [ '755', '644' ]
51 silly gunzTarPerm extractEntry package.json
52 silly gunzTarPerm modified mode [ 'package.json', 438, 420 ]
53 silly gunzTarPerm extractEntry .npmignore
54 silly gunzTarPerm modified mode [ '.npmignore', 438, 420 ]
55 silly gunzTarPerm extractEntry README.md
56 silly gunzTarPerm modified mode [ 'README.md', 438, 420 ]
57 silly gunzTarPerm extractEntry binding.gyp
58 silly gunzTarPerm modified mode [ 'binding.gyp', 438, 420 ]
59 silly gunzTarPerm extractEntry lib/edge.js
60 silly gunzTarPerm modified mode [ 'lib/edge.js', 438, 420 ]
61 silly gunzTarPerm extractEntry lib/native/win32/ia32/0.10.0/.npmignore
62 silly gunzTarPerm modified mode [ 'lib/native/win32/ia32/0.10.0/.npmignore', 438, 420 ]
63 silly gunzTarPerm extractEntry lib/native/win32/ia32/0.10.0/edge.node
64 silly gunzTarPerm modified mode [ 'lib/native/win32/ia32/0.10.0/edge.node', 438, 420 ]
65 silly gunzTarPerm extractEntry lib/native/win32/ia32/0.8.22/.npmignore
66 silly gunzTarPerm modified mode [ 'lib/native/win32/ia32/0.8.22/.npmignore', 438, 420 ]
67 silly gunzTarPerm extractEntry lib/native/win32/ia32/0.8.22/edge.node
68 silly gunzTarPerm modified mode [ 'lib/native/win32/ia32/0.8.22/edge.node', 438, 420 ]
69 silly gunzTarPerm extractEntry lib/native/win32/ia32/msvcr110.dll
70 silly gunzTarPerm modified mode [ 'lib/native/win32/ia32/msvcr110.dll', 438, 420 ]
71 silly gunzTarPerm extractEntry lib/native/win32/x64/0.10.0/.npmignore
72 silly gunzTarPerm modified mode [ 'lib/native/win32/x64/0.10.0/.npmignore', 438, 420 ]
73 silly gunzTarPerm extractEntry lib/native/win32/x64/0.10.0/edge.node
74 silly gunzTarPerm modified mode [ 'lib/native/win32/x64/0.10.0/edge.node', 438, 420 ]
75 silly gunzTarPerm extractEntry lib/native/win32/x64/0.8.22/.npmignore
76 silly gunzTarPerm modified mode [ 'lib/native/win32/x64/0.8.22/.npmignore', 438, 420 ]
77 silly gunzTarPerm extractEntry lib/native/win32/x64/0.8.22/edge.node
78 silly gunzTarPerm modified mode [ 'lib/native/win32/x64/0.8.22/edge.node', 438, 420 ]
79 silly gunzTarPerm extractEntry lib/native/win32/x64/msvcr110.dll
80 silly gunzTarPerm modified mode [ 'lib/native/win32/x64/msvcr110.dll', 438, 420 ]
81 silly gunzTarPerm extractEntry LICENSE.txt
82 silly gunzTarPerm modified mode [ 'LICENSE.txt', 438, 420 ]
83 silly gunzTarPerm extractEntry src/clrfunc.cpp
84 silly gunzTarPerm modified mode [ 'src/clrfunc.cpp', 438, 420 ]
85 silly gunzTarPerm extractEntry src/clrfuncinvokecontext.cpp
86 silly gunzTarPerm modified mode [ 'src/clrfuncinvokecontext.cpp', 438, 420 ]
87 silly gunzTarPerm extractEntry src/edge.cpp
88 silly gunzTarPerm modified mode [ 'src/edge.cpp', 438, 420 ]
89 silly gunzTarPerm extractEntry src/edge.h
90 silly gunzTarPerm modified mode [ 'src/edge.h', 438, 420 ]
91 silly gunzTarPerm extractEntry src/edgejavascriptconverter.cpp
92 silly gunzTarPerm modified mode [ 'src/edgejavascriptconverter.cpp', 438, 420 ]
93 silly gunzTarPerm extractEntry src/nodejsfunc.cpp
94 silly gunzTarPerm modified mode [ 'src/nodejsfunc.cpp', 438, 420 ]
95 silly gunzTarPerm extractEntry src/nodejsfuncinvokecontext.cpp
96 silly gunzTarPerm modified mode [ 'src/nodejsfuncinvokecontext.cpp', 438, 420 ]
97 silly gunzTarPerm extractEntry src/utils.cpp
98 silly gunzTarPerm modified mode [ 'src/utils.cpp', 438, 420 ]
99 silly gunzTarPerm extractEntry test/101_edge_func.js
100 silly gunzTarPerm modified mode [ 'test/101_edge_func.js', 438, 420 ]
101 silly gunzTarPerm extractEntry test/103_net2node.js
102 silly gunzTarPerm modified mode [ 'test/103_net2node.js', 438, 420 ]
103 silly gunzTarPerm extractEntry test/104_csx.js
104 silly gunzTarPerm modified mode [ 'test/104_csx.js', 438, 420 ]
105 silly gunzTarPerm extractEntry test/105_node2net_sync.js
106 silly gunzTarPerm modified mode [ 'test/105_node2net_sync.js', 438, 420 ]
107 silly gunzTarPerm extractEntry test/102_node2net.js
108 silly gunzTarPerm modified mode [ 'test/102_node2net.js', 438, 420 ]
109 silly gunzTarPerm extractEntry test/tests.cs
110 silly gunzTarPerm modified mode [ 'test/tests.cs', 438, 420 ]
111 silly gunzTarPerm extractEntry test/hello_class.cs
112 silly gunzTarPerm modified mode [ 'test/hello_class.cs', 438, 420 ]
113 silly gunzTarPerm extractEntry test/hello_class.csx
114 silly gunzTarPerm modified mode [ 'test/hello_class.csx', 438, 420 ]
115 silly gunzTarPerm extractEntry test/hello_lambda.csx
116 silly gunzTarPerm modified mode [ 'test/hello_lambda.csx', 438, 420 ]
117 silly gunzTarPerm extractEntry test/test.bat
118 silly gunzTarPerm modified mode [ 'test/test.bat', 438, 420 ]
119 silly gunzTarPerm extractEntry test/build.bat
120 silly gunzTarPerm modified mode [ 'test/build.bat', 438, 420 ]
121 silly gunzTarPerm extractEntry tools/checkplatform.js
122 silly gunzTarPerm modified mode [ 'tools/checkplatform.js', 438, 420 ]
123 silly gunzTarPerm extractEntry tools/download.js
124 silly gunzTarPerm modified mode [ 'tools/download.js', 438, 420 ]
125 silly gunzTarPerm extractEntry tools/build.bat
126 silly gunzTarPerm modified mode [ 'tools/build.bat', 438, 420 ]
127 silly gunzTarPerm extractEntry tools/install.bat
128 silly gunzTarPerm modified mode [ 'tools/install.bat', 438, 420 ]
129 verbose read json C:\Program Files\nodejsApps\edge\node_modules\edge\package.json
130 silly lockFile b4325955-odejsApps-edge-node-modules-edge C:\Program Files\nodejsApps\edge\node_modules\edge
131 silly lockFile b4325955-odejsApps-edge-node-modules-edge C:\Program Files\nodejsApps\edge\node_modules\edge
132 silly lockFile aaffca0d-npm-cache-edge-0-7-1-package-tgz C:\Users\mag.NEWNECSY\AppData\Roaming\npm-cache\edge\0.7.1\package.tgz
133 silly lockFile aaffca0d-npm-cache-edge-0-7-1-package-tgz C:\Users\mag.NEWNECSY\AppData\Roaming\npm-cache\edge\0.7.1\package.tgz
134 info preinstall [email protected]
135 verbose from cache C:\Program Files\nodejsApps\edge\node_modules\edge\package.json
136 verbose readDependencies using package.json deps
137 verbose from cache C:\Program Files\nodejsApps\edge\node_modules\edge\package.json
138 verbose readDependencies using package.json deps
139 silly resolved []
140 verbose about to build C:\Program Files\nodejsApps\edge\node_modules\edge
141 info build C:\Program Files\nodejsApps\edge\node_modules\edge
142 verbose from cache C:\Program Files\nodejsApps\edge\node_modules\edge\package.json
143 verbose linkStuff [ false,
143 verbose linkStuff false,
143 verbose linkStuff false,
143 verbose linkStuff 'C:\Program Files\nodejsApps\edge\node_modules' ]
144 info linkStuff [email protected]
145 verbose linkBins [email protected]
146 verbose linkMans [email protected]
147 verbose rebuildBundles [email protected]
148 info install [email protected]
149 verbose unsafe-perm in lifecycle true
150 silly exec cmd "/c" "tools\install.bat"
151 silly cmd,/c,tools\install.bat,C:\Program Files\nodejsApps\edge\node_modules\edge spawning
152 info [email protected] Failed to exec install script
153 info C:\Program Files\nodejsApps\edge\node_modules\edge unbuild
154 verbose from cache C:\Program Files\nodejsApps\edge\node_modules\edge\package.json
155 info preuninstall [email protected]
156 info uninstall [email protected]
157 verbose true,C:\Program Files\nodejsApps\edge\node_modules,C:\Program Files\nodejsApps\edge\node_modules unbuild [email protected]
158 info postuninstall [email protected]
159 error [email protected] install: tools\install.bat
159 error cmd "/c" "tools\\install.bat"
failed with 8
160 error Failed at the [email protected] install script.
160 error This is most likely a problem with the edge package,
160 error not with npm itself.
160 error Tell the author that this fails on your system:
160 error tools\install.bat
160 error You can get their info via:
160 error npm owner ls edge
160 error There is likely additional logging output above.
161 error System Windows_NT 6.1.7601
162 error command "C:\Program Files\nodejs\node.exe" "C:\Program Files\nodejs\node_modules\npm\bin\npm-cli.js" "install" "edge"
163 error cwd C:\Program Files\nodejsApps\edge
164 error node -v v0.10.0
165 error npm -v 1.2.14
166 error code ELIFECYCLE
167 verbose exit [ 1, true ]
"Configuring a C# object after the first Invoke has happened is not straight forward either. Yes, I am misusing owin here. I do my own dispatching depending on a property in the payload. Ideally owin would provide a configurable object wrapping mechanism as well."
[Tomasz Janczuk] This is where the slippery slope starts I think. I specifically wanted to avoid introducing the concept of an “object” into the framework and instead stick with lambdas as something you can proxy to. Would it address your scenario if the .NET code could return a Func<object,Task> instance back to node.js as a return value (or part of a return value payload)? You can then capture whatever context you need in a closure of such func.
An EventEmitter instance that listens to a couple of events, how to trigger it from inside the the .NET module?
Hi,
Is it possible to call native 32-bit dll from .NET code in edge.js, using node.js x64 on Windows x64?
In console .NET application I can call my old 32-bit native dll (by DllImport). But using the same code with edge.js i get BadImageException. The same result I get If I try call x86 .NET assembly.
So, I have to use x86 node.js because of using some legacy x86 components?
Another question, how about COM-s?
I saw that IIS-node uses only x86 node.js. I have no special requirements for x64 for my app (but of course x64 version would be more great on x64 machines). So I should use x86 version, shouldn't I?
var func = edge.func(function () {/*
async (input) =>
{
return (Func<object,Task<object>>)(async (i) => { return "Hello"; });
}
*/});
func(null, function (error, result) {
console.log(result);
});
throws
Unhandled Exception: System.AccessViolationException: Attempted to read or write protected memory. This is often an indi
cation that other memory is corrupt.
at v8.Function.Call(Function* , Local<v8::Value>* , Handle<v8::Object> , Int32 , Handle<v8::Value>* )
at ClrFuncInvokeContext.CompleteOnV8Thread(Handle<v8::Value>* , Boolean completedSynchronously) in c:\projects\edge\s
rc\clrfuncinvokecontext.cpp:line 121
at ClrFunc.Call(Handle<v8::Value>* , Handle<v8::Value> payload, Handle<v8::Value> callback) in c:\projects\edge\src\c
lrfunc.cpp:line 370
at clrFuncProxy(Handle<v8::Value>* , Arguments* args) in c:\projects\edge\src\clrfunc.cpp:line 9
This is to add benchmarks and measure the cost of cross-boundary calls from node.js to .NET. A few numbers that would be useful to understand:
I have a SDK that have an RTE that provides Java .jar files, win32 .dll and x64 .dll, and .NET with two .tlb files. Can this library work with those? I have absolutely no experience with any .NET, but I just want to use the code that communicates via a driver on Windows.
Error: The specified module could not be found.
\10.207.118.155\volume-18-default\f75346505bf53b3e3cf2\81c6b8101b724b59ac8b4a6a4aed623c\site\wwwroot\node_modules\owin\lib\native\win32\ia32\owin.node
at Object.Module._extensions..node (module.js:485:11)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
at Module.require (module.js:362:17)
at require (module.js:378:17)
at Object. (\10.207.118.155\volume-18-default\f75346505bf53b3e3cf2\81c6b8101b724b59ac8b4a6a4aed623c\site\wwwroot\server.js:4:12)
at Module._compile (module.js:449:26)
at Object.Module._extensions..js (module.js:467:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
However, accessinf the file with fs module works fine.
There is a reasonable debugging story for .NET code referenced from a pre-comiled DLL. But there is currently no debugging story for C# code compiled on the fly by node.js. This is to spike on the problem and come up with options, prototype. It is likely related to #16.
This is to provide an edge-csx
module for edge that will allow compiling inline C# script using scriptcs.
When the dust settles one should be able to write code like this (among other interesting idioms):
var myFunc = edge.func('csx', function() {/*
#r "System.Dala.dll"
async (input) =>
{
// do something interesting with ADO.NET
var result;
return result;
}
*/});
myFunc(...);
The packege.json for this app should include both edge
and edge-csx
as a dependency:
{
"dependencies": {
"edge": "0.7.4",
"edge-csx": "0.1.0"
},
...
}
Everything you need to implement edge-csx
should be covered at https://github.com/tjanczuk/edge/wiki/Add-support-for-a-CLR-language. Also make sure to check out https://github.com/tjanczuk/edge-cs for reference implementation in C#.
Hi,
This problem maybe related to #60. However, I'm getting slightly different results. This time I built a demo Node-Webkit app that uses edge as per the code below.
var edge = require('../node_modules/edge')
var helloWorld = edge.func('async (input) => { return ".NET Welcomes " + input.ToString(); }');
helloWorld('JavaScript', function (error, result) {
if (error) throw error;
console.log(result);
});
However, whenever I call it I get the following error:-
Uncaught Error: %1 is not a valid Win32 application.
C:\data\node_modules\edge\lib\native\win32\ia32\0.10.0\edge.node
Obviously a bit different to the problem in #60 !
If I run the same code outside of node-webkit using nodejs it works OK -
This also works OK using Node-Webkit.
var dns = require('../node_modules/native-dns')
var question = dns.Question({
name: 'www.google.com',
type: 'A'
});
var req = dns.Request({
question: question,
server: { address: '8.8.8.8', port: 53, type: 'udp' },
timeout: 1000
});
req.on('timeout', function () {
console.log('Timeout in making request');
});
req.on('message', function (err, answer) {
answer.answer.forEach(function (a) {
console.log(a.address);
});
});
req.on('end', function () {
console.log('Finished processing request');
});
req.send();
Any guidance would be appreciated!
why edge supports only windows x64?
Is support for .NET 4.0:
Just curious. In any case, edge is fantastic.
See #4 (comment)
Hi,
I having problems referencing a external DLL from edge. I've added the DLL to the .NET GAL but I still cannot reference from within edge.
var edge = require('edge');
var hello = edge.func(function () {/*
var listCertificates = edge.func(function() {/*
#r "System.dll"
#r "BouncyCastle.Crypto.dll"
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.OpenSsl;
using System.Text;
using System.IO;
async (data) =>
{
//Requested Certificate Name
X509Name name = new X509Name("CN=Client Cert, C=NL");
*/});
This is the error!
Uncaught System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.InvalidOperationException: Unable to compile C# code.
----> Errors when compiling as a CLR library:
error CS0006: Metadata file 'BouncyCastle.Crypto.dll' could not be found
----> Errors when compiling as a CLR async lambda expression:
error CS0006: Metadata file 'BouncyCastle.Crypto.dll' could not be found
at EdgeCompiler.CompileFunc(IDictionary`2 parameters)
--- End of inner exception stack trace ---
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at ClrFunc.Initialize(Handle<v8::Value>* , Arguments* args) in c:\edge-master-2\edge-master\src\clrfunc.cpp:line 91
Support the ability to create wrappers around C# functions that are guaranteed to complete synchronously. This would result in a node.js function proxy of the form
function(payload)
rather than
function(payload, callback)
will be nice
Just having the scan through the code and it looks like it might be tied to .NET's built-in JavaScriptSerializer? I've found the implementation for that to be quite slow, it would be nice if you could allow the JSON Serialization to be swappable, e.g. we could allow inject a different serializer by implementing a bespoke interface like IJsonConverter
and hook it up in a similar way we do Startup.Invoke
- e.g. maybe if Startup
implements IJsonConverter
we can use that instead?
Otherwise if that's not possible, maybe just allowing JSON strings to be marshaled back and forth, i.e. without the overhead of JavaScriptSerializer, so we can deserialize it ourselves in .NET land.
This is to add a one-file sample showing access to Windows registry from node.js using edge.js.
This is to support hosting node.js within a .NET process while enabling the same interop model between the two.
Code that causes an error:
var edge = require("edge");
var test = edge.func('async (test) => { return new byte[0]; }');
test("test", function(err, res) {
console.log(err);
});
The error caused:
System.IndexOutOfRangeException: Index was outside the bounds of the array.
at ClrFunc.MarshalCLRToV8(Handle<v8::Value>* , Object netdata)
at ClrFuncInvokeContext.CompleteOnV8Thread(Handle<v8::Value>* , Boolean completedSynchronously)
In addition to Buffer <-> byte[] marshalling, consider support for direct marshaling of JavaScrip typed arrays: https://developer.mozilla.org/en-US/docs/JavaScript/Typed_arrays
E.g.
//#r "System.IO.Compression.FileSystem.dll"
async (input) =>
{
System.IO.Compression.ZipFile.ExtractToDirectory(...);
return null;
}
Hi, is there a way to load the config for DLL?
Now, I build a C# library and it has a config file for the library. But, I do not know how to load the config for the library.
Any help?
The edge-connect project that builds on top of edge.js is looking for someone who can show love, passion, and respect.
The goal is to allow people to plug in existing OWIN .NET applications as express.js request handlers or connect middleware. If you are passionate about web frameworks, this may be for you.
Currently, running
npm install edge
on OSX causes the following output
sh: toolsinstall.bat: command not found
npm ERR! [email protected] install: `tools\install.bat`
npm ERR! `sh "-c" "tools\\install.bat"` failed with 127
npm ERR!
npm ERR! Failed at the [email protected] install script.
npm ERR! This is most likely a problem with the edge package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR! tools\install.bat
npm ERR! You can get their info via:
npm ERR! npm owner ls edge
which shows that npm is trying to execute a batch script on the shell.
I know edge doesn't target darwin platforms, but this should fail more gracefully. Maybe, follow through with npm's recommendation on using the "os" key in the package.json file.
Hi,
Is there any chance you could provide a quick example of using edge to interact with the MS certificate/key store using the .NET X509Store class.
http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509store.aspx
I.e is it possible to use edge to maybe return a list of the certificates or add a new certificate?
I was going to use nodes child process to interact with the 'certmgr' via the CLI but edge seems to provide a much more elegant alternative.
Hi,
I've built a basic demo application using AppJS/NodeJS and edge.
Heres the relevant part of the the app.js config file - Basically it just references the external modules.
.......
window.on('ready', function(){
console.log("Window Ready");
window.process = process;
window.module = module;
window.dns = require('native-dns');
window.edge = require('edge');
window.fs = require('fs');
window.frame.openDevTools();
..........
And heres the relevant javascript part of the main index.html page:
.......
function myFunction1()
{
var question = dns.Question({
name: 'www.google.com',
type: 'A'
});
var req = dns.Request({
question: question,
server: { address: '8.8.8.8', port: 53, type: 'udp' },
timeout: 1000
});
req.on('timeout', function () {
console.log('Timeout in making request');
});
req.on('message', function (err, answer) {
answer.answer.forEach(function (a) {
console.log(a.address);
});
});
req.on('end', function () {
console.log('Finished processing request');
});
req.send();
}
function myFunction2()
{
var helloWorld = edge.func('async (input) => { return ".NET Welcomes " + input.ToString(); }');
helloWorld('JavaScript', function (error, result) {
if (error) throw error;
console.log(result);
});
}
..........
If I call myFunction1() which uses another nodejs module (DNS lookup) it works perfectly. However if I call myFunction2() which uses edge I get the following error!
Uncaught TypeError: Property 'func' of object [object Object] is not a function
I've spent hours on this and for cannot work out why this happening!
When calling back into JS from CLR the JS function has to invoke a passed in callback to the CLR again to continue the CLR code in case of an await on the call to JS. If CLR only wants to fire an event in JS and doesn't need to await the return of the callback the pattern can be simplified.
This code highlights a deadlock in acquiring a lock necessary to switch back to V8 thread.
Root cause. The entire code in the example executes synchronously on V8 thread given an optimization put in place in 0.7.2. The first function call from JS to CLR acquires a singleton ticket to switch back to V8 thread. It then enqueues an event in the libuv event loop, which, when processed, will release the ticket to subsequent callers. However, the second invocation if the function on the same thread attempts to acquire the ticket again for its own transition back to V8 thread and blocks, since the ticket is not available. The call stack of the V8 thread does not unwind back the libuv event loop, which prevents the release of the ticket by the subsequent event.
The fix will be to execute continuation synchronously when an attempt is made to switch back to V8 thread while on V8 thread.
If you are passionate about F# and would like to help enable running F# and node.js in one process, please consider contributing your time and energy to add F# support to edge.js.
Edge.js project enables in-process interop between node.js and CLR. Currently it supports dynamic compilation and running of C# code inside of a node.js application. It also provides an extensibility mechanism that enables support for other CLR languages. This issue is about extending language support of edge.js to include F#.
To get started, read the overview of the edge.js project as well as the documentation for C# to understand the concepts of edge.js.
Then read about the language extensibility model of edge.js to understand how to support new CLR languages in edge.js.
If you have any questions or comments, please use this issue to discuss. Thank you for your time, effort, and expertise.
First, I think that this project is awesome...
That said, here are a few suggestions...
If you are passionate about Python and would like to help enable running Python and node.js in one process, please consider contributing your time and energy to add Python support to edge.js.
Edge.js project enables in-process interop between node.js and CLR. Currently it supports dynamic compilation and running of C# code inside of a node.js application. It also provides an extensibility mechanism that enables support for other CLR languages. This issue is about extending language support of edge.js to include IronPython.
To get started, read the overview of the edge.js project as well as the documentation for C# to understand the concepts of edge.js.
Then read about the language extensibility model of edge.js to understand how to support new CLR languages in edge.js.
If you have any questions or comments, please use this issue to discuss. Thank you for your time, effort, and expertise.
This is to allow replacing currently hardcoded CodeDom based C# .NET script compilation with a custom compilation engine. The engine would need to take .NET script and normalize it to Func<object,Task<object>>
in an in-memory assembly.
Potential use cases:
Edge.js core throws a CAS exception when attempting to load edge-cs.dll C# compiler DLL (or an application DLL with C# code). This is because the DLL resides on a UNC share which is in the "internet" security zone.
The fix is to load compiler DLLs as well as application DLLs using Assembly::UnsageLoadFrom rather than Assembly::LoadFrom.
Running it directly under node (not in IIS) makes node (ia32 / 0.8.22) crash with the following exception
Unhandled Exception: System.AccessViolationException: Attempted to read or write protected memory. This is often an indication t
hat other memory is corrupt.
at v8.Function.Call(Function* , Local<v8::Value>* , Handle<v8::Object> , Int32 , Handle<v8::Value>* )
at ClrFuncInvokeContext.CompleteOnV8Thread(Handle<v8::Value>* , Boolean completedSynchronously)
at ClrFuncInvokeContext.CompleteOnV8ThreadAsynchronous()
at continueOnV8Thread(uv_async_s* handle, Int32 status)
server.js:
var express = require('express'),
path = require('path'),
http = require('http'),
edge = require('edge'),
edgetest = edge.func('sql-all.csx');
var app = express();
app.configure(function () {
app.set('port', process.env.PORT);
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.static(path.join(__dirname, 'public')));
});
app.get('/', function(req, res) {
var params = [], results = [];
edgetest(
{
params: params,
row: function(data, callback) {
//console.log(data);
results.push(data);
callback();
}
},
function(error, ret) {
if (error) console.log('ERROR: ' + error);
res.send(results);
res.end();
}
);
});
http.createServer(app).listen(app.get('port'), function () {
console.log('Server listening on port ' + app.get('port'));
});
sql-all.csx:
// Overview of edge.js: http://tjanczuk.github.com/edge
//#r "System.dll"
//#r "System.Data.dll"
//#r "System.Web.Extensions.dll"
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using System.Web.Script.Serialization;
public class Startup
{
public async Task<object> Invoke(object input)
{
IDictionary<string, object> payload = (IDictionary<string, object>)input;
object[] parameters = (object[])payload["params"] ?? null;
Func<object, Task<object>> onRow = (Func<object, Task<object>>)payload["row"];
return await this.CallbackAsync(parameters, onRow);
}
async Task<object> CallbackAsync(object[] parameters, Func<object, Task<object>> rowCallback)
{
int rowCount = 0;
IList<Task<object>> rowEvents = new List<Task<object>>();
IDictionary<string, object> row = new Dictionary<string, object>();
for (int i = 0; i < 5000; ++i)
{
row.Clear();
for (int j = 0; j < 25; j++)
{
row.Add(j.ToString(), j);
}
if (rowCallback != null) rowEvents.Add(rowCallback(row));
rowCount++;
}
await Task.WhenAll(rowEvents);
return rowCount;
}
}
This is to design and add stress tests to test the behavior of the system, in particular interactions with GC, under load.
Currently edge expects to find the EdgeCompiler class in the global namespace of an assembly. To support multiple edge compilers per assembly as well as disambiguate compilers in C# apps (e.g. tests) it would be useful to support edge compilers in a non-global namespace.
Two solutions that come to mind:
Edge.foo.EdgeCompiler
class. In case of C# that could be Edge.cs.EdgeComiler
. In case of Python it would be Edge.py.EdgeCompiler
.I like 2 better.
npm install owin
fails with node version v0.10.0.
see package.json:
...
"engines": {
"node": "0.8.x"
},
...
First of all, this is awesome ... thanks for putting this together.
I am trying to build the module to use in node-webkit, following the instructions here
https://github.com/rogerwang/nw-gyp
I get the following errors ...
C:\owin-master>nw-gyp build
gyp info it worked if it ends with ok
gyp info using [email protected]
gyp info using [email protected] | win32 | x64
gyp info spawn msbuild
gyp info spawn args [ 'build/binding.sln',
gyp info spawn args '/clp:Verbosity=minimal',
gyp info spawn args '/nologo',
gyp info spawn args '/p:Configuration=Release;Platform=Win32' ]
Building the projects in this solution one at a time. To enable parallel build,
please add the "/m" switch.
utils.cpp
clrfuncinvokecontext.cpp
nodejsfunc.cpp
owinjavascriptconverter.cpp
c:\owin-master\src\owin.h(135): error C2217: 'override' requires 'virtual' [C:
owin-master\build\owin.vcxproj]
c:\owin-master\src\owin.h(135): error C2217: 'override' requires 'virtual' [C:
owin-master\build\owin.vcxproj]
c:\owin-master\src\owin.h(135): error C2217: 'override' requires 'virtual' [C:
owin-master\build\owin.vcxproj]
c:\owin-master\src\owin.h(143): error C2217: 'override' requires 'virtual' [C:
owin-master\build\owin.vcxproj]
c:\owin-master\src\owin.h(143): error C2217: 'override' requires 'virtual' [C:
owin-master\build\owin.vcxproj]
c:\owin-master\src\owin.h(143): error C2217: 'override' requires 'virtual' [C:
owin-master\build\owin.vcxproj]
c:\owin-master\src\owin.h(135): error C2217: 'override' requires 'virtual' [C:
owin-master\build\owin.vcxproj]
c:\owin-master\src\owin.h(147): error C2217: 'override' requires 'virtual' [C:
owin-master\build\owin.vcxproj]
c:\owin-master\src\owin.h(147): error C2217: 'override' requires 'virtual' [C:
owin-master\build\owin.vcxproj]
c:\owin-master\src\owin.h(147): error C2217: 'override' requires 'virtual' [C:
owin-master\build\owin.vcxproj]
c:\owin-master\src\owin.h(143): error C2217: 'override' requires 'virtual' [C:
owin-master\build\owin.vcxproj]
c:\owin-master\src\owin.h(147): error C2217: 'override' requires 'virtual' [C:
owin-master\build\owin.vcxproj]
nodejsfuncinvokecontext.cpp
clrfunc.cpp
owin.cpp
c:\owin-master\src\owin.h(135): error C2217: 'override' requires 'virtual' [C:
owin-master\build\owin.vcxproj]
c:\owin-master\src\owin.h(143): error C2217: 'override' requires 'virtual' [C:
owin-master\build\owin.vcxproj]
c:\owin-master\src\owin.h(147): error C2217: 'override' requires 'virtual' [C:
owin-master\build\owin.vcxproj]
c:\owin-master\src\owin.h(135): error C2217: 'override' requires 'virtual' [C:
owin-master\build\owin.vcxproj]
c:\owin-master\src\owin.h(143): error C2217: 'override' requires 'virtual' [C:
owin-master\build\owin.vcxproj]
c:\owin-master\src\owin.h(147): error C2217: 'override' requires 'virtual' [C:
owin-master\build\owin.vcxproj]
c:\owin-master\src\owin.h(135): error C2217: 'override' requires 'virtual' [C:
owin-master\build\owin.vcxproj]
c:\owin-master\src\owin.h(143): error C2217: 'override' requires 'virtual' [C:
owin-master\build\owin.vcxproj]
c:\owin-master\src\owin.h(147): error C2217: 'override' requires 'virtual' [C:
owin-master\build\owin.vcxproj]
gyp ERR! build error
gyp ERR! stack Error: msbuild
failed with exit code: 1
gyp ERR! stack at ChildProcess.onExit (C:\Users\mparsons\AppData\Roaming\npm
\node_modules\nw-gyp\lib\build.js:232:23)
gyp ERR! stack at ChildProcess.EventEmitter.emit (events.js:99:17)
gyp ERR! stack at Process._handle.onexit (child_process.js:678:10)
gyp ERR! System Windows_NT 6.1.7601
gyp ERR! command "node" "C:\Users\mparsons\AppData\Roaming\npm\node_module
s\nw-gyp\bin\nw-gyp.js" "build"
gyp ERR! cwd C:\owin-master
gyp ERR! node -v v0.8.21
gyp ERR! nw-gyp -v v0.7.3-4
gyp ERR! not ok
Any chance you could have a look at this?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.