Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove JSNativeApi.cs #187

Merged
merged 13 commits into from
Jan 27, 2024
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)
vmoroz marked this conversation as resolved.
Show resolved Hide resolved
{
_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
Loading