From 3a3d7b5d3527f0ea04adc4184159b4d7a3d6c93f Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 12 Jun 2024 10:34:39 -0600 Subject: [PATCH] support `System.Net.Http.HttpClient` on WASIp2 This adds `WasiHttpHandler`, a new implementation of `HttpMessageHandler` based on [wasi:http/outgoing-handler](https://github.com/WebAssembly/wasi-http/blob/v0.2.0/wit/handler.wit), plus tweaks to `System.Threading` to allow async `Task`s to work in a single-threaded context, with `ThreadPool` work items dispatched from an application-provided event loop. WASIp2 supports asynchronous I/O and timers via `wasi:io/poll/pollable` resource handles. One or more of those handles may be passed to `wasi:io/poll/poll`, which will block until at least one of them is ready. In order to make this model play nice with C#'s `async`/`await` and `Task` features, we need to reconcile several constraints: - WASI is currently single-threaded, and will continue to be that way for a while. - C#'s `async`/`await` and `Task` features require a working `ThreadPool` implementation capable of deferring work. - A WASI component can export an arbitrary number of functions to the host, and though they will always be called synchronously from the host, they need to be able to perform asynchronous operations before returning. - WASIp3 (currently in the design and prototype phase) will support asynchronous exports, with the top level event loop running in the host instead of the guest, and `wasi:io/poll/pollable` will no longer exist. Therefore, we don't want to add any temporary public APIs to the .NET runtime which will become obsolete when WASIp3 arrives. The solution we arrived at looks something like this: - Tweak the existing `ThreadPool` implementation for WASI so that methods such as `RequestWorkerThread` don't throw `PlatformNotSupportedException`s (i.e. allow work items to be queued even though the "worker thread" is always the same one that is queuing the work) - Add two new methods to `Thread`: - `internal static void Dispatch`: Runs an iteration of event loop, draining the `ThreadPool` queue of ready work items and calling `wasi:io/poll/poll` with any accumulated `pollable` handles - `internal static Task Register(int pollableHandle)`: Registers the specified `pollable` handle to be `poll`ed during the next call to `Dispatch` - Note that these methods are `internal` because they're temporary and should not be part of the public API, but they are intended to be called via `UnsafeAccessor` by application code (or more precisely, code generated by `wit-bindgen` for the application) The upshot is that application code can use `wit-bindgen` (either directly or via the new `componentize-dotnet` package) to generate async export bindings which will provide an event loop backed by `Thread.Dispatch`. Additionally, `wit-bindgen` can transparently convert any `pollable` handles returned by WASI imports into `Task`s via `Thread.Register`, allowing the component to `await` them, pass them to a combinator such as `Task.WhenEach`, etc. Later, when WASIp3 arrives and we update the .NET runtime to target it, we'll be able to remove some of this code (and the corresponding code in `wit-bindgen`) without requiring significant changes to the application developer's experience. This PR contains a few C# source files that were generated by `wit-bindgen` from the official WASI WIT files, plus scripts to regenerate them if desired. Signed-off-by: Joel Dice switch to `wasm32-wasip2` and update WASI test infra Now that we're using WASI-SDK 22, we can target `wasm32-wasip2`, which produces components by default and includes full `wasi:sockets` support. In order to run those components, I've updated the test infrastructure to use Wasmtime 21 (the latest release as of this writing). Other changes of note: - Tweaked src/coreclr/jit/compiler.cpp to make `Debug` builds work on Linux - Added libWasiHttp.a, which includes the encoded component type (in the form of a pre-generated Wasm object file) and a `cabi_realloc` definition. Both of these are generated by `wit-bindgen` and required by `wasm-component-ld` to generate a valid component. - Added a `FindWasmHostExecutableAndRun.sh` script for running the WASI tests on UNIX-style platforms. Signed-off-by: Joel Dice various WASI build tweaks Signed-off-by: Joel Dice quote libWasiHttp.a path in custom linker arg Signed-off-by: Joel Dice fix wasm-component-ld download command Signed-off-by: Joel Dice tweak EmccExtraArgs in CustomMain.csproj so wasm-component-ld understands it Signed-off-by: Joel Dice update CMake minimum version in wasi-sdk-p2.cmake Signed-off-by: Joel Dice use `HeaderDescriptor` to sort content and response headers Signed-off-by: Joel Dice allow building native WASI test code in src/tests/build.sh Signed-off-by: Joel Dice allow WASI runtime tests to be built and run on non-Windows systems Signed-off-by: Joel Dice update runtime tests to work with WASIp2 As of this writing, WASIp2 [does not support process exit statuses](https://github.com/WebAssembly/wasi-cli/issues/11) beyond 0 (success) and 1 (failure). To work around this, I've modified the relevant tests to return 0 on success instead of 100. Signed-off-by: Joel Dice fix CI for Windows builds; remove unused file Signed-off-by: Joel Dice disable sprintf warning in llvmlssa.cpp on macOS Signed-off-by: Joel Dice remove LibraryWorld_cabi_realloc.o I didn't mean to add this to Git. Signed-off-by: Joel Dice rename `generate-bindings.sh` files for clarity This makes it more obvious that, though they are similar, they each have a different job. Signed-off-by: Joel Dice update to `wit-bindgen` 0.27.0 and regenerate bindings Signed-off-by: Joel Dice reorganize code; add HttpClient smoke test - move System/WASIp2 to System/Threading/WASIp2 - remove generated `cabi_realloc` functions since `wasi-libc` will provide one - add HttpClient test to SmokeTests/SharedLibrary Note that I put the HttpClient test in SmokeTests/SharedLibrary since we were already using NodeJS for that test, and adding a simple loopback webserver to SharedLibraryDriver.mjs was easiest option available to keep the whole test self-contained. Signed-off-by: Joel Dice implement SystemNative_SysLog for WASI Signed-off-by: Joel Dice increase NodeJS stack trace limit to 200 Signed-off-by: Joel Dice give guest no filesystem access in SharedLibraryDriver.mjs Signed-off-by: Joel Dice switch to Trace.Assert into HttpClient smoke test Signed-off-by: Joel Dice rename WASIp2 directory to Wasi Signed-off-by: Joel Dice fix non-GET methods and add HttpClient echo test Signed-off-by: Joel Dice use azure NPM rename - WasiEventLoop.RegisterWasiPollable - WasiEventLoop.DispatchWasiEventLoop to make it less confusing on the Thread class - unification of gen-buildsys - cleanup pal_process_wasi.c fix build? more buffer /echo request body in SharedLibraryDriver.mjs Signed-off-by: Joel Dice fix gen-buildsys.sh regression Signed-off-by: Joel Dice allow only infinite `HttpClient.Timeout`s on WASI This temporary code will be reverted once we support `System.Threading.Timer` on WASI in a forthcoming PR. Signed-off-by: Joel Dice use `&` operator to simplify install-jco.ps1 Signed-off-by: Joel Dice remove redundant `CheckWasmSdks` target from SharedLibrary.csproj Signed-off-by: Joel Dice split `FindWasmHostExecutable.sh` out of `FindWasmHostExecutableAndRun.sh` Signed-off-by: Joel Dice replace component type object files with WIT files This updates `wit-bindgen` and `wasm-component-ld`, which now support producing and consuming component type WIT files as an alternative to binary object files. These files are easier to audit from a security perspective. Signed-off-by: Joel Dice preserve slashes in path in SharedLibrary.csproj Signed-off-by: Joel Dice temporarily disable ThreadPoolWorkQueue.Dispatch assertion See https://github.com/dotnet/runtime/issues/104803 Signed-off-by: Joel Dice update `wit-bindgen` to version 0.28.0 Signed-off-by: Joel Dice --- docs/workflow/building/coreclr/nativeaot.md | 4 +- eng/native/gen-buildsys.sh | 2 +- eng/pipelines/common/global-build-job.yml | 8 +- eng/pipelines/runtimelab/install-jco.ps1 | 9 + eng/pipelines/runtimelab/install-nodejs.ps1 | 11 + eng/pipelines/runtimelab/install-wasi-sdk.ps1 | 16 +- eng/pipelines/runtimelab/install-wasmer.cmd | 16 - eng/pipelines/runtimelab/install-wasmer.ps1 | 5 - eng/pipelines/runtimelab/install-wasmtime.cmd | 16 + eng/pipelines/runtimelab/install-wasmtime.ps1 | 8 + eng/testing/FindWasmHostExecutable.cmd | 8 +- eng/testing/FindWasmHostExecutable.sh | 24 + eng/testing/FindWasmHostExecutableAndRun.sh | 12 + src/coreclr/build-runtime.cmd | 8 +- src/coreclr/jit/compiler.cpp | 10 +- src/coreclr/jit/llvmlssa.cpp | 1 + .../Microsoft.NETCore.Native.targets | 3 +- .../nativeaot/Runtime/Portable/CMakeLists.txt | 7 + .../src/System.Net.Http.csproj | 1 - .../src/System/Net/Http/HttpClient.cs | 9 + .../generate-wasi-http-bindings.sh | 3 +- .../System.Private.CoreLib.Shared.projitems | 3 +- .../System/Threading/ThreadPoolWorkQueue.cs | 2 + .../Wasi/generate-wasi-poll-bindings.sh | 2 +- src/tests/Common/CLRTest.Execute.Bash.targets | 2 +- src/tests/Common/scripts/nativeaottest.sh | 14 +- src/tests/nativeaot/CustomMain/CustomMain.cs | 2 +- .../nativeaot/CustomMain/CustomMain.csproj | 3 +- .../DynamicGenerics/DynamicGenerics.csproj | 1 + .../DynamicGenerics/DynamicGenerics.main.cs | 2 +- .../SmokeTests/Exceptions/Exceptions.cs | 2 +- .../SmokeTests/Exceptions/Exceptions.csproj | 1 + .../FrameworkStrings/Baseline.csproj | 1 + .../SmokeTests/FrameworkStrings/Program.cs | 3 +- .../UseSystemResourceKeys.csproj | 1 + .../SmokeTests/HelloWasm/HelloWasm.cs | 4 +- .../SmokeTests/HelloWasm/HelloWasm.csproj | 1 + .../nativeaot/SmokeTests/PInvoke/PInvoke.cs | 2 +- .../SmokeTests/PInvoke/PInvoke.csproj | 1 + .../Preinitialization/Preinitialization.cs | 2 +- .../Preinitialization.csproj | 1 + .../SmokeTests/Reflection/Reflection.cs | 2 +- .../SmokeTests/Reflection/Reflection.csproj | 1 + .../Reflection/Reflection_FromUsage.csproj | 1 + .../nativeaot/SmokeTests/SharedLibrary/.npmrc | 1 + .../SmokeTests/SharedLibrary/Library.cs | 176 +++++ .../LibraryWorld_component_type.wit | 11 + .../SmokeTests/SharedLibrary/SharedLibrary.cs | 133 ++++ .../SharedLibrary/SharedLibrary.csproj | 2 + .../SharedLibrary/SharedLibraryDriver.mjs | 112 ++- .../generate-shared-library-bindings.sh | 16 + .../SharedLibrary/package-lock.json | 698 ++++++++++++++++++ .../SmokeTests/SharedLibrary/package.json | 11 + .../SmokeTests/SharedLibrary/wit/world.wit | 11 + .../StackTraceMetadata/StackTraceMetadata.cs | 2 +- .../StackTraceMetadata.csproj | 1 + .../StackTraceMetadata_Stripped.csproj | 1 + .../SmokeTests/TrimmingBehaviors/Main.cs | 2 +- .../TrimmingBehaviors.csproj | 1 + .../nativeaot/SmokeTests/UnitTests/Main.cs | 2 +- .../SmokeTests/UnitTests/UnitTests.csproj | 1 + 61 files changed, 1329 insertions(+), 87 deletions(-) create mode 100644 eng/pipelines/runtimelab/install-jco.ps1 delete mode 100644 eng/pipelines/runtimelab/install-wasmer.cmd delete mode 100644 eng/pipelines/runtimelab/install-wasmer.ps1 create mode 100644 eng/pipelines/runtimelab/install-wasmtime.cmd create mode 100644 eng/pipelines/runtimelab/install-wasmtime.ps1 create mode 100644 eng/testing/FindWasmHostExecutable.sh create mode 100755 eng/testing/FindWasmHostExecutableAndRun.sh create mode 100644 src/tests/nativeaot/SmokeTests/SharedLibrary/.npmrc create mode 100644 src/tests/nativeaot/SmokeTests/SharedLibrary/Library.cs create mode 100644 src/tests/nativeaot/SmokeTests/SharedLibrary/LibraryWorld_component_type.wit create mode 100644 src/tests/nativeaot/SmokeTests/SharedLibrary/generate-shared-library-bindings.sh create mode 100644 src/tests/nativeaot/SmokeTests/SharedLibrary/package-lock.json create mode 100644 src/tests/nativeaot/SmokeTests/SharedLibrary/package.json create mode 100644 src/tests/nativeaot/SmokeTests/SharedLibrary/wit/world.wit diff --git a/docs/workflow/building/coreclr/nativeaot.md b/docs/workflow/building/coreclr/nativeaot.md index f6743619a6b8..9e90ab278172 100644 --- a/docs/workflow/building/coreclr/nativeaot.md +++ b/docs/workflow/building/coreclr/nativeaot.md @@ -34,7 +34,9 @@ For the runtime libraries: ./emsdk install 3.1.47 ./emsdk activate 3.1.47 ``` -- To build for WASI, download and install WASI-SDK 22 from https://github.com/WebAssembly/wasi-sdk/releases (only Windows and Linux are supported currently) and set the `WASI_SDK_PATH` environment variable to the location where it is installed, e.g. `set WASI_SDK_PATH=c:\github\wasi-sdk`. Note that WASI-SDK 22 only includes a copy of `pthread.h` for the `wasm32-wasi-threads` target, which we must copy to the include directory for the `wasm32-wasi` target, e.g. `cp $WASI_SDK\share\wasi-sysroot\include\wasm32-wasi-threads\pthread.h $WASI_SDK\share\wasi-sysroot\include\wasm32-wasi\`. This is a temporary workaround until https://github.com/WebAssembly/wasi-libc/issues/501 has been addressed and released. +- To build for WASI, download and install WASI-SDK 22 from https://github.com/WebAssembly/wasi-sdk/releases (only Windows and Linux are supported currently) and set the `WASI_SDK_PATH` environment variable to the location where it is installed, e.g. `set WASI_SDK_PATH=c:\github\wasi-sdk`. + - Note that WASI-SDK 22 only includes a copy of `pthread.h` for the `wasm32-wasi-threads` target, which we must copy to the include directory for the `wasm32-wasip2` target, e.g. `cp %WASI_SDK_PATH%\share\wasi-sysroot\include\wasm32-wasi-threads\pthread.h %WASI_SDK_PATH%\share\wasi-sysroot\include\wasm32-wasip2\`. This is a temporary workaround until https://github.com/WebAssembly/wasi-libc/issues/501 has been addressed and released. + - Also, due to [this bug](https://github.com/bytecodealliance/wasm-component-ld/issues/22), we need to replace the `wasm-component-ld` that ships with WASI-SDK 22 with an updated version. If you have [cargo](https://rustup.rs/), you can run e.g. `cargo install wasm-component-ld@0.5.5 --root %WASI_SDK_PATH%`; otherwise, you can download it from [here](https://github.com/bytecodealliance/wasm-component-ld/releases/tag/v0.5.5), extract the binary, and copy it into `%WASI_SDK_PATH%\bin`. - Run `build clr.aot+libs -c [Debug|Release] -a wasm -os [browser|wasi]`. This will create the architecture-dependent libraries needed for linking and runtime execution, as well as the managed binaries to be used as input to ILC. For the compilers: diff --git a/eng/native/gen-buildsys.sh b/eng/native/gen-buildsys.sh index 8acdd3e443bb..a8b22b4cdb9f 100755 --- a/eng/native/gen-buildsys.sh +++ b/eng/native/gen-buildsys.sh @@ -104,7 +104,7 @@ if [[ "$host_arch" == "wasm" ]]; then exit 1 fi - cmake_extra_defines_wasm=("-DCLR_CMAKE_TARGET_OS=wasi" "-DCLR_CMAKE_TARGET_ARCH=wasm" "-DWASI_SDK_PREFIX=$WASI_SDK_PATH" "-DCMAKE_TOOLCHAIN_FILE=$reporoot/src/native/external/wasi-sdk-p2.cmake" "-DCMAKE_SYSROOT=${WASI_SDK_PATH}share/wasi-sysroot" "-DCMAKE_CROSSCOMPILING_EMULATOR=node --experimental-wasm-bigint --experimental-wasi-unstable-preview1") + cmake_extra_defines_wasm=("-DCLR_CMAKE_TARGET_OS=wasi" "-DCLR_CMAKE_TARGET_ARCH=wasm" "-DWASI_SDK_PREFIX=$WASI_SDK_PATH" "-DCMAKE_TOOLCHAIN_FILE=$reporoot/src/native/external/wasi-sdk-p2.cmake" "-DCMAKE_SYSROOT=${WASI_SDK_PATH}/share/wasi-sysroot" "-DCMAKE_CROSSCOMPILING_EMULATOR=node --experimental-wasm-bigint --experimental-wasi-unstable-preview1") else echo "target_os was not specified" exit 1 diff --git a/eng/pipelines/common/global-build-job.yml b/eng/pipelines/common/global-build-job.yml index 08c78b4c686c..0dc71a3fdb44 100644 --- a/eng/pipelines/common/global-build-job.yml +++ b/eng/pipelines/common/global-build-job.yml @@ -224,11 +224,13 @@ jobs: displayName: Install NodeJS - ${{ if and(eq(parameters.runtimeFlavor, 'coreclr'), eq(parameters.platform, 'wasi_wasm_win')) }}: - # Install Wasi Wasm dependencies: wasi-sdk, wasmer + # Install Wasi Wasm dependencies: wasi-sdk, wasmtime - script: call $(Build.SourcesDirectory)/eng/pipelines/runtimelab/install-wasi-sdk.cmd $(Build.SourcesDirectory)\wasm-tools displayName: Install wasi-sdk - - script: call $(Build.SourcesDirectory)/eng/pipelines/runtimelab/install-wasmer.cmd $(Build.SourcesDirectory)\wasm-tools - displayName: Install wasmer + - script: call $(Build.SourcesDirectory)/eng/pipelines/runtimelab/install-wasmtime.cmd $(Build.SourcesDirectory)\wasm-tools + displayName: Install wasmtime + - script: pwsh $(Build.SourcesDirectory)/eng/pipelines/runtimelab/install-jco.ps1 $(Build.SourcesDirectory) + displayName: Install Jco - ${{ if or(eq(parameters.platform, 'browser_wasm_win'), and(eq(parameters.platform, 'wasi_wasm_win'), not(eq(parameters.runtimeFlavor, 'coreclr')))) }}: # Update machine certs diff --git a/eng/pipelines/runtimelab/install-jco.ps1 b/eng/pipelines/runtimelab/install-jco.ps1 new file mode 100644 index 000000000000..06d77575c83f --- /dev/null +++ b/eng/pipelines/runtimelab/install-jco.ps1 @@ -0,0 +1,9 @@ +$RootPath = $Args[0] + +$NpmExePath = $Env:NPM_EXECUTABLE + +Set-Location -Path $RootPath + +& $NpmExePath install @bytecodealliance/jco +& $NpmExePath install @bytecodealliance/preview2-shim + diff --git a/eng/pipelines/runtimelab/install-nodejs.ps1 b/eng/pipelines/runtimelab/install-nodejs.ps1 index 5dee2727f2d4..7d3d21d7ad48 100644 --- a/eng/pipelines/runtimelab/install-nodejs.ps1 +++ b/eng/pipelines/runtimelab/install-nodejs.ps1 @@ -51,11 +51,13 @@ if ($IsWindows) { Expand-Archive -LiteralPath "$InstallPath\$NodeJSZipName" -DestinationPath $InstallPath -Force $NodeJSExePath = "$InstallPath\$NodeJSInstallName\node.exe" + $NpmExePath = "$InstallPath\$NodeJSInstallName\npm.cmd" } else { tar xJf $InstallPath/$NodeJSZipName -C $InstallPath $NodeJSExePath = "$InstallPath/$NodeJSInstallName/bin/node" + $NpmExePath = "$InstallPath/$NodeJSInstallName/bin/npm" } if (!(Test-Path $NodeJSExePath)) @@ -64,5 +66,14 @@ if (!(Test-Path $NodeJSExePath)) exit 1 } +if (!(Test-Path $NpmExePath)) +{ + Write-Error "Did not find NPM at: '$NpmExePath'" + exit 1 +} + Write-Host Setting NODEJS_EXECUTABLE to $NodeJSExePath Write-Host "##vso[task.setvariable variable=NODEJS_EXECUTABLE]$NodeJSExePath" + +Write-Host Setting NPM_EXECUTABLE to $NpmExePath +Write-Host "##vso[task.setvariable variable=NPM_EXECUTABLE]$NpmExePath" diff --git a/eng/pipelines/runtimelab/install-wasi-sdk.ps1 b/eng/pipelines/runtimelab/install-wasi-sdk.ps1 index f6fa9e9e5c51..56a365f6a360 100644 --- a/eng/pipelines/runtimelab/install-wasi-sdk.ps1 +++ b/eng/pipelines/runtimelab/install-wasi-sdk.ps1 @@ -6,8 +6,20 @@ mv wasi-sdk-22.0+m wasi-sdk # Temporary WASI-SDK 22 workaround: Until # https://github.com/WebAssembly/wasi-libc/issues/501 is addressed, we copy -# pthread.h from the wasm32-wasi-threads include directory to the wasm32-wasi +# pthread.h from the wasm32-wasi-threads include directory to the wasm32-wasip2 # include directory. See https://github.com/dotnet/runtimelab/issues/2598 for # the issue to remove this workaround once WASI-SDK 23 is released. -cp wasi-sdk/share/wasi-sysroot/include/wasm32-wasi-threads/pthread.h wasi-sdk/share/wasi-sysroot/include/wasm32-wasi/ +cp wasi-sdk/share/wasi-sysroot/include/wasm32-wasi-threads/pthread.h wasi-sdk/share/wasi-sysroot/include/wasm32-wasip2/ + +# Temporary WASI-SDK 22 workaround #2: The version of `wasm-component-ld` that +# ships with WASI-SDK 22 contains a +# [bug](https://github.com/bytecodealliance/wasm-component-ld/issues/22) which +# has been fixed in a v0.5.3 of that utility, so we upgrade it here. Also, +# v0.5.5 adds support for a `--component-type` option, helping us avoid adding +# .o files to source control. + +Invoke-WebRequest -Uri https://github.com/bytecodealliance/wasm-component-ld/releases/download/v0.5.5/wasm-component-ld-v0.5.5-x86_64-windows.zip -OutFile wasm-component-ld-v0.5.5-x86_64-windows.zip + +Expand-Archive -LiteralPath wasm-component-ld-v0.5.5-x86_64-windows.zip -DestinationPath . +cp wasm-component-ld-v0.5.5-x86_64-windows/wasm-component-ld.exe wasi-sdk/bin diff --git a/eng/pipelines/runtimelab/install-wasmer.cmd b/eng/pipelines/runtimelab/install-wasmer.cmd deleted file mode 100644 index cc0cfcb446d2..000000000000 --- a/eng/pipelines/runtimelab/install-wasmer.cmd +++ /dev/null @@ -1,16 +0,0 @@ -mkdir "%1" 2>nul -cd /D "%1" - -echo Installing Wasmer - -powershell -NoProfile -NoLogo -ExecutionPolicy ByPass -File "%~dp0install-wasmer.ps1" -if %errorlevel% NEQ 0 goto fail - -echo Setting WASMER_EXECUTABLE to %1\wasmer\bin\wasmer.exe -echo ##vso[task.setvariable variable=WASMER_EXECUTABLE]%1\wasmer\bin\wasmer.exe - -exit /b 0 - -fail: -echo "Failed to install wasmer" -exit /b 1 diff --git a/eng/pipelines/runtimelab/install-wasmer.ps1 b/eng/pipelines/runtimelab/install-wasmer.ps1 deleted file mode 100644 index 06710327e66c..000000000000 --- a/eng/pipelines/runtimelab/install-wasmer.ps1 +++ /dev/null @@ -1,5 +0,0 @@ -Invoke-WebRequest -Uri https://github.com/wasmerio/wasmer/releases/download/v3.3.0/wasmer-windows-amd64.tar.gz -OutFile wasmer-windows-amd64.tar.gz - -mkdir wasmer - -tar -xzf wasmer-windows-amd64.tar.gz -C wasmer diff --git a/eng/pipelines/runtimelab/install-wasmtime.cmd b/eng/pipelines/runtimelab/install-wasmtime.cmd new file mode 100644 index 000000000000..0f5baec5fec6 --- /dev/null +++ b/eng/pipelines/runtimelab/install-wasmtime.cmd @@ -0,0 +1,16 @@ +mkdir "%1" 2>nul +cd /D "%1" + +echo Installing Wasmtime + +powershell -NoProfile -NoLogo -ExecutionPolicy ByPass -File "%~dp0install-wasmtime.ps1" +if %errorlevel% NEQ 0 goto fail + +echo Setting WASMTIME_EXECUTABLE to %1\wasmtime\bin\wasmtime.exe +echo ##vso[task.setvariable variable=WASMTIME_EXECUTABLE]%1\wasmtime\bin\wasmtime.exe + +exit /b 0 + +fail: +echo "Failed to install wasmtime" +exit /b 1 diff --git a/eng/pipelines/runtimelab/install-wasmtime.ps1 b/eng/pipelines/runtimelab/install-wasmtime.ps1 new file mode 100644 index 000000000000..78e76f7e1d6d --- /dev/null +++ b/eng/pipelines/runtimelab/install-wasmtime.ps1 @@ -0,0 +1,8 @@ +Invoke-WebRequest -Uri https://github.com/bytecodealliance/wasmtime/releases/download/v21.0.1/wasmtime-v21.0.1-x86_64-windows.zip -OutFile wasmtime-v21.0.1-x86_64-windows.zip + +mkdir wasmtime\bin + +Expand-Archive -LiteralPath wasmtime-v21.0.1-x86_64-windows.zip -DestinationPath . +del wasmtime-v21.0.1-x86_64-windows.zip +move wasmtime-v21.0.1-x86_64-windows\wasmtime.exe wasmtime\bin\ +Remove-Item -Recurse wasmtime-v21.0.1-x86_64-windows diff --git a/eng/testing/FindWasmHostExecutable.cmd b/eng/testing/FindWasmHostExecutable.cmd index 2e5e39ea5971..196a51025a70 100644 --- a/eng/testing/FindWasmHostExecutable.cmd +++ b/eng/testing/FindWasmHostExecutable.cmd @@ -26,12 +26,12 @@ if exist "%__WasmBinaryPathWithoutExtension%.js" ( ) if "%__WasmBinaryExtension%" == ".wasm" ( - if "%WASMER_EXECUTABLE%" == "" ( - :: When running tests locally, assume wasmer is in PATH. - set WASMER_EXECUTABLE=wasmer + if "%WASMTIME_EXECUTABLE%" == "" ( + :: When running tests locally, assume wasmtime is in PATH. + set WASMTIME_EXECUTABLE=wasmtime ) - set WASM_HOST_EXECUTABLE="!WASMER_EXECUTABLE!" -- + set WASM_HOST_EXECUTABLE="!WASMTIME_EXECUTABLE!" run -S http ) else ( if "%NODEJS_EXECUTABLE%" == "" ( :: When running tests locally, assume NodeJS is in PATH. diff --git a/eng/testing/FindWasmHostExecutable.sh b/eng/testing/FindWasmHostExecutable.sh new file mode 100644 index 000000000000..c831cda77610 --- /dev/null +++ b/eng/testing/FindWasmHostExecutable.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash + +exename=$(basename "$1" .dll) +dirname=$(dirname "$1") + +node="node --stack_trace_limit=100" +wasmtime="wasmtime run -S http" + +if [ -e "${dirname}/${exename}.js" ]; then + WASM_HOST_EXECUTABLE=$node + WASM_BINARY_TO_EXECUTE="${dirname}/${exename}.js" +elif [ -e "${dirname}/main.js" ]; then + WASM_HOST_EXECUTABLE=$node + WASM_BINARY_TO_EXECUTE="${dirname}/main.js" +elif [ -e "${dirname}/${exename}.mjs" ]; then + WASM_HOST_EXECUTABLE=$node + WASM_BINARY_TO_EXECUTE="${dirname}/${exename}.mjs" +elif [ -e "${dirname}/main.mjs" ]; then + WASM_HOST_EXECUTABLE=$node + WASM_BINARY_TO_EXECUTE="${dirname}/main.mjs" +elif [ -e "${dirname}/${exename}.wasm" ]; then + WASM_HOST_EXECUTABLE=$wasmtime + WASM_BINARY_TO_EXECUTE="${dirname}/${exename}.wasm" +fi diff --git a/eng/testing/FindWasmHostExecutableAndRun.sh b/eng/testing/FindWasmHostExecutableAndRun.sh new file mode 100755 index 000000000000..9b1bf6f90a2b --- /dev/null +++ b/eng/testing/FindWasmHostExecutableAndRun.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &> /dev/null && pwd) + +source $SCRIPT_DIR/FindWasmHostExecutable.sh "$1" + +if [ -n "${WASM_HOST_EXECUTABLE}" ]; then + echo $WASM_HOST_EXECUTABLE "$WASM_BINARY_TO_EXECUTE" "${@:2}" + $WASM_HOST_EXECUTABLE "$WASM_BINARY_TO_EXECUTE" "${@:2}" +else + exit 1 +fi diff --git a/src/coreclr/build-runtime.cmd b/src/coreclr/build-runtime.cmd index eac7903e1abf..bb679fe5e176 100644 --- a/src/coreclr/build-runtime.cmd +++ b/src/coreclr/build-runtime.cmd @@ -349,9 +349,11 @@ for /f "delims=" %%a in ("-%__RequestedBuildComponents%-") do ( set __CMakeTarget=!__CMakeTarget! nativeaot if "%__TargetArch%"=="wasm" ( - if not defined EMSDK ( - echo %__ErrMsgPrefix%%__MsgPrefix%Error: The EMSDK environment variable pointing to emsdk root must be set. - goto ExitWithError + if "%__TargetOS%"=="browser" ( + if not defined EMSDK ( + echo %__ErrMsgPrefix%%__MsgPrefix%Error: The EMSDK environment variable pointing to emsdk root must be set. + goto ExitWithError + ) ) ) ) diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp index a88bd007482d..ec098003ede5 100644 --- a/src/coreclr/jit/compiler.cpp +++ b/src/coreclr/jit/compiler.cpp @@ -1262,8 +1262,12 @@ void DisplayNowayAssertMap() fout = _wfopen(strJitMeasureNowayAssertFile, W("a")); if (fout == nullptr) { +#if !defined(TARGET_WINDOWS) + // TODO: how do we print a `const char16_t*` portably? +#else fprintf(jitstdout(), "Failed to open JitMeasureNowayAssertFile \"%ws\"\n", strJitMeasureNowayAssertFile); +#endif return; } } @@ -1295,7 +1299,7 @@ void DisplayNowayAssertMap() for (i = 0; i < count; i++) { - fprintf(fout, "%u, %s, %u, \"%s\"\n", nacp[i].count, nacp[i].fl.m_file, nacp[i].fl.m_line, + fprintf(fout, "%u, %s, %u, \"%s\"\n", (unsigned int) nacp[i].count, nacp[i].fl.m_file, nacp[i].fl.m_line, nacp[i].fl.m_condStr); } @@ -3415,7 +3419,7 @@ void Compiler::compInitOptions(JitFlags* jitFlags) if (verbose) { printf("STRESS_NULL_OBJECT_CHECK: compMaxUncheckedOffsetForNullObject=0x%X\n", - compMaxUncheckedOffsetForNullObject); + (unsigned int) compMaxUncheckedOffsetForNullObject); } } @@ -9682,7 +9686,7 @@ void dumpConvertedVarSet(Compiler* comp, VARSET_VALARG_TP vars) { printf(" "); } - printf("V%02u", varNum); + printf("V%02u", (unsigned int) varNum); first = false; } } diff --git a/src/coreclr/jit/llvmlssa.cpp b/src/coreclr/jit/llvmlssa.cpp index 280bf0d2692c..03ccad3de501 100644 --- a/src/coreclr/jit/llvmlssa.cpp +++ b/src/coreclr/jit/llvmlssa.cpp @@ -1639,6 +1639,7 @@ class ShadowStackAllocator #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wformat-security" +#pragma clang diagnostic ignored "-Wdeprecated-declarations" #endif // __clang__ if (pBuffer == nullptr) { diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets index d16d4448fc94..3d4460726815 100644 --- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets +++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets @@ -128,7 +128,7 @@ The .NET Foundation licenses this file to you under the MIT license. -Oz wasm32-unknown-emscripten - wasm32-unknown-wasi + wasm32-unknown-wasip2 1048576 $(EmccStackSize) 1024 @@ -590,6 +590,7 @@ The .NET Foundation licenses this file to you under the MIT license. + diff --git a/src/coreclr/nativeaot/Runtime/Portable/CMakeLists.txt b/src/coreclr/nativeaot/Runtime/Portable/CMakeLists.txt index 4eb224818192..342923738361 100644 --- a/src/coreclr/nativeaot/Runtime/Portable/CMakeLists.txt +++ b/src/coreclr/nativeaot/Runtime/Portable/CMakeLists.txt @@ -41,3 +41,10 @@ if (NOT CLR_CMAKE_TARGET_ARCH_WASM) install_static_library(standalonegc-enabled aotsdk nativeaot) endif() +if (CLR_CMAKE_TARGET_WASI) + install( + FILES ../../../../libraries/System.Net.Http/src/System/Net/Http/WasiHttpHandler/WasiHttpWorld_component_type.wit + DESTINATION aotsdk + COMPONENT nativeaot + ) +endif() diff --git a/src/libraries/System.Net.Http/src/System.Net.Http.csproj b/src/libraries/System.Net.Http/src/System.Net.Http.csproj index 5c5f3a96bc57..38deb72c141a 100644 --- a/src/libraries/System.Net.Http/src/System.Net.Http.csproj +++ b/src/libraries/System.Net.Http/src/System.Net.Http.csproj @@ -525,5 +525,4 @@ - diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/HttpClient.cs b/src/libraries/System.Net.Http/src/System/Net/Http/HttpClient.cs index 822090c0819e..d4370757f64c 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/HttpClient.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/HttpClient.cs @@ -16,7 +16,12 @@ public partial class HttpClient : HttpMessageInvoker #region Fields private static IWebProxy? s_defaultProxy; +#if TARGET_WASI + // TODO: remove this WASI-specific code once `System.Threading.Timer` is supported + private static readonly TimeSpan s_defaultTimeout = Threading.Timeout.InfiniteTimeSpan; +#else private static readonly TimeSpan s_defaultTimeout = TimeSpan.FromSeconds(100); +#endif private static readonly TimeSpan s_maxTimeout = TimeSpan.FromMilliseconds(int.MaxValue); private static readonly TimeSpan s_infiniteTimeout = Threading.Timeout.InfiniteTimeSpan; private const HttpCompletionOption DefaultCompletionOption = HttpCompletionOption.ResponseContentRead; @@ -106,6 +111,10 @@ public TimeSpan Timeout { ArgumentOutOfRangeException.ThrowIfLessThanOrEqual(value, TimeSpan.Zero); ArgumentOutOfRangeException.ThrowIfGreaterThan(value, s_maxTimeout); +#if TARGET_WASI + // TODO: remove this WASI-specific code once `System.Threading.Timer` is supported + throw new PlatformNotSupportedException("finite timeouts not yet supported on WASI"); +#endif } CheckDisposedOrStarted(); _timeout = value; 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 e58891f50877..dfca2212fa01 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,8 +11,7 @@ set -ex # [cargo](https://rustup.rs/) # [curl](https://curl.se/download.html) -# TODO: Update to the next crates.io release containing fa19e08a884ec62f95191319d8d296874424c736: -cargo install --locked --no-default-features --features csharp --git https://github.com/bytecodealliance/wit-bindgen --rev fa19e08a884ec62f95191319d8d296874424c736 wit-bindgen-cli +cargo install --locked --no-default-features --features csharp --version 0.28.0 wit-bindgen-cli curl -OL https://github.com/WebAssembly/wasi-http/archive/refs/tags/v0.2.0.tar.gz tar xzf v0.2.0.tar.gz cat >wasi-http-0.2.0/wit/world.wit < - \ No newline at end of file + + diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadPoolWorkQueue.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadPoolWorkQueue.cs index bc0fe4556bb3..194d8e7bb567 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadPoolWorkQueue.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadPoolWorkQueue.cs @@ -906,11 +906,13 @@ internal static bool Dispatch() // thread because it sees a Determining or Scheduled stage, and the current thread is the last thread processing // work items, the current thread must either see the work item queued by the enqueuer, or it must see a stage of // Scheduled, and try to dequeue again or request another thread. + #if !TARGET_WASI // TODO https://github.com/dotnet/runtime/issues/104803 Debug.Assert(workQueue._separated.queueProcessingStage == QueueProcessingStage.Scheduled); #endif workQueue._separated.queueProcessingStage = QueueProcessingStage.Determining; + Interlocked.MemoryBarrier(); object? workItem = null; 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 eccd07494bab..484d70f3616b 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.27.0 wit-bindgen-cli +cargo install --locked --no-default-features --features csharp --version 0.28.0 wit-bindgen-cli curl -OL https://github.com/WebAssembly/wasi-http/archive/refs/tags/v0.2.0.tar.gz tar xzf v0.2.0.tar.gz cat >wasi-http-0.2.0/wit/world.wit <"$CORE_ROOT/watchdog" $_WatcherTimeoutMins - /dev/null && pwd) + +source $SCRIPT_DIR/../../../../eng/testing/FindWasmHostExecutable.sh "$1/native/$2" + +if [ -n "${WASM_HOST_EXECUTABLE}" ]; then + echo $WASM_HOST_EXECUTABLE "$WASM_BINARY_TO_EXECUTE" "${@:3}" + $WASM_HOST_EXECUTABLE "$WASM_BINARY_TO_EXECUTE" "${@:3}" +else + chmod +x $1/native/$exename + $_DebuggerFullPath $1/native/$exename "${@:3}" +fi diff --git a/src/tests/nativeaot/CustomMain/CustomMain.cs b/src/tests/nativeaot/CustomMain/CustomMain.cs index 97db548fe54d..735c2dc1f843 100644 --- a/src/tests/nativeaot/CustomMain/CustomMain.cs +++ b/src/tests/nativeaot/CustomMain/CustomMain.cs @@ -35,6 +35,6 @@ static void IncrementExitCode(int amount) static int Main(string[] args) { Console.WriteLine("hello from managed main"); - return s_exitCode; + return s_exitCode - 100; } } diff --git a/src/tests/nativeaot/CustomMain/CustomMain.csproj b/src/tests/nativeaot/CustomMain/CustomMain.csproj index 35ee6659fce7..26f0ccbe0673 100644 --- a/src/tests/nativeaot/CustomMain/CustomMain.csproj +++ b/src/tests/nativeaot/CustomMain/CustomMain.csproj @@ -5,7 +5,8 @@ lib - -Xlinker -export-if-defined=__main_argc_argv + -Wl,--export-if-defined=__main_argc_argv + 0 diff --git a/src/tests/nativeaot/SmokeTests/DynamicGenerics/DynamicGenerics.csproj b/src/tests/nativeaot/SmokeTests/DynamicGenerics/DynamicGenerics.csproj index 395a25e52af8..f183b10f8772 100644 --- a/src/tests/nativeaot/SmokeTests/DynamicGenerics/DynamicGenerics.csproj +++ b/src/tests/nativeaot/SmokeTests/DynamicGenerics/DynamicGenerics.csproj @@ -10,6 +10,7 @@ true + 0 diff --git a/src/tests/nativeaot/SmokeTests/DynamicGenerics/DynamicGenerics.main.cs b/src/tests/nativeaot/SmokeTests/DynamicGenerics/DynamicGenerics.main.cs index 9277ea592cb0..fef49a74a131 100644 --- a/src/tests/nativeaot/SmokeTests/DynamicGenerics/DynamicGenerics.main.cs +++ b/src/tests/nativeaot/SmokeTests/DynamicGenerics/DynamicGenerics.main.cs @@ -165,7 +165,7 @@ public static int Main(string[] args) if (passed && CoreFXTestLibrary.Internal.Runner.NumPassedTests > 0) { CoreFXTestLibrary.Logger.LogInformation("All tests PASSED."); - return 100; + return 0; } else { diff --git a/src/tests/nativeaot/SmokeTests/Exceptions/Exceptions.cs b/src/tests/nativeaot/SmokeTests/Exceptions/Exceptions.cs index 41ee2b15f2fd..0ae59ea89ef3 100644 --- a/src/tests/nativeaot/SmokeTests/Exceptions/Exceptions.cs +++ b/src/tests/nativeaot/SmokeTests/Exceptions/Exceptions.cs @@ -9,7 +9,7 @@ public class BringUpTest { - const int Pass = 100; + const int Pass = 0; const int Fail = -1; volatile int myField; diff --git a/src/tests/nativeaot/SmokeTests/Exceptions/Exceptions.csproj b/src/tests/nativeaot/SmokeTests/Exceptions/Exceptions.csproj index 3962aa3e39b9..8ee888607aba 100644 --- a/src/tests/nativeaot/SmokeTests/Exceptions/Exceptions.csproj +++ b/src/tests/nativeaot/SmokeTests/Exceptions/Exceptions.csproj @@ -6,6 +6,7 @@ true true + 0 diff --git a/src/tests/nativeaot/SmokeTests/FrameworkStrings/Baseline.csproj b/src/tests/nativeaot/SmokeTests/FrameworkStrings/Baseline.csproj index 111baa46052b..35eaf4771351 100644 --- a/src/tests/nativeaot/SmokeTests/FrameworkStrings/Baseline.csproj +++ b/src/tests/nativeaot/SmokeTests/FrameworkStrings/Baseline.csproj @@ -4,6 +4,7 @@ 0 true + 0 diff --git a/src/tests/nativeaot/SmokeTests/FrameworkStrings/Program.cs b/src/tests/nativeaot/SmokeTests/FrameworkStrings/Program.cs index 73b0b99b29b6..1de16a9494ab 100644 --- a/src/tests/nativeaot/SmokeTests/FrameworkStrings/Program.cs +++ b/src/tests/nativeaot/SmokeTests/FrameworkStrings/Program.cs @@ -72,4 +72,5 @@ throw new Exception(); #endif -return 100; +return 0; + diff --git a/src/tests/nativeaot/SmokeTests/FrameworkStrings/UseSystemResourceKeys.csproj b/src/tests/nativeaot/SmokeTests/FrameworkStrings/UseSystemResourceKeys.csproj index b775c35874d4..b601a20b555b 100644 --- a/src/tests/nativeaot/SmokeTests/FrameworkStrings/UseSystemResourceKeys.csproj +++ b/src/tests/nativeaot/SmokeTests/FrameworkStrings/UseSystemResourceKeys.csproj @@ -9,6 +9,7 @@ true true + 0 diff --git a/src/tests/nativeaot/SmokeTests/HelloWasm/HelloWasm.cs b/src/tests/nativeaot/SmokeTests/HelloWasm/HelloWasm.cs index 62f5c8444420..d526b42eff55 100644 --- a/src/tests/nativeaot/SmokeTests/HelloWasm/HelloWasm.cs +++ b/src/tests/nativeaot/SmokeTests/HelloWasm/HelloWasm.cs @@ -46,7 +46,7 @@ private static unsafe int Main(string[] args) PrintLine("Hello from C#!"); int tempInt = 0; int tempInt2 = 0; - StartTest("Address/derefernce test"); + StartTest("Address/dereference test"); (*(&tempInt)) = 9; EndTest(tempInt == 9); @@ -437,7 +437,7 @@ private static unsafe int Main(string[] args) } PrintLine("Done"); - return Success ? 100 : -1; + return Success ? 0 : 1; } [MethodImpl(MethodImplOptions.NoInlining)] diff --git a/src/tests/nativeaot/SmokeTests/HelloWasm/HelloWasm.csproj b/src/tests/nativeaot/SmokeTests/HelloWasm/HelloWasm.csproj index f7ee527f54a7..89e13156aabb 100644 --- a/src/tests/nativeaot/SmokeTests/HelloWasm/HelloWasm.csproj +++ b/src/tests/nativeaot/SmokeTests/HelloWasm/HelloWasm.csproj @@ -7,6 +7,7 @@ $(NoWarn);IL3049;CS8500 + 0 diff --git a/src/tests/nativeaot/SmokeTests/PInvoke/PInvoke.cs b/src/tests/nativeaot/SmokeTests/PInvoke/PInvoke.cs index 608cc8c0cb9a..a1615541a946 100644 --- a/src/tests/nativeaot/SmokeTests/PInvoke/PInvoke.cs +++ b/src/tests/nativeaot/SmokeTests/PInvoke/PInvoke.cs @@ -352,7 +352,7 @@ public static int Main() TestDifferentModopts(); TestFunctionPointers(); - return 100; + return 0; } public static void ThrowIfNotEquals(T expected, T actual, string message) diff --git a/src/tests/nativeaot/SmokeTests/PInvoke/PInvoke.csproj b/src/tests/nativeaot/SmokeTests/PInvoke/PInvoke.csproj index e1d8f821b726..a099e3c89d71 100644 --- a/src/tests/nativeaot/SmokeTests/PInvoke/PInvoke.csproj +++ b/src/tests/nativeaot/SmokeTests/PInvoke/PInvoke.csproj @@ -10,6 +10,7 @@ true true + 0 diff --git a/src/tests/nativeaot/SmokeTests/Preinitialization/Preinitialization.cs b/src/tests/nativeaot/SmokeTests/Preinitialization/Preinitialization.cs index 78223dca967f..8cb71ae9f298 100644 --- a/src/tests/nativeaot/SmokeTests/Preinitialization/Preinitialization.cs +++ b/src/tests/nativeaot/SmokeTests/Preinitialization/Preinitialization.cs @@ -64,7 +64,7 @@ private static int Main() Console.WriteLine("Preinitialization is disabled in multimodule builds for now. Skipping test."); #endif - return 100; + return 0; } } diff --git a/src/tests/nativeaot/SmokeTests/Preinitialization/Preinitialization.csproj b/src/tests/nativeaot/SmokeTests/Preinitialization/Preinitialization.csproj index fde40cfb5e69..284c77ff84f3 100644 --- a/src/tests/nativeaot/SmokeTests/Preinitialization/Preinitialization.csproj +++ b/src/tests/nativeaot/SmokeTests/Preinitialization/Preinitialization.csproj @@ -16,6 +16,7 @@ with system C++ runtime library (-lstdc++). --> true + 0 diff --git a/src/tests/nativeaot/SmokeTests/Reflection/Reflection.cs b/src/tests/nativeaot/SmokeTests/Reflection/Reflection.cs index 481ca13d06a6..815814869a6d 100644 --- a/src/tests/nativeaot/SmokeTests/Reflection/Reflection.cs +++ b/src/tests/nativeaot/SmokeTests/Reflection/Reflection.cs @@ -95,7 +95,7 @@ private static int Main() TestBaseOnlyUsedFromCode.Run(); TestEntryPoint.Run(); - return 100; + return 0; } class TestReflectionInvoke diff --git a/src/tests/nativeaot/SmokeTests/Reflection/Reflection.csproj b/src/tests/nativeaot/SmokeTests/Reflection/Reflection.csproj index 04ec10484f88..4f944cacf061 100644 --- a/src/tests/nativeaot/SmokeTests/Reflection/Reflection.csproj +++ b/src/tests/nativeaot/SmokeTests/Reflection/Reflection.csproj @@ -10,6 +10,7 @@ true + 0 diff --git a/src/tests/nativeaot/SmokeTests/Reflection/Reflection_FromUsage.csproj b/src/tests/nativeaot/SmokeTests/Reflection/Reflection_FromUsage.csproj index c569fde4d4cd..fdf81b5c4b45 100644 --- a/src/tests/nativeaot/SmokeTests/Reflection/Reflection_FromUsage.csproj +++ b/src/tests/nativeaot/SmokeTests/Reflection/Reflection_FromUsage.csproj @@ -15,6 +15,7 @@ true false + 0 diff --git a/src/tests/nativeaot/SmokeTests/SharedLibrary/.npmrc b/src/tests/nativeaot/SmokeTests/SharedLibrary/.npmrc new file mode 100644 index 000000000000..33312472ae5b --- /dev/null +++ b/src/tests/nativeaot/SmokeTests/SharedLibrary/.npmrc @@ -0,0 +1 @@ +registry=https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/ \ No newline at end of file diff --git a/src/tests/nativeaot/SmokeTests/SharedLibrary/Library.cs b/src/tests/nativeaot/SmokeTests/SharedLibrary/Library.cs new file mode 100644 index 000000000000..e647de17f71d --- /dev/null +++ b/src/tests/nativeaot/SmokeTests/SharedLibrary/Library.cs @@ -0,0 +1,176 @@ +// Generated by `wit-bindgen` 0.27.0. DO NOT EDIT! +// +#nullable enable +using System; +using System.Runtime.CompilerServices; +using System.Collections; +using System.Runtime.InteropServices; +using System.Text; +using System.Collections.Generic; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; + +namespace LibraryWorld { + + public interface ILibraryWorld { + static abstract void TestHttp(ushort port); + + static abstract int ReturnsPrimitiveInt(); + + static abstract bool ReturnsPrimitiveBool(); + + static abstract uint ReturnsPrimitiveChar(); + + static abstract void EnsureManagedClassLoaders(); + + static abstract int CheckSimpleExceptionHandling(); + + static abstract int CheckSimpleGcCollect(); + + } + + public readonly struct None {} + + [StructLayout(LayoutKind.Sequential)] + public readonly struct Result + { + public readonly byte Tag; + private readonly object value; + + private Result(byte tag, object value) + { + Tag = tag; + this.value = value; + } + + public static Result ok(Ok ok) + { + return new Result(OK, ok!); + } + + public static Result err(Err err) + { + return new Result(ERR, err!); + } + + public bool IsOk => Tag == OK; + public bool IsErr => Tag == ERR; + + public Ok AsOk + { + get + { + if (Tag == OK) + return (Ok)value; + else + throw new ArgumentException("expected OK, got " + Tag); + } + } + + public Err AsErr + { + get + { + if (Tag == ERR) + return (Err)value; + else + throw new ArgumentException("expected ERR, got " + Tag); + } + } + + public const byte OK = 0; + public const byte ERR = 1; + } + + namespace exports { + public static class LibraryWorld + { + + [UnmanagedCallersOnly(EntryPoint = "test-http")] + public static unsafe void wasmExportTestHttp(int p0) { + + LibraryWorldImpl.TestHttp((((ushort)p0))); + + } + + [UnmanagedCallersOnly(EntryPoint = "returns-primitive-int")] + public static unsafe int wasmExportReturnsPrimitiveInt() { + + int ret; + ret = LibraryWorldImpl.ReturnsPrimitiveInt(); + return ret; + + } + + [UnmanagedCallersOnly(EntryPoint = "cabi_post_returns-primitive-int")] + public static void cabi_post_wasmExportReturnsPrimitiveInt(int returnValue) { + Console.WriteLine("TODO: cabi_post_returns-primitive-int"); + } + + [UnmanagedCallersOnly(EntryPoint = "returns-primitive-bool")] + public static unsafe int wasmExportReturnsPrimitiveBool() { + + bool ret; + ret = LibraryWorldImpl.ReturnsPrimitiveBool(); + return (ret ? 1 : 0); + + } + + [UnmanagedCallersOnly(EntryPoint = "cabi_post_returns-primitive-bool")] + public static void cabi_post_wasmExportReturnsPrimitiveBool(int returnValue) { + Console.WriteLine("TODO: cabi_post_returns-primitive-bool"); + } + + [UnmanagedCallersOnly(EntryPoint = "returns-primitive-char")] + public static unsafe int wasmExportReturnsPrimitiveChar() { + + uint ret; + ret = LibraryWorldImpl.ReturnsPrimitiveChar(); + return ((int)ret); + + } + + [UnmanagedCallersOnly(EntryPoint = "cabi_post_returns-primitive-char")] + public static void cabi_post_wasmExportReturnsPrimitiveChar(int returnValue) { + Console.WriteLine("TODO: cabi_post_returns-primitive-char"); + } + + [UnmanagedCallersOnly(EntryPoint = "ensure-managed-class-loaders")] + public static unsafe void wasmExportEnsureManagedClassLoaders() { + + LibraryWorldImpl.EnsureManagedClassLoaders(); + + } + + [UnmanagedCallersOnly(EntryPoint = "check-simple-exception-handling")] + public static unsafe int wasmExportCheckSimpleExceptionHandling() { + + int ret; + ret = LibraryWorldImpl.CheckSimpleExceptionHandling(); + return ret; + + } + + [UnmanagedCallersOnly(EntryPoint = "cabi_post_check-simple-exception-handling")] + public static void cabi_post_wasmExportCheckSimpleExceptionHandling(int returnValue) { + Console.WriteLine("TODO: cabi_post_check-simple-exception-handling"); + } + + [UnmanagedCallersOnly(EntryPoint = "check-simple-gc-collect")] + public static unsafe int wasmExportCheckSimpleGcCollect() { + + int ret; + ret = LibraryWorldImpl.CheckSimpleGcCollect(); + return ret; + + } + + [UnmanagedCallersOnly(EntryPoint = "cabi_post_check-simple-gc-collect")] + public static void cabi_post_wasmExportCheckSimpleGcCollect(int returnValue) { + Console.WriteLine("TODO: cabi_post_check-simple-gc-collect"); + } + + } + } + +} diff --git a/src/tests/nativeaot/SmokeTests/SharedLibrary/LibraryWorld_component_type.wit b/src/tests/nativeaot/SmokeTests/SharedLibrary/LibraryWorld_component_type.wit new file mode 100644 index 000000000000..3dd01916452a --- /dev/null +++ b/src/tests/nativeaot/SmokeTests/SharedLibrary/LibraryWorld_component_type.wit @@ -0,0 +1,11 @@ +package local:local; + +world library { + export test-http: func(port: u16); + export returns-primitive-int: func() -> s32; + export returns-primitive-bool: func() -> bool; + export returns-primitive-char: func() -> char; + export ensure-managed-class-loaders: func(); + export check-simple-exception-handling: func() -> s32; + export check-simple-gc-collect: func() -> s32; +} diff --git a/src/tests/nativeaot/SmokeTests/SharedLibrary/SharedLibrary.cs b/src/tests/nativeaot/SmokeTests/SharedLibrary/SharedLibrary.cs index a6c2c7e74ec1..d501963c8c17 100644 --- a/src/tests/nativeaot/SmokeTests/SharedLibrary/SharedLibrary.cs +++ b/src/tests/nativeaot/SmokeTests/SharedLibrary/SharedLibrary.cs @@ -2,8 +2,15 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Net.Http; +using System.Net.Http.Headers; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; namespace SharedLibrary { @@ -36,6 +43,11 @@ public static void EnsureManagedClassLoaders() [UnmanagedCallersOnly(EntryPoint = "CheckSimpleExceptionHandling", CallConvs = new Type[] { typeof(CallConvStdcall) })] public static int CheckSimpleExceptionHandling() + { + return DoCheckSimpleExceptionHandling(); + } + + public static int DoCheckSimpleExceptionHandling() { int result = 10; @@ -79,6 +91,11 @@ private static void MakeGarbage() [UnmanagedCallersOnly(EntryPoint = "CheckSimpleGCCollect", CallConvs = new Type[] { typeof(CallConvStdcall) })] public static int CheckSimpleGCCollect() + { + return DoCheckSimpleGCCollect(); + } + + public static int DoCheckSimpleGCCollect() { string myString = string.Format("Hello {0}", "world"); @@ -93,3 +110,119 @@ public static int CheckSimpleGCCollect() } } } + +// Implements the component model interface defined in wit/world.wit +namespace LibraryWorld +{ + public class LibraryWorldImpl : ILibraryWorld + { + public static void TestHttp(ushort port) + { + var task = TestHttpAsync(port); + while (!task.IsCompleted) + { + WasiEventLoop.DispatchWasiEventLoop(); + } + var exception = task.Exception; + if (exception is not null) + { + throw exception; + } + } + + private static async Task TestHttpAsync(ushort port) + { + using var client = new HttpClient(); + + Trace.Assert(client.Timeout.Equals(Timeout.InfiniteTimeSpan)); + + try { + client.Timeout = TimeSpan.FromSeconds(100); + throw new Exception("expected PlatformNotSupportedException when setting HttpClient.Timeout"); + } catch (PlatformNotSupportedException e) { + // This is expected until `System.Threading.Timer` is implemented for WASI. + } + + var urlBase = $"http://127.0.0.1:{port}"; + { + var response = await client.GetAsync($"{urlBase}/hello"); + response.EnsureSuccessStatusCode(); + Trace.Assert( + 4 == response.Content.Headers.ContentLength, + $"unexpected content length: {response.Content.Headers.ContentLength}" + ); + Trace.Assert( + "text/plain".Equals(response.Content.Headers.ContentType.ToString()), + $"unexpected content type: \"{response.Content.Headers.ContentType}\"" + ); + var content = await response.Content.ReadAsStringAsync(); + Trace.Assert("hola".Equals(content), $"unexpected content: \"{content}\""); + } + + { + var length = 10 * 1024 * 1024; + var body = new byte[length]; + new Random().NextBytes(body); + + var content = new StreamContent(new MemoryStream(body)); + var type = "application/octet-stream"; + content.Headers.ContentType = new MediaTypeHeaderValue(type); + + var response = await client.PostAsync($"{urlBase}/echo", content); + response.EnsureSuccessStatusCode(); + Trace.Assert( + length == response.Content.Headers.ContentLength, + $"unexpected content length: {response.Content.Headers.ContentLength}" + ); + Trace.Assert( + type.Equals(response.Content.Headers.ContentType.ToString()), + $"unexpected content type: \"{response.Content.Headers.ContentType}\"" + ); + var received = await response.Content.ReadAsByteArrayAsync(); + Trace.Assert(body.SequenceEqual(received), "unexpected content"); + } + } + + public static int ReturnsPrimitiveInt() + { + return 10; + } + + public static bool ReturnsPrimitiveBool() + { + return true; + } + + public static uint ReturnsPrimitiveChar() + { + return (uint)'a'; + } + + public static void EnsureManagedClassLoaders() + { + Random random = new Random(); + random.Next(); + } + + public static int CheckSimpleExceptionHandling() + { + return SharedLibrary.ClassLibrary.DoCheckSimpleExceptionHandling(); + } + + public static int CheckSimpleGcCollect() + { + return SharedLibrary.ClassLibrary.DoCheckSimpleGCCollect(); + } + } + + internal static class WasiEventLoop + { + internal static void DispatchWasiEventLoop() + { + CallDispatchWasiEventLoop((Thread)null!); + + [UnsafeAccessor(UnsafeAccessorKind.StaticMethod, Name = "DispatchWasiEventLoop")] + static extern void CallDispatchWasiEventLoop(Thread t); + } + } +} diff --git a/src/tests/nativeaot/SmokeTests/SharedLibrary/SharedLibrary.csproj b/src/tests/nativeaot/SmokeTests/SharedLibrary/SharedLibrary.csproj index 3c68ba09581d..800baeea78b9 100644 --- a/src/tests/nativeaot/SmokeTests/SharedLibrary/SharedLibrary.csproj +++ b/src/tests/nativeaot/SmokeTests/SharedLibrary/SharedLibrary.csproj @@ -30,6 +30,7 @@ cp SharedLibraryDriver native/SharedLibrary + @@ -55,5 +56,6 @@ cp SharedLibraryDriver$(NativeExtension) native/SharedLibrary$(NativeExtension) + diff --git a/src/tests/nativeaot/SmokeTests/SharedLibrary/SharedLibraryDriver.mjs b/src/tests/nativeaot/SmokeTests/SharedLibrary/SharedLibraryDriver.mjs index 434aab734efd..8d48c93d8aed 100644 --- a/src/tests/nativeaot/SmokeTests/SharedLibrary/SharedLibraryDriver.mjs +++ b/src/tests/nativeaot/SmokeTests/SharedLibrary/SharedLibraryDriver.mjs @@ -1,37 +1,97 @@ -import { readFile } from 'node:fs/promises'; -import { WASI } from 'wasi'; -import { argv, env } from 'node:process'; +import { Worker, parentPort, isMainThread } from 'node:worker_threads'; +import { readFile, writeFile } from 'node:fs/promises'; +import { transpile } from '@bytecodealliance/jco'; +import { _setPreopens } from '@bytecodealliance/preview2-shim/filesystem'; +import * as http from 'node:http'; -const wasi = new WASI({ - version: 'preview1', - args: argv, - env -}); +// Note that `jco` implements `wasi:io` by synchronously dispatching to worker +// threads. That means that when we run `HttpClient` smoke test below, it will +// block the main thread waiting for I/O. Therefore, the HTTP server we launch +// for that test needs to run in a dedicated thread rather than the main thread. -const wasm = await WebAssembly.compile( - await readFile(new URL("./SharedLibrary.wasm", import.meta.url)), -); +if (isMainThread) { + // Run the tests + const base = import.meta.url; + const component = await readFile(new URL("./SharedLibrary.wasm", base)); + const transpiled = await transpile(component, { + name: "shared-library", + typescript: false, + }); + await writeFile(new URL("./shared-library.core.wasm", base), transpiled.files["shared-library.core.wasm"]); + await writeFile(new URL("./shared-library.core2.wasm", base), transpiled.files["shared-library.core2.wasm"]); + await writeFile(new URL("./shared-library.core3.wasm", base), transpiled.files["shared-library.core3.wasm"]); + await writeFile(new URL("./shared-library.mjs", base), transpiled.files["shared-library.js"]); + _setPreopens([]); + const instance = await import(new URL("./shared-library.mjs", base)); -const instance = await WebAssembly.instantiate(wasm, wasi.getImportObject()); + // Spawn a worker thread to run the HTTP server and feed the port number + // it's listening on back to us when ready: + const port = await new Promise((resolve, reject) => { + const worker = new Worker(new URL("./SharedLibrary.mjs", base)); + worker.on("message", resolve); + worker.on("error", reject); + worker.on("exit", (code) => { + reject(new Error(`worker stopped with exit code ${code}`)); + }); + }); -wasi.initialize(instance); + instance.testHttp(port); -if (instance.exports.ReturnsPrimitiveInt() != 10) - process.exit(1); + if (instance.returnsPrimitiveInt() != 10) + process.exit(1); -if (instance.exports.ReturnsPrimitiveBool() != 1) - process.exit(2); + if (instance.returnsPrimitiveBool() != 1) + process.exit(2); -if (instance.exports.ReturnsPrimitiveChar() != 97) // 'a' - process.exit(3); + if (instance.returnsPrimitiveChar() != 'a') + process.exit(3); -// As long as no unmanaged exception is thrown managed class loaders were initialized successfully. -instance.exports.EnsureManagedClassLoaders(); + // As long as no unmanaged exception is thrown managed class loaders were initialized successfully. + instance.ensureManagedClassLoaders(); -if (instance.exports.CheckSimpleGCCollect() != 100) - process.exit(4); + if (instance.checkSimpleGcCollect() != 100) + process.exit(4); -if (instance.exports.CheckSimpleExceptionHandling() != 100) - process.exit(5); + if (instance.checkSimpleExceptionHandling() != 100) + process.exit(5); -process.exit(100); + process.exit(100); +} else { + // Run the HTTP server + const server = http.createServer((req, res) => { + if (req.method === "POST" && req.url === "/echo") { + // Note that we buffer the request body here rather than pipe it + // directly to the response. That's because, as of this writing, + // `WasiHttpHandler` sends the entire request body before reading + // any of the response body, which can lead to deadlock if the + // server is blocked on backpressure when sending the response body. + let chunks = []; + req.on("data", (chunk) => { + chunks.push(chunk); + }); + req.on("end", () => { + res.writeHead(200, req.headers); + res.end(Buffer.concat(chunks)); + }); + } else { + let status; + let body; + if (req.method === "GET" && req.url === "/hello") { + status = 200; + body = "hola"; + } else { + status = 400; + body = "Bad Request"; + } + res + .writeHead(status, { + "content-length": Buffer.byteLength(body), + "content-type": "text/plain", + }) + .end(body); + } + }); + server.listen(() => { + parentPort.postMessage(server.address().port); + }); +} diff --git a/src/tests/nativeaot/SmokeTests/SharedLibrary/generate-shared-library-bindings.sh b/src/tests/nativeaot/SmokeTests/SharedLibrary/generate-shared-library-bindings.sh new file mode 100644 index 000000000000..d546d26287c8 --- /dev/null +++ b/src/tests/nativeaot/SmokeTests/SharedLibrary/generate-shared-library-bindings.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +set -ex + +# This script will regenerate the `wit-bindgen`-generated files in this +# directory. + +# Prerequisites: +# POSIX shell +# tar +# [cargo](https://rustup.rs/) +# [curl](https://curl.se/download.html) + +cargo install --locked --no-default-features --features csharp --version 0.28.0 wit-bindgen-cli +wit-bindgen c-sharp -w library -r native-aot wit +rm LibraryWorld_wasm_import_linkage_attribute.cs LibraryWorld_cabi_realloc.c LibraryWorld_component_type.o diff --git a/src/tests/nativeaot/SmokeTests/SharedLibrary/package-lock.json b/src/tests/nativeaot/SmokeTests/SharedLibrary/package-lock.json new file mode 100644 index 000000000000..0b2ea4e1793b --- /dev/null +++ b/src/tests/nativeaot/SmokeTests/SharedLibrary/package-lock.json @@ -0,0 +1,698 @@ +{ + "name": "sharedlibrarytest", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "sharedlibrarytest", + "version": "1.0.0", + "dependencies": { + "@bytecodealliance/jco": "1.3.1" + } + }, + "node_modules/@bytecodealliance/jco": { + "version": "1.3.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@bytecodealliance/jco/-/jco-1.3.1.tgz", + "integrity": "sha1-k/ZHBglXNPz66y9DL7JIuXLuFeg=", + "license": "(Apache-2.0 WITH LLVM-exception)", + "workspaces": [ + "packages/preview2-shim" + ], + "dependencies": { + "@bytecodealliance/preview2-shim": "^0.16.3", + "binaryen": "^116.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.4", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@bytecodealliance/preview2-shim/-/preview2-shim-0.16.4.tgz", + "integrity": "sha1-Y3CfvaiO8u7hxJLiGP3+GWPOIaw=", + "license": "(Apache-2.0 WITH LLVM-exception)" + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha1-3M5q/3S99trRqVgCtpsEovyx+zY=", + "license": "MIT", + "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://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha1-eg7mAfYPmaIMfHxf8MgDiMEYm9Y=", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha1-VY+2Ry7RakyFC4iVMOazZDjEkoA=", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.6", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha1-nXHKiG4yUC65NiyadKRnh8Nt+Bo=", + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha1-18bmdVx4VnqVHgSrUu8P0m3lnzI=", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha1-FfGQ6YiV8/wjJ27hS8drZ1wuUPA=", + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/acorn": { + "version": "8.12.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha1-cWFr3MviXielRDngBG6JynbfIkg=", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha1-MYPjj66aZdfLXlOUXNWJfQJgoGo=", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/binaryen": { + "version": "116.0.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/binaryen/-/binaryen-116.0.0.tgz", + "integrity": "sha1-rXn7k5JGE4+xKNlDjVV0FS7OOf4=", + "license": "Apache-2.0", + "bin": { + "wasm-opt": "bin/wasm-opt", + "wasm2js": "bin/wasm2js" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha1-KxRqb9cugLT1XSVfNe1Zo6mkG9U=", + "license": "MIT" + }, + "node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha1-Z8IKfr73Dn85cKAfkPohDLaGA4U=", + "license": "MIT", + "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://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/chalk-template/-/chalk-template-1.1.0.tgz", + "integrity": "sha1-/8Vdtt10XpOUuFMnyKyEZu23p7E=", + "license": "MIT", + "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://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/cli-cursor/-/cli-cursor-4.0.0.tgz", + "integrity": "sha1-POz+NzS/T+Aqg2HL3A9v4oxqV+o=", + "license": "MIT", + "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://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha1-F3Oo9LnE1qwxVj31Oz/B15Ri/kE=", + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/commander": { + "version": "12.1.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/commander/-/commander-12.1.0.tgz", + "integrity": "sha1-AUI7NvUBJZ/arE0OTWDJbJkVhdM=", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/emoji-regex": { + "version": "10.3.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha1-dpmLkmhAnrPa496YklTUVucM/iM=", + "license": "MIT" + }, + "node_modules/get-east-asian-width": { + "version": "1.2.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz", + "integrity": "sha1-Xm69m67m+4t7a9UFIhBl8M2R9k4=", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-interactive": { + "version": "2.0.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/is-interactive/-/is-interactive-2.0.0.tgz", + "integrity": "sha1-QMV2FFk4JtoRAK3mBZd41ZfxbpA=", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-unicode-supported": { + "version": "2.0.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/is-unicode-supported/-/is-unicode-supported-2.0.0.tgz", + "integrity": "sha1-/fMt+a6Y/2qyztwVWlpuiVcBxFE=", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-symbols": { + "version": "6.0.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/log-symbols/-/log-symbols-6.0.0.tgz", + "integrity": "sha1-u5Xl8FMiZRysMMD+tkBPnyqKlDk=", + "license": "MIT", + "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://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", + "integrity": "sha1-2CSYS2FsKSouGYIH1KYJmDhC9xQ=", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha1-ftLCzMyvhNP/y3pptXcR/CCDQBs=", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/mkdirp": { + "version": "3.0.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha1-5E5MVgf7J5wWgkFxPMbg/qmty1A=", + "license": "MIT", + "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://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha1-0Oluu1awdHbfHdnEgG5SN5hcpF4=", + "license": "MIT", + "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://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/ora/-/ora-8.0.1.tgz", + "integrity": "sha1-bcuSUKYpZCy+DS3zpjMa1veirz4=", + "license": "MIT", + "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://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/restore-cursor/-/restore-cursor-4.0.0.tgz", + "integrity": "sha1-UZVgpDGJdQlt725gnUQQDtqkzLk=", + "license": "MIT", + "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://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha1-qaF2f4r4QVURTqq9c/mSc8j1mtk=", + "license": "ISC" + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha1-BP58f54e0tZiIzwoyys1ufY/bk8=", + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/stdin-discarder": { + "version": "0.2.2", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/stdin-discarder/-/stdin-discarder-0.2.2.tgz", + "integrity": "sha1-OQA39ExK4aGuU1xf443Dq6jZl74=", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha1-tbuOIWXOJ11NQ0dt0nAK2Qkdttw=", + "license": "MIT", + "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://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha1-1bZWjKaJ2FYTcLBwdoXSJDT6/0U=", + "license": "MIT", + "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.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/terser/-/terser-5.31.1.tgz", + "integrity": "sha1-c13jyYfdZx6VGQ5rmM/i8H888NQ=", + "license": "BSD-2-Clause", + "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://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/commander/-/commander-2.20.3.tgz", + "integrity": "sha1-/UhehMA+tIgcIHIrpIA16FMa6zM=", + "license": "MIT" + } + }, + "dependencies": { + "@bytecodealliance/jco": { + "version": "1.3.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@bytecodealliance/jco/-/jco-1.3.1.tgz", + "integrity": "sha1-k/ZHBglXNPz66y9DL7JIuXLuFeg=", + "requires": { + "@bytecodealliance/preview2-shim": "^0.16.3", + "binaryen": "^116.0.0", + "chalk-template": "^1", + "commander": "^12", + "mkdirp": "^3", + "ora": "^8", + "terser": "^5" + } + }, + "@bytecodealliance/preview2-shim": { + "version": "0.16.4", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@bytecodealliance/preview2-shim/-/preview2-shim-0.16.4.tgz", + "integrity": "sha1-Y3CfvaiO8u7hxJLiGP3+GWPOIaw=" + }, + "@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha1-3M5q/3S99trRqVgCtpsEovyx+zY=", + "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://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha1-eg7mAfYPmaIMfHxf8MgDiMEYm9Y=" + }, + "@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha1-VY+2Ry7RakyFC4iVMOazZDjEkoA=" + }, + "@jridgewell/source-map": { + "version": "0.3.6", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha1-nXHKiG4yUC65NiyadKRnh8Nt+Bo=", + "requires": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha1-18bmdVx4VnqVHgSrUu8P0m3lnzI=" + }, + "@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha1-FfGQ6YiV8/wjJ27hS8drZ1wuUPA=", + "requires": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "acorn": { + "version": "8.12.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha1-cWFr3MviXielRDngBG6JynbfIkg=" + }, + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha1-MYPjj66aZdfLXlOUXNWJfQJgoGo=" + }, + "binaryen": { + "version": "116.0.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/binaryen/-/binaryen-116.0.0.tgz", + "integrity": "sha1-rXn7k5JGE4+xKNlDjVV0FS7OOf4=" + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha1-KxRqb9cugLT1XSVfNe1Zo6mkG9U=" + }, + "chalk": { + "version": "5.3.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha1-Z8IKfr73Dn85cKAfkPohDLaGA4U=" + }, + "chalk-template": { + "version": "1.1.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/chalk-template/-/chalk-template-1.1.0.tgz", + "integrity": "sha1-/8Vdtt10XpOUuFMnyKyEZu23p7E=", + "requires": { + "chalk": "^5.2.0" + } + }, + "cli-cursor": { + "version": "4.0.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/cli-cursor/-/cli-cursor-4.0.0.tgz", + "integrity": "sha1-POz+NzS/T+Aqg2HL3A9v4oxqV+o=", + "requires": { + "restore-cursor": "^4.0.0" + } + }, + "cli-spinners": { + "version": "2.9.2", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha1-F3Oo9LnE1qwxVj31Oz/B15Ri/kE=" + }, + "commander": { + "version": "12.1.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/commander/-/commander-12.1.0.tgz", + "integrity": "sha1-AUI7NvUBJZ/arE0OTWDJbJkVhdM=" + }, + "emoji-regex": { + "version": "10.3.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha1-dpmLkmhAnrPa496YklTUVucM/iM=" + }, + "get-east-asian-width": { + "version": "1.2.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz", + "integrity": "sha1-Xm69m67m+4t7a9UFIhBl8M2R9k4=" + }, + "is-interactive": { + "version": "2.0.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/is-interactive/-/is-interactive-2.0.0.tgz", + "integrity": "sha1-QMV2FFk4JtoRAK3mBZd41ZfxbpA=" + }, + "is-unicode-supported": { + "version": "2.0.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/is-unicode-supported/-/is-unicode-supported-2.0.0.tgz", + "integrity": "sha1-/fMt+a6Y/2qyztwVWlpuiVcBxFE=" + }, + "log-symbols": { + "version": "6.0.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/log-symbols/-/log-symbols-6.0.0.tgz", + "integrity": "sha1-u5Xl8FMiZRysMMD+tkBPnyqKlDk=", + "requires": { + "chalk": "^5.3.0", + "is-unicode-supported": "^1.3.0" + }, + "dependencies": { + "is-unicode-supported": { + "version": "1.3.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", + "integrity": "sha1-2CSYS2FsKSouGYIH1KYJmDhC9xQ=" + } + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha1-ftLCzMyvhNP/y3pptXcR/CCDQBs=" + }, + "mkdirp": { + "version": "3.0.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha1-5E5MVgf7J5wWgkFxPMbg/qmty1A=" + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha1-0Oluu1awdHbfHdnEgG5SN5hcpF4=", + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "ora": { + "version": "8.0.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/ora/-/ora-8.0.1.tgz", + "integrity": "sha1-bcuSUKYpZCy+DS3zpjMa1veirz4=", + "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://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/restore-cursor/-/restore-cursor-4.0.0.tgz", + "integrity": "sha1-UZVgpDGJdQlt725gnUQQDtqkzLk=", + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha1-qaF2f4r4QVURTqq9c/mSc8j1mtk=" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=" + }, + "source-map-support": { + "version": "0.5.21", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha1-BP58f54e0tZiIzwoyys1ufY/bk8=", + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "stdin-discarder": { + "version": "0.2.2", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/stdin-discarder/-/stdin-discarder-0.2.2.tgz", + "integrity": "sha1-OQA39ExK4aGuU1xf443Dq6jZl74=" + }, + "string-width": { + "version": "7.2.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha1-tbuOIWXOJ11NQ0dt0nAK2Qkdttw=", + "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://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha1-1bZWjKaJ2FYTcLBwdoXSJDT6/0U=", + "requires": { + "ansi-regex": "^6.0.1" + } + }, + "terser": { + "version": "5.31.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/terser/-/terser-5.31.1.tgz", + "integrity": "sha1-c13jyYfdZx6VGQ5rmM/i8H888NQ=", + "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://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/commander/-/commander-2.20.3.tgz", + "integrity": "sha1-/UhehMA+tIgcIHIrpIA16FMa6zM=" + } + } + } + } +} diff --git a/src/tests/nativeaot/SmokeTests/SharedLibrary/package.json b/src/tests/nativeaot/SmokeTests/SharedLibrary/package.json new file mode 100644 index 000000000000..3d278ba3cb3e --- /dev/null +++ b/src/tests/nativeaot/SmokeTests/SharedLibrary/package.json @@ -0,0 +1,11 @@ +{ + "name": "sharedlibrarytest", + "type": "module", + "version": "1.0.0", + "scripts": { + "test": "node SharedLibraryDriver.mjs" + }, + "dependencies": { + "@bytecodealliance/jco": "1.3.1" + } +} \ No newline at end of file diff --git a/src/tests/nativeaot/SmokeTests/SharedLibrary/wit/world.wit b/src/tests/nativeaot/SmokeTests/SharedLibrary/wit/world.wit new file mode 100644 index 000000000000..3dd01916452a --- /dev/null +++ b/src/tests/nativeaot/SmokeTests/SharedLibrary/wit/world.wit @@ -0,0 +1,11 @@ +package local:local; + +world library { + export test-http: func(port: u16); + export returns-primitive-int: func() -> s32; + export returns-primitive-bool: func() -> bool; + export returns-primitive-char: func() -> char; + export ensure-managed-class-loaders: func(); + export check-simple-exception-handling: func() -> s32; + export check-simple-gc-collect: func() -> s32; +} diff --git a/src/tests/nativeaot/SmokeTests/StackTraceMetadata/StackTraceMetadata.cs b/src/tests/nativeaot/SmokeTests/StackTraceMetadata/StackTraceMetadata.cs index dcc4613f91a3..4bdc41945bc5 100644 --- a/src/tests/nativeaot/SmokeTests/StackTraceMetadata/StackTraceMetadata.cs +++ b/src/tests/nativeaot/SmokeTests/StackTraceMetadata/StackTraceMetadata.cs @@ -22,7 +22,7 @@ static int Main() const bool expected = true; #endif bool actual = stackTrace.Contains(nameof(Main)) && stackTrace.Contains(nameof(Program)); - return expected == actual ? 100 : 1; + return expected == actual ? 0 : 1; } class DiagnosticMethodInfoTests diff --git a/src/tests/nativeaot/SmokeTests/StackTraceMetadata/StackTraceMetadata.csproj b/src/tests/nativeaot/SmokeTests/StackTraceMetadata/StackTraceMetadata.csproj index 2b2a43eff8dd..8e23b74590a2 100644 --- a/src/tests/nativeaot/SmokeTests/StackTraceMetadata/StackTraceMetadata.csproj +++ b/src/tests/nativeaot/SmokeTests/StackTraceMetadata/StackTraceMetadata.csproj @@ -7,6 +7,7 @@ true true + 0 diff --git a/src/tests/nativeaot/SmokeTests/StackTraceMetadata/StackTraceMetadata_Stripped.csproj b/src/tests/nativeaot/SmokeTests/StackTraceMetadata/StackTraceMetadata_Stripped.csproj index 28a98ff79570..1acbe8ed9a70 100644 --- a/src/tests/nativeaot/SmokeTests/StackTraceMetadata/StackTraceMetadata_Stripped.csproj +++ b/src/tests/nativeaot/SmokeTests/StackTraceMetadata/StackTraceMetadata_Stripped.csproj @@ -9,6 +9,7 @@ true $(DefineConstants);STRIPPED false + 0 diff --git a/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/Main.cs b/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/Main.cs index 7a46f41961da..63fc11493f09 100644 --- a/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/Main.cs +++ b/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/Main.cs @@ -10,7 +10,7 @@ success &= RunTest(ILLinkDescriptor.Run); success &= RunTest(DependencyInjectionPattern.Run); -return success ? 100 : 1; +return success ? 0 : 1; static bool RunTest(Func t, [CallerArgumentExpression("t")] string name = null) { diff --git a/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/TrimmingBehaviors.csproj b/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/TrimmingBehaviors.csproj index c69f6e042a57..60a11257c66b 100644 --- a/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/TrimmingBehaviors.csproj +++ b/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/TrimmingBehaviors.csproj @@ -7,6 +7,7 @@ true + 0 diff --git a/src/tests/nativeaot/SmokeTests/UnitTests/Main.cs b/src/tests/nativeaot/SmokeTests/UnitTests/Main.cs index a3bb605a4c09..6aa9dffa2420 100644 --- a/src/tests/nativeaot/SmokeTests/UnitTests/Main.cs +++ b/src/tests/nativeaot/SmokeTests/UnitTests/Main.cs @@ -20,7 +20,7 @@ success &= RunTest(StackTraces.Run); #endif -return success ? 100 : 1; +return success ? 0 : 1; static bool RunTest(Func t, [CallerArgumentExpression("t")] string name = null) { diff --git a/src/tests/nativeaot/SmokeTests/UnitTests/UnitTests.csproj b/src/tests/nativeaot/SmokeTests/UnitTests/UnitTests.csproj index e097c82aba9d..c738285e2161 100644 --- a/src/tests/nativeaot/SmokeTests/UnitTests/UnitTests.csproj +++ b/src/tests/nativeaot/SmokeTests/UnitTests/UnitTests.csproj @@ -7,6 +7,7 @@ true $(NoWarn);IL3050;IL3054 + 0