未验证 提交 da0e0f73 编写于 作者: P Pavel Savara 提交者: GitHub

[wasm] renames and cleanup before modularization (#61596)

- no imports from outer scope
- move dotnet to -extern-pre-js
- re-enable JS minification with ES2018
- rename main javaScript files to main.js and test-main.js
- sample and test script cleanup
- rename set_exit_code method
- rewrite test start as async method
- improve script loading via script element on page in test
- use BINDING.bind_static_method instead of INTERNAL where possible
- better .d.ts exports
- formatted html files
- renamed modules.ts to imports.ts which makes more sense
- improved error propagation
- renamed __initializeImportsAndExports
- delayed exit and stdout flush
上级 a1b391bd
......@@ -135,7 +135,7 @@ jobs:
artifactName: BrowserWasm
displayName: BrowserWasm
- script: "mkdir $(librariesDownloadDir)/bin/wasm;unzip -o $(librariesDownloadDir)/BrowserWasm/artifacts/packages/Release/Shipping/Microsoft.NETCore.App.Runtime.Mono.browser-wasm.7.0.0-ci.nupkg data/* runtimes/* -d $(librariesDownloadDir)/bin/wasm;cp src/mono/wasm/runtime-test.js $(librariesDownloadDir)/bin/wasm/runtime-test.js;find $(librariesDownloadDir)/bin/wasm -type f -exec chmod 664 {} \\;"
- script: "mkdir $(librariesDownloadDir)/bin/wasm;unzip -o $(librariesDownloadDir)/BrowserWasm/artifacts/packages/Release/Shipping/Microsoft.NETCore.App.Runtime.Mono.browser-wasm.7.0.0-ci.nupkg data/* runtimes/* -d $(librariesDownloadDir)/bin/wasm;cp src/mono/wasm/test-main.js $(librariesDownloadDir)/bin/wasm/test-main.js;find $(librariesDownloadDir)/bin/wasm -type f -exec chmod 664 {} \\;"
displayName: "Create wasm directory (Linux)"
# Download mono AOT
......
......@@ -23,13 +23,13 @@
<_XHarnessArgs Condition="'$(OS)' != 'Windows_NT'">wasm $XHARNESS_COMMAND --app=. --output-directory=$XHARNESS_OUT</_XHarnessArgs>
<_XHarnessArgs Condition="'$(OS)' == 'Windows_NT'">wasm %XHARNESS_COMMAND% --app=. --output-directory=%XHARNESS_OUT%</_XHarnessArgs>
<_XHarnessArgs Condition="'$(Scenario)' != 'WasmTestOnBrowser' and '$(Scenario)' != 'BuildWasmApps'">$(_XHarnessArgs) --engine=$(JSEngine) $(JSEngineArgs) --js-file=runtime.js</_XHarnessArgs>
<_XHarnessArgs Condition="'$(Scenario)' != 'WasmTestOnBrowser' and '$(Scenario)' != 'BuildWasmApps'">$(_XHarnessArgs) --engine=$(JSEngine) $(JSEngineArgs) --js-file=main.js</_XHarnessArgs>
<_XHarnessArgs Condition="'$(BrowserHost)' == 'windows'">$(_XHarnessArgs) --browser=chrome --browser-path=%HELIX_CORRELATION_PAYLOAD%\chrome-win\chrome.exe</_XHarnessArgs>
<_XHarnessArgs Condition="'$(IsFunctionalTest)' == 'true'" >$(_XHarnessArgs) --expected-exit-code=$(ExpectedExitCode)</_XHarnessArgs>
<_XHarnessArgs Condition="'$(WasmXHarnessArgs)' != ''" >$(_XHarnessArgs) $(WasmXHarnessArgs)</_XHarnessArgs>
<_AppArgs Condition="'$(IsFunctionalTest)' != 'true' and '$(Scenario)' != 'BuildWasmApps'">--run WasmTestRunner.dll $(AssemblyName).dll</_AppArgs>
<_AppArgs Condition="'$(IsFunctionalTest)' == 'true'">--run $(AssemblyName).dll --testing</_AppArgs>
<_AppArgs Condition="'$(IsFunctionalTest)' == 'true'">--run $(AssemblyName).dll</_AppArgs>
<_AppArgs Condition="'$(WasmTestAppArgs)' != ''">$(_AppArgs) $(WasmTestAppArgs)</_AppArgs>
......@@ -161,7 +161,7 @@
<PropertyGroup>
<WasmAppDir>$(BundleDir)</WasmAppDir>
<WasmMainAssemblyFileName Condition="'$(WasmMainAssemblyFileName)' == ''">WasmTestRunner.dll</WasmMainAssemblyFileName>
<WasmMainJSPath Condition="'$(WasmMainJSPath)' == ''">$(MonoProjectRoot)\wasm\runtime-test.js</WasmMainJSPath>
<WasmMainJSPath Condition="'$(WasmMainJSPath)' == ''">$(MonoProjectRoot)\wasm\test-main.js</WasmMainJSPath>
<WasmInvariantGlobalization>$(InvariantGlobalization)</WasmInvariantGlobalization>
<WasmGenerateRunV8Script>true</WasmGenerateRunV8Script>
<WasmNativeStrip>false</WasmNativeStrip>
......
......@@ -491,7 +491,7 @@
<HelixWorkItem Include="@(_RunOnlyWorkItem -> '%(FileName)')" >
<PayloadArchive>%(Identity)</PayloadArchive>
<!-- No RunTests script generated for the sample project so we just use the direct command -->
<Command>$(ExecXHarnessCmd) wasm $(XHarnessCommand) --app=. --engine=V8 --engine-arg=--stack-trace-limit=1000 --js-file=runtime.js --output-directory=$(XHarnessOutput) -- --run %(FileName).dll</Command>
<Command>$(ExecXHarnessCmd) wasm $(XHarnessCommand) --app=. --engine=V8 --engine-arg=--stack-trace-limit=1000 --js-file=main.js --output-directory=$(XHarnessOutput) -- --run %(FileName).dll</Command>
</HelixWorkItem>
</ItemGroup>
......@@ -501,7 +501,7 @@
<HelixWorkItem Include="@(_RunOnlyWorkItem -> '%(FileName)')" >
<PayloadArchive>%(Identity)</PayloadArchive>
<!-- No RunTests script generated for the sample project so we just use the direct command -->
<Command>$(ExecXHarnessCmd) wasm $(XHarnessCommand) --app=. --browser=Chrome $(XHarnessBrowserPathArg) --html-file=index.html --output-directory=$(XHarnessOutput) -- %(FileName).dll --testing</Command>
<Command>$(ExecXHarnessCmd) wasm $(XHarnessCommand) --app=. --browser=Chrome $(XHarnessBrowserPathArg) --html-file=index.html --output-directory=$(XHarnessOutput) -- %(FileName).dll</Command>
</HelixWorkItem>
</ItemGroup>
......
......@@ -7,7 +7,7 @@
<OutputPath>bin</OutputPath>
<WasmAppDir>$(MSBuildProjectDirectory)\bin\$(Configuration)\AppBundle\</WasmAppDir>
<WasmMainJSPath>runtime.js</WasmMainJSPath>
<WasmMainJSPath>main.js</WasmMainJSPath>
<EnableDefaultItems>false</EnableDefaultItems>
<!-- Important - deltas don't support trimming! -->
......
......@@ -2,37 +2,37 @@
<!-- Licensed to the .NET Foundation under one or more agreements. -->
<!-- The .NET Foundation licenses this file to you under the MIT license. -->
<html>
<head>
<title>TESTS</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<h3 id="header">Wasm Browser Sample</h3>
Result from Sample.Test.TestMeaning: <span id="out"></span>
<div>
Click here (upto 2 times): <button id="update">Update</button>
</div>
<script type='text/javascript'>
var App = {
init: function () {
var outElement = document.getElementById("out");
document.getElementById("update").addEventListener("click", function () {
INTERNAL.call_static_method("[WasmDelta] Sample.Test:Update", []);
console.log ("applied update");
var ret = INTERNAL.call_static_method("[WasmDelta] Sample.Test:TestMeaning", []);
outElement.innerHTML = ret;
})
var ret = INTERNAL.call_static_method("[WasmDelta] Sample.Test:TestMeaning", []);
outElement.innerHTML = ret;
console.log ("ready");
},
};
</script>
<script type="text/javascript" src="runtime.js"></script>
<script defer src="dotnet.js"></script>
<head>
<title>Hot Reload Sample</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<h3 id="header">Wasm Hot Reload Sample</h3>
Result from Sample.Test.TestMeaning: <span id="out"></span>
<div>
Click here (upto 2 times): <button id="update">Update</button>
</div>
<script type='text/javascript'>
const App = {
init: function () {
const update = BINDING.bind_static_method("[WasmDelta] Sample.Test:Update");
const testMeaning = BINDING.bind_static_method("[Wasm.Browser.Sample] Sample.Test:TestMeaning");
const outElement = document.getElementById("out");
document.getElementById("update").addEventListener("click", function () {
update();
console.log("applied update");
outElement.innerHTML = testMeaning();
})
outElement.innerHTML = testMeaning();
console.log("ready");
},
};
</script>
<script type="text/javascript" src="main.js"></script>
<script defer src="dotnet.js"></script>
</body>
</body>
</html>
</html>
\ No newline at end of file
......@@ -3,7 +3,6 @@
"use strict";
var Module = {
config: null,
configSrc: "./mono-config.json",
onConfigLoaded: function () {
MONO.config.environment_variables["DOTNET_MODIFIABLE_ASSEMBLIES"] = "debug";
......
......@@ -14,12 +14,12 @@
<Exec Command="$(_Dotnet) publish /p:Configuration=$(Configuration) /p:TargetArchitecture=wasm /p:TargetOS=Browser $(_AOTFlag) $(_SampleProject)" />
</Target>
<Target Name="RunSampleWithV8" DependsOnTargets="BuildSampleInTree">
<Exec WorkingDirectory="bin/$(Configuration)/AppBundle" Command="v8 --expose_wasm runtime.js -- $(DOTNET_MONO_LOG_LEVEL) --run $(_SampleAssembly) $(Args)" IgnoreExitCode="true" />
<Exec WorkingDirectory="bin/$(Configuration)/AppBundle" Command="v8 --expose_wasm main.js -- $(DOTNET_MONO_LOG_LEVEL) --run $(_SampleAssembly) $(Args)" IgnoreExitCode="true" />
</Target>
<Target Name="CheckServe">
<Exec Command="dotnet tool install -g dotnet-serve" IgnoreExitCode="true" />
</Target>
<Target Name="RunSampleWithBrowser" DependsOnTargets="BuildSampleInTree;CheckServe">
<Exec Command="$(_Dotnet) serve -o -d:bin/$(Configuration)/AppBundle -p:8000" IgnoreExitCode="true" YieldDuringToolExecution="true" />
<Exec Command="$(_Dotnet) serve -o -d:bin/$(Configuration)/AppBundle -p:8000 --mime .mjs=text/javascript" IgnoreExitCode="true" YieldDuringToolExecution="true" />
</Target>
</Project>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<WasmCopyAppZipToHelixTestDir Condition="'$(ArchiveTests)' == 'true'">true</WasmCopyAppZipToHelixTestDir>
<WasmMainJSPath>$(MonoProjectRoot)\wasm\runtime-test.js</WasmMainJSPath>
<WasmMainJSPath>$(MonoProjectRoot)\wasm\test-main.js</WasmMainJSPath>
<WasmGenerateRunV8Script>true</WasmGenerateRunV8Script>
<SuppressTrimAnalysisWarnings>true</SuppressTrimAnalysisWarnings>
</PropertyGroup>
......
......@@ -2,7 +2,7 @@
<PropertyGroup>
<!-- don't need to run this on helix -->
<WasmCopyAppZipToHelixTestDir>false</WasmCopyAppZipToHelixTestDir>
<WasmMainJSPath>runtime.js</WasmMainJSPath>
<WasmMainJSPath>main.js</WasmMainJSPath>
<SuppressTrimAnalysisWarnings>true</SuppressTrimAnalysisWarnings>
</PropertyGroup>
......
......@@ -11,7 +11,7 @@
<h3 id="header">Wasm Browser Sample - App task frame</h3>
<span id="out"></span>
<script type='text/javascript'>
var test_exit = function(exit_code)
function set_exit_code (exit_code, reason)
{
/* Set result in a tests_done element, to be read by xharness */
var tests_done_elem = document.createElement("label");
......@@ -35,7 +35,7 @@
};
</script>
<script type="text/javascript" src="runtime.js"></script>
<script type="text/javascript" src="main.js"></script>
<script defer src="dotnet.js"></script>
</body>
</html>
......@@ -2,85 +2,78 @@
<!-- Licensed to the .NET Foundation under one or more agreements. -->
<!-- The .NET Foundation licenses this file to you under the MIT license. -->
<html>
<head>
<title>TESTS</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
</head>
<body onload="onLoad()">
<h3 id="header">Wasm Browser Sample - Simple Benchmark</h3>
Output:<br><br> <span id="out"></span>
<script type='text/javascript'>
var is_testing = false;
var tasks = '';
var onLoad = function() {
var url = new URL(decodeURI(window.location));
let args = url.searchParams.getAll('arg');
is_testing = args !== undefined && (args.find(arg => arg == '--testing') !== undefined);
tasks = url.searchParams.getAll('task');
};
var test_exit = function(exit_code)
{
if (!is_testing) {
console.log(`test_exit: ${exit_code}`);
return;
}
<head>
<title>Benchmark Sample</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
</head>
/* Set result in a tests_done element, to be read by xharness */
var tests_done_elem = document.createElement("label");
tests_done_elem.id = "tests_done";
tests_done_elem.innerHTML = exit_code.toString();
document.body.appendChild(tests_done_elem);
<body onload="onLoad()">
<h3 id="header">Wasm Browser Sample - Simple Benchmark</h3>
Output:<br><br> <span id="out"></span>
<script type='text/javascript'>
let tasks = '';
var onLoad = function () {
var url = new URL(decodeURI(window.location));
tasks = url.searchParams.getAll('task');
};
console.log(`WASM EXIT ${exit_code}`);
};
function set_exit_code(exit_code, reason) {
/* Set result in a tests_done element, to be read by xharness */
const tests_done_elem = document.createElement("label");
tests_done_elem.id = "tests_done";
tests_done_elem.innerHTML = exit_code.toString();
document.body.appendChild(tests_done_elem);
function yieldBench () {
let promise = INTERNAL.call_static_method("[Wasm.Browser.Bench.Sample] Sample.Test:RunBenchmark", []);
promise.then(ret => {
document.getElementById("out").innerHTML += ret;
if (ret.length > 0) {
setTimeout(function () { yieldBench(); }, 0);
} else {
document.getElementById("out").innerHTML += "Finished";
}
});
}
console.log(`WASM EXIT ${exit_code}`);
};
var App = {
init: function () {
if (tasks != '')
INTERNAL.call_static_method("[Wasm.Browser.Bench.Sample] Sample.Test:SetTasks", tasks);
yieldBench ();
},
function yieldBench() {
const runBenchmark = BINDING.bind_static_method("[Wasm.Browser.Bench.Sample] Sample.Test:RunBenchmark");
let promise = runBenchmark();
promise.then(ret => {
document.getElementById("out").innerHTML += ret;
if (ret.length > 0) {
setTimeout(function () { yieldBench(); }, 0);
} else {
document.getElementById("out").innerHTML += "Finished";
}
});
}
PageShow: async function ()
{
AppStart.Construct();
try {
await AppStart.WaitForPageShow();
} finally {
AppStart.RemoveFrame();
}
},
const App = {
init: function () {
if (tasks != '') {
const setTasks = BINDING.bind_static_method("[Wasm.Browser.Bench.Sample] Sample.Test:SetTasks");
setTasks(tasks);
}
yieldBench();
},
ReachedManaged: async function ()
{
AppStart.Construct();
try {
await AppStart.WaitForReached();
} finally {
AppStart.RemoveFrame();
}
PageShow: async function () {
AppStart.Construct();
try {
await AppStart.WaitForPageShow();
} finally {
AppStart.RemoveFrame();
}
};
</script>
<script type="text/javascript" src="runtime.js"></script>
<script type="text/javascript" src="appstart.js"></script>
},
<script defer src="dotnet.js"></script>
ReachedManaged: async function () {
AppStart.Construct();
try {
await AppStart.WaitForReached();
} finally {
AppStart.RemoveFrame();
}
}
};
</script>
<script type="text/javascript" src="main.js"></script>
<script type="text/javascript" src="appstart.js"></script>
<script defer src="dotnet.js"></script>
</body>
</body>
</html>
</html>
\ No newline at end of file
......@@ -3,18 +3,17 @@
"use strict";
var Module = {
config: null,
configSrc: "./mono-config.json",
onDotNetReady: function () {
onDotNetReady: () => {
try {
App.init();
} catch (error) {
console.log("exception: " + error);
test_exit(1);
set_exit_code(1, error);
throw (error);
}
},
onAbort: function (err) {
test_exit(1);
onAbort: (error) => {
set_exit_code(1, error);
},
};
......@@ -9,11 +9,11 @@
public static void StopProfile(){}
```
2. Initialize the profiler in the main javascript (e.g. runtime.js)
2. Initialize the profiler in the main javascript (e.g. main.js)
```
var Module = {
onRuntimeInitialized: function () {
onConfigLoaded: () => {
...
if (config.enable_profiler)
......
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<WasmCopyAppZipToHelixTestDir Condition="'$(ArchiveTests)' == 'true'">true</WasmCopyAppZipToHelixTestDir>
<WasmMainJSPath>runtime.js</WasmMainJSPath>
<WasmMainJSPath>main.js</WasmMainJSPath>
<WasmProfilers>aot;</WasmProfilers>
</PropertyGroup>
......@@ -9,4 +9,6 @@
<WasmExtraConfig Include="enable_profiler" Value="true" Condition="'$(EnableProfiler)' == 'true'" />
<WasmExtraFilesToDeploy Include="index.html" />
</ItemGroup>
<Target Name="RunSample" DependsOnTargets="RunSampleWithBrowser" />
</Project>
......@@ -3,15 +3,15 @@
<!-- The .NET Foundation licenses this file to you under the MIT license. -->
<html>
<head>
<title>TESTS</title>
<title>Profiler Sample</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<h3 id="header">Wasm Browser Sample</h3>
<h3 id="header">Wasm Profiler Sample</h3>
Result from Sample.Test.TestMeaning: <span id="out"></span>
<script type="text/javascript" src="runtime.js"></script>
<script type="text/javascript" src="main.js"></script>
<script defer src="dotnet.js"></script>
</body>
......
......@@ -3,10 +3,8 @@
"use strict";
var Module = {
is_testing: false,
config: null,
configSrc: "./mono-config.json",
onConfigLoaded: function () {
onConfigLoaded: () => {
if (MONO.config.enable_profiler) {
MONO.config.aot_profiler_options = {
write_at: "Sample.Test::StopProfile",
......@@ -14,42 +12,37 @@ var Module = {
}
}
},
onDotNetReady: function () {
onDotNetReady: () => {
try {
Module.init();
} catch (error) {
test_exit(1);
set_exit_code(1, error);
throw (error);
}
},
onAbort: function (err) {
test_exit(1);
onAbort: (error) => {
set_exit_code(1, error);
},
init: function () {
init: () => {
console.log("not ready yet")
const ret = INTERNAL.call_static_method("[Wasm.BrowserProfile.Sample] Sample.Test:TestMeaning", []);
const testMeaning = BINDING.bind_static_method("[Wasm.BrowserProfile.Sample] Sample.Test:TestMeaning");
const stopProfile = BINDING.bind_static_method("[Wasm.BrowserProfile.Sample] Sample.Test:StopProfile");
const ret = testMeaning();
document.getElementById("out").innerHTML = ret;
console.log("ready");
if (Module.is_testing) {
console.debug(`ret: ${ret}`);
let exit_code = ret == 42 ? 0 : 1;
Module.test_exit(exit_code);
}
console.debug(`ret: ${ret}`);
let exit_code = ret == 42 ? 0 : 1;
Module.set_exit_code(exit_code);
if (MONO.config.enable_profiler) {
INTERNAL.call_static_method("[Wasm.BrowserProfile.Sample] Sample.Test:StopProfile", []);
stopProfile();
Module.saveProfile();
}
},
test_exit: function (exit_code) {
if (!Module.is_testing) {
console.log(`test_exit: ${exit_code}`);
return;
}
set_exit_code: (exit_code, reason) => {
/* Set result in a tests_done element, to be read by xharness */
const tests_done_elem = document.createElement("label");
tests_done_elem.id = "tests_done";
......@@ -59,7 +52,7 @@ var Module = {
console.log(`WASM EXIT ${exit_code}`);
},
saveProfile: function () {
saveProfile: () => {
const a = document.createElement('a');
const blob = new Blob([INTERNAL.aot_profile_data]);
a.href = URL.createObjectURL(blob);
......
......@@ -2,7 +2,7 @@
<PropertyGroup>
<Configuration>Debug</Configuration>
<WasmCopyAppZipToHelixTestDir Condition="'$(ArchiveTests)' == 'true'">true</WasmCopyAppZipToHelixTestDir>
<WasmMainJSPath>runtime.js</WasmMainJSPath>
<WasmMainJSPath>main.js</WasmMainJSPath>
<DebugSymbols>true</DebugSymbols>
<DebugType>embedded</DebugType>
<WasmDebugLevel>1</WasmDebugLevel>
......
......@@ -2,55 +2,42 @@
<!-- Licensed to the .NET Foundation under one or more agreements. -->
<!-- The .NET Foundation licenses this file to you under the MIT license. -->
<html>
<head>
<title>TESTS</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body onload="onLoad()">
<h3 id="header">Wasm Browser Sample</h3>
Result from Sample.Test.TestMeaning: <span id="out"></span>
<script type='text/javascript'>
var is_testing = false;
var onLoad = function() {
var url = new URL(decodeURI(window.location));
let args = url.searchParams.getAll('arg');
is_testing = args !== undefined && (args.find(arg => arg == '--testing') !== undefined);
};
var test_exit = function(exit_code)
{
if (!is_testing) {
console.log(`test_exit: ${exit_code}`);
return;
}
<head>
<title>Sample</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
/* Set result in a tests_done element, to be read by xharness */
var tests_done_elem = document.createElement("label");
tests_done_elem.id = "tests_done";
tests_done_elem.innerHTML = exit_code.toString();
document.body.appendChild(tests_done_elem);
<body>
<h3 id="header">Wasm Browser Sample</h3>
Result from Sample.Test.TestMeaning: <span id="out"></span>
<script type='text/javascript'>
function set_exit_code(exit_code, reason) {
/* Set result in a tests_done element, to be read by xharness */
const tests_done_elem = document.createElement("label");
tests_done_elem.id = "tests_done";
tests_done_elem.innerHTML = exit_code.toString();
document.body.appendChild(tests_done_elem);
console.log(`WASM EXIT ${exit_code}`);
};
console.log(`WASM EXIT ${exit_code}`);
};
var App = {
init: function () {
var ret = INTERNAL.call_static_method("[Wasm.Browser.Sample] Sample.Test:TestMeaning", []);
document.getElementById("out").innerHTML = ret;
const App = {
init: () => {
const testMeaning = BINDING.bind_static_method("[Wasm.Browser.Sample] Sample.Test:TestMeaning");
const ret = testMeaning();
document.getElementById("out").innerHTML = ret;
if (is_testing)
{
console.debug(`ret: ${ret}`);
let exit_code = ret == 42 ? 0 : 1;
test_exit(exit_code);
}
},
};
</script>
<script type="text/javascript" src="runtime.js"></script>
console.debug(`ret: ${ret}`);
let exit_code = ret == 42 ? 0 : 1;
set_exit_code(exit_code);
},
};
</script>
<script type="text/javascript" src="main.js"></script>
<script defer src="dotnet.js"></script>
<script defer src="dotnet.js"></script>
</body>
</body>
</html>
\ No newline at end of file
......@@ -2,19 +2,18 @@
// The .NET Foundation licenses this file to you under the MIT license.
"use strict";
var Module = {
config: null,
configSrc: "./mono-config.json",
onDotNetReady: function () {
onDotNetReady: () => {
try {
App.init();
} catch (error) {
test_exit(1);
set_exit_code(1, error);
throw (error);
}
},
onAbort: function () {
test_exit(1);
onAbort: (error) => {
set_exit_code(1, error);
},
};
};
\ No newline at end of file
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<WasmCopyAppZipToHelixTestDir Condition="'$(ArchiveTests)' == 'true'">true</WasmCopyAppZipToHelixTestDir>
<WasmMainJSPath>$(MonoProjectRoot)\wasm\runtime-test.js</WasmMainJSPath>
<WasmMainJSPath>$(MonoProjectRoot)\wasm\test-main.js</WasmMainJSPath>
<WasmGenerateRunV8Script>true</WasmGenerateRunV8Script>
</PropertyGroup>
......
......@@ -30,4 +30,4 @@ run-browser:
fi
run-console:
cd bin/$(CONFIG)/AppBundle && ~/.jsvu/v8 --stack-trace-limit=1000 --single-threaded --expose_wasm runtime.js -- $(DOTNET_MONO_LOG_LEVEL) --run $(CONSOLE_DLL) $(ARGS)
cd bin/$(CONFIG)/AppBundle && ~/.jsvu/v8 --stack-trace-limit=1000 --single-threaded --expose_wasm main.js -- $(DOTNET_MONO_LOG_LEVEL) --run $(CONSOLE_DLL) $(ARGS)
......@@ -10,9 +10,9 @@ Wasm app build can run in two scenarios:
A dotnet wasm app has some native wasm files (`dotnet.wasm`, and `dotnet.js`). How these files are obtained, or generated:
1. Build
a. with no native libraries referenced (AOT setting is ignored here)
- a. with no native libraries referenced (AOT setting is ignored here)
- files from the runtime pack are used as-is
b. with native libraries referenced
- b. with native libraries referenced
- dotnet.wasm is relinked with the native libraries
2. Publish
- dotnet.wasm is relinked with the native libraries, and updated pinvoke/icalls from the trimmed assemblies
......
......@@ -223,7 +223,7 @@
<_WasmRuntimePackSrcFile ObjectFile="$(_WasmIntermediateOutputPath)%(FileName).o" />
<_DotnetJSSrcFile Include="$(_WasmRuntimePackSrcDir)\*.js" Exclude="$(_WasmRuntimePackSrcDir)\*.iffe.js"/>
<_WasmExtraJSFile Include="$(_WasmRuntimePackSrcDir)\*.iffe.js" Kind="pre-js" />
<_WasmExtraJSFile Include="$(_WasmRuntimePackSrcDir)\*.iffe.js" Kind="extern-pre-js" />
<_WasmNativeFileForLinking Include="@(NativeFileReference)" />
</ItemGroup>
......@@ -353,8 +353,9 @@
<_EmccLinkStepArgs Include="--js-library &quot;%(_WasmExtraJSFile.Identity)&quot;" Condition="'%(_WasmExtraJSFile.Kind)' == 'js-library'" />
<_EmccLinkStepArgs Include="--pre-js &quot;%(_WasmExtraJSFile.Identity)&quot;" Condition="'%(_WasmExtraJSFile.Kind)' == 'pre-js'" />
<_EmccLinkStepArgs Include="--extern-pre-js &quot;%(_WasmExtraJSFile.Identity)&quot;" Condition="'%(_WasmExtraJSFile.Kind)' == 'extern-pre-js'" />
<_EmccLinkStepArgs Include="--post-js &quot;%(_WasmExtraJSFile.Identity)&quot;" Condition="'%(_WasmExtraJSFile.Kind)' == 'post-js'" />
<_WasmLinkDependencies Include="@(_WasmExtraJSFile)" Condition="'%(_WasmExtraJSFile.Kind)' == 'js-library' or '%(_WasmExtraJSFile.Kind)' == 'pre-js' or '%(_WasmExtraJSFile.Kind)' == 'post-js'" />
<_WasmLinkDependencies Include="@(_WasmExtraJSFile)" Condition="'%(_WasmExtraJSFile.Kind)' == 'js-library' or '%(_WasmExtraJSFile.Kind)' == 'pre-js' or '%(_WasmExtraJSFile.Kind)' == 'post-js' or '%(_WasmExtraJSFile.Kind)' == 'extern-post-js'" />
<_EmccLinkStepArgs Include="&quot;%(_WasmNativeFileForLinking.Identity)&quot;" />
<_WasmLinkDependencies Include="@(_WasmNativeFileForLinking)" />
......
......@@ -299,7 +299,7 @@
<Error Condition="'$(WasmMainAssemblyFileName)' == ''" Text="%24(WasmMainAssemblyFileName) property needs to be set for generating $(WasmRunV8ScriptPath)." />
<WriteLinesToFile
File="$(WasmRunV8ScriptPath)"
Lines="v8 --expose_wasm runtime.js -- ${RUNTIME_ARGS} --run $(WasmMainAssemblyFileName) $*"
Lines="v8 --expose_wasm main.js -- ${RUNTIME_ARGS} --run $(WasmMainAssemblyFileName) $*"
Overwrite="true">
</WriteLinesToFile>
......
......@@ -29,7 +29,7 @@
<PropertyGroup>
<WasmAppDir>$(TestRootDir)AppBundle\</WasmAppDir>
<WasmMainAssemblyFileName>$(OriginalPublishDir)WasmTestRunner.dll</WasmMainAssemblyFileName>
<WasmMainJSPath>$(OriginalPublishDir)runtime-test.js</WasmMainJSPath>
<WasmMainJSPath>$(OriginalPublishDir)test-main.js</WasmMainJSPath>
<WasmGenerateRunV8Script Condition="'$(WasmGenerateRunV8Script)' == ''">true</WasmGenerateRunV8Script>
</PropertyGroup>
......
......@@ -27,8 +27,8 @@ public async Task CreateGoodBreakpoint()
Assert.NotNull(loc["scriptId"]);
Assert.Equal("dotnet://debugger-test.dll/debugger-test.cs", scripts[loc["scriptId"]?.Value<string>()]);
Assert.Equal(10, loc["lineNumber"]);
Assert.Equal(8, loc["columnNumber"]);
Assert.Equal(10, (int)loc["lineNumber"]);
Assert.Equal(8, (int)loc["columnNumber"]);
}
[Fact]
......@@ -45,8 +45,8 @@ public async Task CreateJSBreakpoint()
var loc = bp1_res.Value["locations"]?.Value<JArray>()[0];
Assert.NotNull(loc["scriptId"]);
Assert.Equal(13, loc["lineNumber"]);
Assert.Equal(24, loc["columnNumber"]);
Assert.Equal(13, (int)loc["lineNumber"]);
Assert.Equal(24, (int)loc["columnNumber"]);
var bp2_res = await SetBreakpoint("/debugger-driver.html", 13, 33);
......@@ -56,8 +56,8 @@ public async Task CreateJSBreakpoint()
var loc2 = bp2_res.Value["locations"]?.Value<JArray>()[0];
Assert.NotNull(loc2["scriptId"]);
Assert.Equal(13, loc2["lineNumber"]);
Assert.Equal(33, loc2["columnNumber"]);
Assert.Equal(13, (int)loc2["lineNumber"]);
Assert.Equal(33, (int)loc2["columnNumber"]);
}
[Fact]
......@@ -73,8 +73,8 @@ public async Task CreateJS0Breakpoint()
var loc = bp1_res.Value["locations"]?.Value<JArray>()[0];
Assert.NotNull(loc["scriptId"]);
Assert.Equal(13, loc["lineNumber"]);
Assert.Equal(24, loc["columnNumber"]);
Assert.Equal(13, (int)loc["lineNumber"]);
Assert.Equal(24, (int)loc["columnNumber"]);
var bp2_res = await SetBreakpoint("/debugger-driver.html", 13, 33);
......@@ -84,8 +84,8 @@ public async Task CreateJS0Breakpoint()
var loc2 = bp2_res.Value["locations"]?.Value<JArray>()[0];
Assert.NotNull(loc2["scriptId"]);
Assert.Equal(13, loc2["lineNumber"]);
Assert.Equal(33, loc2["columnNumber"]);
Assert.Equal(13, (int)loc2["lineNumber"]);
Assert.Equal(33, (int)loc2["columnNumber"]);
}
[Theory]
......
......@@ -88,7 +88,7 @@
window.location.replace("http://localhost:9400/non-wasm-page.html");
}
</script>
<script type="text/javascript" src="runtime-debugger.js"></script>
<script type="text/javascript" src="debugger-main.js"></script>
<script type="text/javascript" src="other.js"></script>
<script async type="text/javascript" src="dotnet.js"></script>
Stuff goes here
......
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
"use strict";
var Module = {
configSrc: "./mono-config.json",
onConfigLoaded: () => {
MONO.config.environment_variables["DOTNET_MODIFIABLE_ASSEMBLIES"] = "debug";
// For custom logging patch the functions below
/*
MONO.config.environment_variables["MONO_LOG_LEVEL"] = "debug";
MONO.config.environment_variables["MONO_LOG_MASK"] = "all";
INTERNAL.logging = {
trace: function (domain, log_level, message, isFatal, dataPtr) { },
debugger: function (level, message) { }
};
*/
},
onDotNetReady: () => {
App.init();
},
};
......@@ -12,7 +12,7 @@
<WasmExtraFilesToDeploy Include="debugger-driver.html" />
<WasmExtraFilesToDeploy Include="non-wasm-page.html" />
<WasmExtraFilesToDeploy Include="other.js" />
<WasmExtraFilesToDeploy Include="runtime-debugger.js" />
<WasmExtraFilesToDeploy Include="debugger-main.js" />
<WasmExtraFilesToDeploy Include="weather.json" />
<!-- We want to bundle these assemblies, so build them first -->
......@@ -28,7 +28,7 @@
<PropertyGroup>
<EnableDefaultWasmAssembliesToBundle>false</EnableDefaultWasmAssembliesToBundle>
<WasmAppDir>$(AppDir)</WasmAppDir>
<WasmMainJSPath>$(MonoProjectRoot)wasm\runtime-test.js</WasmMainJSPath>
<WasmMainJSPath>$(MonoProjectRoot)wasm\test-main.js</WasmMainJSPath>
<!-- like is used on blazor -->
<WasmDebugLevel Condition="'$(WasmDebugLevel)'==''">-1</WasmDebugLevel>
......
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
"use strict";
var Module = {
config: null,
configSrc: "./mono-config.json",
onConfigLoaded: function () {
MONO.config.environment_variables["DOTNET_MODIFIABLE_ASSEMBLIES"] = "debug";
// For custom logging patch the functions below
/*
MONO.config.environment_variables["MONO_LOG_LEVEL"] = "debug";
MONO.config.environment_variables["MONO_LOG_MASK"] = "all";
INTERNAL.logging = {
trace: function (domain, log_level, message, isFatal, dataPtr) { },
debugger: function (level, message) { }
};
*/
},
onDotNetReady: function () {
App.init();
},
};
......@@ -25,7 +25,7 @@ target_link_libraries(dotnet
set_target_properties(dotnet PROPERTIES
LINK_DEPENDS "${NATIVE_BIN_DIR}/src/emcc-default.rsp;${NATIVE_BIN_DIR}/src/runtime.iffe.js;${SOURCE_DIR}/library-dotnet.js;${SYSTEM_NATIVE_DIR}/pal_random.js"
LINK_FLAGS "@${NATIVE_BIN_DIR}/src/emcc-default.rsp ${CONFIGURATION_LINK_FLAGS} -DENABLE_NETCORE=1 --pre-js ${NATIVE_BIN_DIR}/src/runtime.iffe.js --js-library ${SOURCE_DIR}/library-dotnet.js --js-library ${SYSTEM_NATIVE_DIR}/pal_random.js"
LINK_FLAGS "@${NATIVE_BIN_DIR}/src/emcc-default.rsp ${CONFIGURATION_LINK_FLAGS} -DENABLE_NETCORE=1 --extern-pre-js ${NATIVE_BIN_DIR}/src/runtime.iffe.js --js-library ${SOURCE_DIR}/library-dotnet.js --js-library ${SYSTEM_NATIVE_DIR}/pal_random.js"
RUNTIME_OUTPUT_DIRECTORY "${NATIVE_BIN_DIR}")
if(CMAKE_BUILD_TYPE STREQUAL "Release")
......
......@@ -2,7 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
import { Int32Ptr, JSHandle, MonoArray, MonoObject, MonoString, VoidPtr } from "./types";
import { Module } from "./modules";
import { Module } from "./imports";
import { mono_wasm_get_jsobj_from_js_handle } from "./gc-handles";
import { wrap_error } from "./method-calls";
import { _js_to_mono_obj } from "./js-to-cs";
......
......@@ -4,7 +4,7 @@
import { JSHandle, GCHandle, MonoObject } from "./types";
import { ArgsMarshalString } from "./method-binding";
import { PromiseControl } from "./cancelable-promise";
import { runtimeHelpers } from "./modules";
import { runtimeHelpers } from "./imports";
const fn_signatures: [jsname: string, csname: string, signature: ArgsMarshalString][] = [
["_get_cs_owned_object_by_js_handle", "GetCSOwnedObjectByJSHandle", "ii!"],
......
......@@ -7,7 +7,7 @@ import {
MonoArrayNull, MonoObject, MonoObjectNull, MonoString,
MonoType, MonoTypeNull
} from "./types";
import { runtimeHelpers } from "./modules";
import { runtimeHelpers } from "./imports";
import { conv_string } from "./strings";
import corebindings from "./corebindings";
import cwraps from "./cwraps";
......
......@@ -7,7 +7,7 @@ import {
MonoMethod, MonoObject, MonoString,
MonoType, VoidPtr
} from "./types";
import { Module } from "./modules";
import { Module } from "./imports";
const fn_signatures: [ident: string, returnType: string | null, argTypes?: string[], opts?: any][] = [
// MONO
......
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
import { Module, MONO, runtimeHelpers } from "./modules";
import { Module, MONO, runtimeHelpers } from "./imports";
import { toBase64StringImpl } from "./base64";
import cwraps from "./cwraps";
import { VoidPtr } from "./types";
......
import { DotNetPublicAPI } from "./exports";
import { EmscriptenModuleConfig } from "./types";
// this is the only public export from the dotnet.js module
declare function createDotnetRuntime(moduleFactory: (api: DotNetPublicAPI) => EmscriptenModuleConfig): Promise<DotNetPublicAPI>;
export default createDotnetRuntime;
......@@ -20,7 +20,7 @@ import {
mono_wasm_raise_debug_event,
mono_wasm_fire_debugger_agent_message,
} from "./debug";
import { runtimeHelpers, setLegacyModules } from "./modules";
import { runtimeHelpers, setImportsAndExports } from "./imports";
import { EmscriptenModuleMono, MonoArray, MonoConfig, MonoConfigError, MonoObject } from "./types";
import {
mono_load_runtime_and_bcl_args, mono_wasm_load_config,
......@@ -63,7 +63,7 @@ import {
getU8, getU16, getU32, getF32, getF64,
} from "./memory";
export const MONO: MONO = <any>{
const MONO: MONO = <any>{
// current "public" MONO API
mono_wasm_setenv,
mono_wasm_load_bytes_into_heap,
......@@ -88,7 +88,7 @@ export const MONO: MONO = <any>{
mono_wasm_new_roots,
};
export const BINDING: BINDING = <any>{
const BINDING: BINDING = <any>{
//current "public" BINDING API
mono_obj_array_new: cwraps.mono_wasm_obj_array_new,
mono_obj_array_set: cwraps.mono_wasm_obj_array_set,
......@@ -115,64 +115,96 @@ export const BINDING: BINDING = <any>{
// this is executed early during load of emscripten runtime
// it exports methods to global objects MONO, BINDING and Module in backward compatible way
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
function export_to_emscripten(dotnet: any, mono: any, binding: any, internal: any, module: any): void {
const moduleExt = module as EmscriptenModuleMono;
function initializeImportsAndExports(
imports: { isGlobal: boolean, isNode: boolean, isShell: boolean, isWeb: boolean, locateFile: Function },
exports: { mono: any, binding: any, internal: any, module: any },
): void {
const module = exports.module as EmscriptenModuleMono;
const globalThisAny = globalThis as any;
// we want to have same instance of MONO, BINDING and Module in dotnet iffe
setLegacyModules(dotnet, mono, binding, internal, module);
setImportsAndExports(imports, exports);
// here we merge methods to it from the local objects
Object.assign(dotnet, DOTNET);
Object.assign(mono, MONO);
Object.assign(binding, BINDING);
Object.assign(internal, INTERNAL);
// here we merge methods from the local objects into exported objects
Object.assign(exports.mono, MONO);
Object.assign(exports.binding, BINDING);
Object.assign(exports.internal, INTERNAL);
const api: DotNetPublicAPI = <any>{
MONO: exports.mono,
BINDING: exports.binding,
INTERNAL: exports.internal,
Module: module
};
if (module.configSrc) {
// this could be overriden on Module
if (!module.preInit) {
module.preInit = [];
} else if (typeof module.preInit === "function") {
module.preInit = [module.preInit];
}
module.preInit.unshift(mono_wasm_pre_init);
}
// this could be overriden on Module
moduleExt.preInit = mono_wasm_pre_init;
moduleExt.onRuntimeInitialized = mono_wasm_on_runtime_initialized;
if (!module.onRuntimeInitialized) {
module.onRuntimeInitialized = mono_wasm_on_runtime_initialized;
}
if (!module.print) {
module.print = console.log;
}
if (!module.printErr) {
module.printErr = console.error;
}
if (imports.isGlobal || !module.disableDotNet6Compatibility) {
Object.assign(module, api);
if (!moduleExt.disableDotNet6Compatibility) {
// backward compatibility
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
moduleExt.mono_bind_static_method = (fqn: string, signature: ArgsMarshalString): Function => {
module.mono_bind_static_method = (fqn: string, signature: ArgsMarshalString): Function => {
console.warn("Module.mono_bind_static_method is obsolete, please use BINDING.bind_static_method instead");
return mono_bind_static_method(fqn, signature);
};
// here we expose objects used in tests to global namespace
(<any>globalThis).Module = module;
const warnWrap = (name: string, value: any) => {
if (typeof ((<any>globalThis)[name]) !== "undefined") {
const warnWrap = (name: string, provider: () => any) => {
if (typeof globalThisAny[name] !== "undefined") {
// it already exists in the global namespace
return;
}
let warnOnce = true;
let value: any = undefined;
Object.defineProperty(globalThis, name, {
get: () => {
if (warnOnce) {
if (!value) {
const stack = (new Error()).stack;
const nextLine = stack ? stack.substr(stack.indexOf("\n", 8) + 1) : "";
console.warn(`global ${name} is obsolete, please use Module.${name} instead ${nextLine}`);
warnOnce = false;
value = provider();
}
return value;
}
});
};
warnWrap("MONO", mono);
warnWrap("BINDING", binding);
globalThisAny.MONO = exports.mono;
globalThisAny.BINDING = exports.binding;
globalThisAny.INTERNAL = exports.internal;
if (!imports.isGlobal) {
globalThisAny.Module = module;
}
// Blazor back compat
warnWrap("cwrap", Module.cwrap);
warnWrap("addRunDependency", Module.addRunDependency);
warnWrap("removeRunDependency", Module.removeRunDependency);
warnWrap("cwrap", () => module.cwrap);
warnWrap("addRunDependency", () => module.addRunDependency);
warnWrap("removeRunDependency", () => module.removeRunDependency);
}
}
export const __initializeImportsAndExports: any = initializeImportsAndExports; // don't want to export the type
// the methods would be visible to EMCC linker
// --- keep in sync with library-dotnet.js ---
const linker_exports = {
// --- keep in sync with dotnet.lib.js ---
export const __linker_exports: any = {
// mini-wasm.c
mono_set_timeout,
......@@ -214,16 +246,10 @@ const linker_exports = {
mono_wasm_load_icu_data,
mono_wasm_get_icudt_name,
};
export const DOTNET: any = {
};
export const INTERNAL: any = {
const INTERNAL: any = {
// startup
BINDING_ASM: "[System.Private.Runtime.InteropServices.JavaScript]System.Runtime.InteropServices.JavaScript.Runtime",
export_to_emscripten,
// linker
linker_exports: linker_exports,
// tests
call_static_method,
......@@ -281,7 +307,7 @@ export const INTERNAL: any = {
// this represents visibility in the javascript
// like https://github.com/dotnet/aspnetcore/blob/main/src/Components/Web.JS/src/Platform/Mono/MonoTypes.ts
export interface MONO {
interface MONO {
mono_wasm_runtime_ready: typeof mono_wasm_runtime_ready
mono_wasm_setenv: typeof mono_wasm_setenv
mono_wasm_load_data_archive: typeof mono_wasm_load_data_archive;
......@@ -294,8 +320,8 @@ export interface MONO {
mono_wasm_release_roots: typeof mono_wasm_release_roots;
// for Blazor's future!
mono_wasm_add_assembly: typeof cwraps.mono_wasm_add_assembly,
mono_wasm_load_runtime: typeof cwraps.mono_wasm_load_runtime,
mono_wasm_add_assembly: (name: string, data: VoidPtr, size: number) => number,
mono_wasm_load_runtime: (unused: string, debug_level: number) => void,
loaded_files: string[];
config: MonoConfig | MonoConfigError,
......@@ -303,7 +329,7 @@ export interface MONO {
// this represents visibility in the javascript
// like https://github.com/dotnet/aspnetcore/blob/main/src/Components/Web.JS/src/Platform/Mono/MonoTypes.ts
export interface BINDING {
interface BINDING {
mono_obj_array_new: (size: number) => MonoArray,
mono_obj_array_set: (array: MonoArray, idx: number, obj: MonoObject) => void,
js_string_to_mono_string: typeof js_string_to_mono_string,
......@@ -314,4 +340,9 @@ export interface BINDING {
bind_static_method: typeof mono_bind_static_method,
call_assembly_entry_point: typeof mono_call_assembly_entry_point,
unbox_mono_obj: typeof unbox_mono_obj
}
export interface DotNetPublicAPI {
MONO: MONO,
BINDING: BINDING,
Module: any
}
\ No newline at end of file
......@@ -7,19 +7,33 @@
import { EmscriptenModuleMono, MonoConfig, RuntimeHelpers } from "./types";
// these are our public API (except internal)
export let Module: EmscriptenModule & EmscriptenModuleMono;
export let MONO: any;
export let BINDING: any;
export let DOTNET: any;
export let INTERNAL: any;
// these are imported and re-exported from emscripten internals
export let ENVIRONMENT_IS_GLOBAL: boolean;
export let ENVIRONMENT_IS_NODE: boolean;
export let ENVIRONMENT_IS_SHELL: boolean;
export let ENVIRONMENT_IS_WEB: boolean;
export let locateFile: Function;
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export function setLegacyModules(dotnet: any, mono: any, binding: any, internal: any, module: EmscriptenModule & EmscriptenModuleMono) {
DOTNET = dotnet;
MONO = mono;
BINDING = binding;
INTERNAL = internal;
Module = module;
export function setImportsAndExports(
imports: { isGlobal: boolean, isNode: boolean, isShell: boolean, isWeb: boolean, locateFile: Function },
exports: { mono: any, binding: any, internal: any, module: any },
) {
MONO = exports.mono;
BINDING = exports.binding;
INTERNAL = exports.internal;
Module = exports.module;
ENVIRONMENT_IS_GLOBAL = imports.isGlobal;
ENVIRONMENT_IS_NODE = imports.isNode;
ENVIRONMENT_IS_SHELL = imports.isShell;
ENVIRONMENT_IS_WEB = imports.isWeb;
locateFile = imports.locateFile;
}
let monoConfig: MonoConfig;
......
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
import { Module, runtimeHelpers } from "./modules";
import { Module, runtimeHelpers } from "./imports";
import {
cs_owned_js_handle_symbol, get_cs_owned_object_by_js_handle, get_js_owned_object_by_gc_handle, js_owned_gc_handle_symbol,
mono_wasm_get_jsobj_from_js_handle, mono_wasm_get_js_handle,
......
/* eslint-disable no-undef */
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
/* eslint-disable no-undef */
"use strict";
......@@ -9,8 +9,8 @@ const DotNetSupportLib = {
$MONO: {},
$BINDING: {},
$INTERNAL: {},
// this line will be executed on runtime, populating the objects with methods
$DOTNET__postset: "__dotnet_runtime.INTERNAL.export_to_emscripten (DOTNET, MONO, BINDING, INTERNAL, Module);",
// this line will be executed early on runtime, passing import and export objects into __dotnet_runtime IFFE
$DOTNET__postset: "__dotnet_runtime.__initializeImportsAndExports({isGlobal:true, isNode:ENVIRONMENT_IS_NODE, isShell:ENVIRONMENT_IS_SHELL, isWeb:ENVIRONMENT_IS_WEB, locateFile}, {mono:MONO, binding:BINDING, internal:INTERNAL, module:Module});",
};
// the methods would be visible to EMCC linker
......@@ -61,7 +61,7 @@ const linked_functions = [
// -- this javascript file is evaluated by emcc during compilation! --
// we generate simple proxy for each exported function so that emcc will include them in the final output
for (let linked_function of linked_functions) {
const fn_template = `return __dotnet_runtime.INTERNAL.linker_exports.${linked_function}.apply(__dotnet_runtime, arguments)`;
const fn_template = `return __dotnet_runtime.__linker_exports.${linked_function}.apply(__dotnet_runtime, arguments)`;
DotNetSupportLib[linked_function] = new Function(fn_template);
}
......
import { Module } from "./modules";
import { Module } from "./imports";
const _temp_mallocs: Array<Array<VoidPtr> | null> = [];
......@@ -31,77 +31,77 @@ export function _release_temp_frame(): void {
type _MemOffset = number | VoidPtr | NativePointer;
export function setU8 (offset: _MemOffset, value: number) : void {
export function setU8(offset: _MemOffset, value: number): void {
Module.HEAPU8[<any>offset] = value;
}
export function setU16 (offset: _MemOffset, value: number) : void {
export function setU16(offset: _MemOffset, value: number): void {
Module.HEAPU16[<any>offset >>> 1] = value;
}
export function setU32 (offset: _MemOffset, value: number) : void {
export function setU32(offset: _MemOffset, value: number): void {
Module.HEAPU32[<any>offset >>> 2] = value;
}
export function setI8 (offset: _MemOffset, value: number) : void {
export function setI8(offset: _MemOffset, value: number): void {
Module.HEAP8[<any>offset] = value;
}
export function setI16 (offset: _MemOffset, value: number) : void {
export function setI16(offset: _MemOffset, value: number): void {
Module.HEAP16[<any>offset >>> 1] = value;
}
export function setI32 (offset: _MemOffset, value: number) : void {
export function setI32(offset: _MemOffset, value: number): void {
Module.HEAP32[<any>offset >>> 2] = value;
}
// NOTE: Accepts a number, not a BigInt, so values over Number.MAX_SAFE_INTEGER will be corrupted
export function setI64 (offset: _MemOffset, value: number) : void {
export function setI64(offset: _MemOffset, value: number): void {
Module.setValue(<VoidPtr><any>offset, value, "i64");
}
export function setF32 (offset: _MemOffset, value: number) : void {
export function setF32(offset: _MemOffset, value: number): void {
Module.HEAPF32[<any>offset >>> 2] = value;
}
export function setF64 (offset: _MemOffset, value: number) : void {
export function setF64(offset: _MemOffset, value: number): void {
Module.HEAPF64[<any>offset >>> 3] = value;
}
export function getU8 (offset: _MemOffset) : number {
export function getU8(offset: _MemOffset): number {
return Module.HEAPU8[<any>offset];
}
export function getU16 (offset: _MemOffset) : number {
export function getU16(offset: _MemOffset): number {
return Module.HEAPU16[<any>offset >>> 1];
}
export function getU32 (offset: _MemOffset) : number {
export function getU32(offset: _MemOffset): number {
return Module.HEAPU32[<any>offset >>> 2];
}
export function getI8 (offset: _MemOffset) : number {
export function getI8(offset: _MemOffset): number {
return Module.HEAP8[<any>offset];
}
export function getI16 (offset: _MemOffset) : number {
export function getI16(offset: _MemOffset): number {
return Module.HEAP16[<any>offset >>> 1];
}
export function getI32 (offset: _MemOffset) : number {
export function getI32(offset: _MemOffset): number {
return Module.HEAP32[<any>offset >>> 2];
}
// NOTE: Returns a number, not a BigInt. This means values over Number.MAX_SAFE_INTEGER will be corrupted
export function getI64 (offset: _MemOffset) : number {
export function getI64(offset: _MemOffset): number {
return Module.getValue(<number><any>offset, "i64");
}
export function getF32 (offset: _MemOffset) : number {
export function getF32(offset: _MemOffset): number {
return Module.HEAPF32[<any>offset >>> 2];
}
export function getF64 (offset: _MemOffset) : number {
export function getF64(offset: _MemOffset): number {
return Module.HEAPF64[<any>offset >>> 3];
}
......@@ -3,13 +3,13 @@
import { WasmRoot, WasmRootBuffer, mono_wasm_new_root } from "./roots";
import { MonoClass, MonoMethod, MonoObject, coerceNull, VoidPtrNull, VoidPtr, MonoType } from "./types";
import { BINDING, runtimeHelpers } from "./modules";
import { BINDING, Module, runtimeHelpers } from "./imports";
import { js_to_mono_enum, _js_to_mono_obj, _js_to_mono_uri } from "./js-to-cs";
import { js_string_to_mono_string, js_string_to_mono_string_interned } from "./strings";
import { MarshalType, _unbox_mono_obj_root_with_known_nonprimitive_type } from "./cs-to-js";
import {
_create_temp_frame,
getI32, getU32, getF32, getF64,
import {
_create_temp_frame,
getI32, getU32, getF32, getF64,
setI32, setU32, setF32, setF64, setI64,
} from "./memory";
import {
......
......@@ -7,7 +7,7 @@ import {
MonoObjectNull, MonoString, coerceNull as coerceNull,
VoidPtr, VoidPtrNull, Int32Ptr, MonoStringNull
} from "./types";
import { BINDING, INTERNAL, Module, MONO, runtimeHelpers } from "./modules";
import { BINDING, INTERNAL, Module, MONO, runtimeHelpers } from "./imports";
import { _mono_array_root_to_js_array, _unbox_mono_obj_root } from "./cs-to-js";
import { get_js_obj, mono_wasm_get_jsobj_from_js_handle } from "./gc-handles";
import { js_array_to_mono_array, _box_js_bool, _js_to_mono_obj } from "./js-to-cs";
......
......@@ -8,7 +8,7 @@
"version": "1.0.0",
"scripts": {
"rollup": "rollup -c",
"lint": "eslint --no-color --max-warnings=0 ./**/*.ts ./**/*.js"
"lint": "eslint --no-color --max-warnings=0 ./**/*.ts ./*.js"
},
"keywords": [
"dotnet",
......
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
import { Module } from "./modules";
import { Module } from "./imports";
import { AOTProfilerOptions, CoverageProfilerOptions } from "./types";
// Initialize the AOT profiler with OPTIONS.
......
......@@ -11,13 +11,15 @@ const isDebug = process.env.Configuration !== "Release";
const nativeBinDir = process.env.NativeBinDir ? process.env.NativeBinDir.replace(/"/g, "") : "bin";
const terserConfig = {
compress: {
defaults: false,// to agressive minification breaks subsequent emcc compilation
defaults: false,// too agressive minification breaks subsequent emcc compilation
drop_debugger: false,// we invoke debugger
drop_console: false,// we log to console
unused: false,// this breaks stuff
// below are minification features which seems to work fine
collapse_vars: true,
conditionals: true,
computed_props: true,
properties: true,
dead_code: true,
if_return: true,
inline: true,
......@@ -32,39 +34,40 @@ const terserConfig = {
// because of stack walk at src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs
keep_fnames: /(mono_wasm_runtime_ready|mono_wasm_fire_debugger_agent_message)/,
},
// we export ES5 because emcc parser has trouble parsing it otherwise
ecma: 5,
};
const plugins = isDebug ? [writeOnChangePlugin()] : [terser(terserConfig), writeOnChangePlugin()];
const banner = "//! Licensed to the .NET Foundation under one or more agreements.\n//! The .NET Foundation licenses this file to you under the MIT license.\n";
// emcc doesn't know how to load ES6 module, that's why we need the whole rollup.js
const format = "iife";
const name = "__dotnet_runtime";
export default defineConfig([
{
treeshake: !isDebug,
input: "exports.ts",
output: [{
banner: "//! Licensed to the .NET Foundation under one or more agreements.\n//! The .NET Foundation licenses this file to you under the MIT license.\n",
name: "__dotnet_runtime",
file: nativeBinDir + "/src/" + outputFileName,
// emcc doesn't know how to load ES6 module, that's why we need the whole rollup.js
format: "iife",
plugins: plugins
name,
banner,
format,
plugins,
}],
plugins: [typescript()]
},
{
input: "./exports.ts",
input: "./export-types.ts",
output: [
// dotnet.d.ts
{
format: "es",
file: nativeBinDir + "/src/" + "dotnet.d.ts",
}
],
plugins: [dts()],
},
}
]);
// this would create .md5 file next to the output file, so that we do not touch datetime of the file if it's same -> faster incremental build.
// this would create .sha256 file next to the output file, so that we do not touch datetime of the file if it's same -> faster incremental build.
function writeOnChangePlugin() {
return {
name: "writeOnChange",
......
......@@ -2,7 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
import cwraps from "./cwraps";
import { Module } from "./modules";
import { Module } from "./imports";
import { VoidPtr, ManagedPointer, NativePointer } from "./types";
const maxScratchRoots = 8192;
......
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
import { INTERNAL, Module, MONO, runtimeHelpers } from "./modules";
import { AllAssetEntryTypes, AssetEntry, CharPtr, CharPtrNull, EmscriptenModuleMono, GlobalizationMode, MonoConfig, VoidPtr, wasm_type_symbol } from "./types";
import { ENVIRONMENT_IS_NODE, ENVIRONMENT_IS_SHELL, INTERNAL, locateFile, Module, MONO, runtimeHelpers } from "./imports";
import cwraps from "./cwraps";
import { mono_wasm_raise_debug_event, mono_wasm_runtime_ready } from "./debug";
import { mono_wasm_globalization_init, mono_wasm_load_icu_data } from "./icu";
......@@ -12,11 +12,25 @@ import { mono_wasm_load_bytes_into_heap } from "./buffers";
import { bind_runtime_method, get_method, _create_primitive_converters } from "./method-binding";
import { find_corlib_class } from "./class-loader";
export let runtime_is_initialized_resolve: Function;
export let runtime_is_initialized_reject: Function;
export const mono_wasm_runtime_is_initialized = new Promise((resolve, reject) => {
runtime_is_initialized_resolve = resolve;
runtime_is_initialized_reject = reject;
});
export async function mono_wasm_pre_init(): Promise<void> {
const moduleExt = Module as EmscriptenModuleMono;
if (moduleExt.configSrc) {
// sets MONO.config implicitly
await mono_wasm_load_config(moduleExt.configSrc);
try {
// sets MONO.config implicitly
await mono_wasm_load_config(moduleExt.configSrc);
}
catch (err: any) {
runtime_is_initialized_reject(err);
throw err;
}
if (moduleExt.onConfigLoaded) {
try {
......@@ -26,6 +40,7 @@ export async function mono_wasm_pre_init(): Promise<void> {
Module.printErr("MONO_WASM: onConfigLoaded () failed: " + err);
Module.printErr("MONO_WASM: Stacktrace: \n");
Module.printErr(err.stack);
runtime_is_initialized_reject(err);
throw err;
}
}
......@@ -62,10 +77,11 @@ async function _fetch_asset(url: string): Promise<Response> {
return fetch(url, { credentials: "same-origin" });
}
else if (ENVIRONMENT_IS_NODE) {
//const fs = (<any>globalThis).require("fs");
// eslint-disable-next-line @typescript-eslint/no-var-requires
const fs = require("fs");
const arrayBuffer = await fs.promises.readFile(url);
return <Response><any> {
return <Response><any>{
ok: true,
url,
arrayBuffer: () => arrayBuffer,
......@@ -74,7 +90,7 @@ async function _fetch_asset(url: string): Promise<Response> {
}
else if (typeof (read) === "function") {
const arrayBuffer = new Uint8Array(read(url, "binary"));
return <Response><any> {
return <Response><any>{
ok: true,
url,
arrayBuffer: () => arrayBuffer,
......@@ -83,7 +99,7 @@ async function _fetch_asset(url: string): Promise<Response> {
}
}
catch (e: any) {
return <Response><any> {
return <Response><any>{
ok: false,
url,
arrayBuffer: () => { throw e; },
......@@ -196,11 +212,12 @@ function _finalize_startup(args: MonoConfig, ctx: MonoInitContext) {
if (ENVIRONMENT_IS_SHELL || ENVIRONMENT_IS_NODE) {
try {
cwraps.mono_wasm_load_runtime("unused", args.debug_level || 0);
} catch (ex: any) {
Module.printErr("MONO_WASM: mono_wasm_load_runtime () failed: " + ex);
} catch (err: any) {
Module.printErr("MONO_WASM: mono_wasm_load_runtime () failed: " + err);
Module.printErr("MONO_WASM: Stacktrace: \n");
Module.printErr(ex.stack);
Module.printErr(err.stack);
runtime_is_initialized_reject(err);
const wasm_exit = cwraps.mono_wasm_exit;
wasm_exit(1);
}
......@@ -219,6 +236,21 @@ function _finalize_startup(args: MonoConfig, ctx: MonoInitContext) {
mono_wasm_setenv("TZ", tz || "UTC");
mono_wasm_runtime_ready();
//legacy config loading
const argsAny: any = args;
if (argsAny.loaded_cb) {
try {
argsAny.loaded_cb();
}
catch (err: any) {
Module.printErr("MONO_WASM: loaded_cb () failed: " + err);
Module.printErr("MONO_WASM: Stacktrace: \n");
Module.printErr(err.stack);
runtime_is_initialized_reject(err);
throw err;
}
}
if (moduleExt.onDotNetReady) {
try {
moduleExt.onDotNetReady();
......@@ -227,9 +259,12 @@ function _finalize_startup(args: MonoConfig, ctx: MonoInitContext) {
Module.printErr("MONO_WASM: onDotNetReady () failed: " + err);
Module.printErr("MONO_WASM: Stacktrace: \n");
Module.printErr(err.stack);
runtime_is_initialized_reject(err);
throw err;
}
}
runtime_is_initialized_resolve();
}
export function bindings_lazy_init(): void {
......@@ -381,9 +416,10 @@ export async function mono_load_runtime_and_bcl_args(args: MonoConfig): Promise<
await Promise.all(fetch_promises);
_finalize_startup(args, ctx);
} catch (exc: any) {
console.error("MONO_WASM: Error in mono_load_runtime_and_bcl_args:", exc);
throw exc;
} catch (err: any) {
console.error("MONO_WASM: Error in mono_load_runtime_and_bcl_args:", err);
runtime_is_initialized_reject(err);
throw err;
}
}
......@@ -462,11 +498,12 @@ export async function mono_wasm_load_config(configFilePath: string): Promise<voi
config.runtime_options = config.runtime_options || [];
config.globalization_mode = config.globalization_mode || GlobalizationMode.AUTO;
} catch (exc) {
const errMessage = `Failed to load config file ${configFilePath} ${exc}`;
} catch (err) {
const errMessage = `Failed to load config file ${configFilePath} ${err}`;
console.error(errMessage);
runtimeHelpers.config = { message: errMessage, error: exc, isError: true };
throw exc;
runtimeHelpers.config = { message: errMessage, error: err, isError: true };
runtime_is_initialized_reject(err);
throw err;
} finally {
Module.removeRunDependency(configFilePath);
}
......
......@@ -3,7 +3,7 @@
import { mono_wasm_new_root_buffer, WasmRootBuffer } from "./roots";
import { CharPtr, MonoString, MonoStringNull, NativePointer } from "./types";
import { Module } from "./modules";
import { Module } from "./imports";
import cwraps from "./cwraps";
import { mono_wasm_new_root } from "./roots";
import { getI32 } from "./memory";
......@@ -187,7 +187,7 @@ export function js_string_to_mono_string(string: string): MonoString | null {
return js_string_to_mono_string_new(string);
}
export function js_string_to_mono_string_new(string: string) : MonoString {
export function js_string_to_mono_string_new(string: string): MonoString {
const buffer = Module._malloc((string.length + 1) * 2);
const buffer16 = (<any>buffer >>> 1) | 0;
for (let i = 0; i < string.length; i++)
......
......@@ -4,7 +4,7 @@
"noEmitOnError": true,
"removeComments": false,
"sourceMap": false,
"target": "ES5",
"target": "ES2018",
"moduleResolution": "Node",
"lib": [
"esnext",
......
......@@ -179,7 +179,9 @@ export type CoverageProfilerOptions = {
}
// how we extended emscripten Module
export type EmscriptenModuleMono = EmscriptenModule & {
export type EmscriptenModuleMono = EmscriptenModule & EmscriptenModuleConfig;
export type EmscriptenModuleConfig = {
disableDotNet6Compatibility?: boolean,
// backward compatibility
......
......@@ -22,20 +22,6 @@ declare interface CharPtrPtr extends NativePointer {
__brand: "CharPtrPtr"
}
declare let ENVIRONMENT_IS_WEB: boolean;
declare let ENVIRONMENT_IS_SHELL: boolean;
declare let ENVIRONMENT_IS_NODE: boolean;
declare let ENVIRONMENT_IS_WORKER: boolean;
declare let LibraryManager: any;
declare function autoAddDeps(a: object, b: string): void;
declare function mergeInto(a: object, b: object): void;
// TODO, what's wrong with EXPORTED_RUNTIME_METHODS ?
declare function locateFile(path: string, prefix?: string): string;
declare let Module: EmscriptenModule;
declare interface EmscriptenModule {
HEAP8: Int8Array,
HEAP16: Int16Array;
......@@ -66,7 +52,7 @@ declare interface EmscriptenModule {
removeRunDependency(id: string): void;
addRunDependency(id: string): void;
preInit?: () => Promise<void>;
preInit?: (() => Promise<void>)[];
onRuntimeInitialized?: () => void;
}
......
......@@ -11,6 +11,7 @@ import { _wrap_js_thenable_as_task } from "./js-to-cs";
import { wrap_error } from "./method-calls";
import { conv_string } from "./strings";
import { Int32Ptr, JSHandle, MonoArray, MonoObject, MonoObjectNull, MonoString } from "./types";
import { Module } from "./imports";
const wasm_ws_pending_send_buffer = Symbol.for("wasm ws_pending_send_buffer");
const wasm_ws_pending_send_buffer_offset = Symbol.for("wasm ws_pending_send_buffer_offset");
......
......@@ -8,7 +8,7 @@
//glue code to deal with the differences between chrome, ch, d8, jsc and sm.
const is_browser = typeof window != "undefined";
const is_node = !is_browser && typeof process != 'undefined';
const is_node = !is_browser && typeof process === 'object' && typeof process.versions === 'object' && typeof process.versions.node === 'string';
// if the engine doesn't provide a console
if (typeof (console) === "undefined") {
......@@ -22,6 +22,8 @@ const originalConsole = {
error: console.error
};
let isXUnitDoneCheck = false;
function proxyMethod(prefix, func, asJson) {
return function () {
const args = [...arguments];
......@@ -36,6 +38,9 @@ function proxyMethod(prefix, func, asJson) {
payload = payload.toString();
}
}
if (payload.indexOf("=== TEST EXECUTION SUMMARY ===") != -1) {
isXUnitDoneCheck = true;
}
if (asJson) {
func(JSON.stringify({
......@@ -65,14 +70,21 @@ if (is_browser) {
const consoleUrl = `${window.location.origin}/console`.replace('http://', 'ws://');
let consoleWebSocket = new WebSocket(consoleUrl);
consoleWebSocket.onopen = function (event) {
proxyJson(function (msg) {
// redirect output so that when emscripten starts it's already redirected
proxyJson(function (msg) {
if (consoleWebSocket.readyState === WebSocket.OPEN) {
consoleWebSocket.send(msg);
});
console.log("browser: Console websocket connected.");
}
else {
originalConsole.log(msg);
}
});
consoleWebSocket.onopen = function (event) {
originalConsole.log("browser: Console websocket connected.");
};
consoleWebSocket.onerror = function (event) {
console.error(`websocket error: ${event}`);
originalConsole.error(`websocket error: ${event}`);
};
}
......@@ -101,18 +113,14 @@ if (typeof globalThis.performance === 'undefined') {
}
}
}
var Module = {
no_global_exports: true,
mainScriptUrlOrBlob: "dotnet.js",
config: null,
configSrc: "./mono-config.json",
print: console.log,
printErr: console.error,
onConfigLoaded: function () {
onConfigLoaded: () => {
if (!Module.config) {
console.error("Could not find ./mono-config.json. Cancelling run");
fail_exec(1);
const err = new Error("Could not find ./mono-config.json. Cancelling run");
set_exit_code(1,);
throw err;
}
// Have to set env vars here to enable setting MONO_LOG_LEVEL etc.
for (let variable in processedArguments.setenv) {
......@@ -123,10 +131,10 @@ var Module = {
INTERNAL.mono_wasm_enable_on_demand_gc(0);
}
},
onDotNetReady: function () {
onDotNetReady: () => {
let wds = Module.FS.stat(processedArguments.working_dir);
if (wds === undefined || !Module.FS.isDir(wds.mode)) {
fail_exec(1, `Could not find working directory ${processedArguments.working_dir}`);
set_exit_code(1, `Could not find working directory ${processedArguments.working_dir}`);
return;
}
......@@ -134,26 +142,26 @@ var Module = {
App.init();
},
onAbort: function (x) {
console.log("ABORT: " + x);
onAbort: (error) => {
console.log("ABORT: " + error);
const err = new Error();
console.log("Stacktrace: \n");
console.error(err.stack);
fail_exec(1);
set_exit_code(1, error);
},
};
const App = {
init: function () {
init: async function () {
console.info("Initializing.....");
for (let i = 0; i < processedArguments.profilers.length; ++i) {
const init = Module.cwrap('mono_wasm_load_profiler_' + processedArguments.profilers[i], 'void', ['string']);
init("");
}
if (processedArguments.applicationArgs.length == 0) {
fail_exec(1, "Missing required --run argument");
set_exit_code(1, "Missing required --run argument");
return;
}
......@@ -171,7 +179,7 @@ const App = {
}
if (res)
fail_exec(1, "REGRESSION TEST FAILED");
set_exit_code(1, "REGRESSION TEST FAILED");
return;
}
......@@ -182,31 +190,23 @@ const App = {
if (processedArguments.applicationArgs[0] == "--run") {
// Run an exe
if (processedArguments.applicationArgs.length == 1) {
fail_exec(1, "Error: Missing main executable argument.");
set_exit_code(1, "Error: Missing main executable argument.");
return;
}
try {
const main_assembly_name = processedArguments.applicationArgs[1];
const app_args = processedArguments.applicationArgs.slice(2);
INTERNAL.mono_wasm_set_main_args(processedArguments.applicationArgs[1], app_args);
// Automatic signature isn't working correctly
const result = BINDING.call_assembly_entry_point(main_assembly_name, [app_args], "m");
const onError = function (error) {
console.error(error);
if (error.stack)
console.error(error.stack);
const main_assembly_name = processedArguments.applicationArgs[1];
const app_args = processedArguments.applicationArgs.slice(2);
INTERNAL.mono_wasm_set_main_args(processedArguments.applicationArgs[1], app_args);
fail_exec(1);
}
try {
result.then(fail_exec).catch(onError);
// Automatic signature isn't working correctly
const result = await BINDING.call_assembly_entry_point(main_assembly_name, [app_args], "m");
set_exit_code(result);
} catch (error) {
onError(error);
set_exit_code(1, error);
}
} else {
fail_exec(1, "Unhandled argument: " + processedArguments.applicationArgs[0]);
set_exit_code(1, "Unhandled argument: " + processedArguments.applicationArgs[0]);
}
},
......@@ -229,19 +229,41 @@ const App = {
};
globalThis.App = App; // Necessary as System.Runtime.InteropServices.JavaScript.Tests.MarshalTests (among others) call the App.call_test_method directly
function fail_exec(exit_code, reason) {
function set_exit_code(exit_code, reason) {
if (reason) {
console.error(reason);
console.error(reason.toString());
if (reason.stack) {
console.error(reason.stack);
}
}
if (is_browser) {
const stack = (new Error()).stack.replace(/\n/g, "").replace(/[ ]*at/g, " at").replace(/https?:\/\/[0-9.:]*/g, "").replace("Error", "");
const messsage = `Exit called with ${exit_code} when isXUnitDoneCheck=${isXUnitDoneCheck} ${stack}.`;
// Notify the selenium script
Module.exit_code = exit_code;
originalConsole.log("WASM EXIT " + exit_code);
//Tell xharness WasmBrowserTestRunner what was the exit code
const tests_done_elem = document.createElement("label");
tests_done_elem.id = "tests_done";
tests_done_elem.innerHTML = exit_code.toString();
document.body.appendChild(tests_done_elem);
} else { // shell or node
// need to flush streams (stdout/stderr)
for (const stream of Module.FS.streams) {
if (stream && stream.stream_ops && stream.stream_ops.flush) {
stream.stream_ops.flush(stream);
}
}
console.log("Flushed stdout!");
console.log('1 ' + messsage);
setTimeout(() => {
originalConsole.log('2 ' + messsage);
// tell xharness WasmTestMessagesProcessor we are done.
console.log("WASM EXIT " + exit_code);
}, 100);
} else if (INTERNAL) {
INTERNAL.mono_wasm_exit(exit_code);
}
}
......@@ -262,7 +284,7 @@ function processArguments(incomingArguments) {
const arg = currentArg.substring("--setenv=".length);
const parts = arg.split('=');
if (parts.length != 2)
fail_exec(1, "Error: malformed argument: '" + currentArg);
set_exit_code(1, "Error: malformed argument: '" + currentArg);
setenv[parts[0]] = parts[1];
} else if (currentArg.startsWith("--runtime-arg=")) {
const arg = currentArg.substring("--runtime-arg=".length);
......@@ -322,8 +344,10 @@ try {
async function loadDotnet(file) {
let loadScript = undefined;
if (typeof WScript !== "undefined") { // Chakra
loadScript = WScript.LoadScriptFile;
return globalThis.Module;
loadScript = function (file) {
WScript.LoadScriptFile(file);
return globalThis.Module;
};
} else if (is_node) { // NodeJS
loadScript = async function (file) {
return require(file);
......@@ -333,7 +357,17 @@ async function loadDotnet(file) {
const script = document.createElement("script");
script.src = file;
document.head.appendChild(script);
return globalThis.Module;
let timeout = 100;
// bysy spin waiting for script to load into global namespace
while (timeout > 0) {
if (globalThis.Module) {
return globalThis.Module;
}
// delay 10ms
await new Promise(resolve => setTimeout(resolve, 10));
timeout--;
}
throw new Error("Can't load " + file);
}
}
else if (typeof globalThis.load !== 'undefined') {
......@@ -351,6 +385,6 @@ async function loadDotnet(file) {
loadDotnet("./dotnet.js").catch(function (err) {
console.error(err);
fail_exec(1, "failed to load the dotnet.js file");
set_exit_code(1, "failed to load the dotnet.js file");
throw err;
});
\ No newline at end of file
......@@ -174,12 +174,12 @@ private bool ExecuteInternal ()
if (!FileCopyChecked(item.ItemSpec, dest, "NativeAssets"))
return false;
}
FileCopyChecked(MainJS!, Path.Combine(AppDir, "runtime.js"), string.Empty);
FileCopyChecked(MainJS!, Path.Combine(AppDir, "main.js"), string.Empty);
string indexHtmlPath = Path.Combine(AppDir, "index.html");
if (!File.Exists(indexHtmlPath))
{
var html = @"<html><body><script type=""text/javascript"" src=""runtime.js""></script></body></html>";
var html = @"<html><body><script type=""text/javascript"" src=""main.js""></script></body></html>";
File.WriteAllText(indexHtmlPath, html);
}
......
......@@ -147,7 +147,7 @@ public BuildTestBase(ITestOutputHelper output, SharedBuildPerTestClassFixture bu
string bundleDir = Path.Combine(GetBinDir(baseDir: buildDir, config: buildArgs.Config), "AppBundle");
(string testCommand, string extraXHarnessArgs) = host switch
{
RunHost.V8 => ("wasm test", "--js-file=runtime.js --engine=V8 -v trace"),
RunHost.V8 => ("wasm test", "--js-file=main.js --engine=V8 -v trace"),
_ => ("wasm test-browser", $"-v trace -b {host}")
};
......@@ -254,7 +254,7 @@ protected static void InitProjectDir(string dir)
<TargetFramework>{s_targetFramework}</TargetFramework>
<OutputType>Exe</OutputType>
<WasmGenerateRunV8Script>true</WasmGenerateRunV8Script>
<WasmMainJSPath>runtime-test.js</WasmMainJSPath>
<WasmMainJSPath>test-main.js</WasmMainJSPath>
##EXTRA_PROPERTIES##
</PropertyGroup>
<ItemGroup>
......@@ -310,7 +310,7 @@ protected static BuildArgs ExpandBuildArgs(BuildArgs buildArgs, string extraProp
initProject?.Invoke();
File.WriteAllText(Path.Combine(_projectDir, $"{buildArgs.ProjectName}.csproj"), buildArgs.ProjectFileContents);
File.Copy(Path.Combine(AppContext.BaseDirectory, "runtime-test.js"), Path.Combine(_projectDir, "runtime-test.js"));
File.Copy(Path.Combine(AppContext.BaseDirectory, "test-main.js"), Path.Combine(_projectDir, "test-main.js"));
}
else if (_projectDir is null)
{
......@@ -486,7 +486,7 @@ protected static void AssertBasicAppBundle(string bundleDir, string projectName,
AssertFilesExist(bundleDir, new []
{
"index.html",
"runtime.js",
"main.js",
"dotnet.timezones.blat",
"dotnet.wasm",
"mono-config.json",
......
......@@ -148,7 +148,7 @@ private void CreateProgramForCultureTest(string dir, string resourceName, string
<TargetFramework>{s_targetFramework}</TargetFramework>
<OutputType>Exe</OutputType>
<WasmGenerateRunV8Script>true</WasmGenerateRunV8Script>
<WasmMainJSPath>runtime-test.js</WasmMainJSPath>
<WasmMainJSPath>test-main.js</WasmMainJSPath>
##EXTRA_PROPERTIES##
</PropertyGroup>
<ItemGroup>
......
......@@ -27,7 +27,7 @@
</PropertyGroup>
<ItemGroup>
<None Include="$(RepoRoot)\src\mono\wasm\runtime-test.js" CopyToOutputDirectory="PreserveNewest" />
<None Include="$(RepoRoot)\src\mono\wasm\test-main.js" CopyToOutputDirectory="PreserveNewest" />
<None Include="..\testassets\**\*" Link="testassets\%(RecursiveDir)%(FileName)%(Extension)" CopyToOutputDirectory="PreserveNewest" />
<None Include="data\**\*" Link="data\%(RecursiveDir)%(FileName)%(Extension)" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
......
......@@ -155,7 +155,7 @@
TargetDir="wasm-test-runner/"/>
<RunTimeDependencyCopyLocal
Include="$(MonoProjectRoot)\wasm\runtime-test.js"
Include="$(MonoProjectRoot)\wasm\test-main.js"
TargetDir="runtime-test/"/>
<RunTimeDependencyCopyLocal
......
......@@ -23,7 +23,7 @@
<PropertyGroup>
<WasmMainAssemblyFileName>$(TestAssemblyFileName)</WasmMainAssemblyFileName>
<WasmAppDir>$(AppDir)</WasmAppDir>
<WasmMainJSPath>$(CORE_ROOT)\runtime-test\runtime-test.js</WasmMainJSPath>
<WasmMainJSPath>$(CORE_ROOT)\runtime-test\test-main.js</WasmMainJSPath>
<WasmResolveAssembliesBeforeBuild>true</WasmResolveAssembliesBeforeBuild>
<WasmGenerateRunV8Script>true</WasmGenerateRunV8Script>
<WasmSkipMissingAssemblies>true</WasmSkipMissingAssemblies>
......
......@@ -387,7 +387,7 @@
TargetDir="wasm-test-runner/"/>
<RunTimeDependencyCopyLocal
Include="$(MonoProjectRoot)\wasm\runtime-test.js"
Include="$(MonoProjectRoot)\wasm\test-main.js"
TargetDir="runtime-test/"/>
<RunTimeDependencyCopyLocal
......
......@@ -6,9 +6,9 @@
<TestRuntime>true</TestRuntime>
<Scenario>WasmTestOnBrowser</Scenario>
<ExpectedExitCode>42</ExpectedExitCode>
<WasmMainJSPath>runtime.js</WasmMainJSPath>
<WasmMainJSPath>main.js</WasmMainJSPath>
<EnableDefaultItems>false</EnableDefaultItems>
<!-- setting WasmXHarnessMonoArgs doesn't work here, but see runtime.js -->
<!-- setting WasmXHarnessMonoArgs doesn't work here, but see main.js -->
<!-- <WasmXHarnessMonoArgs>- -setenv=DOTNET_MODIFIABLE_ASSEMBLIES=debug</WasmXHarnessMonoArgs> -->
</PropertyGroup>
<ItemGroup>
......
......@@ -2,54 +2,41 @@
<!-- Licensed to the .NET Foundation under one or more agreements. -->
<!-- The .NET Foundation licenses this file to you under the MIT license. -->
<html>
<head>
<title>TESTS</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body onload="onLoad()">
<h3 id="header">Wasm Browser Sample</h3>
Result from Sample.Test.TestMeaning: <span id="out"></span>
<script type='text/javascript'>
var is_testing = false;
var onLoad = function() {
var url = new URL(decodeURI(window.location));
let args = url.searchParams.getAll('arg');
is_testing = args !== undefined && (args.find(arg => arg == '--testing') !== undefined);
};
var test_exit = function(exit_code)
{
if (!is_testing) {
console.log(`test_exit: ${exit_code}`);
return;
}
<head>
<title>Wasm HotReload Test</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
/* Set result in a tests_done element, to be read by xharness */
var tests_done_elem = document.createElement("label");
tests_done_elem.id = "tests_done";
tests_done_elem.innerHTML = exit_code.toString();
document.body.appendChild(tests_done_elem);
<body>
<h3 id="header">Wasm HotReload Test</h3>
Result from Sample.Test.TestMeaning: <span id="out"></span>
<script type='text/javascript'>
function set_exit_code(exit_code, reason) {
/* Set result in a tests_done element, to be read by xharness */
var tests_done_elem = document.createElement("label");
tests_done_elem.id = "tests_done";
tests_done_elem.innerHTML = exit_code.toString();
document.body.appendChild(tests_done_elem);
console.log(`WASM EXIT ${exit_code}`);
};
console.log(`WASM EXIT ${exit_code}`);
};
var App = {
init: function () {
var exit_code = INTERNAL.call_static_method("[WebAssembly.Browser.HotReload.Test] Sample.Test:TestMeaning", []);
document.getElementById("out").innerHTML = exit_code;
var App = {
init: function () {
const testMeaning = BINDING.bind_static_method("[WebAssembly.Browser.HotReload.Test] Sample.Test:TestMeaning");
var exit_code = testMeaning();
document.getElementById("out").innerHTML = exit_code;
if (is_testing)
{
console.debug(`exit_code: ${exit_code}`);
test_exit(exit_code);
}
},
};
</script>
<script type="text/javascript" src="runtime.js"></script>
console.debug(`exit_code: ${exit_code}`);
set_exit_code(exit_code);
},
};
</script>
<script type="text/javascript" src="main.js"></script>
<script defer src="dotnet.js"></script>
<script defer src="dotnet.js"></script>
</body>
</body>
</html>
</html>
\ No newline at end of file
......@@ -4,20 +4,19 @@
"use strict";
var Module = {
config: null,
configSrc: "./mono-config.json",
onConfigLoaded: function () {
onConfigLoaded: () => {
MONO.config.environment_variables["DOTNET_MODIFIABLE_ASSEMBLIES"] = "debug";
},
onDotNetReady: function () {
onDotNetReady: () => {
try {
App.init();
} catch (error) {
test_exit(1);
set_exit_code(1, error);
throw (error);
}
},
onAbort: function () {
test_exit(1);
onAbort: (error) => {
set_exit_code(1, error);
},
};
......@@ -3,7 +3,7 @@
<TestRuntime>true</TestRuntime>
<Scenario>WasmTestOnBrowser</Scenario>
<ExpectedExitCode>42</ExpectedExitCode>
<WasmMainJSPath>runtime.js</WasmMainJSPath>
<WasmMainJSPath>main.js</WasmMainJSPath>
</PropertyGroup>
<ItemGroup>
......
......@@ -2,54 +2,41 @@
<!-- Licensed to the .NET Foundation under one or more agreements. -->
<!-- The .NET Foundation licenses this file to you under the MIT license. -->
<html>
<head>
<title>TESTS</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body onload="onLoad()">
<h3 id="header">Wasm Browser Sample</h3>
Result from Sample.Test.TestMeaning: <span id="out"></span>
<script type='text/javascript'>
var is_testing = false;
var onLoad = function() {
var url = new URL(decodeURI(window.location));
let args = url.searchParams.getAll('arg');
is_testing = args !== undefined && (args.find(arg => arg == '--testing') !== undefined);
};
var test_exit = function(exit_code)
{
if (!is_testing) {
console.log(`test_exit: ${exit_code}`);
return;
}
<head>
<title>Runtime config test</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
/* Set result in a tests_done element, to be read by xharness */
var tests_done_elem = document.createElement("label");
tests_done_elem.id = "tests_done";
tests_done_elem.innerHTML = exit_code.toString();
document.body.appendChild(tests_done_elem);
<body>
<h3 id="header">Runtime config test</h3>
Result from Sample.Test.TestMeaning: <span id="out"></span>
<script type='text/javascript'>
function set_exit_code(exit_code, reason) {
/* Set result in a tests_done element, to be read by xharness */
var tests_done_elem = document.createElement("label");
tests_done_elem.id = "tests_done";
tests_done_elem.innerHTML = exit_code.toString();
document.body.appendChild(tests_done_elem);
console.log(`WASM EXIT ${exit_code}`);
};
console.log(`WASM EXIT ${exit_code}`);
};
var App = {
init: function () {
var exit_code = INTERNAL.call_static_method("[WebAssembly.Browser.RuntimeConfig.Test] Sample.Test:TestMeaning", []);
document.getElementById("out").innerHTML = exit_code;
var App = {
init: function () {
const testMeaning = BINDING.bind_static_method("[WebAssembly.Browser.RuntimeConfig.Test] Sample.Test:TestMeaning");
var exit_code = testMeaning();
document.getElementById("out").innerHTML = exit_code;
if (is_testing)
{
console.debug(`exit_code: ${exit_code}`);
test_exit(exit_code);
}
},
};
</script>
<script type="text/javascript" src="runtime.js"></script>
console.debug(`exit_code: ${exit_code}`);
set_exit_code(exit_code);
},
};
</script>
<script type="text/javascript" src="main.js"></script>
<script defer src="dotnet.js"></script>
<script defer src="dotnet.js"></script>
</body>
</body>
</html>
</html>
\ No newline at end of file
......@@ -4,17 +4,16 @@
"use strict";
var Module = {
config: null,
configSrc: "./mono-config.json",
onDotNetReady: function () {
onDotNetReady: () => {
try {
App.init();
} catch (error) {
test_exit(1);
set_exit_code(1, error);
throw (error);
}
},
onAbort: function () {
test_exit(1);
onAbort: (error) => {
set_exit_code(1, error);
},
};
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册