Skip to content

Commit

Permalink
Remove JSNativeApi.cs (#187)
Browse files Browse the repository at this point in the history
  • Loading branch information
vmoroz authored Jan 27, 2024
1 parent a9b983a commit 1b708bf
Show file tree
Hide file tree
Showing 40 changed files with 1,904 additions and 1,549 deletions.
34 changes: 24 additions & 10 deletions bench/Benchmarks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ public static void Main(string[] args)
"libnode" + GetSharedLibraryExtension());

private napi_env _env;
private JSValue _jsString;
private JSFunction _jsFunction;
private JSFunction _jsFunctionWithArgs;
private JSFunction _jsFunctionWithCallback;
Expand Down Expand Up @@ -95,13 +96,14 @@ protected void Setup()

// Create some JS values that will be used by the benchmarks.

_jsFunction = (JSFunction)JSNativeApi.RunScript("function jsFunction() { }; jsFunction");
_jsFunctionWithArgs = (JSFunction)JSNativeApi.RunScript(
_jsString = JSValue.RunScript("'Hello Node-API .Net!'");
_jsFunction = (JSFunction)JSValue.RunScript("function jsFunction() { }; jsFunction");
_jsFunctionWithArgs = (JSFunction)JSValue.RunScript(
"function jsFunctionWithArgs(a, b, c) { }; jsFunctionWithArgs");
_jsFunctionWithCallback = (JSFunction)JSNativeApi.RunScript(
_jsFunctionWithCallback = (JSFunction)JSValue.RunScript(
"function jsFunctionWithCallback(cb, ...args) { cb(...args); }; " +
"jsFunctionWithCallback");
_jsInstance = (JSObject)JSNativeApi.RunScript(
_jsInstance = (JSObject)JSValue.RunScript(
"const jsInstance = { method: (...args) => {} }; jsInstance");

_dotnetFunction = (JSFunction)JSValue.CreateFunction(
Expand All @@ -125,15 +127,15 @@ protected void Setup()
(x, value) => x.Property = (string)value);
classBuilder.AddMethod("method", (x) => (args) => DotnetClass.Method());
_dotnetClass = (JSObject)classBuilder.DefineClass();
_dotnetInstance = (JSObject)JSNativeApi.CallAsConstructor(_dotnetClass);
_dotnetInstance = (JSObject)((JSValue)_dotnetClass).CallAsConstructor();

_jsFunctionCreateInstance = (JSFunction)JSNativeApi.RunScript(
_jsFunctionCreateInstance = (JSFunction)JSValue.RunScript(
"function jsFunctionCreateInstance(Class) { new Class() }; " +
"jsFunctionCreateInstance");
_jsFunctionCallMethod = (JSFunction)JSNativeApi.RunScript(
_jsFunctionCallMethod = (JSFunction)JSValue.RunScript(
"function jsFunctionCallMethod(instance) { instance.method(); }; " +
"jsFunctionCallMethod");
_jsFunctionCallMethodWithArgs = (JSFunction)JSNativeApi.RunScript(
_jsFunctionCallMethodWithArgs = (JSFunction)JSValue.RunScript(
"function jsFunctionCallMethodWithArgs(instance, ...args) " +
"{ instance.method(...args); }; " +
"jsFunctionCallMethodWithArgs");
Expand All @@ -145,6 +147,18 @@ protected void Setup()

// Benchmarks in the base class run in both CLR and AOT environments.

[Benchmark]
public void JSValueToString()
{
_jsString.GetValueStringUtf16();
}

[Benchmark]
public void JSValueToStringAsCharArray()
{
_ = new string(_jsString.GetValueStringUtf16AsCharArray());
}

[Benchmark]
public void CallJSFunction()
{
Expand Down Expand Up @@ -229,13 +243,13 @@ public class Clr : Benchmarks
JSObject hostModule = new();
_ = new ManagedHost(hostModule);
_jsHost = hostModule;
_jsFunctionCallMethodDynamic = (JSFunction)JSNativeApi.RunScript(
_jsFunctionCallMethodDynamic = (JSFunction)JSValue.RunScript(
"function jsFunctionCallMethodDynamic(dotnet) " +
"{ dotnet.System.Object.ReferenceEquals(null, null); }; " +
"jsFunctionCallMethodDynamic");

// Implement IFormatProvider in JS and pass it to a .NET method.
_jsFunctionCallMethodDynamicInterface = (JSFunction)JSNativeApi.RunScript(
_jsFunctionCallMethodDynamicInterface = (JSFunction)JSValue.RunScript(
"function jsFunctionCallMethodDynamicInterface(dotnet) {" +
" const formatProvider = { GetFormat: (type) => null };" +
" dotnet.System.String.Format(formatProvider, '', null, null);" +
Expand Down
198 changes: 109 additions & 89 deletions src/NodeApi.DotNetHost/JSMarshaller.cs

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion src/NodeApi.DotNetHost/JSMarshallerDelegates.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// Licensed under the MIT License.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
Expand Down
3 changes: 1 addition & 2 deletions src/NodeApi.DotNetHost/ManagedHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.Linq;
Expand Down Expand Up @@ -409,7 +408,7 @@ public JSValue LoadModule(JSCallbackArgs args)

if (exports.IsObject())
{
exportsRef = JSNativeApi.CreateReference(exports);
exportsRef = new JSReference(exports);
_loadedModules.Add(assemblyFilePath, exportsRef);
}

Expand Down
1 change: 0 additions & 1 deletion src/NodeApi.DotNetHost/TypeExporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
using System.Linq.Expressions;
using System.Reflection;
using System.Threading.Tasks;
using System.Xml.Linq;
using Microsoft.JavaScript.NodeApi.Interop;

using static Microsoft.JavaScript.NodeApi.DotNetHost.ManagedHost;
Expand Down
1 change: 0 additions & 1 deletion src/NodeApi.Generator/TypeDefinitionsGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
Expand Down
1 change: 0 additions & 1 deletion src/NodeApi/Interop/JSAsyncScope.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// Licensed under the MIT License.

using System;
using System.Threading;

namespace Microsoft.JavaScript.NodeApi.Interop;

Expand Down
4 changes: 2 additions & 2 deletions src/NodeApi/Interop/JSClassBuilderOfT.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ public JSValue DefineClass(JSValue? baseClass = null)
}
else
{
classObject = JSNativeApi.DefineClass(
classObject = JSValue.DefineClass(
ClassName,
new JSCallbackDescriptor(
ClassName,
Expand Down Expand Up @@ -181,7 +181,7 @@ public JSValue DefineInterface()

AddTypeToString();

JSValue obj = JSNativeApi.DefineClass(
JSValue obj = JSValue.DefineClass(
ClassName,
new JSCallbackDescriptor(ClassName, (args) =>
{
Expand Down
11 changes: 5 additions & 6 deletions src/NodeApi/Interop/JSRuntimeContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
using System.Threading;
using Microsoft.JavaScript.NodeApi.Runtime;
using static Microsoft.JavaScript.NodeApi.Interop.JSCollectionProxies;
using static Microsoft.JavaScript.NodeApi.JSNativeApi;
using static Microsoft.JavaScript.NodeApi.Runtime.JSRuntime;

namespace Microsoft.JavaScript.NodeApi.Interop;
Expand All @@ -20,7 +19,7 @@ namespace Microsoft.JavaScript.NodeApi.Interop;
/// </summary>
/// <remarks>
/// A <see cref="JSRuntimeContext"/> instance is constructed when the .NET Node API managed host is
/// loaded, and disposed when the host is unloaded. (For AOT there is no "host" compnoent, so each
/// loaded, and disposed when the host is unloaded. (For AOT there is no "host" component, so each
/// AOT module has a context that matches the module lifetime.) The context tracks several kinds
/// of JS references used internally by this assembly, so that the references can be re-used for
/// the lifetime of the host and disposed when the context is disposed.
Expand Down Expand Up @@ -124,7 +123,7 @@ public static explicit operator napi_env(JSRuntimeContext context)
}

public static explicit operator JSRuntimeContext(napi_env env)
=> GetInstanceData(env) as JSRuntimeContext
=> JSValue.GetInstanceData(env) as JSRuntimeContext
?? throw new InvalidCastException("Context is not found in napi_env instance data.");

public bool IsDisposed { get; private set; }
Expand All @@ -149,7 +148,7 @@ internal JSRuntimeContext(

_env = env;
Runtime = runtime;
SetInstanceData(env, this);
JSValue.SetInstanceData(env, this);
SynchronizationContext = synchronizationContext ?? JSSynchronizationContext.Create();
}

Expand Down Expand Up @@ -260,7 +259,7 @@ internal JSValue InitializeObjectWrapper(JSValue wrapper, JSValue externalInstan
// The reference returned by Wrap() is weak (refcount=0), which is good:
// if the JS object is released then the reference will fail to resolve, and
// GetOrCreateObjectWrapper() will create a new JS wrapper if requested.
JSNativeApi.Wrap(wrapper, obj, out JSReference wrapperWeakRef);
wrapper.Wrap(obj, out JSReference wrapperWeakRef);

_objectMap.AddOrUpdate(
obj,
Expand Down Expand Up @@ -558,7 +557,7 @@ public JSValue CreateStruct<T>() where T : struct
throw new InvalidOperationException("Failed to resolve struct constructor reference.");
}

return JSNativeApi.CallAsConstructor(constructorFunction.Value);
return constructorFunction.Value.CallAsConstructor();
}

/// <summary>
Expand Down
2 changes: 1 addition & 1 deletion src/NodeApi/Interop/JSStructBuilderOfT.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ public JSValue DefineStruct()
AddTypeToString();

// Note this does not use Wrap() because structs are passed by value.
JSValue classObject = JSNativeApi.DefineClass(
JSValue classObject = JSValue.DefineClass(
StructName,
new JSCallbackDescriptor(StructName, (args) => args.ThisArg),
Properties.ToArray());
Expand Down
4 changes: 2 additions & 2 deletions src/NodeApi/Interop/NodeStream.Proxy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ internal static JSValue DefineStreamClass(
// TODO: Consider implementing writev() ?
}).ToArray();

return JSNativeApi.DefineClass(
return JSValue.DefineClass(
className,
new JSCallbackDescriptor(
className,
Expand Down Expand Up @@ -258,7 +258,7 @@ private static async void WriteAsync(
}
catch (Exception ex)
{
bool isExceptionPending5 = JSNativeApi.IsExceptionPending();
bool isExceptionPending5 = JSError.IsExceptionPending();
try
{
callback = callbackReference.GetValue()!.Value;
Expand Down
1 change: 0 additions & 1 deletion src/NodeApi/JSAsyncIterable.Enumerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// Licensed under the MIT License.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;

Expand Down
1 change: 0 additions & 1 deletion src/NodeApi/JSAsyncIterable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// Licensed under the MIT License.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Threading;
Expand Down
83 changes: 83 additions & 0 deletions src/NodeApi/JSBigInt.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using System;
using System.Diagnostics.CodeAnalysis;
using System.Numerics;

namespace Microsoft.JavaScript.NodeApi;

public readonly struct JSBigInt : IEquatable<JSValue>
{
private readonly JSValue _value;

public static explicit operator JSBigInt(JSValue value) => new(value);
public static implicit operator JSValue(JSBigInt value) => value._value;

public static implicit operator JSBigInt(BigInteger value) => new(value);
public static explicit operator BigInteger(JSBigInt value) => value.ToBigInteger();

private JSBigInt(JSValue value)
{
_value = value;
}

public JSBigInt(long value) : this(JSValue.CreateBigInt(value))
{
}

public JSBigInt(ulong value) : this(JSValue.CreateBigInt(value))
{
}

public JSBigInt(int sign, ReadOnlySpan<ulong> words)
: this(JSValue.CreateBigInt(sign, words))
{
}

public JSBigInt(BigInteger value) : this(JSValue.CreateBigInt(value))
{
}

public int GetWordCount() => _value.GetBigIntWordCount();

public void CopyTo(Span<ulong> destination, out int sign, out int wordCount)
=> _value.GetBigIntWords(destination, out sign, out wordCount);

public JSValue AsJSValue() => _value;

public BigInteger ToBigInteger() => _value.ToBigInteger();

public long ToInt64(out bool isLossless) => _value.ToInt64BigInt(out isLossless);

public ulong ToUInt64(out bool isLossless) => _value.ToUInt64BigInt(out isLossless);

public unsafe ulong[] ToUInt64Array(out int sign) => _value.GetBigIntWords(out sign);

/// <summary>
/// Compares two JS values using JS "strict" equality.
/// </summary>
public static bool operator ==(JSBigInt left, JSBigInt right)
=> left._value.StrictEquals(right._value);

/// <summary>
/// Compares two JS values using JS "strict" equality.
/// </summary>
public static bool operator !=(JSBigInt left, JSBigInt right)
=> !left._value.StrictEquals(right._value);

/// <summary>
/// Compares two JS values using JS "strict" equality.
/// </summary>
public bool Equals(JSValue other) => _value.StrictEquals(other);

/// <inheritdoc/>
public override bool Equals([NotNullWhen(true)] object? obj)
=> obj is JSBigInt other && Equals(other)
|| obj is JSValue otherValue && _value.StrictEquals(otherValue);

/// <inheritdoc/>
public override int GetHashCode()
=> throw new NotSupportedException(
"Hashing JS values is not supported. Use JSSet or JSMap instead.");
}
Loading

0 comments on commit 1b708bf

Please sign in to comment.