Skip to content

Commit 045db5d

Browse files
authored
[browser] make dynamic import cancelable (#80257)
* make dynamic import cancelable * feedback
1 parent 2fc497b commit 045db5d

File tree

2 files changed

+26
-8
lines changed
  • src
    • libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript
    • mono/wasm/runtime

2 files changed

+26
-8
lines changed

src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.UnitTests/System/Runtime/InteropServices/JavaScript/JSImportExportTest.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.IO;
66
using System.Runtime.CompilerServices;
77
using System.Threading.Tasks;
8+
using System.Threading;
89
using Xunit;
910
#pragma warning disable xUnit1026 // Theory methods should use all of their parameters
1011

@@ -31,6 +32,19 @@ public async Task MultipleImportAsync()
3132
Assert.Same(instance1, instance2);
3233
}
3334

35+
[Fact]
36+
public async Task CancelableImportAsync()
37+
{
38+
var cts = new CancellationTokenSource();
39+
var exTask = Assert.ThrowsAsync<JSException>(async () => await JSHost.ImportAsync("JavaScriptTestHelper", "./JavaScriptTestHelper.mjs", cts.Token));
40+
cts.Cancel();
41+
var actualEx2 = await exTask;
42+
Assert.Equal("OperationCanceledException", actualEx2.Message);
43+
44+
var actualEx = await Assert.ThrowsAsync<JSException>(async () => await JSHost.ImportAsync("JavaScriptTestHelper", "./JavaScriptTestHelper.mjs", new CancellationToken(true)));
45+
Assert.Equal("OperationCanceledException", actualEx.Message);
46+
}
47+
3448
[Fact]
3549
public unsafe void GlobalThis()
3650
{

src/mono/wasm/runtime/invoke-js.ts

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { mono_wasm_new_external_root } from "./roots";
1313
import { mono_wasm_symbolicate_string } from "./logging";
1414
import { mono_wasm_get_jsobj_from_js_handle } from "./gc-handles";
1515
import { endMeasure, MeasuredBlock, startMeasure } from "./profiler";
16+
import { wrap_as_cancelable_promise } from "./cancelable-promise";
1617

1718
const fn_wrapper_by_fn_handle: Function[] = <any>[null];// 0th slot is dummy, we never free bound functions
1819

@@ -317,7 +318,7 @@ export function get_global_this(): any {
317318
export const importedModulesPromises: Map<string, Promise<any>> = new Map();
318319
export const importedModules: Map<string, Promise<any>> = new Map();
319320

320-
export async function dynamic_import(module_name: string, module_url: string): Promise<any> {
321+
export function dynamic_import(module_name: string, module_url: string): Promise<any> {
321322
mono_assert(module_name, "Invalid module_name");
322323
mono_assert(module_url, "Invalid module_name");
323324
let promise = importedModulesPromises.get(module_name);
@@ -328,13 +329,16 @@ export async function dynamic_import(module_name: string, module_url: string): P
328329
promise = import(/* webpackIgnore: true */module_url);
329330
importedModulesPromises.set(module_name, promise);
330331
}
331-
const module = await promise;
332-
if (newPromise) {
333-
importedModules.set(module_name, module);
334-
if (runtimeHelpers.diagnosticTracing)
335-
console.debug(`MONO_WASM: imported ES6 module '${module_name}' from '${module_url}'`);
336-
}
337-
return module;
332+
333+
return wrap_as_cancelable_promise(async () => {
334+
const module = await promise;
335+
if (newPromise) {
336+
importedModules.set(module_name, module);
337+
if (runtimeHelpers.diagnosticTracing)
338+
console.debug(`MONO_WASM: imported ES6 module '${module_name}' from '${module_url}'`);
339+
}
340+
return module;
341+
});
338342
}
339343

340344

0 commit comments

Comments
 (0)