Skip to content

Latest commit

 

History

History
163 lines (131 loc) · 5.04 KB

presentation.md

File metadata and controls

163 lines (131 loc) · 5.04 KB
marp theme backgroundColor backgroundImage
true
gaia

bg vertical left:30% 75% bg vertical left:30% 75%


Node API for .NET

High-performance in-proc interop
between .NET and JavaScript

github.com/microsoft/node-api-dotnet Jason Ginchereau @jasongin Vladimir Morozov @vmoroz


Project Vision

First-class in-proc interopability between .NET and JavaScript

Motivation

.NET and JavaScript are widely used, and often complementary, but there is not a great interop story between them.

While some limited solutions exist, there are opportunities to do better in many ways!


Primary .NET / JS Interop scenarios

  1. Dynamically invoke .NET APIs (system or app assemblies) from JS.
  2. Develop a Node.js addon module in C#.
  3. Host a JS runtime within a .NET app and call JS APIs from .NET.

Requirements:

  • .NET 6 or later
  • Windows, Mac, or Linux

Dynamically invoke .NET APIs from JS

const dotnet =require('node-api-dotnet');
dotnet.Console.WriteLine('Hello from .NET!');

const MyAssembly = dotnet.load('path/to/MyAssembly.dll');
const myObj = new MyAssembly.MyClass(...args);



Dynamic invocation has some limitations, e.g. some forms of generics, ref/out params. These can be reduced or eliminated with further development.


Develop Node addon modules in C#

// C#
[JSExport]
public class MyClass {
    public MyClass(string[] args) { }
}
// TypeScript
import { MyClass } from 'my-package';
const myObj = new MyClass(...args);

Option: Use .NET Native AOT to avoid .NET Runtime dependency.


Host a JS runtime in a .NET app

(Under development)

.NET app hosts Node.js or another JS engine in-proc, then uses interop capabilities for deep integration between .NET and JS code.


Demo

Calling Azure OpenAI from JavaScript using the .NET Semantic Kernel library


About Node API

  • C-style API - easy to invoke from C# or other languages
  • ABI stable - works across Node.js versions without recompiling
  • JS engine agnostic - implemented by several JS engines, not just V8


Developers of the Node API for .NET project are current/former members of the Node API working group.

.NET / JS Interop features

  • Automatic marshalling for:
    • Classes & interfaces - passed by reference
    • Structs & enums - passed by value
    • Collections - passed by reference
    • TypedArrays - using shared memory
  • Async support:
    • Automatic conversion between Tasks & Promises
    • SynchronizationContext supports await return to JS thread

More interop features

  • Error/exception propagation
  • .NET delegates / JS callbacks
  • .NET Streams / Node Readable, Writable, Duplex streams
  • JS class can extend a .NET class, TS can implement a .NET interface
  • .NET class extend a JS class, implement a TS interface
  • Option to work directly with JS types
    • JSValue, JSObject, JSArray, JSMap, JSPromise, etc.

TypeScript type definitions

JavaScript or TypeScript code can reference type defintions for .NET APIs.

  • A tool generates typedef files (.d.ts) from .NET assemblies.
  • Nuget package MSBuild scripts automatically do this for C# Node addon projects.

Interop performance

.NET / JS interop is fast because:

  • Marshaling does not use JSON serialization.
  • Compile-time or runtime code generation avoids reflection.
  • Use of shared memory and proxies minimizes data transfer.
  • struct, Span<T>, stackalloc minimize heap allocation & copying.

Performance comparison

Warm JS to .NET calls are nearly twice as fast when compared to edge-js using that project's benchmark.

HTTP Edge.js Node API .NET AOT JS (baseline)
Cold 32039 38761 9355 362 1680
Warm 2003 87 54 47 23

Numbers are microseconds. "Warm" is an average of 10000 .NET -> JS calls (passing a medium-size object).


Project status

  • Available for early experimentation
    • Send feedback, bug reports.
    • Help prioritize areas for improvement.
    • Contribute PRs!
  • Current limitations may block some advanced interop scenarios.
  • NOT production ready

Roadmap

Major development areas:

  • Build/packaging/publishing pipelines
  • More marshalling: events, tuples, ref/out params, generics, ...
  • Hosting JS engines in .NET app
  • More test coverage

Project backlog: https://github.com/users/jasongin/projects/1