Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JSImport returning Promise that signals reject #102339

Closed
SerratedSharp opened this issue May 16, 2024 · 3 comments · Fixed by #102549
Closed

JSImport returning Promise that signals reject #102339

SerratedSharp opened this issue May 16, 2024 · 3 comments · Fixed by #102549
Assignees
Labels
arch-wasm WebAssembly architecture area-System.Runtime.InteropServices.JavaScript os-browser Browser variant of arch-wasm
Milestone

Comments

@SerratedSharp
Copy link

SerratedSharp commented May 16, 2024

Description

What's expected if a I call a JSImport method which returns a promise, and the promise signals a reject?

This code works fine when it signals resolve, but if it signals reject it hangs on the await'd ConditionalSuccess() call. Neither the "Error occurred" nor the "More?" message prints, and if F10 each line it never returns from the ConditionalSuccess().

Is this not supported, or am I doing something wrong?

I also tried .ContinueWith() and checking for a faulted task, but the ContinueWith is never called. I assume workaround would be to handle reject's JS-side, and throw instead.

Reproduction Steps

Create a wasm-browser project, define the following JS in a ES6 module, load the module with JSHost.ImportAsync, then call the below C# code.

    PromisesShim.ConditionalSuccess = function (shouldSucceed) {        
        return new Promise((resolve, reject) => {            
            setTimeout(() => {
                if (shouldSucceed) {
                    resolve();// success                
                } else {
                    reject();// failure  
                }
            }, 500);
        });
    };
        [JSImport("PromisesShim.ConditionalSuccess", "PromisesShim")]
        public static partial Task ConditionalSuccess(bool shouldSucceed);
        //....

        try
        {
            await PromisesProxy.ConditionalSuccess(shouldSucceed: false);// await an async JS method
            Console.WriteLine($"Waited {sw.Elapsed.TotalSeconds:#.0} seconds for ConditionalSuccess.");
        }
        catch(Exception ex)
        {
            Console.WriteLine($"Error ocurred: {ex.Message}");
        }        
        Console.WriteLine($"More?");

Expected behavior

Maybe return a faulted task or throw an exception? I'm not a expert on Promises so I wouldn't presume to know what should happen. But I feel confident that it definitely shouldn't just hang.

Actual behavior

The call to PromisesProxy.ConditionalSuccess() hangs and never returns if the JS Promise calls reject()

Regression?

No response

Known Workarounds

Pass string into .reject()

Configuration

VS 17.10.0 Preview 3

dotnet --info:
.NET SDK:
Version: 8.0.300-preview.24203.14
Commit: b7e38f457d
Workload version: 8.0.300-manifests.c4df6daf
MSBuild version: 17.10.0+4f6b1bb28

Runtime Environment:
OS Name: Windows
OS Version: 10.0.22631
OS Platform: Windows
RID: win-x64
Base Path: C:\Program Files\dotnet\sdk\8.0.300-preview.24203.14\

.NET workloads installed:
[aspire]
Installation Source: SDK 8.0.300-preview.24203, VS 17.10.34804.81
Manifest Version: 8.0.0-preview.5.24201.12/8.0.100
Manifest Path: C:\Program Files\dotnet\sdk-manifests\8.0.100\microsoft.net.sdk.aspire\8.0.0-preview.5.24201.12\WorkloadManifest.json
Install Type: Msi

[wasm-experimental]
Installation Source: SDK 8.0.300-preview.24203
Manifest Version: 8.0.4/8.0.100
Manifest Path: C:\Program Files\dotnet\sdk-manifests\8.0.100\microsoft.net.workload.mono.toolchain.current\8.0.4\WorkloadManifest.json
Install Type: Msi

[wasm-tools]
Installation Source: SDK 8.0.300-preview.24203
Manifest Version: 8.0.4/8.0.100
Manifest Path: C:\Program Files\dotnet\sdk-manifests\8.0.100\microsoft.net.workload.mono.toolchain.current\8.0.4\WorkloadManifest.json
Install Type: Msi

Host:
Version: 8.0.4
Architecture: x64
Commit: 2d7eea2

.NET SDKs installed:
6.0.321 [C:\Program Files\dotnet\sdk]
6.0.400 [C:\Program Files\dotnet\sdk]
6.0.406 [C:\Program Files\dotnet\sdk]
8.0.104 [C:\Program Files\dotnet\sdk]
8.0.204 [C:\Program Files\dotnet\sdk]
8.0.300-preview.24203.14 [C:\Program Files\dotnet\sdk]

.NET runtimes installed:
Microsoft.AspNetCore.All 2.1.30 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.App 2.1.30 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 5.0.17 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 6.0.8 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 6.0.14 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 6.0.26 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 6.0.27 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 7.0.16 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 8.0.2 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 8.0.4 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 2.1.30 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 5.0.14 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 5.0.17 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 6.0.8 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 6.0.26 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 6.0.27 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 6.0.29 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 7.0.16 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 8.0.2 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 8.0.4 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 5.0.17 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 6.0.8 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 6.0.26 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 6.0.27 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 6.0.29 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 7.0.16 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 8.0.2 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 8.0.4 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

Other information

No response

@dotnet-issue-labeler dotnet-issue-labeler bot added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label May 16, 2024
@dotnet-policy-service dotnet-policy-service bot added the untriaged New issue has not been triaged by the area owner label May 16, 2024
@maraf maraf added arch-wasm WebAssembly architecture area-System.Runtime.InteropServices.JavaScript os-browser Browser variant of arch-wasm labels May 17, 2024
@maraf
Copy link
Member

maraf commented May 17, 2024

cc @pavelsavara

@vcsjones vcsjones removed the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label May 17, 2024
@pavelsavara
Copy link
Member

This should just work normally. This is how we propagate all exceptions from JS.
Are you sure this is single-threaded build ?

@pavelsavara pavelsavara self-assigned this May 20, 2024
@SerratedSharp
Copy link
Author

SerratedSharp commented May 22, 2024

Threading is not enabled.

Thanks for confirming expected behavior. After fiddling for a bit, I was able to narrow this down to whether or not I pass a string to reject(). Removed setTimeout and just called Promise.reject.

  • With a parameter Promise.reject('noodles') behavior is as expected.
  • Without a parameter Promise.reject() freezes. I think something didn't expect undefined for the reason parameter.

Similar discussion over at Typescript seemed to settle on reject() without parameters being considered valid:
microsoft/TypeScript#23416 (comment)

One other thing I observed is when I created a fresh project to reproduce, execution paused and I got an Exception Unhandled undefined popup in VS. However note when I selected Continue the Program.cs catch block on the C# side never saw this exception and none of the messages afterwards printed, which is consistent with the other occurrence that seemed to indicate it hung:
image

Minimal reproduction with a wasm-browser project attached. Note I also upgraded to latest VS preview and ran workload install for both wasm-tools and wam-experimental tonight to get latest versions, rebooted, then created the new project in VS:

RejectionIsNoodles.zip

pavelsavara added a commit to pavelsavara/runtime that referenced this issue May 22, 2024
@dotnet-policy-service dotnet-policy-service bot removed the untriaged New issue has not been triaged by the area owner label May 22, 2024
@pavelsavara pavelsavara added this to the 9.0.0 milestone May 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
arch-wasm WebAssembly architecture area-System.Runtime.InteropServices.JavaScript os-browser Browser variant of arch-wasm
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants