Skip to content

Commit 1d15f21

Browse files
authored
[wasm] Asserts for externaly configured assets, more pendingDownload (#79886)
* asserts for assets * allow to pass .wasm as pendingDownload
1 parent fa7d049 commit 1d15f21

File tree

2 files changed

+31
-25
lines changed

2 files changed

+31
-25
lines changed

src/mono/wasm/runtime/assets.ts

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -67,30 +67,18 @@ export async function mono_download_assets(): Promise<void> {
6767
// start fetching and instantiating all assets in parallel
6868
for (const a of runtimeHelpers.config.assets!) {
6969
const asset: AssetEntryInternal = a;
70+
mono_assert(typeof asset === "object", "asset must be object");
71+
mono_assert(typeof asset.behavior === "string", "asset behavior must be known string");
72+
mono_assert(typeof asset.name === "string", "asset name must be string");
73+
mono_assert(!asset.resolvedUrl || typeof asset.resolvedUrl === "string", "asset resolvedUrl could be string");
74+
mono_assert(!asset.hash || typeof asset.hash === "string", "asset resolvedUrl could be string");
75+
mono_assert(!asset.pendingDownload || typeof asset.pendingDownload === "object", "asset pendingDownload could be object");
7076
if (!skipInstantiateByAssetTypes[asset.behavior]) {
7177
expected_instantiated_assets_count++;
7278
}
7379
if (!skipDownloadsByAssetTypes[asset.behavior]) {
74-
const headersOnly = skipBufferByAssetTypes[asset.behavior];// `response.arrayBuffer()` can't be called twice. Some usecases are calling it on response in the instantiation.
7580
expected_downloaded_assets_count++;
76-
if (asset.pendingDownload) {
77-
asset.pendingDownloadInternal = asset.pendingDownload;
78-
const waitForExternalData: () => Promise<AssetWithBuffer> = async () => {
79-
const response = await asset.pendingDownloadInternal!.response;
80-
++actual_downloaded_assets_count;
81-
if (!headersOnly) {
82-
asset.buffer = await response.arrayBuffer();
83-
}
84-
return { asset, buffer: asset.buffer };
85-
};
86-
promises_of_assets_with_buffer.push(waitForExternalData());
87-
} else {
88-
const waitForExternalData: () => Promise<AssetWithBuffer> = async () => {
89-
asset.buffer = await start_asset_download_with_retries(asset, !headersOnly);
90-
return { asset, buffer: asset.buffer };
91-
};
92-
promises_of_assets_with_buffer.push(waitForExternalData());
93-
}
81+
promises_of_assets_with_buffer.push(start_asset_download(asset));
9482
}
9583
}
9684
allDownloadsQueued.promise_control.resolve();
@@ -103,6 +91,7 @@ export async function mono_download_assets(): Promise<void> {
10391
if (assetWithBuffer.buffer) {
10492
if (!skipInstantiateByAssetTypes[asset.behavior]) {
10593
const url = asset.pendingDownloadInternal!.url;
94+
mono_assert(asset.buffer && typeof asset.buffer === "object", "asset buffer must be array or buffer like");
10695
const data = new Uint8Array(asset.buffer!);
10796
asset.pendingDownloadInternal = null as any; // GC
10897
asset.pendingDownload = null as any; // GC
@@ -146,8 +135,25 @@ export async function mono_download_assets(): Promise<void> {
146135
}
147136
}
148137

138+
export async function start_asset_download(asset: AssetEntryInternal) {
139+
// `response.arrayBuffer()` can't be called twice. Some use-cases are calling it on response in the instantiation.
140+
const headersOnly = skipBufferByAssetTypes[asset.behavior];
141+
if (asset.pendingDownload) {
142+
asset.pendingDownloadInternal = asset.pendingDownload;
143+
const response = await asset.pendingDownloadInternal!.response;
144+
++actual_downloaded_assets_count;
145+
if (!headersOnly) {
146+
asset.buffer = await response.arrayBuffer();
147+
}
148+
return { asset, buffer: asset.buffer };
149+
} else {
150+
asset.buffer = await start_asset_download_with_retries(asset, !headersOnly);
151+
return { asset, buffer: asset.buffer };
152+
}
153+
}
154+
149155
// FIXME: Connection reset is probably the only good one for which we should retry
150-
export async function start_asset_download_with_retries(asset: AssetEntryInternal, downloadData: boolean): Promise<ArrayBuffer | undefined> {
156+
async function start_asset_download_with_retries(asset: AssetEntryInternal, downloadData: boolean): Promise<ArrayBuffer | undefined> {
151157
try {
152158
return await start_asset_download_with_throttle(asset, downloadData);
153159
} catch (err: any) {
@@ -294,7 +300,7 @@ function resolve_path(asset: AssetEntry, sourcePrefix: string): string {
294300
: asset.name;
295301
}
296302
else if (asset.behavior === "resource") {
297-
const path = asset.culture !== "" ? `${asset.culture}/${asset.name}` : asset.name;
303+
const path = asset.culture && asset.culture !== "" ? `${asset.culture}/${asset.name}` : asset.name;
298304
attemptUrl = assemblyRootFolder
299305
? (assemblyRootFolder + "/" + path)
300306
: path;
@@ -422,7 +428,7 @@ function _instantiate_asset(asset: AssetEntry, url: string, bytes: Uint8Array) {
422428
Module.printErr(`MONO_WASM: Error loading ICU asset ${asset.name}`);
423429
}
424430
else if (asset.behavior === "resource") {
425-
cwraps.mono_wasm_add_satellite_assembly(virtualName, asset.culture!, offset!, bytes.length);
431+
cwraps.mono_wasm_add_satellite_assembly(virtualName, asset.culture || "", offset!, bytes.length);
426432
}
427433
endMeasure(mark, MeasuredBlock.instantiateAsset, asset.name);
428434
++actual_instantiated_assets_count;
@@ -433,7 +439,7 @@ export async function instantiate_wasm_asset(
433439
wasmModuleImports: WebAssembly.Imports,
434440
successCallback: InstantiateWasmSuccessCallback,
435441
): Promise<void> {
436-
mono_assert(pendingAsset && pendingAsset.pendingDownloadInternal, "Can't load dotnet.wasm");
442+
mono_assert(pendingAsset && pendingAsset.pendingDownloadInternal && pendingAsset.pendingDownloadInternal.response, "Can't load dotnet.wasm");
437443
const response = await pendingAsset.pendingDownloadInternal.response;
438444
const contentType = response.headers ? response.headers.get("Content-Type") : undefined;
439445
let compiledInstance: WebAssembly.Instance;

src/mono/wasm/runtime/startup.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import { init_legacy_exports } from "./net6-legacy/corebindings";
2222
import { cwraps_internal } from "./exports-internal";
2323
import { cwraps_binding_api, cwraps_mono_api } from "./net6-legacy/exports-legacy";
2424
import { CharPtr, InstantiateWasmCallBack, InstantiateWasmSuccessCallback } from "./types/emscripten";
25-
import { instantiate_wasm_asset, mono_download_assets, resolve_asset_path, start_asset_download_with_retries, wait_for_all_assets } from "./assets";
25+
import { instantiate_wasm_asset, mono_download_assets, resolve_asset_path, start_asset_download, wait_for_all_assets } from "./assets";
2626
import { BINDING, MONO } from "./net6-legacy/imports";
2727
import { readSymbolMapFile } from "./logging";
2828
import { mono_wasm_init_diagnostics } from "./diagnostics";
@@ -445,7 +445,7 @@ async function instantiate_wasm_module(
445445
if (runtimeHelpers.diagnosticTracing) console.debug("MONO_WASM: instantiate_wasm_module");
446446
const assetToLoad = resolve_asset_path("dotnetwasm");
447447
// FIXME: this would not apply re-try (on connection reset during download) for dotnet.wasm because we could not download the buffer before we pass it to instantiate_wasm_asset
448-
await start_asset_download_with_retries(assetToLoad, false);
448+
await start_asset_download(assetToLoad);
449449
await beforePreInit.promise;
450450
Module.addRunDependency("instantiate_wasm_module");
451451
await instantiate_wasm_asset(assetToLoad, imports, successCallback);

0 commit comments

Comments
 (0)