diff --git a/src/mono/sample/wasm/browser/Wasm.Browser.Sample.csproj b/src/mono/sample/wasm/browser/Wasm.Browser.Sample.csproj
index 817971712ae5fe..c1eca5280663e1 100644
--- a/src/mono/sample/wasm/browser/Wasm.Browser.Sample.csproj
+++ b/src/mono/sample/wasm/browser/Wasm.Browser.Sample.csproj
@@ -14,5 +14,5 @@
<_SampleProject>Wasm.Browser.Sample.csproj
-
+
diff --git a/src/mono/sample/wasm/browser/main.js b/src/mono/sample/wasm/browser/main.js
index afe23356a73951..cf71a8e416b30b 100644
--- a/src/mono/sample/wasm/browser/main.js
+++ b/src/mono/sample/wasm/browser/main.js
@@ -8,12 +8,28 @@ function sub(a, b) {
return a - b;
}
+let testError = true;
+let testAbort = true;
try {
const { runtimeBuildInfo, setModuleImports, getAssemblyExports, runMain, getConfig } = await dotnet
.withConsoleForwarding()
.withElementOnExit()
.withModuleConfig({
configSrc: "./mono-config.json",
+ imports: {
+ fetch: (url, fetchArgs) => {
+ // we are testing that we can retry loading of the assembly
+ if (testAbort && url.indexOf('System.Private.Uri.dll') != -1) {
+ testAbort = false;
+ return fetch(url + "?testAbort=true", fetchArgs);
+ }
+ if (testError && url.indexOf('System.Console.dll') != -1) {
+ testError = false;
+ return fetch(url + "?testError=true", fetchArgs);
+ }
+ return fetch(url, fetchArgs);
+ }
+ },
onConfigLoaded: (config) => {
// This is called during emscripten `dotnet.wasm` instantiation, after we fetched config.
console.log('user code Module.onConfigLoaded');
diff --git a/src/mono/sample/wasm/simple-server/Program.cs b/src/mono/sample/wasm/simple-server/Program.cs
index 70ef1e573093f1..7a26f4406fb0dd 100644
--- a/src/mono/sample/wasm/simple-server/Program.cs
+++ b/src/mono/sample/wasm/simple-server/Program.cs
@@ -159,12 +159,36 @@ private async void ServeAsync(HttpListenerContext context)
if (path.EndsWith(".js") || path.EndsWith(".mjs") || path.EndsWith(".cjs"))
contentType = "text/javascript";
+ var stream = context.Response.OutputStream;
+
+ // test download re-try
+ if (url.Query.Contains("testError"))
+ {
+ Console.WriteLine("Faking 500 " + url);
+ context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
+ await stream.WriteAsync(buffer, 0, 0).ConfigureAwait(false);
+ await stream.FlushAsync();
+ context.Response.Close();
+ return;
+ }
+
if (contentType != null)
context.Response.ContentType = contentType;
context.Response.ContentLength64 = buffer.Length;
context.Response.AppendHeader("cache-control", "public, max-age=31536000");
- var stream = context.Response.OutputStream;
+
+ // test download re-try
+ if (url.Query.Contains("testAbort"))
+ {
+ Console.WriteLine("Faking abort " + url);
+ await stream.WriteAsync(buffer, 0, 10).ConfigureAwait(false);
+ await stream.FlushAsync();
+ await Task.Delay(100);
+ context.Response.Abort();
+ return;
+ }
+
try
{
await stream.WriteAsync(buffer).ConfigureAwait(false);
diff --git a/src/mono/wasm/runtime/assets.ts b/src/mono/wasm/runtime/assets.ts
index 80d63429102938..8e3630188ddbfb 100644
--- a/src/mono/wasm/runtime/assets.ts
+++ b/src/mono/wasm/runtime/assets.ts
@@ -76,10 +76,10 @@ export async function mono_download_assets(): Promise {
asset.pendingDownloadInternal = asset.pendingDownload;
const waitForExternalData: () => Promise = async () => {
const response = await asset.pendingDownloadInternal!.response;
- ++actual_downloaded_assets_count;
if (!headersOnly) {
asset.buffer = await response.arrayBuffer();
}
+ ++actual_downloaded_assets_count;
return { asset, buffer: asset.buffer };
};
promises_of_assets_with_buffer.push(waitForExternalData());
@@ -122,6 +122,10 @@ export async function mono_download_assets(): Promise {
if (!skipInstantiateByAssetTypes[asset.behavior]) {
expected_instantiated_assets_count--;
}
+ } else {
+ if (skipBufferByAssetTypes[asset.behavior]) {
+ ++actual_downloaded_assets_count;
+ }
}
}
})());
@@ -197,7 +201,9 @@ async function start_asset_download_with_throttle(asset: AssetEntry, downloadDat
if (!downloadData || !response) {
return undefined;
}
- return await response.arrayBuffer();
+ const buffer = await response.arrayBuffer();
+ ++actual_downloaded_assets_count;
+ return buffer;
}
finally {
--parallel_count;
@@ -226,7 +232,6 @@ async function start_asset_download_sources(asset: AssetEntryInternal): Promise<
}
}) as any
};
- ++actual_downloaded_assets_count;
return asset.pendingDownloadInternal.response;
}
if (asset.pendingDownloadInternal && asset.pendingDownloadInternal.response) {
@@ -262,7 +267,6 @@ async function start_asset_download_sources(asset: AssetEntryInternal): Promise<
if (!response.ok) {
continue;// next source
}
- ++actual_downloaded_assets_count;
return response;
}
catch (err) {
@@ -293,7 +297,7 @@ function resolve_path(asset: AssetEntry, sourcePrefix: string): string {
: asset.name;
}
else if (asset.behavior === "resource") {
- const path = asset.culture !== "" ? `${asset.culture}/${asset.name}` : asset.name;
+ const path = asset.culture && asset.culture !== "" ? `${asset.culture}/${asset.name}` : asset.name;
attemptUrl = assemblyRootFolder
? (assemblyRootFolder + "/" + path)
: path;
@@ -420,7 +424,7 @@ function _instantiate_asset(asset: AssetEntry, url: string, bytes: Uint8Array) {
Module.printErr(`MONO_WASM: Error loading ICU asset ${asset.name}`);
}
else if (asset.behavior === "resource") {
- cwraps.mono_wasm_add_satellite_assembly(virtualName, asset.culture!, offset!, bytes.length);
+ cwraps.mono_wasm_add_satellite_assembly(virtualName, asset.culture || "", offset!, bytes.length);
}
++actual_instantiated_assets_count;
}
@@ -429,10 +433,10 @@ export async function instantiate_wasm_asset(
pendingAsset: AssetEntryInternal,
wasmModuleImports: WebAssembly.Imports,
successCallback: InstantiateWasmSuccessCallback,
-) {
- mono_assert(pendingAsset && pendingAsset.pendingDownloadInternal, "Can't load dotnet.wasm");
+): Promise {
+ mono_assert(pendingAsset && pendingAsset.pendingDownloadInternal && pendingAsset.pendingDownloadInternal.response, "Can't load dotnet.wasm");
const response = await pendingAsset.pendingDownloadInternal.response;
- const contentType = response.headers ? response.headers.get("Content-Type") : undefined;
+ const contentType = response.headers && response.headers.get ? response.headers.get("Content-Type") : undefined;
let compiledInstance: WebAssembly.Instance;
let compiledModule: WebAssembly.Module;
if (typeof WebAssembly.instantiateStreaming === "function" && contentType === "application/wasm") {