From 50115517b4e0659cdce99f648cd0be060b938620 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Mon, 19 Aug 2024 15:53:11 +0200 Subject: [PATCH 01/11] test pollable clock too --- src/mono/sample/wasi/http-p2/Program.cs | 3 ++- src/mono/wasi/testassets/Http.cs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/mono/sample/wasi/http-p2/Program.cs b/src/mono/sample/wasi/http-p2/Program.cs index 98df1a50a0537..d6637f711e578 100644 --- a/src/mono/sample/wasi/http-p2/Program.cs +++ b/src/mono/sample/wasi/http-p2/Program.cs @@ -13,8 +13,9 @@ public static class WasiMainWrapper { public static async Task MainAsync(string[] args) { + await Task.Delay(100); + using HttpClient client = new(); - client.Timeout = Timeout.InfiniteTimeSpan; client.DefaultRequestHeaders.Accept.Clear(); client.DefaultRequestHeaders.Add("User-Agent", "dotnet WASI unit test"); diff --git a/src/mono/wasi/testassets/Http.cs b/src/mono/wasi/testassets/Http.cs index d8043bf017ca7..8b9a95b1f7f6e 100644 --- a/src/mono/wasi/testassets/Http.cs +++ b/src/mono/wasi/testassets/Http.cs @@ -17,8 +17,9 @@ public static async Task MainAsync(string[] args) for (int i = 0; i < args.Length; i ++) Console.WriteLine($"args[{i}] = {args[i]}"); + await Task.Delay(100); + using HttpClient client = new(); - client.Timeout = Timeout.InfiniteTimeSpan; client.DefaultRequestHeaders.Accept.Clear(); client.DefaultRequestHeaders.Add("User-Agent", "dotnet WASI unit test"); From 5e260b52776906a92d98973c57e1ab4896ed88b0 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Wed, 21 Aug 2024 12:25:12 +0200 Subject: [PATCH 02/11] re-generate --- .../Net/Http/WasiHttpHandler/WasiHttp.cs | 2 +- ...asi.clocks.v0_2_1.MonotonicClockInterop.cs | 2 +- ...rld.wit.imports.wasi.http.v0_2_1.ITypes.cs | 2 +- ...wasi.http.v0_2_1.OutgoingHandlerInterop.cs | 2 +- ...t.imports.wasi.http.v0_2_1.TypesInterop.cs | 2 +- ...wit.imports.wasi.io.v0_2_1.ErrorInterop.cs | 2 +- ...World.wit.imports.wasi.io.v0_2_1.IError.cs | 2 +- ...pWorld.wit.imports.wasi.io.v0_2_1.IPoll.cs | 2 +- ...rld.wit.imports.wasi.io.v0_2_1.IStreams.cs | 2 +- ....wit.imports.wasi.io.v0_2_1.PollInterop.cs | 2 +- ...t.imports.wasi.io.v0_2_1.StreamsInterop.cs | 2 +- .../generate-wasi-http-bindings.ps1 | 21 +++++++++++++++++++ .../generate-wasi-http-bindings.sh | 12 ++++------- .../System/Net/Http/WasiHttpHandler/world.wit | 3 +++ .../src/System/Threading/Wasi/WasiPoll.cs | 2 +- ...asi.clocks.v0_2_1.MonotonicClockInterop.cs | 2 +- ...lWorld.wit.imports.wasi.io.v0_2_1.IPoll.cs | 2 +- ....wit.imports.wasi.io.v0_2_1.PollInterop.cs | 2 +- .../Wasi/generate-wasi-poll-bindings.ps1 | 21 +++++++++++++++++++ .../Wasi/generate-wasi-poll-bindings.sh | 2 +- .../src/System/Threading/Wasi/world.wit | 4 ++++ 21 files changed, 69 insertions(+), 24 deletions(-) create mode 100644 src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/generate-wasi-http-bindings.ps1 create mode 100644 src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/world.wit create mode 100644 src/libraries/System.Private.CoreLib/src/System/Threading/Wasi/generate-wasi-poll-bindings.ps1 create mode 100644 src/libraries/System.Private.CoreLib/src/System/Threading/Wasi/world.wit diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/WasiHttp.cs b/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/WasiHttp.cs index 67ec0a4b7c8dc..db7224a70342d 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/WasiHttp.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/WasiHttp.cs @@ -1,4 +1,4 @@ -// Generated by `wit-bindgen` 0.29.0. DO NOT EDIT! +// Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! // #nullable enable using System; diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/WasiHttpWorld.wit.imports.wasi.clocks.v0_2_1.MonotonicClockInterop.cs b/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/WasiHttpWorld.wit.imports.wasi.clocks.v0_2_1.MonotonicClockInterop.cs index 1de0ee2b24744..4eef64ee389e5 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/WasiHttpWorld.wit.imports.wasi.clocks.v0_2_1.MonotonicClockInterop.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/WasiHttpWorld.wit.imports.wasi.clocks.v0_2_1.MonotonicClockInterop.cs @@ -1,4 +1,4 @@ -// Generated by `wit-bindgen` 0.29.0. DO NOT EDIT! +// Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! // #nullable enable diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/WasiHttpWorld.wit.imports.wasi.http.v0_2_1.ITypes.cs b/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/WasiHttpWorld.wit.imports.wasi.http.v0_2_1.ITypes.cs index ed00640bb855e..b65506f194c44 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/WasiHttpWorld.wit.imports.wasi.http.v0_2_1.ITypes.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/WasiHttpWorld.wit.imports.wasi.http.v0_2_1.ITypes.cs @@ -1,4 +1,4 @@ -// Generated by `wit-bindgen` 0.29.0. DO NOT EDIT! +// Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! // #nullable enable diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/WasiHttpWorld.wit.imports.wasi.http.v0_2_1.OutgoingHandlerInterop.cs b/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/WasiHttpWorld.wit.imports.wasi.http.v0_2_1.OutgoingHandlerInterop.cs index 10aba859a4ba5..77435d5b2c7f2 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/WasiHttpWorld.wit.imports.wasi.http.v0_2_1.OutgoingHandlerInterop.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/WasiHttpWorld.wit.imports.wasi.http.v0_2_1.OutgoingHandlerInterop.cs @@ -1,4 +1,4 @@ -// Generated by `wit-bindgen` 0.29.0. DO NOT EDIT! +// Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! // #nullable enable diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/WasiHttpWorld.wit.imports.wasi.http.v0_2_1.TypesInterop.cs b/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/WasiHttpWorld.wit.imports.wasi.http.v0_2_1.TypesInterop.cs index 121f6cfdd5035..8a5802302e148 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/WasiHttpWorld.wit.imports.wasi.http.v0_2_1.TypesInterop.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/WasiHttpWorld.wit.imports.wasi.http.v0_2_1.TypesInterop.cs @@ -1,4 +1,4 @@ -// Generated by `wit-bindgen` 0.29.0. DO NOT EDIT! +// Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! // #nullable enable diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/WasiHttpWorld.wit.imports.wasi.io.v0_2_1.ErrorInterop.cs b/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/WasiHttpWorld.wit.imports.wasi.io.v0_2_1.ErrorInterop.cs index 2c3246555fcc2..a395aa89033fb 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/WasiHttpWorld.wit.imports.wasi.io.v0_2_1.ErrorInterop.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/WasiHttpWorld.wit.imports.wasi.io.v0_2_1.ErrorInterop.cs @@ -1,4 +1,4 @@ -// Generated by `wit-bindgen` 0.29.0. DO NOT EDIT! +// Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! // #nullable enable diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/WasiHttpWorld.wit.imports.wasi.io.v0_2_1.IError.cs b/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/WasiHttpWorld.wit.imports.wasi.io.v0_2_1.IError.cs index 3621e1c1fd372..be423962894b5 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/WasiHttpWorld.wit.imports.wasi.io.v0_2_1.IError.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/WasiHttpWorld.wit.imports.wasi.io.v0_2_1.IError.cs @@ -1,4 +1,4 @@ -// Generated by `wit-bindgen` 0.29.0. DO NOT EDIT! +// Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! // #nullable enable diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/WasiHttpWorld.wit.imports.wasi.io.v0_2_1.IPoll.cs b/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/WasiHttpWorld.wit.imports.wasi.io.v0_2_1.IPoll.cs index 0c4559fe841dd..b9116711bf03d 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/WasiHttpWorld.wit.imports.wasi.io.v0_2_1.IPoll.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/WasiHttpWorld.wit.imports.wasi.io.v0_2_1.IPoll.cs @@ -1,4 +1,4 @@ -// Generated by `wit-bindgen` 0.29.0. DO NOT EDIT! +// Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! // #nullable enable diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/WasiHttpWorld.wit.imports.wasi.io.v0_2_1.IStreams.cs b/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/WasiHttpWorld.wit.imports.wasi.io.v0_2_1.IStreams.cs index ab775cbfeb08a..737858ba97f5c 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/WasiHttpWorld.wit.imports.wasi.io.v0_2_1.IStreams.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/WasiHttpWorld.wit.imports.wasi.io.v0_2_1.IStreams.cs @@ -1,4 +1,4 @@ -// Generated by `wit-bindgen` 0.29.0. DO NOT EDIT! +// Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! // #nullable enable diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/WasiHttpWorld.wit.imports.wasi.io.v0_2_1.PollInterop.cs b/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/WasiHttpWorld.wit.imports.wasi.io.v0_2_1.PollInterop.cs index 4c48ffe69e2f9..01157399463dd 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/WasiHttpWorld.wit.imports.wasi.io.v0_2_1.PollInterop.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/WasiHttpWorld.wit.imports.wasi.io.v0_2_1.PollInterop.cs @@ -1,4 +1,4 @@ -// Generated by `wit-bindgen` 0.29.0. DO NOT EDIT! +// Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! // #nullable enable diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/WasiHttpWorld.wit.imports.wasi.io.v0_2_1.StreamsInterop.cs b/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/WasiHttpWorld.wit.imports.wasi.io.v0_2_1.StreamsInterop.cs index 7d479e6b160c4..1e2ade74bb38c 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/WasiHttpWorld.wit.imports.wasi.io.v0_2_1.StreamsInterop.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/WasiHttpWorld.wit.imports.wasi.io.v0_2_1.StreamsInterop.cs @@ -1,4 +1,4 @@ -// Generated by `wit-bindgen` 0.29.0. DO NOT EDIT! +// Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! // #nullable enable diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/generate-wasi-http-bindings.ps1 b/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/generate-wasi-http-bindings.ps1 new file mode 100644 index 0000000000000..b57834c224208 --- /dev/null +++ b/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/generate-wasi-http-bindings.ps1 @@ -0,0 +1,21 @@ +# Prerequisites: +# powershell +# tar +# [cargo](https://rustup.rs/) +$ProgressPreference = 'SilentlyContinue' +$ErrorActionPreference='Stop' +$scriptpath = $MyInvocation.MyCommand.Path +$dir = Split-Path $scriptpath + +Push-Location $dir + + +cargo install --locked --no-default-features --features csharp --version 0.30.0 wit-bindgen-cli +Invoke-WebRequest -Uri https://github.com/WebAssembly/wasi-http/archive/refs/tags/v0.2.1.tar.gz -OutFile v0.2.1.tar.gz +tar xzf v0.2.1.tar.gz +cp world.wit wasi-http-0.2.1/wit/world.wit +wit-bindgen c-sharp -w wasi-http -r native-aot --internal --skip-support-files wasi-http-0.2.1/wit +rm -r wasi-http-0.2.1 +rm v0.2.1.tar.gz + +Pop-Location diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/generate-wasi-http-bindings.sh b/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/generate-wasi-http-bindings.sh index f4bc2b72ef74d..f79fdbc61bd83 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/generate-wasi-http-bindings.sh +++ b/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/generate-wasi-http-bindings.sh @@ -11,13 +11,9 @@ set -ex # [cargo](https://rustup.rs/) # [curl](https://curl.se/download.html) -cargo install --locked --no-default-features --features csharp --version 0.29.0 wit-bindgen-cli +cargo install --locked --no-default-features --features csharp --version 0.30.0 wit-bindgen-cli curl -OL https://github.com/WebAssembly/wasi-http/archive/refs/tags/v0.2.1.tar.gz tar xzf v0.2.1.tar.gz -cat >wasi-http-0.2.1/wit/world.wit < #nullable enable using System; diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Wasi/WasiPollWorld.wit.imports.wasi.clocks.v0_2_1.MonotonicClockInterop.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Wasi/WasiPollWorld.wit.imports.wasi.clocks.v0_2_1.MonotonicClockInterop.cs index 1a0ef026540eb..b3c646e7e4bb8 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Wasi/WasiPollWorld.wit.imports.wasi.clocks.v0_2_1.MonotonicClockInterop.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Wasi/WasiPollWorld.wit.imports.wasi.clocks.v0_2_1.MonotonicClockInterop.cs @@ -1,4 +1,4 @@ -// Generated by `wit-bindgen` 0.29.0. DO NOT EDIT! +// Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! // #nullable enable diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Wasi/WasiPollWorld.wit.imports.wasi.io.v0_2_1.IPoll.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Wasi/WasiPollWorld.wit.imports.wasi.io.v0_2_1.IPoll.cs index 8ad5cabf64b6a..fd8a827304a91 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Wasi/WasiPollWorld.wit.imports.wasi.io.v0_2_1.IPoll.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Wasi/WasiPollWorld.wit.imports.wasi.io.v0_2_1.IPoll.cs @@ -1,4 +1,4 @@ -// Generated by `wit-bindgen` 0.29.0. DO NOT EDIT! +// Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! // #nullable enable diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Wasi/WasiPollWorld.wit.imports.wasi.io.v0_2_1.PollInterop.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Wasi/WasiPollWorld.wit.imports.wasi.io.v0_2_1.PollInterop.cs index dc01e87574900..c403ef10d1ff2 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Wasi/WasiPollWorld.wit.imports.wasi.io.v0_2_1.PollInterop.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Wasi/WasiPollWorld.wit.imports.wasi.io.v0_2_1.PollInterop.cs @@ -1,4 +1,4 @@ -// Generated by `wit-bindgen` 0.29.0. DO NOT EDIT! +// Generated by `wit-bindgen` 0.30.0. DO NOT EDIT! // #nullable enable diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Wasi/generate-wasi-poll-bindings.ps1 b/src/libraries/System.Private.CoreLib/src/System/Threading/Wasi/generate-wasi-poll-bindings.ps1 new file mode 100644 index 0000000000000..0a7cd7bebb722 --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Wasi/generate-wasi-poll-bindings.ps1 @@ -0,0 +1,21 @@ +# Prerequisites: +# powershell +# tar +# [cargo](https://rustup.rs/) +$ProgressPreference = 'SilentlyContinue' +$ErrorActionPreference='Stop' +$scriptpath = $MyInvocation.MyCommand.Path +$dir = Split-Path $scriptpath + +Push-Location $dir + + +cargo install --locked --no-default-features --features csharp --version 0.30.0 wit-bindgen-cli +Invoke-WebRequest -Uri https://github.com/WebAssembly/wasi-http/archive/refs/tags/v0.2.1.tar.gz -OutFile v0.2.1.tar.gz +tar xzf v0.2.1.tar.gz +cp world.wit wasi-http-0.2.1/wit/world.wit +wit-bindgen c-sharp -w wasi-poll -r native-aot --internal --skip-support-files wasi-http-0.2.1/wit +rm -r wasi-http-0.2.1 +rm v0.2.1.tar.gz + +Pop-Location diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Wasi/generate-wasi-poll-bindings.sh b/src/libraries/System.Private.CoreLib/src/System/Threading/Wasi/generate-wasi-poll-bindings.sh index fd20df8e9df20..f722aeaa668fb 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Wasi/generate-wasi-poll-bindings.sh +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Wasi/generate-wasi-poll-bindings.sh @@ -11,7 +11,7 @@ set -ex # [cargo](https://rustup.rs/) # [curl](https://curl.se/download.html) -cargo install --locked --no-default-features --features csharp --version 0.29.0 wit-bindgen-cli +cargo install --locked --no-default-features --features csharp --version 0.30.0 wit-bindgen-cli curl -OL https://github.com/WebAssembly/wasi-http/archive/refs/tags/v0.2.1.tar.gz tar xzf v0.2.1.tar.gz cat >wasi-http-0.2.1/wit/world.wit < Date: Wed, 21 Aug 2024 14:59:06 +0200 Subject: [PATCH 03/11] JCO sample --- src/mono/sample/wasi/Directory.Build.props | 6 + src/mono/sample/wasi/Directory.Build.targets | 25 +- src/mono/sample/wasi/jco/Program.cs | 41 + .../wasi/jco/Wasi.Jco.Http.Sample.csproj | 10 + src/mono/sample/wasi/jco/main.mjs | 3 + src/mono/sample/wasi/jco/package-lock.json | 735 ++++++++++++++++++ src/mono/sample/wasi/jco/package.json | 10 + 7 files changed, 826 insertions(+), 4 deletions(-) create mode 100644 src/mono/sample/wasi/jco/Program.cs create mode 100644 src/mono/sample/wasi/jco/Wasi.Jco.Http.Sample.csproj create mode 100644 src/mono/sample/wasi/jco/main.mjs create mode 100644 src/mono/sample/wasi/jco/package-lock.json create mode 100644 src/mono/sample/wasi/jco/package.json diff --git a/src/mono/sample/wasi/Directory.Build.props b/src/mono/sample/wasi/Directory.Build.props index 15caee9a376b6..ee0b4644bda9b 100644 --- a/src/mono/sample/wasi/Directory.Build.props +++ b/src/mono/sample/wasi/Directory.Build.props @@ -15,6 +15,12 @@ bin + <_ScriptExt Condition="'$(OS)' == 'Windows_NT'">.cmd + <_ScriptExt Condition="'$(OS)' != 'Windows_NT'">.sh + <_Dotnet>$(RepoRoot)dotnet$(_ScriptExt) + <_ExeExt Condition="$([MSBuild]::IsOSPlatform('WINDOWS'))">.exe + <_Nodejs>$(RepoRoot)node$(_ScriptExt) + <_Npm>$(RepoRoot)npm$(_ScriptExt) false diff --git a/src/mono/sample/wasi/Directory.Build.targets b/src/mono/sample/wasi/Directory.Build.targets index 8e098fca7e92f..90f89953129d7 100644 --- a/src/mono/sample/wasi/Directory.Build.targets +++ b/src/mono/sample/wasi/Directory.Build.targets @@ -8,7 +8,6 @@ <_SampleProjectName>$([System.String]::Copy('$(_SampleProject)').Replace('.csproj','')) <_MONO_LOG_LEVEL Condition="false">--env MONO_LOG_LEVEL=debug --env MONO_LOG_MASK=all <_DOTNET_WASI_PRINT_EXIT_CODE>--env DOTNET_WASI_PRINT_EXIT_CODE=1 - <_ExeExt Condition="$([MSBuild]::IsOSPlatform('WINDOWS'))">.exe - <_ScriptExt Condition="'$(OS)' == 'Windows_NT'">.cmd - <_ScriptExt Condition="'$(OS)' != 'Windows_NT'">.sh - <_Dotnet>$(RepoRoot)dotnet$(_ScriptExt) <_AOTFlag Condition="'$(RunAOTCompilation)' != ''">/p:RunAOTCompilation=$(RunAOTCompilation) @@ -55,5 +51,26 @@ IgnoreExitCode="true" /> + + + + + + + + + \ No newline at end of file diff --git a/src/mono/sample/wasi/jco/Program.cs b/src/mono/sample/wasi/jco/Program.cs new file mode 100644 index 0000000000000..d6637f711e578 --- /dev/null +++ b/src/mono/sample/wasi/jco/Program.cs @@ -0,0 +1,41 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Net.Http.Headers; +using System.Net.Http; +using System.Threading.Tasks; +using System.Threading; +using System.Runtime.CompilerServices; + +// keep in sync with src\mono\wasi\testassets\Http.cs +public static class WasiMainWrapper +{ + public static async Task MainAsync(string[] args) + { + await Task.Delay(100); + + using HttpClient client = new(); + client.DefaultRequestHeaders.Accept.Clear(); + client.DefaultRequestHeaders.Add("User-Agent", "dotnet WASI unit test"); + + var query="https://corefx-net-http11.azurewebsites.net/Echo.ashx"; + var json = await client.GetStringAsync(query); + + Console.WriteLine(); + Console.WriteLine("GET "+query); + Console.WriteLine(); + Console.WriteLine(json); + + return 0; + } + + public static int Main(string[] args) + { + return PollWasiEventLoopUntilResolved((Thread)null!, MainAsync(args)); + + [UnsafeAccessor(UnsafeAccessorKind.StaticMethod, Name = "PollWasiEventLoopUntilResolved")] + static extern int PollWasiEventLoopUntilResolved(Thread t, Task mainTask); + } + +} diff --git a/src/mono/sample/wasi/jco/Wasi.Jco.Http.Sample.csproj b/src/mono/sample/wasi/jco/Wasi.Jco.Http.Sample.csproj new file mode 100644 index 0000000000000..7fbbc7083e6b8 --- /dev/null +++ b/src/mono/sample/wasi/jco/Wasi.Jco.Http.Sample.csproj @@ -0,0 +1,10 @@ + + + $(NetCoreAppCurrent) + <_WasiNeedsHttp>true + true + true + + + + diff --git a/src/mono/sample/wasi/jco/main.mjs b/src/mono/sample/wasi/jco/main.mjs new file mode 100644 index 0000000000000..c697950452303 --- /dev/null +++ b/src/mono/sample/wasi/jco/main.mjs @@ -0,0 +1,3 @@ +import { run } from './Wasi.Jco.Http.Sample.js'; + +run.run(); diff --git a/src/mono/sample/wasi/jco/package-lock.json b/src/mono/sample/wasi/jco/package-lock.json new file mode 100644 index 0000000000000..9bbfebc77607f --- /dev/null +++ b/src/mono/sample/wasi/jco/package-lock.json @@ -0,0 +1,735 @@ +{ + "name": "jco", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "devDependencies": { + "@bytecodealliance/jco": "^1.4.4" + } + }, + "node_modules/@bytecodealliance/jco": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/@bytecodealliance/jco/-/jco-1.4.4.tgz", + "integrity": "sha512-Gu9VzU99rptKnRgx1KSMUIy56BoVWy6uKCoKZwLL+nvEM9kSLtvEp2CLSSnpOxXaFIpTLhmNhSu7j8h965C8zw==", + "dev": true, + "dependencies": { + "@bytecodealliance/preview2-shim": "^0.16.5", + "binaryen": "^118.0.0", + "chalk-template": "^1", + "commander": "^12", + "mkdirp": "^3", + "ora": "^8", + "terser": "^5" + }, + "bin": { + "jco": "src/jco.js" + } + }, + "node_modules/@bytecodealliance/preview2-shim": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@bytecodealliance/preview2-shim/-/preview2-shim-0.16.5.tgz", + "integrity": "sha512-1YThPyZ/gWZBgmJ3nEsnBXLxgSV3VOW3vLfyxe/RTKk9fWkTKaUouuZHWBvP0aFN7Hnat733rUeSYAUjEUNONQ==", + "dev": true + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/acorn": { + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/binaryen": { + "version": "118.0.0", + "resolved": "https://registry.npmjs.org/binaryen/-/binaryen-118.0.0.tgz", + "integrity": "sha512-KzekjPjpLE1zk29BKQSHNWLSHPYAfa80lcsIi5bDnev8vyfDyiMCVFPjaplhfXIKs7LI3r1RPyhoAj4qsRQwwg==", + "dev": true, + "bin": { + "wasm-as": "bin/wasm-as", + "wasm-ctor-eval": "bin/wasm-ctor-eval", + "wasm-dis": "bin/wasm-dis", + "wasm-merge": "bin/wasm-merge", + "wasm-metadce": "bin/wasm-metadce", + "wasm-opt": "bin/wasm-opt", + "wasm-reduce": "bin/wasm-reduce", + "wasm-shell": "bin/wasm-shell", + "wasm2js": "bin/wasm2js" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "dev": true, + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk-template": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/chalk-template/-/chalk-template-1.1.0.tgz", + "integrity": "sha512-T2VJbcDuZQ0Tb2EWwSotMPJjgpy1/tGee1BTpUNsGZ/qgNjV2t7Mvu+d4600U564nbLesN1x2dPL+xii174Ekg==", + "dev": true, + "dependencies": { + "chalk": "^5.2.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/chalk/chalk-template?sponsor=1" + } + }, + "node_modules/cli-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", + "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", + "dev": true, + "dependencies": { + "restore-cursor": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "dev": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/emoji-regex": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", + "dev": true + }, + "node_modules/get-east-asian-width": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz", + "integrity": "sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-interactive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", + "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-unicode-supported": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.0.0.tgz", + "integrity": "sha512-FRdAyx5lusK1iHG0TWpVtk9+1i+GjrzRffhDg4ovQ7mcidMQ6mj+MhKPmvh7Xwyv5gIS06ns49CA7Sqg7lC22Q==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-symbols": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-6.0.0.tgz", + "integrity": "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==", + "dev": true, + "dependencies": { + "chalk": "^5.3.0", + "is-unicode-supported": "^1.3.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-symbols/node_modules/is-unicode-supported": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", + "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/mkdirp": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", + "dev": true, + "bin": { + "mkdirp": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-8.0.1.tgz", + "integrity": "sha512-ANIvzobt1rls2BDny5fWZ3ZVKyD6nscLvfFRpQgfWsythlcsVUC9kL0zq6j2Z5z9wwp1kd7wpsD/T9qNPVLCaQ==", + "dev": true, + "dependencies": { + "chalk": "^5.3.0", + "cli-cursor": "^4.0.0", + "cli-spinners": "^2.9.2", + "is-interactive": "^2.0.0", + "is-unicode-supported": "^2.0.0", + "log-symbols": "^6.0.0", + "stdin-discarder": "^0.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/restore-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", + "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "dev": true, + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/stdin-discarder": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.2.2.tgz", + "integrity": "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/terser": { + "version": "5.31.6", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.6.tgz", + "integrity": "sha512-PQ4DAriWzKj+qgehQ7LK5bQqCFNMmlhjR2PFFLuqGCpuCAauxemVBWwWOxo3UIwWQx8+Pr61Df++r76wDmkQBg==", + "dev": true, + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + } + }, + "dependencies": { + "@bytecodealliance/jco": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/@bytecodealliance/jco/-/jco-1.4.4.tgz", + "integrity": "sha512-Gu9VzU99rptKnRgx1KSMUIy56BoVWy6uKCoKZwLL+nvEM9kSLtvEp2CLSSnpOxXaFIpTLhmNhSu7j8h965C8zw==", + "dev": true, + "requires": { + "@bytecodealliance/preview2-shim": "^0.16.5", + "binaryen": "^118.0.0", + "chalk-template": "^1", + "commander": "^12", + "mkdirp": "^3", + "ora": "^8", + "terser": "^5" + } + }, + "@bytecodealliance/preview2-shim": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@bytecodealliance/preview2-shim/-/preview2-shim-0.16.5.tgz", + "integrity": "sha512-1YThPyZ/gWZBgmJ3nEsnBXLxgSV3VOW3vLfyxe/RTKk9fWkTKaUouuZHWBvP0aFN7Hnat733rUeSYAUjEUNONQ==", + "dev": true + }, + "@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true + }, + "@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true + }, + "@jridgewell/source-map": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true + }, + "@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "acorn": { + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "dev": true + }, + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true + }, + "binaryen": { + "version": "118.0.0", + "resolved": "https://registry.npmjs.org/binaryen/-/binaryen-118.0.0.tgz", + "integrity": "sha512-KzekjPjpLE1zk29BKQSHNWLSHPYAfa80lcsIi5bDnev8vyfDyiMCVFPjaplhfXIKs7LI3r1RPyhoAj4qsRQwwg==", + "dev": true + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "dev": true + }, + "chalk-template": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/chalk-template/-/chalk-template-1.1.0.tgz", + "integrity": "sha512-T2VJbcDuZQ0Tb2EWwSotMPJjgpy1/tGee1BTpUNsGZ/qgNjV2t7Mvu+d4600U564nbLesN1x2dPL+xii174Ekg==", + "dev": true, + "requires": { + "chalk": "^5.2.0" + } + }, + "cli-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", + "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", + "dev": true, + "requires": { + "restore-cursor": "^4.0.0" + } + }, + "cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "dev": true + }, + "commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "dev": true + }, + "emoji-regex": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", + "dev": true + }, + "get-east-asian-width": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz", + "integrity": "sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==", + "dev": true + }, + "is-interactive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", + "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", + "dev": true + }, + "is-unicode-supported": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.0.0.tgz", + "integrity": "sha512-FRdAyx5lusK1iHG0TWpVtk9+1i+GjrzRffhDg4ovQ7mcidMQ6mj+MhKPmvh7Xwyv5gIS06ns49CA7Sqg7lC22Q==", + "dev": true + }, + "log-symbols": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-6.0.0.tgz", + "integrity": "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==", + "dev": true, + "requires": { + "chalk": "^5.3.0", + "is-unicode-supported": "^1.3.0" + }, + "dependencies": { + "is-unicode-supported": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", + "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", + "dev": true + } + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "mkdirp": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", + "dev": true + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "ora": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-8.0.1.tgz", + "integrity": "sha512-ANIvzobt1rls2BDny5fWZ3ZVKyD6nscLvfFRpQgfWsythlcsVUC9kL0zq6j2Z5z9wwp1kd7wpsD/T9qNPVLCaQ==", + "dev": true, + "requires": { + "chalk": "^5.3.0", + "cli-cursor": "^4.0.0", + "cli-spinners": "^2.9.2", + "is-interactive": "^2.0.0", + "is-unicode-supported": "^2.0.0", + "log-symbols": "^6.0.0", + "stdin-discarder": "^0.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + } + }, + "restore-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", + "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "dev": true, + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "stdin-discarder": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.2.2.tgz", + "integrity": "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==", + "dev": true + }, + "string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "requires": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + } + }, + "strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "requires": { + "ansi-regex": "^6.0.1" + } + }, + "terser": { + "version": "5.31.6", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.6.tgz", + "integrity": "sha512-PQ4DAriWzKj+qgehQ7LK5bQqCFNMmlhjR2PFFLuqGCpuCAauxemVBWwWOxo3UIwWQx8+Pr61Df++r76wDmkQBg==", + "dev": true, + "requires": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + } + } + } + } +} diff --git a/src/mono/sample/wasi/jco/package.json b/src/mono/sample/wasi/jco/package.json new file mode 100644 index 0000000000000..696f416110653 --- /dev/null +++ b/src/mono/sample/wasi/jco/package.json @@ -0,0 +1,10 @@ +{ + "type": "module", + "devDependencies": { + "@bytecodealliance/jco": "1.4.4" + }, + "scripts": { + "transpile": "npx jco transpile --no-typescript bin/wasi-wasm/AppBundle/Wasi.Jco.Http.Sample.wasm -o bin/wasi-wasm/JCOBundle/ && powershell cp ./main.mjs ./bin/wasi-wasm/JCOBundle/main.mjs", + "run": "node bin/wasi-wasm/JCOBundle/main.mjs" + } +} \ No newline at end of file From 3594b873ea5ff7e779feb78ec770012d9bc6f297 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Wed, 21 Aug 2024 18:48:57 +0200 Subject: [PATCH 04/11] - CancellationToken - Pollable lifetime by lifetime of the Task --- .../Http/WasiHttpHandler/WasiHttpHandler.cs | 17 +-- .../src/System/Threading/Thread.Unix.cs | 4 +- .../System/Threading/Wasi/WasiEventLoop.cs | 129 +++++++++++++----- .../System/Threading/TimerQueue.Wasi.Mono.cs | 2 +- 4 files changed, 106 insertions(+), 46 deletions(-) diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/WasiHttpHandler.cs b/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/WasiHttpHandler.cs index dcccb98991096..8d9abb2d433b5 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/WasiHttpHandler.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/WasiHttpHandler.cs @@ -242,7 +242,7 @@ CancellationToken cancellationToken await Task.WhenAll( new Task[] { - SendRequestAsync(outgoingRequest), + SendRequestAsync(outgoingRequest, cancellationToken), sendContent() } ) @@ -279,7 +279,8 @@ await Task.WhenAll( } private static async Task SendRequestAsync( - ITypes.OutgoingRequest request + ITypes.OutgoingRequest request, + CancellationToken cancellationToken ) { ITypes.FutureIncomingResponse future; @@ -314,7 +315,7 @@ ITypes.OutgoingRequest request } else { - await RegisterWasiPollable(future.Subscribe()).ConfigureAwait(false); + await RegisterWasiPollable(future.Subscribe(), cancellationToken).ConfigureAwait(false); } } } @@ -461,7 +462,7 @@ private static async Task SendContentAsync(HttpContent? content, Stream stream) } } - private static Task RegisterWasiPollable(IPoll.Pollable pollable) + private static Task RegisterWasiPollable(IPoll.Pollable pollable, CancellationToken cancellationToken) { var handle = pollable.Handle; @@ -470,12 +471,12 @@ private static Task RegisterWasiPollable(IPoll.Pollable pollable) pollable.Handle = 0; GC.SuppressFinalize(pollable); - return CallRegisterWasiPollableHandle((Thread)null!, handle); + return CallRegisterWasiPollableHandle((Thread)null!, handle, cancellationToken); } [UnsafeAccessor(UnsafeAccessorKind.StaticMethod, Name = "RegisterWasiPollableHandle")] - private static extern Task CallRegisterWasiPollableHandle(Thread t, int handle); + private static extern Task CallRegisterWasiPollableHandle(Thread t, int handle, CancellationToken cancellationToken); private sealed class InputStream : Stream { @@ -562,7 +563,7 @@ CancellationToken cancellationToken var buffer = result; if (buffer.Length == 0) { - await RegisterWasiPollable(stream.Subscribe()) + await RegisterWasiPollable(stream.Subscribe(), cancellationToken) .ConfigureAwait(false); } else @@ -699,7 +700,7 @@ CancellationToken cancellationToken var count = (int)stream.CheckWrite(); if (count == 0) { - await RegisterWasiPollable(stream.Subscribe()).ConfigureAwait(false); + await RegisterWasiPollable(stream.Subscribe(), cancellationToken).ConfigureAwait(false); } else if (offset == limit) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Thread.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Thread.Unix.cs index 359c889c975b8..a3302b3bedc38 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Thread.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Thread.Unix.cs @@ -13,9 +13,9 @@ public sealed partial class Thread { // these methods are temporarily accessed via UnsafeAccessor from generated code until we have it in public API, probably in WASI preview3 and promises #if TARGET_WASI - internal static System.Threading.Tasks.Task RegisterWasiPollableHandle(int handle) + internal static System.Threading.Tasks.Task RegisterWasiPollableHandle(int handle, CancellationToken cancellationToken) { - return WasiEventLoop.RegisterWasiPollableHandle(handle); + return WasiEventLoop.RegisterWasiPollableHandle(handle, cancellationToken); } internal static int PollWasiEventLoopUntilResolved(Task mainTask) diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Wasi/WasiEventLoop.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Wasi/WasiEventLoop.cs index 379c5c001c08a..f26bcf5ce2f99 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Wasi/WasiEventLoop.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Wasi/WasiEventLoop.cs @@ -4,72 +4,131 @@ using System.Collections.Generic; using System.Threading.Tasks; using WasiPollWorld.wit.imports.wasi.io.v0_2_1; +using Pollable = WasiPollWorld.wit.imports.wasi.io.v0_2_1.IPoll.Pollable; namespace System.Threading { internal static class WasiEventLoop { - private static List> s_pollables = new(); + private static readonly List> s_weakRefHolders = new(); - internal static Task RegisterWasiPollableHandle(int handle) + internal static Task RegisterWasiPollableHandle(int handle, CancellationToken cancellationToken) { // note that this is duplicate of the original Pollable - // the original should be neutralized without disposing the handle - var pollableCpy = new IPoll.Pollable(new IPoll.Pollable.THandle(handle)); - return RegisterWasiPollable(pollableCpy); + // the original should have been neutralized without disposing the handle + var pollableCpy = new Pollable(new Pollable.THandle(handle)); + return RegisterWasiPollable(pollableCpy, cancellationToken); } - internal static Task RegisterWasiPollable(IPoll.Pollable pollable) + internal static Task RegisterWasiPollable(Pollable pollable, CancellationToken cancellationToken) { - var tcs = new TaskCompletionSource(pollable); - var weakRef = new WeakReference(tcs); - s_pollables.Add(weakRef); - return tcs.Task; + // this will register the pollable holder into s_pollables + var holder = new PollableHolder(pollable, cancellationToken); + s_weakRefHolders.Add(holder.selfWeakRef); + return holder.taskCompletionSource.Task; } + // this is not thread safe internal static void DispatchWasiEventLoop() { ThreadPoolWorkQueue.Dispatch(); - if (s_pollables.Count > 0) + var holders = new List(s_weakRefHolders.Count); + var pending = new List(s_weakRefHolders.Count); + for (int i = 0; i < s_weakRefHolders.Count; i++) { - var pollables = s_pollables; - s_pollables = new List>(pollables.Count); - var arguments = new List(pollables.Count); - var indexes = new List(pollables.Count); - for (var i = 0; i < pollables.Count; i++) + var weakRef = s_weakRefHolders[i]; + if (weakRef.TryGetTarget(out var holder)) { - var weakRef = pollables[i]; - if (weakRef.TryGetTarget(out TaskCompletionSource? tcs)) + if (!holder.isDisposed) { - var pollable = (IPoll.Pollable)tcs!.Task.AsyncState!; - arguments.Add(pollable); - indexes.Add(i); + holders.Add(holder); + pending.Add(holder.pollable); } } + } - // this is blocking until at least one pollable resolves - var readyIndexes = PollInterop.Poll(arguments); + s_weakRefHolders.Clear(); - var ready = new bool[arguments.Count]; - foreach (int readyIndex in readyIndexes) + if (pending.Count > 0) + { + var readyIndexes = PollInterop.Poll(pending); + for (int i = 0; i < readyIndexes.Length; i++) { - ready[readyIndex] = true; - arguments[readyIndex].Dispose(); - var weakRef = pollables[indexes[readyIndex]]; - if (weakRef.TryGetTarget(out TaskCompletionSource? tcs)) - { - tcs!.SetResult(); - } + uint readyIndex = readyIndexes[i]; + var holder = holders[(int)readyIndex]; + holder.ResolveAndDispose(); } - for (var i = 0; i < arguments.Count; ++i) + for (int i = 0; i < holders.Count; i++) { - if (!ready[i]) + PollableHolder holder = holders[i]; + if (!holder.isDisposed) { - s_pollables.Add(pollables[indexes[i]]); + s_weakRefHolders.Add(holder.selfWeakRef); } } } } + + private sealed class PollableHolder + { + public bool isDisposed; + public readonly Pollable pollable; + public readonly TaskCompletionSource taskCompletionSource; + public readonly WeakReference selfWeakRef; + public readonly CancellationTokenRegistration cancellationTokenRegistration; + + public PollableHolder(Pollable pollable, CancellationToken cancellationToken) + { + this.pollable = pollable; + + // this means that taskCompletionSource.Task.AsyncState -> this; + // which means PollableHolder will be alive until the Task alive + taskCompletionSource = new TaskCompletionSource(this); + + // static method is used to avoid allocating a delegate + cancellationTokenRegistration = cancellationToken.Register(CancelAndDispose, this); + + // don't allocate it for each re-registration + selfWeakRef = new WeakReference(this); + } + + public void ResolveAndDispose() + { + if (isDisposed) + { + return; + } + + // no need to unregister the holder from s_pollables, when this is called + isDisposed = true; + taskCompletionSource.TrySetResult(); + pollable.Dispose(); + cancellationTokenRegistration.Dispose(); + GC.SuppressFinalize(this); + } + + // for GC of abandoned Tasks or for cancellation + private static void CancelAndDispose(object? s) + { + PollableHolder self = (PollableHolder)s!; + if (self.isDisposed) + { + return; + } + + // it will be removed from s_pollables on the next run + self.isDisposed = true; + self.taskCompletionSource.TrySetCanceled(); + self.pollable.Dispose(); + self.cancellationTokenRegistration.Dispose(); + GC.SuppressFinalize(self); + } + + ~PollableHolder() + { + CancelAndDispose(this); + } + } } } diff --git a/src/mono/System.Private.CoreLib/src/System/Threading/TimerQueue.Wasi.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Threading/TimerQueue.Wasi.Mono.cs index 20c017cce1fe1..89a150780444d 100644 --- a/src/mono/System.Private.CoreLib/src/System/Threading/TimerQueue.Wasi.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Threading/TimerQueue.Wasi.Mono.cs @@ -81,7 +81,7 @@ private static unsafe void SetNextTimer(long shortestDueTimeMs, long currentTime // `SubscribeDuration` expects nanoseconds: var pollable = MonotonicClockInterop.SubscribeDuration(shortestWaitMs * 1000 * 1000); - Task task = WasiEventLoop.RegisterWasiPollable(pollable); + Task task = WasiEventLoop.RegisterWasiPollable(pollable, CancellationToken.None); task.ContinueWith(TimerHandler, TaskScheduler.Default); } } From 5154353d33cbb6275b866173305c822899ff1d3d Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Mon, 26 Aug 2024 15:13:06 +0200 Subject: [PATCH 05/11] test GC of Pollable->Task --- src/mono/sample/wasi/http-p2/Program.cs | 2 ++ src/mono/wasi/testassets/Http.cs | 3 +++ 2 files changed, 5 insertions(+) diff --git a/src/mono/sample/wasi/http-p2/Program.cs b/src/mono/sample/wasi/http-p2/Program.cs index d6637f711e578..50ca4b773c7b2 100644 --- a/src/mono/sample/wasi/http-p2/Program.cs +++ b/src/mono/sample/wasi/http-p2/Program.cs @@ -14,6 +14,7 @@ public static class WasiMainWrapper public static async Task MainAsync(string[] args) { await Task.Delay(100); + GC.Collect(); // test that Pollable->Task is not collected until resolved using HttpClient client = new(); client.DefaultRequestHeaders.Accept.Clear(); @@ -27,6 +28,7 @@ public static async Task MainAsync(string[] args) Console.WriteLine(); Console.WriteLine(json); + GC.Collect(); return 0; } diff --git a/src/mono/wasi/testassets/Http.cs b/src/mono/wasi/testassets/Http.cs index 8b9a95b1f7f6e..2886e6a06c597 100644 --- a/src/mono/wasi/testassets/Http.cs +++ b/src/mono/wasi/testassets/Http.cs @@ -18,6 +18,7 @@ public static async Task MainAsync(string[] args) Console.WriteLine($"args[{i}] = {args[i]}"); await Task.Delay(100); + GC.Collect(); // test that Pollable->Task is not collected until resolved using HttpClient client = new(); client.DefaultRequestHeaders.Accept.Clear(); @@ -31,6 +32,8 @@ public static async Task MainAsync(string[] args) Console.WriteLine(); Console.WriteLine(json); + GC.Collect(); + return 42; } From 0e6f86c052d35d3cb92fbcd514a6d73bb8893074 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Mon, 26 Aug 2024 15:37:57 +0200 Subject: [PATCH 06/11] WasiEventLoop to keep Pollable->Task alive from GC --- .../System/Threading/Wasi/WasiEventLoop.cs | 39 +++++++------------ 1 file changed, 14 insertions(+), 25 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Wasi/WasiEventLoop.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Wasi/WasiEventLoop.cs index f26bcf5ce2f99..921cc9a99795e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Wasi/WasiEventLoop.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Wasi/WasiEventLoop.cs @@ -10,7 +10,10 @@ namespace System.Threading { internal static class WasiEventLoop { - private static readonly List> s_weakRefHolders = new(); + // TODO: if the Pollable never resolves and and the Task is abandoned + // it will be leaked and stay in this list forever. + // it will also keep the Pollable handle alive and prevent it from being disposed + private static readonly List s_pollables = new(); internal static Task RegisterWasiPollableHandle(int handle, CancellationToken cancellationToken) { @@ -24,7 +27,7 @@ internal static Task RegisterWasiPollable(Pollable pollable, CancellationToken c { // this will register the pollable holder into s_pollables var holder = new PollableHolder(pollable, cancellationToken); - s_weakRefHolders.Add(holder.selfWeakRef); + s_pollables.Add(holder); return holder.taskCompletionSource.Task; } @@ -33,22 +36,19 @@ internal static void DispatchWasiEventLoop() { ThreadPoolWorkQueue.Dispatch(); - var holders = new List(s_weakRefHolders.Count); - var pending = new List(s_weakRefHolders.Count); - for (int i = 0; i < s_weakRefHolders.Count; i++) + var holders = new List(s_pollables.Count); + var pending = new List(s_pollables.Count); + for (int i = 0; i < s_pollables.Count; i++) { - var weakRef = s_weakRefHolders[i]; - if (weakRef.TryGetTarget(out var holder)) + var holder = s_pollables[i]; + if (!holder.isDisposed) { - if (!holder.isDisposed) - { - holders.Add(holder); - pending.Add(holder.pollable); - } + holders.Add(holder); + pending.Add(holder.pollable); } } - s_weakRefHolders.Clear(); + s_pollables.Clear(); if (pending.Count > 0) { @@ -64,7 +64,7 @@ internal static void DispatchWasiEventLoop() PollableHolder holder = holders[i]; if (!holder.isDisposed) { - s_weakRefHolders.Add(holder.selfWeakRef); + s_pollables.Add(holder); } } } @@ -75,7 +75,6 @@ private sealed class PollableHolder public bool isDisposed; public readonly Pollable pollable; public readonly TaskCompletionSource taskCompletionSource; - public readonly WeakReference selfWeakRef; public readonly CancellationTokenRegistration cancellationTokenRegistration; public PollableHolder(Pollable pollable, CancellationToken cancellationToken) @@ -88,9 +87,6 @@ public PollableHolder(Pollable pollable, CancellationToken cancellationToken) // static method is used to avoid allocating a delegate cancellationTokenRegistration = cancellationToken.Register(CancelAndDispose, this); - - // don't allocate it for each re-registration - selfWeakRef = new WeakReference(this); } public void ResolveAndDispose() @@ -105,7 +101,6 @@ public void ResolveAndDispose() taskCompletionSource.TrySetResult(); pollable.Dispose(); cancellationTokenRegistration.Dispose(); - GC.SuppressFinalize(this); } // for GC of abandoned Tasks or for cancellation @@ -122,12 +117,6 @@ private static void CancelAndDispose(object? s) self.taskCompletionSource.TrySetCanceled(); self.pollable.Dispose(); self.cancellationTokenRegistration.Dispose(); - GC.SuppressFinalize(self); - } - - ~PollableHolder() - { - CancelAndDispose(this); } } } From f857f3631877d616aa75b233a1a512458fbe73c9 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Tue, 27 Aug 2024 11:59:45 +0200 Subject: [PATCH 07/11] feedback --- .../System/Threading/Wasi/generate-wasi-poll-bindings.sh | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Wasi/generate-wasi-poll-bindings.sh b/src/libraries/System.Private.CoreLib/src/System/Threading/Wasi/generate-wasi-poll-bindings.sh index f722aeaa668fb..bd32a739d8871 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Wasi/generate-wasi-poll-bindings.sh +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Wasi/generate-wasi-poll-bindings.sh @@ -14,11 +14,6 @@ set -ex cargo install --locked --no-default-features --features csharp --version 0.30.0 wit-bindgen-cli curl -OL https://github.com/WebAssembly/wasi-http/archive/refs/tags/v0.2.1.tar.gz tar xzf v0.2.1.tar.gz -cat >wasi-http-0.2.1/wit/world.wit < Date: Tue, 27 Aug 2024 15:51:32 +0200 Subject: [PATCH 08/11] more tests --- src/mono/sample/wasi/http-p2/Program.cs | 28 +++++++++++++++++++++++++ src/mono/wasi/testassets/Http.cs | 28 +++++++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/src/mono/sample/wasi/http-p2/Program.cs b/src/mono/sample/wasi/http-p2/Program.cs index 50ca4b773c7b2..d568afae02f15 100644 --- a/src/mono/sample/wasi/http-p2/Program.cs +++ b/src/mono/sample/wasi/http-p2/Program.cs @@ -16,6 +16,34 @@ public static async Task MainAsync(string[] args) await Task.Delay(100); GC.Collect(); // test that Pollable->Task is not collected until resolved + using HttpClient impatientClient = new(); + impatientClient.DefaultRequestHeaders.Add("User-Agent", "dotnet WASI unit test"); + impatientClient.Timeout = TimeSpan.FromMilliseconds(10); + try { + await impatientClient.GetAsync("https://corefx-net-http11.azurewebsites.net/Echo.ashx?delay10sec"); + throw new Exception("request should have timed out"); + } catch (TaskCanceledException) { + Console.WriteLine("1st impatientClient was canceled as expected"); + // The /slow-hello endpoint takes 10 seconds to return a + // response, whereas we've set a 100ms timeout, so this is + // expected. + } + + var cts = new CancellationTokenSource(10); + try { + await impatientClient.GetAsync("https://corefx-net-http11.azurewebsites.net/Echo.ashx?delay10sec", cts.Token); + throw new Exception("request should have timed out"); + } catch (TaskCanceledException tce) { + if (cts.Token != tce.CancellationToken) + { + throw new Exception("Different CancellationToken"); + } + Console.WriteLine("2nd impatientClient was canceled as expected"); + // The /slow-hello endpoint takes 10 seconds to return a + // response, whereas we've set a 100ms timeout, so this is + // expected. + } + using HttpClient client = new(); client.DefaultRequestHeaders.Accept.Clear(); client.DefaultRequestHeaders.Add("User-Agent", "dotnet WASI unit test"); diff --git a/src/mono/wasi/testassets/Http.cs b/src/mono/wasi/testassets/Http.cs index 2886e6a06c597..ae3b3e6a074d2 100644 --- a/src/mono/wasi/testassets/Http.cs +++ b/src/mono/wasi/testassets/Http.cs @@ -20,6 +20,34 @@ public static async Task MainAsync(string[] args) await Task.Delay(100); GC.Collect(); // test that Pollable->Task is not collected until resolved + using HttpClient impatientClient = new(); + impatientClient.DefaultRequestHeaders.Add("User-Agent", "dotnet WASI unit test"); + impatientClient.Timeout = TimeSpan.FromMilliseconds(10); + try { + await impatientClient.GetAsync("https://corefx-net-http11.azurewebsites.net/Echo.ashx?delay10sec"); + throw new Exception("request should have timed out"); + } catch (TaskCanceledException) { + Console.WriteLine("1st impatientClient was canceled as expected"); + // The /slow-hello endpoint takes 10 seconds to return a + // response, whereas we've set a 100ms timeout, so this is + // expected. + } + + var cts = new CancellationTokenSource(10); + try { + await impatientClient.GetAsync("https://corefx-net-http11.azurewebsites.net/Echo.ashx?delay10sec", cts.Token); + throw new Exception("request should have timed out"); + } catch (TaskCanceledException tce) { + if (cts.Token != tce.CancellationToken) + { + throw new Exception("Different CancellationToken"); + } + Console.WriteLine("2nd impatientClient was canceled as expected"); + // The /slow-hello endpoint takes 10 seconds to return a + // response, whereas we've set a 100ms timeout, so this is + // expected. + } + using HttpClient client = new(); client.DefaultRequestHeaders.Accept.Clear(); client.DefaultRequestHeaders.Add("User-Agent", "dotnet WASI unit test"); From d52387ee00a2de44e7c342c0ca16df226bc4b115 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Tue, 27 Aug 2024 15:58:28 +0200 Subject: [PATCH 09/11] comments --- src/mono/wasi/testassets/Http.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/mono/wasi/testassets/Http.cs b/src/mono/wasi/testassets/Http.cs index ae3b3e6a074d2..085efa92cabac 100644 --- a/src/mono/wasi/testassets/Http.cs +++ b/src/mono/wasi/testassets/Http.cs @@ -35,6 +35,9 @@ public static async Task MainAsync(string[] args) var cts = new CancellationTokenSource(10); try { + // in reality server side doesn't delay because it doesn't implement it. So 10ms is bit fragile. + // TODO: remove this once we have real WASI HTTP library unit tests with local server loop in Xharness. + // https://github.com/dotnet/xharness/pull/1244 await impatientClient.GetAsync("https://corefx-net-http11.azurewebsites.net/Echo.ashx?delay10sec", cts.Token); throw new Exception("request should have timed out"); } catch (TaskCanceledException tce) { From 7bedb3bc857da0e957eadcd79c373593687bb082 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Tue, 27 Aug 2024 16:09:14 +0200 Subject: [PATCH 10/11] more testing --- src/mono/sample/wasi/http-p2/Program.cs | 23 +++++++++++++++++------ src/mono/wasi/testassets/Http.cs | 20 ++++++++++++++------ 2 files changed, 31 insertions(+), 12 deletions(-) diff --git a/src/mono/sample/wasi/http-p2/Program.cs b/src/mono/sample/wasi/http-p2/Program.cs index d568afae02f15..9fe7bf29bb977 100644 --- a/src/mono/sample/wasi/http-p2/Program.cs +++ b/src/mono/sample/wasi/http-p2/Program.cs @@ -16,19 +16,33 @@ public static async Task MainAsync(string[] args) await Task.Delay(100); GC.Collect(); // test that Pollable->Task is not collected until resolved + var ctsDelay = new CancellationTokenSource(10); + try { + await Task.Delay(1000, ctsDelay.Token); + throw new Exception("delay should have timed out"); + } catch (TaskCanceledException tce) { + if (ctsDelay.Token != tce.CancellationToken) + { + throw new Exception("Different CancellationToken for delay"); + } + Console.WriteLine("impatient delay was canceled as expected"); + } + using HttpClient impatientClient = new(); impatientClient.DefaultRequestHeaders.Add("User-Agent", "dotnet WASI unit test"); impatientClient.Timeout = TimeSpan.FromMilliseconds(10); try { + // in reality server side doesn't delay because it doesn't implement it. So 10ms is bit fragile. + // TODO: remove this once we have real WASI HTTP library unit tests with local server loop in Xharness. + // https://github.com/dotnet/xharness/pull/1244 await impatientClient.GetAsync("https://corefx-net-http11.azurewebsites.net/Echo.ashx?delay10sec"); throw new Exception("request should have timed out"); } catch (TaskCanceledException) { Console.WriteLine("1st impatientClient was canceled as expected"); - // The /slow-hello endpoint takes 10 seconds to return a - // response, whereas we've set a 100ms timeout, so this is - // expected. } + GC.Collect(); + var cts = new CancellationTokenSource(10); try { await impatientClient.GetAsync("https://corefx-net-http11.azurewebsites.net/Echo.ashx?delay10sec", cts.Token); @@ -39,9 +53,6 @@ public static async Task MainAsync(string[] args) throw new Exception("Different CancellationToken"); } Console.WriteLine("2nd impatientClient was canceled as expected"); - // The /slow-hello endpoint takes 10 seconds to return a - // response, whereas we've set a 100ms timeout, so this is - // expected. } using HttpClient client = new(); diff --git a/src/mono/wasi/testassets/Http.cs b/src/mono/wasi/testassets/Http.cs index 085efa92cabac..2db66f58ebd03 100644 --- a/src/mono/wasi/testassets/Http.cs +++ b/src/mono/wasi/testassets/Http.cs @@ -20,6 +20,18 @@ public static async Task MainAsync(string[] args) await Task.Delay(100); GC.Collect(); // test that Pollable->Task is not collected until resolved + var ctsDelay = new CancellationTokenSource(10); + try { + await Task.Delay(1000, ctsDelay.Token); + throw new Exception("delay should have timed out"); + } catch (TaskCanceledException tce) { + if (ctsDelay.Token != tce.CancellationToken) + { + throw new Exception("Different CancellationToken for delay"); + } + Console.WriteLine("impatient delay was canceled as expected"); + } + using HttpClient impatientClient = new(); impatientClient.DefaultRequestHeaders.Add("User-Agent", "dotnet WASI unit test"); impatientClient.Timeout = TimeSpan.FromMilliseconds(10); @@ -28,11 +40,10 @@ public static async Task MainAsync(string[] args) throw new Exception("request should have timed out"); } catch (TaskCanceledException) { Console.WriteLine("1st impatientClient was canceled as expected"); - // The /slow-hello endpoint takes 10 seconds to return a - // response, whereas we've set a 100ms timeout, so this is - // expected. } + GC.Collect(); + var cts = new CancellationTokenSource(10); try { // in reality server side doesn't delay because it doesn't implement it. So 10ms is bit fragile. @@ -46,9 +57,6 @@ public static async Task MainAsync(string[] args) throw new Exception("Different CancellationToken"); } Console.WriteLine("2nd impatientClient was canceled as expected"); - // The /slow-hello endpoint takes 10 seconds to return a - // response, whereas we've set a 100ms timeout, so this is - // expected. } using HttpClient client = new(); From 292b9089d0f25e732de8294ef6053d0c5643db2b Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Tue, 27 Aug 2024 19:30:58 +0200 Subject: [PATCH 11/11] fix token and test --- .../src/System/Threading/Wasi/WasiEventLoop.cs | 4 +++- src/mono/sample/wasi/http-p2/Program.cs | 18 ++++++++++-------- src/mono/wasi/testassets/Http.cs | 12 +++++++----- 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Wasi/WasiEventLoop.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Wasi/WasiEventLoop.cs index 921cc9a99795e..d52d443bd518d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Wasi/WasiEventLoop.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Wasi/WasiEventLoop.cs @@ -76,10 +76,12 @@ private sealed class PollableHolder public readonly Pollable pollable; public readonly TaskCompletionSource taskCompletionSource; public readonly CancellationTokenRegistration cancellationTokenRegistration; + public readonly CancellationToken cancellationToken; public PollableHolder(Pollable pollable, CancellationToken cancellationToken) { this.pollable = pollable; + this.cancellationToken = cancellationToken; // this means that taskCompletionSource.Task.AsyncState -> this; // which means PollableHolder will be alive until the Task alive @@ -114,7 +116,7 @@ private static void CancelAndDispose(object? s) // it will be removed from s_pollables on the next run self.isDisposed = true; - self.taskCompletionSource.TrySetCanceled(); + self.taskCompletionSource.TrySetCanceled(self.cancellationToken); self.pollable.Dispose(); self.cancellationTokenRegistration.Dispose(); } diff --git a/src/mono/sample/wasi/http-p2/Program.cs b/src/mono/sample/wasi/http-p2/Program.cs index 9fe7bf29bb977..e940c0a4100b6 100644 --- a/src/mono/sample/wasi/http-p2/Program.cs +++ b/src/mono/sample/wasi/http-p2/Program.cs @@ -28,14 +28,11 @@ public static async Task MainAsync(string[] args) Console.WriteLine("impatient delay was canceled as expected"); } - using HttpClient impatientClient = new(); - impatientClient.DefaultRequestHeaders.Add("User-Agent", "dotnet WASI unit test"); - impatientClient.Timeout = TimeSpan.FromMilliseconds(10); + using HttpClient impatientClient1 = new(); + impatientClient1.DefaultRequestHeaders.Add("User-Agent", "dotnet WASI unit test"); + impatientClient1.Timeout = TimeSpan.FromMilliseconds(10); try { - // in reality server side doesn't delay because it doesn't implement it. So 10ms is bit fragile. - // TODO: remove this once we have real WASI HTTP library unit tests with local server loop in Xharness. - // https://github.com/dotnet/xharness/pull/1244 - await impatientClient.GetAsync("https://corefx-net-http11.azurewebsites.net/Echo.ashx?delay10sec"); + await impatientClient1.GetAsync("https://corefx-net-http11.azurewebsites.net/Echo.ashx?delay10sec"); throw new Exception("request should have timed out"); } catch (TaskCanceledException) { Console.WriteLine("1st impatientClient was canceled as expected"); @@ -43,9 +40,14 @@ public static async Task MainAsync(string[] args) GC.Collect(); + using HttpClient impatientClient2 = new(); + impatientClient2.DefaultRequestHeaders.Add("User-Agent", "dotnet WASI unit test"); var cts = new CancellationTokenSource(10); try { - await impatientClient.GetAsync("https://corefx-net-http11.azurewebsites.net/Echo.ashx?delay10sec", cts.Token); + // in reality server side doesn't delay because it doesn't implement it. So 10ms is bit fragile. + // TODO: remove this once we have real WASI HTTP library unit tests with local server loop in Xharness. + // https://github.com/dotnet/xharness/pull/1244 + await impatientClient2.GetAsync("https://corefx-net-http11.azurewebsites.net/Echo.ashx?delay10sec", cts.Token); throw new Exception("request should have timed out"); } catch (TaskCanceledException tce) { if (cts.Token != tce.CancellationToken) diff --git a/src/mono/wasi/testassets/Http.cs b/src/mono/wasi/testassets/Http.cs index 2db66f58ebd03..49bc33f28fa3c 100644 --- a/src/mono/wasi/testassets/Http.cs +++ b/src/mono/wasi/testassets/Http.cs @@ -32,11 +32,11 @@ public static async Task MainAsync(string[] args) Console.WriteLine("impatient delay was canceled as expected"); } - using HttpClient impatientClient = new(); - impatientClient.DefaultRequestHeaders.Add("User-Agent", "dotnet WASI unit test"); - impatientClient.Timeout = TimeSpan.FromMilliseconds(10); + using HttpClient impatientClient1 = new(); + impatientClient1.DefaultRequestHeaders.Add("User-Agent", "dotnet WASI unit test"); + impatientClient1.Timeout = TimeSpan.FromMilliseconds(10); try { - await impatientClient.GetAsync("https://corefx-net-http11.azurewebsites.net/Echo.ashx?delay10sec"); + await impatientClient1.GetAsync("https://corefx-net-http11.azurewebsites.net/Echo.ashx?delay10sec"); throw new Exception("request should have timed out"); } catch (TaskCanceledException) { Console.WriteLine("1st impatientClient was canceled as expected"); @@ -44,12 +44,14 @@ public static async Task MainAsync(string[] args) GC.Collect(); + using HttpClient impatientClient2 = new(); + impatientClient2.DefaultRequestHeaders.Add("User-Agent", "dotnet WASI unit test"); var cts = new CancellationTokenSource(10); try { // in reality server side doesn't delay because it doesn't implement it. So 10ms is bit fragile. // TODO: remove this once we have real WASI HTTP library unit tests with local server loop in Xharness. // https://github.com/dotnet/xharness/pull/1244 - await impatientClient.GetAsync("https://corefx-net-http11.azurewebsites.net/Echo.ashx?delay10sec", cts.Token); + await impatientClient2.GetAsync("https://corefx-net-http11.azurewebsites.net/Echo.ashx?delay10sec", cts.Token); throw new Exception("request should have timed out"); } catch (TaskCanceledException tce) { if (cts.Token != tce.CancellationToken)