diff --git a/docs/workflow/building/coreclr/wasm.md b/docs/workflow/building/coreclr/wasm.md index 00064df946a46f..b2c6caa2d495d6 100644 --- a/docs/workflow/building/coreclr/wasm.md +++ b/docs/workflow/building/coreclr/wasm.md @@ -61,15 +61,27 @@ This will start a local HTTP server and you can open the provided URL in your br ### Console Testing You can also run the runtime directly in Node.js: +In script below please replace `/path/to/runtime/` by a **absolute unix path** to the actual runtime repo (even on Windows). ```bash -cp /runtime3/artifacts/bin/microsoft.netcore.app.runtime.browser-wasm/Debug/runtimes/browser-wasm/lib/net10.0/*.dll /runtime3/artifacts/bin/coreclr/browser.wasm.Debug/IL -cp helloworld.dll /runtime3/artifacts/bin/coreclr/browser.wasm.Debug/IL -cd /runtime3/artifacts/bin/coreclr/browser.wasm.Debug/ -node ./corerun.js -c /runtime3/artifacts/bin/coreclr/browser.wasm.Debug/IL /runtime3/artifacts/bin/coreclr/browser.wasm.Debug/IL/helloworld.dll +cp ./artifacts/bin/microsoft.netcore.app.runtime.browser-wasm/Debug/runtimes/browser-wasm/lib/net10.0/*.dll ./artifacts/bin/coreclr/browser.wasm.Debug/IL +cp helloworld.dll ./artifacts/bin/coreclr/browser.wasm.Debug/IL +cd ./artifacts/bin/coreclr/browser.wasm.Debug/ +node ./corerun.js -c /path/to/runtime/artifacts/bin/coreclr/browser.wasm.Debug/IL /path/to/runtime/artifacts/bin/coreclr/browser.wasm.Debug/IL/helloworld.dll ``` -Note that path in the node args need to be **absolute path** on your host file system in **unix format** (even on Windows). +### Console Testing with corehost + +You can also run the corehost directly in Node.js: + +```bash +cp ./artifacts/bin/microsoft.netcore.app.runtime.browser-wasm/Debug/runtimes/browser-wasm/lib/net10.0/*.dll ./artifacts/bin/coreclr/browser.wasm.Debug/corehost +cp helloworld.dll ./artifacts/bin/coreclr/browser.wasm.Debug/corehost +cd ./artifacts/bin/coreclr/browser.wasm.Debug/corehost +node ./main.mjs +``` + +Note that paths to assemblies are in the `src/native/corehost/browserhost/sample/dotnet.boot.js` ## Debugging @@ -97,6 +109,9 @@ VS Code, through Node.js, provides a good debugging option for WebAssembly CoreC - [WebAssembly Dwarf Debugging](https://marketplace.visualstudio.com/items?itemName=ms-vscode.wasm-dwarf-debugging) 2. **Create a launch.json configuration:** + +In config below please replace `/path/to/runtime/` by a **absolute unix path** to the actual runtime repo (even on Windows). + ```json { "version": "0.2.0", @@ -111,12 +126,26 @@ VS Code, through Node.js, provides a good debugging option for WebAssembly CoreC "outputCapture": "std", "program": "corerun.js", "env": { - "CORE_ROOT":"/runtime3/artifacts/bin/coreclr/browser.wasm.Debug/IL/" + "CORE_ROOT":"/path/to/runtime/artifacts/bin/coreclr/browser.wasm.Debug/IL/" }, "args": [ - "/runtime3/artifacts/bin/coreclr/browser.wasm.Debug/IL/helloworld.dll" + "/path/to/runtime/artifacts/bin/coreclr/browser.wasm.Debug/IL/helloworld.dll" ], "cwd": "${workspaceFolder}/artifacts/bin/coreclr/browser.wasm.Debug/" + }, + { + "name": "browserhost", + "type": "node", + "request": "launch", + "skipFiles": [ + "/**" + ], + "args": [ + "HelloWorld.dll" + ], + "outputCapture": "std", + "cwd": "${workspaceFolder}/artifacts/bin/coreclr/browser.wasm.Debug/corehost", + "program": "main.mjs", } ] } diff --git a/eng/pipelines/common/evaluate-default-paths.yml b/eng/pipelines/common/evaluate-default-paths.yml index 2ac74a96249d2e..80fd14756e59c0 100644 --- a/eng/pipelines/common/evaluate-default-paths.yml +++ b/eng/pipelines/common/evaluate-default-paths.yml @@ -43,6 +43,10 @@ parameters: src/tasks/Microsoft.NET.WebAssembly.Webcil/* src/tests/Common/wasm-test-runner/* src/coreclr/vm/wasm/* + src/native/corehost/browserhost/* + src/native/libs/Common/JavaScript/* + src/native/libs/System.Native.Browser/* + src/native/libs/System.Runtime.InteropServices.JavaScript.Native/* ] _wasm_pipelines: [ eng/pipelines/**/*wasm* @@ -57,6 +61,10 @@ parameters: src/native/libs/System.Globalization.Native/* src/native/libs/System.IO.Compression.Native/* src/native/libs/System.Native/* + src/native/corehost/browserhost/* + src/native/libs/Common/JavaScript/* + src/native/libs/System.Native.Browser/* + src/native/libs/System.Runtime.InteropServices.JavaScript.Native/* ] _wasm_chrome: [ eng/testing/bump-chrome-version.proj diff --git a/src/coreclr/CMakeLists.txt b/src/coreclr/CMakeLists.txt index 8913fbd7899ed6..e0b3dc71482d4f 100644 --- a/src/coreclr/CMakeLists.txt +++ b/src/coreclr/CMakeLists.txt @@ -69,8 +69,12 @@ if(NOT CLR_CROSS_COMPONENTS_BUILD AND NOT CLR_CMAKE_TARGET_MACCATALYST AND NOT C add_dependencies(runtime singlefilehost) else() if(CLR_CMAKE_TARGET_BROWSER) - # TODOWASM set GEN_PINVOKE to 1 once we generate them. static entrypoint.c prevents C linker from trimming, when IL trimming trims PInvokes + # WASM-TODO set GEN_PINVOKE to 1 once we generate them. static entrypoint.c prevents C linker from trimming, when IL trimming trims PInvokes set(GEN_PINVOKE 0) + # WASM-TODO should we start using System.Native.Browser and System.Runtime.InteropServices.JavaScript.Native also for Mono ? + set(BUILD_LIBS_NATIVE_BROWSER 1) + add_subdirectory(${CLR_SRC_NATIVE_DIR}/corehost browserhost) + add_dependencies(runtime browserhost) endif() endif() diff --git a/src/coreclr/hosts/corerun/CMakeLists.txt b/src/coreclr/hosts/corerun/CMakeLists.txt index ba96616399d25c..9dec6dcc2cdbaa 100644 --- a/src/coreclr/hosts/corerun/CMakeLists.txt +++ b/src/coreclr/hosts/corerun/CMakeLists.txt @@ -52,15 +52,24 @@ else(CLR_CMAKE_HOST_WIN32) # linker options for NodeJs, link in JavaScript helper, access to local filesystem if (CLR_CMAKE_TARGET_BROWSER) target_compile_options(corerun PRIVATE -fwasm-exceptions) + target_link_libraries(corerun PRIVATE + System.Native.Browser-Static) + set(JS_SYSTEM_NATIVE_BROWSER + "${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Native.Browser/libSystem.Native.Browser.js") + set(JS_CORE_RUN_PRE + "${CMAKE_CURRENT_SOURCE_DIR}/libCorerun.pre.js") + set_target_properties(corerun PROPERTIES + LINK_DEPENDS "${JS_CORE_RUN_PRE};${JS_SYSTEM_NATIVE_BROWSER};" + LINK_FLAGS "--pre-js ${JS_CORE_RUN_PRE} --js-library ${JS_SYSTEM_NATIVE_BROWSER}" + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") target_link_options(corerun PRIVATE -fwasm-exceptions - -sEXPORTED_RUNTIME_METHODS=FS -sEXIT_RUNTIME=1 -sINITIAL_MEMORY=134217728 + -sENVIRONMENT=node,shell -sSTACK_SIZE=5MB -lnoderawfs.js -lnodefs.js - --pre-js ${CMAKE_CURRENT_SOURCE_DIR}/corerun.js -Wl,-error-limit=0) endif() endif() diff --git a/src/coreclr/hosts/corerun/corerun.js b/src/coreclr/hosts/corerun/corerun.js deleted file mode 100644 index e29d5cc7026cdc..00000000000000 --- a/src/coreclr/hosts/corerun/corerun.js +++ /dev/null @@ -1,6 +0,0 @@ -Module.preRun = () => { - // copy all node/shell env variables to emscripten env - for (const [key, value] of Object.entries(process.env)) { - ENV[key] = value; - } -}; \ No newline at end of file diff --git a/src/coreclr/hosts/corerun/libCorerun.pre.js b/src/coreclr/hosts/corerun/libCorerun.pre.js new file mode 100644 index 00000000000000..13aefa18b76e91 --- /dev/null +++ b/src/coreclr/hosts/corerun/libCorerun.pre.js @@ -0,0 +1,14 @@ +var dotnetInternals = { + runtimeApi: { + Module: Module, + }, + updates: [], +}; +Module.preRun = () => { + // copy all node/shell env variables to emscripten env + if (globalThis.process && globalThis.process.env) { + for (const [key, value] of Object.entries(process.env)) { + ENV[key] = value; + } + } +}; \ No newline at end of file diff --git a/src/coreclr/hosts/corewasmrun/CMakeLists.txt b/src/coreclr/hosts/corewasmrun/CMakeLists.txt index df0e158e0a815a..600866a94201f6 100644 --- a/src/coreclr/hosts/corewasmrun/CMakeLists.txt +++ b/src/coreclr/hosts/corewasmrun/CMakeLists.txt @@ -17,6 +17,15 @@ target_include_directories(corewasmrun PRIVATE ) target_compile_options(corewasmrun PRIVATE -fwasm-exceptions) + +set(JS_SYSTEM_NATIVE_BROWSER + "${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Native.Browser/libSystem.Native.Browser.js") +set(JS_CORE_WASM_RUN_PRE + "${CMAKE_CURRENT_SOURCE_DIR}/libCorewasmrun.pre.js") +set_target_properties(corewasmrun PROPERTIES + LINK_DEPENDS "${JS_CORE_WASM_RUN_PRE};${JS_SYSTEM_NATIVE_BROWSER};" + LINK_FLAGS "--pre-js ${JS_CORE_WASM_RUN_PRE} --js-library ${JS_SYSTEM_NATIVE_BROWSER}" + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") target_link_options(corewasmrun PRIVATE -fwasm-exceptions -sEXIT_RUNTIME=1 @@ -27,6 +36,7 @@ target_link_options(corewasmrun PRIVATE -Wl,-error-limit=0) target_link_libraries(corewasmrun PRIVATE coreclr_static + System.Native.Browser-Static System.Native-Static System.Native.TimeZoneData) diff --git a/src/coreclr/hosts/corewasmrun/libCorewasmrun.pre.js b/src/coreclr/hosts/corewasmrun/libCorewasmrun.pre.js new file mode 100644 index 00000000000000..f2dc1b77184106 --- /dev/null +++ b/src/coreclr/hosts/corewasmrun/libCorewasmrun.pre.js @@ -0,0 +1,6 @@ +var dotnetInternals = { + runtimeApi: { + Module: Module, + }, + updates: [], +}; diff --git a/src/coreclr/vm/dllimportcallback.cpp b/src/coreclr/vm/dllimportcallback.cpp index 3947a139990a70..341a538e9fd185 100644 --- a/src/coreclr/vm/dllimportcallback.cpp +++ b/src/coreclr/vm/dllimportcallback.cpp @@ -289,7 +289,7 @@ UMEntryThunkData* UMEntryThunkData::CreateUMEntryThunk() pData = (UMEntryThunkData *)pamTracker->Track(pLoaderAllocator->GetLowFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(UMEntryThunkData)))); UMEntryThunk* pThunk; #ifdef FEATURE_PORTABLE_ENTRYPOINTS - PORTABILITY_ASSERT("WASMTODO: Marshalled delegates are not supported with wasm."); + PORTABILITY_ASSERT("WASM-TODO: Marshalled delegates are not supported with wasm."); pThunk = NULL; #else // !FEATURE_PORTABLE_ENTRYPOINTS pThunk = (UMEntryThunk*)pamTracker->Track(pLoaderAllocator->GetNewStubPrecodeHeap()->AllocStub()); diff --git a/src/coreclr/vm/interpexec.cpp b/src/coreclr/vm/interpexec.cpp index bd5d445683d029..45ca634bd72143 100644 --- a/src/coreclr/vm/interpexec.cpp +++ b/src/coreclr/vm/interpexec.cpp @@ -2300,7 +2300,7 @@ void InterpExecMethod(InterpreterFrame *pInterpreterFrame, InterpMethodContextFr { PCODE calliFunctionPointer = LOCAL_VAR(calliFunctionPointerVar, PCODE); #ifdef FEATURE_PORTABLE_ENTRYPOINTS - // WASMTODO: We may end up here with native JIT helper entrypoint without MethodDesc + // WASM-TODO: We may end up here with native JIT helper entrypoint without MethodDesc // that CALL_INTERP_METHOD is not able to handle. This is a potential problem for // interpreter<->native code stub generator. // https://github.com/dotnet/runtime/pull/119516#discussion_r2337631271 diff --git a/src/coreclr/vm/wasm/helpers.cpp b/src/coreclr/vm/wasm/helpers.cpp index 23c8a03d13fe10..865089d30a9dcf 100644 --- a/src/coreclr/vm/wasm/helpers.cpp +++ b/src/coreclr/vm/wasm/helpers.cpp @@ -379,12 +379,6 @@ void _DacGlobals::Initialize() // Incorrectly typed temporary symbol to satisfy the linker. int g_pDebugger; -extern "C" int32_t SystemJS_RandomBytes(uint8_t* buffer, int32_t bufferLength) -{ - PORTABILITY_ASSERT("SystemJS_RandomBytes is not implemented"); - return -1; -} - void InvokeCalliStub(PCODE ftn, void* cookie, int8_t *pArgs, int8_t *pRet) { _ASSERTE(ftn != (PCODE)NULL); @@ -399,7 +393,7 @@ void InvokeUnmanagedCalli(PCODE ftn, void *cookie, int8_t *pArgs, int8_t *pRet) _ASSERTE(ftn != (PCODE)NULL); _ASSERTE(cookie != NULL); - // WASMTODO: Reconcile calling conventions. + // WASM-TODO: Reconcile calling conventions. ((void(*)(PCODE, int8_t*, int8_t*))cookie)(ftn, pArgs, pRet); } @@ -571,7 +565,7 @@ namespace case ELEMENT_TYPE_VALUETYPE: { // In WASM, values types that are larger than pointer size or have multiple fields are passed indirectly. - // WASMTODO: Single fields may not always be passed as i32. Floats and doubles are passed as f32 and f64 respectively. + // WASM-TODO: Single fields may not always be passed as i32. Floats and doubles are passed as f32 and f64 respectively. TypeHandle vt = isReturn ? sig.GetRetTypeHandleThrowing() : sig.GetLastTypeHandleThrowing(); diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props b/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props index c8ec9362231bf4..969316103d3db2 100644 --- a/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props +++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props @@ -100,6 +100,8 @@ + + diff --git a/src/native/.eslintignore b/src/native/.eslintignore new file mode 100644 index 00000000000000..7b605f50936ed9 --- /dev/null +++ b/src/native/.eslintignore @@ -0,0 +1,3 @@ +./corehost/browserhost/loader/dotnet.d.ts +./**/*.js +./**/*.mjs diff --git a/src/native/.eslintrc.cjs b/src/native/.eslintrc.cjs new file mode 100644 index 00000000000000..d2dac5fc310a7f --- /dev/null +++ b/src/native/.eslintrc.cjs @@ -0,0 +1,65 @@ +module.exports = { + "env": { + "browser": true, + "es2021": true, + "node": true + }, + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended" + ], + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaVersion": 12, + "sourceType": "module" + }, + "plugins": [ + "@typescript-eslint" + ], + "ignorePatterns": [ + "node_modules/**/*.*", + "bin/**/*.*", + "obj/**/*.*", + "**/*.js", + "**/*.mjs", + "dotnet.d.ts", + ], + "rules": { + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/no-non-null-assertion": "off", + "@typescript-eslint/ban-types": "off", + "@typescript-eslint/no-loss-of-precision": "off", + "indent": [ + "error", + 4, + { + SwitchCase: 1, + "ignoredNodes": ["VariableDeclaration[declarations.length=0]"] // fixes https://github.com/microsoft/vscode-eslint/issues/1149 + } + ], + "no-multi-spaces": ["error"], + "no-console": ["error"], + "arrow-spacing": ["error"], + "block-spacing": ["error"], + "comma-spacing": ["error"], + "quotes": [ + "error", + "double" + ], + "semi": [ + "error", + "always" + ], + "brace-style": ["error"], + "eol-last": ["error"], + "space-before-blocks": ["error"], + "semi-spacing": ["error"], + "keyword-spacing": ["error"], + "no-trailing-spaces": ["error"], + "object-curly-spacing": ["error", "always"], + "array-bracket-spacing": ["error"], + "space-infix-ops": ["error"], + "func-call-spacing": ["error", "never"], + "space-before-function-paren": ["error", "never"], + } +}; diff --git a/src/native/libs/.npmrc b/src/native/.npmrc similarity index 100% rename from src/native/libs/.npmrc rename to src/native/.npmrc diff --git a/src/native/corehost/CMakeLists.txt b/src/native/corehost/CMakeLists.txt index 02ed291648817b..663455d6a0ba8f 100644 --- a/src/native/corehost/CMakeLists.txt +++ b/src/native/corehost/CMakeLists.txt @@ -79,25 +79,30 @@ if(CLR_CMAKE_TARGET_LINUX OR CLR_CMAKE_TARGET_SUNOS) add_link_options(LINKER:-Bsymbolic) endif() -add_library(fxr_resolver INTERFACE) -target_sources(fxr_resolver INTERFACE fxr_resolver.cpp) -target_include_directories(fxr_resolver INTERFACE fxr) +if(NOT CLR_CMAKE_TARGET_BROWSER) + add_library(fxr_resolver INTERFACE) + target_sources(fxr_resolver INTERFACE fxr_resolver.cpp) + target_include_directories(fxr_resolver INTERFACE fxr) -add_compile_definitions(RAPIDJSON_HAS_CXX17) + add_compile_definitions(RAPIDJSON_HAS_CXX17) -if ((NOT DEFINED CLR_CMAKE_USE_SYSTEM_RAPIDJSON) OR (NOT CLR_CMAKE_USE_SYSTEM_RAPIDJSON)) - include_directories(${CLR_SRC_NATIVE_DIR}/external/) -endif() - -add_subdirectory(hostcommon) -add_subdirectory(hostmisc) -add_subdirectory(fxr) -add_subdirectory(hostpolicy) + if ((NOT DEFINED CLR_CMAKE_USE_SYSTEM_RAPIDJSON) OR (NOT CLR_CMAKE_USE_SYSTEM_RAPIDJSON)) + include_directories(${CLR_SRC_NATIVE_DIR}/external/) + endif() -add_subdirectory(apphost) -add_subdirectory(dotnet) -add_subdirectory(nethost) -add_subdirectory(test) + add_subdirectory(hostcommon) + add_subdirectory(hostmisc) + add_subdirectory(fxr) + add_subdirectory(hostpolicy) + + add_subdirectory(apphost) + add_subdirectory(dotnet) + add_subdirectory(nethost) + add_subdirectory(test) +else() + add_subdirectory(hostmisc) + add_subdirectory(browserhost) +endif() # If there's a dynamic ASAN runtime, then install it in the directories where we put our executables. if (NOT "${ASAN_RUNTIME}" STREQUAL "") diff --git a/src/native/corehost/browserhost/CMakeLists.txt b/src/native/corehost/browserhost/CMakeLists.txt new file mode 100644 index 00000000000000..bd3b54b9ffb521 --- /dev/null +++ b/src/native/corehost/browserhost/CMakeLists.txt @@ -0,0 +1,108 @@ +# Licensed to the .NET Foundation under one or more agreements. +# The .NET Foundation licenses this file to you under the MIT license. + +project(browserhost) +set(DOTNET_PROJECT_NAME "browserhost") + +configure_file(${CLR_SRC_NATIVE_DIR}/corehost/configure.h.in ${GENERATED_INCLUDE_DIR}/corehost/configure.h) +target_include_directories(hostmisc_interface INTERFACE ${GENERATED_INCLUDE_DIR}/corehost) + +set(SOURCES + ./browserhost.cpp + native.rc +) +set(HEADERS +) + +add_compile_definitions(FEATURE_APPHOST) +add_definitions(-DFEATURE_APPHOST=1) +add_definitions(-DFEATURE_STATIC_HOST=1) + +add_executable(browserhost ${SOURCES}) +set_target_properties(browserhost PROPERTIES OUTPUT_NAME dotnet.native) +set(CMAKE_EXECUTABLE_SUFFIX ".js") + +install(TARGETS browserhost DESTINATION corehost COMPONENT runtime) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/dotnet.native.wasm DESTINATION corehost COMPONENT runtime) + +include(configure.cmake) + +LIST(APPEND NATIVE_LIBS + coreclr_static + System.Native.Browser-Static + System.Runtime.InteropServices.JavaScript.Native-Static + System.Native-Static + System.Globalization.Native-Static + System.IO.Compression.Native-Static + nativeresourcestring + gcinfo + # WASM-TODO respect $(InvariantTimezone) + # System.Native.TimeZoneData.Invariant + System.Native.TimeZoneData +) + +# WASM-TODO set(RUNTIMEINFO_LIB runtimeinfo) + +target_compile_options(browserhost PRIVATE + -fwasm-exceptions + -msimd128 + ) + +set(JS_SYSTEM_NATIVE_BROWSER + "${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Native.Browser/libSystem.Native.Browser.js") +set(JS_SYSTEM_RUNTIME_INTEROPSERVICES_JAVASCRIPT_NATIVE + "${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Runtime.InteropServices.JavaScript.Native/libSystem.Runtime.InteropServices.JavaScript.Native.js") +set(JS_BROWSER_HOST + "${CLR_ARTIFACTS_OBJ_DIR}/coreclr/browser.wasm.${CMAKE_BUILD_TYPE}/corehost/libBrowserHost.js") +set(JS_SYSTEM_NATIVE_BROWSER_EXPOST + "${CMAKE_CURRENT_SOURCE_DIR}/../../libs/System.Native.Browser/libSystem.Native.Browser.extpost.js") + +set_target_properties(browserhost PROPERTIES + LINK_DEPENDS "${JS_SYSTEM_NATIVE_BROWSER};${JS_SYSTEM_RUNTIME_INTEROPSERVICES_JAVASCRIPT_NATIVE};${JS_BROWSER_HOST};${JS_SYSTEM_NATIVE_BROWSER_EXPOST};" + LINK_FLAGS "--js-library ${JS_SYSTEM_NATIVE_BROWSER} --js-library ${JS_SYSTEM_RUNTIME_INTEROPSERVICES_JAVASCRIPT_NATIVE} --js-library ${JS_BROWSER_HOST} --extern-post-js ${JS_SYSTEM_NATIVE_BROWSER_EXPOST}" + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") + +if (UPPERCASE_CMAKE_BUILD_TYPE STREQUAL DEBUG) + target_link_options(browserhost PRIVATE +# -sVERBOSE +# -sASSERTIONS=1 + --emit-symbol-map + -sLLD_REPORT_UNDEFINED + -sERROR_ON_UNDEFINED_SYMBOLS=1 + ) +endif () + +# TODO-WASM -sWASM_BIGINT=1 +# TODO-WASM -emit-llvm +# TODO-WASM --source-map-base http://microsoft.com +target_link_options(browserhost PRIVATE + -sINITIAL_MEMORY=134217728 + -sMAXIMUM_MEMORY=2147483648 + -sALLOW_MEMORY_GROWTH=1 + -sALLOW_TABLE_GROWTH=1 + -sSTACK_SIZE=5MB + -sMODULARIZE=1 + -sEXPORT_ES6=1 + -sEXIT_RUNTIME=0 + -sEXPORTED_RUNTIME_METHODS=UTF8ToString,cwrap,ccall,HEAPU8,HEAPU32,HEAPU64,BROWSER_HOST + -sEXPORTED_FUNCTIONS=_posix_memalign,_free,stackAlloc,stackRestore,stackSave,_browserHostInitializeCoreCLR,_browserHostExecuteAssembly,___cpp_exception + -sEXPORT_NAME=createDotnetRuntime + -fwasm-exceptions + -msimd128 + -lnodefs.js + -Wno-unused-command-line-argument + -Wl,-error-limit=0) + +target_link_libraries( + browserhost + PRIVATE + hostmisc + clrinterpreter + ${NATIVE_LIBS} + + ${START_WHOLE_ARCHIVE} + ${RUNTIMEINFO_LIB} + ${END_WHOLE_ARCHIVE} +) + +add_subdirectory(sample) diff --git a/src/native/corehost/browserhost/ReadMe.md b/src/native/corehost/browserhost/ReadMe.md new file mode 100644 index 00000000000000..ddc3ca082eced7 --- /dev/null +++ b/src/native/corehost/browserhost/ReadMe.md @@ -0,0 +1,32 @@ +# browserhost + +**Emscripten application** and **JavaScript wrapper and a loader** for it. + +## Loader dotnet.js + +It loads application manifest and based on the manifest, it downloads other JS modules, managed assemblies and other assets. +It plays role of a host and a public API for JavaScript user code. +It's good to keep this file small, so that it could start the download cascade as soon as possible. +It's **JavaScript ES6 module** + +- `loader/dotnet.ts` compiled -> `dotnet.js` + +## Native host + +Implements native part of the CoreCLR host and exposes it as an internal JavaScript interface to the loader. +It is **Emscripten application** statically linked from libraries. + +- `host/index.ts` -> compiled -> `libBrowserHost.js` linked -> `dotnet.native.js` +- `libBrowserHost.footer.js` -> compiled -> `libBrowserHost.js` linked -> `dotnet.native.js` +- `libSystem.Native.Browser.js` linked -> `dotnet.native.js` +- `libSystem.Runtime.InteropServices.JavaScript.Native.js` linked -> `dotnet.native.js` +- `browserhost.cpp` compiled + linked -> `dotnet.native.wasm` +- `libSystem.Native.Browser.a` linked -> `dotnet.native.wasm` +- `libSystem.Runtime.InteropServices.JavaScript.Native.a` linked -> `dotnet.native.wasm` + +## Build +TypeScript is compiled by `src/native/rollup.config.js` +JavaScript tools like `npm`, `tsc`, `rollup` are installed in `src/native/package.json`. +JS tools depend on `nodeJS` installation of Emscripten. +Emscripten compilations is part of `src/native/corehost/CMakeLists.txt` +Final app static linking happens here in `CMakeLists.txt` diff --git a/src/native/corehost/browserhost/browserhost.cpp b/src/native/corehost/browserhost/browserhost.cpp new file mode 100644 index 00000000000000..2bfd4850e3ede0 --- /dev/null +++ b/src/native/corehost/browserhost/browserhost.cpp @@ -0,0 +1,174 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include +#include + +#include +#include +#include + +typedef void (*coreclr_error_writer_callback_fn)(const char* line); +extern "C" +{ + pal::hresult_t coreclr_initialize( + const char* exePath, + const char* appDomainFriendlyName, + int propertyCount, + const char** propertyKeys, + const char** propertyValues, + void** hostHandle, + unsigned int* domainId); + + pal::hresult_t coreclr_shutdown_2( + void* hostHandle, + unsigned int domainId, + int* latchedExitCode); + + pal::hresult_t coreclr_execute_assembly( + void* hostHandle, + unsigned int domainId, + int argc, + const char** argv, + const char* managedAssemblyPath, + unsigned int* exitCode); + + pal::hresult_t coreclr_create_delegate( + void* hostHandle, + unsigned int domainId, + const char* entryPointAssemblyName, + const char* entryPointTypeName, + const char* entryPointMethodName, + void** delegate); + + pal::hresult_t coreclr_set_error_writer( + coreclr_error_writer_callback_fn error_writer); + + const void* SystemResolveDllImport(const char* name); + const void* SystemJSResolveDllImport(const char* name); + const void* SystemJSInteropResolveDllImport(const char* name); + const void* GlobalizationResolveDllImport(const char* name); + const void* CompressionResolveDllImport(const char* name); + + bool browserHostExternalAssemblyProbe(const char* pathPtr, /*out*/ void **outDataStartPtr, /*out*/ int64_t* outSize); + void browserHostResolveMain(int exitCode); + void browserHostRejectMain(const char *reason); +} + +// The current CoreCLR instance details. +static void* CurrentClrInstance; +static unsigned int CurrentAppDomainId; + +static void log_error_info(const char* line) +{ + std::fprintf(stderr, "log error: %s\n", line); +} + +static bool external_assembly_probe(const char* path, /*out*/ void **data_start, /*out*/ int64_t* size) +{ + *size = 0; + *data_start = nullptr; + return browserHostExternalAssemblyProbe(path, data_start, size);; +} + +static const void* pinvoke_override(const char* library_name, const char* entry_point_name) +{ + if (strcmp(library_name, "libSystem.Native") == 0) + { + return SystemResolveDllImport(entry_point_name); + } + if (strcmp(library_name, "libSystem.JavaScript") == 0) + { + return SystemJSResolveDllImport(entry_point_name); + } + if (strcmp(library_name, "libSystem.Runtime.InteropServices.JavaScript") == 0) + { + return SystemJSInteropResolveDllImport(entry_point_name); + } + if (strcmp(library_name, "libSystem.IO.Compression.Native") == 0) + { + return CompressionResolveDllImport(entry_point_name); + } + // duplicates https://github.com/dotnet/runtime/blob/7a33b4bb6ced097f081b1eeab575cfb1c8c88bb5/src/coreclr/vm/pinvokeoverride.cpp#L21-L36 for clarity + if (strcmp(library_name, "libSystem.Globalization.Native") == 0) + { + return GlobalizationResolveDllImport(entry_point_name); + } + + return nullptr; +} + +static pal::string_t app_path; +static pal::string_t search_paths; +static pal::string_t tpa; +static const pal::string_t app_domain_name = "corehost"; +static const pal::string_t exe_path = "/managed"; +static std::vector propertyKeys; +static std::vector propertyValues; +static pal::char_t ptr_to_string_buffer[STRING_LENGTH("0xffffffffffffffff") + 1]; + +extern "C" int browserHostInitializeCoreCLR(void) +{ + //WASM-TODO: does getenv return UTF8 ? + pal::getenv(HOST_PROPERTY_APP_PATHS, &app_path); + pal::getenv(HOST_PROPERTY_NATIVE_DLL_SEARCH_DIRECTORIES, &search_paths); + pal::getenv(HOST_PROPERTY_TRUSTED_PLATFORM_ASSEMBLIES, &tpa); + + // Set base initialization properties. + propertyKeys.push_back(HOST_PROPERTY_APP_PATHS); + propertyValues.push_back(app_path.c_str()); + propertyKeys.push_back(HOST_PROPERTY_NATIVE_DLL_SEARCH_DIRECTORIES); + propertyValues.push_back(search_paths.c_str()); + propertyKeys.push_back(HOST_PROPERTY_TRUSTED_PLATFORM_ASSEMBLIES); + propertyValues.push_back(tpa.c_str()); + + host_runtime_contract host_contract = { sizeof(host_runtime_contract), nullptr }; + host_contract.pinvoke_override = &pinvoke_override; + host_contract.external_assembly_probe = &external_assembly_probe; + + pal::snwprintf(ptr_to_string_buffer, ARRAY_SIZE(ptr_to_string_buffer), _X("0x%zx"), (size_t)(&host_contract)); + + propertyKeys.push_back(HOST_PROPERTY_RUNTIME_CONTRACT); + propertyValues.push_back(ptr_to_string_buffer); + + coreclr_set_error_writer(log_error_info); + + int retval = coreclr_initialize(exe_path.c_str(), app_domain_name.c_str(), (int)propertyKeys.size(), propertyKeys.data(), propertyValues.data(), &CurrentClrInstance, &CurrentAppDomainId); + + if (retval < 0) + { + std::fprintf(stderr, "coreclr_initialize failed - Error: 0x%08x\n", retval); + return -1; + } + return 0; +} + +// WASM-TODO: browser needs async entrypoint +extern "C" int browserHostExecuteAssembly(const char* assemblyPath) +{ + int exit_code; + int retval = coreclr_execute_assembly(CurrentClrInstance, CurrentAppDomainId, 0, nullptr, assemblyPath, (uint32_t*)&exit_code); + + if (retval < 0) + { + std::fprintf(stderr, "coreclr_execute_assembly failed - Error: 0x%08x\n", retval); + return -1; + } + + int latched_exit_code = 0; + + retval = coreclr_shutdown_2(CurrentClrInstance, CurrentAppDomainId, &latched_exit_code); + + if (retval < 0) + { + std::fprintf(stderr, "coreclr_shutdown_2 failed - Error: 0x%08x\n", retval); + exit_code = -1; + // WASM-TODO: this is too trivial + browserHostRejectMain("coreclr_shutdown_2 failed"); + } + + // WASM-TODO: this is too trivial + // because nothing runs continuations yet and also coreclr_execute_assembly is sync looping + browserHostResolveMain(exit_code); + return retval; +} diff --git a/src/native/corehost/browserhost/config.h.in b/src/native/corehost/browserhost/config.h.in new file mode 100644 index 00000000000000..0c2e459443b136 --- /dev/null +++ b/src/native/corehost/browserhost/config.h.in @@ -0,0 +1,10 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#ifndef __CONFIG_H__ +#define __CONFIG_H__ + +#cmakedefine01 HAVE_GETAUXVAL +#cmakedefine01 HAVE_DIRENT_D_TYPE + +#endif // __CONFIG_H__ diff --git a/src/native/corehost/browserhost/configure.cmake b/src/native/corehost/browserhost/configure.cmake new file mode 100644 index 00000000000000..61c98113949945 --- /dev/null +++ b/src/native/corehost/browserhost/configure.cmake @@ -0,0 +1,6 @@ +check_symbol_exists(getauxval sys/auxv.h HAVE_GETAUXVAL) +check_struct_has_member ("struct dirent" d_type dirent.h HAVE_DIRENT_D_TYPE) + +configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/config.h.in + ${CMAKE_CURRENT_BINARY_DIR}/config.h) diff --git a/src/native/corehost/browserhost/libBrowserHost.js b/src/native/corehost/browserhost/libBrowserHost.js new file mode 100644 index 00000000000000..b9b27dd9436849 --- /dev/null +++ b/src/native/corehost/browserhost/libBrowserHost.js @@ -0,0 +1,550 @@ +//! Licensed to the .NET Foundation under one or more agreements. +//! The .NET Foundation licenses this file to you under the MIT license. +//! This is generated file, see src/native/libs/Browser/rollup.config.defines.js + + +var libBrowserHost = (function (exports) { + 'use strict'; + + // Licensed to the .NET Foundation under one or more agreements. + // The .NET Foundation licenses this file to you under the MIT license. + let Module; + let runtimeApi; + let Logger = {}; + let Assert = {}; + let JSEngine = {}; + let loaderExports = {}; + let runtimeExports = {}; + let hostExports = {}; + let interopExports = {}; + let nativeBrowserExports = {}; + let dotnetInternals; + function getInternals() { + return dotnetInternals; + } + function setInternals(internal) { + dotnetInternals = internal; + runtimeApi = dotnetInternals.runtimeApi; + Module = dotnetInternals.runtimeApi.Module; + } + function updateAllInternals() { + if (dotnetInternals.updates === undefined) { + dotnetInternals.updates = []; + } + for (const updateImpl of dotnetInternals.updates) { + updateImpl(); + } + } + function updateMyInternals() { + if (Object.keys(loaderExports).length === 0 && dotnetInternals.loaderExportsTable) { + loaderExports = {}; + Logger = {}; + Assert = {}; + JSEngine = {}; + expandLE(dotnetInternals.loaderExportsTable, Logger, Assert, JSEngine, loaderExports); + } + if (Object.keys(runtimeExports).length === 0 && dotnetInternals.runtimeExportsTable) { + runtimeExports = {}; + expandRE(dotnetInternals.runtimeExportsTable, runtimeExports); + } + if (Object.keys(hostExports).length === 0 && dotnetInternals.hostNativeExportsTable) { + hostExports = {}; + expandHE(dotnetInternals.hostNativeExportsTable, hostExports); + } + if (Object.keys(interopExports).length === 0 && dotnetInternals.interopJavaScriptNativeExportsTable) { + interopExports = {}; + expandJSNE(dotnetInternals.interopJavaScriptNativeExportsTable, interopExports); + } + if (Object.keys(nativeBrowserExports).length === 0 && dotnetInternals.nativeBrowserExportsTable) { + nativeBrowserExports = {}; + expandNBE(dotnetInternals.nativeBrowserExportsTable, nativeBrowserExports); + } + } + /** + * Functions below allow our JS modules to exchange internal interfaces by passing tables of functions in known order instead of using string symbols. + * IMPORTANT: If you need to add more functions, make sure that you add them at the end of the table, so that the order of existing functions does not change. + */ + function tabulateLE(logger, assert, loaderExports) { + return [ + logger.info, + logger.warn, + logger.error, + assert.check, + loaderExports.ENVIRONMENT_IS_NODE, + loaderExports.ENVIRONMENT_IS_SHELL, + loaderExports.ENVIRONMENT_IS_WEB, + loaderExports.ENVIRONMENT_IS_WORKER, + loaderExports.ENVIRONMENT_IS_SIDECAR, + loaderExports.browserHostResolveMain, + loaderExports.browserHostRejectMain, + loaderExports.getRunMainPromise, + ]; + } + function expandLE(table, logger, assert, jsEngine, loaderExports) { + const loggerLocal = { + info: table[0], + warn: table[1], + error: table[2], + }; + const assertLocal = { + check: table[3], + }; + const loaderExportsLocal = { + ENVIRONMENT_IS_NODE: table[4], + ENVIRONMENT_IS_SHELL: table[5], + ENVIRONMENT_IS_WEB: table[6], + ENVIRONMENT_IS_WORKER: table[7], + ENVIRONMENT_IS_SIDECAR: table[8], + browserHostResolveMain: table[9], + browserHostRejectMain: table[10], + getRunMainPromise: table[11], + }; + const jsEngineLocal = { + IS_NODE: loaderExportsLocal.ENVIRONMENT_IS_NODE(), + IS_SHELL: loaderExportsLocal.ENVIRONMENT_IS_SHELL(), + IS_WEB: loaderExportsLocal.ENVIRONMENT_IS_WEB(), + IS_WORKER: loaderExportsLocal.ENVIRONMENT_IS_WORKER(), + IS_SIDECAR: loaderExportsLocal.ENVIRONMENT_IS_SIDECAR(), + }; + Object.assign(loaderExports, loaderExportsLocal); + Object.assign(logger, loggerLocal); + Object.assign(assert, assertLocal); + Object.assign(jsEngine, jsEngineLocal); + } + // eslint-disable-next-line @typescript-eslint/no-unused-vars + function tabulateRE(map) { + return []; + } + function expandRE(table, runtime) { + Object.assign(runtime, {}); + } + function tabulateHE(map) { + return [ + map.registerDllBytes, + map.isSharedArrayBuffer, + ]; + } + function expandHE(table, native) { + const nativeLocal = { + registerDllBytes: table[0], + isSharedArrayBuffer: table[1], + }; + Object.assign(native, nativeLocal); + } + // eslint-disable-next-line @typescript-eslint/no-unused-vars + function tabulateJSNE(map) { + return []; + } + function expandJSNE(table, interop) { + const interopLocal = {}; + Object.assign(interop, interopLocal); + } + // eslint-disable-next-line @typescript-eslint/no-unused-vars + function tabulateNBE(map) { + return []; + } + function expandNBE(table, interop) { + const interopLocal = {}; + Object.assign(interop, interopLocal); + } + + // Licensed to the .NET Foundation under one or more agreements. + // The .NET Foundation licenses this file to you under the MIT license. + + // Licensed to the .NET Foundation under one or more agreements. + // The .NET Foundation licenses this file to you under the MIT license. + // see also `reserved` in `rollup.config.defines.js` + + // Licensed to the .NET Foundation under one or more agreements. + // The .NET Foundation licenses this file to you under the MIT license. + const loadedAssemblies = {}; + function registerDllBytes(bytes, asset) { + const sp = Module.stackSave(); + try { + const sizeOfPtr = 4; + const ptrPtr = Module.stackAlloc(sizeOfPtr); + if (Module._posix_memalign(ptrPtr, 16, bytes.length)) { + throw new Error("posix_memalign failed"); + } + const ptr = Module.HEAPU32[ptrPtr >>> 2]; + Module.HEAPU8.set(bytes, ptr); + loadedAssemblies[asset.name] = { ptr, length: bytes.length }; + } + finally { + Module.stackRestore(sp); + } + } + // bool browserHostExternalAssemblyProbe(const char* pathPtr, /*out*/ void **outDataStartPtr, /*out*/ int64_t* outSize); + function browserHostExternalAssemblyProbe(pathPtr, outDataStartPtr, outSize) { + const path = Module.UTF8ToString(pathPtr); + const assembly = loadedAssemblies[path]; + if (assembly) { + Module.HEAPU32[outDataStartPtr >>> 2] = assembly.ptr; + // int64_t target + Module.HEAPU32[outSize >>> 2] = assembly.length; + Module.HEAPU32[(outSize + 4) >>> 2] = 0; + return true; + } + Module.HEAPU32[outDataStartPtr >>> 2] = 0; + Module.HEAPU32[outSize >>> 2] = 0; + Module.HEAPU32[(outSize + 4) >>> 2] = 0; + return false; + } + function browserHostResolveMain(exitCode) { + loaderExports.browserHostResolveMain(exitCode); + } + function browserHostRejectMain(reason) { + loaderExports.browserHostRejectMain(reason); + } + // TODO-WASM: take ideas from Mono + // - second call to exit should be silent + // - second call to exit not override the first exit code + // - improve reason extraction + // - install global handler for unhandled exceptions and promise rejections + function exit(exit_code, reason) { + const reasonStr = reason ? (reason.stack ? reason.stack || reason.message : reason.toString()) : ""; + if (exit_code !== 0) { + Logger.error(`Exit with code ${exit_code} ${reason ? "and reason: " + reasonStr : ""}`); + } + if (JSEngine.IS_NODE) { + globalThis.process.exit(exit_code); + } + } + // eslint-disable-next-line @typescript-eslint/no-unused-vars + async function runMain(mainAssemblyName, args) { + // int browserHostExecuteAssembly(char * assemblyPath) + const res = Module.ccall("browserHostExecuteAssembly", "number", ["string"], [mainAssemblyName]); + if (res != 0) { + const reason = new Error("Failed to execute assembly"); + exit(res, reason); + throw reason; + } + return loaderExports.getRunMainPromise(); + } + // eslint-disable-next-line @typescript-eslint/no-unused-vars + async function runMainAndExit(mainAssemblyName, args) { + try { + await runMain(mainAssemblyName, args); + } + catch (error) { + exit(1, error); + throw error; + } + exit(0, null); + return 0; + } + // eslint-disable-next-line @typescript-eslint/no-unused-vars + function setEnvironmentVariable(name, value) { + throw new Error("Not implemented"); + } + + // Licensed to the .NET Foundation under one or more agreements. + // The .NET Foundation licenses this file to you under the MIT license. + const max_int64_big = BigInt("9223372036854775807"); + const min_int64_big = BigInt("-9223372036854775808"); + const sharedArrayBufferDefined = typeof SharedArrayBuffer !== "undefined"; + function assert_int_in_range(value, min, max) { + Assert.check(Number.isSafeInteger(value), () => `Value is not an integer: ${value} (${typeof (value)})`); + Assert.check(value >= min && value <= max, () => `Overflow: value ${value} is out of ${min} ${max} range`); + } + function _zero_region(byteOffset, sizeBytes) { + localHeapViewU8().fill(0, byteOffset, byteOffset + sizeBytes); + } + /** note: boolean is 8 bits not 32 bits when inside a structure or array */ + function setHeapB32(offset, value) { + const boolValue = !!value; + if (typeof (value) === "number") + assert_int_in_range(value, 0, 1); + Module.HEAP32[offset >>> 2] = boolValue ? 1 : 0; + } + function setHeapB8(offset, value) { + const boolValue = !!value; + if (typeof (value) === "number") + assert_int_in_range(value, 0, 1); + Module.HEAPU8[offset] = boolValue ? 1 : 0; + } + function setHeapU8(offset, value) { + assert_int_in_range(value, 0, 0xFF); + Module.HEAPU8[offset] = value; + } + function setHeapU16(offset, value) { + assert_int_in_range(value, 0, 0xFFFF); + Module.HEAPU16[offset >>> 1] = value; + } + // does not check for growable heap + function setHeapU16_local(localView, offset, value) { + assert_int_in_range(value, 0, 0xFFFF); + localView[offset >>> 1] = value; + } + // does not check for overflow nor growable heap + function setHeapU16_unchecked(offset, value) { + Module.HEAPU16[offset >>> 1] = value; + } + // does not check for overflow nor growable heap + function setHeapU32_unchecked(offset, value) { + Module.HEAPU32[offset >>> 2] = value; + } + function setHeapU32(offset, value) { + assert_int_in_range(value, 0, 4294967295); + Module.HEAPU32[offset >>> 2] = value; + } + function setHeapI8(offset, value) { + assert_int_in_range(value, -0x80, 0x7F); + Module.HEAP8[offset] = value; + } + function setHeapI16(offset, value) { + assert_int_in_range(value, -0x8000, 0x7FFF); + Module.HEAP16[offset >>> 1] = value; + } + function setHeapI32_unchecked(offset, value) { + Module.HEAP32[offset >>> 2] = value; + } + function setHeapI32(offset, value) { + assert_int_in_range(value, -2147483648, 2147483647); + Module.HEAP32[offset >>> 2] = value; + } + /** + * Throws for values which are not 52 bit integer. See Number.isSafeInteger() + */ + function setHeapI52(offset, value) { + Assert.check(Number.isSafeInteger(value), () => `Value is not a safe integer: ${value} (${typeof (value)})`); + throw new Error("TODO"); + // const error = cwraps.mono_wasm_f64_to_i52(offset, value); + // autoThrowI52(error); + } + /** + * Throws for values which are not 52 bit integer or are negative. See Number.isSafeInteger(). + */ + function setHeapU52(offset, value) { + Assert.check(Number.isSafeInteger(value), () => `Value is not a safe integer: ${value} (${typeof (value)})`); + Assert.check(value >= 0, "Can't convert negative Number into UInt64"); + throw new Error("TODO"); + //const error = cwraps.mono_wasm_f64_to_u52(offset, value); + //autoThrowI52(error); + } + function setHeapI64Big(offset, value) { + Assert.check(typeof value === "bigint", () => `Value is not an bigint: ${value} (${typeof (value)})`); + Assert.check(value >= min_int64_big && value <= max_int64_big, () => `Overflow: value ${value} is out of ${min_int64_big} ${max_int64_big} range`); + Module.HEAP64[offset >>> 3] = value; + } + function setHeapF32(offset, value) { + Assert.check(typeof value === "number", () => `Value is not a Number: ${value} (${typeof (value)})`); + Module.HEAPF32[offset >>> 2] = value; + } + function setHeapF64(offset, value) { + Assert.check(typeof value === "number", () => `Value is not a Number: ${value} (${typeof (value)})`); + Module.HEAPF64[offset >>> 3] = value; + } + function getHeapB32(offset) { + const value = (Module.HEAPU32[offset >>> 2]); + if (value > 1 && !getHeapB32.warnDirtyBool) { + getHeapB32.warnDirtyBool = true; + Logger.warn(`getB32: value at ${offset} is not a boolean, but a number: ${value}`); + } + return !!value; + } + function getHeapB8(offset) { + return !!(Module.HEAPU8[offset]); + } + function getHeapU8(offset) { + return Module.HEAPU8[offset]; + } + function getHeapU16(offset) { + return Module.HEAPU16[offset >>> 1]; + } + // does not check for growable heap + function getHeapU16_local(localView, offset) { + return localView[offset >>> 1]; + } + function getHeapU32(offset) { + return Module.HEAPU32[offset >>> 2]; + } + // does not check for growable heap + function getHeapU32_local(localView, offset) { + return localView[offset >>> 2]; + } + function getHeapI8(offset) { + return Module.HEAP8[offset]; + } + function getHeapI16(offset) { + return Module.HEAP16[offset >>> 1]; + } + // does not check for growable heap + function getHeapI16_local(localView, offset) { + return localView[offset >>> 1]; + } + function getHeapI32(offset) { + return Module.HEAP32[offset >>> 2]; + } + // does not check for growable heap + function getHeapI32_local(localView, offset) { + return localView[offset >>> 2]; + } + /** + * Throws for Number.MIN_SAFE_INTEGER > value > Number.MAX_SAFE_INTEGER + */ + // eslint-disable-next-line @typescript-eslint/no-unused-vars + function getHeapI52(offset) { + throw new Error("TODO"); + //const result = cwraps.mono_wasm_i52_to_f64(offset, runtimeHelpers._i52_error_scratch_buffer); + //const error = getI32(runtimeHelpers._i52_error_scratch_buffer); + //autoThrowI52(error); + //return result; + } + /** + * Throws for 0 > value > Number.MAX_SAFE_INTEGER + */ + // eslint-disable-next-line @typescript-eslint/no-unused-vars + function getHeapU52(offset) { + throw new Error("TODO"); + //const result = cwraps.mono_wasm_u52_to_f64(offset, runtimeHelpers._i52_error_scratch_buffer); + //const error = getI32(runtimeHelpers._i52_error_scratch_buffer); + //autoThrowI52(error); + //return result; + } + function getHeapI64Big(offset) { + return Module.HEAP64[offset >>> 3]; + } + function getHeapF32(offset) { + return Module.HEAPF32[offset >>> 2]; + } + function getHeapF64(offset) { + return Module.HEAPF64[offset >>> 3]; + } + // returns memory view which is valid within current synchronous call stack + function localHeapViewI8() { + return Module.HEAP8; + } + // returns memory view which is valid within current synchronous call stack + function localHeapViewI16() { + return Module.HEAP16; + } + // returns memory view which is valid within current synchronous call stack + function localHeapViewI32() { + return Module.HEAP32; + } + // returns memory view which is valid within current synchronous call stack + function localHeapViewI64Big() { + return Module.HEAP64; + } + // returns memory view which is valid within current synchronous call stack + function localHeapViewU8() { + return Module.HEAPU8; + } + // returns memory view which is valid within current synchronous call stack + function localHeapViewU16() { + return Module.HEAPU16; + } + // returns memory view which is valid within current synchronous call stack + function localHeapViewU32() { + return Module.HEAPU32; + } + // returns memory view which is valid within current synchronous call stack + function localHeapViewF32() { + return Module.HEAPF32; + } + // returns memory view which is valid within current synchronous call stack + function localHeapViewF64() { + return Module.HEAPF64; + } + function copyBytes(srcPtr, dstPtr, bytes) { + const heap = localHeapViewU8(); + heap.copyWithin(dstPtr, srcPtr, srcPtr + bytes); + } + function isSharedArrayBuffer(buffer) { + // BEWARE: In some cases, `instanceof SharedArrayBuffer` returns false even though buffer is an SAB. + // Patch adapted from https://github.com/emscripten-core/emscripten/pull/16994 + // See also https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/toStringTag + return sharedArrayBufferDefined && buffer[Symbol.toStringTag] === "SharedArrayBuffer"; + } + + // Licensed to the .NET Foundation under one or more agreements. + // The .NET Foundation licenses this file to you under the MIT license. + function initialize(internals) { + const runtimeApiLocal = { + runMain, + runMainAndExit, + setEnvironmentVariable, + exit, + setHeapB32, setHeapB8, setHeapU8, setHeapU16, setHeapU32, setHeapI8, setHeapI16, setHeapI32, setHeapI52, setHeapU52, setHeapI64Big, setHeapF32, setHeapF64, + getHeapB32, getHeapB8, getHeapU8, getHeapU16, getHeapU32, getHeapI8, getHeapI16, getHeapI32, getHeapI52, getHeapU52, getHeapI64Big, getHeapF32, getHeapF64, + localHeapViewI8, localHeapViewI16, localHeapViewI32, localHeapViewI64Big, localHeapViewU8, localHeapViewU16, localHeapViewU32, localHeapViewF32, localHeapViewF64, + }; + const hostNativeExportsLocal = { + registerDllBytes, + isSharedArrayBuffer + }; + setInternals(internals); + Object.assign(internals.runtimeApi, runtimeApiLocal); + internals.hostNativeExportsTable = [...tabulateHE(hostNativeExportsLocal)]; + internals.updates.push(updateMyInternals); + updateAllInternals(); + } + + exports.browserHostExternalAssemblyProbe = browserHostExternalAssemblyProbe; + exports.browserHostRejectMain = browserHostRejectMain; + exports.browserHostResolveMain = browserHostResolveMain; + exports.initialize = initialize; + + return exports; + +}); +//! Licensed to the .NET Foundation under one or more agreements. +//! The .NET Foundation licenses this file to you under the MIT license. + +/** + * This is root of **Emscripten library** that would become part of `dotnet.native.js` + * It implements the corehost and a part of public JS API related to memory and runtime hosting. + */ + +(function (exports) { + function libFactory() { + const lib = { + $BROWSER_HOST: { + selfInitialize: () => { + if (typeof dotnetInternals !== "undefined") { + BROWSER_HOST.dotnetInternals = dotnetInternals; + + const exports = libBrowserHostFn(BROWSER_HOST); + exports.initialize(dotnetInternals); + BROWSER_HOST.assignExports(exports, BROWSER_HOST); + + const HOST_PROPERTY_TRUSTED_PLATFORM_ASSEMBLIES = "TRUSTED_PLATFORM_ASSEMBLIES"; + const HOST_PROPERTY_ENTRY_ASSEMBLY_NAME = "ENTRY_ASSEMBLY_NAME"; + const HOST_PROPERTY_NATIVE_DLL_SEARCH_DIRECTORIES = "NATIVE_DLL_SEARCH_DIRECTORIES"; + const HOST_PROPERTY_APP_PATHS = "APP_PATHS"; + + const config = dotnetInternals.config; + const assemblyPaths = config.resources.assembly.map(a => a.virtualPath); + const coreAssemblyPaths = config.resources.coreAssembly.map(a => a.virtualPath); + ENV[HOST_PROPERTY_TRUSTED_PLATFORM_ASSEMBLIES] = config.environmentVariables[HOST_PROPERTY_TRUSTED_PLATFORM_ASSEMBLIES] = [...coreAssemblyPaths, ...assemblyPaths].join(":"); + ENV[HOST_PROPERTY_NATIVE_DLL_SEARCH_DIRECTORIES] = config.environmentVariables[HOST_PROPERTY_NATIVE_DLL_SEARCH_DIRECTORIES] = config.virtualWorkingDirectory; + ENV[HOST_PROPERTY_APP_PATHS] = config.environmentVariables[HOST_PROPERTY_APP_PATHS] = config.virtualWorkingDirectory; + ENV[HOST_PROPERTY_ENTRY_ASSEMBLY_NAME] = config.environmentVariables[HOST_PROPERTY_ENTRY_ASSEMBLY_NAME] = config.mainAssemblyName; + } + }, + }, + "$libBrowserHostFn": libBrowserHost, + "$BROWSER_HOST__postset": "BROWSER_HOST.selfInitialize();", + }; + + // this executes the function at compile time in order to capture export names + const exports = libBrowserHost({}); + let commonDeps = ["$libBrowserHostFn", "$DOTNET", "$DOTNET_INTEROP", "$ENV"]; + let assignExportsBuilder = ""; + for (const exportName of Reflect.ownKeys(exports)) { + const name = String(exportName); + if (name === "cross") continue; + if (name === "initialize") continue; + lib[name] = () => "dummy"; + assignExportsBuilder += `_${String(name)} = exports.${String(name)};\n`; + } + lib.$BROWSER_HOST.assignExports = new Function("exports", assignExportsBuilder); + lib["$BROWSER_HOST__deps"] = commonDeps; + + autoAddDeps(lib, "$BROWSER_HOST"); + addToLibrary(lib); + } + libFactory(); + return exports; +})({}); diff --git a/src/native/corehost/browserhost/loader/dotnet.d.ts b/src/native/corehost/browserhost/loader/dotnet.d.ts new file mode 100644 index 00000000000000..3e878a4724ee72 --- /dev/null +++ b/src/native/corehost/browserhost/loader/dotnet.d.ts @@ -0,0 +1,782 @@ +//! Licensed to the .NET Foundation under one or more agreements. +//! The .NET Foundation licenses this file to you under the MIT license. +//! This is generated file, see src/native/libs/Browser/rollup.config.defines.js + +//! This is not considered public API with backward compatibility guarantees. + +interface NativePointer { + __brandNativePointer: "NativePointer"; +} +interface VoidPtr extends NativePointer { + __brand: "VoidPtr"; +} +interface VoidPtrPtr extends NativePointer { + __brand: "VoidPtrPtr"; +} +interface CharPtr extends NativePointer { + __brand: "CharPtr"; +} +interface Int32Ptr extends NativePointer { + __brand: "Int32Ptr"; +} +interface EmscriptenModule { + _malloc(size: number): VoidPtr; + _free(ptr: VoidPtr): void; + _sbrk(size: number): VoidPtr; + _posix_memalign(res: VoidPtrPtr, alignment: number, size: number): number; + out(message: string): void; + err(message: string): void; + ccall(ident: string, returnType?: string | null, argTypes?: string[], args?: any[], opts?: any): T; + cwrap(ident: string, returnType: string, argTypes?: string[], opts?: any): T; + cwrap(ident: string, ...args: any[]): T; + setValue(ptr: VoidPtr, value: number, type: string, noSafe?: number | boolean): void; + setValue(ptr: Int32Ptr, value: number, type: string, noSafe?: number | boolean): void; + getValue(ptr: number, type: string, noSafe?: number | boolean): number; + UTF8ToString(ptr: CharPtr, maxBytesToRead?: number): string; + UTF8ArrayToString(u8Array: Uint8Array, idx?: number, maxBytesToRead?: number): string; + stringToUTF8Array(str: string, heap: Uint8Array, outIdx: number, maxBytesToWrite: number): void; + lengthBytesUTF8(str: string): number; + FS_createPath(parent: string, path: string, canRead?: boolean, canWrite?: boolean): string; + FS_createDataFile(parent: string, name: string, data: TypedArray, canRead: boolean, canWrite: boolean, canOwn?: boolean): string; + addFunction(fn: Function, signature: string): number; + stackSave(): VoidPtr; + stackRestore(stack: VoidPtr): void; + stackAlloc(size: number): VoidPtr; + instantiateWasm?: InstantiateWasmCallBack; + preInit?: (() => any)[] | (() => any); + preRun?: (() => any)[] | (() => any); + onRuntimeInitialized?: () => any; + postRun?: (() => any)[] | (() => any); + onAbort?: { + (error: any): void; + }; + onExit?: { + (code: number): void; + }; +} +type InstantiateWasmSuccessCallback = (instance: WebAssembly.Instance, module: WebAssembly.Module | undefined) => void; +type InstantiateWasmCallBack = (imports: WebAssembly.Imports, successCallback: InstantiateWasmSuccessCallback) => any; +type TypedArray = Int8Array | Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array; + +interface DotnetHostBuilder { + /** + * @param config default values for the runtime configuration. It will be merged with the default values. + * Note that if you provide resources and don't provide custom configSrc URL, the dotnet.boot.js will be downloaded and applied by default. + */ + withConfig(config: LoaderConfig): DotnetHostBuilder; + /** + * @param configSrc URL to the configuration file. ./dotnet.boot.js is a default config file location. + */ + withConfigSrc(configSrc: string): DotnetHostBuilder; + /** + * "command line" arguments for the Main() method. + * @param args + */ + withApplicationArguments(...args: string[]): DotnetHostBuilder; + /** + * Sets the environment variable for the "process" + */ + withEnvironmentVariable(name: string, value: string): DotnetHostBuilder; + /** + * Sets the environment variables for the "process" + */ + withEnvironmentVariables(variables: { + [i: string]: string; + }): DotnetHostBuilder; + /** + * Sets the "current directory" for the "process" on the virtual file system. + */ + withVirtualWorkingDirectory(vfsPath: string): DotnetHostBuilder; + /** + * @param enabled if "true", writes diagnostic messages during runtime startup and execution to the browser console. + */ + withDiagnosticTracing(enabled: boolean): DotnetHostBuilder; + /** + * @param level + * level > 0 enables debugging and sets the logging level to debug + * level == 0 disables debugging and enables interpreter optimizations + * level < 0 enables debugging and disables debug logging. + */ + withDebugging(level: number): DotnetHostBuilder; + /** + * @param mainAssemblyName Sets the name of the assembly with the Main() method. Default is the same as the .csproj name. + */ + withMainAssembly(mainAssemblyName: string): DotnetHostBuilder; + /** + * Supply "command line" arguments for the Main() method from browser query arguments named "arg". Eg. `index.html?arg=A&arg=B&arg=C`. + * @param args + */ + withApplicationArgumentsFromQuery(): DotnetHostBuilder; + /** + * Sets application environment, such as "Development", "Staging", "Production", etc. + */ + withApplicationEnvironment(applicationEnvironment?: string): DotnetHostBuilder; + /** + * Sets application culture. This is a name specified in the BCP 47 format. See https://tools.ietf.org/html/bcp47 + */ + withApplicationCulture(applicationCulture?: string): DotnetHostBuilder; + /** + * Overrides the built-in boot resource loading mechanism so that boot resources can be fetched + * from a custom source, such as an external CDN. + */ + withResourceLoader(loadBootResource?: LoadBootResourceCallback): DotnetHostBuilder; + /** + * Downloads all the assets but doesn't create the runtime instance. + */ + download(): Promise; + /** + * Starts the runtime and returns promise of the API object. + */ + create(): Promise; + /** + * Runs the Main() method of the application and exits the runtime. + * You can provide "command line" arguments for the Main() method using + * - dotnet.withApplicationArguments(["A", "B", "C"]) + * - dotnet.withApplicationArgumentsFromQuery() + * Note: after the runtime exits, it would reject all further calls to the API. + * You can use runMain() if you want to keep the runtime alive. + */ + run(): Promise; +} +type LoaderConfig = { + /** + * Additional search locations for assets. + */ + remoteSources?: string[]; + /** + * It will not fail the startup is .pdb files can't be downloaded + */ + ignorePdbLoadErrors?: boolean; + /** + * We are throttling parallel downloads in order to avoid net::ERR_INSUFFICIENT_RESOURCES on chrome. The default value is 16. + */ + maxParallelDownloads?: number; + /** + * We are making up to 2 more delayed attempts to download same asset. Default true. + */ + enableDownloadRetry?: boolean; + /** + * Name of the assembly with main entrypoint + */ + mainAssemblyName?: string; + /** + * Configures the runtime's globalization mode + */ + globalizationMode?: GlobalizationMode; + /** + * debugLevel > 0 enables debugging and sets the debug log level to debugLevel + * debugLevel == 0 disables debugging and enables interpreter optimizations + * debugLevel < 0 enables debugging and disables debug logging. + */ + debugLevel?: number; + /** + * Configures use of the `integrity` directive for fetching assets + */ + disableIntegrityCheck?: boolean; + /** + * Configures use of the `no-cache` directive for fetching assets + */ + disableNoCacheFetch?: boolean; + /** + * Enables diagnostic log messages during startup + */ + diagnosticTracing?: boolean; + /** + * Dictionary-style Object containing environment variables + */ + environmentVariables?: { + [i: string]: string; + }; + /** + * Subset of runtimeconfig.json + */ + runtimeConfig?: { + runtimeOptions?: { + configProperties?: { + [i: string]: string | number | boolean; + }; + }; + }; + /** + * initial number of workers to add to the emscripten pthread pool + */ + pthreadPoolInitialSize?: number; + /** + * number of unused workers kept in the emscripten pthread pool after startup + */ + pthreadPoolUnusedSize?: number; + /** + * If true, a list of the methods optimized by the interpreter will be saved and used for faster startup + * on future runs of the application + */ + interpreterPgo?: boolean; + /** + * Configures how long to wait before saving the interpreter PGO list. If your application takes + * a while to start you should adjust this value. + */ + interpreterPgoSaveDelay?: number; + /** + * application environment + */ + applicationEnvironment?: string; + /** + * Gets the application culture. This is a name specified in the BCP 47 format. See https://tools.ietf.org/html/bcp47 + */ + applicationCulture?: string; + resources?: Assets; + /** + * appsettings files to load to VFS + */ + appsettings?: string[]; + /** + * config extensions declared in MSBuild items @(WasmBootConfigExtension) + */ + extensions?: { + [name: string]: any; + }; + /** + * This is initial working directory for the runtime on the virtual file system. Default is "/". + */ + virtualWorkingDirectory?: string; + /** + * This is the arguments to the Main() method of the program when called with dotnet.run() Default is []. + * Note: RuntimeAPI.runMain() and RuntimeAPI.runMainAndExit() will replace this value, if they provide it. + */ + applicationArguments?: string[]; +}; +type ResourceExtensions = { + [extensionName: string]: ResourceList; +}; +interface Assets { + hash?: string; + coreAssembly: AssemblyAsset[]; + assembly: AssemblyAsset[]; + lazyAssembly?: AssemblyAsset[]; + corePdb?: PdbAsset[]; + pdb?: PdbAsset[]; + jsModuleWorker?: JsAsset[]; + jsModuleDiagnostics?: JsAsset[]; + jsModuleNative: JsAsset[]; + jsModuleRuntime: JsAsset[]; + wasmSymbols?: SymbolsAsset[]; + wasmNative: WasmAsset[]; + icu?: IcuAsset[]; + satelliteResources?: { + [cultureName: string]: AssemblyAsset[]; + }; + modulesAfterConfigLoaded?: JsAsset[]; + modulesAfterRuntimeReady?: JsAsset[]; + extensions?: ResourceExtensions; + coreVfs?: VfsAsset[]; + vfs?: VfsAsset[]; +} +type Asset = { + /** + * this should be absolute url to the asset + */ + resolvedUrl?: string; + /** + * If true, the runtime startup would not fail if the asset download was not successful. + */ + isOptional?: boolean; + /** + * If provided, runtime doesn't have to fetch the data. + * Runtime would set the buffer to null after instantiation to free the memory. + */ + buffer?: ArrayBuffer | Promise; + /** + * It's metadata + fetch-like Promise + * If provided, the runtime doesn't have to initiate the download. It would just await the response. + */ + pendingDownload?: LoadingResource; +}; +type WasmAsset = Asset & { + name: string; + hash?: string | null | ""; +}; +type AssemblyAsset = Asset & { + virtualPath: string; + name: string; + hash?: string | null | ""; +}; +type PdbAsset = Asset & { + virtualPath: string; + name: string; + hash?: string | null | ""; +}; +type JsAsset = Asset & { + /** + * If provided, runtime doesn't have to import it's JavaScript modules. + * This will not work for multi-threaded runtime. + */ + moduleExports?: any | Promise; + name?: string; +}; +type SymbolsAsset = Asset & { + name: string; +}; +type VfsAsset = Asset & { + virtualPath: string; + name: string; + hash?: string | null | ""; +}; +type IcuAsset = Asset & { + virtualPath: string; + name: string; + hash?: string | null | ""; +}; +/** + * A "key" is name of the file, a "value" is optional hash for integrity check. + */ +type ResourceList = { + [name: string]: string | null | ""; +}; +/** + * Overrides the built-in boot resource loading mechanism so that boot resources can be fetched + * from a custom source, such as an external CDN. + * @param type The type of the resource to be loaded. + * @param name The name of the resource to be loaded. + * @param defaultUri The URI from which the framework would fetch the resource by default. The URI may be relative or absolute. + * @param integrity The integrity string representing the expected content in the response. + * @param behavior The detailed behavior/type of the resource to be loaded. + * @returns A URI string or a Response promise to override the loading process, or null/undefined to allow the default loading behavior. + * When returned string is not qualified with `./` or absolute URL, it will be resolved against the application base URI. + */ +type LoadBootResourceCallback = (type: WebAssemblyBootResourceType, name: string, defaultUri: string, integrity: string, behavior: AssetBehaviors) => string | Promise | Promise | null | undefined; +type BootModule = { + config: LoaderConfig; +}; +interface LoadingResource { + name: string; + url: string; + response: Promise; +} +interface AssetEntry { + /** + * the name of the asset, including extension. + */ + name: string; + /** + * determines how the asset will be handled once loaded + */ + behavior: AssetBehaviors; + /** + * this should be absolute url to the asset + */ + resolvedUrl?: string; + /** + * the integrity hash of the asset (if any) + */ + hash?: string | null | ""; + /** + * If specified, overrides the path of the asset in the virtual filesystem and similar data structures once downloaded. + */ + virtualPath?: string; + /** + * Culture code + */ + culture?: string; + /** + * If true, an attempt will be made to load the asset from each location in LoaderConfig.remoteSources. + */ + loadRemote?: boolean; + /** + * If true, the runtime startup would not fail if the asset download was not successful. + */ + isOptional?: boolean; + /** + * If provided, runtime doesn't have to fetch the data. + * Runtime would set the buffer to null after instantiation to free the memory. + */ + buffer?: ArrayBuffer | Promise; + /** + * If provided, runtime doesn't have to import it's JavaScript modules. + * This will not work for multi-threaded runtime. + */ + moduleExports?: any | Promise; + /** + * It's metadata + fetch-like Promise + * If provided, the runtime doesn't have to initiate the download. It would just await the response. + */ + pendingDownload?: LoadingResource; +} +type SingleAssetBehaviors = +/** + * The binary of the .NET runtime. + */ +"dotnetwasm" +/** + * The javascript module for loader. + */ + | "js-module-dotnet" +/** + * The javascript module for threads. + */ + | "js-module-threads" +/** + * The javascript module for diagnostic server and client. + */ + | "js-module-diagnostics" +/** + * The javascript module for runtime. + */ + | "js-module-runtime" +/** + * The javascript module for emscripten. + */ + | "js-module-native" +/** + * Typically dotnet.boot.js + */ + | "manifest" +/** + * The debugging symbols + */ + | "symbols"; +type AssetBehaviors = SingleAssetBehaviors | +/** + * Load asset as a managed resource assembly. + */ +"resource" +/** + * Load asset as a managed assembly. + */ + | "assembly" +/** + * Load asset as a managed debugging information. + */ + | "pdb" +/** + * Store asset into the native heap. + */ + | "heap" +/** + * Load asset as an ICU data archive. + */ + | "icu" +/** + * Load asset into the virtual filesystem (for fopen, File.Open, etc). + */ + | "vfs" +/** + * The javascript module that came from nuget package . + */ + | "js-module-library-initializer"; +declare const enum GlobalizationMode { + /** + * Load sharded ICU data. + */ + Sharded = "sharded", + /** + * Load all ICU data. + */ + All = "all", + /** + * Operate in invariant globalization mode. + */ + Invariant = "invariant", + /** + * Use user defined icu file. + */ + Custom = "custom" +} +type DotnetModuleConfig = { + config?: LoaderConfig; + configSrc?: string; + onConfigLoaded?: (config: LoaderConfig) => void | Promise; + onDotnetReady?: () => void | Promise; + onDownloadResourceProgress?: (resourcesLoaded: number, totalResources: number) => void; + imports?: any; + exports?: string[]; +} & Partial; +type RunAPIType = { + /** + * Runs the Main() method of the application. + * Note: this will keep the .NET runtime alive and the APIs will be available for further calls. + * @param mainAssemblyName name of the assembly with the Main() method. Optional. Default is the same as the .csproj name. + * @param args command line arguments for the Main() method. Optional. + * @returns exit code of the Main() method. + */ + runMain: (mainAssemblyName?: string, args?: string[]) => Promise; + /** + * Runs the Main() method of the application and exits the runtime. + * Note: after the runtime exits, it would reject all further calls to the API. + * @param mainAssemblyName name of the assembly with the Main() method. Optional. Default is the same as the .csproj name. + * @param args command line arguments for the Main() method. Optional. + * @returns exit code of the Main() method. + */ + runMainAndExit: (mainAssemblyName?: string, args?: string[]) => Promise; + /** + * Exits the runtime. + * Note: after the runtime exits, it would reject all further calls to the API. + * @param code "process" exit code. + * @param reason could be a string or an Error object. + */ + exit: (code: number, reason?: any) => void; + /** + * Sets the environment variable for the "process" + * @param name + * @param value + */ + setEnvironmentVariable: (name: string, value: string) => void; + /** + * Returns the [JSExport] methods of the assembly with the given name + * @param assemblyName + */ + getAssemblyExports(assemblyName: string): Promise; + /** + * Provides functions which could be imported by the managed code using [JSImport] + * @param moduleName maps to the second parameter of [JSImport] + * @param moduleImports object with functions which could be imported by the managed code. The keys map to the first parameter of [JSImport] + */ + setModuleImports(moduleName: string, moduleImports: any): void; + /** + * Returns the configuration object used to start the runtime. + */ + getConfig: () => LoaderConfig; + /** + * Executes scripts which were loaded during runtime bootstrap. + * You can register the scripts using LoaderConfig.resources.modulesAfterConfigLoaded and LoaderConfig.resources.modulesAfterRuntimeReady. + */ + invokeLibraryInitializers: (functionName: string, args: any[]) => Promise; +}; +type MemoryAPIType = { + /** + * Writes to the WASM linear memory + */ + setHeapB32: (offset: NativePointer, value: number | boolean) => void; + /** + * Writes to the WASM linear memory + */ + setHeapB8: (offset: NativePointer, value: number | boolean) => void; + /** + * Writes to the WASM linear memory + */ + setHeapU8: (offset: NativePointer, value: number) => void; + /** + * Writes to the WASM linear memory + */ + setHeapU16: (offset: NativePointer, value: number) => void; + /** + * Writes to the WASM linear memory + */ + setHeapU32: (offset: NativePointer, value: NativePointer | number) => void; + /** + * Writes to the WASM linear memory + */ + setHeapI8: (offset: NativePointer, value: number) => void; + /** + * Writes to the WASM linear memory + */ + setHeapI16: (offset: NativePointer, value: number) => void; + /** + * Writes to the WASM linear memory + */ + setHeapI32: (offset: NativePointer, value: number) => void; + /** + * Writes to the WASM linear memory + */ + setHeapI52: (offset: NativePointer, value: number) => void; + /** + * Writes to the WASM linear memory + */ + setHeapU52: (offset: NativePointer, value: number) => void; + /** + * Writes to the WASM linear memory + */ + setHeapI64Big: (offset: NativePointer, value: bigint) => void; + /** + * Writes to the WASM linear memory + */ + setHeapF32: (offset: NativePointer, value: number) => void; + /** + * Writes to the WASM linear memory + */ + setHeapF64: (offset: NativePointer, value: number) => void; + /** + * Reads from the WASM linear memory + */ + getHeapB32: (offset: NativePointer) => boolean; + /** + * Reads from the WASM linear memory + */ + getHeapB8: (offset: NativePointer) => boolean; + /** + * Reads from the WASM linear memory + */ + getHeapU8: (offset: NativePointer) => number; + /** + * Reads from the WASM linear memory + */ + getHeapU16: (offset: NativePointer) => number; + /** + * Reads from the WASM linear memory + */ + getHeapU32: (offset: NativePointer) => number; + /** + * Reads from the WASM linear memory + */ + getHeapI8: (offset: NativePointer) => number; + /** + * Reads from the WASM linear memory + */ + getHeapI16: (offset: NativePointer) => number; + /** + * Reads from the WASM linear memory + */ + getHeapI32: (offset: NativePointer) => number; + /** + * Reads from the WASM linear memory + */ + getHeapI52: (offset: NativePointer) => number; + /** + * Reads from the WASM linear memory + */ + getHeapU52: (offset: NativePointer) => number; + /** + * Reads from the WASM linear memory + */ + getHeapI64Big: (offset: NativePointer) => bigint; + /** + * Reads from the WASM linear memory + */ + getHeapF32: (offset: NativePointer) => number; + /** + * Reads from the WASM linear memory + */ + getHeapF64: (offset: NativePointer) => number; + /** + * Returns a short term view of the WASM linear memory. Don't store the reference, don't use it after await. + */ + localHeapViewI8: () => Int8Array; + /** + * Returns a short term view of the WASM linear memory. Don't store the reference, don't use it after await. + */ + localHeapViewI16: () => Int16Array; + /** + * Returns a short term view of the WASM linear memory. Don't store the reference, don't use it after await. + */ + localHeapViewI32: () => Int32Array; + /** + * Returns a short term view of the WASM linear memory. Don't store the reference, don't use it after await. + */ + localHeapViewI64Big: () => BigInt64Array; + /** + * Returns a short term view of the WASM linear memory. Don't store the reference, don't use it after await. + */ + localHeapViewU8: () => Uint8Array; + /** + * Returns a short term view of the WASM linear memory. Don't store the reference, don't use it after await. + */ + localHeapViewU16: () => Uint16Array; + /** + * Returns a short term view of the WASM linear memory. Don't store the reference, don't use it after await. + */ + localHeapViewU32: () => Uint32Array; + /** + * Returns a short term view of the WASM linear memory. Don't store the reference, don't use it after await. + */ + localHeapViewF32: () => Float32Array; + /** + * Returns a short term view of the WASM linear memory. Don't store the reference, don't use it after await. + */ + localHeapViewF64: () => Float64Array; +}; +type DiagnosticsAPIType = { + /** + * creates diagnostic trace file. Default is 60 seconds. + * It could be opened in PerfView or Visual Studio as is. + */ + collectCpuSamples: (options?: DiagnosticCommandOptions) => Promise; + /** + * creates diagnostic trace file. Default is 60 seconds. + * It could be opened in PerfView or Visual Studio as is. + * It could be summarized by `dotnet-trace report xxx.nettrace topN -n 10` + */ + collectMetrics: (options?: DiagnosticCommandOptions) => Promise; + /** + * creates diagnostic trace file. + * It could be opened in PerfView as is. + * It could be converted for Visual Studio using `dotnet-gcdump convert`. + */ + collectGcDump: (options?: DiagnosticCommandOptions) => Promise; + /** + * changes DOTNET_DiagnosticPorts and makes a new connection to WebSocket on that URL. + */ + connectDSRouter(url: string): void; +}; +type DiagnosticCommandProviderV2 = { + keywords: [number, number]; + logLevel: number; + provider_name: string; + arguments: string | null; +}; +type DiagnosticCommandOptions = { + durationSeconds?: number; + intervalSeconds?: number; + skipDownload?: boolean; + circularBufferMB?: number; + extraProviders?: DiagnosticCommandProviderV2[]; +}; +type APIType = RunAPIType & MemoryAPIType & DiagnosticsAPIType; +type RuntimeAPI = { + INTERNAL: any; + Module: EmscriptenModule; + runtimeId: number; + runtimeBuildInfo: { + productVersion: string; + gitHash: string; + buildConfiguration: string; + wasmEnableThreads: boolean; + wasmEnableSIMD: boolean; + wasmEnableExceptionHandling: boolean; + }; +} & APIType; +type ModuleAPI = { + /** + * The builder for the .NET runtime. + */ + dotnet: DotnetHostBuilder; + /** + * Terminates the runtime "process" and reject all further calls to the API. + */ + exit: (code: number, reason?: any) => void; +}; +type CreateDotnetRuntimeType = (moduleFactory: DotnetModuleConfig | ((api: RuntimeAPI) => DotnetModuleConfig)) => Promise; +type WebAssemblyBootResourceType = "assembly" | "pdb" | "dotnetjs" | "dotnetwasm" | "globalization" | "manifest" | "configuration"; +interface IDisposable { + dispose(): void; + get isDisposed(): boolean; +} +interface IMemoryView extends IDisposable { + /** + * copies elements from provided source to the wasm memory. + * target has to have the elements of the same type as the underlying C# array. + * same as TypedArray.set() + */ + set(source: TypedArray, targetOffset?: number): void; + /** + * copies elements from wasm memory to provided target. + * target has to have the elements of the same type as the underlying C# array. + */ + copyTo(target: TypedArray, sourceOffset?: number): void; + /** + * same as TypedArray.slice() + */ + slice(start?: number, end?: number): TypedArray; + get length(): number; + get byteLength(): number; +} +declare function exit(exit_code: number, reason?: any): void; +declare const dotnet: DotnetHostBuilder; +declare global { + function getDotnetRuntime(runtimeId: number): RuntimeAPI | undefined; +} + +declare global { + function getDotnetRuntime(runtimeId: number): RuntimeAPI | undefined; + const dotnetSidecar: boolean | undefined; +} +declare const createDotnetRuntime: CreateDotnetRuntimeType; + +export { type AssetBehaviors, type AssetEntry, type CreateDotnetRuntimeType, type DotnetHostBuilder, type DotnetModuleConfig, type EmscriptenModule, GlobalizationMode, type IMemoryView, type LoaderConfig, type ModuleAPI, type RuntimeAPI, createDotnetRuntime as default, dotnet, exit }; diff --git a/src/native/corehost/browserhost/loader/dotnet.js b/src/native/corehost/browserhost/loader/dotnet.js new file mode 100644 index 00000000000000..9b96e58e74ef0c --- /dev/null +++ b/src/native/corehost/browserhost/loader/dotnet.js @@ -0,0 +1,948 @@ +//! Licensed to the .NET Foundation under one or more agreements. +//! The .NET Foundation licenses this file to you under the MIT license. +//! This is generated file, see src/native/libs/Browser/rollup.config.defines.js + + +/*! bundlerFriendlyImports */ + +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +let Module; +let runtimeApi; +let Logger = {}; +let Assert = {}; +let JSEngine = {}; +let loaderExports = {}; +let runtimeExports = {}; +let hostExports = {}; +let interopExports = {}; +let nativeBrowserExports = {}; +let dotnetInternals; +function getInternals() { + return dotnetInternals; +} +function setInternals(internal) { + dotnetInternals = internal; + runtimeApi = dotnetInternals.runtimeApi; + Module = dotnetInternals.runtimeApi.Module; +} +function updateAllInternals() { + if (dotnetInternals.updates === undefined) { + dotnetInternals.updates = []; + } + for (const updateImpl of dotnetInternals.updates) { + updateImpl(); + } +} +function updateMyInternals() { + if (Object.keys(loaderExports).length === 0 && dotnetInternals.loaderExportsTable) { + loaderExports = {}; + Logger = {}; + Assert = {}; + JSEngine = {}; + expandLE(dotnetInternals.loaderExportsTable, Logger, Assert, JSEngine, loaderExports); + } + if (Object.keys(runtimeExports).length === 0 && dotnetInternals.runtimeExportsTable) { + runtimeExports = {}; + expandRE(dotnetInternals.runtimeExportsTable, runtimeExports); + } + if (Object.keys(hostExports).length === 0 && dotnetInternals.hostNativeExportsTable) { + hostExports = {}; + expandHE(dotnetInternals.hostNativeExportsTable, hostExports); + } + if (Object.keys(interopExports).length === 0 && dotnetInternals.interopJavaScriptNativeExportsTable) { + interopExports = {}; + expandJSNE(dotnetInternals.interopJavaScriptNativeExportsTable, interopExports); + } + if (Object.keys(nativeBrowserExports).length === 0 && dotnetInternals.nativeBrowserExportsTable) { + nativeBrowserExports = {}; + expandNBE(dotnetInternals.nativeBrowserExportsTable, nativeBrowserExports); + } +} +/** + * Functions below allow our JS modules to exchange internal interfaces by passing tables of functions in known order instead of using string symbols. + * IMPORTANT: If you need to add more functions, make sure that you add them at the end of the table, so that the order of existing functions does not change. + */ +function tabulateLE(logger, assert, loaderExports) { + return [ + logger.info, + logger.warn, + logger.error, + assert.check, + loaderExports.ENVIRONMENT_IS_NODE, + loaderExports.ENVIRONMENT_IS_SHELL, + loaderExports.ENVIRONMENT_IS_WEB, + loaderExports.ENVIRONMENT_IS_WORKER, + loaderExports.ENVIRONMENT_IS_SIDECAR, + loaderExports.browserHostResolveMain, + loaderExports.browserHostRejectMain, + loaderExports.getRunMainPromise, + ]; +} +function expandLE(table, logger, assert, jsEngine, loaderExports) { + const loggerLocal = { + info: table[0], + warn: table[1], + error: table[2], + }; + const assertLocal = { + check: table[3], + }; + const loaderExportsLocal = { + ENVIRONMENT_IS_NODE: table[4], + ENVIRONMENT_IS_SHELL: table[5], + ENVIRONMENT_IS_WEB: table[6], + ENVIRONMENT_IS_WORKER: table[7], + ENVIRONMENT_IS_SIDECAR: table[8], + browserHostResolveMain: table[9], + browserHostRejectMain: table[10], + getRunMainPromise: table[11], + }; + const jsEngineLocal = { + IS_NODE: loaderExportsLocal.ENVIRONMENT_IS_NODE(), + IS_SHELL: loaderExportsLocal.ENVIRONMENT_IS_SHELL(), + IS_WEB: loaderExportsLocal.ENVIRONMENT_IS_WEB(), + IS_WORKER: loaderExportsLocal.ENVIRONMENT_IS_WORKER(), + IS_SIDECAR: loaderExportsLocal.ENVIRONMENT_IS_SIDECAR(), + }; + Object.assign(loaderExports, loaderExportsLocal); + Object.assign(logger, loggerLocal); + Object.assign(assert, assertLocal); + Object.assign(jsEngine, jsEngineLocal); +} +// eslint-disable-next-line @typescript-eslint/no-unused-vars +function tabulateRE(map) { + return []; +} +function expandRE(table, runtime) { + Object.assign(runtime, {}); +} +function tabulateHE(map) { + return [ + map.registerDllBytes, + map.isSharedArrayBuffer, + ]; +} +function expandHE(table, native) { + const nativeLocal = { + registerDllBytes: table[0], + isSharedArrayBuffer: table[1], + }; + Object.assign(native, nativeLocal); +} +// eslint-disable-next-line @typescript-eslint/no-unused-vars +function tabulateJSNE(map) { + return []; +} +function expandJSNE(table, interop) { + const interopLocal = {}; + Object.assign(interop, interopLocal); +} +// eslint-disable-next-line @typescript-eslint/no-unused-vars +function tabulateNBE(map) { + return []; +} +function expandNBE(table, interop) { + const interopLocal = {}; + Object.assign(interop, interopLocal); +} + +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +const config = {}; +let isConfigDownloaded = false; +async function downloadConfig(url, loadBootResource) { + if (loadBootResource) + throw new Error("TODO: loadBootResource is not implemented yet"); + if (isConfigDownloaded) + return; // only download config once + if (!url) { + url = "./dotnet.boot.js"; + } + // url ends with .json + if (url.endsWith(".json")) { + const response = await fetch(url); + if (!response.ok) { + throw new Error(`Failed to download config from ${url}: ${response.status} ${response.statusText}`); + } + const newConfig = await response.json(); + mergeConfig(newConfig); + } + else if (url.endsWith(".js") || url.endsWith(".mjs")) { + const module = await import(/* webpackIgnore: true */ url); + mergeConfig(module.config); + } + isConfigDownloaded = true; +} +function getConfig() { + return config; +} +function mergeConfig(source) { + normalizeConfig(config); + normalizeConfig(source); + mergeConfigs(config, source); +} +function mergeConfigs(target, source) { + // no need to merge the same object + if (target === source || source === undefined || source === null) + return target; + mergeResources(target.resources, source.resources); + source.appendElementOnExit = source.appendElementOnExit !== undefined ? source.appendElementOnExit : target.appendElementOnExit; + source.logExitCode = source.logExitCode !== undefined ? source.logExitCode : target.logExitCode; + source.exitOnUnhandledError = source.exitOnUnhandledError !== undefined ? source.exitOnUnhandledError : target.exitOnUnhandledError; + source.loadAllSatelliteResources = source.loadAllSatelliteResources !== undefined ? source.loadAllSatelliteResources : target.loadAllSatelliteResources; + source.mainAssemblyName = source.mainAssemblyName !== undefined ? source.mainAssemblyName : target.mainAssemblyName; + source.virtualWorkingDirectory = source.virtualWorkingDirectory !== undefined ? source.virtualWorkingDirectory : target.virtualWorkingDirectory; + source.debugLevel = source.debugLevel !== undefined ? source.debugLevel : target.debugLevel; + source.diagnosticTracing = source.diagnosticTracing !== undefined ? source.diagnosticTracing : target.diagnosticTracing; + source.environmentVariables = { ...target.environmentVariables, ...source.environmentVariables }; + source.runtimeOptions = [...target.runtimeOptions, ...source.runtimeOptions]; + Object.assign(target, source); + if (target.resources.coreAssembly.length) { + isConfigDownloaded = true; + } + return target; +} +function mergeResources(target, source) { + // no need to merge the same object + if (target === source || source === undefined || source === null) + return target; + source.coreAssembly = [...target.coreAssembly, ...source.coreAssembly]; + source.assembly = [...target.assembly, ...source.assembly]; + source.lazyAssembly = [...target.lazyAssembly, ...source.lazyAssembly]; + source.corePdb = [...target.corePdb, ...source.corePdb]; + source.pdb = [...target.pdb, ...source.pdb]; + source.jsModuleWorker = [...target.jsModuleWorker, ...source.jsModuleWorker]; + source.jsModuleNative = [...target.jsModuleNative, ...source.jsModuleNative]; + source.jsModuleDiagnostics = [...target.jsModuleDiagnostics, ...source.jsModuleDiagnostics]; + source.jsModuleRuntime = [...target.jsModuleRuntime, ...source.jsModuleRuntime]; + source.wasmSymbols = [...target.wasmSymbols, ...source.wasmSymbols]; + source.wasmNative = [...target.wasmNative, ...source.wasmNative]; + source.icu = [...target.icu, ...source.icu]; + source.vfs = [...target.vfs, ...source.vfs]; + source.modulesAfterConfigLoaded = [...target.modulesAfterConfigLoaded, ...source.modulesAfterConfigLoaded]; + source.modulesAfterRuntimeReady = [...target.modulesAfterRuntimeReady, ...source.modulesAfterRuntimeReady]; + source.extensions = { ...target.extensions, ...source.extensions }; + for (const key in source.satelliteResources) { + source.satelliteResources[key] = [...target.satelliteResources[key] || [], ...source.satelliteResources[key] || []]; + } + return Object.assign(target, source); +} +function normalizeConfig(target) { + if (!target.resources) + target.resources = {}; + normalizeResources(target.resources); + if (!target.environmentVariables) + target.environmentVariables = {}; + if (!target.runtimeOptions) + target.runtimeOptions = []; + if (target.appendElementOnExit === undefined) + target.appendElementOnExit = false; + if (target.logExitCode === undefined) + target.logExitCode = false; + if (target.exitOnUnhandledError === undefined) + target.exitOnUnhandledError = false; + if (target.loadAllSatelliteResources === undefined) + target.loadAllSatelliteResources = false; + if (target.debugLevel === undefined) + target.debugLevel = 0; + if (target.diagnosticTracing === undefined) + target.diagnosticTracing = false; + if (target.virtualWorkingDirectory === undefined) + target.virtualWorkingDirectory = "/"; + if (target.mainAssemblyName === undefined) + target.mainAssemblyName = "HelloWorld.dll"; +} +function normalizeResources(target) { + if (!target.coreAssembly) + target.coreAssembly = []; + if (!target.assembly) + target.assembly = []; + if (!target.lazyAssembly) + target.lazyAssembly = []; + if (!target.corePdb) + target.corePdb = []; + if (!target.pdb) + target.pdb = []; + if (!target.jsModuleWorker) + target.jsModuleWorker = []; + if (!target.jsModuleNative) + target.jsModuleNative = []; + if (!target.jsModuleDiagnostics) + target.jsModuleDiagnostics = []; + if (!target.jsModuleRuntime) + target.jsModuleRuntime = []; + if (!target.wasmSymbols) + target.wasmSymbols = []; + if (!target.wasmNative) + target.wasmNative = []; + if (!target.icu) + target.icu = []; + if (!target.modulesAfterConfigLoaded) + target.modulesAfterConfigLoaded = []; + if (!target.modulesAfterRuntimeReady) + target.modulesAfterRuntimeReady = []; + if (!target.satelliteResources) + target.satelliteResources = {}; + if (!target.extensions) + target.extensions = {}; + if (!target.vfs) + target.vfs = []; +} + +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// eslint-disable-next-line @typescript-eslint/no-unused-vars +function exit(exit_code, reason) { + const reasonStr = reason ? (reason.stack ? reason.stack || reason.message : reason.toString()) : ""; + if (exit_code !== 0) { + Logger.error(`Exit with code ${exit_code} ${reason ? "and reason: " + reasonStr : ""}`); + } + if (JSEngine.IS_NODE) { + globalThis.process.exit(exit_code); + } +} + +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +/// a unique symbol used to mark a promise as controllable +const promise_control_symbol = Symbol.for("wasm promise_control"); +/// Creates a new promise together with a controller that can be used to resolve or reject that promise. +/// Optionally takes callbacks to be called immediately after a promise is resolved or rejected. +function createPromiseController(afterResolve, afterReject) { + let promiseControl = null; + const promise = new Promise((resolve, reject) => { + promiseControl = { + isDone: false, + promise: null, + resolve: (data) => { + if (!promiseControl.isDone) { + promiseControl.isDone = true; + resolve(data); + if (afterResolve) { + afterResolve(); + } + } + }, + reject: (reason) => { + if (!promiseControl.isDone) { + promiseControl.isDone = true; + reject(reason); + if (afterReject) { + afterReject(); + } + } + }, + propagateFrom: (other) => { + other.then(promiseControl.resolve).catch(promiseControl.reject); + } + }; + }); + promiseControl.promise = promise; + const controllablePromise = promise; + controllablePromise[promise_control_symbol] = promiseControl; + return promiseControl; +} +function getPromiseController(promise) { + return promise[promise_control_symbol]; +} +function isControllablePromise(promise) { + return promise[promise_control_symbol] !== undefined; +} + +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +let CoreCLRInitialized = false; +const runMainPromiseController = createPromiseController(); +function browserHostInitializeCoreCLR() { + if (CoreCLRInitialized) { + return; + } + // int browserHostInitializeCoreCLR(void) + const res = Module.ccall("browserHostInitializeCoreCLR", "number"); + if (res != 0) { + const reason = new Error("Failed to initialize CoreCLR"); + runMainPromiseController.reject(reason); + exit(res, reason); + } + CoreCLRInitialized = true; +} +function browserHostResolveMain(exitCode) { + runMainPromiseController.resolve(exitCode); +} +function browserHostRejectMain(reason) { + runMainPromiseController.reject(reason); +} +function getRunMainPromise() { + return runMainPromiseController.promise; +} + +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +const scriptUrlQuery = /*! webpackIgnore: true */ import.meta.url; +const queryIndex = scriptUrlQuery.indexOf("?"); +const modulesUniqueQuery = queryIndex > 0 ? scriptUrlQuery.substring(queryIndex) : ""; +const scriptUrl = normalizeFileUrl(scriptUrlQuery); +const scriptDirectory = normalizeDirectoryUrl(scriptUrl); +const nativeModulePromiseController = createPromiseController(() => { + updateAllInternals(); +}); +// WASM-TODO: retry logic +// WASM-TODO: throttling logic +// WASM-TODO: load icu data +// WASM-TODO: invokeLibraryInitializers +// WASM-TODO: webCIL +async function createRuntime(downloadOnly, loadBootResource) { + const config = getConfig(); + if (!config.resources || !config.resources.coreAssembly || !config.resources.coreAssembly.length) + throw new Error("Invalid config, resources is not set"); + const coreAssembliesPromise = Promise.all(config.resources.coreAssembly.map(fetchDll)); + const assembliesPromise = Promise.all(config.resources.assembly.map(fetchDll)); + const runtimeModulePromise = loadModule(config.resources.jsModuleRuntime[0], loadBootResource); + const nativeModulePromise = loadModule(config.resources.jsModuleNative[0], loadBootResource); + const nativeModule = await nativeModulePromise; + const modulePromise = nativeModule.initialize(getInternals()); + nativeModulePromiseController.propagateFrom(modulePromise); + const runtimeModule = await runtimeModulePromise; + const runtimeModuleReady = runtimeModule.initialize(getInternals()); + await nativeModulePromiseController.promise; + await coreAssembliesPromise; + if (!downloadOnly) { + browserHostInitializeCoreCLR(); + } + await assembliesPromise; + await runtimeModuleReady; +} +async function loadModule(asset, loadBootResource) { + if (loadBootResource) + throw new Error("TODO: loadBootResource is not implemented yet"); + if (asset.name && !asset.resolvedUrl) { + asset.resolvedUrl = locateFile(asset.name); + } + if (!asset.resolvedUrl) + throw new Error("Invalid config, resources is not set"); + return await import(/* webpackIgnore: true */ asset.resolvedUrl); +} +function fetchWasm(asset) { + if (asset.name && !asset.resolvedUrl) { + asset.resolvedUrl = locateFile(asset.name); + } + return fetchBytes(asset); +} +async function fetchDll(asset) { + if (asset.name && !asset.resolvedUrl) { + asset.resolvedUrl = locateFile(asset.name); + } + const bytes = await fetchBytes(asset); + await nativeModulePromiseController.promise; + hostExports.registerDllBytes(bytes, asset); +} +async function fetchBytes(asset) { + Assert.check(asset && asset.resolvedUrl, "Bad asset.resolvedUrl"); + if (JSEngine.IS_NODE) { + const { promises: fs } = await import('fs'); + const { fileURLToPath } = await import(/*! webpackIgnore: true */ 'url'); + const isFileUrl = asset.resolvedUrl.startsWith("file://"); + if (isFileUrl) { + asset.resolvedUrl = fileURLToPath(asset.resolvedUrl); + } + const buffer = await fs.readFile(asset.resolvedUrl); + return new Uint8Array(buffer); + } + else { + const response = await fetch(asset.resolvedUrl); + if (!response.ok) { + throw new Error(`Failed to load ${asset.resolvedUrl} with ${response.status} ${response.statusText}`); + } + const buffer = await response.arrayBuffer(); + return new Uint8Array(buffer); + } +} +function locateFile(path) { + if ("URL" in globalThis) { + return new URL(path, scriptDirectory).toString(); + } + if (isPathAbsolute(path)) + return path; + return scriptDirectory + path + modulesUniqueQuery; +} +function normalizeFileUrl(filename) { + // unix vs windows + // remove query string + return filename.replace(/\\/g, "/").replace(/[?#].*/, ""); +} +function normalizeDirectoryUrl(dir) { + return dir.slice(0, dir.lastIndexOf("/")) + "/"; +} +const protocolRx = /^[a-zA-Z][a-zA-Z\d+\-.]*?:\/\//; +const windowsAbsoluteRx = /[a-zA-Z]:[\\/]/; +function isPathAbsolute(path) { + if (JSEngine.IS_NODE || JSEngine.IS_SHELL) { + // unix /x.json + // windows \x.json + // windows C:\x.json + // windows C:/x.json + return path.startsWith("/") || path.startsWith("\\") || path.indexOf("///") !== -1 || windowsAbsoluteRx.test(path); + } + // anything with protocol is always absolute + // windows file:///C:/x.json + // windows http://C:/x.json + return protocolRx.test(path); +} + +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +let configUrl = undefined; +let applicationArguments = []; +let loadBootResourceCallback = undefined; +/* eslint-disable @typescript-eslint/no-unused-vars */ +class HostBuilder { + withConfig(config) { + mergeConfig(config); + return this; + } + withConfigSrc(configSrc) { + configUrl = configSrc; + return this; + } + withApplicationArguments(...args) { + applicationArguments = args; + return this; + } + withEnvironmentVariable(name, value) { + mergeConfig({ + environmentVariables: { + [name]: value + } + }); + return this; + } + withEnvironmentVariables(variables) { + mergeConfig({ + environmentVariables: variables + }); + return this; + } + withVirtualWorkingDirectory(vfsPath) { + mergeConfig({ + virtualWorkingDirectory: vfsPath + }); + return this; + } + withDiagnosticTracing(enabled) { + mergeConfig({ + diagnosticTracing: enabled + }); + return this; + } + withDebugging(level) { + mergeConfig({ + debugLevel: level + }); + return this; + } + withMainAssembly(mainAssemblyName) { + mergeConfig({ + mainAssemblyName: mainAssemblyName + }); + return this; + } + withApplicationArgumentsFromQuery() { + if (!globalThis.window) { + throw new Error("Missing window to the query parameters from"); + } + if (typeof globalThis.URLSearchParams == "undefined") { + throw new Error("URLSearchParams is supported"); + } + const params = new URLSearchParams(globalThis.window.location.search); + const values = params.getAll("arg"); + return this.withApplicationArguments(...values); + } + withApplicationEnvironment(applicationEnvironment) { + mergeConfig({ + applicationEnvironment: applicationEnvironment + }); + return this; + } + withApplicationCulture(applicationCulture) { + mergeConfig({ + applicationCulture: applicationCulture + }); + return this; + } + withResourceLoader(loadBootResource) { + loadBootResourceCallback = loadBootResource; + return this; + } + // internal + withModuleConfig(moduleConfig) { + Object.assign(Module, moduleConfig); + return this; + } + // internal + withConsoleForwarding() { + // TODO + return this; + } + // internal + withExitOnUnhandledError() { + // TODO + return this; + } + // internal + withAsyncFlushOnExit() { + // TODO + return this; + } + // internal + withExitCodeLogging() { + // TODO + return this; + } + // internal + withElementOnExit() { + // TODO + return this; + } + // internal + withInteropCleanupOnExit() { + // TODO + return this; + } + async download() { + try { + await downloadConfig(configUrl, loadBootResourceCallback); + return createRuntime(true, loadBootResourceCallback); + } + catch (err) { + exit(1, err); + throw err; + } + } + async create() { + try { + await downloadConfig(configUrl, loadBootResourceCallback); + await createRuntime(false, loadBootResourceCallback); + this.runtimeApi = runtimeApi; + return this.runtimeApi; + } + catch (err) { + exit(1, err); + throw err; + } + } + async run() { + try { + if (!this.runtimeApi) { + await this.create(); + } + const config = getConfig(); + return this.runtimeApi.runMainAndExit(config.mainAssemblyName, applicationArguments); + } + catch (err) { + exit(1, err); + throw err; + } + } +} + +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +function initPolyfills() { + if (typeof globalThis.WeakRef !== "function") { + class WeakRefPolyfill { + constructor(value) { + this._value = value; + } + deref() { + return this._value; + } + } + globalThis.WeakRef = WeakRefPolyfill; + } + if (typeof globalThis.fetch !== "function") { + globalThis.fetch = fetchLike; + } +} +async function initPolyfillsAsync() { + if (JSEngine.IS_NODE) { + if (!globalThis.crypto) { + globalThis.crypto = {}; + } + if (!globalThis.crypto.getRandomValues) { + let nodeCrypto = undefined; + try { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore: + nodeCrypto = await import(/*! webpackIgnore: true */ 'node:crypto'); + } + catch (err) { + // Noop, error throwing polyfill provided bellow + } + if (!nodeCrypto) { + globalThis.crypto.getRandomValues = () => { + throw new Error("Using node without crypto support. To enable current operation, either provide polyfill for 'globalThis.crypto.getRandomValues' or enable 'node:crypto' module."); + }; + } + else if (nodeCrypto.webcrypto) { + globalThis.crypto = nodeCrypto.webcrypto; + } + else if (nodeCrypto.randomBytes) { + const getRandomValues = (buffer) => { + if (buffer) { + buffer.set(nodeCrypto.randomBytes(buffer.length)); + } + }; + globalThis.crypto.getRandomValues = getRandomValues; + } + } + if (!globalThis.performance) { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore: + globalThis.performance = (await import(/*! webpackIgnore: true */ 'perf_hooks')).performance; + } + } +} +async function fetchLike(url, init) { + let node_fs = undefined; + let node_url = undefined; + try { + // this need to be detected only after we import node modules in onConfigLoaded + const hasFetch = typeof (globalThis.fetch) === "function"; + if (JSEngine.IS_NODE) { + const isFileUrl = url.startsWith("file://"); + if (!isFileUrl && hasFetch) { + return globalThis.fetch(url, init || { credentials: "same-origin" }); + } + if (!node_fs) { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore: + node_url = await import(/*! webpackIgnore: true */ 'url'); + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore: + node_fs = await import(/*! webpackIgnore: true */ 'fs'); + } + if (isFileUrl) { + url = node_url.fileURLToPath(url); + } + const arrayBuffer = await node_fs.promises.readFile(url); + return { + ok: true, + headers: { + length: 0, + get: () => null + }, + url, + arrayBuffer: () => arrayBuffer, + json: () => JSON.parse(arrayBuffer), + text: () => { + throw new Error("NotImplementedException"); + } + }; + } + else if (hasFetch) { + return globalThis.fetch(url, init || { credentials: "same-origin" }); + } + else if (typeof (read) === "function") { + // note that it can't open files with unicode names, like Strae.xml + // https://bugs.chromium.org/p/v8/issues/detail?id=12541 + return { + ok: true, + url, + headers: { + length: 0, + get: () => null + }, + arrayBuffer: () => { + return new Uint8Array(read(url, "binary")); + }, + json: () => { + return JSON.parse(read(url, "utf8")); + }, + text: () => read(url, "utf8") + }; + } + } + catch (e) { + return { + ok: false, + url, + status: 500, + headers: { + length: 0, + get: () => null + }, + statusText: "ERR28: " + e, + arrayBuffer: () => { + throw e; + }, + json: () => { + throw e; + }, + text: () => { + throw e; + } + }; + } + throw new Error("No fetch implementation available"); +} + +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +let runtimeList; +class RuntimeList { + constructor() { + this.list = {}; + } + registerRuntime(api) { + if (api.runtimeId === undefined) { + api.runtimeId = Object.keys(this.list).length; + } + this.list[api.runtimeId] = new globalThis.WeakRef(api); + return api.runtimeId; + } + getRuntime(runtimeId) { + const wr = this.list[runtimeId]; + return wr ? wr.deref() : undefined; + } +} +function registerRuntime(api) { + const globalThisAny = globalThis; + // this code makes it possible to find dotnet runtime on a page via global namespace, even when there are multiple runtimes at the same time + if (!globalThisAny.getDotnetRuntime) { + globalThisAny.getDotnetRuntime = (runtimeId) => globalThisAny.getDotnetRuntime.__list.getRuntime(runtimeId); + globalThisAny.getDotnetRuntime.__list = runtimeList = new RuntimeList(); + } + else { + runtimeList = globalThisAny.getDotnetRuntime.__list; + } + return runtimeList.registerRuntime(api); +} + +var ProductVersion = "10.0.0-dev"; + +var BuildConfiguration = "Debug"; + +var GitHash = "3f5c7d9c448b99bdeae770df46ffc3c923f7ccf4"; + +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// eslint-disable-next-line @typescript-eslint/no-unused-vars +async function invokeLibraryInitializers(functionName, args) { + throw new Error("Not implemented"); +} + +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// WASMTODO inline the code +function check(condition, messageFactory) { + if (!condition) { + const message = typeof messageFactory === "string" ? messageFactory : messageFactory(); + throw new Error(`Assert failed: ${message}`); + } +} +/* eslint-disable no-console */ +const prefix = "CLR_WASM: "; +function info(msg, ...data) { + console.info(prefix + msg, ...data); +} +function warn(msg, ...data) { + console.warn(prefix + msg, ...data); +} +function error(msg, ...data) { + if (data && data.length > 0 && data[0] && typeof data[0] === "object") { + // don't log silent errors + if (data[0].silent) { + return; + } + if (data[0].toString) { + console.error(prefix + msg, data[0].toString()); + return; + } + } + console.error(prefix + msg, ...data); +} + +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +function initialize() { + const ENVIRONMENT_IS_NODE = () => typeof process == "object" && typeof process.versions == "object" && typeof process.versions.node == "string"; + const ENVIRONMENT_IS_WEB_WORKER = () => typeof importScripts == "function"; + const ENVIRONMENT_IS_SIDECAR = () => ENVIRONMENT_IS_WEB_WORKER() && typeof dotnetSidecar !== "undefined"; // sidecar is emscripten main running in a web worker + const ENVIRONMENT_IS_WORKER = () => ENVIRONMENT_IS_WEB_WORKER() && !ENVIRONMENT_IS_SIDECAR(); // we redefine what ENVIRONMENT_IS_WORKER, we replace it in emscripten internals, so that sidecar works + const ENVIRONMENT_IS_WEB = () => typeof window == "object" || (ENVIRONMENT_IS_WEB_WORKER() && !ENVIRONMENT_IS_NODE()); + const ENVIRONMENT_IS_SHELL = () => !ENVIRONMENT_IS_WEB() && !ENVIRONMENT_IS_NODE(); + const runtimeApi = { + INTERNAL: {}, + Module: {}, + runtimeId: -1, + runtimeBuildInfo: { + productVersion: ProductVersion, + gitHash: GitHash, + buildConfiguration: BuildConfiguration, + wasmEnableThreads: false, + wasmEnableSIMD: true, + wasmEnableExceptionHandling: true, + }, + }; + const updates = []; + setInternals({ + config: config, + runtimeApi: runtimeApi, + updates, + }); + const runtimeApiFunctions = { + getConfig, + exit, + invokeLibraryInitializers, + }; + const loaderFunctions = { + ENVIRONMENT_IS_NODE, + ENVIRONMENT_IS_SHELL, + ENVIRONMENT_IS_WEB, + ENVIRONMENT_IS_WORKER, + ENVIRONMENT_IS_SIDECAR, + getRunMainPromise, + browserHostRejectMain, + browserHostResolveMain, + }; + const jsEngine = { + IS_NODE: ENVIRONMENT_IS_NODE(), + IS_SHELL: ENVIRONMENT_IS_SHELL(), + IS_WEB: ENVIRONMENT_IS_WEB(), + IS_WORKER: ENVIRONMENT_IS_WORKER(), + IS_SIDECAR: ENVIRONMENT_IS_SIDECAR(), + }; + const logger = { + info, + warn, + error, + }; + const assert = { + check, + }; + Object.assign(runtimeApi, runtimeApiFunctions); + Object.assign(Logger, logger); + Object.assign(Assert, assert); + Object.assign(JSEngine, jsEngine); + Object.assign(loaderExports, loaderFunctions); + dotnetInternals.loaderExportsTable = [...tabulateLE(Logger, Assert, loaderExports)]; + updates.push(updateMyInternals); + updateAllInternals(); + return runtimeApi; +} + +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +initPolyfills(); +registerRuntime(initialize()); +await initPolyfillsAsync(); +const dotnet = new HostBuilder(); + +export { dotnet, exit }; diff --git a/src/native/corehost/browserhost/native.rc b/src/native/corehost/browserhost/native.rc new file mode 100644 index 00000000000000..0a49d6b55d9591 --- /dev/null +++ b/src/native/corehost/browserhost/native.rc @@ -0,0 +1,7 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#define FX_VER_FILEDESCRIPTION_STR "CoreCLR test host" + +#include +#include diff --git a/src/native/corehost/browserhost/sample/CMakeLists.txt b/src/native/corehost/browserhost/sample/CMakeLists.txt new file mode 100644 index 00000000000000..ad0437cbdbdd0f --- /dev/null +++ b/src/native/corehost/browserhost/sample/CMakeLists.txt @@ -0,0 +1,24 @@ +# Licensed to the .NET Foundation under one or more agreements. +# The .NET Foundation licenses this file to you under the MIT license. + +# this is just a incomplete sample app deployment +# WASM-TODO: implement proper in-tree project via MSBuild and WASM SDK +# WASM-TODO: deploy *.js.map when available +set(SAMPLE_ASSETS + index.html + main.mjs + dotnet.boot.js + ${CLR_ARTIFACTS_OBJ_DIR}/coreclr/browser.wasm.${CMAKE_BUILD_TYPE}/corehost/dotnet.js + ${CLR_ARTIFACTS_OBJ_DIR}/coreclr/browser.wasm.${CMAKE_BUILD_TYPE}/corehost/dotnet.d.ts + ${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Runtime.InteropServices.JavaScript.Native/dotnet.runtime.js + + # Bring your own DLLs and update the dotnet.boot.js to match + # HelloWorld.dll + # System.Private.CoreLib.dll + # System.Console.dll + # System.Runtime.dll + # System.Runtime.InteropServices.dll + # System.Threading.dll + +) +install(FILES ${SAMPLE_ASSETS} DESTINATION corehost COMPONENT runtime) diff --git a/src/native/corehost/browserhost/sample/HelloWorld.cs b/src/native/corehost/browserhost/sample/HelloWorld.cs new file mode 100644 index 00000000000000..26459b2020e59a --- /dev/null +++ b/src/native/corehost/browserhost/sample/HelloWorld.cs @@ -0,0 +1,11 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace HelloWorld; +public class Program +{ + public static void Main(string[] args) + { + System.Console.WriteLine("Hello, World!"); + } +} diff --git a/src/native/corehost/browserhost/sample/HelloWorld.csproj b/src/native/corehost/browserhost/sample/HelloWorld.csproj new file mode 100644 index 00000000000000..ba5d1561035f8a --- /dev/null +++ b/src/native/corehost/browserhost/sample/HelloWorld.csproj @@ -0,0 +1,11 @@ + + + + Exe + net10.0 + enable + enable + true + + + diff --git a/src/native/corehost/browserhost/sample/ReadMe.md b/src/native/corehost/browserhost/sample/ReadMe.md new file mode 100644 index 00000000000000..9f87c04d56bbba --- /dev/null +++ b/src/native/corehost/browserhost/sample/ReadMe.md @@ -0,0 +1,9 @@ +# Demo files + +This is simple demo customer code that uses dotnet.js + +Easiest way is to test it is: +- copy this and other assemblies into `artifacts/bin/coreclr/browser.wasm.Debug/corehost` +- edit `dotnet.boot.js` to match your assemblies +- run `dotnet-serve --directory artifacts/bin/coreclr/browser.wasm.Debug/corehost` and point your browser +- or run `node ./main.mjs` in that directory. \ No newline at end of file diff --git a/src/native/corehost/browserhost/sample/dotnet.boot.js b/src/native/corehost/browserhost/sample/dotnet.boot.js new file mode 100644 index 00000000000000..52971a6be1143b --- /dev/null +++ b/src/native/corehost/browserhost/sample/dotnet.boot.js @@ -0,0 +1,54 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// WASM-TODO: this is dummy configuration until we have MSBuild WASM SDK for corehost, which will generate this file + +export const config = /*json-start*/{ + "mainAssemblyName": "HelloWorld.dll", + "virtualWorkingDirectory": "/", + "resources": { + "jsModuleNative": [ + { + "name": "dotnet.native.js" + } + ], + "jsModuleRuntime": [ + { + "name": "dotnet.runtime.js" + } + ], + "wasmNative": [ + { + "name": "dotnet.native.wasm", + } + ], + "coreAssembly": [ + { + "virtualPath": "/System.Private.CoreLib.dll", + "name": "System.Private.CoreLib.dll" + }, + ], + "assembly": [ + { + "virtualPath": "/System.Runtime.dll", + "name": "System.Runtime.dll" + }, + { + "virtualPath": "/System.Threading.dll", + "name": "System.Threading.dll" + }, + { + "virtualPath": "/System.Runtime.InteropServices.dll", + "name": "System.Runtime.InteropServices.dll" + }, + { + "virtualPath": "/System.Console.dll", + "name": "System.Console.dll" + }, + { + "virtualPath": "/HelloWorld.dll", + "name": "HelloWorld.dll" + } + ] + } +}/*json-end*/; \ No newline at end of file diff --git a/src/native/corehost/browserhost/sample/index.html b/src/native/corehost/browserhost/sample/index.html new file mode 100644 index 00000000000000..dac625bb04d191 --- /dev/null +++ b/src/native/corehost/browserhost/sample/index.html @@ -0,0 +1,18 @@ + + + + + + + Wasm Browser Sample + + + + + + + + Answer to the Ultimate Question of Life, the Universe, and Everything is : + + + \ No newline at end of file diff --git a/src/native/corehost/browserhost/sample/main.mjs b/src/native/corehost/browserhost/sample/main.mjs new file mode 100644 index 00000000000000..9ec5bc9c8fec45 --- /dev/null +++ b/src/native/corehost/browserhost/sample/main.mjs @@ -0,0 +1,12 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +import { dotnet, exit } from './dotnet.js' + +try { + await dotnet.run(); +} +catch (err) { + console.error(err); + exit(2, err); +} diff --git a/src/native/corehost/hostpolicy/hostpolicy_context.cpp b/src/native/corehost/hostpolicy/hostpolicy_context.cpp index e513472211f01b..38e324cade070b 100644 --- a/src/native/corehost/hostpolicy/hostpolicy_context.cpp +++ b/src/native/corehost/hostpolicy/hostpolicy_context.cpp @@ -354,9 +354,9 @@ int hostpolicy_context_t::initialize(const hostpolicy_init_t &hostpolicy_init, c } host_contract.get_runtime_property = &get_runtime_property; - pal::char_t buffer[STRING_LENGTH("0xffffffffffffffff")]; - pal::snwprintf(buffer, ARRAY_SIZE(buffer), _X("0x%zx"), (size_t)(&host_contract)); - if (!coreclr_properties.add(_STRINGIFY(HOST_PROPERTY_RUNTIME_CONTRACT), buffer)) + pal::char_t ptr_to_string_buffer[STRING_LENGTH("0xffffffffffffffff") + 1]; + pal::snwprintf(ptr_to_string_buffer, ARRAY_SIZE(ptr_to_string_buffer), _X("0x%zx"), (size_t)(&host_contract)); + if (!coreclr_properties.add(_STRINGIFY(HOST_PROPERTY_RUNTIME_CONTRACT), ptr_to_string_buffer)) { log_duplicate_property_error(_STRINGIFY(HOST_PROPERTY_RUNTIME_CONTRACT)); return StatusCode::LibHostDuplicateProperty; diff --git a/src/native/libs/CMakeLists.txt b/src/native/libs/CMakeLists.txt index 5fd8f0d051a9d8..cec9bc263339b6 100644 --- a/src/native/libs/CMakeLists.txt +++ b/src/native/libs/CMakeLists.txt @@ -86,6 +86,8 @@ if (CLR_CMAKE_TARGET_UNIX OR CLR_CMAKE_TARGET_BROWSER OR CLR_CMAKE_TARGET_WASI) # -O2 optimization generates faster/smaller code on Android # TODO: This duplicates the settings in eng/native/configureoptimization.cmake, we should unify it add_compile_options (-O2) + elseif (CLR_CMAKE_TARGET_BROWSER) + add_compile_options (-Oz) else() add_compile_options (-O3) endif () @@ -108,6 +110,12 @@ endif () add_subdirectory(System.IO.Compression.Native) +# Only when Browser for CoreCLR +if (CLR_CMAKE_TARGET_BROWSER AND BUILD_LIBS_NATIVE_BROWSER) + add_subdirectory(System.Native.Browser) + add_subdirectory(System.Runtime.InteropServices.JavaScript.Native) +endif () + if (CLR_CMAKE_TARGET_UNIX OR CLR_CMAKE_TARGET_BROWSER OR CLR_CMAKE_TARGET_WASI) include(configure.cmake) diff --git a/src/native/libs/Common/JavaScript/types/consts.d.ts b/src/native/libs/Common/JavaScript/types/consts.d.ts new file mode 100644 index 00000000000000..1074aac7814744 --- /dev/null +++ b/src/native/libs/Common/JavaScript/types/consts.d.ts @@ -0,0 +1,8 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +declare module "consts:*" { + //Constant that will be inlined by Rollup and rollup-plugin-consts. + const constant: any; + export default constant; +} diff --git a/src/native/libs/Common/JavaScript/types/emscripten.ts b/src/native/libs/Common/JavaScript/types/emscripten.ts new file mode 100644 index 00000000000000..e906165a35b7a4 --- /dev/null +++ b/src/native/libs/Common/JavaScript/types/emscripten.ts @@ -0,0 +1,68 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +export interface ManagedPointer { + __brandManagedPointer: "ManagedPointer" +} + +export interface NativePointer { + __brandNativePointer: "NativePointer" +} + +export interface VoidPtr extends NativePointer { + __brand: "VoidPtr" +} +export interface VoidPtrPtr extends NativePointer { + __brand: "VoidPtrPtr" +} +export interface CharPtr extends NativePointer { + __brand: "CharPtr" +} +export interface Int32Ptr extends NativePointer { + __brand: "Int32Ptr" +} +export interface CharPtrPtr extends NativePointer { + __brand: "CharPtrPtr" +} + +export interface EmscriptenModule { + // this should match emcc -s EXPORTED_FUNCTIONS + _malloc(size: number): VoidPtr; + _free(ptr: VoidPtr): void; + _sbrk(size: number): VoidPtr; + _posix_memalign(res: VoidPtrPtr, alignment: number, size: number): number; + + // this should match emcc -s EXPORTED_RUNTIME_METHODS + out(message: string): void; + err(message: string): void; + ccall(ident: string, returnType?: string | null, argTypes?: string[], args?: any[], opts?: any): T; + cwrap(ident: string, returnType: string, argTypes?: string[], opts?: any): T; + cwrap(ident: string, ...args: any[]): T; + setValue(ptr: VoidPtr, value: number, type: string, noSafe?: number | boolean): void; + setValue(ptr: Int32Ptr, value: number, type: string, noSafe?: number | boolean): void; + getValue(ptr: number, type: string, noSafe?: number | boolean): number; + UTF8ToString(ptr: CharPtr, maxBytesToRead?: number): string; + UTF8ArrayToString(u8Array: Uint8Array, idx?: number, maxBytesToRead?: number): string; + stringToUTF8Array(str: string, heap: Uint8Array, outIdx: number, maxBytesToWrite: number): void; + lengthBytesUTF8(str: string): number; + FS_createPath(parent: string, path: string, canRead?: boolean, canWrite?: boolean): string; + FS_createDataFile(parent: string, name: string, data: TypedArray, canRead: boolean, canWrite: boolean, canOwn?: boolean): string; + addFunction(fn: Function, signature: string): number; + stackSave(): VoidPtr; + stackRestore(stack: VoidPtr): void; + stackAlloc(size: number): VoidPtr; + + + instantiateWasm?: InstantiateWasmCallBack; + preInit?: (() => any)[] | (() => any); + preRun?: (() => any)[] | (() => any); + onRuntimeInitialized?: () => any; + postRun?: (() => any)[] | (() => any); + onAbort?: { (error: any): void }; + onExit?: { (code: number): void }; +} + +export type InstantiateWasmSuccessCallback = (instance: WebAssembly.Instance, module: WebAssembly.Module | undefined) => void; +export type InstantiateWasmCallBack = (imports: WebAssembly.Imports, successCallback: InstantiateWasmSuccessCallback) => any; + +export type TypedArray = Int8Array | Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array; diff --git a/src/native/libs/Common/JavaScript/types/emsdk.d.ts b/src/native/libs/Common/JavaScript/types/emsdk.d.ts new file mode 100644 index 00000000000000..04e8e2e61bac20 --- /dev/null +++ b/src/native/libs/Common/JavaScript/types/emsdk.d.ts @@ -0,0 +1,5 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +declare function autoAddDeps(obj: any, name: string): void; +declare function addToLibrary(obj: any): void; diff --git a/src/native/libs/Common/JavaScript/types/exchange.ts b/src/native/libs/Common/JavaScript/types/exchange.ts new file mode 100644 index 00000000000000..da388fb591910f --- /dev/null +++ b/src/native/libs/Common/JavaScript/types/exchange.ts @@ -0,0 +1,79 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +import type { registerDllBytes } from "../../../../corehost/browserhost/host/host"; +import type { isSharedArrayBuffer } from "../../../../corehost/browserhost/host/memory"; +import type { check, error, info, warn } from "../../../../corehost/browserhost/loader/logging"; +import type { browserHostResolveMain, browserHostRejectMain, getRunMainPromise } from "../../../../corehost/browserhost/loader/run"; + +export type EnvironmentType = { + IS_NODE: boolean, + IS_SHELL: boolean, + IS_WEB: boolean, + IS_WORKER: boolean, + IS_SIDECAR: boolean, +} + +export type RuntimeExports = { +} + +export type RuntimeExportsTable = [ +] + +export type LoggerType = { + info: typeof info, + warn: typeof warn, + error: typeof error, +} + +export type AssertType = { + check: typeof check, +} + +export type LoaderExports = { + ENVIRONMENT_IS_NODE: ()=> boolean, + ENVIRONMENT_IS_SHELL: ()=> boolean, + ENVIRONMENT_IS_WEB: ()=> boolean, + ENVIRONMENT_IS_WORKER: ()=> boolean, + ENVIRONMENT_IS_SIDECAR: ()=> boolean, + browserHostResolveMain:typeof browserHostResolveMain, + browserHostRejectMain:typeof browserHostRejectMain, + getRunMainPromise:typeof getRunMainPromise, +} + +export type LoaderExportsTable = [ + typeof info, + typeof warn, + typeof error, + typeof check, + ()=> boolean, + ()=> boolean, + ()=> boolean, + ()=> boolean, + ()=> boolean, + typeof browserHostResolveMain, + typeof browserHostRejectMain, + typeof getRunMainPromise, +] + +export type HostNativeExports = { + isSharedArrayBuffer : typeof isSharedArrayBuffer, + registerDllBytes: typeof registerDllBytes +} + +export type HostNativeExportsTable = [ + typeof registerDllBytes, + typeof isSharedArrayBuffer, +] + +export type InteropJavaScriptNativeExports = { +} + +export type InteropJavaScriptNativeExportsTable = [ +] + +export type NativeBrowserExports = { +} + +export type NativeBrowserExportsTable = [ +] diff --git a/src/native/libs/Common/JavaScript/types/export-api.ts b/src/native/libs/Common/JavaScript/types/export-api.ts new file mode 100644 index 00000000000000..90d65cc84dd041 --- /dev/null +++ b/src/native/libs/Common/JavaScript/types/export-api.ts @@ -0,0 +1,21 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +import type { CreateDotnetRuntimeType, DotnetHostBuilder, DotnetModuleConfig, ModuleAPI, LoaderConfig, IMemoryView, AssetEntry, GlobalizationMode, AssetBehaviors, RuntimeAPI, dotnet, exit } from "./public-api"; +import type { EmscriptenModule } from "./emscripten"; + +// Here, declare things that go in the global namespace, or augment existing declarations in the global namespace +declare global { + function getDotnetRuntime(runtimeId: number): RuntimeAPI | undefined; + const dotnetSidecar: boolean | undefined; +} + +declare const createDotnetRuntime: CreateDotnetRuntimeType; + +export default createDotnetRuntime; + +export { + EmscriptenModule, + RuntimeAPI, ModuleAPI, DotnetHostBuilder, DotnetModuleConfig, CreateDotnetRuntimeType, LoaderConfig, IMemoryView, AssetEntry, GlobalizationMode, AssetBehaviors, + dotnet, exit +}; diff --git a/src/native/libs/Common/JavaScript/types/index.ts b/src/native/libs/Common/JavaScript/types/index.ts new file mode 100644 index 00000000000000..c60ad4c72d2072 --- /dev/null +++ b/src/native/libs/Common/JavaScript/types/index.ts @@ -0,0 +1,8 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +export * from "./emscripten"; +export * from "./internal"; +export * from "./public-api"; +export * from "./exchange"; + diff --git a/src/native/libs/Common/JavaScript/types/internal.ts b/src/native/libs/Common/JavaScript/types/internal.ts new file mode 100644 index 00000000000000..d05e1f8f0e8305 --- /dev/null +++ b/src/native/libs/Common/JavaScript/types/internal.ts @@ -0,0 +1,123 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +import type { DotnetModuleConfig, RuntimeAPI, AssetEntry, LoaderConfig, LoadingResource } from "./public-api"; +import type { CharPtr, EmscriptenModule, ManagedPointer, NativePointer, VoidPtr } from "./emscripten"; +import { InteropJavaScriptNativeExportsTable, LoaderExportsTable, HostNativeExportsTable, RuntimeExportsTable, NativeBrowserExportsTable } from "./exchange"; + +export type GCHandle = { + __brand: "GCHandle" +} +export type JSHandle = { + __brand: "JSHandle" +} +export type JSFnHandle = { + __brand: "JSFnHandle" +} + +export type MemOffset = number | VoidPtr | NativePointer | ManagedPointer; +export type NumberOrPointer = number | VoidPtr | NativePointer | ManagedPointer; + +export const VoidPtrNull: VoidPtr = 0; +export const CharPtrNull: CharPtr = 0; +export const NativePointerNull: NativePointer = 0; + +// how we extended emscripten Module +export type DotnetModule = EmscriptenModule & DotnetModuleConfig; +export type DotnetModuleInternal = EmscriptenModule & DotnetModuleConfig & EmscriptenModuleInternal; + +// these are values from the last re-link with emcc/workload +export type EmscriptenBuildOptions = { + gitHash: string, +}; + +export type EmscriptenInternals = { + isPThread: boolean, + quit_: Function, + ExitStatus: new (status: number) => any, + gitHash: string, + getMemory(): WebAssembly.Memory, + getWasmIndirectFunctionTable(): WebAssembly.Table, + updateMemoryViews: () => void, +}; + +export declare interface EmscriptenModuleInternal extends EmscriptenModule { + HEAP8: Int8Array, + HEAP16: Int16Array; + HEAP32: Int32Array; + HEAP64: BigInt64Array; + HEAPU8: Uint8Array; + HEAPU16: Uint16Array; + HEAPU32: Uint32Array; + HEAPF32: Float32Array; + HEAPF64: Float64Array; + + locateFile?: (path: string, prefix?: string) => string; + mainScriptUrlOrBlob?: string; + ENVIRONMENT_IS_PTHREAD?: boolean; + FS: any; + wasmModule: WebAssembly.Instance | null; + ready: Promise; + wasmExports: any; + getWasmTableEntry(index: number): any; + removeRunDependency(id: string): void; + addRunDependency(id: string): void; + safeSetTimeout(func: Function, timeout: number): number; + runtimeKeepalivePush(): void; + runtimeKeepalivePop(): void; + maybeExit(): void; + print(message: string): void; + printErr(message: string): void; + abort(reason: any): void; + _emscripten_force_exit(exit_code: number): void; +} + +export interface AssetEntryInternal extends AssetEntry { + // this could have multiple values in time, because of re-try download logic + pendingDownloadInternal?: LoadingResource + noCache?: boolean + useCredentials?: boolean + isCore?: boolean +} + +export type LoaderConfigInternal = LoaderConfig & { + linkerEnabled?: boolean, + runtimeOptions?: string[], // array of runtime options as strings + appendElementOnExit?: boolean + logExitCode?: boolean + exitOnUnhandledError?: boolean + loadAllSatelliteResources?: boolean + resourcesHash?: string, +}; + + +/// A Promise with a controller attached +export interface ControllablePromise extends Promise { + __brand: "ControllablePromise" +} + +/// Just a pair of a promise and its controller +export interface PromiseController { + readonly promise: ControllablePromise; + isDone: boolean; + resolve: (value: T | PromiseLike) => void; + reject: (reason?: any) => void; + propagateFrom: (other: Promise) => void; +} + + +export type InternalApis = { + runtimeApi: RuntimeAPI, + runtimeExportsTable: RuntimeExportsTable, + loaderExportsTable: LoaderExportsTable, + hostNativeExportsTable: HostNativeExportsTable, + interopJavaScriptNativeExportsTable: InteropJavaScriptNativeExportsTable, + nativeBrowserExportsTable: NativeBrowserExportsTable, + config: LoaderConfigInternal, + updates: (() => void)[], +} + +export type JsModuleExports = { + initialize(internals: InternalApis): Promise; +}; + diff --git a/src/native/libs/Common/JavaScript/types/node.d.ts b/src/native/libs/Common/JavaScript/types/node.d.ts new file mode 100644 index 00000000000000..6985ad706b559d --- /dev/null +++ b/src/native/libs/Common/JavaScript/types/node.d.ts @@ -0,0 +1,5 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// only when script loaded as CJS +declare function importScripts(...urls: string[]): void; diff --git a/src/native/libs/Common/JavaScript/types/public-api.ts b/src/native/libs/Common/JavaScript/types/public-api.ts new file mode 100644 index 00000000000000..b90e51b2cd1efb --- /dev/null +++ b/src/native/libs/Common/JavaScript/types/public-api.ts @@ -0,0 +1,736 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +import type { EmscriptenModule, NativePointer, TypedArray } from "./emscripten"; + +// ----------------------------------------------------------- +// this files has all public exports from the dotnet.js module +// ----------------------------------------------------------- + +export interface DotnetHostBuilder { + /** + * @param config default values for the runtime configuration. It will be merged with the default values. + * Note that if you provide resources and don't provide custom configSrc URL, the dotnet.boot.js will be downloaded and applied by default. + */ + withConfig(config: LoaderConfig): DotnetHostBuilder; + /** + * @param configSrc URL to the configuration file. ./dotnet.boot.js is a default config file location. + */ + withConfigSrc(configSrc: string): DotnetHostBuilder; + /** + * "command line" arguments for the Main() method. + * @param args + */ + withApplicationArguments(...args: string[]): DotnetHostBuilder; + /** + * Sets the environment variable for the "process" + */ + withEnvironmentVariable(name: string, value: string): DotnetHostBuilder; + /** + * Sets the environment variables for the "process" + */ + withEnvironmentVariables(variables: { + [i: string]: string; + }): DotnetHostBuilder; + /** + * Sets the "current directory" for the "process" on the virtual file system. + */ + withVirtualWorkingDirectory(vfsPath: string): DotnetHostBuilder; + /** + * @param enabled if "true", writes diagnostic messages during runtime startup and execution to the browser console. + */ + withDiagnosticTracing(enabled: boolean): DotnetHostBuilder; + /** + * @param level + * level > 0 enables debugging and sets the logging level to debug + * level == 0 disables debugging and enables interpreter optimizations + * level < 0 enables debugging and disables debug logging. + */ + withDebugging(level: number): DotnetHostBuilder; + /** + * @param mainAssemblyName Sets the name of the assembly with the Main() method. Default is the same as the .csproj name. + */ + withMainAssembly(mainAssemblyName: string): DotnetHostBuilder; + /** + * Supply "command line" arguments for the Main() method from browser query arguments named "arg". Eg. `index.html?arg=A&arg=B&arg=C`. + * @param args + */ + withApplicationArgumentsFromQuery(): DotnetHostBuilder; + /** + * Sets application environment, such as "Development", "Staging", "Production", etc. + */ + withApplicationEnvironment(applicationEnvironment?: string): DotnetHostBuilder; + /** + * Sets application culture. This is a name specified in the BCP 47 format. See https://tools.ietf.org/html/bcp47 + */ + withApplicationCulture(applicationCulture?: string): DotnetHostBuilder; + /** + * Overrides the built-in boot resource loading mechanism so that boot resources can be fetched + * from a custom source, such as an external CDN. + */ + withResourceLoader(loadBootResource?: LoadBootResourceCallback): DotnetHostBuilder; + /** + * Downloads all the assets but doesn't create the runtime instance. + */ + download(): Promise; + /** + * Starts the runtime and returns promise of the API object. + */ + create(): Promise; + /** + * Runs the Main() method of the application and exits the runtime. + * You can provide "command line" arguments for the Main() method using + * - dotnet.withApplicationArguments(["A", "B", "C"]) + * - dotnet.withApplicationArgumentsFromQuery() + * Note: after the runtime exits, it would reject all further calls to the API. + * You can use runMain() if you want to keep the runtime alive. + */ + run(): Promise; +} +export type LoaderConfig = { + /** + * Additional search locations for assets. + */ + remoteSources?: string[]; + /** + * It will not fail the startup is .pdb files can't be downloaded + */ + ignorePdbLoadErrors?: boolean; + /** + * We are throttling parallel downloads in order to avoid net::ERR_INSUFFICIENT_RESOURCES on chrome. The default value is 16. + */ + maxParallelDownloads?: number; + /** + * We are making up to 2 more delayed attempts to download same asset. Default true. + */ + enableDownloadRetry?: boolean; + /** + * Name of the assembly with main entrypoint + */ + mainAssemblyName?: string; + /** + * Configures the runtime's globalization mode + */ + globalizationMode?: GlobalizationMode; + /** + * debugLevel > 0 enables debugging and sets the debug log level to debugLevel + * debugLevel == 0 disables debugging and enables interpreter optimizations + * debugLevel < 0 enables debugging and disables debug logging. + */ + debugLevel?: number; + /** + * Configures use of the `integrity` directive for fetching assets + */ + disableIntegrityCheck?: boolean; + /** + * Configures use of the `no-cache` directive for fetching assets + */ + disableNoCacheFetch?: boolean; + /** + * Enables diagnostic log messages during startup + */ + diagnosticTracing?: boolean; + /** + * Dictionary-style Object containing environment variables + */ + environmentVariables?: { + [i: string]: string; + }; + /** + * Subset of runtimeconfig.json + */ + runtimeConfig?: { + runtimeOptions?: { + configProperties?: { + [i: string]: string | number | boolean; + }; + }; + }; + /** + * initial number of workers to add to the emscripten pthread pool + */ + pthreadPoolInitialSize?: number; + /** + * number of unused workers kept in the emscripten pthread pool after startup + */ + pthreadPoolUnusedSize?: number; + /** + * If true, a list of the methods optimized by the interpreter will be saved and used for faster startup + * on future runs of the application + */ + interpreterPgo?: boolean; + /** + * Configures how long to wait before saving the interpreter PGO list. If your application takes + * a while to start you should adjust this value. + */ + interpreterPgoSaveDelay?: number; + /** + * application environment + */ + applicationEnvironment?: string; + /** + * Gets the application culture. This is a name specified in the BCP 47 format. See https://tools.ietf.org/html/bcp47 + */ + applicationCulture?: string; + resources?: Assets; + /** + * appsettings files to load to VFS + */ + appsettings?: string[]; + /** + * config extensions declared in MSBuild items @(WasmBootConfigExtension) + */ + extensions?: { + [name: string]: any; + }; + /** + * This is initial working directory for the runtime on the virtual file system. Default is "/". + */ + virtualWorkingDirectory?: string; + /** + * This is the arguments to the Main() method of the program when called with dotnet.run() Default is []. + * Note: RuntimeAPI.runMain() and RuntimeAPI.runMainAndExit() will replace this value, if they provide it. + */ + applicationArguments?: string[]; +}; +export type ResourceExtensions = { + [extensionName: string]: ResourceList; +}; +export interface Assets { + hash?: string; + coreAssembly: AssemblyAsset[]; + assembly: AssemblyAsset[]; + lazyAssembly?: AssemblyAsset[]; + corePdb?: PdbAsset[]; + pdb?: PdbAsset[]; + jsModuleWorker?: JsAsset[]; + jsModuleDiagnostics?: JsAsset[]; + jsModuleNative: JsAsset[]; + jsModuleRuntime: JsAsset[]; + wasmSymbols?: SymbolsAsset[]; + wasmNative: WasmAsset[]; + icu?: IcuAsset[]; + satelliteResources?: { + [cultureName: string]: AssemblyAsset[]; + }; + modulesAfterConfigLoaded?: JsAsset[]; + modulesAfterRuntimeReady?: JsAsset[]; + extensions?: ResourceExtensions; + coreVfs?: VfsAsset[]; + vfs?: VfsAsset[]; +} +export type Asset = { + /** + * this should be absolute url to the asset + */ + resolvedUrl?: string; + /** + * If true, the runtime startup would not fail if the asset download was not successful. + */ + isOptional?: boolean; + /** + * If provided, runtime doesn't have to fetch the data. + * Runtime would set the buffer to null after instantiation to free the memory. + */ + buffer?: ArrayBuffer | Promise; + /** + * It's metadata + fetch-like Promise + * If provided, the runtime doesn't have to initiate the download. It would just await the response. + */ + pendingDownload?: LoadingResource; +}; +export type WasmAsset = Asset & { + name: string; + hash?: string | null | ""; +}; +export type AssemblyAsset = Asset & { + virtualPath: string; + name: string; + hash?: string | null | ""; +}; +export type PdbAsset = Asset & { + virtualPath: string; + name: string; + hash?: string | null | ""; +}; +export type JsAsset = Asset & { + /** + * If provided, runtime doesn't have to import it's JavaScript modules. + * This will not work for multi-threaded runtime. + */ + moduleExports?: any | Promise; + name?: string; +}; +export type SymbolsAsset = Asset & { + name: string; +}; +export type VfsAsset = Asset & { + virtualPath: string; + name: string; + hash?: string | null | ""; +}; +export type IcuAsset = Asset & { + virtualPath: string; + name: string; + hash?: string | null | ""; +}; +/** + * A "key" is name of the file, a "value" is optional hash for integrity check. + */ +export type ResourceList = { + [name: string]: string | null | ""; +}; +/** + * Overrides the built-in boot resource loading mechanism so that boot resources can be fetched + * from a custom source, such as an external CDN. + * @param type The type of the resource to be loaded. + * @param name The name of the resource to be loaded. + * @param defaultUri The URI from which the framework would fetch the resource by default. The URI may be relative or absolute. + * @param integrity The integrity string representing the expected content in the response. + * @param behavior The detailed behavior/type of the resource to be loaded. + * @returns A URI string or a Response promise to override the loading process, or null/undefined to allow the default loading behavior. + * When returned string is not qualified with `./` or absolute URL, it will be resolved against the application base URI. + */ +export type LoadBootResourceCallback = (type: WebAssemblyBootResourceType, name: string, defaultUri: string, integrity: string, behavior: AssetBehaviors) => string | Promise | Promise | null | undefined; +export type BootModule = { + config: LoaderConfig; +}; +export interface LoadingResource { + name: string; + url: string; + response: Promise; +} +export interface AssetEntry { + /** + * the name of the asset, including extension. + */ + name: string; + /** + * determines how the asset will be handled once loaded + */ + behavior: AssetBehaviors; + /** + * this should be absolute url to the asset + */ + resolvedUrl?: string; + /** + * the integrity hash of the asset (if any) + */ + hash?: string | null | ""; + /** + * If specified, overrides the path of the asset in the virtual filesystem and similar data structures once downloaded. + */ + virtualPath?: string; + /** + * Culture code + */ + culture?: string; + /** + * If true, an attempt will be made to load the asset from each location in LoaderConfig.remoteSources. + */ + loadRemote?: boolean; + /** + * If true, the runtime startup would not fail if the asset download was not successful. + */ + isOptional?: boolean; + /** + * If provided, runtime doesn't have to fetch the data. + * Runtime would set the buffer to null after instantiation to free the memory. + */ + buffer?: ArrayBuffer | Promise; + /** + * If provided, runtime doesn't have to import it's JavaScript modules. + * This will not work for multi-threaded runtime. + */ + moduleExports?: any | Promise; + /** + * It's metadata + fetch-like Promise + * If provided, the runtime doesn't have to initiate the download. It would just await the response. + */ + pendingDownload?: LoadingResource; +} +export type SingleAssetBehaviors = + /** + * The binary of the .NET runtime. + */ + "dotnetwasm" + /** + * The javascript module for loader. + */ + | "js-module-dotnet" + /** + * The javascript module for threads. + */ + | "js-module-threads" + /** + * The javascript module for diagnostic server and client. + */ + | "js-module-diagnostics" + /** + * The javascript module for runtime. + */ + | "js-module-runtime" + /** + * The javascript module for emscripten. + */ + | "js-module-native" + /** + * Typically dotnet.boot.js + */ + | "manifest" + /** + * The debugging symbols + */ + | "symbols"; +export type AssetBehaviors = SingleAssetBehaviors | + /** + * Load asset as a managed resource assembly. + */ + "resource" + /** + * Load asset as a managed assembly. + */ + | "assembly" + /** + * Load asset as a managed debugging information. + */ + | "pdb" + /** + * Store asset into the native heap. + */ + | "heap" + /** + * Load asset as an ICU data archive. + */ + | "icu" + /** + * Load asset into the virtual filesystem (for fopen, File.Open, etc). + */ + | "vfs" + /** + * The javascript module that came from nuget package . + */ + | "js-module-library-initializer"; +export declare const enum GlobalizationMode { + /** + * Load sharded ICU data. + */ + Sharded = "sharded", + /** + * Load all ICU data. + */ + All = "all", + /** + * Operate in invariant globalization mode. + */ + Invariant = "invariant", + /** + * Use user defined icu file. + */ + Custom = "custom" +} + +export type DotnetModuleConfig = { + config?: LoaderConfig; + configSrc?: string; + onConfigLoaded?: (config: LoaderConfig) => void | Promise; + onDotnetReady?: () => void | Promise; + onDownloadResourceProgress?: (resourcesLoaded: number, totalResources: number) => void; + imports?: any; + exports?: string[]; +} & Partial; + +export type RunAPIType = { + /** + * Runs the Main() method of the application. + * Note: this will keep the .NET runtime alive and the APIs will be available for further calls. + * @param mainAssemblyName name of the assembly with the Main() method. Optional. Default is the same as the .csproj name. + * @param args command line arguments for the Main() method. Optional. + * @returns exit code of the Main() method. + */ + runMain: (mainAssemblyName?: string, args?: string[]) => Promise; + /** + * Runs the Main() method of the application and exits the runtime. + * Note: after the runtime exits, it would reject all further calls to the API. + * @param mainAssemblyName name of the assembly with the Main() method. Optional. Default is the same as the .csproj name. + * @param args command line arguments for the Main() method. Optional. + * @returns exit code of the Main() method. + */ + runMainAndExit: (mainAssemblyName?: string, args?: string[]) => Promise; + /** + * Exits the runtime. + * Note: after the runtime exits, it would reject all further calls to the API. + * @param code "process" exit code. + * @param reason could be a string or an Error object. + */ + exit: (code: number, reason?: any) => void; + /** + * Sets the environment variable for the "process" + * @param name + * @param value + */ + setEnvironmentVariable: (name: string, value: string) => void; + /** + * Returns the [JSExport] methods of the assembly with the given name + * @param assemblyName + */ + getAssemblyExports(assemblyName: string): Promise; + /** + * Provides functions which could be imported by the managed code using [JSImport] + * @param moduleName maps to the second parameter of [JSImport] + * @param moduleImports object with functions which could be imported by the managed code. The keys map to the first parameter of [JSImport] + */ + setModuleImports(moduleName: string, moduleImports: any): void; + /** + * Returns the configuration object used to start the runtime. + */ + getConfig: () => LoaderConfig; + /** + * Executes scripts which were loaded during runtime bootstrap. + * You can register the scripts using LoaderConfig.resources.modulesAfterConfigLoaded and LoaderConfig.resources.modulesAfterRuntimeReady. + */ + invokeLibraryInitializers: (functionName: string, args: any[]) => Promise; +}; + +export type MemoryAPIType = { + /** + * Writes to the WASM linear memory + */ + setHeapB32: (offset: NativePointer, value: number | boolean) => void; + /** + * Writes to the WASM linear memory + */ + setHeapB8: (offset: NativePointer, value: number | boolean) => void; + /** + * Writes to the WASM linear memory + */ + setHeapU8: (offset: NativePointer, value: number) => void; + /** + * Writes to the WASM linear memory + */ + setHeapU16: (offset: NativePointer, value: number) => void; + /** + * Writes to the WASM linear memory + */ + setHeapU32: (offset: NativePointer, value: NativePointer | number) => void; + /** + * Writes to the WASM linear memory + */ + setHeapI8: (offset: NativePointer, value: number) => void; + /** + * Writes to the WASM linear memory + */ + setHeapI16: (offset: NativePointer, value: number) => void; + /** + * Writes to the WASM linear memory + */ + setHeapI32: (offset: NativePointer, value: number) => void; + /** + * Writes to the WASM linear memory + */ + setHeapI52: (offset: NativePointer, value: number) => void; + /** + * Writes to the WASM linear memory + */ + setHeapU52: (offset: NativePointer, value: number) => void; + /** + * Writes to the WASM linear memory + */ + setHeapI64Big: (offset: NativePointer, value: bigint) => void; + /** + * Writes to the WASM linear memory + */ + setHeapF32: (offset: NativePointer, value: number) => void; + /** + * Writes to the WASM linear memory + */ + setHeapF64: (offset: NativePointer, value: number) => void; + /** + * Reads from the WASM linear memory + */ + getHeapB32: (offset: NativePointer) => boolean; + /** + * Reads from the WASM linear memory + */ + getHeapB8: (offset: NativePointer) => boolean; + /** + * Reads from the WASM linear memory + */ + getHeapU8: (offset: NativePointer) => number; + /** + * Reads from the WASM linear memory + */ + getHeapU16: (offset: NativePointer) => number; + /** + * Reads from the WASM linear memory + */ + getHeapU32: (offset: NativePointer) => number; + /** + * Reads from the WASM linear memory + */ + getHeapI8: (offset: NativePointer) => number; + /** + * Reads from the WASM linear memory + */ + getHeapI16: (offset: NativePointer) => number; + /** + * Reads from the WASM linear memory + */ + getHeapI32: (offset: NativePointer) => number; + /** + * Reads from the WASM linear memory + */ + getHeapI52: (offset: NativePointer) => number; + /** + * Reads from the WASM linear memory + */ + getHeapU52: (offset: NativePointer) => number; + /** + * Reads from the WASM linear memory + */ + getHeapI64Big: (offset: NativePointer) => bigint; + /** + * Reads from the WASM linear memory + */ + getHeapF32: (offset: NativePointer) => number; + /** + * Reads from the WASM linear memory + */ + getHeapF64: (offset: NativePointer) => number; + /** + * Returns a short term view of the WASM linear memory. Don't store the reference, don't use it after await. + */ + localHeapViewI8: () => Int8Array; + /** + * Returns a short term view of the WASM linear memory. Don't store the reference, don't use it after await. + */ + localHeapViewI16: () => Int16Array; + /** + * Returns a short term view of the WASM linear memory. Don't store the reference, don't use it after await. + */ + localHeapViewI32: () => Int32Array; + /** + * Returns a short term view of the WASM linear memory. Don't store the reference, don't use it after await. + */ + localHeapViewI64Big: () => BigInt64Array; + /** + * Returns a short term view of the WASM linear memory. Don't store the reference, don't use it after await. + */ + localHeapViewU8: () => Uint8Array; + /** + * Returns a short term view of the WASM linear memory. Don't store the reference, don't use it after await. + */ + localHeapViewU16: () => Uint16Array; + /** + * Returns a short term view of the WASM linear memory. Don't store the reference, don't use it after await. + */ + localHeapViewU32: () => Uint32Array; + /** + * Returns a short term view of the WASM linear memory. Don't store the reference, don't use it after await. + */ + localHeapViewF32: () => Float32Array; + /** + * Returns a short term view of the WASM linear memory. Don't store the reference, don't use it after await. + */ + localHeapViewF64: () => Float64Array; +}; + +export type DiagnosticsAPIType = { + /** + * creates diagnostic trace file. Default is 60 seconds. + * It could be opened in PerfView or Visual Studio as is. + */ + collectCpuSamples: (options?: DiagnosticCommandOptions) => Promise; + /** + * creates diagnostic trace file. Default is 60 seconds. + * It could be opened in PerfView or Visual Studio as is. + * It could be summarized by `dotnet-trace report xxx.nettrace topN -n 10` + */ + collectMetrics: (options?: DiagnosticCommandOptions) => Promise; + /** + * creates diagnostic trace file. + * It could be opened in PerfView as is. + * It could be converted for Visual Studio using `dotnet-gcdump convert`. + */ + collectGcDump: (options?: DiagnosticCommandOptions) => Promise; + /** + * changes DOTNET_DiagnosticPorts and makes a new connection to WebSocket on that URL. + */ + connectDSRouter(url: string): void; +}; + +export type DiagnosticCommandProviderV2 = { + keywords: [number, number]; + logLevel: number; + provider_name: string; + arguments: string | null; +}; + +export type DiagnosticCommandOptions = { + durationSeconds?: number; + intervalSeconds?: number; + skipDownload?: boolean; + circularBufferMB?: number; + extraProviders?: DiagnosticCommandProviderV2[]; +}; +export type APIType = RunAPIType & MemoryAPIType & DiagnosticsAPIType; +export type RuntimeAPI = { + INTERNAL: any; + Module: EmscriptenModule; + runtimeId: number; + runtimeBuildInfo: { + productVersion: string; + gitHash: string; + buildConfiguration: string; + wasmEnableThreads: boolean; + wasmEnableSIMD: boolean; + wasmEnableExceptionHandling: boolean; + }; +} & APIType; +export type ModuleAPI = { + /** + * The builder for the .NET runtime. + */ + dotnet: DotnetHostBuilder; + /** + * Terminates the runtime "process" and reject all further calls to the API. + */ + exit: (code: number, reason?: any) => void; +}; +export type CreateDotnetRuntimeType = (moduleFactory: DotnetModuleConfig | ((api: RuntimeAPI) => DotnetModuleConfig)) => Promise; +export type WebAssemblyBootResourceType = "assembly" | "pdb" | "dotnetjs" | "dotnetwasm" | "globalization" | "manifest" | "configuration"; + +export interface IDisposable { + dispose(): void; + get isDisposed(): boolean; +} +export interface IMemoryView extends IDisposable { + /** + * copies elements from provided source to the wasm memory. + * target has to have the elements of the same type as the underlying C# array. + * same as TypedArray.set() + */ + set(source: TypedArray, targetOffset?: number): void; + /** + * copies elements from wasm memory to provided target. + * target has to have the elements of the same type as the underlying C# array. + */ + copyTo(target: TypedArray, sourceOffset?: number): void; + /** + * same as TypedArray.slice() + */ + slice(start?: number, end?: number): TypedArray; + get length(): number; + get byteLength(): number; +} + +export declare function exit(exit_code: number, reason?: any): void; + +export declare const dotnet: DotnetHostBuilder; + +declare global { + function getDotnetRuntime(runtimeId: number): RuntimeAPI | undefined; +} +export declare const createDotnetRuntime: CreateDotnetRuntimeType; + + diff --git a/src/native/libs/Common/JavaScript/types/v8.d.ts b/src/native/libs/Common/JavaScript/types/v8.d.ts new file mode 100644 index 00000000000000..95093e37c3e974 --- /dev/null +++ b/src/native/libs/Common/JavaScript/types/v8.d.ts @@ -0,0 +1,5 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// read is a v8 debugger command +declare function read(name: string, mode?: string): any; diff --git a/src/native/libs/System.Native.Browser/CMakeLists.txt b/src/native/libs/System.Native.Browser/CMakeLists.txt new file mode 100644 index 00000000000000..ef53459c67af5a --- /dev/null +++ b/src/native/libs/System.Native.Browser/CMakeLists.txt @@ -0,0 +1,92 @@ +project(System.Native.Browser C) + +set(BROWSER_SOURCES) + +if (NOT GEN_PINVOKE) + set (BROWSER_SOURCES ${BROWSER_SOURCES} entrypoints.c) +endif() + +add_library(System.Native.Browser-Static + STATIC + ${BROWSER_SOURCES} +) +set_target_properties(System.Native.Browser-Static PROPERTIES OUTPUT_NAME System.Native.Browser CLEAN_DIRECT_OUTPUT 1) +install(TARGETS System.Native.Browser-Static DESTINATION ${STATIC_LIB_DESTINATION} COMPONENT libs) + +# WASM-TODO *.ts files instead +set(ROLLUP_TS_SOURCES + "${CMAKE_CURRENT_SOURCE_DIR}/../../corehost/browserhost/loader/dotnet.js" + "${CMAKE_CURRENT_SOURCE_DIR}/../../corehost/browserhost/loader/dotnet.d.ts" + "${CMAKE_CURRENT_SOURCE_DIR}/../../corehost/browserhost/libBrowserHost.js" + "${CMAKE_CURRENT_SOURCE_DIR}/libSystem.Native.Browser.js" + "${CMAKE_CURRENT_SOURCE_DIR}/libSystem.Native.Browser.extpost.js" + "${CMAKE_CURRENT_SOURCE_DIR}/../System.Runtime.InteropServices.JavaScript.Native/libSystem.Runtime.InteropServices.JavaScript.Native.js" + "${CMAKE_CURRENT_SOURCE_DIR}/../System.Runtime.InteropServices.JavaScript.Native/dotnet.runtime.js" + "${CMAKE_CURRENT_SOURCE_DIR}/./libSystem.Native.Browser.extpost.js" + "${CMAKE_CURRENT_SOURCE_DIR}/./libSystem.Native.Browser.js" + "${CMAKE_CURRENT_SOURCE_DIR}/../../package.json" + "${CMAKE_CURRENT_SOURCE_DIR}/../../tsconfig.json" +) + +# WASM-TODO *.js.map files +set(ROLLUP_OUTPUTS + "${CLR_ARTIFACTS_OBJ_DIR}/coreclr/browser.wasm.${CMAKE_BUILD_TYPE}/corehost/dotnet.js" + "${CLR_ARTIFACTS_OBJ_DIR}/coreclr/browser.wasm.${CMAKE_BUILD_TYPE}/corehost/dotnet.d.ts" + "${CLR_ARTIFACTS_OBJ_DIR}/coreclr/browser.wasm.${CMAKE_BUILD_TYPE}/corehost/libBrowserHost.js" + "${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Native.Browser/libSystem.Native.Browser.js" + "${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Native.Browser/dotnet.runtime.js" + "${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Runtime.InteropServices.JavaScript.Native/libSystem.Runtime.InteropServices.JavaScript.Native.js" +) + +set(ROLLUP_STAMP + "${CLR_ARTIFACTS_OBJ_DIR}/coreclr/browser.wasm.${CMAKE_BUILD_TYPE}/corehost/.rollup.stamp" +) + +if(NOT PRODUCT_VERSION_JS) + # WASM-TODO get dotnet ProductVersion from MSBuild + set(PRODUCT_VERSION_JS "10.0.0-dev") +endif() +if(NOT CI_BUILD_JS) + # WASM-TODO get ContinuousIntegrationBuild from MSBuild + set(CI_BUILD_JS "false") +endif() + +add_custom_command( + OUTPUT ${ROLLUP_STAMP} + BYPRODUCTS ${ROLLUP_OUTPUTS} + COMMAND npm run rollup:stub -- ${CMAKE_BUILD_TYPE} ${PRODUCT_VERSION_JS} ${CI_BUILD_JS} + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../.." + COMMENT "Running 'npm run rollup' to generate JavaScript bundles" + DEPENDS ${ROLLUP_TS_SOURCES} + VERBATIM +) + +# WASM-TODO fixme: make this incremental +add_custom_target(System.Native.Browser-Rollup + DEPENDS ${ROLLUP_STAMP} +) + +add_dependencies(System.Native.Browser-Static System.Native.Browser-Rollup) + +set(NPM_INSTALL_OUTPUTS + "${CMAKE_CURRENT_SOURCE_DIR}/../../node_modules/.package-lock.json" +) + +set(NPM_INSTALL_SOURCES + "${CMAKE_CURRENT_SOURCE_DIR}/../../package.json" +) + +add_dependencies(System.Native.Browser-Rollup System.Native.Browser-NpmInstall) + +add_custom_command( + OUTPUT ${NPM_INSTALL_OUTPUTS} + COMMAND npm ci + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../.." + COMMENT "Running 'npm ci' to install npm packages" + DEPENDS ${NPM_INSTALL_SOURCES} + VERBATIM +) + +add_custom_target(System.Native.Browser-NpmInstall + DEPENDS ${NPM_INSTALL_OUTPUTS} +) diff --git a/src/native/libs/System.Native.Browser/ReadMe.md b/src/native/libs/System.Native.Browser/ReadMe.md new file mode 100644 index 00000000000000..aa24964b1fa381 --- /dev/null +++ b/src/native/libs/System.Native.Browser/ReadMe.md @@ -0,0 +1,19 @@ +# System.Native.Browser + +This library implements PAL for the VM/runtime. + +It is a TypeScript project that is compiled via `src\native\rollup.config.js` into **Emscripten library**. +And a native library compiled by CMake into `libSystem.Native.Browser.a` as part of `/src/native/libs/CMakeLists.txt` + +## Emscripten library +- `native/index` compiled -> `libSystem.Native.Browser.js` linked ->`dotnet.native.js` +- `libSystem.Native.Browser.footer.js` compiled -> `libSystem.Native.Browser.js` linked ->`dotnet.native.js` +- `libSystem.Native.Browser.extpost.js` linked ->`dotnet.native.js` +- `ententrypoints.c` compiled -> `libSystem.Native.Browser.a` linked -> `dotnet.native.wasm` + +## Build +TypeScript is compiled by `src/native/rollup.config.js` +JavaScript tools like `npm`, `tsc`, `rollup` are installed in `src/native/package.json`. +JS tools depend on `nodeJS` installation of Emscripten. +Emscripten compilations is part of `/src/native/libs/CMakeLists.txt` +Final static linking happens in `/src/native/corehost/browserhost/CMakeLists.txt` diff --git a/src/native/libs/System.Native.Browser/entrypoints.c b/src/native/libs/System.Native.Browser/entrypoints.c new file mode 100644 index 00000000000000..de5c91cf87238b --- /dev/null +++ b/src/native/libs/System.Native.Browser/entrypoints.c @@ -0,0 +1,24 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include +#include + +#ifndef EXTERN_C +#define EXTERN_C extern +#endif//EXTERN_C + +// implemented in JavaScript +EXTERN_C int32_t SystemJS_RandomBytes(uint8_t* buffer, int32_t bufferLength); + +static const Entry s_browserNative[] = +{ + DllImportEntry(SystemJS_RandomBytes) +}; + +EXTERN_C const void* SystemJSResolveDllImport(const char* name); + +EXTERN_C const void* SystemJSResolveDllImport(const char* name) +{ + return minipal_resolve_dllimport(s_browserNative, ARRAY_SIZE(s_browserNative), name); +} diff --git a/src/native/libs/System.Native.Browser/libSystem.Native.Browser.extpost.js b/src/native/libs/System.Native.Browser/libSystem.Native.Browser.extpost.js new file mode 100644 index 00000000000000..81df9991c0d16d --- /dev/null +++ b/src/native/libs/System.Native.Browser/libSystem.Native.Browser.extpost.js @@ -0,0 +1,10 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +var fetch = fetch || undefined; var _nativeModuleLoaded = false; var dotnetInternals = null; +export function initialize(internals) { + if (_nativeModuleLoaded) throw new Error("Native module already loaded"); + dotnetInternals = internals; + _nativeModuleLoaded = true; + return createDotnetRuntime(dotnetInternals.runtimeApi.Module); +} diff --git a/src/native/libs/System.Native.Browser/libSystem.Native.Browser.js b/src/native/libs/System.Native.Browser/libSystem.Native.Browser.js new file mode 100644 index 00000000000000..42dae127fd3568 --- /dev/null +++ b/src/native/libs/System.Native.Browser/libSystem.Native.Browser.js @@ -0,0 +1,279 @@ +//! Licensed to the .NET Foundation under one or more agreements. +//! The .NET Foundation licenses this file to you under the MIT license. +//! This is generated file, see src/native/libs/Browser/rollup.config.defines.js + + +var libNativeBrowser = (function (exports) { + 'use strict'; + + // Licensed to the .NET Foundation under one or more agreements. + // The .NET Foundation licenses this file to you under the MIT license. + let Module; + let runtimeApi; + let Logger = {}; + let Assert = {}; + let JSEngine = {}; + let loaderExports = {}; + let runtimeExports = {}; + let hostExports = {}; + let interopExports = {}; + let nativeBrowserExports = {}; + let dotnetInternals; + function getInternals() { + return dotnetInternals; + } + function setInternals(internal) { + dotnetInternals = internal; + runtimeApi = dotnetInternals.runtimeApi; + Module = dotnetInternals.runtimeApi.Module; + } + function updateAllInternals() { + if (dotnetInternals.updates === undefined) { + dotnetInternals.updates = []; + } + for (const updateImpl of dotnetInternals.updates) { + updateImpl(); + } + } + function updateMyInternals() { + if (Object.keys(loaderExports).length === 0 && dotnetInternals.loaderExportsTable) { + loaderExports = {}; + Logger = {}; + Assert = {}; + JSEngine = {}; + expandLE(dotnetInternals.loaderExportsTable, Logger, Assert, JSEngine, loaderExports); + } + if (Object.keys(runtimeExports).length === 0 && dotnetInternals.runtimeExportsTable) { + runtimeExports = {}; + expandRE(dotnetInternals.runtimeExportsTable, runtimeExports); + } + if (Object.keys(hostExports).length === 0 && dotnetInternals.hostNativeExportsTable) { + hostExports = {}; + expandHE(dotnetInternals.hostNativeExportsTable, hostExports); + } + if (Object.keys(interopExports).length === 0 && dotnetInternals.interopJavaScriptNativeExportsTable) { + interopExports = {}; + expandJSNE(dotnetInternals.interopJavaScriptNativeExportsTable, interopExports); + } + if (Object.keys(nativeBrowserExports).length === 0 && dotnetInternals.nativeBrowserExportsTable) { + nativeBrowserExports = {}; + expandNBE(dotnetInternals.nativeBrowserExportsTable, nativeBrowserExports); + } + } + /** + * Functions below allow our JS modules to exchange internal interfaces by passing tables of functions in known order instead of using string symbols. + * IMPORTANT: If you need to add more functions, make sure that you add them at the end of the table, so that the order of existing functions does not change. + */ + function tabulateLE(logger, assert, loaderExports) { + return [ + logger.info, + logger.warn, + logger.error, + assert.check, + loaderExports.ENVIRONMENT_IS_NODE, + loaderExports.ENVIRONMENT_IS_SHELL, + loaderExports.ENVIRONMENT_IS_WEB, + loaderExports.ENVIRONMENT_IS_WORKER, + loaderExports.ENVIRONMENT_IS_SIDECAR, + loaderExports.browserHostResolveMain, + loaderExports.browserHostRejectMain, + loaderExports.getRunMainPromise, + ]; + } + function expandLE(table, logger, assert, jsEngine, loaderExports) { + const loggerLocal = { + info: table[0], + warn: table[1], + error: table[2], + }; + const assertLocal = { + check: table[3], + }; + const loaderExportsLocal = { + ENVIRONMENT_IS_NODE: table[4], + ENVIRONMENT_IS_SHELL: table[5], + ENVIRONMENT_IS_WEB: table[6], + ENVIRONMENT_IS_WORKER: table[7], + ENVIRONMENT_IS_SIDECAR: table[8], + browserHostResolveMain: table[9], + browserHostRejectMain: table[10], + getRunMainPromise: table[11], + }; + const jsEngineLocal = { + IS_NODE: loaderExportsLocal.ENVIRONMENT_IS_NODE(), + IS_SHELL: loaderExportsLocal.ENVIRONMENT_IS_SHELL(), + IS_WEB: loaderExportsLocal.ENVIRONMENT_IS_WEB(), + IS_WORKER: loaderExportsLocal.ENVIRONMENT_IS_WORKER(), + IS_SIDECAR: loaderExportsLocal.ENVIRONMENT_IS_SIDECAR(), + }; + Object.assign(loaderExports, loaderExportsLocal); + Object.assign(logger, loggerLocal); + Object.assign(assert, assertLocal); + Object.assign(jsEngine, jsEngineLocal); + } + // eslint-disable-next-line @typescript-eslint/no-unused-vars + function tabulateRE(map) { + return []; + } + function expandRE(table, runtime) { + Object.assign(runtime, {}); + } + function tabulateHE(map) { + return [ + map.registerDllBytes, + map.isSharedArrayBuffer, + ]; + } + function expandHE(table, native) { + const nativeLocal = { + registerDllBytes: table[0], + isSharedArrayBuffer: table[1], + }; + Object.assign(native, nativeLocal); + } + // eslint-disable-next-line @typescript-eslint/no-unused-vars + function tabulateJSNE(map) { + return []; + } + function expandJSNE(table, interop) { + const interopLocal = {}; + Object.assign(interop, interopLocal); + } + // eslint-disable-next-line @typescript-eslint/no-unused-vars + function tabulateNBE(map) { + return []; + } + function expandNBE(table, interop) { + const interopLocal = {}; + Object.assign(interop, interopLocal); + } + + // Licensed to the .NET Foundation under one or more agreements. + // The .NET Foundation licenses this file to you under the MIT license. + + var crossModule = /*#__PURE__*/Object.freeze({ + __proto__: null, + get Assert() { return Assert; }, + get JSEngine() { return JSEngine; }, + get Logger() { return Logger; }, + get Module() { return Module; }, + get dotnetInternals() { return dotnetInternals; }, + expandHE: expandHE, + expandJSNE: expandJSNE, + expandLE: expandLE, + expandNBE: expandNBE, + expandRE: expandRE, + getInternals: getInternals, + get hostExports() { return hostExports; }, + get interopExports() { return interopExports; }, + get loaderExports() { return loaderExports; }, + get nativeBrowserExports() { return nativeBrowserExports; }, + get runtimeApi() { return runtimeApi; }, + get runtimeExports() { return runtimeExports; }, + setInternals: setInternals, + tabulateHE: tabulateHE, + tabulateJSNE: tabulateJSNE, + tabulateLE: tabulateLE, + tabulateNBE: tabulateNBE, + tabulateRE: tabulateRE, + updateAllInternals: updateAllInternals, + updateMyInternals: updateMyInternals + }); + + // Licensed to the .NET Foundation under one or more agreements. + // The .NET Foundation licenses this file to you under the MIT license. + function SystemJS_RandomBytes(bufferPtr, bufferLength) { + // batchedQuotaMax is the max number of bytes as specified by the api spec. + // If the byteLength of array is greater than 65536, throw a QuotaExceededError and terminate the algorithm. + // https://www.w3.org/TR/WebCryptoAPI/#Crypto-method-getRandomValues + const batchedQuotaMax = 65536; + if (!globalThis.crypto || !globalThis.crypto.getRandomValues) { + if (!globalThis["cryptoWarnOnce"]) { + Logger.warn("This engine doesn't support crypto.getRandomValues. Please use a modern version or provide polyfill for 'globalThis.crypto.getRandomValues'."); + globalThis["cryptoWarnOnce"] = true; + } + return -1; + } + const memoryView = runtimeApi.localHeapViewU8(); + const targetView = memoryView.subarray(bufferPtr, bufferPtr + bufferLength); + // When threading is enabled, Chrome doesn't want SharedArrayBuffer to be passed to crypto APIs + const needsCopy = hostExports.isSharedArrayBuffer(memoryView.buffer); + const targetBuffer = needsCopy + ? new Uint8Array(bufferLength) + : targetView; + // fill the targetBuffer in batches of batchedQuotaMax + for (let i = 0; i < bufferLength; i += batchedQuotaMax) { + const targetBatch = targetBuffer.subarray(i, i + Math.min(bufferLength - i, batchedQuotaMax)); + globalThis.crypto.getRandomValues(targetBatch); + } + if (needsCopy) { + targetView.set(targetBuffer); + } + return 0; + } + + // Licensed to the .NET Foundation under one or more agreements. + // The .NET Foundation licenses this file to you under the MIT license. + function initialize(internals) { + const nativeBrowserExportsLocal = {}; + setInternals(internals); + internals.nativeBrowserExportsTable = [...tabulateNBE(nativeBrowserExportsLocal)]; + internals.updates.push(updateMyInternals); + updateAllInternals(); + } + + exports.SystemJS_RandomBytes = SystemJS_RandomBytes; + exports.cross = crossModule; + exports.initialize = initialize; + + return exports; + +}); +//! Licensed to the .NET Foundation under one or more agreements. +//! The .NET Foundation licenses this file to you under the MIT license. + +/** + * This is root of **Emscripten library** that would become part of `dotnet.native.js` + * It implements PAL for the VM/runtime. + */ + +(function (exports) { + function libFactory() { + const lib = { + $DOTNET: { + selfInitialize: () => { + if (typeof dotnetInternals !== "undefined") { + DOTNET.dotnetInternals = dotnetInternals; + DOTNET.initialize(dotnetInternals); + } + }, + }, + "$DOTNET__postset": "DOTNET.selfInitialize();", + }; + + // this executes the function at compile time in order to capture exports + const exports = libNativeBrowser({}); + let commonDeps = []; + for (const exportName of Reflect.ownKeys(exports.cross)) { + const name = String(exportName); + if (name === "dotnetInternals") continue; + if (name === "Module") continue; + const emName = "$" + name; + lib[emName] = exports.cross[exportName]; + commonDeps.push(emName); + } + for (const exportName of Reflect.ownKeys(exports)) { + const name = String(exportName); + if (name === "cross") continue; + if (name === "initialize") continue; + lib[name] = exports[name]; + } + lib["$DOTNET__deps"] = commonDeps; + lib.$DOTNET.initialize = exports.initialize; + + autoAddDeps(lib, "$DOTNET"); + addToLibrary(lib); + } + libFactory(); + return exports; +})({}); diff --git a/src/native/libs/System.Runtime.InteropServices.JavaScript.Native/CMakeLists.txt b/src/native/libs/System.Runtime.InteropServices.JavaScript.Native/CMakeLists.txt new file mode 100644 index 00000000000000..4af087e8dd2b10 --- /dev/null +++ b/src/native/libs/System.Runtime.InteropServices.JavaScript.Native/CMakeLists.txt @@ -0,0 +1,14 @@ +project(System.Runtime.InteropServices.JavaScript.Native C) + +set(BROWSER_INTEROP_SOURCES) + +if (NOT GEN_PINVOKE) + set (BROWSER_INTEROP_SOURCES ${BROWSER_INTEROP_SOURCES} entrypoints.c) +endif() + +add_library(System.Runtime.InteropServices.JavaScript.Native-Static + STATIC + ${BROWSER_INTEROP_SOURCES} +) +set_target_properties(System.Runtime.InteropServices.JavaScript.Native-Static PROPERTIES OUTPUT_NAME System.Runtime.InteropServices.JavaScript.Native CLEAN_DIRECT_OUTPUT 1) +install(TARGETS System.Runtime.InteropServices.JavaScript.Native-Static DESTINATION ${STATIC_LIB_DESTINATION} COMPONENT libs) diff --git a/src/native/libs/System.Runtime.InteropServices.JavaScript.Native/ReadMe.md b/src/native/libs/System.Runtime.InteropServices.JavaScript.Native/ReadMe.md new file mode 100644 index 00000000000000..13db2c03f231d8 --- /dev/null +++ b/src/native/libs/System.Runtime.InteropServices.JavaScript.Native/ReadMe.md @@ -0,0 +1,19 @@ +# System.Runtime.InteropServices.JavaScript.Native + +This library implements interop between JS and .NET +This library also implements public JS API related JS interop. + +## Native interop helpers +- `native/index` compiled -> `libSystem.Runtime.InteropServices.JavaScript.Native.js` linked ->`dotnet.native.js` +- `libSystem.Runtime.InteropServices.JavaScript.Native.footer.js` compiled -> `libSystem.Runtime.InteropServices.JavaScript.Native.js` linked ->`dotnet.native.js` +- `ententrypoints.c` compiled -> `libSystem.Runtime.InteropServices.JavaScript.Native.a` linked -> `dotnet.native.wasm` + +## JavaScript interop helpers +- `dotnet.runtime.ts` compiled -> `dotnet.runtime.js` + +## Build +TypeScript is compiled by `src/native/rollup.config.js` +JavaScript tools like `npm`, `tsc`, `rollup` are installed in `src/native/package.json`. +JS tools depend on `nodeJS` installation of Emscripten. +Emscripten compilations is part of `/src/native/libs/CMakeLists.txt` +Final static linking happens in `/src/native/corehost/browserhost/CMakeLists.txt` diff --git a/src/native/libs/System.Runtime.InteropServices.JavaScript.Native/dotnet.runtime.js b/src/native/libs/System.Runtime.InteropServices.JavaScript.Native/dotnet.runtime.js new file mode 100644 index 00000000000000..eb2e761bf9984b --- /dev/null +++ b/src/native/libs/System.Runtime.InteropServices.JavaScript.Native/dotnet.runtime.js @@ -0,0 +1,177 @@ +//! Licensed to the .NET Foundation under one or more agreements. +//! The .NET Foundation licenses this file to you under the MIT license. +//! This is generated file, see src/native/libs/Browser/rollup.config.defines.js + + +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +let Module; +let runtimeApi; +let Logger = {}; +let Assert = {}; +let JSEngine = {}; +let loaderExports = {}; +let runtimeExports = {}; +let hostExports = {}; +let interopExports = {}; +let nativeBrowserExports = {}; +let dotnetInternals; +function getInternals() { + return dotnetInternals; +} +function setInternals(internal) { + dotnetInternals = internal; + runtimeApi = dotnetInternals.runtimeApi; + Module = dotnetInternals.runtimeApi.Module; +} +function updateAllInternals() { + if (dotnetInternals.updates === undefined) { + dotnetInternals.updates = []; + } + for (const updateImpl of dotnetInternals.updates) { + updateImpl(); + } +} +function updateMyInternals() { + if (Object.keys(loaderExports).length === 0 && dotnetInternals.loaderExportsTable) { + loaderExports = {}; + Logger = {}; + Assert = {}; + JSEngine = {}; + expandLE(dotnetInternals.loaderExportsTable, Logger, Assert, JSEngine, loaderExports); + } + if (Object.keys(runtimeExports).length === 0 && dotnetInternals.runtimeExportsTable) { + runtimeExports = {}; + expandRE(dotnetInternals.runtimeExportsTable, runtimeExports); + } + if (Object.keys(hostExports).length === 0 && dotnetInternals.hostNativeExportsTable) { + hostExports = {}; + expandHE(dotnetInternals.hostNativeExportsTable, hostExports); + } + if (Object.keys(interopExports).length === 0 && dotnetInternals.interopJavaScriptNativeExportsTable) { + interopExports = {}; + expandJSNE(dotnetInternals.interopJavaScriptNativeExportsTable, interopExports); + } + if (Object.keys(nativeBrowserExports).length === 0 && dotnetInternals.nativeBrowserExportsTable) { + nativeBrowserExports = {}; + expandNBE(dotnetInternals.nativeBrowserExportsTable, nativeBrowserExports); + } +} +/** + * Functions below allow our JS modules to exchange internal interfaces by passing tables of functions in known order instead of using string symbols. + * IMPORTANT: If you need to add more functions, make sure that you add them at the end of the table, so that the order of existing functions does not change. + */ +function tabulateLE(logger, assert, loaderExports) { + return [ + logger.info, + logger.warn, + logger.error, + assert.check, + loaderExports.ENVIRONMENT_IS_NODE, + loaderExports.ENVIRONMENT_IS_SHELL, + loaderExports.ENVIRONMENT_IS_WEB, + loaderExports.ENVIRONMENT_IS_WORKER, + loaderExports.ENVIRONMENT_IS_SIDECAR, + loaderExports.browserHostResolveMain, + loaderExports.browserHostRejectMain, + loaderExports.getRunMainPromise, + ]; +} +function expandLE(table, logger, assert, jsEngine, loaderExports) { + const loggerLocal = { + info: table[0], + warn: table[1], + error: table[2], + }; + const assertLocal = { + check: table[3], + }; + const loaderExportsLocal = { + ENVIRONMENT_IS_NODE: table[4], + ENVIRONMENT_IS_SHELL: table[5], + ENVIRONMENT_IS_WEB: table[6], + ENVIRONMENT_IS_WORKER: table[7], + ENVIRONMENT_IS_SIDECAR: table[8], + browserHostResolveMain: table[9], + browserHostRejectMain: table[10], + getRunMainPromise: table[11], + }; + const jsEngineLocal = { + IS_NODE: loaderExportsLocal.ENVIRONMENT_IS_NODE(), + IS_SHELL: loaderExportsLocal.ENVIRONMENT_IS_SHELL(), + IS_WEB: loaderExportsLocal.ENVIRONMENT_IS_WEB(), + IS_WORKER: loaderExportsLocal.ENVIRONMENT_IS_WORKER(), + IS_SIDECAR: loaderExportsLocal.ENVIRONMENT_IS_SIDECAR(), + }; + Object.assign(loaderExports, loaderExportsLocal); + Object.assign(logger, loggerLocal); + Object.assign(assert, assertLocal); + Object.assign(jsEngine, jsEngineLocal); +} +// eslint-disable-next-line @typescript-eslint/no-unused-vars +function tabulateRE(map) { + return []; +} +function expandRE(table, runtime) { + Object.assign(runtime, {}); +} +function tabulateHE(map) { + return [ + map.registerDllBytes, + map.isSharedArrayBuffer, + ]; +} +function expandHE(table, native) { + const nativeLocal = { + registerDllBytes: table[0], + isSharedArrayBuffer: table[1], + }; + Object.assign(native, nativeLocal); +} +// eslint-disable-next-line @typescript-eslint/no-unused-vars +function tabulateJSNE(map) { + return []; +} +function expandJSNE(table, interop) { + const interopLocal = {}; + Object.assign(interop, interopLocal); +} +// eslint-disable-next-line @typescript-eslint/no-unused-vars +function tabulateNBE(map) { + return []; +} +function expandNBE(table, interop) { + const interopLocal = {}; + Object.assign(interop, interopLocal); +} + +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +function initialize(internals) { + const runtimeApiLocal = { + getAssemblyExports, + setModuleImports, + }; + const runtimeExportsLocal = {}; + setInternals(internals); + Object.assign(internals.runtimeApi, runtimeApiLocal); + internals.runtimeExportsTable = [...tabulateRE(runtimeExportsLocal)]; + internals.updates.push(updateMyInternals); + updateAllInternals(); +} +// eslint-disable-next-line @typescript-eslint/no-unused-vars +async function getAssemblyExports(assemblyName) { + throw new Error("Not implemented"); +} +// eslint-disable-next-line @typescript-eslint/no-unused-vars +function setModuleImports(moduleName, moduleImports) { + throw new Error("Not implemented"); +} + +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +export { initialize }; diff --git a/src/native/libs/System.Runtime.InteropServices.JavaScript.Native/entrypoints.c b/src/native/libs/System.Runtime.InteropServices.JavaScript.Native/entrypoints.c new file mode 100644 index 00000000000000..a8016806dc103c --- /dev/null +++ b/src/native/libs/System.Runtime.InteropServices.JavaScript.Native/entrypoints.c @@ -0,0 +1,24 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include +#include + +#ifndef EXTERN_C +#define EXTERN_C extern +#endif//EXTERN_C + +// implemented in JavaScript +EXTERN_C int32_t SystemInteropJS_InvokeJSImportST(uint8_t* buffer, int32_t bufferLength); + +static const Entry s_browserNative[] = +{ + DllImportEntry(SystemInteropJS_InvokeJSImportST) +}; + +EXTERN_C const void* SystemJSInteropResolveDllImport(const char* name); + +EXTERN_C const void* SystemJSInteropResolveDllImport(const char* name) +{ + return minipal_resolve_dllimport(s_browserNative, ARRAY_SIZE(s_browserNative), name); +} diff --git a/src/native/libs/System.Runtime.InteropServices.JavaScript.Native/libSystem.Runtime.InteropServices.JavaScript.Native.js b/src/native/libs/System.Runtime.InteropServices.JavaScript.Native/libSystem.Runtime.InteropServices.JavaScript.Native.js new file mode 100644 index 00000000000000..84efa97500a1ec --- /dev/null +++ b/src/native/libs/System.Runtime.InteropServices.JavaScript.Native/libSystem.Runtime.InteropServices.JavaScript.Native.js @@ -0,0 +1,253 @@ +//! Licensed to the .NET Foundation under one or more agreements. +//! The .NET Foundation licenses this file to you under the MIT license. +//! This is generated file, see src/native/libs/Browser/rollup.config.defines.js + + +var libInteropJavaScriptNative = (function (exports) { + 'use strict'; + + // Licensed to the .NET Foundation under one or more agreements. + // The .NET Foundation licenses this file to you under the MIT license. + let Module; + let runtimeApi; + let Logger = {}; + let Assert = {}; + let JSEngine = {}; + let loaderExports = {}; + let runtimeExports = {}; + let hostExports = {}; + let interopExports = {}; + let nativeBrowserExports = {}; + let dotnetInternals; + function getInternals() { + return dotnetInternals; + } + function setInternals(internal) { + dotnetInternals = internal; + runtimeApi = dotnetInternals.runtimeApi; + Module = dotnetInternals.runtimeApi.Module; + } + function updateAllInternals() { + if (dotnetInternals.updates === undefined) { + dotnetInternals.updates = []; + } + for (const updateImpl of dotnetInternals.updates) { + updateImpl(); + } + } + function updateMyInternals() { + if (Object.keys(loaderExports).length === 0 && dotnetInternals.loaderExportsTable) { + loaderExports = {}; + Logger = {}; + Assert = {}; + JSEngine = {}; + expandLE(dotnetInternals.loaderExportsTable, Logger, Assert, JSEngine, loaderExports); + } + if (Object.keys(runtimeExports).length === 0 && dotnetInternals.runtimeExportsTable) { + runtimeExports = {}; + expandRE(dotnetInternals.runtimeExportsTable, runtimeExports); + } + if (Object.keys(hostExports).length === 0 && dotnetInternals.hostNativeExportsTable) { + hostExports = {}; + expandHE(dotnetInternals.hostNativeExportsTable, hostExports); + } + if (Object.keys(interopExports).length === 0 && dotnetInternals.interopJavaScriptNativeExportsTable) { + interopExports = {}; + expandJSNE(dotnetInternals.interopJavaScriptNativeExportsTable, interopExports); + } + if (Object.keys(nativeBrowserExports).length === 0 && dotnetInternals.nativeBrowserExportsTable) { + nativeBrowserExports = {}; + expandNBE(dotnetInternals.nativeBrowserExportsTable, nativeBrowserExports); + } + } + /** + * Functions below allow our JS modules to exchange internal interfaces by passing tables of functions in known order instead of using string symbols. + * IMPORTANT: If you need to add more functions, make sure that you add them at the end of the table, so that the order of existing functions does not change. + */ + function tabulateLE(logger, assert, loaderExports) { + return [ + logger.info, + logger.warn, + logger.error, + assert.check, + loaderExports.ENVIRONMENT_IS_NODE, + loaderExports.ENVIRONMENT_IS_SHELL, + loaderExports.ENVIRONMENT_IS_WEB, + loaderExports.ENVIRONMENT_IS_WORKER, + loaderExports.ENVIRONMENT_IS_SIDECAR, + loaderExports.browserHostResolveMain, + loaderExports.browserHostRejectMain, + loaderExports.getRunMainPromise, + ]; + } + function expandLE(table, logger, assert, jsEngine, loaderExports) { + const loggerLocal = { + info: table[0], + warn: table[1], + error: table[2], + }; + const assertLocal = { + check: table[3], + }; + const loaderExportsLocal = { + ENVIRONMENT_IS_NODE: table[4], + ENVIRONMENT_IS_SHELL: table[5], + ENVIRONMENT_IS_WEB: table[6], + ENVIRONMENT_IS_WORKER: table[7], + ENVIRONMENT_IS_SIDECAR: table[8], + browserHostResolveMain: table[9], + browserHostRejectMain: table[10], + getRunMainPromise: table[11], + }; + const jsEngineLocal = { + IS_NODE: loaderExportsLocal.ENVIRONMENT_IS_NODE(), + IS_SHELL: loaderExportsLocal.ENVIRONMENT_IS_SHELL(), + IS_WEB: loaderExportsLocal.ENVIRONMENT_IS_WEB(), + IS_WORKER: loaderExportsLocal.ENVIRONMENT_IS_WORKER(), + IS_SIDECAR: loaderExportsLocal.ENVIRONMENT_IS_SIDECAR(), + }; + Object.assign(loaderExports, loaderExportsLocal); + Object.assign(logger, loggerLocal); + Object.assign(assert, assertLocal); + Object.assign(jsEngine, jsEngineLocal); + } + // eslint-disable-next-line @typescript-eslint/no-unused-vars + function tabulateRE(map) { + return []; + } + function expandRE(table, runtime) { + Object.assign(runtime, {}); + } + function tabulateHE(map) { + return [ + map.registerDllBytes, + map.isSharedArrayBuffer, + ]; + } + function expandHE(table, native) { + const nativeLocal = { + registerDllBytes: table[0], + isSharedArrayBuffer: table[1], + }; + Object.assign(native, nativeLocal); + } + // eslint-disable-next-line @typescript-eslint/no-unused-vars + function tabulateJSNE(map) { + return []; + } + function expandJSNE(table, interop) { + const interopLocal = {}; + Object.assign(interop, interopLocal); + } + // eslint-disable-next-line @typescript-eslint/no-unused-vars + function tabulateNBE(map) { + return []; + } + function expandNBE(table, interop) { + const interopLocal = {}; + Object.assign(interop, interopLocal); + } + + // Licensed to the .NET Foundation under one or more agreements. + // The .NET Foundation licenses this file to you under the MIT license. + + var crossModule = /*#__PURE__*/Object.freeze({ + __proto__: null, + get Assert() { return Assert; }, + get JSEngine() { return JSEngine; }, + get Logger() { return Logger; }, + get Module() { return Module; }, + get dotnetInternals() { return dotnetInternals; }, + expandHE: expandHE, + expandJSNE: expandJSNE, + expandLE: expandLE, + expandNBE: expandNBE, + expandRE: expandRE, + getInternals: getInternals, + get hostExports() { return hostExports; }, + get interopExports() { return interopExports; }, + get loaderExports() { return loaderExports; }, + get nativeBrowserExports() { return nativeBrowserExports; }, + get runtimeApi() { return runtimeApi; }, + get runtimeExports() { return runtimeExports; }, + setInternals: setInternals, + tabulateHE: tabulateHE, + tabulateJSNE: tabulateJSNE, + tabulateLE: tabulateLE, + tabulateNBE: tabulateNBE, + tabulateRE: tabulateRE, + updateAllInternals: updateAllInternals, + updateMyInternals: updateMyInternals + }); + + // Licensed to the .NET Foundation under one or more agreements. + // The .NET Foundation licenses this file to you under the MIT license. + // eslint-disable-next-line @typescript-eslint/no-unused-vars + function SystemInteropJS_InvokeJSImportST(function_handle, args) { + // WASMTODO implementation + Logger.error("SystemInteropJS_InvokeJSImportST called"); + return -1; + } + function initialize(internals) { + const interopJavaScriptNativeExportsLocal = {}; + setInternals(internals); + internals.interopJavaScriptNativeExportsTable = [...tabulateJSNE(interopJavaScriptNativeExportsLocal)]; + internals.updates.push(updateMyInternals); + updateAllInternals(); + } + + exports.SystemInteropJS_InvokeJSImportST = SystemInteropJS_InvokeJSImportST; + exports.cross = crossModule; + exports.initialize = initialize; + + return exports; + +}); +//! Licensed to the .NET Foundation under one or more agreements. +//! The .NET Foundation licenses this file to you under the MIT license. + +/** + * This is root of **Emscripten library** that would become part of `dotnet.native.js` + * It implements interop between JS and .NET + */ + +(function (exports) { + function libFactory() { + const lib = { + $DOTNET_INTEROP: { + selfInitialize: () => { + if (typeof dotnetInternals !== "undefined") { + DOTNET_INTEROP.dotnetInternals = dotnetInternals; + DOTNET_INTEROP.initialize(dotnetInternals); + } + }, + }, + "$DOTNET_INTEROP__postset": "DOTNET_INTEROP.selfInitialize();", + }; + + // this executes the function at compile time in order to capture exports + const exports = libInteropJavaScriptNative({}); + let commonDeps = ["$DOTNET"]; + for (const exportName of Reflect.ownKeys(exports.cross)) { + const name = String(exportName); + if (name === "dotnetInternals") continue; + if (name === "Module") continue; + const emName = "$" + name; + commonDeps.push(emName); + } + for (const exportName of Reflect.ownKeys(exports)) { + const name = String(exportName); + if (name === "cross") continue; + if (name === "initialize") continue; + lib[name] = exports[name]; + } + + lib["$DOTNET_INTEROP__deps"] = commonDeps; + lib.$DOTNET_INTEROP.initialize = exports.initialize; + + autoAddDeps(lib, "$DOTNET_INTEROP"); + addToLibrary(lib); + } + libFactory(); + return exports; +})({}); diff --git a/src/native/package-lock.json b/src/native/package-lock.json new file mode 100644 index 00000000000000..675f79827e3614 --- /dev/null +++ b/src/native/package-lock.json @@ -0,0 +1,3035 @@ +{ + "name": "@microsoft/dotnet-runtime", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@microsoft/dotnet-runtime", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "wasm-feature-detect": "1.6.1" + }, + "devDependencies": { + "@rollup/plugin-node-resolve": "15.2.3", + "@rollup/plugin-terser": "0.4.4", + "@rollup/plugin-typescript": "11.1.6", + "@rollup/plugin-virtual": "3.0.2", + "@types/node": "^24.5.2", + "@typescript-eslint/eslint-plugin": "5.59.1", + "@typescript-eslint/parser": "5.59.1", + "eslint": "8.44.0", + "fast-glob": "3.3.2", + "git-commit-info": "2.0.2", + "magic-string": "0.30.10", + "rollup": "4.34.9", + "rollup-plugin-dts": "6.1.1", + "terser": "5.31.1", + "tslib": "2.6.3", + "typescript": "5.4.5" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.24.7", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@babel/code-frame/-/code-frame-7.24.7.tgz", + "integrity": "sha1-iC/Z4J6O4yTklr0EBAHG8EbvRGU=", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@babel/highlight": "^7.24.7", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.24.7", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", + "integrity": "sha1-dbiJz6+eNcKq9Czw1yyOkXGSUds=", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.24.7", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@babel/highlight/-/highlight-7.24.7.tgz", + "integrity": "sha1-oFqx3xNLKGVYquDtQebF9zG/QJ0=", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.24.7", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha1-QfuyAkPlCxK+DwS43tvwdSDOhB0=", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha1-zUJUFnelQzPPVBpJEIwUMrRMlCQ=", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha1-u3GFBpDh8TZWfeYp0tVHHe2kweg=", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha1-4uaaRKyHcveKHsCzW2id9lMO/I8=", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha1-ojUU6Pua8SadX3eIqlVnmNYca1k=", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.10.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@eslint-community/regexpp/-/regexpp-4.10.1.tgz", + "integrity": "sha1-NhRh5cs4Rdh05hcxwRz+3WZNg6A=", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha1-OIomnw8lwbatwxe1osVXFIlMcK0=", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/globals/-/globals-13.24.0.tgz", + "integrity": "sha1-hDKhnXjODB6DOUnDats0VAC7EXE=", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "8.44.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@eslint/js/-/js-8.44.0.tgz", + "integrity": "sha1-lhpZA8dBOTkEeL3ICLzeP8Rat68=", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.14", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha1-145IGgOfdWbsyWYLTqf+ax/sRCs=", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha1-r1smkaIrRL6EewyoFkHF+2rQFyw=", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha1-Siho111taWPkI7z5C3/RvjQ0CdM=", + "dev": true, + "license": "BSD-3-Clause" + }, + "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=", + "dev": true, + "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=", + "dev": true, + "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=", + "dev": true, + "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=", + "dev": true, + "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=", + "dev": true, + "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=", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha1-dhnC6yGyVIP20WdUi0z9WnSIw9U=", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha1-W9Jir5Tp0lvR5xsF3u1Eh2oiLos=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha1-6Vc36LtnRt3t9pxVaVNJTxlv5po=", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@rollup/plugin-node-resolve": { + "version": "15.2.3", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.2.3.tgz", + "integrity": "sha1-5eCwWb2FyldIlJLylc6IwtSw2vk=", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "@types/resolve": "1.20.2", + "deepmerge": "^4.2.2", + "is-builtin-module": "^3.2.1", + "is-module": "^1.0.0", + "resolve": "^1.22.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.78.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-terser": { + "version": "0.4.4", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@rollup/plugin-terser/-/plugin-terser-0.4.4.tgz", + "integrity": "sha1-Fd/9s/c/Ehqk+7N+fKa+mu6pGWI=", + "dev": true, + "license": "MIT", + "dependencies": { + "serialize-javascript": "^6.0.1", + "smob": "^1.0.0", + "terser": "^5.17.4" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-typescript": { + "version": "11.1.6", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@rollup/plugin-typescript/-/plugin-typescript-11.1.6.tgz", + "integrity": "sha1-ckI31ewSYJ7AFCn2GdKj59TRsis=", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.1.0", + "resolve": "^1.22.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.14.0||^3.0.0||^4.0.0", + "tslib": "*", + "typescript": ">=3.7.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + }, + "tslib": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-virtual": { + "version": "3.0.2", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@rollup/plugin-virtual/-/plugin-virtual-3.0.2.tgz", + "integrity": "sha1-F+F+7stMn6HApucsnl9mOC/du4I=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/pluginutils": { + "version": "5.1.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@rollup/pluginutils/-/pluginutils-5.1.0.tgz", + "integrity": "sha1-flPt3Ix/SDpK0LlK+x9/X9PHceA=", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.34.9", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.9.tgz", + "integrity": "sha1-ZhpFpHCccOWeWW7HjaqcuLjSdgQ=", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.34.9", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.34.9.tgz", + "integrity": "sha1-Eo/o3VENiAz5i0y2x63TJoFaDEs=", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.34.9", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.9.tgz", + "integrity": "sha1-NjRnvEn9Cx4XB1eYrI6a0eHilTU=", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.34.9", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.9.tgz", + "integrity": "sha1-wv49hf/+R/DtDwdrNWOtoiyK8Zw=", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.34.9", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.34.9.tgz", + "integrity": "sha1-2VvY9uqvgpeBFE/IvS1dcdn2qfU=", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.34.9", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.34.9.tgz", + "integrity": "sha1-w1dsYBFlbklm3tKfBR7exja0RWQ=", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.34.9", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.34.9.tgz", + "integrity": "sha1-SMh9De5PjclZGkFnF/kbSonXfj0=", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.34.9", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.34.9.tgz", + "integrity": "sha1-9MTnwDp3Z/Llqp0MXPv1wPWfLUE=", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.34.9", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.9.tgz", + "integrity": "sha1-EBXJ0HqZAFAl0TuGIrdgACnQtS8=", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.34.9", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.9.tgz", + "integrity": "sha1-j4letVd3SPx1ryG+rjJDlibgoUw=", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.34.9", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.34.9.tgz", + "integrity": "sha1-yc1du9xrPKTb7rAzdJjPMZSQBKA=", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.34.9", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.34.9.tgz", + "integrity": "sha1-frtbREH6oXhDohD30Fg6IMk7QOQ=", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.34.9", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.34.9.tgz", + "integrity": "sha1-EPXXNJ+9L+ePnjbsyQqrMVRDXI0=", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.34.9", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.34.9.tgz", + "integrity": "sha1-GWNH0vogWTqwnQt+JYn7ab33QsY=", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.34.9", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.9.tgz", + "integrity": "sha1-cZPL2NEoISuKzaN+AbOdnpYlnvg=", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.34.9", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.9.tgz", + "integrity": "sha1-KaaGcnjKBCC4kVdM+rmOytcMWdE=", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.34.9", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.9.tgz", + "integrity": "sha1-iUJ9ysDI46bTKxOgOilqJ10N6ak=", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.34.9", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.34.9.tgz", + "integrity": "sha1-7LlxG6K20r9u5RJlq+BXq5CRPes=", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.34.9", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.9.tgz", + "integrity": "sha1-GXOHGFCFaucrxniusGarlSMw6SM=", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@types/estree": { + "version": "1.0.6", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha1-Yo7/7q4gZKG055946B2Ht+X8e1A=", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha1-WWoXRyM2lNUPatinhp/Lb1bPWEE=", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "24.5.2", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@types/node/-/node-24.5.2.tgz", + "integrity": "sha1-Us64P1D+D8/fvSqfq22y6efvZEY=", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.12.0" + } + }, + "node_modules/@types/resolve": { + "version": "1.20.2", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@types/resolve/-/resolve-1.20.2.tgz", + "integrity": "sha1-l9JuAM1KBCO0r2IKvs8+b0QreXU=", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/semver": { + "version": "7.5.8", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@types/semver/-/semver-7.5.8.tgz", + "integrity": "sha1-gmioxXo+Sr0lwWXs02I323lIpV4=", + "dev": true, + "license": "MIT" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.59.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.1.tgz", + "integrity": "sha1-mwnuFUG/8dLOvcuH585KQAOs3gg=", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.59.1", + "@typescript-eslint/type-utils": "5.59.1", + "@typescript-eslint/utils": "5.59.1", + "debug": "^4.3.4", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "5.59.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@typescript-eslint/parser/-/parser-5.59.1.tgz", + "integrity": "sha1-c8LBISfFwRgtLltxqPoqhdIVy7Q=", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/scope-manager": "5.59.1", + "@typescript-eslint/types": "5.59.1", + "@typescript-eslint/typescript-estree": "5.59.1", + "debug": "^4.3.4" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.59.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@typescript-eslint/scope-manager/-/scope-manager-5.59.1.tgz", + "integrity": "sha1-iiAiJxnOvFGYYYpdRBE3BbUf1/4=", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "5.59.1", + "@typescript-eslint/visitor-keys": "5.59.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "5.59.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@typescript-eslint/type-utils/-/type-utils-5.59.1.tgz", + "integrity": "sha1-Y5gdYWhP0k7aL58IwKR+ywAKIRE=", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "5.59.1", + "@typescript-eslint/utils": "5.59.1", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "5.59.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@typescript-eslint/types/-/types-5.59.1.tgz", + "integrity": "sha1-A/P+3RwETLM268NMx4VfEhmR9B0=", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.59.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.1.tgz", + "integrity": "sha1-SqVG0n/Q1HfGGPDKALSD8OyExDw=", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/types": "5.59.1", + "@typescript-eslint/visitor-keys": "5.59.1", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "5.59.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@typescript-eslint/utils/-/utils-5.59.1.tgz", + "integrity": "sha1-2J/HWK0j0hV8+uU/C0Kb3xXblHM=", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.59.1", + "@typescript-eslint/types": "5.59.1", + "@typescript-eslint/typescript-estree": "5.59.1", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.59.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.1.tgz", + "integrity": "sha1-DZbDbvtlYNf7jrhd4QRCwQ2PYFg=", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "5.59.1", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/acorn": { + "version": "8.12.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/acorn/-/acorn-8.12.0.tgz", + "integrity": "sha1-Fie/ouBYFIA2EzuNm1GnAGY8KUw=", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha1-ftW7VZCLOy8bxVxq8WU7rafweTc=", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha1-uvWmLoArB9l3A0WG+MO69a3ybfQ=", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha1-CCyyyJyf6GWaMRpTvWpNxTAdswQ=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha1-7dgDYornHATIWuegkG7a00tkiTc=", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha1-JG9Q88p4oyQPbJl+ipvR6sSeSzg=", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha1-t5hCCtvrHego2ErNii4j0+/oXo0=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha1-6D46fj8wCzTLnYf2FfoMvzV2kO4=", + "dev": true, + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0=", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/braces/-/braces-3.0.3.tgz", + "integrity": "sha1-SQMy9AkZRSJy1VqEgK3AxEE1h4k=", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "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=", + "dev": true, + "license": "MIT" + }, + "node_modules/builtin-modules": { + "version": "3.3.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/builtin-modules/-/builtin-modules-3.3.0.tgz", + "integrity": "sha1-yuYoEriYAellYzbkYiPgMDhr57Y=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha1-s2MKvYlDQy9Us/BRkjjjPNffL3M=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha1-qsTit3NKdAhnrrFr8CqtVWoeegE=", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha1-ctOmjVmMm9s68q0ehPIdiWq9TeM=", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha1-wqCah6y95pVD3m9j+jmVyCbFNqI=", + "dev": true, + "license": "MIT" + }, + "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=", + "dev": true, + "license": "MIT" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha1-9zqFudXUHQRVUcF34ogtSshXKKY=", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.3.5", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/debug/-/debug-4.3.5.tgz", + "integrity": "sha1-6DRE7Ouf7dSh2lbWca4kRqAabh4=", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha1-pvLc5hL63S7x9Rm3NVHxfoUZmDE=", + "dev": true, + "license": "MIT" + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha1-RLXyFHzTsA1LVhN2hZZvJv0l3Uo=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha1-Vtv3PZkqSpO6FYT0U0Bj/S5BcX8=", + "dev": true, + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha1-rd6+rXKmV023g2OdyHoSF3OXOWE=", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha1-WuZKX0UFe682JuwU2gyl5LJDHrA=", + "dev": true, + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha1-FLqDpdNz49MR5a/KKc9b+tllvzQ=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.44.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/eslint/-/eslint-8.44.0.tgz", + "integrity": "sha1-USRuOImyWbvNHX1zagwQrdTw5QA=", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.4.0", + "@eslint/eslintrc": "^2.1.0", + "@eslint/js": "8.44.0", + "@humanwhocodes/config-array": "^0.11.10", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.0", + "eslint-visitor-keys": "^3.4.1", + "espree": "^9.6.0", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha1-54blmmbLkrP2wfsNUIqrF0hI9Iw=", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha1-DNcv6FUOPC6uFWqWpN3c0cisWAA=", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha1-3rT5JWM5DzIAaJSvYqItuhxGQj8=", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha1-LupSkHAvJquP5TcDcP+GyWXSESM=", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/globals/-/globals-13.24.0.tgz", + "integrity": "sha1-hDKhnXjODB6DOUnDats0VAC7EXE=", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/espree/-/espree-9.6.1.tgz", + "integrity": "sha1-oqF7jkNGkKVDLy+AGM5x0zGkjG8=", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha1-bOF3ON6Fd2lO3XNhxXGCrIyw2ws=", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha1-LupSkHAvJquP5TcDcP+GyWXSESM=", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha1-eteWTWeauyi+5yzsY3WLHF0smSE=", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha1-LupSkHAvJquP5TcDcP+GyWXSESM=", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha1-OYrT88WiSUi+dyXoPRGn3ijNvR0=", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha1-UvAQF4wqTBF6d1fP6UKtt9LaTKw=", + "dev": true, + "license": "MIT" + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha1-dNLrTeC42hKTcRkQ1Qd1ubcQ72Q=", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/execa": { + "version": "4.1.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/execa/-/execa-4.1.0.tgz", + "integrity": "sha1-TlSRrRVy8vF6d9OIxshXE1sihHo=", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha1-On1WtVnWy8PrUSMlJE5hmmXGxSU=", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha1-qQRQHlfP3S/83tRemaVP71XkYSk=", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha1-hpgyxYA0/mikCTwX3BXoNA2EAcQ=", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha1-h0v2nG9ATCtdmcSBNBOZ/VWJJjM=", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha1-KlI/B6TnsegaQrkbi/IlQQd1O0c=", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha1-IRst2WWcsDlLBz5zI6w8kz1SICc=", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha1-RCZdPKwH4+p9wkdRY4BkN1SgUpI=", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha1-TJKBnstwg1YeT0okCoa+UZj1Nvw=", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha1-LAwtUEDJmxYydxqdEFclwBFTY+4=", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.3.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha1-IdtHBymmc01JlwAvQ5yzCJh/Vno=", + "dev": true, + "license": "ISC" + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha1-ysZAd4XQNnWipeGlMFxpezR9kNY=", + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha1-LALYZNl/PqbIgwxGTL0Rq26rehw=", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha1-SWaheV7lrOZecGxLe+txJX1uItM=", + "dev": true, + "license": "MIT", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/git-commit-info": { + "version": "2.0.2", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/git-commit-info/-/git-commit-info-2.0.2.tgz", + "integrity": "sha1-XrAre34zk+zq+6KsIH3l2ceMzxs=", + "dev": true, + "license": "MIT", + "dependencies": { + "execa": "^4.0.3", + "is-git-repository": "^1.1.1", + "path-is-absolute": "^1.0.1" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/glob/-/glob-7.2.3.tgz", + "integrity": "sha1-uN8PuAK7+o6JvR2Ti04WV47UTys=", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha1-bSN9mQg5UMeSkPJMdkKj3poo+eM=", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/globby/-/globby-11.1.0.tgz", + "integrity": "sha1-vUvpi7BC+D15b344EZkfvoKg00s=", + "dev": true, + "license": "MIT", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha1-nPOmZcYkdHmJaDSvNc8du0QAdn4=", + "dev": true, + "license": "MIT" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha1-+y8dVeDjoYSa7/yQxPoN1ToOZsY=", + "dev": true, + "license": "MIT" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha1-lEdx/ZyByBJlxNaUGGDaBrtZR5s=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha1-AD6vkb563DcuhOxZ3DclLO24AAM=", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/human-signals": { + "version": "1.1.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/human-signals/-/human-signals-1.1.1.tgz", + "integrity": "sha1-xbHNFPUK6uCatsWf5jujOV/k36M=", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8.12.0" + } + }, + "node_modules/ignore": { + "version": "5.3.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha1-UHPlVM1CxbM7OUN19Ti4WT401O8=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha1-NxYsJfy566oublPVtNiM4X2eDCs=", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha1-D6LGT5MpF8NDOg3tVTY6rjdBa3w=", + "dev": true, + "license": "ISC" + }, + "node_modules/is-builtin-module": { + "version": "3.2.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/is-builtin-module/-/is-builtin-module-3.2.1.tgz", + "integrity": "sha1-8DJxcX2GVM/K8HqwRj+qNXFYEWk=", + "dev": true, + "license": "MIT", + "dependencies": { + "builtin-modules": "^3.3.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-core-module": { + "version": "2.13.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha1-rQ11Msb+qdoevcgnQtdFJcYnM4Q=", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-git-repository": { + "version": "1.1.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/is-git-repository/-/is-git-repository-1.1.1.tgz", + "integrity": "sha1-xo5LeoBkIjSarsSIlzqQVY1+m+A=", + "dev": true, + "license": "MIT", + "dependencies": { + "execa": "^0.6.1", + "path-is-absolute": "^1.0.1" + } + }, + "node_modules/is-git-repository/node_modules/cross-spawn": { + "version": "5.1.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "license": "MIT", + "dependencies": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "node_modules/is-git-repository/node_modules/execa": { + "version": "0.6.3", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/execa/-/execa-0.6.3.tgz", + "integrity": "sha1-V7aaWU8IF1nGnlNw8NF7nLEWWP4=", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/is-git-repository/node_modules/get-stream": { + "version": "3.0.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/is-git-repository/node_modules/is-stream": { + "version": "1.1.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-git-repository/node_modules/npm-run-path": { + "version": "2.0.2", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/is-git-repository/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/is-git-repository/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-git-repository/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-git-repository/node_modules/which": { + "version": "1.3.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/which/-/which-1.3.1.tgz", + "integrity": "sha1-pFBD1U9YBTFtqNYvn1CRjT2nCwo=", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha1-ZPYeQsu7LuwgcanawLKLoeZdUIQ=", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-module": { + "version": "1.0.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=", + "dev": true, + "license": "MIT" + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha1-dTU0W4lnNNX4DE0GxQlVUnoU8Ss=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha1-0jE2LlOgf/Kw4Op/7QSRYf/RYoM=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha1-+sHj1TuXrVqdCunO8jifWBClwHc=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true, + "license": "ISC" + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha1-GSA/tZmR35jjoocFDUZHzerzJJk=", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha1-wftl+PUBeQHN0slRhkuhhFihBgI=", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha1-kziAKjDTtmBfvgYT4JQAjKjAWhM=", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha1-afaofZUTq4u4/mO9sJecRI5oRmA=", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true, + "license": "MIT" + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha1-qHmpnilFL5QkOfKkBeOvizHU3pM=", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/levn/-/levn-0.4.1.tgz", + "integrity": "sha1-rkViwAdHO5MqYgDUAyaN0v/8at4=", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha1-VTIeswn+u8WcSAHZMackUqaB0oY=", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha1-VYqlO0O2YeGSWgr9+japoQhf5Xo=", + "dev": true, + "license": "MIT" + }, + "node_modules/lru-cache": { + "version": "4.1.5", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha1-i75Q6oW+1ZvJ4z3KuCNe6bz0Q80=", + "dev": true, + "license": "ISC", + "dependencies": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "node_modules/magic-string": { + "version": "0.30.10", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/magic-string/-/magic-string-0.30.10.tgz", + "integrity": "sha1-Ej2cQaDLVkDIkrBB1M+zvQqks54=", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha1-UoI2KaFN0AyXcPtq1H3GMQ8sH2A=", + "dev": true, + "license": "MIT" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha1-Q2iJL4hekHRVpv19xVwMnUBJkK4=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.7", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/micromatch/-/micromatch-4.0.7.tgz", + "integrity": "sha1-M+gZDZ/kdKmJVSX1YY7uE21GwuU=", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "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=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha1-Gc0ZS/0+Qo8EmnCBfAONiatL41s=", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/ms/-/ms-2.1.2.tgz", + "integrity": "sha1-0J0fNXtEP0kzgqjrPM0YOHKuYAk=", + "dev": true, + "license": "MIT" + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true, + "license": "MIT" + }, + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha1-F7CVgZiJef3a/gIB6TG6kzyWy7Q=", + "dev": true, + "license": "MIT" + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha1-t+zR5e1T2o43pV4cImnguX7XSOo=", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "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=", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha1-fqHBpdkddk+yghOciP4R4YKjpzQ=", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha1-4drMvnjQ0TiMoYxk/qOOPlfjcGs=", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha1-g8gxXGeFAF470CGDlBHJ4RDm2DQ=", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha1-aR0nCeeMefrjoVZiJFLQB2LKqqI=", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha1-UTvb4tO5XXdi6METfvoZXGxhtbM=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha1-WB9q3mWMu6ZaDTOA3ndTKVBU83U=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha1-+8EUtgykKzDZ2vWFjkvWi77bZzU=", + "dev": true, + "license": "MIT" + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha1-hO0BwKe6OAr+CdkKjBgNzZ0DBDs=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.0.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha1-qK1Xm1cZUvDl0liS3lRFvP4lqqE=", + "dev": true, + "license": "ISC", + "optional": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha1-O6ODNzNkbZ0+SZWUbBNlpn+wekI=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha1-3rxkidem5rDnYRiIzsiAM30xY5Y=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/pseudomap": { + "version": "1.0.2", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true, + "license": "ISC" + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/pump/-/pump-3.0.0.tgz", + "integrity": "sha1-tKIRaBW94vTh6mAjVOjHVWUQemQ=", + "dev": true, + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha1-AnQi4vrsCyXhVJw+G9gwm5EztuU=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha1-SSkii7xyTfrEPg77BYyve2z7YkM=", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha1-32+ENy8CcNxlzfYpE0mrekc9Tyo=", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha1-tsh6nyqgbfq1Lj1wrIzeMh+lpI0=", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha1-SrzYUq0y3Xuqv+m0DgCjbbXzkuY=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha1-kNo4Kx4SbvwCFG6QhFqI2xKSXXY=", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha1-8aVAK6YiCtUswSgrrBrjqkn9Bho=", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rollup": { + "version": "4.34.9", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/rollup/-/rollup-4.34.9.tgz", + "integrity": "sha1-4es5eFZHZ3iutqwqw9CbLOF3pVg=", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.6" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.34.9", + "@rollup/rollup-android-arm64": "4.34.9", + "@rollup/rollup-darwin-arm64": "4.34.9", + "@rollup/rollup-darwin-x64": "4.34.9", + "@rollup/rollup-freebsd-arm64": "4.34.9", + "@rollup/rollup-freebsd-x64": "4.34.9", + "@rollup/rollup-linux-arm-gnueabihf": "4.34.9", + "@rollup/rollup-linux-arm-musleabihf": "4.34.9", + "@rollup/rollup-linux-arm64-gnu": "4.34.9", + "@rollup/rollup-linux-arm64-musl": "4.34.9", + "@rollup/rollup-linux-loongarch64-gnu": "4.34.9", + "@rollup/rollup-linux-powerpc64le-gnu": "4.34.9", + "@rollup/rollup-linux-riscv64-gnu": "4.34.9", + "@rollup/rollup-linux-s390x-gnu": "4.34.9", + "@rollup/rollup-linux-x64-gnu": "4.34.9", + "@rollup/rollup-linux-x64-musl": "4.34.9", + "@rollup/rollup-win32-arm64-msvc": "4.34.9", + "@rollup/rollup-win32-ia32-msvc": "4.34.9", + "@rollup/rollup-win32-x64-msvc": "4.34.9", + "fsevents": "~2.3.2" + } + }, + "node_modules/rollup-plugin-dts": { + "version": "6.1.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/rollup-plugin-dts/-/rollup-plugin-dts-6.1.1.tgz", + "integrity": "sha1-RrM/TR1/TmbxFxztmygqwRoVolQ=", + "dev": true, + "license": "LGPL-3.0-only", + "dependencies": { + "magic-string": "^0.30.10" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/Swatinem" + }, + "optionalDependencies": { + "@babel/code-frame": "^7.24.2" + }, + "peerDependencies": { + "rollup": "^3.29.4 || ^4", + "typescript": "^4.5 || ^5.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha1-ZtE2jae9+SHrnZW9GpIp5/IaQ+4=", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha1-Hq+fqb2x/dTsdfWPnNtOa3gn7sY=", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.6.2", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/semver/-/semver-7.6.2.tgz", + "integrity": "sha1-Hjs0dZ+Jbo8U1hNHMs55iusMbhM=", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha1-3voeBVyDv21Z6oBdjahiJU62psI=", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha1-zNCvT4g1+9wmW4JGGq8MNmY/NOo=", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha1-rhbxZE2HPsrYQ7AwexQzYtTEIXI=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "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=", + "dev": true, + "license": "ISC" + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/slash/-/slash-3.0.0.tgz", + "integrity": "sha1-ZTm+hwwWWtvVJAIg2+Nh8bxNRjQ=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/smob": { + "version": "1.5.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/smob/-/smob-1.5.0.tgz", + "integrity": "sha1-hdeaFAOr8SjSTT68HNxeGpVI06s=", + "dev": true, + "license": "MIT" + }, + "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=", + "dev": true, + "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=", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha1-nibGPTD1NEPpSJSVshBdN7Z6hdk=", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-eof": { + "version": "1.0.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha1-ibhS+y/L6Tb29LMYevsKEsGrWK0=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha1-MfEoGzgyYwQ0gxwxDAHMzajL4AY=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha1-G33NyzK4E4gBs+R4umpRyqiWSNo=", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha1-btpL00SjyUrqN21MwxvHcxEDngk=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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=", + "dev": true, + "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/text-table": { + "version": "0.2.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true, + "license": "MIT" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha1-FkjESq58jZiKMmAY7XL1tN0DkuQ=", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tslib": { + "version": "2.6.3", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha1-BDj4EK16ntzeeiQcPYDbaTyMv+A=", + "dev": true, + "license": "0BSD" + }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha1-tIcX05TOpsHglpg+7Vjp1hcVtiM=", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/tsutils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha1-zy04vcNKE0vK8QkcQfZhni9nLQA=", + "dev": true, + "license": "0BSD" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha1-B7ggO/pwVsBlcFDjzNLDdzC6uPE=", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha1-G/IH9LKPkVg2ZstfvTJ4hzAc1fQ=", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "5.4.5", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha1-QszvLFcf29D2cYsdH15uXvAG9hE=", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "7.12.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/undici-types/-/undici-types-7.12.0.tgz", + "integrity": "sha1-FcXHR1wqO6MGWVKfXNtGdLYi+vs=", + "dev": true, + "license": "MIT" + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha1-mxpSWVIlhZ5V9mnZKPiMbFfyp34=", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/wasm-feature-detect": { + "version": "1.6.1", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/wasm-feature-detect/-/wasm-feature-detect-1.6.1.tgz", + "integrity": "sha1-IcfDX5sjPXHSlI1Kiz4gmMRSuUA=", + "license": "Apache-2.0" + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/which/-/which-2.0.2.tgz", + "integrity": "sha1-fGqN0KY2oDJ+ELWckobu6T8/UbE=", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha1-0sRcbdT7zmIaZvE2y+Mor9BBCzQ=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true, + "license": "ISC" + }, + "node_modules/yallist": { + "version": "2.1.2", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true, + "license": "ISC" + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-npm/npm/registry/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha1-ApTrPe4FAo0x7hpfosVWpqrxChs=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/src/native/package.json b/src/native/package.json new file mode 100644 index 00000000000000..c67c0721191489 --- /dev/null +++ b/src/native/package.json @@ -0,0 +1,48 @@ +{ + "name": "@microsoft/dotnet-runtime", + "description": ".NET is a developer platform with tools and libraries for building any type of app, including web, mobile, desktop, games, IoT, cloud, and microservices.", + "repository": { + "type": "git", + "url": "https://github.com/dotnet/runtime.git" + }, + "version": "1.0.0", + "main": "dotnet.js", + "type": "module", + "types": "dotnet.d.ts", + "scripts": { + "rollup:stub": "node rollup.stub.js", + "rollup:cmake": "rollup -c --environment ", + "rollup:release": "rollup -c --environment Configuration:Release,ProductVersion:10.0.0-dev,ContinuousIntegrationBuild:false", + "rollup:debug": "rollup -c --environment Configuration:Debug,ProductVersion:10.0.0-dev,ContinuousIntegrationBuild:false", + "lint": "eslint --no-color --max-warnings=0 \"./**/*.ts\" \"./*.js\"", + "format": "eslint --fix \"./**/*.ts\" \"./*.js\"" + }, + "keywords": [ + "dotnet", + "runtime", + "wasm" + ], + "author": "Microsoft", + "license": "MIT", + "devDependencies": { + "@rollup/plugin-node-resolve": "15.2.3", + "@rollup/plugin-terser": "0.4.4", + "@rollup/plugin-typescript": "11.1.6", + "@rollup/plugin-virtual": "3.0.2", + "@types/node": "^24.5.2", + "@typescript-eslint/eslint-plugin": "5.59.1", + "@typescript-eslint/parser": "5.59.1", + "eslint": "8.44.0", + "fast-glob": "3.3.2", + "git-commit-info": "2.0.2", + "magic-string": "0.30.10", + "rollup": "4.34.9", + "rollup-plugin-dts": "6.1.1", + "terser": "5.31.1", + "tslib": "2.6.3", + "typescript": "5.4.5" + }, + "dependencies": { + "wasm-feature-detect": "1.6.1" + } +} \ No newline at end of file diff --git a/src/native/rollup.stub.js b/src/native/rollup.stub.js new file mode 100644 index 00000000000000..1b59e429abce59 --- /dev/null +++ b/src/native/rollup.stub.js @@ -0,0 +1,45 @@ +//! Licensed to the .NET Foundation under one or more agreements. +//! The .NET Foundation licenses this file to you under the MIT license. + +import { promises as fs } from "fs"; +import path from "path"; + +/** + * This would be replace by real rollup with TypeScript compilation in next iteration + */ + + +const artifactsObjDir = "../../artifacts/obj"; +const configuration = process.argv[2] || "Debug"; +const productVersion = process.argv[3] || "10.0.0-dev"; +const isContinuousIntegrationBuild = process.argv[4] === "true" ? true : false; + +console.log(`Rollup configuration: Configuration=${configuration}, ProductVersion=${productVersion}, ContinuousIntegrationBuild=${isContinuousIntegrationBuild}`); + +const copies = [ + ["./corehost/browserhost/loader/dotnet.d.ts", + `${artifactsObjDir}/coreclr/browser.wasm.${configuration}/corehost/dotnet.d.ts`], + ["./corehost/browserhost/loader/dotnet.js", + `${artifactsObjDir}/coreclr/browser.wasm.${configuration}/corehost/dotnet.js`], + ["./corehost/browserhost/libBrowserHost.js", + `${artifactsObjDir}/coreclr/browser.wasm.${configuration}/corehost/libBrowserHost.js`], + ["./libs/System.Native.Browser/libSystem.Native.Browser.js", + `${artifactsObjDir}/native/browser-${configuration}-wasm/System.Native.Browser/libSystem.Native.Browser.js`], + ["./libs/System.Runtime.InteropServices.JavaScript.Native/dotnet.runtime.js", + `${artifactsObjDir}/native/browser-${configuration}-wasm/System.Runtime.InteropServices.JavaScript.Native/dotnet.runtime.js`], + ["./libs/System.Runtime.InteropServices.JavaScript.Native/libSystem.Runtime.InteropServices.JavaScript.Native.js", + `${artifactsObjDir}/native/browser-${configuration}-wasm/System.Runtime.InteropServices.JavaScript.Native/libSystem.Runtime.InteropServices.JavaScript.Native.js`] +]; + +const now = new Date(); +for (const [src, dest] of copies) { + const absoluteSrc = path.resolve(src); + const absoluteDest = path.resolve(dest); + const destDir = path.resolve(path.dirname(dest)); + console.log(`Copying ${absoluteSrc} to ${destDir}`); + await fs.mkdir(destDir, { recursive: true }); + await fs.copyFile(absoluteSrc, absoluteDest); + // TODO-WASM: make rollup incremental + // await fs.utimes(absoluteDest, now, now); +} +await fs.writeFile(`${artifactsObjDir}/coreclr/browser.wasm.${configuration}/corehost/.rollup.stamp`, new Date().toISOString()); diff --git a/src/native/tsconfig.json b/src/native/tsconfig.json new file mode 100644 index 00000000000000..6709400b3bc508 --- /dev/null +++ b/src/native/tsconfig.json @@ -0,0 +1,30 @@ +{ + "compilerOptions": { + "noImplicitAny": true, + "noEmitOnError": true, + "removeComments": false, + "module": "esnext", + "sourceMap": true, + "target": "ES2018", + "moduleResolution": "Node", + "strict": true, + "lib": [ + "esnext", + "dom" + ], + "types": [ + "node" + ], + "typeRoots": [ + "./node_modules/@types", + "./libs/Common/JavaScript/types" + ], + "rootDirs": [ + "./", + "../../artifacts/bin/native/generated" + ] + }, + "exclude": [ + "./corehost/loader/dotnet.d.ts" + ] +} \ No newline at end of file