Skip to content

Commit

Permalink
[wasm] deprecate legacy JS API and propose new (#73068)
Browse files Browse the repository at this point in the history
- Added new API methods to top level next to MONO and BINDING namespaces
- marked MONO and BINDING namespaces obsolete
- separated legacy API into dotnet-legacy.d.ts
- renamed snake_case to camelCase names

Co-authored-by: Marek Fišera <mara@neptuo.com>
Co-authored-by: Ankit Jain <radical@gmail.com>
  • Loading branch information
3 people authored Aug 4, 2022
1 parent 0ea3031 commit 0d80733
Show file tree
Hide file tree
Showing 75 changed files with 1,631 additions and 1,356 deletions.
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,4 @@ src/tests/JIT/Performance/CodeQuality/BenchmarksGame/reverse-complement/revcomp-
src/tests/JIT/Performance/CodeQuality/BenchmarksGame/k-nucleotide/knucleotide-input.txt text eol=lf
src/tests/JIT/Performance/CodeQuality/BenchmarksGame/k-nucleotide/knucleotide-input-big.txt text eol=lf
src/mono/wasm/runtime/dotnet.d.ts text eol=lf
src/mono/wasm/runtime/dotnet-legacy.d.ts text eol=lf
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,8 @@ node_modules/
*.metaproj.tmp
bin.localpkg/
src/mono/wasm/runtime/dotnet.d.ts.sha256
src/mono/wasm/runtime/dotnet-legacy.d.ts.sha256

src/mono/sample/wasm/browser-nextjs/public/

# RIA/Silverlight projects
Expand Down
1 change: 1 addition & 0 deletions eng/liveBuilds.targets
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@
$(LibrariesNativeArtifactsPath)dotnet.js;
$(LibrariesNativeArtifactsPath)src\dotnet-crypto-worker.js;
$(LibrariesNativeArtifactsPath)dotnet.d.ts;
$(LibrariesNativeArtifactsPath)dotnet-legacy.d.ts;
$(LibrariesNativeArtifactsPath)package.json;
$(LibrariesNativeArtifactsPath)dotnet.wasm;
$(LibrariesNativeArtifactsPath)dotnet.js.symbols;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@
<PlatformManifestFileEntry Include="dotnet.worker.js" IsNative="true" />
<PlatformManifestFileEntry Include="dotnet.js.symbols" IsNative="true" />
<PlatformManifestFileEntry Include="dotnet.d.ts" IsNative="true" />
<PlatformManifestFileEntry Include="dotnet-legacy.d.ts" IsNative="true" />
<PlatformManifestFileEntry Include="dotnet.wasm" IsNative="true" />
<PlatformManifestFileEntry Include="dotnet.timezones.blat" IsNative="true" />
<PlatformManifestFileEntry Include="icudt.dat" IsNative="true" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ public static unsafe void Int52TestOK(long value)
long dummy = 0xA6A6A6A6L;
long actual2 = dummy;
var bagFn = new Function("ptr", "ptr2", @"
const value=globalThis.App.MONO.getI52(ptr);
globalThis.App.MONO.setI52(ptr2, value);
const value=globalThis.App.runtime.getHeapI52(ptr);
globalThis.App.runtime.setHeapI52(ptr2, value);
return ''+value;");

uint ptr = (uint)Unsafe.AsPointer(ref expected);
Expand All @@ -53,8 +53,8 @@ public static unsafe void UInt52TestOK(ulong value)
ulong dummy = 0xA6A6A6A6UL;
ulong actual2 = dummy;
var bagFn = new Function("ptr", "ptr2", @"
const value=globalThis.App.MONO.getI52(ptr);
globalThis.App.MONO.setU52(ptr2, value);
const value=globalThis.App.runtime.getHeapI52(ptr);
globalThis.App.runtime.setHeapU52(ptr2, value);
return ''+value;");

uint ptr = (uint)Unsafe.AsPointer(ref expected);
Expand Down Expand Up @@ -99,14 +99,14 @@ public static unsafe void Int52TestRange(double value)
long actual = 0;
uint ptr = (uint)Unsafe.AsPointer(ref actual);
var bagFn = new Function("ptr", "value", @"
globalThis.App.MONO.setI52(ptr, value);");
globalThis.App.runtime.setHeapI52(ptr, value);");
var ex=Assert.Throws<JSException>(() => bagFn.Call(null, ptr, value));
Assert.Contains("Value is not a safe integer", ex.Message);

double expectedD = value;
uint ptrD = (uint)Unsafe.AsPointer(ref expectedD);
var bagFnD = new Function("ptr", "value", @"
globalThis.App.MONO.getI52(ptr);");
globalThis.App.runtime.getHeapI52(ptr);");
var exD = Assert.Throws<JSException>(() => bagFn.Call(null, ptr, value));
Assert.Contains("Value is not a safe integer", ex.Message);
}
Expand All @@ -118,14 +118,14 @@ public static unsafe void UInt52TestRange(double value)
long actual = 0;
uint ptr = (uint)Unsafe.AsPointer(ref actual);
var bagFn = new Function("ptr", "value", @"
globalThis.App.MONO.setU52(ptr, value);");
globalThis.App.runtime.setHeapU52(ptr, value);");
var ex=Assert.Throws<JSException>(() => bagFn.Call(null, ptr, value));
Assert.Contains("Can't convert negative Number into UInt64", ex.Message);

double expectedD = value;
uint ptrD = (uint)Unsafe.AsPointer(ref expectedD);
var bagFnD = new Function("ptr", "value", @"
globalThis.App.MONO.getU52(ptr);");
globalThis.App.runtime.getHeapU52(ptr);");
var exD = Assert.Throws<JSException>(() => bagFn.Call(null, ptr, value));
Assert.Contains("Can't convert negative Number into UInt64", ex.Message);
}
Expand All @@ -136,7 +136,7 @@ public static unsafe void Int52TestNaN()
long actual = 0;
uint ptr = (uint)Unsafe.AsPointer(ref actual);
var bagFn = new Function("ptr", "value", @"
globalThis.App.MONO.setI52(ptr, value);");
globalThis.App.runtime.setHeapI52(ptr, value);");
var ex=Assert.Throws<JSException>(() => bagFn.Call(null, ptr, double.NaN));
Assert.Contains("Value is not a safe integer: NaN (number)", ex.Message);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ public static void StopProfile()
{
}

// Called by the AOT profiler to save profile data into INTERNAL.aot_profile_data
// Called by the AOT profiler to save profile data into INTERNAL.aotProfileData
[MethodImpl(MethodImplOptions.NoInlining)] // https://github.com/dotnet/runtime/issues/71425
public static unsafe void DumpAotProfileData(ref byte buf, int len, string extraArg)
{
Expand All @@ -133,7 +133,7 @@ public static unsafe void DumpAotProfileData(ref byte buf, int len, string extra
if (module == null)
throw new InvalidOperationException();

module.SetProperty("aot_profile_data", span.ToArray());
module.SetProperty("aotProfileData", span.ToArray());
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ namespace System.Runtime.InteropServices.JavaScript
/// public static partial int librarySum(int a, int b);
/// [JSImport("Math.sum", "my-math-helper")]
/// public static partial int libraryNamespaceSum(int a, int b);
/// [JSImport("IMPORTS.sum")]
/// public static partial int runtimeImportsSum(int a, int b);
/// [JSImport("globalThis.Math.sum")]
/// public static partial int globalSum(int a, int b);
/// </code>
Expand All @@ -31,7 +29,7 @@ namespace System.Runtime.InteropServices.JavaScript
public sealed class JSImportAttribute : Attribute
{
/// <summary>
/// The name of the target JavaScript function. This name will be used as a key to locate the function in the IMPORTS JavaScript object owned by the runtime.
/// The name of the target JavaScript function. This name will be used as a key to locate the function in the module.
/// Functions nested inside of objects can be referred to by using the dot operator to connect one or more names.
/// </summary>
public string FunctionName { get; }
Expand All @@ -44,7 +42,7 @@ public sealed class JSImportAttribute : Attribute
/// <summary>
/// Initializes a new instance of the <see cref="JSImportAttribute"/>.
/// </summary>
/// <param name="functionName">Name of the function to be bound in the IMPORTS object of the runtime instance in the JavaScript page. It allows dots for nested objects.</param>
/// <param name="functionName">Name of the function to be bound in the module. It allows dots for nested objects.</param>
public JSImportAttribute(string functionName)
{
FunctionName = functionName;
Expand All @@ -54,7 +52,7 @@ public JSImportAttribute(string functionName)
/// Initializes a new instance of the <see cref="JSImportAttribute"/>.
/// </summary>
/// <param name="functionName">
/// The name of the target JavaScript function. This name will be used as a key to locate the function in the IMPORTS JavaScript object owned by the runtime.
/// The name of the target JavaScript function. This name will be used as a key to locate the function in the module.
/// Functions nested inside of objects can be referred to by using the dot operator to connect one or more names.
/// </param>
/// <param name="moduleName">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -918,13 +918,17 @@ public static JSObject EchoIJSObject([JSMarshalAs<JSType.Object>] JSObject arg1)
}
#endregion JSObject

[JSImport("setup", "JavaScriptTestHelper")]
internal static partial Task Setup();

static JSObject _module;
public static async Task InitializeAsync()
{
if (_module == null)
{
// Log("JavaScriptTestHelper.mjs importing");
_module = await JSHost.ImportAsync("JavaScriptTestHelper", "./JavaScriptTestHelper.mjs");
await Setup();
// Log("JavaScriptTestHelper.mjs imported");
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ class JSData {
constructor(name) {
this.name = name;
}
echoMemberMethod(arg1){
return arg1 + "-w-i-t-h-"+ this.name;
echoMemberMethod(arg1) {
return arg1 + "-w-i-t-h-" + this.name;
}
toString() {
return `JSData("${this.name}")`;
Expand Down Expand Up @@ -146,14 +146,14 @@ export function getClass1() {
// console.log(`getClass1(arg1:${cname !== null ? cname : '<null>'})`)
return cname;
}

let dllExports;
export function invoke1(arg1, name) {
if (globalThis.gc) {
// console.log('globalThis.gc');
globalThis.gc();
}
// console.log(`invoke1: ${name}(arg1:${arg1 !== null ? typeof arg1 : '<null>'})`)
const JavaScriptTestHelper = globalThis.App.EXPORTS.System.Runtime.InteropServices.JavaScript.Tests.JavaScriptTestHelper
const JavaScriptTestHelper = dllExports.System.Runtime.InteropServices.JavaScript.Tests.JavaScriptTestHelper;
const fn = JavaScriptTestHelper[name];

// console.log("invoke1:" + typeof fn);
Expand All @@ -164,8 +164,7 @@ export function invoke1(arg1, name) {
}

export function invoke2(arg1, name) {
const JavaScriptTestHelperNoNamespace = globalThis.App.EXPORTS.JavaScriptTestHelperNoNamespace
const fn = JavaScriptTestHelperNoNamespace[name];
const fn = dllExports.JavaScriptTestHelperNoNamespace[name];
//console.log("invoke1:" + fn.toString());
const res = fn(arg1);
// console.log(`invoke1: res ${res !== null ? typeof res : '<null>'}`)
Expand Down Expand Up @@ -272,5 +271,8 @@ globalThis.rebound = {
echoMemberMethod: globalThis.data.echoMemberMethod.bind(globalThis.data)
}

export async function setup() {
dllExports = await App.runtime.getAssemblyExports("System.Runtime.InteropServices.JavaScript.Tests.dll");
}

// console.log('JavaScriptTestHelper:' Object.keys(globalThis.JavaScriptTestHelper));
4 changes: 2 additions & 2 deletions src/mono/sample/mbr/browser/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import createDotnetRuntime from './dotnet.js'
try {
const { BINDING } = await createDotnetRuntime(({ MONO }) => ({
configSrc: "./mono-config.json",
onConfigLoaded: () => {
MONO.config.environment_variables["DOTNET_MODIFIABLE_ASSEMBLIES"] = "debug";
onConfigLoaded: (config) => {
config.environmentVariables["DOTNET_MODIFIABLE_ASSEMBLIES"] = "debug";
},
}));
const update = BINDING.bind_static_method("[WasmDelta] Sample.Test:Update");
Expand Down
29 changes: 18 additions & 11 deletions src/mono/sample/wasm/browser-bench/frame-main.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,31 @@
import createDotnetRuntime from './dotnet.js'

class FrameApp {
async init({ MONO }) {
const exports = await MONO.mono_wasm_get_assembly_exports("Wasm.Browser.Bench.Sample.dll");
async init({ getAssemblyExports }) {
const exports = await getAssemblyExports("Wasm.Browser.Bench.Sample.dll");
exports.Sample.AppStartTask.FrameApp.ReachedManaged();
}

reachedCallback() {
window.parent.resolveAppStartEvent("reached");
if (window.parent != window) {
window.parent.resolveAppStartEvent("reached");
}
}
}

let mute = false;
try {
globalThis.frameApp = new FrameApp();
globalThis.frameApp.ReachedCallback = globalThis.frameApp.reachedCallback.bind(globalThis.frameApp);

let mute = false;
window.addEventListener("pageshow", event => { window.parent.resolveAppStartEvent("pageshow"); })
if (window.parent != window) {
window.addEventListener("pageshow", event => { window.parent.resolveAppStartEvent("pageshow"); })
}

window.muteErrors = () => {
mute = true;
}

const { MONO } = await createDotnetRuntime(() => ({
const runtime = await createDotnetRuntime(() => ({
disableDotnet6Compatibility: true,
configSrc: "./mono-config.json",
printErr: function () {
Expand All @@ -36,16 +39,20 @@ try {
}
},
onConfigLoaded: () => {
window.parent.resolveAppStartEvent("onConfigLoaded");
// Module.config.diagnostic_tracing = true;
if (window.parent != window) {
window.parent.resolveAppStartEvent("onConfigLoaded");
}
// Module.config.diagnosticTracing = true;
},
onAbort: (error) => {
wasm_exit(1, error);
},
}));

window.parent.resolveAppStartEvent("onDotnetReady");
await frameApp.init({ MONO });
if (window.parent != window) {
window.parent.resolveAppStartEvent("onDotnetReady");
}
await frameApp.init(runtime);
}
catch (err) {
if (!mute) {
Expand Down
8 changes: 4 additions & 4 deletions src/mono/sample/wasm/browser-bench/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ let setTasks;
let getFullJsonResults;

class MainApp {
async init({ MONO }) {
const exports = await MONO.mono_wasm_get_assembly_exports("Wasm.Browser.Bench.Sample.dll");
async init({ getAssemblyExports }) {
const exports = await getAssemblyExports("Wasm.Browser.Bench.Sample.dll");
runBenchmark = exports.Sample.Test.RunBenchmark;
setTasks = exports.Sample.Test.SetTasks;
getFullJsonResults = exports.Sample.Test.GetFullJsonResults;
Expand Down Expand Up @@ -94,14 +94,14 @@ try {
globalThis.mainApp.FrameReachedManaged = globalThis.mainApp.frameReachedManaged.bind(globalThis.mainApp);
globalThis.mainApp.PageShow = globalThis.mainApp.pageShow.bind(globalThis.mainApp);

const { MONO } = await createDotnetRuntime(() => ({
const runtime = await createDotnetRuntime(() => ({
disableDotnet6Compatibility: true,
configSrc: "./mono-config.json",
onAbort: (error) => {
wasm_exit(1, error);
}
}));
await mainApp.init({ MONO });
await mainApp.init(runtime);
}
catch (err) {
wasm_exit(1, err);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,23 @@
<ItemGroup>
<WasmExtraFilesToDeploy Include="index.html" />
<WasmExtraFilesToDeploy Include="mock.js" Condition="'$(MonoDiagnosticsMock)' == 'true'"/>
<WasmExtraConfig Condition="true" Include="environment_variables" Value='
<WasmExtraConfig Condition="true" Include="environmentVariables" Value='
{
"MONO_LOG_LEVEL": "warning",
"MONO_LOG_MASK": "all"
}' />
<!-- this option requires running dotnet-dsrouter and a real dotnet-trace client -->
<WasmExtraConfig Condition="true and '$(MonoDiagnosticsMock)' != 'true'" Include="diagnostic_options" Value='
<WasmExtraConfig Condition="true and '$(MonoDiagnosticsMock)' != 'true'" Include="diagnosticOptions" Value='
{
"server": { "suspend": true, "connect_url": "ws://localhost:8088/diagnostics" }
"server": { "suspend": true, "connectUrl": "ws://localhost:8088/diagnostics" }
}' />
<!-- this option requires compiling the runtime with /p:MonoDiagnosticsMock=true and also building this project with the same property-->
<WasmExtraConfig Condition="true and '$(MonoDiagnosticsMock)' == 'true'" Include="diagnostic_options" Value='
<WasmExtraConfig Condition="true and '$(MonoDiagnosticsMock)' == 'true'" Include="diagnosticOptions" Value='
{
"server": { "suspend": false, "connect_url": "mock:./mock.js" }
"server": { "suspend": false, "connectUrl": "mock:./mock.js" }
}' />
<!-- this option will create an EventPipe session at startup, that will dump its data into the Emscripten VFS -->
<WasmExtraConfig Condition="false" Include="diagnostic_options" Value='
<WasmExtraConfig Condition="false" Include="diagnosticOptions" Value='
{
"sessions": [ { "collectRundownEvents": "true", "providers": "WasmHello::5:EventCounterIntervalSec=1" } ]
}' />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

<ItemGroup>
<WasmExtraFilesToDeploy Include="index.html" />
<WasmExtraConfig Include="environment_variables" Value='
<WasmExtraConfig Include="environmentVariables" Value='
{
"DOTNET_EnableEventPipe": "1",
"DOTNET_EventPipeOutputPath": "/trace.nettrace"
Expand Down
4 changes: 2 additions & 2 deletions src/mono/sample/wasm/browser-mt-eventpipe/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ function Uint8ToString(u8a) {
}

async function main() {
const { MONO, BINDING, Module, RuntimeBuildInfo } = await createDotnetRuntime(() => {
const { MONO, BINDING, Module, runtimeBuildInfo } = await createDotnetRuntime(() => {
console.log('user code in createDotnetRuntime')
return {
disableDotnet6Compatibility: true,
Expand All @@ -40,7 +40,7 @@ async function main() {
try {
const testMeaning = BINDING.bind_static_method("[Wasm.Browser.ThreadsEP.Sample] Sample.Test:TestMeaning");
const ret = testMeaning();
document.getElementById("out").innerHTML = `${ret} as computed on dotnet ver ${RuntimeBuildInfo.ProductVersion}`;
document.getElementById("out").innerHTML = `${ret} as computed on dotnet ver ${runtimeBuildInfo.productVersion}`;

console.debug(`ret: ${ret}`);

Expand Down
Loading

0 comments on commit 0d80733

Please sign in to comment.