Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/sdks/wasm
diff options
context:
space:
mode:
authorThays Grazia <thaystg@gmail.com>2020-08-14 14:29:47 +0300
committerGitHub <noreply@github.com>2020-08-14 14:29:47 +0300
commit2d567b395e1fe467a83c2ecb7484196cc57fa2aa (patch)
treef75a07f8626b3e0e3d3ebb5646dae6505663de12 /sdks/wasm
parent5f44f27a0d84bc911ac932f11d2c45fa490b7152 (diff)
[wasm] Renaming debugger files. (#20244)
* Renaming projects and files as we did on dotnet/runtime repo. * Fixing library-mono.js to run debugger tests. Fixing typo on DebuggerTestSuite.
Diffstat (limited to 'sdks/wasm')
-rw-r--r--sdks/wasm/BrowserDebugHost/BrowserDebugHost.csproj (renamed from sdks/wasm/ProxyDriver/ProxyDriver.csproj)2
-rw-r--r--sdks/wasm/BrowserDebugHost/Program.cs (renamed from sdks/wasm/ProxyDriver/Program.cs)0
-rw-r--r--sdks/wasm/BrowserDebugHost/Properties/launchSettings.json (renamed from sdks/wasm/ProxyDriver/Properties/launchSettings.json)2
-rw-r--r--sdks/wasm/BrowserDebugHost/Startup.cs (renamed from sdks/wasm/ProxyDriver/Startup.cs)0
-rw-r--r--sdks/wasm/BrowserDebugHost/TestHarnessStartup.cs (renamed from sdks/wasm/ProxyDriver/TestHarnessStartup.cs)0
-rw-r--r--sdks/wasm/BrowserDebugProxy/.editorconfig (renamed from sdks/wasm/Mono.WebAssembly.DebuggerProxy/.editorconfig)0
-rw-r--r--sdks/wasm/BrowserDebugProxy/AssemblyInfo.cs (renamed from sdks/wasm/Mono.WebAssembly.DebuggerProxy/AssemblyInfo.cs)0
-rw-r--r--sdks/wasm/BrowserDebugProxy/BrowserDebugProxy.csproj (renamed from sdks/wasm/Mono.WebAssembly.DebuggerProxy/Mono.WebAssembly.DebuggerProxy.csproj)0
-rw-r--r--sdks/wasm/BrowserDebugProxy/BrowserDebugProxy.sln (renamed from sdks/wasm/Mono.WebAssembly.DebuggerProxy/Mono.WebAssembly.DebuggerProxy.sln)4
-rw-r--r--sdks/wasm/BrowserDebugProxy/DebugStore.cs (renamed from sdks/wasm/Mono.WebAssembly.DebuggerProxy/DebugStore.cs)0
-rw-r--r--sdks/wasm/BrowserDebugProxy/DebuggerProxy.cs (renamed from sdks/wasm/Mono.WebAssembly.DebuggerProxy/DebuggerProxy.cs)0
-rw-r--r--sdks/wasm/BrowserDebugProxy/DevToolsHelper.cs (renamed from sdks/wasm/Mono.WebAssembly.DebuggerProxy/DevToolsHelper.cs)0
-rw-r--r--sdks/wasm/BrowserDebugProxy/DevToolsProxy.cs (renamed from sdks/wasm/Mono.WebAssembly.DebuggerProxy/DevToolsProxy.cs)0
-rw-r--r--sdks/wasm/BrowserDebugProxy/EvaluateExpression.cs (renamed from sdks/wasm/Mono.WebAssembly.DebuggerProxy/EvaluateExpression.cs)0
-rw-r--r--sdks/wasm/BrowserDebugProxy/MonoProxy.cs (renamed from sdks/wasm/Mono.WebAssembly.DebuggerProxy/MonoProxy.cs)0
-rw-r--r--sdks/wasm/DebuggerTestSuite/DebuggerTestSuite.csproj4
-rw-r--r--sdks/wasm/Makefile8
-rw-r--r--sdks/wasm/README.md2
-rw-r--r--sdks/wasm/package-update/download-packages.ps12
-rw-r--r--sdks/wasm/package-update/download-packages.sh2
-rw-r--r--sdks/wasm/src/library_mono.js1350
21 files changed, 974 insertions, 402 deletions
diff --git a/sdks/wasm/ProxyDriver/ProxyDriver.csproj b/sdks/wasm/BrowserDebugHost/BrowserDebugHost.csproj
index c0551057f5a..f1765749813 100644
--- a/sdks/wasm/ProxyDriver/ProxyDriver.csproj
+++ b/sdks/wasm/BrowserDebugHost/BrowserDebugHost.csproj
@@ -9,7 +9,7 @@
</ItemGroup>
<ItemGroup>
- <ProjectReference Include="..\Mono.WebAssembly.DebuggerProxy\Mono.WebAssembly.DebuggerProxy.csproj" />
+ <ProjectReference Include="..\BrowserDebugProxy\BrowserDebugProxy.csproj" />
</ItemGroup>
</Project>
diff --git a/sdks/wasm/ProxyDriver/Program.cs b/sdks/wasm/BrowserDebugHost/Program.cs
index faaa4960c58..faaa4960c58 100644
--- a/sdks/wasm/ProxyDriver/Program.cs
+++ b/sdks/wasm/BrowserDebugHost/Program.cs
diff --git a/sdks/wasm/ProxyDriver/Properties/launchSettings.json b/sdks/wasm/BrowserDebugHost/Properties/launchSettings.json
index 22258c4cb66..0acb48fc972 100644
--- a/sdks/wasm/ProxyDriver/Properties/launchSettings.json
+++ b/sdks/wasm/BrowserDebugHost/Properties/launchSettings.json
@@ -15,7 +15,7 @@
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
- "ProxyDriver": {
+ "BrowserDebugHost": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
diff --git a/sdks/wasm/ProxyDriver/Startup.cs b/sdks/wasm/BrowserDebugHost/Startup.cs
index e18df90c39c..e18df90c39c 100644
--- a/sdks/wasm/ProxyDriver/Startup.cs
+++ b/sdks/wasm/BrowserDebugHost/Startup.cs
diff --git a/sdks/wasm/ProxyDriver/TestHarnessStartup.cs b/sdks/wasm/BrowserDebugHost/TestHarnessStartup.cs
index 6ae4ba32b76..6ae4ba32b76 100644
--- a/sdks/wasm/ProxyDriver/TestHarnessStartup.cs
+++ b/sdks/wasm/BrowserDebugHost/TestHarnessStartup.cs
diff --git a/sdks/wasm/Mono.WebAssembly.DebuggerProxy/.editorconfig b/sdks/wasm/BrowserDebugProxy/.editorconfig
index ca41c33264a..ca41c33264a 100644
--- a/sdks/wasm/Mono.WebAssembly.DebuggerProxy/.editorconfig
+++ b/sdks/wasm/BrowserDebugProxy/.editorconfig
diff --git a/sdks/wasm/Mono.WebAssembly.DebuggerProxy/AssemblyInfo.cs b/sdks/wasm/BrowserDebugProxy/AssemblyInfo.cs
index 8e935c7ed0d..8e935c7ed0d 100644
--- a/sdks/wasm/Mono.WebAssembly.DebuggerProxy/AssemblyInfo.cs
+++ b/sdks/wasm/BrowserDebugProxy/AssemblyInfo.cs
diff --git a/sdks/wasm/Mono.WebAssembly.DebuggerProxy/Mono.WebAssembly.DebuggerProxy.csproj b/sdks/wasm/BrowserDebugProxy/BrowserDebugProxy.csproj
index 4063416ceb0..4063416ceb0 100644
--- a/sdks/wasm/Mono.WebAssembly.DebuggerProxy/Mono.WebAssembly.DebuggerProxy.csproj
+++ b/sdks/wasm/BrowserDebugProxy/BrowserDebugProxy.csproj
diff --git a/sdks/wasm/Mono.WebAssembly.DebuggerProxy/Mono.WebAssembly.DebuggerProxy.sln b/sdks/wasm/BrowserDebugProxy/BrowserDebugProxy.sln
index c99f5389610..cfb208d1562 100644
--- a/sdks/wasm/Mono.WebAssembly.DebuggerProxy/Mono.WebAssembly.DebuggerProxy.sln
+++ b/sdks/wasm/BrowserDebugProxy/BrowserDebugProxy.sln
@@ -3,9 +3,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.28407.52
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProxyDriver", "..\ProxyDriver\ProxyDriver.csproj", "{954F768A-23E6-4B14-90E0-27EA6B41FBCC}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BrowserDebugHost", "..\BrowserDebugHost\BrowserDebugHost.csproj", "{954F768A-23E6-4B14-90E0-27EA6B41FBCC}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mono.WebAssembly.DebuggerProxy", "Mono.WebAssembly.DebuggerProxy.csproj", "{490128B6-9F21-46CA-878A-F22BCF51EF3C}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BrowserDebugProxy", "BrowserDebugProxy.csproj", "{490128B6-9F21-46CA-878A-F22BCF51EF3C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
diff --git a/sdks/wasm/Mono.WebAssembly.DebuggerProxy/DebugStore.cs b/sdks/wasm/BrowserDebugProxy/DebugStore.cs
index f633fe786d5..f633fe786d5 100644
--- a/sdks/wasm/Mono.WebAssembly.DebuggerProxy/DebugStore.cs
+++ b/sdks/wasm/BrowserDebugProxy/DebugStore.cs
diff --git a/sdks/wasm/Mono.WebAssembly.DebuggerProxy/DebuggerProxy.cs b/sdks/wasm/BrowserDebugProxy/DebuggerProxy.cs
index 74566c56024..74566c56024 100644
--- a/sdks/wasm/Mono.WebAssembly.DebuggerProxy/DebuggerProxy.cs
+++ b/sdks/wasm/BrowserDebugProxy/DebuggerProxy.cs
diff --git a/sdks/wasm/Mono.WebAssembly.DebuggerProxy/DevToolsHelper.cs b/sdks/wasm/BrowserDebugProxy/DevToolsHelper.cs
index a615540e450..a615540e450 100644
--- a/sdks/wasm/Mono.WebAssembly.DebuggerProxy/DevToolsHelper.cs
+++ b/sdks/wasm/BrowserDebugProxy/DevToolsHelper.cs
diff --git a/sdks/wasm/Mono.WebAssembly.DebuggerProxy/DevToolsProxy.cs b/sdks/wasm/BrowserDebugProxy/DevToolsProxy.cs
index 5eac86d124a..5eac86d124a 100644
--- a/sdks/wasm/Mono.WebAssembly.DebuggerProxy/DevToolsProxy.cs
+++ b/sdks/wasm/BrowserDebugProxy/DevToolsProxy.cs
diff --git a/sdks/wasm/Mono.WebAssembly.DebuggerProxy/EvaluateExpression.cs b/sdks/wasm/BrowserDebugProxy/EvaluateExpression.cs
index 7bcf6f81174..7bcf6f81174 100644
--- a/sdks/wasm/Mono.WebAssembly.DebuggerProxy/EvaluateExpression.cs
+++ b/sdks/wasm/BrowserDebugProxy/EvaluateExpression.cs
diff --git a/sdks/wasm/Mono.WebAssembly.DebuggerProxy/MonoProxy.cs b/sdks/wasm/BrowserDebugProxy/MonoProxy.cs
index 5169d1ccfff..5169d1ccfff 100644
--- a/sdks/wasm/Mono.WebAssembly.DebuggerProxy/MonoProxy.cs
+++ b/sdks/wasm/BrowserDebugProxy/MonoProxy.cs
diff --git a/sdks/wasm/DebuggerTestSuite/DebuggerTestSuite.csproj b/sdks/wasm/DebuggerTestSuite/DebuggerTestSuite.csproj
index c00fda67aaf..8cd99732b99 100644
--- a/sdks/wasm/DebuggerTestSuite/DebuggerTestSuite.csproj
+++ b/sdks/wasm/DebuggerTestSuite/DebuggerTestSuite.csproj
@@ -12,8 +12,8 @@
</ItemGroup>
<ItemGroup>
- <ProjectReference Include="..\ProxyDriver\ProxyDriver.csproj" />
- <ProjectReference Include="..\Mono.WebAssembly.DebuggerProxy\Mono.WebAssembly.DebuggerProxy.csproj" />
+ <ProjectReference Include="..\BrowserDebugHost\BrowserDebugHost.csproj" />
+ <ProjectReference Include="..\BrowserDebugProxy\BrowserDebugProxy.csproj" />
</ItemGroup>
</Project>
diff --git a/sdks/wasm/Makefile b/sdks/wasm/Makefile
index 29553fcd7b2..1e0faa2400f 100644
--- a/sdks/wasm/Makefile
+++ b/sdks/wasm/Makefile
@@ -674,7 +674,7 @@ build-debugger-test-app: bin/debugger-test-suite/dotnet.wasm
build-managed: build-debug-sample build-test-suite
build-dbg-proxy:
- $(DOTNET_BUILD) ProxyDriver
+ $(DOTNET_BUILD) BrowserDebugHost
build-dbg-testsuite:
$(DOTNET_BUILD) DebuggerTestSuite
@@ -791,10 +791,10 @@ package: build build-sdk build-dbg-proxy
cp $(OPTIONS_CS) tmp/
cp packager.exe tmp/
cp runtime.js tmp/
- cp Mono.WebAssembly.DebuggerProxy/bin/Debug/netstandard2.1/Mono.WebAssembly.DebuggerProxy.dll tmp/
- cp Mono.WebAssembly.DebuggerProxy/bin/Debug/netstandard2.1/Mono.WebAssembly.DebuggerProxy.pdb tmp/
+ cp BrowserDebugProxy/bin/Debug/netstandard2.1/BrowserDebugProxy.dll tmp/
+ cp BrowserDebugProxy/bin/Debug/netstandard2.1/BrowserDebugProxy.pdb tmp/
mkdir tmp/dbg-proxy
- cp -r ProxyDriver/bin/Debug/netcoreapp3.0/ tmp/dbg-proxy/
+ cp -r BrowserDebugHost/bin/Debug/netcoreapp3.0/ tmp/dbg-proxy/
mkdir tmp/docs
cp -r ./docs/ tmp/docs/
mkdir tmp/packages
diff --git a/sdks/wasm/README.md b/sdks/wasm/README.md
index ff1bb31805b..95a3d133124 100644
--- a/sdks/wasm/README.md
+++ b/sdks/wasm/README.md
@@ -197,7 +197,7 @@ To experiment with the debugger, do the following steps:
- When calling `packager.exe` pass the `-debug` argument to it.
- Start Chrome with remote debugging enabled (IE `/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222`)
-- Run the proxy: `dotnet run -p ProxyDriver/ProxyDriver.csproj`
+- Run the proxy: `dotnet run -p BrowserDebugHost/BrowserDebugHost.csproj`
- Connect to the proxy by visiting http://localhost:9300/ and select the tab you wish to debug from the list of tabs
- Refresh the debugged page and you should be set
diff --git a/sdks/wasm/package-update/download-packages.ps1 b/sdks/wasm/package-update/download-packages.ps1
index 2c12a12d082..1452bcd2f1b 100644
--- a/sdks/wasm/package-update/download-packages.ps1
+++ b/sdks/wasm/package-update/download-packages.ps1
@@ -40,7 +40,7 @@ $NUGET_HOME="~\\.nuget"
$PACKAGE_PATH="$NUGET_HOME\\packages\\microsoft.aspnetcore.components.webassembly.runtime\\$runtime\\tools\\dotnetwasm"
$PROXY_PACKAGE_PATH="$NUGET_HOME\\packages\\microsoft.aspnetcore.components.webassembly.devserver\\$runtime\\tools\\BlazorDebugProxy"
$ASP_PROXY_PATH="$asp_working_dir\\src\\Components\\WebAssembly\\DebugProxy\\src"
-$MONO_PROXY_PATH="$mono_working_dir\\sdks\\wasm\\Mono.WebAssembly.DebuggerProxy"
+$MONO_PROXY_PATH="$mono_working_dir\\sdks\\wasm\\BrowserDebugProxy"
$TMP_DIR=(mktemp -d)
$TMP_PKG_DIR="$TMP_DIR\\wasm-package"
mkdir $TMP_DIR
diff --git a/sdks/wasm/package-update/download-packages.sh b/sdks/wasm/package-update/download-packages.sh
index 22350c6913a..ad83c462f30 100644
--- a/sdks/wasm/package-update/download-packages.sh
+++ b/sdks/wasm/package-update/download-packages.sh
@@ -63,7 +63,7 @@ NUGET_HOME=${NUGET_HOME:-"$HOME/.nuget"}
PACKAGE_PATH="$NUGET_HOME/packages/microsoft.aspnetcore.components.webassembly.runtime/$RUNTIME_VER/tools/dotnetwasm"
PROXY_PACKAGE_PATH="$NUGET_HOME/packages/microsoft.aspnetcore.components.webassembly.devserver/$RUNTIME_VER/tools/BlazorDebugProxy"
ASP_PROXY_PATH="$ASPNETCORE/src/Components/WebAssembly/DebugProxy/src"
-MONO_PROXY_PATH="$MONO/sdks/wasm/Mono.WebAssembly.DebuggerProxy"
+MONO_PROXY_PATH="$MONO/sdks/wasm/BrowserDebugProxy"
TMP_DIR=`mktemp -d`
TMP_PKG_DIR=$TMP_DIR/wasm-package
mkdir $TMP_PKG_DIR
diff --git a/sdks/wasm/src/library_mono.js b/sdks/wasm/src/library_mono.js
index 8e8f9080be2..14e191e79cd 100644
--- a/sdks/wasm/src/library_mono.js
+++ b/sdks/wasm/src/library_mono.js
@@ -1,5 +1,15 @@
-/* jshint esversion: 6 */
-/* jshint evil: true */
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+/**
+ * @typedef WasmId
+ * @type {object}
+ * @property {string} idStr - full object id string
+ * @property {string} scheme - eg, object, valuetype, array ..
+ * @property {string} value - string part after `dotnet:scheme:` of the id string
+ * @property {object} o - value parsed as JSON
+ */
+
var MonoSupportLib = {
$MONO__postset: 'MONO.export_functions (Module);',
$MONO: {
@@ -8,6 +18,10 @@ var MonoSupportLib = {
_vt_stack: [],
mono_wasm_runtime_is_ready : false,
mono_wasm_ignore_pdb_load_errors: true,
+
+ /** @type {object.<string, object>} */
+ _id_table: {},
+
pump_message: function () {
if (!this.mono_background_exec)
this.mono_background_exec = Module.cwrap ("mono_background_exec", null);
@@ -24,6 +38,11 @@ var MonoSupportLib = {
export_functions: function (module) {
module ["pump_message"] = MONO.pump_message;
module ["mono_load_runtime_and_bcl"] = MONO.mono_load_runtime_and_bcl;
+ module ["mono_load_runtime_and_bcl_args"] = MONO.mono_load_runtime_and_bcl_args;
+ module ["mono_wasm_load_bytes_into_heap"] = MONO.mono_wasm_load_bytes_into_heap;
+ module ["mono_wasm_load_icu_data"] = MONO.mono_wasm_load_icu_data;
+ module ["mono_wasm_globalization_init"] = MONO.mono_wasm_globalization_init;
+ module ["mono_wasm_get_loaded_files"] = MONO.mono_wasm_get_loaded_files;
},
mono_text_decoder: undefined,
@@ -43,11 +62,11 @@ var MonoSupportLib = {
decode: function (start, end, save) {
if (!MONO.mono_text_decoder) {
MONO.mono_text_decoder = typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-16le') : undefined;
- }
+ }
var str = "";
if (MONO.mono_text_decoder) {
- // When threading is enabled, TextDecoder does not accept a view of a
+ // When threading is enabled, TextDecoder does not accept a view of a
// SharedArrayBuffer, we must make a copy of the array first.
var subArray = typeof SharedArrayBuffer !== 'undefined' && Module.HEAPU8.buffer instanceof SharedArrayBuffer
? Module.HEAPU8.slice(start, end)
@@ -67,6 +86,12 @@ var MonoSupportLib = {
},
},
+ mono_wasm_get_exception_object: function() {
+ var exception_obj = MONO.active_exception;
+ MONO.active_exception = null;
+ return exception_obj ;
+ },
+
mono_wasm_get_call_stack: function() {
if (!this.mono_wasm_current_bp_id)
this.mono_wasm_current_bp_id = Module.cwrap ("mono_wasm_current_bp_id", 'number');
@@ -86,30 +111,19 @@ var MonoSupportLib = {
},
_fixup_name_value_objects: function (var_list) {
- var out_list = [];
-
- var _fixup_value = function (value) {
- if (value != null && value != undefined) {
- var descr = value.description;
- if (descr == null || descr == undefined)
- value.description = '' + value.value;
- }
- return value;
- };
+ let out_list = [];
var i = 0;
while (i < var_list.length) {
- var o = var_list [i];
- var name = o.name;
+ let o = var_list [i];
+ const name = o.name;
if (name == null || name == undefined) {
i ++;
- o.value = _fixup_value(o.value);
out_list.push (o);
continue;
}
if (i + 1 < var_list.length) {
- _fixup_value(var_list[i + 1].value);
o = Object.assign (o, var_list [i + 1]);
}
@@ -121,8 +135,8 @@ var MonoSupportLib = {
},
_filter_automatic_properties: function (props) {
- var names_found = {};
- var final_var_list = [];
+ let names_found = {};
+ let final_var_list = [];
for (var i in props) {
var p = props [i];
@@ -141,48 +155,116 @@ var MonoSupportLib = {
return final_var_list;
},
- // code from https://stackoverflow.com/a/5582308
- //
- // Given `dotnet:object:foo:bar`,
- // returns [ 'dotnet', 'object', 'foo:bar']
- _split_object_id: function (id, delim = ':', count = 3) {
- if (id === undefined || id == "")
- return [];
+ /** Given `dotnet:object:foo:bar`,
+ * returns { scheme:'object', value: 'foo:bar' }
+ *
+ * Given `dotnet:pointer:{ b: 3 }`
+ * returns { scheme:'object', value: '{b:3}`, o: {b:3}
+ *
+ * @param {string} idStr
+ * @param {boolean} [throwOnError=false]
+ *
+ * @returns {WasmId}
+ */
+ _parse_object_id: function (idStr, throwOnError = false) {
+ if (idStr === undefined || idStr == "" || !idStr.startsWith ('dotnet:')) {
+ if (throwOnError)
+ throw new Error (`Invalid id: ${idStr}`);
+
+ return undefined;
+ }
+
+ const [, scheme, ...rest] = idStr.split(':');
+ let res = {
+ scheme,
+ value: rest.join (':'),
+ idStr,
+ o: {}
+ };
- if (delim === undefined) delim = ':';
- if (count === undefined) count = 3;
+ try {
+ res.o = JSON.parse(res.value);
+ // eslint-disable-next-line no-empty
+ } catch (e) {}
- var arr = id.split (delim);
- var result = arr.splice (0, count - 1);
+ return res;
+ },
- if (arr.length > 0)
- result.push (arr.join (delim));
- return result;
+ /**
+ * @param {WasmId} id
+ * @returns {object[]}
+ */
+ _get_vt_properties: function (id) {
+ let entry = this._id_table [id.idStr];
+ if (entry !== undefined && entry.members !== undefined)
+ return entry.members;
+
+ if (!isNaN (id.o.containerId))
+ this._get_object_properties (id.o.containerId, true);
+ else if (!isNaN (id.o.arrayId))
+ this._get_array_values (id, Number (id.o.arrayIdx), 1, true);
+ else
+ throw new Error (`Invalid valuetype id (${id.idStr}). Can't get properties for it.`);
+
+ entry = this._get_id_props (id.idStr);
+ if (entry !== undefined && entry.members !== undefined)
+ return entry.members;
+
+ throw new Error (`Unknown valuetype id: ${id.idStr}`);
+ },
+
+ /**
+ *
+ * @callback GetIdArgsCallback
+ * @param {object} var
+ * @param {number} idx
+ * @returns {object}
+ */
+
+ /**
+ * @param {object[]} vars
+ * @param {GetIdArgsCallback} getIdArgs
+ * @returns {object}
+ */
+ _assign_vt_ids: function (vars, getIdArgs)
+ {
+ vars.forEach ((v, i) => {
+ // we might not have a `.value`, like in case of getters which have a `.get` instead
+ const value = v.value;
+ if (value === undefined || !value.isValueType)
+ return;
+
+ if (value.objectId !== undefined)
+ throw new Error (`Bug: Trying to assign valuetype id, but the var already has one: ${v}`);
+
+ value.objectId = this._new_or_add_id_props ({ scheme: 'valuetype', idArgs: getIdArgs (v, i), props: value._props });
+ delete value._props;
+ });
+
+ return vars;
},
//
// @var_list: [ { index: <var_id>, name: <var_name> }, .. ]
mono_wasm_get_variables: function(scope, var_list) {
- if (!this.mono_wasm_get_var_info)
- this.mono_wasm_get_var_info = Module.cwrap ("mono_wasm_get_var_info", null, [ 'number', 'number', 'number']);
-
- this.var_info = [];
- var numBytes = var_list.length * Int32Array.BYTES_PER_ELEMENT;
- var ptr = Module._malloc(numBytes);
- var heapBytes = new Int32Array(Module.HEAP32.buffer, ptr, numBytes);
+ const numBytes = var_list.length * Int32Array.BYTES_PER_ELEMENT;
+ const ptr = Module._malloc(numBytes);
+ let heapBytes = new Int32Array(Module.HEAP32.buffer, ptr, numBytes);
for (let i=0; i<var_list.length; i++) {
heapBytes[i] = var_list[i].index;
}
this._async_method_objectId = 0;
- this.mono_wasm_get_var_info (scope, heapBytes.byteOffset, var_list.length);
+ let { res_ok, res } = this.mono_wasm_get_local_vars_info (scope, heapBytes.byteOffset, var_list.length);
Module._free(heapBytes.byteOffset);
- var res = MONO._fixup_name_value_objects (this.var_info);
+ if (!res_ok)
+ throw new Error (`Failed to get locals for scope ${scope}`);
- for (let i in res) {
- var res_name = res [i].name;
+ if (this._async_method_objectId != 0)
+ this._assign_vt_ids (res, v => ({ containerId: this._async_method_objectId, fieldOffset: v.fieldOffset }));
- var value = res[i].value;
+ for (let i in res) {
+ const res_name = res [i].name;
if (this._async_method_objectId != 0) {
//Async methods are special in the way that local variables can be lifted to generated class fields
//value of "this" comes here either
@@ -191,9 +273,6 @@ var MonoSupportLib = {
// ALTHOUGH, the name wouldn't have `<>` for method args
res [i].name = res_name.substring (1, res_name.indexOf ('>'));
}
-
- if (value.isValueType)
- value.objectId = `dotnet:valuetype:${this._async_method_objectId}:${res [i].fieldOffset}`;
} else if (res_name === undefined && var_list [i] !== undefined) {
// For non-async methods, we just have the var id, but we have the name
// from the caller
@@ -202,69 +281,49 @@ var MonoSupportLib = {
}
this._post_process_details(res);
- this.var_info = []
-
return res;
},
- mono_wasm_get_object_properties: function(objId, expandValueTypes) {
- if (!this.mono_wasm_get_object_properties_info)
- this.mono_wasm_get_object_properties_info = Module.cwrap ("mono_wasm_get_object_properties", null, [ 'number', 'bool' ]);
-
- this.var_info = [];
- this.mono_wasm_get_object_properties_info (objId, expandValueTypes);
-
- var res = MONO._filter_automatic_properties (MONO._fixup_name_value_objects (this.var_info));
- for (var i = 0; i < res.length; i++) {
- var res_val = res [i].value;
- // we might not have a `.value`, like in case of getters which have a `.get` instead
- if (res_val !== undefined && res_val.isValueType != undefined && res_val.isValueType)
- res_val.objectId = `dotnet:valuetype:${objId}:${res [i].fieldOffset}`;
- }
-
- this.var_info = [];
+ /**
+ * @param {number} idNum
+ * @param {boolean} expandValueTypes
+ * @returns {object}
+ */
+ _get_object_properties: function(idNum, expandValueTypes) {
+ let { res_ok, res } = this.mono_wasm_get_object_properties_info (idNum, expandValueTypes);
+ if (!res_ok)
+ throw new Error (`Failed to get properties for ${idNum}`);
+
+ res = MONO._filter_automatic_properties (res);
+ res = this._assign_vt_ids (res, v => ({ containerId: idNum, fieldOffset: v.fieldOffset }));
+ res = this._post_process_details (res);
return res;
},
- mono_wasm_get_array_values: function(objId) {
- if (!this.mono_wasm_get_array_values_info)
- this.mono_wasm_get_array_values_info = Module.cwrap ("mono_wasm_get_array_values", null, [ 'number' ]);
-
- this.var_info = [];
- this.mono_wasm_get_array_values_info (objId);
-
- var res = MONO._fixup_name_value_objects (this.var_info);
- for (var i = 0; i < res.length; i++) {
- var prop_value = res [i].value;
- if (prop_value.isValueType) {
- res [i].value.objectId = `dotnet:array:${objId}:${i}`;
- } else if (prop_value.objectId !== undefined && prop_value.objectId.startsWith("dotnet:pointer")) {
- prop_value.objectId = this._get_updated_ptr_id (prop_value.objectId, {
- varName: `[${i}]`
- });
- }
+ /**
+ * @param {WasmId} id
+ * @param {number} [startIdx=0]
+ * @param {number} [count=-1]
+ * @param {boolean} [expandValueTypes=false]
+ * @returns {object[]}
+ */
+ _get_array_values: function (id, startIdx = 0, count = -1, expandValueTypes = false) {
+ if (isNaN (id.o.arrayId) || isNaN (startIdx))
+ throw new Error (`Invalid array id: ${id.idStr}`);
+
+ let { res_ok, res } = this.mono_wasm_get_array_values_info (id.o.arrayId, startIdx, count, expandValueTypes);
+ if (!res_ok)
+ throw new Error (`Failed to get properties for array id ${id.idStr}`);
+
+ res = this._assign_vt_ids (res, (_, i) => ({ arrayId: id.o.arrayId, arrayIdx: Number (startIdx) + i}));
+
+ for (let i = 0; i < res.length; i ++) {
+ let value = res [i].value;
+ if (value.objectId !== undefined && value.objectId.startsWith("dotnet:pointer"))
+ this._new_or_add_id_props ({ objectId: value.objectId, props: { varName: `[${i}]` } });
}
-
- this.var_info = [];
-
- return res;
- },
-
- mono_wasm_get_array_value_expanded: function(objId, idx) {
- if (!this.mono_wasm_get_array_value_expanded_info)
- this.mono_wasm_get_array_value_expanded_info = Module.cwrap ("mono_wasm_get_array_value_expanded", null, [ 'number', 'number' ]);
-
- this.var_info = [];
- this.mono_wasm_get_array_value_expanded_info (objId, idx);
-
- var res = MONO._fixup_name_value_objects (this.var_info);
- // length should be exactly one!
- if (res [0].value.isValueType != undefined && res [0].value.isValueType)
- res [0].value.objectId = `dotnet:array:${objId}:${idx}`;
-
- this.var_info = [];
-
+ res = this._post_process_details (res);
return res;
},
@@ -278,8 +337,13 @@ var MonoSupportLib = {
return details;
},
- _next_value_type_id: function () {
- return ++this._next_value_type_id_var;
+ /**
+ * Gets the next id number to use for generating ids
+ *
+ * @returns {number}
+ */
+ _next_id: function () {
+ return ++this._next_id_var;
},
_extract_and_cache_value_types: function (var_list) {
@@ -287,82 +351,46 @@ var MonoSupportLib = {
return var_list;
for (let i in var_list) {
- var value = var_list [i].value;
+ let value = var_list [i].value;
if (value === undefined)
continue;
if (value.objectId !== undefined && value.objectId.startsWith ("dotnet:pointer:")) {
- var ptr_args = this._get_ptr_args (value.objectId);
- if (ptr_args.varName === undefined) {
- // It might have been already set in some cases, like arrays
- // where the name would be `0`, but we want `[0]` for pointers,
- // so the deref would look like `*[0]`
- value.objectId = this._get_updated_ptr_id (value.objectId, {
- varName: var_list [i].name
- });
- }
+ let ptr_args = this._get_id_props (value.objectId);
+ if (ptr_args === undefined)
+ throw new Error (`Bug: Expected to find an entry for pointer id: ${value.objectId}`);
+
+ // It might have been already set in some cases, like arrays
+ // where the name would be `0`, but we want `[0]` for pointers,
+ // so the deref would look like `*[0]`
+ ptr_args.varName = ptr_args.varName || var_list [i].name;
}
if (value.type != "object" || value.isValueType != true || value.expanded != true) // undefined would also give us false
continue;
// Generate objectId for expanded valuetypes
-
- var objectId = value.objectId;
- if (objectId == undefined)
- objectId = `dotnet:valuetype:${this._next_value_type_id ()}`;
- value.objectId = objectId;
+ value.objectId = value.objectId || this._new_or_add_id_props ({ scheme: 'valuetype' });
this._extract_and_cache_value_types (value.members);
- this._value_types_cache [objectId] = value.members;
+ const new_props = Object.assign ({ members: value.members }, value.__extra_vt_props);
+
+ this._new_or_add_id_props ({ objectId: value.objectId, props: new_props });
delete value.members;
+ delete value.__extra_vt_props;
}
return var_list;
},
- _get_details_for_value_type: function (objectId, fetchDetailsFn) {
- if (objectId in this._value_types_cache)
- return this._value_types_cache[objectId];
-
- this._post_process_details (fetchDetailsFn());
- if (objectId in this._value_types_cache)
- return this._value_types_cache[objectId];
-
- // return error
- throw new Error (`Could not get details for ${objectId}`);
- },
-
- _is_object_id_array: function (objectId) {
- // Keep this in sync with `_get_array_details`
- return (objectId.startsWith ('dotnet:array:') && objectId.split (':').length == 3);
- },
-
- _get_array_details: function (objectId, objectIdParts) {
- // Keep this in sync with `_is_object_id_array`
- switch (objectIdParts.length) {
- case 3:
- return this._post_process_details (this.mono_wasm_get_array_values(objectIdParts[2]));
-
- case 4:
- var arrayObjectId = objectIdParts[2];
- var arrayIdx = objectIdParts[3];
- return this._get_details_for_value_type(
- objectId, () => this.mono_wasm_get_array_value_expanded(arrayObjectId, arrayIdx));
-
- default:
- throw new Error (`object id format not supported : ${objectId}`);
- }
- },
-
_get_cfo_res_details: function (objectId, args) {
if (!(objectId in this._call_function_res_cache))
throw new Error(`Could not find any object with id ${objectId}`);
- var real_obj = this._call_function_res_cache [objectId];
+ const real_obj = this._call_function_res_cache [objectId];
- var descriptors = Object.getOwnPropertyDescriptors (real_obj);
+ const descriptors = Object.getOwnPropertyDescriptors (real_obj);
if (args.accessorPropertiesOnly) {
Object.keys (descriptors).forEach (k => {
if (descriptors [k].get === undefined)
@@ -370,10 +398,10 @@ var MonoSupportLib = {
});
}
- var res_details = [];
+ let res_details = [];
Object.keys (descriptors).forEach (k => {
- var new_obj;
- var prop_desc = descriptors [k];
+ let new_obj;
+ let prop_desc = descriptors [k];
if (typeof prop_desc.value == "object") {
// convert `{value: { type='object', ... }}`
// to `{ name: 'foo', value: { type='object', ... }}
@@ -414,34 +442,77 @@ var MonoSupportLib = {
return { __value_as_json_string__: JSON.stringify (res_details) };
},
- _get_ptr_args: function (objectId) {
- var parts = this._split_object_id (objectId);
- if (parts.length != 3)
- throw new Error (`Bug: Unexpected objectId format for a pointer, expected 3 parts: ${objectId}`);
- return JSON.parse (parts [2]);
- },
+ /**
+ * Generates a new id, and a corresponding entry for associated properties
+ * like `dotnet:pointer:{ a: 4 }`
+ * The third segment of that `{a:4}` is the idArgs parameter
+ *
+ * Only `scheme` or `objectId` can be set.
+ * if `scheme`, then a new id is generated, and it's properties set
+ * if `objectId`, then it's properties are updated
+ *
+ * @param {object} args
+ * @param {string} [args.scheme=undefined] scheme second part of `dotnet:pointer:..`
+ * @param {string} [args.objectId=undefined] objectId
+ * @param {object} [args.idArgs={}] The third segment of the objectId
+ * @param {object} [args.props={}] Properties for the generated id
+ *
+ * @returns {string} generated/updated id string
+ */
+ _new_or_add_id_props: function ({ scheme = undefined, objectId = undefined, idArgs = {}, props = {} }) {
+ if (scheme === undefined && objectId === undefined)
+ throw new Error (`Either scheme or objectId must be given`);
+
+ if (scheme !== undefined && objectId !== undefined)
+ throw new Error (`Both scheme, and objectId cannot be given`);
+
+ if (objectId !== undefined && Object.entries (idArgs).length > 0)
+ throw new Error (`Both objectId, and idArgs cannot be given`);
+
+ if (Object.entries (idArgs).length == 0) {
+ // We want to generate a new id, only if it doesn't have other
+ // attributes that it can use to uniquely identify.
+ // Eg, we don't do this for `dotnet:valuetype:{containerId:4, fieldOffset: 24}`
+ idArgs.num = this._next_id ();
+ }
+
+ let idStr;
+ if (objectId !== undefined) {
+ idStr = objectId;
+ const old_props = this._id_table [idStr];
+ if (old_props === undefined)
+ throw new Error (`ObjectId not found in the id table: ${idStr}`);
+
+ this._id_table [idStr] = Object.assign (old_props, props);
+ } else {
+ idStr = `dotnet:${scheme}:${JSON.stringify (idArgs)}`;
+ this._id_table [idStr] = props;
+ }
- _get_updated_ptr_id: function (objectId, new_args) {
- var old_args = {};
- if (typeof (objectId) === 'string' && objectId.length)
- old_args = this._get_ptr_args (objectId);
+ return idStr;
+ },
- return `dotnet:pointer:${JSON.stringify ( Object.assign (old_args, new_args) )}`;
+ /**
+ * @param {string} objectId
+ * @returns {object}
+ */
+ _get_id_props: function (objectId) {
+ return this._id_table [objectId];
},
_get_deref_ptr_value: function (objectId) {
- if (!this.mono_wasm_get_deref_ptr_value_info)
- this.mono_wasm_get_deref_ptr_value_info = Module.cwrap("mono_wasm_get_deref_ptr_value", null, ['number', 'number']);
+ const ptr_args = this._get_id_props (objectId);
+ if (ptr_args === undefined)
+ throw new Error (`Unknown pointer id: ${objectId}`);
- var ptr_args = this._get_ptr_args (objectId);
if (ptr_args.ptr_addr == 0 || ptr_args.klass_addr == 0)
throw new Error (`Both ptr_addr and klass_addr need to be non-zero, to dereference a pointer. objectId: ${objectId}`);
- this.var_info = [];
- var value_addr = new DataView (Module.HEAPU8.buffer).getUint32 (ptr_args.ptr_addr, /* littleEndian */ true);
- this.mono_wasm_get_deref_ptr_value_info (value_addr, ptr_args.klass_addr);
+ const value_addr = new DataView (Module.HEAPU8.buffer).getUint32 (ptr_args.ptr_addr, /* littleEndian */ true);
+ let { res_ok, res } = this.mono_wasm_get_deref_ptr_value_info (value_addr, ptr_args.klass_addr);
+ if (!res_ok)
+ throw new Error (`Failed to dereference pointer ${objectId}`);
- var res = MONO._fixup_name_value_objects(this.var_info);
if (res.length > 0) {
if (ptr_args.varName === undefined)
throw new Error (`Bug: no varName found for the pointer. objectId: ${objectId}`);
@@ -450,34 +521,25 @@ var MonoSupportLib = {
}
res = this._post_process_details (res);
- this.var_info = [];
return res;
},
mono_wasm_get_details: function (objectId, args) {
- var parts = objectId.split(":");
- if (parts[0] != "dotnet")
- throw new Error ("Can't handle non-dotnet object ids. ObjectId: " + objectId);
+ let id = this._parse_object_id (objectId, true);
- switch (parts[1]) {
- case "object":
- if (parts.length != 3)
- throw new Error(`exception this time: Invalid object id format: ${objectId}`);
+ switch (id.scheme) {
+ case "object": {
+ if (isNaN (id.value))
+ throw new Error (`Invalid objectId: ${objectId}. Expected a numeric id.`);
- return this._post_process_details(this.mono_wasm_get_object_properties(parts[2], false));
+ return this._get_object_properties(id.value, false);
+ }
case "array":
- return this._get_array_details(objectId, parts);
+ return this._get_array_values (id);
case "valuetype":
- if (parts.length != 3 && parts.length != 4) {
- // dotnet:valuetype:vtid
- // dotnet:valuetype:containerObjectId:vtId
- throw new Error(`Invalid object id format: ${objectId}`);
- }
-
- var containerObjectId = parts[2];
- return this._get_details_for_value_type(objectId, () => this.mono_wasm_get_object_properties(containerObjectId, true));
+ return this._get_vt_properties(id);
case "cfo_res":
return this._get_cfo_res_details (objectId, args);
@@ -492,7 +554,7 @@ var MonoSupportLib = {
},
_cache_call_function_res: function (obj) {
- var id = `dotnet:cfo_res:${this._next_call_function_res_id++}`;
+ const id = `dotnet:cfo_res:${this._next_call_function_res_id++}`;
this._call_function_res_cache[id] = obj;
return id;
},
@@ -502,44 +564,69 @@ var MonoSupportLib = {
delete this._cache_call_function_res[objectId];
},
- _invoke_getter_on_object: function (objectId, name) {
- if (!this.mono_wasm_invoke_getter_on_object)
- this.mono_wasm_invoke_getter_on_object = Module.cwrap ("mono_wasm_invoke_getter_on_object", 'void', [ 'number', 'string' ]);
-
- if (objectId < 0) {
- // invalid id
- return [];
+ /**
+ * @param {string} objectIdStr objectId
+ * @param {string} name property name
+ * @returns {object} return value
+ */
+ _invoke_getter: function (objectIdStr, name) {
+ const id = this._parse_object_id (objectIdStr);
+ if (id === undefined)
+ throw new Error (`Invalid object id: ${objectIdStr}`);
+
+ let getter_res;
+ if (id.scheme == 'object') {
+ if (isNaN (id.o) || id.o < 0)
+ throw new Error (`Invalid object id: ${objectIdStr}`);
+
+ let { res_ok, res } = this.mono_wasm_invoke_getter_on_object_info (id.o, name);
+ if (!res_ok)
+ throw new Error (`Invoking getter on ${objectIdStr} failed`);
+
+ getter_res = res;
+ } else if (id.scheme == 'valuetype') {
+ const id_props = this._get_id_props (objectIdStr);
+ if (id_props === undefined)
+ throw new Error (`Unknown valuetype id: ${objectIdStr}`);
+
+ if (typeof id_props.value64 !== 'string' || isNaN (id_props.klass))
+ throw new Error (`Bug: Cannot invoke getter on ${objectIdStr}, because of missing or invalid klass/value64 fields. idProps: ${JSON.stringify (id_props)}`);
+
+ const dataPtr = Module._malloc (id_props.value64.length);
+ const dataHeap = new Uint8Array (Module.HEAPU8.buffer, dataPtr, id_props.value64.length);
+ dataHeap.set (new Uint8Array (this._base64_to_uint8 (id_props.value64)));
+
+ let { res_ok, res } = this.mono_wasm_invoke_getter_on_value_info (dataHeap.byteOffset, id_props.klass, name);
+ Module._free (dataHeap.byteOffset);
+
+ if (!res_ok) {
+ console.debug (`Invoking getter on valuetype ${objectIdStr}, with props: ${JSON.stringify (id_props)} failed`);
+ throw new Error (`Invoking getter on valuetype ${objectIdStr} failed`);
+ }
+ getter_res = res;
+ } else {
+ throw new Error (`Only object, and valuetypes supported for getters, id: ${objectIdStr}`);
}
- this.mono_wasm_invoke_getter_on_object (objectId, name);
- var getter_res = MONO._post_process_details (MONO.var_info);
-
- MONO.var_info = [];
- return getter_res [0];
+ getter_res = MONO._post_process_details (getter_res);
+ return getter_res.length > 0 ? getter_res [0] : {};
},
_create_proxy_from_object_id: function (objectId) {
- var details = this.mono_wasm_get_details(objectId);
+ const details = this.mono_wasm_get_details(objectId);
- if (this._is_object_id_array (objectId))
+ if (objectId.startsWith ('dotnet:array:'))
return details.map (p => p.value);
- var objIdParts = objectId.split (':');
- var objIdNum = -1;
- if (objectId.startsWith ("dotnet:object:"))
- objIdNum = objIdParts [2];
-
- var proxy = {};
+ let proxy = {};
Object.keys (details).forEach (p => {
var prop = details [p];
if (prop.get !== undefined) {
// TODO: `set`
- // We don't add a `get` for non-object types right now,
- // so, we shouldn't get here with objIdNum==-1
Object.defineProperty (proxy,
prop.name,
- { get () { return MONO._invoke_getter_on_object (objIdNum, prop.name); } }
+ { get () { return MONO._invoke_getter (objectId, prop.name); } }
);
} else {
proxy [prop.name] = prop.value;
@@ -553,21 +640,27 @@ var MonoSupportLib = {
if (request.arguments != undefined && !Array.isArray (request.arguments))
throw new Error (`"arguments" should be an array, but was ${request.arguments}`);
- var objId = request.objectId;
- var proxy;
+ const objId = request.objectId;
+ let proxy;
- if (objId in this._call_function_res_cache) {
- proxy = this._call_function_res_cache [objId];
- } else if (!objId.startsWith ('dotnet:cfo_res:')) {
+ if (objId.startsWith ('dotnet:cfo_res:')) {
+ if (objId in this._call_function_res_cache)
+ proxy = this._call_function_res_cache [objId];
+ else
+ throw new Error (`Unknown object id ${objId}`);
+ } else {
proxy = this._create_proxy_from_object_id (objId);
}
- var fn_args = request.arguments != undefined ? request.arguments.map(a => JSON.stringify(a.value)) : [];
- var fn_eval_str = `var fn = ${request.functionDeclaration}; fn.call (proxy, ...[${fn_args}]);`;
+ const fn_args = request.arguments != undefined ? request.arguments.map(a => JSON.stringify(a.value)) : [];
+ const fn_eval_str = `var fn = ${request.functionDeclaration}; fn.call (proxy, ...[${fn_args}]);`;
+
+ const fn_res = eval (fn_eval_str);
+ if (fn_res === undefined)
+ return { type: "undefined" };
- var fn_res = eval (fn_eval_str);
- if (fn_res == undefined) // should we just return undefined?
- throw Error ('Function returned undefined result');
+ if (fn_res === null || (fn_res.subtype === 'null' && fn_res.value === undefined))
+ return fn_res;
// primitive type
if (Object (fn_res) !== fn_res)
@@ -580,7 +673,7 @@ var MonoSupportLib = {
if (request.returnByValue)
return {type: "object", value: fn_res};
- var fn_res_id = this._cache_call_function_res (fn_res);
+ const fn_res_id = this._cache_call_function_res (fn_res);
if (Object.getPrototypeOf (fn_res) == Array.prototype) {
return {
type: "object",
@@ -595,8 +688,8 @@ var MonoSupportLib = {
},
_clear_per_step_state: function () {
- this._next_value_type_id_var = 0;
- this._value_types_cache = {};
+ this._next_id_var = 0;
+ this._id_table = {};
},
mono_wasm_debugger_resume: function () {
@@ -613,16 +706,75 @@ var MonoSupportLib = {
return this.mono_wasm_setup_single_step (kind);
},
+ mono_wasm_set_pause_on_exceptions: function (state) {
+ if (!this.mono_wasm_pause_on_exceptions)
+ this.mono_wasm_pause_on_exceptions = Module.cwrap ("mono_wasm_pause_on_exceptions", 'number', [ 'number']);
+ var state_enum = 0;
+ switch (state) {
+ case 'uncaught':
+ state_enum = 1; //EXCEPTION_MODE_UNCAUGHT
+ break;
+ case 'all':
+ state_enum = 2; //EXCEPTION_MODE_ALL
+ break;
+ }
+ return this.mono_wasm_pause_on_exceptions (state_enum);
+ },
+
+ _register_c_fn: function (name, ...args) {
+ Object.defineProperty (this._c_fn_table, name + '_wrapper', { value: Module.cwrap (name, ...args) });
+ },
+
+ /**
+ * Calls `Module.cwrap` for the function name,
+ * and creates a wrapper around it that returns
+ * `{ bool result, object var_info }
+ *
+ * @param {string} name C function name
+ * @param {string} ret_type
+ * @param {string[]} params
+ *
+ * @returns {void}
+ */
+ _register_c_var_fn: function (name, ret_type, params) {
+ if (ret_type !== 'bool')
+ throw new Error (`Bug: Expected a C function signature that returns bool`);
+
+ this._register_c_fn (name, ret_type, params);
+ Object.defineProperty (this, name + '_info', {
+ value: function (...args) {
+ MONO.var_info = [];
+ const res_ok = MONO._c_fn_table [name + '_wrapper'] (...args);
+ let res = MONO.var_info;
+ MONO.var_info = [];
+ if (res_ok) {
+ res = this._fixup_name_value_objects (res);
+ return { res_ok, res };
+ }
+
+ return { res_ok, res: undefined };
+ }
+ });
+ },
+
mono_wasm_runtime_ready: function () {
this.mono_wasm_runtime_is_ready = true;
// DO NOT REMOVE - magic debugger init function
- console.debug ("mono_wasm_runtime_ready", "fe00e07a-5519-4dfe-b35a-f867dbaf2e28", JSON.stringify (this.loaded_files));
+ console.debug ("mono_wasm_runtime_ready", "fe00e07a-5519-4dfe-b35a-f867dbaf2e28");
this._clear_per_step_state ();
// FIXME: where should this go?
this._next_call_function_res_id = 0;
this._call_function_res_cache = {};
+
+ this._c_fn_table = {};
+ this._register_c_var_fn ('mono_wasm_get_object_properties', 'bool', [ 'number', 'bool' ]);
+ this._register_c_var_fn ('mono_wasm_get_array_values', 'bool', [ 'number', 'number', 'number', 'bool' ]);
+ this._register_c_var_fn ('mono_wasm_invoke_getter_on_object', 'bool', [ 'number', 'string' ]);
+ this._register_c_var_fn ('mono_wasm_invoke_getter_on_value', 'bool', [ 'number', 'number', 'string' ]);
+ this._register_c_var_fn ('mono_wasm_get_local_vars', 'bool', [ 'number', 'number', 'number']);
+ this._register_c_var_fn ('mono_wasm_get_deref_ptr_value', 'bool', [ 'number', 'number']);
},
mono_wasm_set_breakpoint: function (assembly, method_token, il_offset) {
@@ -640,7 +792,7 @@ var MonoSupportLib = {
},
// Set environment variable NAME to VALUE
- // Should be called before mono_load_runtime_and_bcl () in most cases
+ // Should be called before mono_load_runtime_and_bcl () in most cases
mono_wasm_setenv: function (name, value) {
if (!this.wasm_setenv)
this.wasm_setenv = Module.cwrap ('mono_wasm_setenv', null, ['string', 'string']);
@@ -652,7 +804,7 @@ var MonoSupportLib = {
this.wasm_parse_runtime_options = Module.cwrap ('mono_wasm_parse_runtime_options', null, ['number', 'number']);
var argv = Module._malloc (options.length * 4);
var wasm_strdup = Module.cwrap ('mono_wasm_strdup', 'number', ['string']);
- aindex = 0;
+ let aindex = 0;
for (var i = 0; i < options.length; ++i) {
Module.setValue (argv + (aindex * 4), wasm_strdup (options [i]), "i32");
aindex += 1;
@@ -696,117 +848,440 @@ var MonoSupportLib = {
Module.ccall ('mono_wasm_load_profiler_coverage', null, ['string'], [arg]);
},
- mono_load_runtime_and_bcl: function (vfs_prefix, deploy_prefix, enable_debugging, file_list, loaded_cb, fetch_file_cb) {
- var pending = file_list.length;
- var loaded_files = [];
- var loaded_files_with_debug_info = [];
- var mono_wasm_add_assembly = Module.cwrap ('mono_wasm_add_assembly', 'number', ['string', 'number', 'number']);
-
- if (!fetch_file_cb) {
- if (ENVIRONMENT_IS_NODE) {
- var fs = require('fs');
- fetch_file_cb = function (asset) {
- console.log("MONO_WASM: Loading... " + asset);
- var binary = fs.readFileSync (asset);
- var resolve_func2 = function(resolve, reject) {
- resolve(new Uint8Array (binary));
- };
+ _apply_configuration_from_args: function (args) {
+ for (var k in (args.environment_variables || {}))
+ MONO.mono_wasm_setenv (k, args.environment_variables[k]);
- var resolve_func1 = function(resolve, reject) {
- var response = {
- ok: true,
- url: asset,
- arrayBuffer: function() {
- return new Promise(resolve_func2);
- }
- };
- resolve(response);
- };
+ if (args.runtime_options)
+ MONO.mono_wasm_set_runtime_options (args.runtime_options);
- return new Promise(resolve_func1);
+ if (args.aot_profiler_options)
+ MONO.mono_wasm_init_aot_profiler (args.aot_profiler_options);
+
+ if (args.coverage_profiler_options)
+ MONO.mono_wasm_init_coverage_profiler (args.coverage_profiler_options);
+ },
+
+ _get_fetch_file_cb_from_args: function (args) {
+ if (typeof (args.fetch_file_cb) === "function")
+ return args.fetch_file_cb;
+
+ if (ENVIRONMENT_IS_NODE) {
+ var fs = require('fs');
+ return function (asset) {
+ console.log ("MONO_WASM: Loading... " + asset);
+ var binary = fs.readFileSync (asset);
+ var resolve_func2 = function (resolve, reject) {
+ resolve (new Uint8Array (binary));
};
- } else {
- fetch_file_cb = function (asset) {
- return fetch (asset, { credentials: 'same-origin' });
+
+ var resolve_func1 = function (resolve, reject) {
+ var response = {
+ ok: true,
+ url: asset,
+ arrayBuffer: function () {
+ return new Promise (resolve_func2);
+ }
+ };
+ resolve (response);
+ };
+
+ return new Promise (resolve_func1);
+ };
+ } else if (typeof (fetch) === "function") {
+ return function (asset) {
+ return fetch (asset, { credentials: 'same-origin' });
+ };
+ } else {
+ throw new Error ("No fetch_file_cb was provided and this environment does not expose 'fetch'.");
+ }
+ },
+
+ _handle_loaded_asset: function (ctx, asset, url, blob) {
+ var bytes = new Uint8Array (blob);
+ if (ctx.tracing)
+ console.log ("MONO_WASM: Loaded:", asset.name, "size", bytes.length, "from", url);
+ else
+ console.log ("MONO_WASM: Loaded:", asset.name);
+
+ var virtualName = asset.virtual_path || asset.name;
+ var offset = null;
+
+ switch (asset.behavior) {
+ case "assembly":
+ ctx.loaded_files.push ({ url: url, file: virtualName});
+ case "heap":
+ case "icu":
+ offset = this.mono_wasm_load_bytes_into_heap (bytes);
+ ctx.loaded_assets[virtualName] = [offset, bytes.length];
+ break;
+
+ case "vfs":
+ // FIXME
+ var lastSlash = virtualName.lastIndexOf("/");
+ var parentDirectory = (lastSlash > 0)
+ ? virtualName.substr(0, lastSlash)
+ : null;
+ var fileName = (lastSlash > 0)
+ ? virtualName.substr(lastSlash + 1)
+ : virtualName;
+ if (fileName.startsWith("/"))
+ fileName = fileName.substr(1);
+ if (parentDirectory) {
+ if (ctx.tracing)
+ console.log ("MONO_WASM: Creating directory '" + parentDirectory + "'");
+
+ var pathRet = ctx.createPath(
+ "/", parentDirectory, true, true // fixme: should canWrite be false?
+ );
+ } else {
+ parentDirectory = "/";
+ }
+
+ if (ctx.tracing)
+ console.log ("MONO_WASM: Creating file '" + fileName + "' in directory '" + parentDirectory + "'");
+
+ if (!this.mono_wasm_load_data_archive (bytes, parentDirectory)) {
+ var fileRet = ctx.createDataFile (
+ parentDirectory, fileName,
+ bytes, true /* canRead */, true /* canWrite */, true /* canOwn */
+ );
}
+ break;
+
+ default:
+ throw new Error ("Unrecognized asset behavior:", asset.behavior, "for asset", asset.name);
+ }
+
+ if (asset.behavior === "assembly") {
+ var hasPpdb = ctx.mono_wasm_add_assembly (virtualName, offset, bytes.length);
+
+ if (!hasPpdb) {
+ var index = ctx.loaded_files.findIndex(element => element.file == virtualName);
+ ctx.loaded_files.splice(index, 1);
}
}
+ else if (asset.behavior === "icu") {
+ if (this.mono_wasm_load_icu_data (offset))
+ ctx.num_icu_assets_loaded_successfully += 1;
+ else
+ console.error ("Error loading ICU asset", asset.name);
+ }
+ },
+
+ // deprecated
+ mono_load_runtime_and_bcl: function (
+ unused_vfs_prefix, deploy_prefix, debug_level, file_list, loaded_cb, fetch_file_cb
+ ) {
+ var args = {
+ fetch_file_cb: fetch_file_cb,
+ loaded_cb: loaded_cb,
+ debug_level: debug_level,
+ assembly_root: deploy_prefix,
+ assets: []
+ };
+
+ for (var i = 0; i < file_list.length; i++) {
+ var file_name = file_list[i];
+ var behavior;
+ if (file_name === "icudt.dat")
+ behavior = "icu";
+ else // if (file_name.endsWith (".pdb") || file_name.endsWith (".dll"))
+ behavior = "assembly";
+
+ args.assets.push ({
+ name: file_name,
+ behavior: behavior
+ });
+ }
+
+ return this.mono_load_runtime_and_bcl_args (args);
+ },
+
+ // Initializes the runtime and loads assemblies, debug information, and other files.
+ // @args is a dictionary-style Object with the following properties:
+ // assembly_root: (required) the subfolder containing managed assemblies and pdbs
+ // debug_level or enable_debugging: (required)
+ // assets: (required) a list of assets to load along with the runtime. each asset
+ // is a dictionary-style Object with the following properties:
+ // name: (required) the name of the asset, including extension.
+ // behavior: (required) determines how the asset will be handled once loaded:
+ // "heap": store asset into the native heap
+ // "assembly": load asset as a managed assembly (or debugging information)
+ // "icu": load asset as an ICU data archive
+ // "vfs": load asset into the virtual filesystem (for fopen, File.Open, etc)
+ // load_remote: (optional) if true, an attempt will be made to load the asset
+ // from each location in @args.remote_sources.
+ // virtual_path: (optional) if specified, overrides the path of the asset in
+ // the virtual filesystem and similar data structures once loaded.
+ // is_optional: (optional) if true, any failure to load this asset will be ignored.
+ // loaded_cb: (required) a function () invoked when loading has completed.
+ // fetch_file_cb: (optional) a function (string) invoked to fetch a given file.
+ // If no callback is provided a default implementation appropriate for the current
+ // environment will be selected (readFileSync in node, fetch elsewhere).
+ // If no default implementation is available this call will fail.
+ // remote_sources: (optional) additional search locations for assets.
+ // sources will be checked in sequential order until the asset is found.
+ // the string "./" indicates to load from the application directory (as with the
+ // files in assembly_list), and a fully-qualified URL like "https://example.com/" indicates
+ // that asset loads can be attempted from a remote server. Sources must end with a "/".
+ // environment_variables: (optional) dictionary-style Object containing environment variables
+ // runtime_options: (optional) array of runtime options as strings
+ // aot_profiler_options: (optional) dictionary-style Object. see the comments for
+ // mono_wasm_init_aot_profiler. If omitted, aot profiler will not be initialized.
+ // coverage_profiler_options: (optional) dictionary-style Object. see the comments for
+ // mono_wasm_init_coverage_profiler. If omitted, coverage profiler will not be initialized.
+ // globalization_mode: (optional) configures the runtime's globalization mode:
+ // "icu": load ICU globalization data from any runtime assets with behavior "icu".
+ // "invariant": operate in invariant globalization mode.
+ // "auto" (default): if "icu" behavior assets are present, use ICU, otherwise invariant.
+ // diagnostic_tracing: (optional) enables diagnostic log messages during startup
+ mono_load_runtime_and_bcl_args: function (args) {
+ try {
+ return this._load_assets_and_runtime (args);
+ } catch (exc) {
+ console.error ("error in mono_load_runtime_and_bcl_args:", exc);
+ throw exc;
+ }
+ },
- file_list.forEach (function(file_name) {
-
- var fetch_promise = fetch_file_cb (locateFile(deploy_prefix + "/" + file_name));
+ // @bytes must be a typed array. space is allocated for it in the native heap
+ // and it is copied to that location. returns the address of the allocation.
+ mono_wasm_load_bytes_into_heap: function (bytes) {
+ var memoryOffset = Module._malloc (bytes.length);
+ var heapBytes = new Uint8Array (Module.HEAPU8.buffer, memoryOffset, bytes.length);
+ heapBytes.set (bytes);
+ return memoryOffset;
+ },
- fetch_promise.then (function (response) {
+ num_icu_assets_loaded_successfully: 0,
+
+ // @offset must be the address of an ICU data archive in the native heap.
+ // returns true on success.
+ mono_wasm_load_icu_data: function (offset) {
+ var fn = Module.cwrap ('mono_wasm_load_icu_data', 'number', ['number']);
+ var ok = (fn (offset)) === 1;
+ if (ok)
+ this.num_icu_assets_loaded_successfully++;
+ return ok;
+ },
+
+ _finalize_startup: function (args, ctx) {
+ var loaded_files_with_debug_info = [];
+
+ MONO.loaded_assets = ctx.loaded_assets;
+ ctx.loaded_files.forEach(value => loaded_files_with_debug_info.push(value.url));
+ MONO.loaded_files = loaded_files_with_debug_info;
+ if (ctx.tracing) {
+ console.log ("MONO_WASM: loaded_assets: " + JSON.stringify(ctx.loaded_assets));
+ console.log ("MONO_WASM: loaded_files: " + JSON.stringify(ctx.loaded_files));
+ }
+
+ var load_runtime = Module.cwrap ('mono_wasm_load_runtime', null, ['string', 'number']);
+
+ console.log ("MONO_WASM: Initializing mono runtime");
+
+ this.mono_wasm_globalization_init (args.globalization_mode);
+
+ if (ENVIRONMENT_IS_SHELL || ENVIRONMENT_IS_NODE) {
+ try {
+ load_runtime ("unused", args.debug_level);
+ } catch (ex) {
+ print ("MONO_WASM: load_runtime () failed: " + ex);
+ print ("MONO_WASM: Stacktrace: \n");
+ print (ex.stack);
+
+ var wasm_exit = Module.cwrap ('mono_wasm_exit', null, ['number']);
+ wasm_exit (1);
+ }
+ } else {
+ load_runtime ("unused", args.debug_level);
+ }
+
+ MONO.mono_wasm_runtime_ready ();
+ args.loaded_cb ();
+ },
+
+ _load_assets_and_runtime: function (args) {
+ if (args.enable_debugging)
+ args.debug_level = args.enable_debugging;
+ if (args.assembly_list)
+ throw new Error ("Invalid args (assembly_list was replaced by assets)");
+ if (args.runtime_assets)
+ throw new Error ("Invalid args (runtime_assets was replaced by assets)");
+ if (args.runtime_asset_sources)
+ throw new Error ("Invalid args (runtime_asset_sources was replaced by remote_sources)");
+ if (!args.loaded_cb)
+ throw new Error ("loaded_cb not provided");
+
+ var ctx = {
+ tracing: args.diagnostic_tracing || false,
+ pending_count: args.assets.length,
+ mono_wasm_add_assembly: Module.cwrap ('mono_wasm_add_assembly', 'number', ['string', 'number', 'number']),
+ loaded_assets: Object.create (null),
+ // dlls and pdbs, used by blazor and the debugger
+ loaded_files: [],
+ createPath: Module['FS_createPath'],
+ createDataFile: Module['FS_createDataFile']
+ };
+
+ if (ctx.tracing)
+ console.log ("mono_wasm_load_runtime_with_args", JSON.stringify(args));
+
+ this._apply_configuration_from_args (args);
+
+ var fetch_file_cb = this._get_fetch_file_cb_from_args (args);
+
+ var onPendingRequestComplete = function () {
+ --ctx.pending_count;
+
+ if (ctx.pending_count === 0) {
+ try {
+ MONO._finalize_startup (args, ctx);
+ } catch (exc) {
+ console.error ("Unhandled exception in _finalize_startup", exc);
+ throw exc;
+ }
+ }
+ };
+
+ var processFetchResponseBuffer = function (asset, url, blob) {
+ try {
+ MONO._handle_loaded_asset (ctx, asset, url, blob);
+ } catch (exc) {
+ console.error ("Unhandled exception in processFetchResponseBuffer", exc);
+ throw exc;
+ } finally {
+ onPendingRequestComplete ();
+ }
+ };
+
+ args.assets.forEach (function (asset) {
+ var attemptNextSource;
+ var sourceIndex = 0;
+ var sourcesList = asset.load_remote ? args.remote_sources : [""];
+
+ var handleFetchResponse = function (response) {
if (!response.ok) {
- // If it's a 404 on a .pdb, we don't want to block the app from starting up.
- // We'll just skip that file and continue (though the 404 is logged in the console).
- if (response.status === 404 && file_name.match(/\.pdb$/) && MONO.mono_wasm_ignore_pdb_load_errors) {
- --pending;
- throw "MONO-WASM: Skipping failed load for .pdb file: '" + file_name + "'";
+ try {
+ attemptNextSource ();
+ return;
+ } catch (exc) {
+ console.error ("MONO_WASM: Unhandled exception in handleFetchResponse attemptNextSource for asset", asset.name, exc);
+ throw exc;
}
- else {
- throw "MONO_WASM: Failed to load file: '" + file_name + "'";
- }
- }
- else {
- loaded_files.push ({ url: response.url, file: file_name});
- return response ['arrayBuffer'] ();
}
- }).then (function (blob) {
- var asm = new Uint8Array (blob);
- var memory = Module._malloc(asm.length);
- var heapBytes = new Uint8Array(Module.HEAPU8.buffer, memory, asm.length);
- heapBytes.set (asm);
- var hasPpdb = mono_wasm_add_assembly (file_name, memory, asm.length);
-
- if (!hasPpdb) {
- var index = loaded_files.findIndex(element => element.file == file_name);
- loaded_files.splice(index, 1);
+
+ try {
+ var bufferPromise = response ['arrayBuffer'] ();
+ bufferPromise.then (processFetchResponseBuffer.bind (this, asset, response.url));
+ } catch (exc) {
+ console.error ("MONO_WASM: Unhandled exception in handleFetchResponse for asset", asset.name, exc);
+ attemptNextSource ();
}
- //console.log ("MONO_WASM: Loaded: " + file_name);
- --pending;
- if (pending == 0) {
- loaded_files.forEach(value => loaded_files_with_debug_info.push(value.url));
- MONO.loaded_files = loaded_files_with_debug_info;
- var load_runtime = Module.cwrap ('mono_wasm_load_runtime', null, ['string', 'number']);
-
- console.log ("MONO_WASM: Initializing mono runtime");
- if (ENVIRONMENT_IS_SHELL || ENVIRONMENT_IS_NODE) {
- try {
- load_runtime (vfs_prefix, enable_debugging);
- } catch (ex) {
- print ("MONO_WASM: load_runtime () failed: " + ex);
- print ("MONO_WASM: Stacktrace: \n");
- print (ex.stack);
-
- var wasm_exit = Module.cwrap ('mono_wasm_exit', null, ['number']);
- wasm_exit (1);
+ };
+
+ attemptNextSource = function () {
+ if (sourceIndex >= sourcesList.length) {
+ var msg = "MONO_WASM: Failed to load " + asset.name;
+ try {
+ var isOk = asset.is_optional ||
+ (asset.name.match (/\.pdb$/) && MONO.mono_wasm_ignore_pdb_load_errors);
+
+ if (isOk)
+ console.log (msg);
+ else {
+ console.error (msg);
+ throw new Error (msg);
}
+ } finally {
+ onPendingRequestComplete ();
+ }
+ }
+
+ var sourcePrefix = sourcesList[sourceIndex];
+ sourceIndex++;
+
+ // HACK: Special-case because MSBuild doesn't allow "" as an attribute
+ if (sourcePrefix === "./")
+ sourcePrefix = "";
+
+ var attemptUrl;
+ if (sourcePrefix.trim() === "") {
+ if (asset.behavior === "assembly")
+ attemptUrl = locateFile (args.assembly_root + "/" + asset.name);
+ else
+ attemptUrl = asset.name;
+ } else {
+ attemptUrl = sourcePrefix + asset.name;
+ }
+
+ try {
+ if (asset.name === attemptUrl) {
+ if (ctx.tracing)
+ console.log ("Attempting to fetch '" + attemptUrl + "'");
} else {
- load_runtime (vfs_prefix, enable_debugging);
+ if (ctx.tracing)
+ console.log ("Attempting to fetch '" + attemptUrl + "' for", asset.name);
}
- MONO.mono_wasm_runtime_ready ();
- loaded_cb ();
+ var fetch_promise = fetch_file_cb (attemptUrl);
+ fetch_promise.then (handleFetchResponse);
+ } catch (exc) {
+ console.error ("MONO_WASM: Error fetching " + attemptUrl, exc);
+ attemptNextSource ();
}
- });
+ };
+
+ attemptNextSource ();
});
},
+ // Performs setup for globalization.
+ // @globalization_mode is one of "icu", "invariant", or "auto".
+ // "auto" will use "icu" if any ICU data archives have been loaded,
+ // otherwise "invariant".
+ mono_wasm_globalization_init: function (globalization_mode) {
+ var invariantMode = false;
+
+ if (globalization_mode === "invariant")
+ invariantMode = true;
+
+ if (!invariantMode) {
+ if (this.num_icu_assets_loaded_successfully > 0) {
+ console.log ("MONO_WASM: ICU data archive(s) loaded, disabling invariant mode");
+ } else if (globalization_mode !== "icu") {
+ console.log ("MONO_WASM: ICU data archive(s) not loaded, using invariant globalization mode");
+ invariantMode = true;
+ } else {
+ var msg = "invariant globalization mode is inactive and no ICU data archives were loaded";
+ console.error ("MONO_WASM: ERROR: " + msg);
+ throw new Error (msg);
+ }
+ }
+
+ if (invariantMode)
+ this.mono_wasm_setenv ("DOTNET_SYSTEM_GLOBALIZATION_INVARIANT", "1");
+ },
+
+ // Used by the debugger to enumerate loaded dlls and pdbs
mono_wasm_get_loaded_files: function() {
- console.log(">>>mono_wasm_get_loaded_files");
- return this.loaded_files;
+ return MONO.loaded_files;
+ },
+
+ mono_wasm_get_loaded_asset_table: function() {
+ return MONO.loaded_assets;
},
-
+
mono_wasm_clear_all_breakpoints: function() {
if (!this.mono_clear_bps)
this.mono_clear_bps = Module.cwrap ('mono_wasm_clear_all_breakpoints', null);
this.mono_clear_bps ();
},
-
+
mono_wasm_add_null_var: function(className)
{
- fixed_class_name = MONO._mono_csharp_fixup_class_name(Module.UTF8ToString (className));
+ let fixed_class_name = MONO._mono_csharp_fixup_class_name(Module.UTF8ToString (className));
if (!fixed_class_name) {
// Eg, when a @className is passed from js itself, like
// mono_wasm_add_null_var ("string")
@@ -830,12 +1305,13 @@ var MonoSupportLib = {
value: {
type: "string",
value: var_value,
+ description: var_value
}
});
},
_mono_wasm_add_getter_var: function(className, invokable) {
- fixed_class_name = MONO._mono_csharp_fixup_class_name (className);
+ const fixed_class_name = MONO._mono_csharp_fixup_class_name (className);
if (invokable != 0) {
var name;
if (MONO.var_info.length > 0)
@@ -862,7 +1338,7 @@ var MonoSupportLib = {
},
_mono_wasm_add_array_var: function(className, objectId, length) {
- fixed_class_name = MONO._mono_csharp_fixup_class_name(className);
+ const fixed_class_name = MONO._mono_csharp_fixup_class_name(className);
if (objectId == 0) {
MONO.mono_wasm_add_null_var (fixed_class_name);
return;
@@ -874,42 +1350,121 @@ var MonoSupportLib = {
subtype: "array",
className: fixed_class_name,
description: `${fixed_class_name}(${length})`,
- objectId: "dotnet:array:"+ objectId,
+ objectId: this._new_or_add_id_props ({ scheme: 'array', idArgs: { arrayId: objectId } })
}
});
},
+ // FIXME: improve
+ _base64_to_uint8: function (base64String) {
+ const byteCharacters = atob (base64String);
+ const byteNumbers = new Array(byteCharacters.length);
+ for (let i = 0; i < byteCharacters.length; i++) {
+ byteNumbers[i] = byteCharacters.charCodeAt(i);
+ }
+
+ return new Uint8Array (byteNumbers);
+ },
+
+ _begin_value_type_var: function(className, args) {
+ if (args === undefined || (typeof args !== 'object')) {
+ console.debug (`_begin_value_type_var: Expected an args object`);
+ return;
+ }
+
+ const fixed_class_name = MONO._mono_csharp_fixup_class_name(className);
+ const toString = args.toString;
+ const base64String = btoa (String.fromCharCode (...new Uint8Array (Module.HEAPU8.buffer, args.value_addr, args.value_size)));
+ const vt_obj = {
+ value: {
+ type : "object",
+ className : fixed_class_name,
+ description : (toString == 0 ? fixed_class_name: Module.UTF8ToString (toString)),
+ expanded : true,
+ isValueType : true,
+ __extra_vt_props: { klass: args.klass, value64: base64String },
+ members : []
+ }
+ };
+ if (MONO._vt_stack.length == 0)
+ MONO._old_var_info = MONO.var_info;
+
+ MONO.var_info = vt_obj.value.members;
+ MONO._vt_stack.push (vt_obj);
+ },
+
+ _end_value_type_var: function() {
+ let top_vt_obj_popped = MONO._vt_stack.pop ();
+ top_vt_obj_popped.value.members = MONO._filter_automatic_properties (
+ MONO._fixup_name_value_objects (top_vt_obj_popped.value.members));
+
+ if (MONO._vt_stack.length == 0) {
+ MONO.var_info = MONO._old_var_info;
+ MONO.var_info.push(top_vt_obj_popped);
+ } else {
+ var top_obj = MONO._vt_stack [MONO._vt_stack.length - 1];
+ top_obj.value.members.push (top_vt_obj_popped);
+ MONO.var_info = top_obj.value.members;
+ }
+ },
+
+ _add_valuetype_unexpanded_var: function(className, args) {
+ if (args === undefined || (typeof args !== 'object')) {
+ console.debug (`_add_valuetype_unexpanded_var: Expected an args object`);
+ return;
+ }
+
+ const fixed_class_name = MONO._mono_csharp_fixup_class_name (className);
+ const toString = args.toString;
+
+ MONO.var_info.push ({
+ value: {
+ type: "object",
+ className: fixed_class_name,
+ description: (toString == 0 ? fixed_class_name : Module.UTF8ToString (toString)),
+ isValueType: true
+ }
+ });
+ },
+
+
mono_wasm_add_typed_value: function (type, str_value, value) {
- var type_str = type;
+ let type_str = type;
if (typeof type != 'string')
type_str = Module.UTF8ToString (type);
- if (typeof str_value != 'string')
str_value = Module.UTF8ToString (str_value);
switch (type_str) {
- case "bool":
+ case "bool": {
+ const v = value != 0;
MONO.var_info.push ({
value: {
type: "boolean",
- value: value != 0
+ value: v,
+ description: v.toString ()
}
});
break;
+ }
- case "char":
+ case "char": {
+ const v = `${value} '${String.fromCharCode (value)}'`;
MONO.var_info.push ({
value: {
type: "symbol",
- value: `${value} '${String.fromCharCode (value)}'`
+ value: v,
+ description: v
}
});
break;
+ }
case "number":
MONO.var_info.push ({
value: {
type: "number",
- value: value
+ value: value,
+ description: '' + value
}
});
break;
@@ -926,8 +1481,20 @@ var MonoSupportLib = {
MONO._mono_wasm_add_array_var (str_value, value.objectId, value.length);
break;
+ case "begin_vt":
+ MONO._begin_value_type_var (str_value, value);
+ break;
+
+ case "end_vt":
+ MONO._end_value_type_var ();
+ break;
+
+ case "unexpanded_vt":
+ MONO._add_valuetype_unexpanded_var (str_value, value);
+ break;
+
case "pointer": {
- var fixed_value_str = MONO._mono_csharp_fixup_class_name (str_value);
+ const fixed_value_str = MONO._mono_csharp_fixup_class_name (str_value);
if (value.klass_addr == 0 || value.ptr_addr == 0 || fixed_value_str.startsWith ('(void*')) {
// null or void*, which we can't deref
MONO.var_info.push({
@@ -943,7 +1510,7 @@ var MonoSupportLib = {
type: "object",
className: fixed_value_str,
description: fixed_value_str,
- objectId: this._get_updated_ptr_id ('', value)
+ objectId: this._new_or_add_id_props ({ scheme: 'pointer', props: value })
}
});
}
@@ -951,7 +1518,7 @@ var MonoSupportLib = {
break;
default: {
- var msg = `'${str_value}' ${value}`;
+ const msg = `'${str_value}' ${value}`;
MONO.var_info.push ({
value: {
@@ -971,6 +1538,59 @@ var MonoSupportLib = {
// and nested class names like Foo/Bar to Foo.Bar
return className.replace(/\//g, '.').replace(/`\d+/g, '');
},
+
+ mono_wasm_load_data_archive: function (data, prefix) {
+ if (data.length < 8)
+ return false;
+
+ var dataview = new DataView(data.buffer);
+ var magic = dataview.getUint32(0, true);
+ // get magic number
+ if (magic != 0x626c6174) {
+ return false;
+ }
+ var manifestSize = dataview.getUint32(4, true);
+ if (manifestSize == 0 || data.length < manifestSize + 8)
+ return false;
+
+ var manifest;
+ try {
+ manifestContent = Module.UTF8ArrayToString(data, 8, manifestSize);
+ manifest = JSON.parse(manifestContent);
+ if (!(manifest instanceof Array))
+ return false;
+ } catch (exc) {
+ return false;
+ }
+
+ data = data.slice(manifestSize+8);
+
+ // Create the folder structure
+ // /usr/share/zoneinfo
+ // /usr/share/zoneinfo/Africa
+ // /usr/share/zoneinfo/Asia
+ // ..
+
+ var folders = new Set()
+ manifest.filter(m => {
+ var file = m[0];
+ var last = file.lastIndexOf ("/");
+ var directory = file.slice (0, last);
+ folders.add(directory);
+ });
+ folders.forEach(folder => {
+ Module['FS_createPath'](prefix, folder, true, true);
+ });
+
+ for (row of manifest) {
+ var name = row[0];
+ var length = row[1];
+ var bytes = data.slice(0, length);
+ Module['FS_createDataFile'](prefix, name, bytes, true, true);
+ data = data.slice(length);
+ }
+ return true;
+ }
},
mono_wasm_add_typed_value: function (type, str_value, value) {
@@ -988,55 +1608,6 @@ var MonoSupportLib = {
MONO._async_method_objectId = objectId;
},
- mono_wasm_begin_value_type_var: function(className, toString) {
- fixed_class_name = MONO._mono_csharp_fixup_class_name(Module.UTF8ToString (className));
- var vt_obj = {
- value: {
- type: "object",
- className: fixed_class_name,
- description: (toString == 0 ? fixed_class_name : Module.UTF8ToString (toString)),
- // objectId will be generated by MonoProxy
- expanded: true,
- isValueType: true,
- members: []
- }
- };
- if (MONO._vt_stack.length == 0)
- MONO._old_var_info = MONO.var_info;
-
- MONO.var_info = vt_obj.value.members;
- MONO._vt_stack.push (vt_obj);
- },
-
- mono_wasm_end_value_type_var: function() {
- var top_vt_obj_popped = MONO._vt_stack.pop ();
- top_vt_obj_popped.value.members = MONO._filter_automatic_properties (
- MONO._fixup_name_value_objects (top_vt_obj_popped.value.members));
-
- if (MONO._vt_stack.length == 0) {
- MONO.var_info = MONO._old_var_info;
- MONO.var_info.push(top_vt_obj_popped);
- } else {
- var top_obj = MONO._vt_stack [MONO._vt_stack.length - 1];
- top_obj.value.members.push (top_vt_obj_popped);
- MONO.var_info = top_obj.value.members;
- }
- },
-
- mono_wasm_add_value_type_unexpanded_var: function (className, toString) {
- fixed_class_name = MONO._mono_csharp_fixup_class_name(Module.UTF8ToString (className));
- MONO.var_info.push({
- value: {
- type: "object",
- className: fixed_class_name,
- description: (toString == 0 ? fixed_class_name : Module.UTF8ToString (toString)),
- // objectId added when enumerating object's properties
- expanded: false,
- isValueType: true
- }
- });
- },
-
mono_wasm_add_enum_var: function(className, members, value) {
// FIXME: flags
//
@@ -1044,13 +1615,13 @@ var MonoSupportLib = {
// group0: Monday:0
// group1: Monday
// group2: 0
- var re = new RegExp (`[,]?([^,:]+):(${value}(?=,)|${value}$)`, 'g')
- var members_str = Module.UTF8ToString (members);
+ const re = new RegExp (`[,]?([^,:]+):(${value}(?=,)|${value}$)`, 'g')
+ const members_str = Module.UTF8ToString (members);
- var match = re.exec(members_str);
- var member_name = match == null ? ('' + value) : match [1];
+ const match = re.exec(members_str);
+ const member_name = match == null ? ('' + value) : match [1];
- fixed_class_name = MONO._mono_csharp_fixup_class_name(Module.UTF8ToString (className));
+ const fixed_class_name = MONO._mono_csharp_fixup_class_name(Module.UTF8ToString (className));
MONO.var_info.push({
value: {
type: "object",
@@ -1073,7 +1644,7 @@ var MonoSupportLib = {
return;
}
- fixed_class_name = MONO._mono_csharp_fixup_class_name(Module.UTF8ToString (className));
+ const fixed_class_name = MONO._mono_csharp_fixup_class_name(Module.UTF8ToString (className));
MONO.var_info.push({
value: {
type: "object",
@@ -1110,11 +1681,11 @@ var MonoSupportLib = {
return `${ret_sig} ${method_name} (${args_sig})`;
}
- var tgt_sig;
+ let tgt_sig;
if (targetName != 0)
tgt_sig = args_to_sig (Module.UTF8ToString (targetName));
- var type_name = MONO._mono_csharp_fixup_class_name (Module.UTF8ToString (className));
+ const type_name = MONO._mono_csharp_fixup_class_name (Module.UTF8ToString (className));
if (objectId == -1) {
// Target property
@@ -1184,6 +1755,7 @@ var MonoSupportLib = {
mono_wasm_fire_bp: function () {
console.log ("mono_wasm_fire_bp");
+ // eslint-disable-next-line no-debugger
debugger;
},