From 2178a5710bdc3df636bd0e8d31fd1c99414e6d17 Mon Sep 17 00:00:00 2001 From: Larry Ewing Date: Mon, 15 Nov 2021 16:13:59 -0600 Subject: [PATCH 1/8] Unify some code --- src/mono/wasm/runtime/startup.ts | 83 ++++++++++++++------------------ 1 file changed, 36 insertions(+), 47 deletions(-) diff --git a/src/mono/wasm/runtime/startup.ts b/src/mono/wasm/runtime/startup.ts index df61a27399d861..e581d3e7beb96b 100644 --- a/src/mono/wasm/runtime/startup.ts +++ b/src/mono/wasm/runtime/startup.ts @@ -147,41 +147,9 @@ function _get_fetch_implementation(args: MonoConfig): (asset: string) => Promise if (typeof (args.fetch_file_cb) === "function") return args.fetch_file_cb; - if (typeof (fetch) === "function") { - return function (asset) { - return fetch(asset, { credentials: "same-origin" }); - }; - } else if (ENVIRONMENT_IS_NODE || typeof (read) === "function") { - return async function (asset) { - let data: any = null; - let err: any = null; - try { - if (ENVIRONMENT_IS_NODE) { - // eslint-disable-next-line @typescript-eslint/no-var-requires - const fs = require("fs"); - data = await fs.promises.readFile(asset); - } - else { - data = read(asset, "binary"); - } - } - catch (exc) { - data = null; - err = exc; - } - const res: any = { - ok: !!data, - url: asset, - arrayBuffer: async function () { - if (err) throw err; - return new Uint8Array(data); - } - }; - return res; - }; - } else { - throw new Error("No fetch_file_cb was provided and this environment does not expose 'fetch'."); - } + return function (asset) { + return _fetch_data(asset); + }; } function _finalize_startup(args: MonoConfig, ctx: MonoInitContext) { @@ -445,6 +413,36 @@ export function mono_wasm_load_data_archive(data: TypedArray, prefix: string): b return true; } +async function _fetch_data (url: string): Promise { + if (typeof (fetch) === "function") { + return fetch(url, { credentials: "same-origin" }); + } else if (ENVIRONMENT_IS_NODE || typeof (read) === "function") { + let data: any = null; + try { + if (ENVIRONMENT_IS_NODE) { + // eslint-disable-next-line @typescript-eslint/no-var-requires + const fs = require("fs"); + data = await fs.promises.readFile(url); + } + else { + data = read(url, "binary"); + } + } + catch (exc) { + data = null; + return Promise.reject(exc); + } + return Promise.resolve({ + ok: !!data, + url: url, + arrayBuffer: () => Promise.resolve (new Uint8Array (data)), + json: () => Promise.resolve(JSON.parse(data)) + }); + } else { + return Promise.reject(Error("No fetch implementation available")); + } +} + /** * Loads the mono config file (typically called mono-config.json) asynchroniously * Note: the run dependencies are so emsdk actually awaits it in order. @@ -458,18 +456,9 @@ export async function mono_wasm_load_config(configFilePath: string): Promise Date: Mon, 15 Nov 2021 18:08:16 -0600 Subject: [PATCH 2/8] Work around v8 not having a nice way to convert to string --- src/mono/wasm/runtime/startup.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mono/wasm/runtime/startup.ts b/src/mono/wasm/runtime/startup.ts index e581d3e7beb96b..0da593b76e0636 100644 --- a/src/mono/wasm/runtime/startup.ts +++ b/src/mono/wasm/runtime/startup.ts @@ -436,7 +436,7 @@ async function _fetch_data (url: string): Promise { ok: !!data, url: url, arrayBuffer: () => Promise.resolve (new Uint8Array (data)), - json: () => Promise.resolve(JSON.parse(data)) + json: () => Promise.resolve (JSON.parse (ENVIRONMENT_IS_NODE ? data : read(url))), }); } else { return Promise.reject(Error("No fetch implementation available")); From c7bef9e9dc9a034d7c85d6b3eba626f519d1c68b Mon Sep 17 00:00:00 2001 From: Larry Ewing Date: Mon, 15 Nov 2021 19:29:34 -0600 Subject: [PATCH 3/8] redo naming and formatting --- src/mono/wasm/runtime/startup.ts | 63 ++++++++++++++++---------------- 1 file changed, 31 insertions(+), 32 deletions(-) diff --git a/src/mono/wasm/runtime/startup.ts b/src/mono/wasm/runtime/startup.ts index 0da593b76e0636..c2898d96bb2b7c 100644 --- a/src/mono/wasm/runtime/startup.ts +++ b/src/mono/wasm/runtime/startup.ts @@ -56,6 +56,35 @@ export function mono_wasm_set_runtime_options(options: string[]): void { cwraps.mono_wasm_parse_runtime_options(options.length, argv); } +async function _fetch_asset(url: string): Promise { + if (typeof (fetch) === "function") { + return fetch(url, { credentials: "same-origin" }); + } else if (ENVIRONMENT_IS_NODE || typeof (read) === "function") { + let data: any = null; + try { + if (ENVIRONMENT_IS_NODE) { + // eslint-disable-next-line @typescript-eslint/no-var-requires + const fs = require("fs"); + data = await fs.promises.readFile(url); + } + else { + data = read(url, "binary"); + } + return Promise.resolve( { + ok: !!data, + url: url, + arrayBuffer: () => Promise.resolve(new Uint8Array(data)), + json: () => Promise.resolve(JSON.parse(ENVIRONMENT_IS_NODE ? data : read(url))) + }); + } + catch (exc) { + return Promise.reject(exc); + } + } else { + return Promise.reject(Error("No fetch implementation available")); + } +} + function _handle_fetched_asset(ctx: MonoInitContext, asset: AssetEntry, url: string, blob: ArrayBuffer) { const bytes = new Uint8Array(blob); if (ctx.tracing) @@ -148,7 +177,7 @@ function _get_fetch_implementation(args: MonoConfig): (asset: string) => Promise return args.fetch_file_cb; return function (asset) { - return _fetch_data(asset); + return _fetch_asset(asset); }; } @@ -413,36 +442,6 @@ export function mono_wasm_load_data_archive(data: TypedArray, prefix: string): b return true; } -async function _fetch_data (url: string): Promise { - if (typeof (fetch) === "function") { - return fetch(url, { credentials: "same-origin" }); - } else if (ENVIRONMENT_IS_NODE || typeof (read) === "function") { - let data: any = null; - try { - if (ENVIRONMENT_IS_NODE) { - // eslint-disable-next-line @typescript-eslint/no-var-requires - const fs = require("fs"); - data = await fs.promises.readFile(url); - } - else { - data = read(url, "binary"); - } - } - catch (exc) { - data = null; - return Promise.reject(exc); - } - return Promise.resolve({ - ok: !!data, - url: url, - arrayBuffer: () => Promise.resolve (new Uint8Array (data)), - json: () => Promise.resolve (JSON.parse (ENVIRONMENT_IS_NODE ? data : read(url))), - }); - } else { - return Promise.reject(Error("No fetch implementation available")); - } -} - /** * Loads the mono config file (typically called mono-config.json) asynchroniously * Note: the run dependencies are so emsdk actually awaits it in order. @@ -456,7 +455,7 @@ export async function mono_wasm_load_config(configFilePath: string): Promise Date: Mon, 15 Nov 2021 23:13:39 -0600 Subject: [PATCH 4/8] do it all aync --- src/mono/wasm/runtime/startup.ts | 43 +++++++++++++++----------------- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/src/mono/wasm/runtime/startup.ts b/src/mono/wasm/runtime/startup.ts index c2898d96bb2b7c..a39d9fd58b5383 100644 --- a/src/mono/wasm/runtime/startup.ts +++ b/src/mono/wasm/runtime/startup.ts @@ -59,30 +59,27 @@ export function mono_wasm_set_runtime_options(options: string[]): void { async function _fetch_asset(url: string): Promise { if (typeof (fetch) === "function") { return fetch(url, { credentials: "same-origin" }); - } else if (ENVIRONMENT_IS_NODE || typeof (read) === "function") { - let data: any = null; - try { - if (ENVIRONMENT_IS_NODE) { - // eslint-disable-next-line @typescript-eslint/no-var-requires - const fs = require("fs"); - data = await fs.promises.readFile(url); - } - else { - data = read(url, "binary"); - } - return Promise.resolve( { - ok: !!data, - url: url, - arrayBuffer: () => Promise.resolve(new Uint8Array(data)), - json: () => Promise.resolve(JSON.parse(ENVIRONMENT_IS_NODE ? data : read(url))) - }); - } - catch (exc) { - return Promise.reject(exc); - } - } else { - return Promise.reject(Error("No fetch implementation available")); } + else if (ENVIRONMENT_IS_NODE) { + // eslint-disable-next-line @typescript-eslint/no-var-requires + const fs = require("fs"); + const arrayBuffer = await fs.readFileSync(url); + return { + ok: true, + url, + arrayBuffer: () => arrayBuffer, + json: () => JSON.parse(arrayBuffer) + }; + } + else if (typeof (read) === "function") { + return { + ok: true, + url, + arrayBuffer: () => new Uint8Array(read(url, "binary")), + json: () => JSON.parse(read(url)) + }; + } + throw new Error("No fetch implementation available"); } function _handle_fetched_asset(ctx: MonoInitContext, asset: AssetEntry, url: string, blob: ArrayBuffer) { From d9438a447e60417a2437d91761fe700f18eda221 Mon Sep 17 00:00:00 2001 From: Larry Ewing Date: Mon, 15 Nov 2021 23:47:39 -0600 Subject: [PATCH 5/8] Trap more exceptions again and drop _get_fetch_implmentation --- src/mono/wasm/runtime/startup.ts | 55 ++++++++++++++++---------------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/src/mono/wasm/runtime/startup.ts b/src/mono/wasm/runtime/startup.ts index a39d9fd58b5383..1746abc0e80415 100644 --- a/src/mono/wasm/runtime/startup.ts +++ b/src/mono/wasm/runtime/startup.ts @@ -57,26 +57,36 @@ export function mono_wasm_set_runtime_options(options: string[]): void { } async function _fetch_asset(url: string): Promise { - if (typeof (fetch) === "function") { - return fetch(url, { credentials: "same-origin" }); - } - else if (ENVIRONMENT_IS_NODE) { - // eslint-disable-next-line @typescript-eslint/no-var-requires - const fs = require("fs"); - const arrayBuffer = await fs.readFileSync(url); - return { - ok: true, - url, - arrayBuffer: () => arrayBuffer, - json: () => JSON.parse(arrayBuffer) - }; + try { + if (typeof (fetch) === "function") { + return fetch(url, { credentials: "same-origin" }); + } + else if (ENVIRONMENT_IS_NODE) { + // eslint-disable-next-line @typescript-eslint/no-var-requires + const fs = require("fs"); + const arrayBuffer = await fs.readFileSync(url); + return { + ok: true, + url, + arrayBuffer: () => arrayBuffer, + json: () => JSON.parse(arrayBuffer) + }; + } + else if (typeof (read) === "function") { + return { + ok: true, + url, + arrayBuffer: () => new Uint8Array(read(url, "binary")), + json: () => JSON.parse(read(url)) + }; + } } - else if (typeof (read) === "function") { + catch (e) { return { - ok: true, + ok: false, url, - arrayBuffer: () => new Uint8Array(read(url, "binary")), - json: () => JSON.parse(read(url)) + arrayBuffer: () => { throw e; }, + json: () => { throw e; } }; } throw new Error("No fetch implementation available"); @@ -169,15 +179,6 @@ function _apply_configuration_from_args(args: MonoConfig) { mono_wasm_init_coverage_profiler(args.coverage_profiler_options); } -function _get_fetch_implementation(args: MonoConfig): (asset: string) => Promise { - if (typeof (args.fetch_file_cb) === "function") - return args.fetch_file_cb; - - return function (asset) { - return _fetch_asset(asset); - }; -} - function _finalize_startup(args: MonoConfig, ctx: MonoInitContext) { const moduleExt = Module as EmscriptenModuleMono; @@ -310,7 +311,7 @@ export async function mono_load_runtime_and_bcl_args(args: MonoConfig): Promise< _apply_configuration_from_args(args); - const local_fetch = _get_fetch_implementation(args); + const local_fetch = typeof (args.fetch_file_cb) === "function" ? args.fetch_file_cb : _fetch_asset; const load_asset = async (asset: AllAssetEntryTypes): Promise => { //TODO we could do module.addRunDependency(asset.name) and delay emscripten run() after all assets are loaded From e8e2982bb649ebea4b6e7210d45247c5eeff5e5d Mon Sep 17 00:00:00 2001 From: Larry Ewing Date: Tue, 16 Nov 2021 01:08:25 -0600 Subject: [PATCH 6/8] Fix the type definitions for UTF8ArrayToString --- src/mono/wasm/runtime/startup.ts | 5 ++--- src/mono/wasm/runtime/types/emscripten.d.ts | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/mono/wasm/runtime/startup.ts b/src/mono/wasm/runtime/startup.ts index 1746abc0e80415..6de09e5651ede0 100644 --- a/src/mono/wasm/runtime/startup.ts +++ b/src/mono/wasm/runtime/startup.ts @@ -387,7 +387,7 @@ export async function mono_load_runtime_and_bcl_args(args: MonoConfig): Promise< } // used from Blazor -export function mono_wasm_load_data_archive(data: TypedArray, prefix: string): boolean { +export function mono_wasm_load_data_archive(data: Uint8Array, prefix: string): boolean { if (data.length < 8) return false; @@ -451,10 +451,9 @@ export async function mono_wasm_load_config(configFilePath: string): Promise Date: Tue, 16 Nov 2021 08:21:10 -0600 Subject: [PATCH 7/8] Fix accidental sync call --- src/mono/wasm/runtime/startup.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/mono/wasm/runtime/startup.ts b/src/mono/wasm/runtime/startup.ts index 6de09e5651ede0..734560c1afc9cf 100644 --- a/src/mono/wasm/runtime/startup.ts +++ b/src/mono/wasm/runtime/startup.ts @@ -64,7 +64,7 @@ async function _fetch_asset(url: string): Promise { else if (ENVIRONMENT_IS_NODE) { // eslint-disable-next-line @typescript-eslint/no-var-requires const fs = require("fs"); - const arrayBuffer = await fs.readFileSync(url); + const arrayBuffer = await fs.promises.readFile(url); return { ok: true, url, @@ -73,15 +73,16 @@ async function _fetch_asset(url: string): Promise { }; } else if (typeof (read) === "function") { + const arrayBuffer = new Uint8Array(read(url, "binary")); return { ok: true, url, - arrayBuffer: () => new Uint8Array(read(url, "binary")), - json: () => JSON.parse(read(url)) + arrayBuffer: () => arrayBuffer, + json: () => JSON.parse(Module.UTF8ArrayToString(arrayBuffer, 0, arrayBuffer.length)) }; } } - catch (e) { + catch (e: any) { return { ok: false, url, From 3bfbd66eda951fba975eb1a4c7c284ecd740606e Mon Sep 17 00:00:00 2001 From: Larry Ewing Date: Tue, 16 Nov 2021 09:54:16 -0600 Subject: [PATCH 8/8] Remove TypedArray import --- src/mono/wasm/runtime/startup.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mono/wasm/runtime/startup.ts b/src/mono/wasm/runtime/startup.ts index 734560c1afc9cf..dcab05fefeb783 100644 --- a/src/mono/wasm/runtime/startup.ts +++ b/src/mono/wasm/runtime/startup.ts @@ -2,7 +2,7 @@ // 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, TypedArray, VoidPtr, wasm_type_symbol } from "./types"; +import { AllAssetEntryTypes, AssetEntry, CharPtr, CharPtrNull, EmscriptenModuleMono, GlobalizationMode, MonoConfig, VoidPtr, wasm_type_symbol } from "./types"; 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";