From 84d9fdba37df014820f67027049437b068b0bb8e Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Sat, 20 Sep 2025 01:24:02 +0200 Subject: [PATCH 01/25] feedback, rebase --- docs/workflow/building/coreclr/wasm.md | 14 + .../common/evaluate-default-paths.yml | 8 + src/coreclr/CMakeLists.txt | 2 + src/coreclr/hosts/corerun/CMakeLists.txt | 8 +- src/coreclr/hosts/corerun/corerun.js | 6 - src/coreclr/hosts/corerun/libCorerun.pre.js | 14 + src/coreclr/hosts/corewasmrun/CMakeLists.txt | 5 + .../hosts/corewasmrun/libCorewasmrun.pre.js | 6 + src/coreclr/vm/wasm/helpers.cpp | 6 - .../Directory.Build.props | 2 + src/native/.eslintignore | 3 + src/native/.eslintrc.cjs | 65 + src/native/{libs => }/.npmrc | 0 src/native/corehost/CMakeLists.txt | 41 +- .../corehost/browserhost/CMakeLists.txt | 96 + .../corehost/browserhost/browserhost.cpp | 173 + src/native/corehost/browserhost/config.h.in | 10 + .../corehost/browserhost/configure.cmake | 6 + .../corehost/browserhost/libBrowserHost.js | 40 + .../corehost/browserhost/loader/ReadMe.md | 15 + .../corehost/browserhost/loader/dotnet.d.ts | 782 +++++ .../corehost/browserhost/loader/dotnet.js | 910 +++++ src/native/corehost/browserhost/native.rc | 7 + .../corehost/browserhost/sample/HelloWorld.cs | 11 + .../browserhost/sample/HelloWorld.csproj | 11 + .../corehost/browserhost/sample/ReadMe.md | 3 + .../browserhost/sample/dotnet.boot.js | 101 + .../corehost/browserhost/sample/index.html | 18 + .../corehost/browserhost/sample/main.mjs | 12 + src/native/libs/CMakeLists.txt | 5 + .../libs/Common/JavaScript/types/consts.d.ts | 8 + .../Common/JavaScript/types/emscripten.ts | 68 + .../libs/Common/JavaScript/types/emsdk.d.ts | 5 + .../libs/Common/JavaScript/types/exchange.ts | 64 + .../Common/JavaScript/types/export-api.ts | 21 + .../libs/Common/JavaScript/types/index.ts | 8 + .../libs/Common/JavaScript/types/internal.ts | 122 + .../libs/Common/JavaScript/types/node.d.ts | 5 + .../Common/JavaScript/types/public-api.ts | 736 ++++ .../libs/Common/JavaScript/types/v8.d.ts | 5 + .../libs/System.Native.Browser/CMakeLists.txt | 53 + .../libs/System.Native.Browser/ReadMe.md | 15 + .../libs/System.Native.Browser/entrypoints.c | 24 + .../libSystem.Native.Browser.extpost.js | 10 + .../libSystem.Native.Browser.js | 721 ++++ .../CMakeLists.txt | 14 + .../ReadMe.md | 16 + .../dotnet.runtime.js | 461 +++ .../entrypoints.c | 24 + ...ntime.InteropServices.JavaScript.Native.js | 236 ++ src/native/package-lock.json | 3035 +++++++++++++++++ src/native/package.json | 45 + src/native/rollup.config.defines.js | 30 + src/native/rollup.config.js | 20 + src/native/rollup.config.plugins.js | 128 + src/native/tsconfig.json | 33 + 56 files changed, 8258 insertions(+), 29 deletions(-) delete mode 100644 src/coreclr/hosts/corerun/corerun.js create mode 100644 src/coreclr/hosts/corerun/libCorerun.pre.js create mode 100644 src/coreclr/hosts/corewasmrun/libCorewasmrun.pre.js create mode 100644 src/native/.eslintignore create mode 100644 src/native/.eslintrc.cjs rename src/native/{libs => }/.npmrc (100%) create mode 100644 src/native/corehost/browserhost/CMakeLists.txt create mode 100644 src/native/corehost/browserhost/browserhost.cpp create mode 100644 src/native/corehost/browserhost/config.h.in create mode 100644 src/native/corehost/browserhost/configure.cmake create mode 100644 src/native/corehost/browserhost/libBrowserHost.js create mode 100644 src/native/corehost/browserhost/loader/ReadMe.md create mode 100644 src/native/corehost/browserhost/loader/dotnet.d.ts create mode 100644 src/native/corehost/browserhost/loader/dotnet.js create mode 100644 src/native/corehost/browserhost/native.rc create mode 100644 src/native/corehost/browserhost/sample/HelloWorld.cs create mode 100644 src/native/corehost/browserhost/sample/HelloWorld.csproj create mode 100644 src/native/corehost/browserhost/sample/ReadMe.md create mode 100644 src/native/corehost/browserhost/sample/dotnet.boot.js create mode 100644 src/native/corehost/browserhost/sample/index.html create mode 100644 src/native/corehost/browserhost/sample/main.mjs create mode 100644 src/native/libs/Common/JavaScript/types/consts.d.ts create mode 100644 src/native/libs/Common/JavaScript/types/emscripten.ts create mode 100644 src/native/libs/Common/JavaScript/types/emsdk.d.ts create mode 100644 src/native/libs/Common/JavaScript/types/exchange.ts create mode 100644 src/native/libs/Common/JavaScript/types/export-api.ts create mode 100644 src/native/libs/Common/JavaScript/types/index.ts create mode 100644 src/native/libs/Common/JavaScript/types/internal.ts create mode 100644 src/native/libs/Common/JavaScript/types/node.d.ts create mode 100644 src/native/libs/Common/JavaScript/types/public-api.ts create mode 100644 src/native/libs/Common/JavaScript/types/v8.d.ts create mode 100644 src/native/libs/System.Native.Browser/CMakeLists.txt create mode 100644 src/native/libs/System.Native.Browser/ReadMe.md create mode 100644 src/native/libs/System.Native.Browser/entrypoints.c create mode 100644 src/native/libs/System.Native.Browser/libSystem.Native.Browser.extpost.js create mode 100644 src/native/libs/System.Native.Browser/libSystem.Native.Browser.js create mode 100644 src/native/libs/System.Runtime.InteropServices.JavaScript.Native/CMakeLists.txt create mode 100644 src/native/libs/System.Runtime.InteropServices.JavaScript.Native/ReadMe.md create mode 100644 src/native/libs/System.Runtime.InteropServices.JavaScript.Native/dotnet.runtime.js create mode 100644 src/native/libs/System.Runtime.InteropServices.JavaScript.Native/entrypoints.c create mode 100644 src/native/libs/System.Runtime.InteropServices.JavaScript.Native/libSystem.Runtime.InteropServices.JavaScript.Native.js create mode 100644 src/native/package-lock.json create mode 100644 src/native/package.json create mode 100644 src/native/rollup.config.defines.js create mode 100644 src/native/rollup.config.js create mode 100644 src/native/rollup.config.plugins.js create mode 100644 src/native/tsconfig.json diff --git a/docs/workflow/building/coreclr/wasm.md b/docs/workflow/building/coreclr/wasm.md index 00064df946a46f..0024aa758d0eee 100644 --- a/docs/workflow/building/coreclr/wasm.md +++ b/docs/workflow/building/coreclr/wasm.md @@ -117,6 +117,20 @@ VS Code, through Node.js, provides a good debugging option for WebAssembly CoreC "/runtime3/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..21f61575b3be16 100644 --- a/src/coreclr/CMakeLists.txt +++ b/src/coreclr/CMakeLists.txt @@ -71,6 +71,8 @@ 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 set(GEN_PINVOKE 0) + 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..813740797aff53 100644 --- a/src/coreclr/hosts/corerun/CMakeLists.txt +++ b/src/coreclr/hosts/corerun/CMakeLists.txt @@ -52,15 +52,21 @@ 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_target_properties(corerun PROPERTIES + LINK_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/libCorerun.pre.js;${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Native.Browser/libSystem.Native.Browser.js;" + LINK_FLAGS "--pre-js ${CMAKE_CURRENT_SOURCE_DIR}/libCorerun.pre.js --js-library ${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Native.Browser/libSystem.Native.Browser.js" + 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..3f83f398cc8373 100644 --- a/src/coreclr/hosts/corewasmrun/CMakeLists.txt +++ b/src/coreclr/hosts/corewasmrun/CMakeLists.txt @@ -17,6 +17,10 @@ target_include_directories(corewasmrun PRIVATE ) target_compile_options(corewasmrun PRIVATE -fwasm-exceptions) +set_target_properties(corewasmrun PROPERTIES + LINK_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/libCorewasmrun.pre.js;${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Native.Browser/libSystem.Native.Browser.js;" + LINK_FLAGS "--pre-js ${CMAKE_CURRENT_SOURCE_DIR}/libCorewasmrun.pre.js --js-library ${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Native.Browser/libSystem.Native.Browser.js" + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") target_link_options(corewasmrun PRIVATE -fwasm-exceptions -sEXIT_RUNTIME=1 @@ -27,6 +31,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/wasm/helpers.cpp b/src/coreclr/vm/wasm/helpers.cpp index 23c8a03d13fe10..182eaf99210616 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); 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..cc09f5bd35788d 100644 --- a/src/native/corehost/CMakeLists.txt +++ b/src/native/corehost/CMakeLists.txt @@ -3,6 +3,10 @@ project(corehost) include(../../../eng/native/configurepaths.cmake) include(${CLR_ENG_NATIVE_DIR}/configurecompiler.cmake) +if(CLR_CMAKE_TARGET_BROWSER) +# include_directories(${CLR_SRC_NATIVE_DIR}/libs/System.Native.Browser) +# include_directories(${CLR_SRC_NATIVE_DIR}/libs/System.Runtime.InteropServices.JavaScript.Native) +endif(CLR_CMAKE_TARGET_BROWSER) set(COREHOST_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}") @@ -79,25 +83,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..f95c6cb9dc9c69 --- /dev/null +++ b/src/native/corehost/browserhost/CMakeLists.txt @@ -0,0 +1,96 @@ +# 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 + # WASMTODO respect $(InvariantTimezone) + # System.Native.TimeZoneData.Invariant + System.Native.TimeZoneData +) + +# WASMTODO set(RUNTIMEINFO_LIB runtimeinfo) + +target_compile_options(browserhost PRIVATE -fwasm-exceptions) + +set_target_properties(browserhost PROPERTIES + LINK_DEPENDS "${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.Runtime.InteropServices.JavaScript.Native/libSystem.Runtime.InteropServices.JavaScript.Native.js;${CMAKE_CURRENT_SOURCE_DIR}/libBrowserHost.js;${CMAKE_CURRENT_SOURCE_DIR}/../../libs/System.Native.Browser/libSystem.Native.Browser.extpost.js;" + LINK_FLAGS "--js-library ${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Native.Browser/libSystem.Native.Browser.js --js-library ${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Runtime.InteropServices.JavaScript.Native/libSystem.Runtime.InteropServices.JavaScript.Native.js --js-library ${CMAKE_CURRENT_SOURCE_DIR}/libBrowserHost.js --extern-post-js ${CMAKE_CURRENT_SOURCE_DIR}/../../libs/System.Native.Browser/libSystem.Native.Browser.extpost.js " + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") + +# WASMTODO -Oz -sVERBOSE +target_link_options(browserhost PRIVATE + -fwasm-exceptions + -sEXIT_RUNTIME=0 + -sINITIAL_MEMORY=134217728 + -sSTACK_SIZE=5MB + -sMODULARIZE=1 + -sEXPORT_ES6=1 + -sEXPORTED_RUNTIME_METHODS=UTF8ToString,cwrap,ccall,HEAPU8,HEAPU32,HEAPU64,BROWSER_HOST + -sEXPORTED_FUNCTIONS=_posix_memalign,_free,stackAlloc,stackRestore,stackSave,_browserHostInitializeCoreCLR,_browserHostExecuteAssembly + -sEXPORT_NAME=createDotnetRuntime + -lnodefs.js + -Wl,-error-limit=0) + +target_link_libraries( + browserhost + PRIVATE + hostmisc + clrinterpreter + ${NATIVE_LIBS} + + ${START_WHOLE_ARCHIVE} + ${RUNTIMEINFO_LIB} + ${END_WHOLE_ARCHIVE} +) + +# TODOWASM: this is temporary locations +set(SAMPLE_ASSETS + sample/index.html + sample/main.mjs + sample/dotnet.boot.js + # ${CLR_ARTIFACTS_OBJ_DIR}/sfx-finish/${CMAKE_BUILD_TYPE}/net10.0-browser/illink-wasm/System.Console.dll + # ${CLR_ARTIFACTS_OBJ_DIR}/sfx-finish/${CMAKE_BUILD_TYPE}/net10.0-browser/illink-wasm/System.Private.CoreLib.dll + # ${CLR_ARTIFACTS_OBJ_DIR}/sfx-finish/${CMAKE_BUILD_TYPE}/net10.0-browser/illink-wasm/System.Runtime.dll + # ${CLR_ARTIFACTS_OBJ_DIR}/sfx-finish/${CMAKE_BUILD_TYPE}/net10.0-browser/illink-wasm/System.Runtime.InteropServices.dll + # ${CLR_ARTIFACTS_OBJ_DIR}/sfx-finish/${CMAKE_BUILD_TYPE}/net10.0-browser/illink-wasm/System.Threading.dll + # ${CLR_ARTIFACTS_BIN_DIR}/artifacts/bin/HelloWorld/${CMAKE_BUILD_TYPE}/net10.0/win-x64/HelloWorld.dll + ${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.js.map + ${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 + ${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Runtime.InteropServices.JavaScript.Native/dotnet.runtime.js.map +) +install(FILES ${SAMPLE_ASSETS} DESTINATION corehost COMPONENT runtime) diff --git a/src/native/corehost/browserhost/browserhost.cpp b/src/native/corehost/browserhost/browserhost.cpp new file mode 100644 index 00000000000000..2ace734adc8cd9 --- /dev/null +++ b/src/native/corehost/browserhost/browserhost.cpp @@ -0,0 +1,173 @@ +// 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.Globalization.Native") == 0) + { + return GlobalizationResolveDllImport(entry_point_name); + } + if (strcmp(library_name, "libSystem.IO.Compression.Native") == 0) + { + return CompressionResolveDllImport(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 buffer[STRING_LENGTH("0xffffffffffffffff")]; + +extern "C" int browserHostInitializeCoreCLR(void) +{ + //TODOWASM: 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(buffer, ARRAY_SIZE(buffer), _X("0x%zx"), (size_t)(&host_contract)); + + propertyKeys.push_back(HOST_PROPERTY_RUNTIME_CONTRACT); + propertyValues.push_back(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; +} + +// TODOWASM: 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; + // TODOWASM: this is too trivial + browserHostRejectMain("coreclr_shutdown_2 failed"); + } + + // TODOWASM: 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..b284c010edabdb --- /dev/null +++ b/src/native/corehost/browserhost/libBrowserHost.js @@ -0,0 +1,40 @@ +//! 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. + */ + +(function (exports) { + function browserHostLibLibFactory() { + const BrowserHostLib = { + $BROWSER_HOST: { + selfInitialize: () => { + if (typeof dotnetInternals !== "undefined") { + BROWSER_HOST.dotnetInternals = dotnetInternals; + + 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); + config.environmentVariables[HOST_PROPERTY_TRUSTED_PLATFORM_ASSEMBLIES] = [...coreAssemblyPaths, assemblyPaths].join(":"); + config.environmentVariables[HOST_PROPERTY_NATIVE_DLL_SEARCH_DIRECTORIES] = config.virtualWorkingDirectory; + config.environmentVariables[HOST_PROPERTY_APP_PATHS] = config.virtualWorkingDirectory; + config.environmentVariables[HOST_PROPERTY_ENTRY_ASSEMBLY_NAME] = config.mainAssemblyName; + } + }, + }, + "$BROWSER_HOST__deps": ["$DOTNET", "browserHostInitializeCoreCLR", "browserHostExecuteAssembly", "browserHostExternalAssemblyProbe"], + "$BROWSER_HOST__postset": "DOTNET.selfInitialize();", + }; + autoAddDeps(BrowserHostLib, "$BROWSER_HOST"); + addToLibrary(BrowserHostLib); + } + browserHostLibLibFactory(); + return exports; +})({}); diff --git a/src/native/corehost/browserhost/loader/ReadMe.md b/src/native/corehost/browserhost/loader/ReadMe.md new file mode 100644 index 00000000000000..35479644c1a6de --- /dev/null +++ b/src/native/corehost/browserhost/loader/ReadMe.md @@ -0,0 +1,15 @@ +# System.JavaScript.Loader + +Is TypeScript project that is compiled via `src\native\libs\Browser\rollup.config.js` into JavaScript ES6 module. + +## Dotnet.Loader.ts -> dotnet.js + +`System.JavaScript.Loader.ts` is root of **JavaScript module** that would become of `dotnet.js`. +It implements host for the browser together with `src/native/corehost/browserhost`. +It exposes the public JS runtime APIs that is implemented in `Dotnet.Runtime.ts`. +It's good to keep this file small. + + +And one native library compiled by CMake into `System.JavaScript.a` as part of `/src/native/libs/CMakeLists.txt` + + 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..1ee4e6849bbeac --- /dev/null +++ b/src/native/corehost/browserhost/loader/dotnet.js @@ -0,0 +1,910 @@ +//! 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 JSEngine; +let Module; +let runtimeApi; +let Logger = {}; +let Assert = {}; +let loaderExports = {}; +let runtimeExports = {}; +let nativeExports = {}; +let interopExports = {}; +let dotnetInternals; +function getInternals() { + return dotnetInternals; +} +function setInternals(internal) { + dotnetInternals = internal; + runtimeApi = dotnetInternals.runtimeApi; + Module = dotnetInternals.runtimeApi.Module; +} +function updateInternals() { + if (dotnetInternals.updates === undefined) { + dotnetInternals.updates = []; + } + for (const updateImpl of dotnetInternals.updates) { + updateImpl(); + } +} +function updateInternalsImpl() { + if (!JSEngine) { + 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; + 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, + }; + } + if (Object.keys(loaderExports).length === 0 && dotnetInternals.loaderExportsTable) { + loaderExports = {}; + Logger = {}; + Assert = {}; + loaderExportsFromTable(dotnetInternals.loaderExportsTable, Logger, Assert, loaderExports); + } + if (Object.keys(runtimeExports).length === 0 && dotnetInternals.runtimeExportsTable) { + runtimeExports = {}; + runtimeExportsFromTable(dotnetInternals.runtimeExportsTable, runtimeExports); + } + if (Object.keys(nativeExports).length === 0 && dotnetInternals.nativeExportsTable) { + nativeExports = {}; + nativeExportsFromTable(dotnetInternals.nativeExportsTable, nativeExports); + } + if (Object.keys(interopExports).length === 0 && dotnetInternals.interopExportsTable) { + interopExports = {}; + interopExportsFromTable(dotnetInternals.interopExportsTable, interopExports); + } +} +/** + * 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 loaderExportsToTable(logger, assert, loaderExports) { + return [ + logger.info, + logger.warn, + logger.error, + assert.check, + loaderExports.browserHostResolveMain, + loaderExports.browserHostRejectMain, + loaderExports.getRunMainPromise, + ]; +} +function loaderExportsFromTable(table, logger, assert, loaderExports) { + const loggerLocal = { + info: table[0], + warn: table[1], + error: table[2], + }; + const assertLocal = { + check: table[3], + }; + const loaderExportsLocal = { + browserHostResolveMain: table[4], + browserHostRejectMain: table[5], + getRunMainPromise: table[6], + }; + Object.assign(logger, loggerLocal); + Object.assign(assert, assertLocal); + Object.assign(loaderExports, loaderExportsLocal); +} +// eslint-disable-next-line @typescript-eslint/no-unused-vars +function runtimeExportsToTable(map) { + return []; +} +function runtimeExportsFromTable(table, runtime) { + Object.assign(runtime, {}); +} +function nativeExportsToTable(map) { + return [ + map.registerDllBytes, + map.isSharedArrayBuffer, + ]; +} +function nativeExportsFromTable(table, native) { + const nativeLocal = { + registerDllBytes: table[0], + isSharedArrayBuffer: table[1], + }; + Object.assign(native, nativeLocal); +} +// eslint-disable-next-line @typescript-eslint/no-unused-vars +function interopExportsToTable(map) { + return []; +} +function interopExportsFromTable(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. +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(() => { + updateInternals(); +}); +// TODOWASM: retry logic +// TODOWASM: throttling logic +// TODOWASM: load icu data +// TODOWASM: invokeLibraryInitializers +// TODOWASM: 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); + fetchWasm(config.resources.wasmNative[0]); // start loading early, no await + 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; + nativeExports.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 = "becd20635d51b17f7f344df90775c63e7e744d11"; + +// 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 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 = { + getRunMainPromise, + browserHostRejectMain, + browserHostResolveMain, + }; + const logger = { + info, + warn, + error, + }; + const assert = { + check, + }; + Object.assign(runtimeApi, runtimeApiFunctions); + Object.assign(Logger, logger); + Object.assign(Assert, assert); + Object.assign(loaderExports, loaderFunctions); + dotnetInternals.loaderExportsTable = [...loaderExportsToTable(Logger, Assert, loaderExports)]; + updates.push(updateInternalsImpl); + updateInternals(); + 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/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..efd26667a528fc --- /dev/null +++ b/src/native/corehost/browserhost/sample/ReadMe.md @@ -0,0 +1,3 @@ +# Demo files + +This is simple demo customer code that uses dotnet.js \ 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..18ba61ca61670a --- /dev/null +++ b/src/native/corehost/browserhost/sample/dotnet.boot.js @@ -0,0 +1,101 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// TODOWASM: this is dummy configuration until WASM SDK for corehost + +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", + } + ], + "icu": [ + { + "virtualPath": "icudt_CJK.dat", + "name": "icudt_CJK.dat", + }, + { + "virtualPath": "icudt_EFIGS.dat", + "name": "icudt_EFIGS.dat", + }, + { + "virtualPath": "icudt_no_CJK.dat", + "name": "icudt_no_CJK.dat", + } + ], + "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" + }, + { + "virtualPath": "/System.Runtime.InteropServices.JavaScript.dll", + "name": "System.Runtime.InteropServices.JavaScript.dll" + }, + ] + }, + "debugLevel": -1, + "globalizationMode": "sharded", + "runtimeConfig": { + "runtimeOptions": { + "configProperties": { + "System.Net.Http.dllEnableStreamingResponse": true, + "Microsoft.Extensions.DependencyInjection.VerifyOpenGenericServiceTrimmability": true, + "System.ComponentModel.DefaultValueAttribute.IsSupported": false, + "System.ComponentModel.Design.IDesignerHost.IsSupported": false, + "System.ComponentModel.TypeConverter.EnableUnsafeBinaryFormatterInDesigntimeLicenseContextSerialization": false, + "System.ComponentModel.TypeDescriptor.IsComObjectDescriptorSupported": false, + "System.Data.DataSet.XmlSerializationIsSupported": false, + "System.Diagnostics.Metrics.Meter.IsSupported": false, + "System.Reflection.Metadata.MetadataUpdater.IsSupported": false, + "System.Resources.ResourceManager.AllowCustomResourceTypes": false, + "System.Resources.UseSystemResourceKeys": false, + "System.Runtime.CompilerServices.RuntimeFeature.IsDynamicCodeSupported": true, + "System.Runtime.InteropServices.BuiltInComInterop.IsSupported": false, + "System.Runtime.InteropServices.EnableConsumingManagedCodeFromNativeHosting": false, + "System.Runtime.InteropServices.EnableCppCLIHostActivation": false, + "System.Runtime.InteropServices.Marshalling.EnableGeneratedComInterfaceComImportInterop": false, + "System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": false, + "System.StartupHookProvider.IsSupported": false, + "System.Text.Encoding.EnableUnsafeUTF7Encoding": false, + "System.Text.Json.JsonSerializer.IsReflectionEnabledByDefault": false, + "System.Threading.Thread.EnableAutoreleasePool": false + } + } + } +}/*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/libs/CMakeLists.txt b/src/native/libs/CMakeLists.txt index 5fd8f0d051a9d8..4ce3c665f8a919 100644 --- a/src/native/libs/CMakeLists.txt +++ b/src/native/libs/CMakeLists.txt @@ -108,6 +108,11 @@ endif () add_subdirectory(System.IO.Compression.Native) +if (CLR_CMAKE_TARGET_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..7b03c4d3a6a80d --- /dev/null +++ b/src/native/libs/Common/JavaScript/types/exchange.ts @@ -0,0 +1,64 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +import type { isSharedArrayBuffer } from "../../../System.Native.Browser/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 = { + browserHostResolveMain:typeof browserHostResolveMain, + browserHostRejectMain:typeof browserHostRejectMain, + getRunMainPromise:typeof getRunMainPromise, +} + +export type LoaderExportsTable = [ + typeof info, + typeof warn, + typeof error, + typeof check, + typeof browserHostResolveMain, + typeof browserHostRejectMain, + typeof getRunMainPromise, +] + +type registerDllBytesType = (bytes: Uint8Array, asset: { name: string })=>void; + +export type NativeExports = { + isSharedArrayBuffer : typeof isSharedArrayBuffer, + registerDllBytes: registerDllBytesType +} + +export type NativeExportsTable = [ + registerDllBytesType, + typeof isSharedArrayBuffer, +] + +export type InteropExports = { +} + +export type InteropExportsTable = [ +] 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..3785fb99ca5ec0 --- /dev/null +++ b/src/native/libs/Common/JavaScript/types/internal.ts @@ -0,0 +1,122 @@ +// 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 { InteropExportsTable, LoaderExportsTable, NativeExportsTable, RuntimeExportsTable } 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 { + 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, + nativeExportsTable: NativeExportsTable, + interopExportsTable: InteropExportsTable, + 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..2b087862339ff2 --- /dev/null +++ b/src/native/libs/System.Native.Browser/CMakeLists.txt @@ -0,0 +1,53 @@ +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) + + +file(GLOB_RECURSE ROLLUP_TS_SOURCES + "${CMAKE_CURRENT_SOURCE_DIR}/*.ts" + "${CMAKE_CURRENT_SOURCE_DIR}/*.js" + "${CMAKE_CURRENT_SOURCE_DIR}/../System.Runtime.InteropServices.JavaScript.Native/*.ts" + "${CMAKE_CURRENT_SOURCE_DIR}/../System.Runtime.InteropServices.JavaScript.Native/*.js" + "${CMAKE_CURRENT_SOURCE_DIR}/../Common/JavaScript/*.ts" + "${CMAKE_CURRENT_SOURCE_DIR}/../Common/JavaScript/*.js" + "${CMAKE_CURRENT_SOURCE_DIR}/../../corehost/browserhost/*.ts" + "${CMAKE_CURRENT_SOURCE_DIR}/../../corehost/browserhost/*.js" +) + +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.js.map" + "${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.Native.Browser/libSystem.Native.Browser.js" + "${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Native.Browser/libSystem.Native.Browser.js.map" + "${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.Native.Browser/dotnet.runtime.js.map" + "${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Runtime.InteropServices.JavaScript.Native/libSystem.Runtime.InteropServices.JavaScript.Native.js" + "${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Runtime.InteropServices.JavaScript.Native/libSystem.Runtime.InteropServices.JavaScript.Native.js.map" +) + +add_custom_command( + OUTPUT ${ROLLUP_OUTPUTS} + COMMAND npm run rollup + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/.." + COMMENT "Running 'npm run rollup' to generate JavaScript bundles" + DEPENDS ${ROLLUP_TS_SOURCES} + VERBATIM +) + +add_custom_target(System.Native.Browser-Rollup + DEPENDS ${ROLLUP_OUTPUTS} +) + +add_dependencies(System.Native.Browser-Static System.Native.Browser-Rollup) \ No newline at end of file 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..6c7136d9c5ee9a --- /dev/null +++ b/src/native/libs/System.Native.Browser/ReadMe.md @@ -0,0 +1,15 @@ +# System.JavaScript + +Is TypeScript project that is compiled via `src\native\libs\rollup.config.js` into Emscripten JS library. +And a native library compiled by CMake into `System.JavaScript.a` as part of `/src/native/libs/CMakeLists.txt` + +## System.JavaScript.ts -> dotnet.native.js + +This is root of **Emscripten library** that would become part of `dotnet.runtime.js` +It implements native parts of PAL for the VM/runtime. + +## ententrypoints.c -> System.JavaScript.a -> dotnet.native.wasm + +This is making functions from `runtime/native-exports.ts` visible in C code. + +**TODOWASM**: This is preventing trimming and should be replaced by generated P/Invokes that are IL trimmed first. 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..04cb94aba0e7b6 --- /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 async 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..0b41e5d0f4aa08 --- /dev/null +++ b/src/native/libs/System.Native.Browser/libSystem.Native.Browser.js @@ -0,0 +1,721 @@ +//! 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 libSystemNativeBrowserJS = (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 JSEngine; + let Module; + let runtimeApi; + let Logger = {}; + let Assert = {}; + let loaderExports = {}; + let runtimeExports = {}; + let nativeExports = {}; + let interopExports = {}; + let dotnetInternals; + function getInternals() { + return dotnetInternals; + } + function setInternals(internal) { + dotnetInternals = internal; + runtimeApi = dotnetInternals.runtimeApi; + Module = dotnetInternals.runtimeApi.Module; + } + function updateInternals() { + if (dotnetInternals.updates === undefined) { + dotnetInternals.updates = []; + } + for (const updateImpl of dotnetInternals.updates) { + updateImpl(); + } + } + function updateInternalsImpl() { + if (!JSEngine) { + 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; + 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, + }; + } + if (Object.keys(loaderExports).length === 0 && dotnetInternals.loaderExportsTable) { + loaderExports = {}; + Logger = {}; + Assert = {}; + loaderExportsFromTable(dotnetInternals.loaderExportsTable, Logger, Assert, loaderExports); + } + if (Object.keys(runtimeExports).length === 0 && dotnetInternals.runtimeExportsTable) { + runtimeExports = {}; + runtimeExportsFromTable(dotnetInternals.runtimeExportsTable, runtimeExports); + } + if (Object.keys(nativeExports).length === 0 && dotnetInternals.nativeExportsTable) { + nativeExports = {}; + nativeExportsFromTable(dotnetInternals.nativeExportsTable, nativeExports); + } + if (Object.keys(interopExports).length === 0 && dotnetInternals.interopExportsTable) { + interopExports = {}; + interopExportsFromTable(dotnetInternals.interopExportsTable, interopExports); + } + } + /** + * 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 loaderExportsToTable(logger, assert, loaderExports) { + return [ + logger.info, + logger.warn, + logger.error, + assert.check, + loaderExports.browserHostResolveMain, + loaderExports.browserHostRejectMain, + loaderExports.getRunMainPromise, + ]; + } + function loaderExportsFromTable(table, logger, assert, loaderExports) { + const loggerLocal = { + info: table[0], + warn: table[1], + error: table[2], + }; + const assertLocal = { + check: table[3], + }; + const loaderExportsLocal = { + browserHostResolveMain: table[4], + browserHostRejectMain: table[5], + getRunMainPromise: table[6], + }; + Object.assign(logger, loggerLocal); + Object.assign(assert, assertLocal); + Object.assign(loaderExports, loaderExportsLocal); + } + // eslint-disable-next-line @typescript-eslint/no-unused-vars + function runtimeExportsToTable(map) { + return []; + } + function runtimeExportsFromTable(table, runtime) { + Object.assign(runtime, {}); + } + function nativeExportsToTable(map) { + return [ + map.registerDllBytes, + map.isSharedArrayBuffer, + ]; + } + function nativeExportsFromTable(table, native) { + const nativeLocal = { + registerDllBytes: table[0], + isSharedArrayBuffer: table[1], + }; + Object.assign(native, nativeLocal); + } + // eslint-disable-next-line @typescript-eslint/no-unused-vars + function interopExportsToTable(map) { + return []; + } + function interopExportsFromTable(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. + const loadedAssemblies = {}; + + var commonInfra = /*#__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; }, + getInternals: getInternals, + get interopExports() { return interopExports; }, + interopExportsFromTable: interopExportsFromTable, + interopExportsToTable: interopExportsToTable, + loadedAssemblies: loadedAssemblies, + get loaderExports() { return loaderExports; }, + loaderExportsFromTable: loaderExportsFromTable, + loaderExportsToTable: loaderExportsToTable, + get nativeExports() { return nativeExports; }, + nativeExportsFromTable: nativeExportsFromTable, + nativeExportsToTable: nativeExportsToTable, + get runtimeApi() { return runtimeApi; }, + get runtimeExports() { return runtimeExports; }, + runtimeExportsFromTable: runtimeExportsFromTable, + runtimeExportsToTable: runtimeExportsToTable, + setInternals: setInternals, + updateInternals: updateInternals, + updateInternalsImpl: updateInternalsImpl + }); + + // 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 (!SystemJS_RandomBytes["cryptoWarnOnce"]) { + Logger.warn("This engine doesn't support crypto.getRandomValues. Please use a modern version or provide polyfill for 'globalThis.crypto.getRandomValues'."); + SystemJS_RandomBytes["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 = nativeExports.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. + + var trimmableExports = /*#__PURE__*/Object.freeze({ + __proto__: null, + SystemJS_RandomBytes: SystemJS_RandomBytes + }); + + // Licensed to the .NET Foundation under one or more agreements. + // The .NET Foundation licenses this file to you under the MIT license. + 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) { + return false; + } + Module.HEAPU32[outDataStartPtr >> 2] = assembly.ptr; + // upper bits are cleared by the C caller + Module.HEAPU32[outSize >> 2] = assembly.length; + return true; + } + browserHostExternalAssemblyProbe["__deps"] = ["loadedAssemblies"]; + function browserHostResolveMain(exitCode) { + loaderExports.browserHostResolveMain(exitCode); + } + function browserHostRejectMain(reason) { + loaderExports.browserHostRejectMain(reason); + } + 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"); + } + //setEnvironmentVariable["__deps"] = ["setenv"]; + + // 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. + async function initialize(internals) { + const runtimeApiFunctions = { + 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 nativeExports = { + registerDllBytes, + isSharedArrayBuffer + }; + setInternals(internals); + Object.assign(internals.runtimeApi, runtimeApiFunctions); + Object.assign(nativeExports, nativeExports); + internals.nativeExportsTable = [...nativeExportsToTable(nativeExports)]; + internals.updates.push(updateInternalsImpl); + updateInternals(); + } + + var exchange = /*#__PURE__*/Object.freeze({ + __proto__: null, + _zero_region: _zero_region, + assert_int_in_range: assert_int_in_range, + browserHostExternalAssemblyProbe: browserHostExternalAssemblyProbe, + browserHostRejectMain: browserHostRejectMain, + browserHostResolveMain: browserHostResolveMain, + copyBytes: copyBytes, + exit: exit, + getHeapB32: getHeapB32, + getHeapB8: getHeapB8, + getHeapF32: getHeapF32, + getHeapF64: getHeapF64, + getHeapI16: getHeapI16, + getHeapI16_local: getHeapI16_local, + getHeapI32: getHeapI32, + getHeapI32_local: getHeapI32_local, + getHeapI52: getHeapI52, + getHeapI64Big: getHeapI64Big, + getHeapI8: getHeapI8, + getHeapU16: getHeapU16, + getHeapU16_local: getHeapU16_local, + getHeapU32: getHeapU32, + getHeapU32_local: getHeapU32_local, + getHeapU52: getHeapU52, + getHeapU8: getHeapU8, + initialize: initialize, + isSharedArrayBuffer: isSharedArrayBuffer, + localHeapViewF32: localHeapViewF32, + localHeapViewF64: localHeapViewF64, + localHeapViewI16: localHeapViewI16, + localHeapViewI32: localHeapViewI32, + localHeapViewI64Big: localHeapViewI64Big, + localHeapViewI8: localHeapViewI8, + localHeapViewU16: localHeapViewU16, + localHeapViewU32: localHeapViewU32, + localHeapViewU8: localHeapViewU8, + max_int64_big: max_int64_big, + min_int64_big: min_int64_big, + registerDllBytes: registerDllBytes, + runMain: runMain, + runMainAndExit: runMainAndExit, + setEnvironmentVariable: setEnvironmentVariable, + setHeapB32: setHeapB32, + setHeapB8: setHeapB8, + setHeapF32: setHeapF32, + setHeapF64: setHeapF64, + setHeapI16: setHeapI16, + setHeapI32: setHeapI32, + setHeapI32_unchecked: setHeapI32_unchecked, + setHeapI52: setHeapI52, + setHeapI64Big: setHeapI64Big, + setHeapI8: setHeapI8, + setHeapU16: setHeapU16, + setHeapU16_local: setHeapU16_local, + setHeapU16_unchecked: setHeapU16_unchecked, + setHeapU32: setHeapU32, + setHeapU32_unchecked: setHeapU32_unchecked, + setHeapU52: setHeapU52, + setHeapU8: setHeapU8, + sharedArrayBufferDefined: sharedArrayBufferDefined + }); + + // 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. + * It also implements part of public JS API related to memory and runtime hosting. + */ + // Exports that can be trimmed away by emscripten linker if not used. + function dotnetLibFactory() { + // Symbols that would be protected from emscripten linker + const commonInfraTransformed = { + Assert: Assert, + JSEngine: JSEngine, + Logger: Logger, + Module: Module, + runtimeApi: runtimeApi, + runtimeExports: runtimeExports, + nativeExports: nativeExports, + interopExports: interopExports, + loaderExports: loaderExports, + loadedAssemblies: loadedAssemblies, + loaderExportsFromTable: loaderExportsFromTable, + runtimeExportsFromTable: runtimeExportsFromTable, + nativeExportsFromTable: nativeExportsFromTable, + interopExportsFromTable: interopExportsFromTable, + nativeExportsToTable: nativeExportsToTable, + interopExportsToTable: interopExportsToTable, + setInternals: setInternals, + getInternals: getInternals, + updateInternals: updateInternals, + updateInternalsImpl: updateInternalsImpl, + }; + // Symbols that would be protected from emscripten linker + const exchangeTransformed = { + setHeapB32: setHeapB32, + setHeapB8: setHeapB8, + setHeapU8: setHeapU8, + setHeapU16: setHeapU16, + setHeapU32: setHeapU32, + setHeapI8: setHeapI8, + setHeapI16: setHeapI16, + setHeapI32: setHeapI32, + setHeapI52: setHeapI52, + setHeapU52: setHeapU52, + setHeapI64Big: setHeapI64Big, + setHeapF32: setHeapF32, + setHeapF64: setHeapF64, + getHeapB32: getHeapB32, + getHeapB8: getHeapB8, + getHeapU8: getHeapU8, + getHeapU16: getHeapU16, + getHeapU32: getHeapU32, + getHeapI8: getHeapI8, + getHeapI16: getHeapI16, + getHeapI32: getHeapI32, + getHeapI52: getHeapI52, + getHeapU52: getHeapU52, + getHeapI64Big: getHeapI64Big, + getHeapF32: getHeapF32, + getHeapF64: getHeapF64, + localHeapViewI8: localHeapViewI8, + localHeapViewI16: localHeapViewI16, + localHeapViewI32: localHeapViewI32, + localHeapViewI64Big: localHeapViewI64Big, + localHeapViewU8: localHeapViewU8, + localHeapViewU16: localHeapViewU16, + localHeapViewU32: localHeapViewU32, + localHeapViewF32: localHeapViewF32, + localHeapViewF64: localHeapViewF64, + isSharedArrayBuffer: isSharedArrayBuffer, + exit: exit, + runMain: runMain, + runMainAndExit: runMainAndExit, + setEnvironmentVariable: setEnvironmentVariable, + registerDllBytes: registerDllBytes, + browserHostExternalAssemblyProbe: browserHostExternalAssemblyProbe, + browserHostRejectMain: browserHostRejectMain, + browserHostResolveMain: browserHostResolveMain, + _zero_region: _zero_region, + assert_int_in_range: assert_int_in_range, + max_int64_big: max_int64_big, + min_int64_big: min_int64_big, + sharedArrayBufferDefined: sharedArrayBufferDefined, + }; + const moduleDeps = ["$ENV"]; + for (const exportName of Reflect.ownKeys(commonInfraTransformed)) { + const emName = "$" + exportName.toString(); + commonInfraTransformed[emName] = commonInfra[exportName]; + moduleDeps.push(emName); + } + for (const exportName of Reflect.ownKeys(exchangeTransformed)) { + const emName = "$" + exportName.toString(); + exchangeTransformed[emName] = exchange[exportName]; + moduleDeps.push(emName); + } + const trimmableDeps = {}; + for (const exportName of Reflect.ownKeys(trimmableExports)) { + const emName = exportName.toString() + "__deps"; + const deps = trimmableExports[exportName]["__deps"]; + if (deps) { + trimmableDeps[emName] = deps; + } + } + const lib = { + $DOTNET: { + selfInitialize: () => { + if (typeof dotnetInternals !== "undefined") { + DOTNET.dotnetInternals = dotnetInternals; + DOTNET.initialize(dotnetInternals); + if (dotnetInternals.config && dotnetInternals.config.environmentVariables) { + Object.assign(ENV, dotnetInternals.config.environmentVariables); + } + } + }, + initialize: initialize, + }, + "$DOTNET__postset": "DOTNET.selfInitialize();", + "$DOTNET__deps": moduleDeps, + ...commonInfraTransformed, + ...exchangeTransformed, + ...trimmableExports, + ...trimmableDeps + }; + autoAddDeps(lib, "$DOTNET"); + addToLibrary(lib); + } + dotnetLibFactory(); + + exports.commonInfra = commonInfra; + exports.exchange = exchange; + exports.trimmableExports = trimmableExports; + + 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..88ac624e7643ac --- /dev/null +++ b/src/native/libs/System.Runtime.InteropServices.JavaScript.Native/ReadMe.md @@ -0,0 +1,16 @@ +# System.Runtime.InteropServices.JavaScript + +Is TypeScript project that is compiled via `src\native\libs\rollup.config.js` into Emscripten library. +And native library compiled by CMake into `System.JavaScript.a` as part of `/src/native/libs/CMakeLists.txt` + +# System.Runtime.InteropServices.JavaScript.ts -> dotnet.native.js + +This is root of **Emscripten library** that would become part of `dotnet.runtime.js` +It implements native part of interop between JS and .NET +Functions exported from `runtime/native-exports.ts` will be added into `dotnet.native.js` in trimmable way. + +# ententrypoints.c -> System.Runtime.InteropServices.JavaScript.a -> dotnet.native.wasm + +This is making functions from `runtime/native-exports.ts` visible in C code. + +**TODOWASM**: This is preventing trimming and should be replaced by generated P/Invokes that are IL trimmed first. 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..3bc4a355ac01e3 --- /dev/null +++ b/src/native/libs/System.Runtime.InteropServices.JavaScript.Native/dotnet.runtime.js @@ -0,0 +1,461 @@ +//! 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 ProductVersion = "10.0.0-dev"; + +var BuildConfiguration = "Debug"; + +var GitHash = "becd20635d51b17f7f344df90775c63e7e744d11"; + +// 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. +let JSEngine; +let Module; +let runtimeApi; +let Logger = {}; +let Assert = {}; +let loaderExports = {}; +let runtimeExports = {}; +let nativeExports = {}; +let interopExports = {}; +let dotnetInternals; +function getInternals() { + return dotnetInternals; +} +function setInternals(internal) { + dotnetInternals = internal; + runtimeApi = dotnetInternals.runtimeApi; + Module = dotnetInternals.runtimeApi.Module; +} +function updateInternals() { + if (dotnetInternals.updates === undefined) { + dotnetInternals.updates = []; + } + for (const updateImpl of dotnetInternals.updates) { + updateImpl(); + } +} +function updateInternalsImpl() { + if (!JSEngine) { + 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; + 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, + }; + } + if (Object.keys(loaderExports).length === 0 && dotnetInternals.loaderExportsTable) { + loaderExports = {}; + Logger = {}; + Assert = {}; + loaderExportsFromTable(dotnetInternals.loaderExportsTable, Logger, Assert, loaderExports); + } + if (Object.keys(runtimeExports).length === 0 && dotnetInternals.runtimeExportsTable) { + runtimeExports = {}; + runtimeExportsFromTable(dotnetInternals.runtimeExportsTable, runtimeExports); + } + if (Object.keys(nativeExports).length === 0 && dotnetInternals.nativeExportsTable) { + nativeExports = {}; + nativeExportsFromTable(dotnetInternals.nativeExportsTable, nativeExports); + } + if (Object.keys(interopExports).length === 0 && dotnetInternals.interopExportsTable) { + interopExports = {}; + interopExportsFromTable(dotnetInternals.interopExportsTable, interopExports); + } +} +/** + * 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 loaderExportsToTable(logger, assert, loaderExports) { + return [ + logger.info, + logger.warn, + logger.error, + assert.check, + loaderExports.browserHostResolveMain, + loaderExports.browserHostRejectMain, + loaderExports.getRunMainPromise, + ]; +} +function loaderExportsFromTable(table, logger, assert, loaderExports) { + const loggerLocal = { + info: table[0], + warn: table[1], + error: table[2], + }; + const assertLocal = { + check: table[3], + }; + const loaderExportsLocal = { + browserHostResolveMain: table[4], + browserHostRejectMain: table[5], + getRunMainPromise: table[6], + }; + Object.assign(logger, loggerLocal); + Object.assign(assert, assertLocal); + Object.assign(loaderExports, loaderExportsLocal); +} +// eslint-disable-next-line @typescript-eslint/no-unused-vars +function runtimeExportsToTable(map) { + return []; +} +function runtimeExportsFromTable(table, runtime) { + Object.assign(runtime, {}); +} +function nativeExportsToTable(map) { + return [ + map.registerDllBytes, + map.isSharedArrayBuffer, + ]; +} +function nativeExportsFromTable(table, native) { + const nativeLocal = { + registerDllBytes: table[0], + isSharedArrayBuffer: table[1], + }; + Object.assign(native, nativeLocal); +} +// eslint-disable-next-line @typescript-eslint/no-unused-vars +function interopExportsToTable(map) { + return []; +} +function interopExportsFromTable(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. +// 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. +// 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. +/// 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. +function initialize() { + 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 = { + getRunMainPromise, + browserHostRejectMain, + browserHostResolveMain, + }; + const logger = { + info, + warn, + error, + }; + const assert = { + check, + }; + Object.assign(runtimeApi, runtimeApiFunctions); + Object.assign(Logger, logger); + Object.assign(Assert, assert); + Object.assign(loaderExports, loaderFunctions); + dotnetInternals.loaderExportsTable = [...loaderExportsToTable(Logger, Assert, loaderExports)]; + updates.push(updateInternalsImpl); + updateInternals(); + return runtimeApi; +} + +// 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..dd62b2c63e7b30 --- /dev/null +++ b/src/native/libs/System.Runtime.InteropServices.JavaScript.Native/libSystem.Runtime.InteropServices.JavaScript.Native.js @@ -0,0 +1,236 @@ +//! 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 libSystemRuntimeInteropServicesJavaScriptNativeBrowserJS = (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 JSEngine; + let Module; + let runtimeApi; + let Logger = {}; + let Assert = {}; + let loaderExports = {}; + let runtimeExports = {}; + let nativeExports = {}; + let interopExports = {}; + let dotnetInternals; + function getInternals() { + return dotnetInternals; + } + function setInternals(internal) { + dotnetInternals = internal; + runtimeApi = dotnetInternals.runtimeApi; + Module = dotnetInternals.runtimeApi.Module; + } + function updateInternals() { + if (dotnetInternals.updates === undefined) { + dotnetInternals.updates = []; + } + for (const updateImpl of dotnetInternals.updates) { + updateImpl(); + } + } + function updateInternalsImpl() { + if (!JSEngine) { + 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; + 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, + }; + } + if (Object.keys(loaderExports).length === 0 && dotnetInternals.loaderExportsTable) { + loaderExports = {}; + Logger = {}; + Assert = {}; + loaderExportsFromTable(dotnetInternals.loaderExportsTable, Logger, Assert, loaderExports); + } + if (Object.keys(runtimeExports).length === 0 && dotnetInternals.runtimeExportsTable) { + runtimeExports = {}; + runtimeExportsFromTable(dotnetInternals.runtimeExportsTable, runtimeExports); + } + if (Object.keys(nativeExports).length === 0 && dotnetInternals.nativeExportsTable) { + nativeExports = {}; + nativeExportsFromTable(dotnetInternals.nativeExportsTable, nativeExports); + } + if (Object.keys(interopExports).length === 0 && dotnetInternals.interopExportsTable) { + interopExports = {}; + interopExportsFromTable(dotnetInternals.interopExportsTable, interopExports); + } + } + /** + * 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 loaderExportsToTable(logger, assert, loaderExports) { + return [ + logger.info, + logger.warn, + logger.error, + assert.check, + loaderExports.browserHostResolveMain, + loaderExports.browserHostRejectMain, + loaderExports.getRunMainPromise, + ]; + } + function loaderExportsFromTable(table, logger, assert, loaderExports) { + const loggerLocal = { + info: table[0], + warn: table[1], + error: table[2], + }; + const assertLocal = { + check: table[3], + }; + const loaderExportsLocal = { + browserHostResolveMain: table[4], + browserHostRejectMain: table[5], + getRunMainPromise: table[6], + }; + Object.assign(logger, loggerLocal); + Object.assign(assert, assertLocal); + Object.assign(loaderExports, loaderExportsLocal); + } + // eslint-disable-next-line @typescript-eslint/no-unused-vars + function runtimeExportsToTable(map) { + return []; + } + function runtimeExportsFromTable(table, runtime) { + Object.assign(runtime, {}); + } + function nativeExportsToTable(map) { + return [ + map.registerDllBytes, + map.isSharedArrayBuffer, + ]; + } + function nativeExportsFromTable(table, native) { + const nativeLocal = { + registerDllBytes: table[0], + isSharedArrayBuffer: table[1], + }; + Object.assign(native, nativeLocal); + } + // eslint-disable-next-line @typescript-eslint/no-unused-vars + function interopExportsToTable(map) { + return []; + } + function interopExportsFromTable(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; }, + getInternals: getInternals, + get interopExports() { return interopExports; }, + interopExportsFromTable: interopExportsFromTable, + interopExportsToTable: interopExportsToTable, + get loaderExports() { return loaderExports; }, + loaderExportsFromTable: loaderExportsFromTable, + loaderExportsToTable: loaderExportsToTable, + get nativeExports() { return nativeExports; }, + nativeExportsFromTable: nativeExportsFromTable, + nativeExportsToTable: nativeExportsToTable, + get runtimeApi() { return runtimeApi; }, + get runtimeExports() { return runtimeExports; }, + runtimeExportsFromTable: runtimeExportsFromTable, + runtimeExportsToTable: runtimeExportsToTable, + setInternals: setInternals, + updateInternals: updateInternals, + updateInternalsImpl: updateInternalsImpl + }); + + // Licensed to the .NET Foundation under one or more agreements. + // The .NET Foundation licenses this file to you under the MIT license. + async function initialize(internals) { + const interopExportsFunctions = {}; + Object.assign(interopExports, interopExportsFunctions); + internals.interopExportsTable = [...interopExportsToTable(interopExportsFunctions)]; + internals.updates.push(updateInternalsImpl); + updateInternals(); + } + + var nativeExchange = /*#__PURE__*/Object.freeze({ + __proto__: null, + initialize: initialize + }); + + // 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; + } + SystemInteropJS_InvokeJSImportST["__deps"] = ["loadedAssemblies"]; + + var trimmableExports = /*#__PURE__*/Object.freeze({ + __proto__: null, + SystemInteropJS_InvokeJSImportST: SystemInteropJS_InvokeJSImportST + }); + + // 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 DotnetInteropLibFactory() { + // Symbols that would be protected from emscripten linker + const moduleDeps = ["$DOTNET"]; + const trimmableDeps = {}; + for (const exportName of Reflect.ownKeys(trimmableExports)) { + const emName = exportName.toString() + "__deps"; + const deps = trimmableExports[exportName]["__deps"]; + if (deps) { + trimmableDeps[emName] = deps; + } + } + const lib = { + $DOTNET_INTEROP: { + selfInitialize: () => { + if (typeof dotnetInternals !== "undefined") { + DOTNET_INTEROP.dotnetInternals = dotnetInternals; + DOTNET_INTEROP.initialize(dotnetInternals); + } + }, + initialize: initialize, + }, + "$DOTNET_INTEROP__deps": moduleDeps, + "$DOTNET_INTEROP__postset": "DOTNET_INTEROP.selfInitialize();", + ...trimmableExports, + ...trimmableDeps, + }; + autoAddDeps(lib, "$DOTNET_INTEROP"); + addToLibrary(lib); + } + DotnetInteropLibFactory(); + + exports.commonInfra = crossModule; + exports.exchange = nativeExchange; + exports.trimmableExports = trimmableExports; + + 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..05e1734a1f50f2 --- /dev/null +++ b/src/native/package.json @@ -0,0 +1,45 @@ +{ + "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": "node rollup.config.js", + "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.config.defines.js b/src/native/rollup.config.defines.js new file mode 100644 index 00000000000000..47db8df4d7347d --- /dev/null +++ b/src/native/rollup.config.defines.js @@ -0,0 +1,30 @@ +//! Licensed to the .NET Foundation under one or more agreements. +//! The .NET Foundation licenses this file to you under the MIT license. + +import gitCommitInfo from "git-commit-info"; + +const productVersion = process.env.ProductVersion || "10.0.0-dev"; +export const configuration = process.env.Configuration || "Debug"; +export const artifactsObjDir = process.env.ArtifactsObjDir ? process.env.ArtifactsObjDir.replace(/"/g, "") : "../../artifacts/obj"; +export const isContinuousIntegrationBuild = process.env.ContinuousIntegrationBuild === "true" ? true : false; +export const isDebug = configuration !== "Release"; + +export const banner = "//! Licensed to the .NET Foundation under one or more agreements.\n//! The .NET Foundation licenses this file to you under the MIT license.\n//! This is generated file, see src/native/libs/Browser/rollup.config.defines.js\n\n"; +export const banner_dts = banner + "//! This is not considered public API with backward compatibility guarantees. \n"; +export const keep_classnames = /(ManagedObject|ManagedError|Span|ArraySegment)/; +export const externalDependencies = ["module", "process", "perf_hooks", "node:crypto"]; + +let gitHash; +try { + const gitInfo = gitCommitInfo(); + gitHash = gitInfo.hash; +} catch (e) { + gitHash = "unknown"; +} + +export const envConstants = { + productVersion, + configuration, + gitHash, + isContinuousIntegrationBuild, +}; diff --git a/src/native/rollup.config.js b/src/native/rollup.config.js new file mode 100644 index 00000000000000..2e6aa0e4dea1f2 --- /dev/null +++ b/src/native/rollup.config.js @@ -0,0 +1,20 @@ +//! 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 { artifactsObjDir, configuration } from "./rollup.config.defines.js" + +/** + * This would be replace by real rollup with TypeScript compilation in next iteration + */ + +await fs.copyFile("./corehost/browserhost/loader/dotnet.d.ts", + artifactsObjDir + `/coreclr/browser.wasm.${configuration}/corehost/dotnet.d.ts`); +await fs.copyFile("./corehost/browserhost/loader/dotnet.js", + artifactsObjDir + `/coreclr/browser.wasm.${configuration}/corehost/dotnet.js`); +await fs.copyFile("./libs/System.Native.Browser/libSystem.Native.Browser.js", + artifactsObjDir + `/native/browser-${configuration}-wasm/System.Native.Browser/libSystem.Native.Browser.js`); +await fs.copyFile("./libs/System.Runtime.InteropServices.JavaScript.Native/dotnet.runtime.js", + artifactsObjDir + `/native/browser-${configuration}-wasm/System.Runtime.InteropServices.JavaScript.Native/dotnet.runtime.js`); +await fs.copyFile("./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`); diff --git a/src/native/rollup.config.plugins.js b/src/native/rollup.config.plugins.js new file mode 100644 index 00000000000000..f11962eba54722 --- /dev/null +++ b/src/native/rollup.config.plugins.js @@ -0,0 +1,128 @@ +//! Licensed to the .NET Foundation under one or more agreements. +//! The .NET Foundation licenses this file to you under the MIT license. + +import { createHash } from "crypto"; +import { readFile, writeFile, mkdir } from "fs/promises"; +import virtual from "@rollup/plugin-virtual"; +import * as fs from "fs"; +import * as path from "path"; +import terser from "@rollup/plugin-terser"; + +import { isContinuousIntegrationBuild, keep_classnames } from "./rollup.config.defines.js" + +export const terserPlugin = () => terser({ + compress: { + defaults: true, + passes: 2, + drop_debugger: false, // we invoke debugger + drop_console: false, // we log to console + keep_classnames, + }, + mangle: { + keep_classnames, + }, +}); + +// this would create .sha256 file next to the output file, so that we do not touch datetime of the file if it's same -> faster incremental build. +export const writeOnChangePlugin = () => ({ + name: "writeOnChange", + generateBundle: writeWhenChanged +}); + +// force always unix line ending +export const alwaysLF = () => ({ + name: "writeOnChange", + generateBundle: (options, bundle) => { + const name = Object.keys(bundle)[0]; + const asset = bundle[name]; + const code = asset.code; + asset.code = code.replace(/\r/g, ""); + } +}); + +async function writeWhenChanged(options, bundle) { + try { + const name = Object.keys(bundle)[0]; + const asset = bundle[name]; + const code = asset.code; + const hashFileName = options.file + ".sha256"; + const oldHashExists = await checkFileExists(hashFileName); + const oldFileExists = await checkFileExists(options.file); + + const newHash = createHash("sha256").update(code).digest("hex"); + + let isOutputChanged = true; + if (oldHashExists && oldFileExists) { + const oldHash = await readFile(hashFileName, { encoding: "ascii" }); + isOutputChanged = oldHash !== newHash; + } + if (isOutputChanged) { + const dir = path.dirname(options.file); + if (!await checkFileExists(dir)) { + await mkdir(dir, { recursive: true }); + } + await writeFile(hashFileName, newHash); + } else { + // this.warn('No change in ' + options.file) + delete bundle[name]; + } + } catch (ex) { + this.warn(ex.toString()); + } +} + +function checkFileExists(file) { + return fs.promises.access(file, fs.constants.F_OK) + .then(() => true) + .catch(() => false); +} + +export function onwarn(warning) { + if (warning.code === "CIRCULAR_DEPENDENCY") { + return; + } + + if (warning.code === "UNRESOLVED_IMPORT" && warning.exporter === "process") { + return; + } + + if (warning.code === "PLUGIN_WARNING" && warning.message.indexOf("sourcemap") !== -1) { + return; + } + + // eslint-disable-next-line no-console + console.warn(`(!) ${warning.toString()} ${warning.code}`); +} + +export function consts(dict) { + // implement rollup-plugin-const in terms of @rollup/plugin-virtual + // It's basically the same thing except "consts" names all its modules with a "consts:" prefix, + // and the virtual module always exports a single default binding (the const value). + + let newDict = {}; + for (const k in dict) { + const newKey = "consts:" + k; + const newVal = JSON.stringify(dict[k]); + newDict[newKey] = `export default ${newVal}`; + } + return virtual(newDict); +} + +const locationCache = {}; +export function sourcemapPathTransform(relativeSourcePath, sourcemapPath) { + let res = locationCache[relativeSourcePath]; + if (res === undefined) { + if (!isContinuousIntegrationBuild) { + const sourcePath = path.resolve( + path.dirname(sourcemapPath), + relativeSourcePath + ); + res = `file:///${sourcePath.replace(/\\/g, "/")}`; + } else { + relativeSourcePath = relativeSourcePath.substring(12); + res = `https://raw.githubusercontent.com/dotnet/runtime/${gitHash}/${relativeSourcePath}`; + } + locationCache[relativeSourcePath] = res; + } + return res; +} diff --git a/src/native/tsconfig.json b/src/native/tsconfig.json new file mode 100644 index 00000000000000..8e502ea48ec777 --- /dev/null +++ b/src/native/tsconfig.json @@ -0,0 +1,33 @@ +{ + "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": [ + "./corehost/browserhost/loader", + "./libs/Common/JavaScript", + "./libs/System.Native.Browser", + "./libs/System.Runtime.InteropServices.JavaScript.Native", + "../../artifacts/bin/native/generated" + ] + }, + "exclude": [ + "./corehost/loader/dotnet.d.ts" + ] +} \ No newline at end of file From 29bfc732b4527f4952508db35dce7ab7eb43fc23 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Sat, 20 Sep 2025 01:57:43 +0200 Subject: [PATCH 02/25] readme feedback --- src/native/corehost/browserhost/ReadMe.md | 25 +++++++++++++++++++ .../corehost/browserhost/loader/ReadMe.md | 15 ----------- .../libs/System.Native.Browser/ReadMe.md | 22 ++++++++-------- .../ReadMe.md | 23 ++++++++--------- 4 files changed, 47 insertions(+), 38 deletions(-) create mode 100644 src/native/corehost/browserhost/ReadMe.md delete mode 100644 src/native/corehost/browserhost/loader/ReadMe.md diff --git a/src/native/corehost/browserhost/ReadMe.md b/src/native/corehost/browserhost/ReadMe.md new file mode 100644 index 00000000000000..1c50d3adce60a0 --- /dev/null +++ b/src/native/corehost/browserhost/ReadMe.md @@ -0,0 +1,25 @@ +# browserhost + +Is **Emscripten application** and **JavaScript wrapper and a loader** + +## 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 TypeScript project that is compiled via `src\native\rollup.config.js`. +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** + +- `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` diff --git a/src/native/corehost/browserhost/loader/ReadMe.md b/src/native/corehost/browserhost/loader/ReadMe.md deleted file mode 100644 index 35479644c1a6de..00000000000000 --- a/src/native/corehost/browserhost/loader/ReadMe.md +++ /dev/null @@ -1,15 +0,0 @@ -# System.JavaScript.Loader - -Is TypeScript project that is compiled via `src\native\libs\Browser\rollup.config.js` into JavaScript ES6 module. - -## Dotnet.Loader.ts -> dotnet.js - -`System.JavaScript.Loader.ts` is root of **JavaScript module** that would become of `dotnet.js`. -It implements host for the browser together with `src/native/corehost/browserhost`. -It exposes the public JS runtime APIs that is implemented in `Dotnet.Runtime.ts`. -It's good to keep this file small. - - -And one native library compiled by CMake into `System.JavaScript.a` as part of `/src/native/libs/CMakeLists.txt` - - diff --git a/src/native/libs/System.Native.Browser/ReadMe.md b/src/native/libs/System.Native.Browser/ReadMe.md index 6c7136d9c5ee9a..fa7aed78fc516e 100644 --- a/src/native/libs/System.Native.Browser/ReadMe.md +++ b/src/native/libs/System.Native.Browser/ReadMe.md @@ -1,15 +1,15 @@ -# System.JavaScript +# System.Native.Browser -Is TypeScript project that is compiled via `src\native\libs\rollup.config.js` into Emscripten JS library. -And a native library compiled by CMake into `System.JavaScript.a` as part of `/src/native/libs/CMakeLists.txt` +This library implements PAL for the VM/runtime. +It also implements part of public JS API related to memory and runtime hosting. -## System.JavaScript.ts -> dotnet.native.js +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` -This is root of **Emscripten library** that would become part of `dotnet.runtime.js` -It implements native parts of PAL for the VM/runtime. +## Emscripten library +- `libSystem.Native.Browser.ts` compiled -> `libSystem.Native.Browser.js` linked ->`dotnet.native.js` +- `ententrypoints.c` compiled -> `libSystem.Native.Browser.a` linked -> `dotnet.native.wasm` -## ententrypoints.c -> System.JavaScript.a -> dotnet.native.wasm - -This is making functions from `runtime/native-exports.ts` visible in C code. - -**TODOWASM**: This is preventing trimming and should be replaced by generated P/Invokes that are IL trimmed first. +TypeScript is driven by `src/native/rollup.config.js` +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/ReadMe.md b/src/native/libs/System.Runtime.InteropServices.JavaScript.Native/ReadMe.md index 88ac624e7643ac..216bd296a24960 100644 --- a/src/native/libs/System.Runtime.InteropServices.JavaScript.Native/ReadMe.md +++ b/src/native/libs/System.Runtime.InteropServices.JavaScript.Native/ReadMe.md @@ -1,16 +1,15 @@ -# System.Runtime.InteropServices.JavaScript +# System.Runtime.InteropServices.JavaScript.Native -Is TypeScript project that is compiled via `src\native\libs\rollup.config.js` into Emscripten library. -And native library compiled by CMake into `System.JavaScript.a` as part of `/src/native/libs/CMakeLists.txt` +This library implements interop between JS and .NET +It also implements public JS API related JS interop. -# System.Runtime.InteropServices.JavaScript.ts -> dotnet.native.js +## Emscripten library +- `libSystem.Runtime.InteropServices.JavaScript.Native.ts` compiled -> `libSystem.Runtime.InteropServices.JavaScript.Native.js` linked -> `dotnet.native.js` +- `ententrypoints.c` compiled -> `libSystem.Runtime.InteropServices.JavaScript.Native.a` linked -> `dotnet.native.wasm` -This is root of **Emscripten library** that would become part of `dotnet.runtime.js` -It implements native part of interop between JS and .NET -Functions exported from `runtime/native-exports.ts` will be added into `dotnet.native.js` in trimmable way. +## ES6 JavaScript module +- `dotnet.runtime.ts` compiled -> `dotnet.runtime.js` -# ententrypoints.c -> System.Runtime.InteropServices.JavaScript.a -> dotnet.native.wasm - -This is making functions from `runtime/native-exports.ts` visible in C code. - -**TODOWASM**: This is preventing trimming and should be replaced by generated P/Invokes that are IL trimmed first. +TypeScript is driven by `src/native/rollup.config.js` +Emscripten compilations is part of `/src/native/libs/CMakeLists.txt` +Final static linking happens in `/src/native/corehost/browserhost/CMakeLists.txt` From 6b979942a5ce2b1b05ebe77acd61d33dca488859 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Sat, 20 Sep 2025 02:03:25 +0200 Subject: [PATCH 03/25] cleanup --- src/native/corehost/CMakeLists.txt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/native/corehost/CMakeLists.txt b/src/native/corehost/CMakeLists.txt index cc09f5bd35788d..663455d6a0ba8f 100644 --- a/src/native/corehost/CMakeLists.txt +++ b/src/native/corehost/CMakeLists.txt @@ -3,10 +3,6 @@ project(corehost) include(../../../eng/native/configurepaths.cmake) include(${CLR_ENG_NATIVE_DIR}/configurecompiler.cmake) -if(CLR_CMAKE_TARGET_BROWSER) -# include_directories(${CLR_SRC_NATIVE_DIR}/libs/System.Native.Browser) -# include_directories(${CLR_SRC_NATIVE_DIR}/libs/System.Runtime.InteropServices.JavaScript.Native) -endif(CLR_CMAKE_TARGET_BROWSER) set(COREHOST_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}") From 91365d2a0ee677b222b17b830b9cbfab8ef710f8 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Sat, 20 Sep 2025 02:07:05 +0200 Subject: [PATCH 04/25] more --- src/native/corehost/browserhost/ReadMe.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/native/corehost/browserhost/ReadMe.md b/src/native/corehost/browserhost/ReadMe.md index 1c50d3adce60a0..971b462eda3f15 100644 --- a/src/native/corehost/browserhost/ReadMe.md +++ b/src/native/corehost/browserhost/ReadMe.md @@ -1,6 +1,6 @@ # browserhost -Is **Emscripten application** and **JavaScript wrapper and a loader** +Is **Emscripten application** and **JavaScript wrapper and a loader** for it. ## Loader dotnet.js @@ -15,7 +15,7 @@ It's **JavaScript ES6 module** ## Native host Implements native part of the CoreCLR host and exposes it as an internal JavaScript interface to the loader. -It is **Emscripten application** +It is **Emscripten application** statically linked from libraries. - `libBrowserHost.js` linked -> `dotnet.native.js` - `libSystem.Native.Browser.js` linked -> `dotnet.native.js` From befa52aa744f63666033a163df0352c1afe96c38 Mon Sep 17 00:00:00 2001 From: Pavel Savara Date: Sat, 20 Sep 2025 08:29:07 +0200 Subject: [PATCH 05/25] Update src/native/corehost/browserhost/ReadMe.md Co-authored-by: Jan Kotas --- src/native/corehost/browserhost/ReadMe.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/native/corehost/browserhost/ReadMe.md b/src/native/corehost/browserhost/ReadMe.md index 971b462eda3f15..d408e16e6ea438 100644 --- a/src/native/corehost/browserhost/ReadMe.md +++ b/src/native/corehost/browserhost/ReadMe.md @@ -1,6 +1,6 @@ # browserhost -Is **Emscripten application** and **JavaScript wrapper and a loader** for it. +**Emscripten application** and **JavaScript wrapper and a loader** for it. ## Loader dotnet.js From 0318db5958a3118a5f9d0e5a898569c7abc35dee Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Sat, 20 Sep 2025 16:15:51 +0200 Subject: [PATCH 06/25] don't build System.Native.Browser for mono --- src/native/libs/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/native/libs/CMakeLists.txt b/src/native/libs/CMakeLists.txt index 4ce3c665f8a919..8edbb8410acc73 100644 --- a/src/native/libs/CMakeLists.txt +++ b/src/native/libs/CMakeLists.txt @@ -108,7 +108,7 @@ endif () add_subdirectory(System.IO.Compression.Native) -if (CLR_CMAKE_TARGET_BROWSER) +if (CLR_CMAKE_TARGET_BROWSER AND NOT MONO_LIB_NAME) add_subdirectory(System.Native.Browser) add_subdirectory(System.Runtime.InteropServices.JavaScript.Native) endif () From 6342dc505b91987743de1241a087b96f776134e6 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Sat, 20 Sep 2025 16:58:35 +0200 Subject: [PATCH 07/25] - build JS libs only when BUILD_LIBS_NATIVE_BROWSER is set (not for Mono) - install rollup via System.Native.Browser-NpmInstall --- src/coreclr/CMakeLists.txt | 2 ++ src/native/libs/CMakeLists.txt | 3 +- .../libs/System.Native.Browser/CMakeLists.txt | 34 +++++++++++++++++-- 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/src/coreclr/CMakeLists.txt b/src/coreclr/CMakeLists.txt index 21f61575b3be16..aa6ad5b75b5ac4 100644 --- a/src/coreclr/CMakeLists.txt +++ b/src/coreclr/CMakeLists.txt @@ -71,6 +71,8 @@ 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 set(GEN_PINVOKE 0) + # TODOWASM 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() diff --git a/src/native/libs/CMakeLists.txt b/src/native/libs/CMakeLists.txt index 8edbb8410acc73..75cc2055d6e1fb 100644 --- a/src/native/libs/CMakeLists.txt +++ b/src/native/libs/CMakeLists.txt @@ -108,7 +108,8 @@ endif () add_subdirectory(System.IO.Compression.Native) -if (CLR_CMAKE_TARGET_BROWSER AND NOT MONO_LIB_NAME) +# 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 () diff --git a/src/native/libs/System.Native.Browser/CMakeLists.txt b/src/native/libs/System.Native.Browser/CMakeLists.txt index 2b087862339ff2..34cffaa6670c72 100644 --- a/src/native/libs/System.Native.Browser/CMakeLists.txt +++ b/src/native/libs/System.Native.Browser/CMakeLists.txt @@ -23,6 +23,8 @@ file(GLOB_RECURSE ROLLUP_TS_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/../Common/JavaScript/*.js" "${CMAKE_CURRENT_SOURCE_DIR}/../../corehost/browserhost/*.ts" "${CMAKE_CURRENT_SOURCE_DIR}/../../corehost/browserhost/*.js" + "${CMAKE_CURRENT_SOURCE_DIR}../../package.json" + "${CMAKE_CURRENT_SOURCE_DIR}../../tsconfig.json" ) set(ROLLUP_OUTPUTS @@ -37,10 +39,11 @@ set(ROLLUP_OUTPUTS "${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Runtime.InteropServices.JavaScript.Native/libSystem.Runtime.InteropServices.JavaScript.Native.js.map" ) +# TODOWASM pass env variables to rollup: ProductVersion, Configuration, ArtifactsObjDir, ContinuousIntegrationBuild add_custom_command( OUTPUT ${ROLLUP_OUTPUTS} COMMAND npm run rollup - WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/.." + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../.." COMMENT "Running 'npm run rollup' to generate JavaScript bundles" DEPENDS ${ROLLUP_TS_SOURCES} VERBATIM @@ -50,4 +53,31 @@ add_custom_target(System.Native.Browser-Rollup DEPENDS ${ROLLUP_OUTPUTS} ) -add_dependencies(System.Native.Browser-Static System.Native.Browser-Rollup) \ No newline at end of file +add_dependencies(System.Native.Browser-Static System.Native.Browser-Rollup) + +set(NPM_INSTALL_OUTPUTS + "${CMAKE_CURRENT_SOURCE_DIR}/../../node_modules/.bin/rollup" + "${CMAKE_CURRENT_SOURCE_DIR}/../../node_modules/.bin/terser" + "${CMAKE_CURRENT_SOURCE_DIR}/../../node_modules/.bin/tsc" + "${CMAKE_CURRENT_SOURCE_DIR}/../../node_modules/.bin/eslint" + "${CMAKE_CURRENT_SOURCE_DIR}/../../node_modules/.npm-stamp" +) + +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} +) From b8c628dbe9dfc087b869ca94aa9f6fd4b6bb00bf Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Sat, 20 Sep 2025 18:02:14 +0200 Subject: [PATCH 08/25] more cmake --- .../libs/System.Native.Browser/CMakeLists.txt | 1 + src/native/rollup.config.js | 29 ++++++++++++------- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/native/libs/System.Native.Browser/CMakeLists.txt b/src/native/libs/System.Native.Browser/CMakeLists.txt index 34cffaa6670c72..604e5cebd2d586 100644 --- a/src/native/libs/System.Native.Browser/CMakeLists.txt +++ b/src/native/libs/System.Native.Browser/CMakeLists.txt @@ -25,6 +25,7 @@ file(GLOB_RECURSE ROLLUP_TS_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/../../corehost/browserhost/*.js" "${CMAKE_CURRENT_SOURCE_DIR}../../package.json" "${CMAKE_CURRENT_SOURCE_DIR}../../tsconfig.json" + "${CMAKE_CURRENT_SOURCE_DIR}/../../node_modules/.npm-stamp" ) set(ROLLUP_OUTPUTS diff --git a/src/native/rollup.config.js b/src/native/rollup.config.js index 2e6aa0e4dea1f2..05290e0d14b47b 100644 --- a/src/native/rollup.config.js +++ b/src/native/rollup.config.js @@ -2,19 +2,28 @@ //! The .NET Foundation licenses this file to you under the MIT license. import { promises as fs } from "fs"; +import path from "path"; import { artifactsObjDir, configuration } from "./rollup.config.defines.js" /** * This would be replace by real rollup with TypeScript compilation in next iteration */ -await fs.copyFile("./corehost/browserhost/loader/dotnet.d.ts", - artifactsObjDir + `/coreclr/browser.wasm.${configuration}/corehost/dotnet.d.ts`); -await fs.copyFile("./corehost/browserhost/loader/dotnet.js", - artifactsObjDir + `/coreclr/browser.wasm.${configuration}/corehost/dotnet.js`); -await fs.copyFile("./libs/System.Native.Browser/libSystem.Native.Browser.js", - artifactsObjDir + `/native/browser-${configuration}-wasm/System.Native.Browser/libSystem.Native.Browser.js`); -await fs.copyFile("./libs/System.Runtime.InteropServices.JavaScript.Native/dotnet.runtime.js", - artifactsObjDir + `/native/browser-${configuration}-wasm/System.Runtime.InteropServices.JavaScript.Native/dotnet.runtime.js`); -await fs.copyFile("./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 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`], + ["./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`] +]; + +for (const [src, dest] of copies) { + const destDir = path.dirname(dest); + await fs.mkdir(destDir, { recursive: true }); + await fs.copyFile(src, dest); +} From c4cfad7116ff0338736e84642fb61afc91527373 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Sun, 21 Sep 2025 19:47:08 +0200 Subject: [PATCH 09/25] rollup for release config --- .../corehost/browserhost/CMakeLists.txt | 4 ++-- .../libs/System.Native.Browser/CMakeLists.txt | 19 +++++++++++++------ src/native/rollup.config.defines.js | 12 +++++++----- src/native/rollup.config.js | 6 ++++-- 4 files changed, 26 insertions(+), 15 deletions(-) diff --git a/src/native/corehost/browserhost/CMakeLists.txt b/src/native/corehost/browserhost/CMakeLists.txt index f95c6cb9dc9c69..252dc009bae265 100644 --- a/src/native/corehost/browserhost/CMakeLists.txt +++ b/src/native/corehost/browserhost/CMakeLists.txt @@ -88,9 +88,9 @@ set(SAMPLE_ASSETS # ${CLR_ARTIFACTS_OBJ_DIR}/sfx-finish/${CMAKE_BUILD_TYPE}/net10.0-browser/illink-wasm/System.Threading.dll # ${CLR_ARTIFACTS_BIN_DIR}/artifacts/bin/HelloWorld/${CMAKE_BUILD_TYPE}/net10.0/win-x64/HelloWorld.dll ${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.js.map + # TODOWASM ${CLR_ARTIFACTS_OBJ_DIR}/coreclr/browser.wasm.${CMAKE_BUILD_TYPE}/corehost/dotnet.js.map ${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 - ${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Runtime.InteropServices.JavaScript.Native/dotnet.runtime.js.map + # TODOWASM ${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Runtime.InteropServices.JavaScript.Native/dotnet.runtime.js.map ) install(FILES ${SAMPLE_ASSETS} DESTINATION corehost COMPONENT runtime) diff --git a/src/native/libs/System.Native.Browser/CMakeLists.txt b/src/native/libs/System.Native.Browser/CMakeLists.txt index 604e5cebd2d586..7d549df07d7268 100644 --- a/src/native/libs/System.Native.Browser/CMakeLists.txt +++ b/src/native/libs/System.Native.Browser/CMakeLists.txt @@ -30,20 +30,27 @@ file(GLOB_RECURSE ROLLUP_TS_SOURCES 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.js.map" + # TODOWASM "${CLR_ARTIFACTS_OBJ_DIR}/coreclr/browser.wasm.${CMAKE_BUILD_TYPE}/corehost/dotnet.js.map" "${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.Native.Browser/libSystem.Native.Browser.js" - "${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Native.Browser/libSystem.Native.Browser.js.map" + # TODOWASM "${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Native.Browser/libSystem.Native.Browser.js.map" "${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.Native.Browser/dotnet.runtime.js.map" + # TODOWASM "${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Native.Browser/dotnet.runtime.js.map" "${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Runtime.InteropServices.JavaScript.Native/libSystem.Runtime.InteropServices.JavaScript.Native.js" - "${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Runtime.InteropServices.JavaScript.Native/libSystem.Runtime.InteropServices.JavaScript.Native.js.map" + # TODOWASM "${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Runtime.InteropServices.JavaScript.Native/libSystem.Runtime.InteropServices.JavaScript.Native.js.map" ) +if(NOT PRODUCT_VERSION_JS) + # TODOWASM get dotnet ProductVersion from MSBuild + set(PRODUCT_VERSION_JS "10.0.0-dev") +endif() +if(NOT CI_BUILD_JS) + # TODOWASM get ContinuousIntegrationBuild from MSBuild + set(CI_BUILD_JS "false") +endif() -# TODOWASM pass env variables to rollup: ProductVersion, Configuration, ArtifactsObjDir, ContinuousIntegrationBuild add_custom_command( OUTPUT ${ROLLUP_OUTPUTS} - COMMAND npm run rollup + COMMAND npm run rollup ${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} diff --git a/src/native/rollup.config.defines.js b/src/native/rollup.config.defines.js index 47db8df4d7347d..9b1448e09c4356 100644 --- a/src/native/rollup.config.defines.js +++ b/src/native/rollup.config.defines.js @@ -3,16 +3,18 @@ import gitCommitInfo from "git-commit-info"; -const productVersion = process.env.ProductVersion || "10.0.0-dev"; -export const configuration = process.env.Configuration || "Debug"; -export const artifactsObjDir = process.env.ArtifactsObjDir ? process.env.ArtifactsObjDir.replace(/"/g, "") : "../../artifacts/obj"; -export const isContinuousIntegrationBuild = process.env.ContinuousIntegrationBuild === "true" ? true : false; -export const isDebug = configuration !== "Release"; +export const configuration = process.argv[2] || "Debug"; +export const productVersion = process.argv[3] || "10.0.0-dev"; +export const isContinuousIntegrationBuild = process.argv[4] === "true" ? true : false; + +console.log(`Rollup configuration: Configuration=${configuration}, ProductVersion=${productVersion}, ContinuousIntegrationBuild=${isContinuousIntegrationBuild}`); export const banner = "//! Licensed to the .NET Foundation under one or more agreements.\n//! The .NET Foundation licenses this file to you under the MIT license.\n//! This is generated file, see src/native/libs/Browser/rollup.config.defines.js\n\n"; export const banner_dts = banner + "//! This is not considered public API with backward compatibility guarantees. \n"; export const keep_classnames = /(ManagedObject|ManagedError|Span|ArraySegment)/; export const externalDependencies = ["module", "process", "perf_hooks", "node:crypto"]; +export const artifactsObjDir = "../../artifacts/obj"; +export const isDebug = configuration !== "Release"; let gitHash; try { diff --git a/src/native/rollup.config.js b/src/native/rollup.config.js index 05290e0d14b47b..6b4ebc6f24c821 100644 --- a/src/native/rollup.config.js +++ b/src/native/rollup.config.js @@ -23,7 +23,9 @@ const copies = [ ]; for (const [src, dest] of copies) { - const destDir = path.dirname(dest); + const absoluteSrc = path.resolve(src); + const destDir = path.resolve(path.dirname(dest)); + console.log(`Copying ${absoluteSrc} to ${destDir}`); await fs.mkdir(destDir, { recursive: true }); - await fs.copyFile(src, dest); + await fs.copyFile(absoluteSrc, dest); } From 1a3974f610f79cf1f8b03882d53886f115e09a90 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Mon, 22 Sep 2025 13:48:22 +0200 Subject: [PATCH 10/25] feedback --- src/coreclr/CMakeLists.txt | 4 ++-- src/native/corehost/browserhost/CMakeLists.txt | 6 +++--- src/native/corehost/browserhost/browserhost.cpp | 8 ++++---- src/native/corehost/browserhost/loader/dotnet.js | 10 +++++----- .../corehost/browserhost/sample/dotnet.boot.js | 2 +- src/native/libs/System.Native.Browser/CMakeLists.txt | 12 ++++++------ 6 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/coreclr/CMakeLists.txt b/src/coreclr/CMakeLists.txt index aa6ad5b75b5ac4..e0b3dc71482d4f 100644 --- a/src/coreclr/CMakeLists.txt +++ b/src/coreclr/CMakeLists.txt @@ -69,9 +69,9 @@ 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) - # TODOWASM should we start using System.Native.Browser and System.Runtime.InteropServices.JavaScript.Native also for Mono ? + # 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) diff --git a/src/native/corehost/browserhost/CMakeLists.txt b/src/native/corehost/browserhost/CMakeLists.txt index 252dc009bae265..dc94d158a93212 100644 --- a/src/native/corehost/browserhost/CMakeLists.txt +++ b/src/native/corehost/browserhost/CMakeLists.txt @@ -76,7 +76,7 @@ target_link_libraries( ${END_WHOLE_ARCHIVE} ) -# TODOWASM: this is temporary locations +# WASM-TODO: this is temporary locations set(SAMPLE_ASSETS sample/index.html sample/main.mjs @@ -88,9 +88,9 @@ set(SAMPLE_ASSETS # ${CLR_ARTIFACTS_OBJ_DIR}/sfx-finish/${CMAKE_BUILD_TYPE}/net10.0-browser/illink-wasm/System.Threading.dll # ${CLR_ARTIFACTS_BIN_DIR}/artifacts/bin/HelloWorld/${CMAKE_BUILD_TYPE}/net10.0/win-x64/HelloWorld.dll ${CLR_ARTIFACTS_OBJ_DIR}/coreclr/browser.wasm.${CMAKE_BUILD_TYPE}/corehost/dotnet.js - # TODOWASM ${CLR_ARTIFACTS_OBJ_DIR}/coreclr/browser.wasm.${CMAKE_BUILD_TYPE}/corehost/dotnet.js.map + # WASM-TODO ${CLR_ARTIFACTS_OBJ_DIR}/coreclr/browser.wasm.${CMAKE_BUILD_TYPE}/corehost/dotnet.js.map ${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 - # TODOWASM ${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Runtime.InteropServices.JavaScript.Native/dotnet.runtime.js.map + # WASM-TODO ${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Runtime.InteropServices.JavaScript.Native/dotnet.runtime.js.map ) install(FILES ${SAMPLE_ASSETS} DESTINATION corehost COMPONENT runtime) diff --git a/src/native/corehost/browserhost/browserhost.cpp b/src/native/corehost/browserhost/browserhost.cpp index 2ace734adc8cd9..ed128cadb5b753 100644 --- a/src/native/corehost/browserhost/browserhost.cpp +++ b/src/native/corehost/browserhost/browserhost.cpp @@ -108,7 +108,7 @@ static pal::char_t buffer[STRING_LENGTH("0xffffffffffffffff")]; extern "C" int browserHostInitializeCoreCLR(void) { - //TODOWASM: does getenv return UTF8 ? + //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); @@ -142,7 +142,7 @@ extern "C" int browserHostInitializeCoreCLR(void) return 0; } -// TODOWASM: browser needs async entrypoint +// WASM-TODO: browser needs async entrypoint extern "C" int browserHostExecuteAssembly(const char* assemblyPath) { int exit_code; @@ -162,11 +162,11 @@ extern "C" int browserHostExecuteAssembly(const char* assemblyPath) { std::fprintf(stderr, "coreclr_shutdown_2 failed - Error: 0x%08x\n", retval); exit_code = -1; - // TODOWASM: this is too trivial + // WASM-TODO: this is too trivial browserHostRejectMain("coreclr_shutdown_2 failed"); } - // TODOWASM: this is too trivial + // 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/loader/dotnet.js b/src/native/corehost/browserhost/loader/dotnet.js index 1ee4e6849bbeac..22599fc132ea60 100644 --- a/src/native/corehost/browserhost/loader/dotnet.js +++ b/src/native/corehost/browserhost/loader/dotnet.js @@ -373,11 +373,11 @@ const scriptDirectory = normalizeDirectoryUrl(scriptUrl); const nativeModulePromiseController = createPromiseController(() => { updateInternals(); }); -// TODOWASM: retry logic -// TODOWASM: throttling logic -// TODOWASM: load icu data -// TODOWASM: invokeLibraryInitializers -// TODOWASM: webCIL +// 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) diff --git a/src/native/corehost/browserhost/sample/dotnet.boot.js b/src/native/corehost/browserhost/sample/dotnet.boot.js index 18ba61ca61670a..7042b99ae1caa3 100644 --- a/src/native/corehost/browserhost/sample/dotnet.boot.js +++ b/src/native/corehost/browserhost/sample/dotnet.boot.js @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -// TODOWASM: this is dummy configuration until WASM SDK for corehost +// WASM-TODO: this is dummy configuration until WASM SDK for corehost export const config = /*json-start*/{ "mainAssemblyName": "HelloWorld.dll", diff --git a/src/native/libs/System.Native.Browser/CMakeLists.txt b/src/native/libs/System.Native.Browser/CMakeLists.txt index 7d549df07d7268..84472c361814f5 100644 --- a/src/native/libs/System.Native.Browser/CMakeLists.txt +++ b/src/native/libs/System.Native.Browser/CMakeLists.txt @@ -30,21 +30,21 @@ file(GLOB_RECURSE ROLLUP_TS_SOURCES set(ROLLUP_OUTPUTS "${CLR_ARTIFACTS_OBJ_DIR}/coreclr/browser.wasm.${CMAKE_BUILD_TYPE}/corehost/dotnet.js" - # TODOWASM "${CLR_ARTIFACTS_OBJ_DIR}/coreclr/browser.wasm.${CMAKE_BUILD_TYPE}/corehost/dotnet.js.map" + # WASM-TODO "${CLR_ARTIFACTS_OBJ_DIR}/coreclr/browser.wasm.${CMAKE_BUILD_TYPE}/corehost/dotnet.js.map" "${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.Native.Browser/libSystem.Native.Browser.js" - # TODOWASM "${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Native.Browser/libSystem.Native.Browser.js.map" + # WASM-TODO "${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Native.Browser/libSystem.Native.Browser.js.map" "${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Native.Browser/dotnet.runtime.js" - # TODOWASM "${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Native.Browser/dotnet.runtime.js.map" + # WASM-TODO "${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Native.Browser/dotnet.runtime.js.map" "${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Runtime.InteropServices.JavaScript.Native/libSystem.Runtime.InteropServices.JavaScript.Native.js" - # TODOWASM "${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Runtime.InteropServices.JavaScript.Native/libSystem.Runtime.InteropServices.JavaScript.Native.js.map" + # WASM-TODO "${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Runtime.InteropServices.JavaScript.Native/libSystem.Runtime.InteropServices.JavaScript.Native.js.map" ) if(NOT PRODUCT_VERSION_JS) - # TODOWASM get dotnet ProductVersion from MSBuild + # WASM-TODO get dotnet ProductVersion from MSBuild set(PRODUCT_VERSION_JS "10.0.0-dev") endif() if(NOT CI_BUILD_JS) - # TODOWASM get ContinuousIntegrationBuild from MSBuild + # WASM-TODO get ContinuousIntegrationBuild from MSBuild set(CI_BUILD_JS "false") endif() From e14fedd65ee8fcb06bd12c8d84707827cbde80cb Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Mon, 22 Sep 2025 14:16:50 +0200 Subject: [PATCH 11/25] wip --- .../corehost/browserhost/CMakeLists.txt | 4 +-- .../libs/Common/JavaScript/types/exchange.ts | 33 ++++++++++++++----- .../libs/Common/JavaScript/types/internal.ts | 9 ++--- .../libs/System.Native.Browser/CMakeLists.txt | 2 ++ .../libSystem.Native.Browser.extpost.js | 2 +- src/native/package.json | 4 ++- src/native/rollup.config.defines.js | 1 + src/native/rollup.config.js | 2 ++ src/native/rollup.config.plugins.js | 27 ++++++++++++++- src/native/tsconfig.json | 5 +-- 10 files changed, 67 insertions(+), 22 deletions(-) diff --git a/src/native/corehost/browserhost/CMakeLists.txt b/src/native/corehost/browserhost/CMakeLists.txt index dc94d158a93212..72faf41a261d86 100644 --- a/src/native/corehost/browserhost/CMakeLists.txt +++ b/src/native/corehost/browserhost/CMakeLists.txt @@ -46,8 +46,8 @@ LIST(APPEND NATIVE_LIBS target_compile_options(browserhost PRIVATE -fwasm-exceptions) set_target_properties(browserhost PROPERTIES - LINK_DEPENDS "${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.Runtime.InteropServices.JavaScript.Native/libSystem.Runtime.InteropServices.JavaScript.Native.js;${CMAKE_CURRENT_SOURCE_DIR}/libBrowserHost.js;${CMAKE_CURRENT_SOURCE_DIR}/../../libs/System.Native.Browser/libSystem.Native.Browser.extpost.js;" - LINK_FLAGS "--js-library ${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Native.Browser/libSystem.Native.Browser.js --js-library ${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Runtime.InteropServices.JavaScript.Native/libSystem.Runtime.InteropServices.JavaScript.Native.js --js-library ${CMAKE_CURRENT_SOURCE_DIR}/libBrowserHost.js --extern-post-js ${CMAKE_CURRENT_SOURCE_DIR}/../../libs/System.Native.Browser/libSystem.Native.Browser.extpost.js " + LINK_DEPENDS "${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.Runtime.InteropServices.JavaScript.Native/libSystem.Runtime.InteropServices.JavaScript.Native.js;${CLR_ARTIFACTS_OBJ_DIR}/coreclr/browser.wasm.${CMAKE_BUILD_TYPE}/corehost/libBrowserHost.js;${CMAKE_CURRENT_SOURCE_DIR}/../../libs/System.Native.Browser/libSystem.Native.Browser.extpost.js;" + LINK_FLAGS "--js-library ${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Native.Browser/libSystem.Native.Browser.js --js-library ${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Runtime.InteropServices.JavaScript.Native/libSystem.Runtime.InteropServices.JavaScript.Native.js --js-library ${CLR_ARTIFACTS_OBJ_DIR}/coreclr/browser.wasm.${CMAKE_BUILD_TYPE}/corehost/libBrowserHost.js --extern-post-js ${CMAKE_CURRENT_SOURCE_DIR}/../../libs/System.Native.Browser/libSystem.Native.Browser.extpost.js " RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") # WASMTODO -Oz -sVERBOSE diff --git a/src/native/libs/Common/JavaScript/types/exchange.ts b/src/native/libs/Common/JavaScript/types/exchange.ts index 7b03c4d3a6a80d..da388fb591910f 100644 --- a/src/native/libs/Common/JavaScript/types/exchange.ts +++ b/src/native/libs/Common/JavaScript/types/exchange.ts @@ -1,7 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -import type { isSharedArrayBuffer } from "../../../System.Native.Browser/memory"; +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"; @@ -30,6 +31,11 @@ export type AssertType = { } 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, @@ -40,25 +46,34 @@ export type LoaderExportsTable = [ typeof warn, typeof error, typeof check, + ()=> boolean, + ()=> boolean, + ()=> boolean, + ()=> boolean, + ()=> boolean, typeof browserHostResolveMain, typeof browserHostRejectMain, typeof getRunMainPromise, ] -type registerDllBytesType = (bytes: Uint8Array, asset: { name: string })=>void; - -export type NativeExports = { +export type HostNativeExports = { isSharedArrayBuffer : typeof isSharedArrayBuffer, - registerDllBytes: registerDllBytesType + registerDllBytes: typeof registerDllBytes } -export type NativeExportsTable = [ - registerDllBytesType, +export type HostNativeExportsTable = [ + typeof registerDllBytes, typeof isSharedArrayBuffer, ] -export type InteropExports = { +export type InteropJavaScriptNativeExports = { +} + +export type InteropJavaScriptNativeExportsTable = [ +] + +export type NativeBrowserExports = { } -export type InteropExportsTable = [ +export type NativeBrowserExportsTable = [ ] diff --git a/src/native/libs/Common/JavaScript/types/internal.ts b/src/native/libs/Common/JavaScript/types/internal.ts index 3785fb99ca5ec0..d8f6432ff182d6 100644 --- a/src/native/libs/Common/JavaScript/types/internal.ts +++ b/src/native/libs/Common/JavaScript/types/internal.ts @@ -3,7 +3,7 @@ import type { DotnetModuleConfig, RuntimeAPI, AssetEntry, LoaderConfig, LoadingResource } from "./public-api"; import type { CharPtr, EmscriptenModule, ManagedPointer, NativePointer, VoidPtr } from "./emscripten"; -import { InteropExportsTable, LoaderExportsTable, NativeExportsTable, RuntimeExportsTable } from "./exchange"; +import { InteropJavaScriptNativeExportsTable, LoaderExportsTable, HostNativeExportsTable, RuntimeExportsTable, NativeBrowserExports } from "./exchange"; export type GCHandle = { __brand: "GCHandle" @@ -41,7 +41,7 @@ export type EmscriptenInternals = { updateMemoryViews: () => void, }; -export declare interface EmscriptenModuleInternal { +export declare interface EmscriptenModuleInternal extends EmscriptenModule { HEAP8: Int8Array, HEAP16: Int16Array; HEAP32: Int32Array; @@ -110,8 +110,9 @@ export type InternalApis = { runtimeApi: RuntimeAPI, runtimeExportsTable: RuntimeExportsTable, loaderExportsTable: LoaderExportsTable, - nativeExportsTable: NativeExportsTable, - interopExportsTable: InteropExportsTable, + hostNativeExportsTable: HostNativeExportsTable, + interopJavaScriptNativeExportsTable: InteropJavaScriptNativeExportsTable, + nativeBrowserExportsTable: NativeBrowserExports, config: LoaderConfigInternal, updates: (() => void)[], } diff --git a/src/native/libs/System.Native.Browser/CMakeLists.txt b/src/native/libs/System.Native.Browser/CMakeLists.txt index 84472c361814f5..9f641ca05d8484 100644 --- a/src/native/libs/System.Native.Browser/CMakeLists.txt +++ b/src/native/libs/System.Native.Browser/CMakeLists.txt @@ -32,6 +32,8 @@ set(ROLLUP_OUTPUTS "${CLR_ARTIFACTS_OBJ_DIR}/coreclr/browser.wasm.${CMAKE_BUILD_TYPE}/corehost/dotnet.js" # WASM-TODO "${CLR_ARTIFACTS_OBJ_DIR}/coreclr/browser.wasm.${CMAKE_BUILD_TYPE}/corehost/dotnet.js.map" "${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" + # WASM-TODO "${CLR_ARTIFACTS_OBJ_DIR}/coreclr/browser.wasm.${CMAKE_BUILD_TYPE}/corehost/libBrowserHost.js.map" "${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Native.Browser/libSystem.Native.Browser.js" # WASM-TODO "${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Native.Browser/libSystem.Native.Browser.js.map" "${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Native.Browser/dotnet.runtime.js" 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 index 04cb94aba0e7b6..81df9991c0d16d 100644 --- a/src/native/libs/System.Native.Browser/libSystem.Native.Browser.extpost.js +++ b/src/native/libs/System.Native.Browser/libSystem.Native.Browser.extpost.js @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. var fetch = fetch || undefined; var _nativeModuleLoaded = false; var dotnetInternals = null; -export async function initialize(internals) { +export function initialize(internals) { if (_nativeModuleLoaded) throw new Error("Native module already loaded"); dotnetInternals = internals; _nativeModuleLoaded = true; diff --git a/src/native/package.json b/src/native/package.json index 05e1734a1f50f2..335505703723b8 100644 --- a/src/native/package.json +++ b/src/native/package.json @@ -10,7 +10,9 @@ "type": "module", "types": "dotnet.d.ts", "scripts": { - "rollup": "node rollup.config.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\"" }, diff --git a/src/native/rollup.config.defines.js b/src/native/rollup.config.defines.js index 9b1448e09c4356..5c3fb8096fdc7d 100644 --- a/src/native/rollup.config.defines.js +++ b/src/native/rollup.config.defines.js @@ -12,6 +12,7 @@ console.log(`Rollup configuration: Configuration=${configuration}, ProductVersio export const banner = "//! Licensed to the .NET Foundation under one or more agreements.\n//! The .NET Foundation licenses this file to you under the MIT license.\n//! This is generated file, see src/native/libs/Browser/rollup.config.defines.js\n\n"; export const banner_dts = banner + "//! This is not considered public API with backward compatibility guarantees. \n"; export const keep_classnames = /(ManagedObject|ManagedError|Span|ArraySegment)/; +export const reserved = ["Assert", "JSEngine", "Logger", "Module", "dotnetInternals", "interopExports", "loaderExports", "nativeExports", "runtimeApi", "runtimeExports"]; export const externalDependencies = ["module", "process", "perf_hooks", "node:crypto"]; export const artifactsObjDir = "../../artifacts/obj"; export const isDebug = configuration !== "Release"; diff --git a/src/native/rollup.config.js b/src/native/rollup.config.js index 6b4ebc6f24c821..11f582e39e38e5 100644 --- a/src/native/rollup.config.js +++ b/src/native/rollup.config.js @@ -14,6 +14,8 @@ const copies = [ `${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", diff --git a/src/native/rollup.config.plugins.js b/src/native/rollup.config.plugins.js index f11962eba54722..6cab1709b6e9ab 100644 --- a/src/native/rollup.config.plugins.js +++ b/src/native/rollup.config.plugins.js @@ -8,7 +8,7 @@ import * as fs from "fs"; import * as path from "path"; import terser from "@rollup/plugin-terser"; -import { isContinuousIntegrationBuild, keep_classnames } from "./rollup.config.defines.js" +import { isContinuousIntegrationBuild, keep_classnames, reserved } from "./rollup.config.defines.js" export const terserPlugin = () => terser({ compress: { @@ -17,9 +17,16 @@ export const terserPlugin = () => terser({ drop_debugger: false, // we invoke debugger drop_console: false, // we log to console keep_classnames, + ecma: "2015", + toplevel: true, + module: true, + }, }, mangle: { keep_classnames, + reserved, + toplevel: true, + module: true, }, }); @@ -29,6 +36,24 @@ export const writeOnChangePlugin = () => ({ generateBundle: writeWhenChanged }); +// Drop invocation from IIFE +export function iife2fe() { + return { + name: "iife2fe", + generateBundle: (options, bundle) => { + const name = Object.keys(bundle)[0]; + if (name.endsWith(".map")) return; + const asset = bundle[name]; + const code = asset.code; + //throw new Error("iife2fe " + code); + asset.code = code + .replace(/}\({}\);/, "};") // }({}); ->}; + .replace(/}\)\({}\);/, "});") // })({}); ->}); + ; + } + }; +} + // force always unix line ending export const alwaysLF = () => ({ name: "writeOnChange", diff --git a/src/native/tsconfig.json b/src/native/tsconfig.json index 8e502ea48ec777..6709400b3bc508 100644 --- a/src/native/tsconfig.json +++ b/src/native/tsconfig.json @@ -20,10 +20,7 @@ "./libs/Common/JavaScript/types" ], "rootDirs": [ - "./corehost/browserhost/loader", - "./libs/Common/JavaScript", - "./libs/System.Native.Browser", - "./libs/System.Runtime.InteropServices.JavaScript.Native", + "./", "../../artifacts/bin/native/generated" ] }, From 098da32e27d040c5c40c4832de28a1a15ff70169 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Mon, 22 Sep 2025 15:03:01 +0200 Subject: [PATCH 12/25] feedback --- src/coreclr/vm/dllimportcallback.cpp | 2 +- src/coreclr/vm/interpexec.cpp | 2 +- src/coreclr/vm/wasm/helpers.cpp | 4 ++-- src/native/corehost/browserhost/CMakeLists.txt | 6 +++--- 4 files changed, 7 insertions(+), 7 deletions(-) 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 182eaf99210616..865089d30a9dcf 100644 --- a/src/coreclr/vm/wasm/helpers.cpp +++ b/src/coreclr/vm/wasm/helpers.cpp @@ -393,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); } @@ -565,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/native/corehost/browserhost/CMakeLists.txt b/src/native/corehost/browserhost/CMakeLists.txt index 72faf41a261d86..b08a1f2886732a 100644 --- a/src/native/corehost/browserhost/CMakeLists.txt +++ b/src/native/corehost/browserhost/CMakeLists.txt @@ -36,12 +36,12 @@ LIST(APPEND NATIVE_LIBS System.IO.Compression.Native-Static nativeresourcestring gcinfo - # WASMTODO respect $(InvariantTimezone) + # WASM-TODO respect $(InvariantTimezone) # System.Native.TimeZoneData.Invariant System.Native.TimeZoneData ) -# WASMTODO set(RUNTIMEINFO_LIB runtimeinfo) +# WASM-TODO set(RUNTIMEINFO_LIB runtimeinfo) target_compile_options(browserhost PRIVATE -fwasm-exceptions) @@ -50,7 +50,7 @@ set_target_properties(browserhost PROPERTIES LINK_FLAGS "--js-library ${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Native.Browser/libSystem.Native.Browser.js --js-library ${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Runtime.InteropServices.JavaScript.Native/libSystem.Runtime.InteropServices.JavaScript.Native.js --js-library ${CLR_ARTIFACTS_OBJ_DIR}/coreclr/browser.wasm.${CMAKE_BUILD_TYPE}/corehost/libBrowserHost.js --extern-post-js ${CMAKE_CURRENT_SOURCE_DIR}/../../libs/System.Native.Browser/libSystem.Native.Browser.extpost.js " RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") -# WASMTODO -Oz -sVERBOSE +# WASM-TODO -Oz -sVERBOSE target_link_options(browserhost PRIVATE -fwasm-exceptions -sEXIT_RUNTIME=0 From 66dcad1d0caa40b656f5198923f8bcdb3d6949d9 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Mon, 22 Sep 2025 15:03:34 +0200 Subject: [PATCH 13/25] updates --- .../corehost/browserhost/libBrowserHost.js | 512 +++++++++++++- .../corehost/browserhost/loader/dotnet.js | 98 ++- .../libs/System.Native.Browser/CMakeLists.txt | 2 +- .../libSystem.Native.Browser.js | 634 +++--------------- .../dotnet.runtime.js | 401 ++--------- ...ntime.InteropServices.JavaScript.Native.js | 180 ++--- src/native/package.json | 1 + src/native/rollup.config.defines.js | 33 - src/native/rollup.config.plugins.js | 153 ----- .../{rollup.config.js => rollup.stub.js} | 9 +- 10 files changed, 825 insertions(+), 1198 deletions(-) delete mode 100644 src/native/rollup.config.defines.js delete mode 100644 src/native/rollup.config.plugins.js rename src/native/{rollup.config.js => rollup.stub.js} (81%) diff --git a/src/native/corehost/browserhost/libBrowserHost.js b/src/native/corehost/browserhost/libBrowserHost.js index b284c010edabdb..af9dbbca77b04d 100644 --- a/src/native/corehost/browserhost/libBrowserHost.js +++ b/src/native/corehost/browserhost/libBrowserHost.js @@ -1,19 +1,500 @@ //! 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 nativeExports = {}; + let interopExports = {}; + let dotnetInternals; + function getInternals() { + return dotnetInternals; + } + function setInternals(internal) { + dotnetInternals = internal; + runtimeApi = dotnetInternals.runtimeApi; + Module = dotnetInternals.runtimeApi.Module; + } + function updateInternals() { + if (dotnetInternals.updates === undefined) { + dotnetInternals.updates = []; + } + for (const updateImpl of dotnetInternals.updates) { + updateImpl(); + } + } + function updateInternalsImpl() { + if (Object.keys(loaderExports).length === 0 && dotnetInternals.loaderExportsTable) { + loaderExports = {}; + Logger = {}; + Assert = {}; + JSEngine = {}; + loaderExportsFromTable(dotnetInternals.loaderExportsTable, Logger, Assert, JSEngine, loaderExports); + } + if (Object.keys(runtimeExports).length === 0 && dotnetInternals.runtimeExportsTable) { + runtimeExports = {}; + runtimeExportsFromTable(dotnetInternals.runtimeExportsTable, runtimeExports); + } + if (Object.keys(nativeExports).length === 0 && dotnetInternals.hostNativeExportsTable) { + nativeExports = {}; + hostNativeExportsFromTable(dotnetInternals.hostNativeExportsTable, nativeExports); + } + if (Object.keys(interopExports).length === 0 && dotnetInternals.interopJavaScriptNativeExportsTable) { + interopExports = {}; + interopJavaScriptNativeExportsFromTable(dotnetInternals.interopJavaScriptNativeExportsTable, interopExports); + } + } + /** + * 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 loaderExportsToTable(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 loaderExportsFromTable(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 runtimeExportsToTable(map) { + return []; + } + function runtimeExportsFromTable(table, runtime) { + Object.assign(runtime, {}); + } + function hostNativeExportsToTable(map) { + return [ + map.registerDllBytes, + map.isSharedArrayBuffer, + ]; + } + function hostNativeExportsFromTable(table, native) { + const nativeLocal = { + registerDllBytes: table[0], + isSharedArrayBuffer: table[1], + }; + Object.assign(native, nativeLocal); + } + // eslint-disable-next-line @typescript-eslint/no-unused-vars + function interopJavaScriptNativeExportsToTable(map) { + return []; + } + function interopJavaScriptNativeExportsFromTable(table, interop) { + const interopLocal = {}; + Object.assign(interop, interopLocal); + } + // eslint-disable-next-line @typescript-eslint/no-unused-vars + function nativeBrowserExportsToTable(map) { + return []; + } + function nativeBrowserExportsFromTable(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) { + return false; + } + Module.HEAPU32[outDataStartPtr >> 2] = assembly.ptr; + // upper bits are cleared by the C caller + Module.HEAPU32[outSize >> 2] = assembly.length; + return true; + } + function browserHostResolveMain(exitCode) { + loaderExports.browserHostResolveMain(exitCode); + } + function browserHostRejectMain(reason) { + loaderExports.browserHostRejectMain(reason); + } + 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 = [...hostNativeExportsToTable(hostNativeExportsLocal)]; + internals.updates.push(updateInternalsImpl); + updateInternals(); + } + + 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. + * It implements the corehost and a part of public JS API related to memory and runtime hosting. */ (function (exports) { - function browserHostLibLibFactory() { - const BrowserHostLib = { + function libFactory() { + const lib = { $BROWSER_HOST: { selfInitialize: () => { if (typeof dotnetInternals !== "undefined") { BROWSER_HOST.dotnetInternals = dotnetInternals; + const exports = libBrowserHost(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"; @@ -29,12 +510,27 @@ } }, }, - "$BROWSER_HOST__deps": ["$DOTNET", "browserHostInitializeCoreCLR", "browserHostExecuteAssembly", "browserHostExternalAssemblyProbe"], - "$BROWSER_HOST__postset": "DOTNET.selfInitialize();", + "$libBrowserHost": libBrowserHost, + "$BROWSER_HOST__postset": "BROWSER_HOST.selfInitialize();", }; - autoAddDeps(BrowserHostLib, "$BROWSER_HOST"); - addToLibrary(BrowserHostLib); + + // this executes the function at compile time in order to capture export names + const exports = libBrowserHost({}); + let commonDeps = ["$libBrowserHost", "$DOTNET", "$DOTNET_INTEROP", "browserHostInitializeCoreCLR", "browserHostExecuteAssembly"]; + 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["$DOTNET_INTEROP__deps"] = commonDeps; + + autoAddDeps(lib, "$BROWSER_HOST"); + addToLibrary(lib); } - browserHostLibLibFactory(); + libFactory(); return exports; })({}); diff --git a/src/native/corehost/browserhost/loader/dotnet.js b/src/native/corehost/browserhost/loader/dotnet.js index 22599fc132ea60..2e1e30eb469d86 100644 --- a/src/native/corehost/browserhost/loader/dotnet.js +++ b/src/native/corehost/browserhost/loader/dotnet.js @@ -7,11 +7,11 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -let JSEngine; let Module; let runtimeApi; let Logger = {}; let Assert = {}; +let JSEngine = {}; let loaderExports = {}; let runtimeExports = {}; let nativeExports = {}; @@ -34,38 +34,24 @@ function updateInternals() { } } function updateInternalsImpl() { - if (!JSEngine) { - 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; - 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, - }; - } if (Object.keys(loaderExports).length === 0 && dotnetInternals.loaderExportsTable) { loaderExports = {}; Logger = {}; Assert = {}; - loaderExportsFromTable(dotnetInternals.loaderExportsTable, Logger, Assert, loaderExports); + JSEngine = {}; + loaderExportsFromTable(dotnetInternals.loaderExportsTable, Logger, Assert, JSEngine, loaderExports); } if (Object.keys(runtimeExports).length === 0 && dotnetInternals.runtimeExportsTable) { runtimeExports = {}; runtimeExportsFromTable(dotnetInternals.runtimeExportsTable, runtimeExports); } - if (Object.keys(nativeExports).length === 0 && dotnetInternals.nativeExportsTable) { + if (Object.keys(nativeExports).length === 0 && dotnetInternals.hostNativeExportsTable) { nativeExports = {}; - nativeExportsFromTable(dotnetInternals.nativeExportsTable, nativeExports); + hostNativeExportsFromTable(dotnetInternals.hostNativeExportsTable, nativeExports); } - if (Object.keys(interopExports).length === 0 && dotnetInternals.interopExportsTable) { + if (Object.keys(interopExports).length === 0 && dotnetInternals.interopJavaScriptNativeExportsTable) { interopExports = {}; - interopExportsFromTable(dotnetInternals.interopExportsTable, interopExports); + interopJavaScriptNativeExportsFromTable(dotnetInternals.interopJavaScriptNativeExportsTable, interopExports); } } /** @@ -78,12 +64,17 @@ function loaderExportsToTable(logger, assert, loaderExports) { 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 loaderExportsFromTable(table, logger, assert, loaderExports) { +function loaderExportsFromTable(table, logger, assert, jsEngine, loaderExports) { const loggerLocal = { info: table[0], warn: table[1], @@ -93,13 +84,26 @@ function loaderExportsFromTable(table, logger, assert, loaderExports) { check: table[3], }; const loaderExportsLocal = { - browserHostResolveMain: table[4], - browserHostRejectMain: table[5], - getRunMainPromise: table[6], + 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(loaderExports, loaderExportsLocal); + Object.assign(jsEngine, jsEngineLocal); } // eslint-disable-next-line @typescript-eslint/no-unused-vars function runtimeExportsToTable(map) { @@ -108,13 +112,13 @@ function runtimeExportsToTable(map) { function runtimeExportsFromTable(table, runtime) { Object.assign(runtime, {}); } -function nativeExportsToTable(map) { +function hostNativeExportsToTable(map) { return [ map.registerDllBytes, map.isSharedArrayBuffer, ]; } -function nativeExportsFromTable(table, native) { +function hostNativeExportsFromTable(table, native) { const nativeLocal = { registerDllBytes: table[0], isSharedArrayBuffer: table[1], @@ -122,10 +126,18 @@ function nativeExportsFromTable(table, native) { Object.assign(native, nativeLocal); } // eslint-disable-next-line @typescript-eslint/no-unused-vars -function interopExportsToTable(map) { +function interopJavaScriptNativeExportsToTable(map) { return []; } -function interopExportsFromTable(table, interop) { +function interopJavaScriptNativeExportsFromTable(table, interop) { + const interopLocal = {}; + Object.assign(interop, interopLocal); +} +// eslint-disable-next-line @typescript-eslint/no-unused-vars +function nativeBrowserExportsToTable(map) { + return []; +} +function nativeBrowserExportsFromTable(table, interop) { const interopLocal = {}; Object.assign(interop, interopLocal); } @@ -133,6 +145,9 @@ function interopExportsFromTable(table, interop) { // 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 = {}; @@ -810,7 +825,7 @@ var ProductVersion = "10.0.0-dev"; var BuildConfiguration = "Debug"; -var GitHash = "becd20635d51b17f7f344df90775c63e7e744d11"; +var GitHash = "b45b9a54d6619520903f5be728767b66e5a37429"; // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. @@ -821,7 +836,7 @@ async function invokeLibraryInitializers(functionName, args) { // 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 +// WASM-TODO inline the code function check(condition, messageFactory) { if (!condition) { const message = typeof messageFactory === "string" ? messageFactory : messageFactory(); @@ -853,6 +868,12 @@ function error(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: {}, @@ -878,10 +899,22 @@ function initialize() { 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, @@ -893,6 +926,7 @@ function initialize() { Object.assign(runtimeApi, runtimeApiFunctions); Object.assign(Logger, logger); Object.assign(Assert, assert); + Object.assign(JSEngine, jsEngine); Object.assign(loaderExports, loaderFunctions); dotnetInternals.loaderExportsTable = [...loaderExportsToTable(Logger, Assert, loaderExports)]; updates.push(updateInternalsImpl); diff --git a/src/native/libs/System.Native.Browser/CMakeLists.txt b/src/native/libs/System.Native.Browser/CMakeLists.txt index 9f641ca05d8484..a4d4e947876735 100644 --- a/src/native/libs/System.Native.Browser/CMakeLists.txt +++ b/src/native/libs/System.Native.Browser/CMakeLists.txt @@ -52,7 +52,7 @@ endif() add_custom_command( OUTPUT ${ROLLUP_OUTPUTS} - COMMAND npm run rollup ${CMAKE_BUILD_TYPE} ${PRODUCT_VERSION_JS} ${CI_BUILD_JS} + 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} diff --git a/src/native/libs/System.Native.Browser/libSystem.Native.Browser.js b/src/native/libs/System.Native.Browser/libSystem.Native.Browser.js index 0b41e5d0f4aa08..9d2459ba4ce4c6 100644 --- a/src/native/libs/System.Native.Browser/libSystem.Native.Browser.js +++ b/src/native/libs/System.Native.Browser/libSystem.Native.Browser.js @@ -3,16 +3,16 @@ //! This is generated file, see src/native/libs/Browser/rollup.config.defines.js -var libSystemNativeBrowserJS = (function (exports) { +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 JSEngine; let Module; let runtimeApi; let Logger = {}; let Assert = {}; + let JSEngine = {}; let loaderExports = {}; let runtimeExports = {}; let nativeExports = {}; @@ -35,38 +35,24 @@ var libSystemNativeBrowserJS = (function (exports) { } } function updateInternalsImpl() { - if (!JSEngine) { - 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; - 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, - }; - } if (Object.keys(loaderExports).length === 0 && dotnetInternals.loaderExportsTable) { loaderExports = {}; Logger = {}; Assert = {}; - loaderExportsFromTable(dotnetInternals.loaderExportsTable, Logger, Assert, loaderExports); + JSEngine = {}; + loaderExportsFromTable(dotnetInternals.loaderExportsTable, Logger, Assert, JSEngine, loaderExports); } if (Object.keys(runtimeExports).length === 0 && dotnetInternals.runtimeExportsTable) { runtimeExports = {}; runtimeExportsFromTable(dotnetInternals.runtimeExportsTable, runtimeExports); } - if (Object.keys(nativeExports).length === 0 && dotnetInternals.nativeExportsTable) { + if (Object.keys(nativeExports).length === 0 && dotnetInternals.hostNativeExportsTable) { nativeExports = {}; - nativeExportsFromTable(dotnetInternals.nativeExportsTable, nativeExports); + hostNativeExportsFromTable(dotnetInternals.hostNativeExportsTable, nativeExports); } - if (Object.keys(interopExports).length === 0 && dotnetInternals.interopExportsTable) { + if (Object.keys(interopExports).length === 0 && dotnetInternals.interopJavaScriptNativeExportsTable) { interopExports = {}; - interopExportsFromTable(dotnetInternals.interopExportsTable, interopExports); + interopJavaScriptNativeExportsFromTable(dotnetInternals.interopJavaScriptNativeExportsTable, interopExports); } } /** @@ -79,12 +65,17 @@ var libSystemNativeBrowserJS = (function (exports) { 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 loaderExportsFromTable(table, logger, assert, loaderExports) { + function loaderExportsFromTable(table, logger, assert, jsEngine, loaderExports) { const loggerLocal = { info: table[0], warn: table[1], @@ -94,13 +85,26 @@ var libSystemNativeBrowserJS = (function (exports) { check: table[3], }; const loaderExportsLocal = { - browserHostResolveMain: table[4], - browserHostRejectMain: table[5], - getRunMainPromise: table[6], + 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(loaderExports, loaderExportsLocal); + Object.assign(jsEngine, jsEngineLocal); } // eslint-disable-next-line @typescript-eslint/no-unused-vars function runtimeExportsToTable(map) { @@ -109,13 +113,13 @@ var libSystemNativeBrowserJS = (function (exports) { function runtimeExportsFromTable(table, runtime) { Object.assign(runtime, {}); } - function nativeExportsToTable(map) { + function hostNativeExportsToTable(map) { return [ map.registerDllBytes, map.isSharedArrayBuffer, ]; } - function nativeExportsFromTable(table, native) { + function hostNativeExportsFromTable(table, native) { const nativeLocal = { registerDllBytes: table[0], isSharedArrayBuffer: table[1], @@ -123,19 +127,26 @@ var libSystemNativeBrowserJS = (function (exports) { Object.assign(native, nativeLocal); } // eslint-disable-next-line @typescript-eslint/no-unused-vars - function interopExportsToTable(map) { + function interopJavaScriptNativeExportsToTable(map) { + return []; + } + function interopJavaScriptNativeExportsFromTable(table, interop) { + const interopLocal = {}; + Object.assign(interop, interopLocal); + } + // eslint-disable-next-line @typescript-eslint/no-unused-vars + function nativeBrowserExportsToTable(map) { return []; } - function interopExportsFromTable(table, interop) { + function nativeBrowserExportsFromTable(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. - const loadedAssemblies = {}; - var commonInfra = /*#__PURE__*/Object.freeze({ + var crossModule = /*#__PURE__*/Object.freeze({ __proto__: null, get Assert() { return Assert; }, get JSEngine() { return JSEngine; }, @@ -143,16 +154,17 @@ var libSystemNativeBrowserJS = (function (exports) { get Module() { return Module; }, get dotnetInternals() { return dotnetInternals; }, getInternals: getInternals, + hostNativeExportsFromTable: hostNativeExportsFromTable, + hostNativeExportsToTable: hostNativeExportsToTable, get interopExports() { return interopExports; }, - interopExportsFromTable: interopExportsFromTable, - interopExportsToTable: interopExportsToTable, - loadedAssemblies: loadedAssemblies, + interopJavaScriptNativeExportsFromTable: interopJavaScriptNativeExportsFromTable, + interopJavaScriptNativeExportsToTable: interopJavaScriptNativeExportsToTable, get loaderExports() { return loaderExports; }, loaderExportsFromTable: loaderExportsFromTable, loaderExportsToTable: loaderExportsToTable, + nativeBrowserExportsFromTable: nativeBrowserExportsFromTable, + nativeBrowserExportsToTable: nativeBrowserExportsToTable, get nativeExports() { return nativeExports; }, - nativeExportsFromTable: nativeExportsFromTable, - nativeExportsToTable: nativeExportsToTable, get runtimeApi() { return runtimeApi; }, get runtimeExports() { return runtimeExports; }, runtimeExportsFromTable: runtimeExportsFromTable, @@ -170,9 +182,9 @@ var libSystemNativeBrowserJS = (function (exports) { // https://www.w3.org/TR/WebCryptoAPI/#Crypto-method-getRandomValues const batchedQuotaMax = 65536; if (!globalThis.crypto || !globalThis.crypto.getRandomValues) { - if (!SystemJS_RandomBytes["cryptoWarnOnce"]) { + if (!globalThis["cryptoWarnOnce"]) { Logger.warn("This engine doesn't support crypto.getRandomValues. Please use a modern version or provide polyfill for 'globalThis.crypto.getRandomValues'."); - SystemJS_RandomBytes["cryptoWarnOnce"] = true; + globalThis["cryptoWarnOnce"] = true; } return -1; } @@ -196,526 +208,66 @@ var libSystemNativeBrowserJS = (function (exports) { // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. - - var trimmableExports = /*#__PURE__*/Object.freeze({ - __proto__: null, - SystemJS_RandomBytes: SystemJS_RandomBytes - }); - - // Licensed to the .NET Foundation under one or more agreements. - // The .NET Foundation licenses this file to you under the MIT license. - 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) { - return false; - } - Module.HEAPU32[outDataStartPtr >> 2] = assembly.ptr; - // upper bits are cleared by the C caller - Module.HEAPU32[outSize >> 2] = assembly.length; - return true; - } - browserHostExternalAssemblyProbe["__deps"] = ["loadedAssemblies"]; - function browserHostResolveMain(exitCode) { - loaderExports.browserHostResolveMain(exitCode); - } - function browserHostRejectMain(reason) { - loaderExports.browserHostRejectMain(reason); - } - 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"); - } - //setEnvironmentVariable["__deps"] = ["setenv"]; - - // 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. - async function initialize(internals) { - const runtimeApiFunctions = { - 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 nativeExports = { - registerDllBytes, - isSharedArrayBuffer - }; + function initialize(internals) { + const nativeBrowserExportsLocal = {}; setInternals(internals); - Object.assign(internals.runtimeApi, runtimeApiFunctions); - Object.assign(nativeExports, nativeExports); - internals.nativeExportsTable = [...nativeExportsToTable(nativeExports)]; + internals.nativeBrowserExportsTable = [...nativeBrowserExportsToTable(nativeBrowserExportsLocal)]; internals.updates.push(updateInternalsImpl); updateInternals(); } - var exchange = /*#__PURE__*/Object.freeze({ - __proto__: null, - _zero_region: _zero_region, - assert_int_in_range: assert_int_in_range, - browserHostExternalAssemblyProbe: browserHostExternalAssemblyProbe, - browserHostRejectMain: browserHostRejectMain, - browserHostResolveMain: browserHostResolveMain, - copyBytes: copyBytes, - exit: exit, - getHeapB32: getHeapB32, - getHeapB8: getHeapB8, - getHeapF32: getHeapF32, - getHeapF64: getHeapF64, - getHeapI16: getHeapI16, - getHeapI16_local: getHeapI16_local, - getHeapI32: getHeapI32, - getHeapI32_local: getHeapI32_local, - getHeapI52: getHeapI52, - getHeapI64Big: getHeapI64Big, - getHeapI8: getHeapI8, - getHeapU16: getHeapU16, - getHeapU16_local: getHeapU16_local, - getHeapU32: getHeapU32, - getHeapU32_local: getHeapU32_local, - getHeapU52: getHeapU52, - getHeapU8: getHeapU8, - initialize: initialize, - isSharedArrayBuffer: isSharedArrayBuffer, - localHeapViewF32: localHeapViewF32, - localHeapViewF64: localHeapViewF64, - localHeapViewI16: localHeapViewI16, - localHeapViewI32: localHeapViewI32, - localHeapViewI64Big: localHeapViewI64Big, - localHeapViewI8: localHeapViewI8, - localHeapViewU16: localHeapViewU16, - localHeapViewU32: localHeapViewU32, - localHeapViewU8: localHeapViewU8, - max_int64_big: max_int64_big, - min_int64_big: min_int64_big, - registerDllBytes: registerDllBytes, - runMain: runMain, - runMainAndExit: runMainAndExit, - setEnvironmentVariable: setEnvironmentVariable, - setHeapB32: setHeapB32, - setHeapB8: setHeapB8, - setHeapF32: setHeapF32, - setHeapF64: setHeapF64, - setHeapI16: setHeapI16, - setHeapI32: setHeapI32, - setHeapI32_unchecked: setHeapI32_unchecked, - setHeapI52: setHeapI52, - setHeapI64Big: setHeapI64Big, - setHeapI8: setHeapI8, - setHeapU16: setHeapU16, - setHeapU16_local: setHeapU16_local, - setHeapU16_unchecked: setHeapU16_unchecked, - setHeapU32: setHeapU32, - setHeapU32_unchecked: setHeapU32_unchecked, - setHeapU52: setHeapU52, - setHeapU8: setHeapU8, - sharedArrayBufferDefined: sharedArrayBufferDefined - }); + exports.SystemJS_RandomBytes = SystemJS_RandomBytes; + exports.cross = crossModule; + exports.initialize = initialize; - // 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. - * It also implements part of public JS API related to memory and runtime hosting. - */ - // Exports that can be trimmed away by emscripten linker if not used. - function dotnetLibFactory() { - // Symbols that would be protected from emscripten linker - const commonInfraTransformed = { - Assert: Assert, - JSEngine: JSEngine, - Logger: Logger, - Module: Module, - runtimeApi: runtimeApi, - runtimeExports: runtimeExports, - nativeExports: nativeExports, - interopExports: interopExports, - loaderExports: loaderExports, - loadedAssemblies: loadedAssemblies, - loaderExportsFromTable: loaderExportsFromTable, - runtimeExportsFromTable: runtimeExportsFromTable, - nativeExportsFromTable: nativeExportsFromTable, - interopExportsFromTable: interopExportsFromTable, - nativeExportsToTable: nativeExportsToTable, - interopExportsToTable: interopExportsToTable, - setInternals: setInternals, - getInternals: getInternals, - updateInternals: updateInternals, - updateInternalsImpl: updateInternalsImpl, - }; - // Symbols that would be protected from emscripten linker - const exchangeTransformed = { - setHeapB32: setHeapB32, - setHeapB8: setHeapB8, - setHeapU8: setHeapU8, - setHeapU16: setHeapU16, - setHeapU32: setHeapU32, - setHeapI8: setHeapI8, - setHeapI16: setHeapI16, - setHeapI32: setHeapI32, - setHeapI52: setHeapI52, - setHeapU52: setHeapU52, - setHeapI64Big: setHeapI64Big, - setHeapF32: setHeapF32, - setHeapF64: setHeapF64, - getHeapB32: getHeapB32, - getHeapB8: getHeapB8, - getHeapU8: getHeapU8, - getHeapU16: getHeapU16, - getHeapU32: getHeapU32, - getHeapI8: getHeapI8, - getHeapI16: getHeapI16, - getHeapI32: getHeapI32, - getHeapI52: getHeapI52, - getHeapU52: getHeapU52, - getHeapI64Big: getHeapI64Big, - getHeapF32: getHeapF32, - getHeapF64: getHeapF64, - localHeapViewI8: localHeapViewI8, - localHeapViewI16: localHeapViewI16, - localHeapViewI32: localHeapViewI32, - localHeapViewI64Big: localHeapViewI64Big, - localHeapViewU8: localHeapViewU8, - localHeapViewU16: localHeapViewU16, - localHeapViewU32: localHeapViewU32, - localHeapViewF32: localHeapViewF32, - localHeapViewF64: localHeapViewF64, - isSharedArrayBuffer: isSharedArrayBuffer, - exit: exit, - runMain: runMain, - runMainAndExit: runMainAndExit, - setEnvironmentVariable: setEnvironmentVariable, - registerDllBytes: registerDllBytes, - browserHostExternalAssemblyProbe: browserHostExternalAssemblyProbe, - browserHostRejectMain: browserHostRejectMain, - browserHostResolveMain: browserHostResolveMain, - _zero_region: _zero_region, - assert_int_in_range: assert_int_in_range, - max_int64_big: max_int64_big, - min_int64_big: min_int64_big, - sharedArrayBufferDefined: sharedArrayBufferDefined, - }; - const moduleDeps = ["$ENV"]; - for (const exportName of Reflect.ownKeys(commonInfraTransformed)) { - const emName = "$" + exportName.toString(); - commonInfraTransformed[emName] = commonInfra[exportName]; - moduleDeps.push(emName); - } - for (const exportName of Reflect.ownKeys(exchangeTransformed)) { - const emName = "$" + exportName.toString(); - exchangeTransformed[emName] = exchange[exportName]; - moduleDeps.push(emName); - } - const trimmableDeps = {}; - for (const exportName of Reflect.ownKeys(trimmableExports)) { - const emName = exportName.toString() + "__deps"; - const deps = trimmableExports[exportName]["__deps"]; - if (deps) { - trimmableDeps[emName] = deps; - } - } + 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); - if (dotnetInternals.config && dotnetInternals.config.environmentVariables) { - Object.assign(ENV, dotnetInternals.config.environmentVariables); - } } }, - initialize: initialize, }, "$DOTNET__postset": "DOTNET.selfInitialize();", - "$DOTNET__deps": moduleDeps, - ...commonInfraTransformed, - ...exchangeTransformed, - ...trimmableExports, - ...trimmableDeps }; + + // 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); } - dotnetLibFactory(); - - exports.commonInfra = commonInfra; - exports.exchange = exchange; - exports.trimmableExports = trimmableExports; - + libFactory(); return exports; - })({}); 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 index 3bc4a355ac01e3..d359657c4cdc38 100644 --- a/src/native/libs/System.Runtime.InteropServices.JavaScript.Native/dotnet.runtime.js +++ b/src/native/libs/System.Runtime.InteropServices.JavaScript.Native/dotnet.runtime.js @@ -3,162 +3,13 @@ //! This is generated file, see src/native/libs/Browser/rollup.config.defines.js -var ProductVersion = "10.0.0-dev"; - -var BuildConfiguration = "Debug"; - -var GitHash = "becd20635d51b17f7f344df90775c63e7e744d11"; - -// 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. -let JSEngine; let Module; let runtimeApi; let Logger = {}; let Assert = {}; +let JSEngine = {}; let loaderExports = {}; let runtimeExports = {}; let nativeExports = {}; @@ -181,38 +32,24 @@ function updateInternals() { } } function updateInternalsImpl() { - if (!JSEngine) { - 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; - 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, - }; - } if (Object.keys(loaderExports).length === 0 && dotnetInternals.loaderExportsTable) { loaderExports = {}; Logger = {}; Assert = {}; - loaderExportsFromTable(dotnetInternals.loaderExportsTable, Logger, Assert, loaderExports); + JSEngine = {}; + loaderExportsFromTable(dotnetInternals.loaderExportsTable, Logger, Assert, JSEngine, loaderExports); } if (Object.keys(runtimeExports).length === 0 && dotnetInternals.runtimeExportsTable) { runtimeExports = {}; runtimeExportsFromTable(dotnetInternals.runtimeExportsTable, runtimeExports); } - if (Object.keys(nativeExports).length === 0 && dotnetInternals.nativeExportsTable) { + if (Object.keys(nativeExports).length === 0 && dotnetInternals.hostNativeExportsTable) { nativeExports = {}; - nativeExportsFromTable(dotnetInternals.nativeExportsTable, nativeExports); + hostNativeExportsFromTable(dotnetInternals.hostNativeExportsTable, nativeExports); } - if (Object.keys(interopExports).length === 0 && dotnetInternals.interopExportsTable) { + if (Object.keys(interopExports).length === 0 && dotnetInternals.interopJavaScriptNativeExportsTable) { interopExports = {}; - interopExportsFromTable(dotnetInternals.interopExportsTable, interopExports); + interopJavaScriptNativeExportsFromTable(dotnetInternals.interopJavaScriptNativeExportsTable, interopExports); } } /** @@ -225,12 +62,17 @@ function loaderExportsToTable(logger, assert, loaderExports) { 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 loaderExportsFromTable(table, logger, assert, loaderExports) { +function loaderExportsFromTable(table, logger, assert, jsEngine, loaderExports) { const loggerLocal = { info: table[0], warn: table[1], @@ -240,13 +82,26 @@ function loaderExportsFromTable(table, logger, assert, loaderExports) { check: table[3], }; const loaderExportsLocal = { - browserHostResolveMain: table[4], - browserHostRejectMain: table[5], - getRunMainPromise: table[6], + 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(loaderExports, loaderExportsLocal); + Object.assign(jsEngine, jsEngineLocal); } // eslint-disable-next-line @typescript-eslint/no-unused-vars function runtimeExportsToTable(map) { @@ -255,13 +110,13 @@ function runtimeExportsToTable(map) { function runtimeExportsFromTable(table, runtime) { Object.assign(runtime, {}); } -function nativeExportsToTable(map) { +function hostNativeExportsToTable(map) { return [ map.registerDllBytes, map.isSharedArrayBuffer, ]; } -function nativeExportsFromTable(table, native) { +function hostNativeExportsFromTable(table, native) { const nativeLocal = { registerDllBytes: table[0], isSharedArrayBuffer: table[1], @@ -269,190 +124,46 @@ function nativeExportsFromTable(table, native) { Object.assign(native, nativeLocal); } // eslint-disable-next-line @typescript-eslint/no-unused-vars -function interopExportsToTable(map) { +function interopJavaScriptNativeExportsToTable(map) { return []; } -function interopExportsFromTable(table, interop) { +function interopJavaScriptNativeExportsFromTable(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. -// 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. // 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. -/// 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 nativeBrowserExportsToTable(map) { + return []; } -function isControllablePromise(promise) { - return promise[promise_control_symbol] !== undefined; +function nativeBrowserExportsFromTable(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. -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. -function initialize() { - 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 = { - getRunMainPromise, - browserHostRejectMain, - browserHostResolveMain, +function initialize(internals) { + const runtimeApiLocal = { + getAssemblyExports, + setModuleImports, }; - const logger = { - info, - warn, - error, - }; - const assert = { - check, - }; - Object.assign(runtimeApi, runtimeApiFunctions); - Object.assign(Logger, logger); - Object.assign(Assert, assert); - Object.assign(loaderExports, loaderFunctions); - dotnetInternals.loaderExportsTable = [...loaderExportsToTable(Logger, Assert, loaderExports)]; - updates.push(updateInternalsImpl); + const runtimeExportsLocal = {}; + setInternals(internals); + Object.assign(internals.runtimeApi, runtimeApiLocal); + internals.runtimeExportsTable = [...runtimeExportsToTable(runtimeExportsLocal)]; + internals.updates.push(updateInternalsImpl); updateInternals(); - return runtimeApi; +} +// 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. 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 index dd62b2c63e7b30..a335f11f1dffe3 100644 --- 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 @@ -3,16 +3,16 @@ //! This is generated file, see src/native/libs/Browser/rollup.config.defines.js -var libSystemRuntimeInteropServicesJavaScriptNativeBrowserJS = (function (exports) { +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 JSEngine; let Module; let runtimeApi; let Logger = {}; let Assert = {}; + let JSEngine = {}; let loaderExports = {}; let runtimeExports = {}; let nativeExports = {}; @@ -35,38 +35,24 @@ var libSystemRuntimeInteropServicesJavaScriptNativeBrowserJS = (function (export } } function updateInternalsImpl() { - if (!JSEngine) { - 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; - 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, - }; - } if (Object.keys(loaderExports).length === 0 && dotnetInternals.loaderExportsTable) { loaderExports = {}; Logger = {}; Assert = {}; - loaderExportsFromTable(dotnetInternals.loaderExportsTable, Logger, Assert, loaderExports); + JSEngine = {}; + loaderExportsFromTable(dotnetInternals.loaderExportsTable, Logger, Assert, JSEngine, loaderExports); } if (Object.keys(runtimeExports).length === 0 && dotnetInternals.runtimeExportsTable) { runtimeExports = {}; runtimeExportsFromTable(dotnetInternals.runtimeExportsTable, runtimeExports); } - if (Object.keys(nativeExports).length === 0 && dotnetInternals.nativeExportsTable) { + if (Object.keys(nativeExports).length === 0 && dotnetInternals.hostNativeExportsTable) { nativeExports = {}; - nativeExportsFromTable(dotnetInternals.nativeExportsTable, nativeExports); + hostNativeExportsFromTable(dotnetInternals.hostNativeExportsTable, nativeExports); } - if (Object.keys(interopExports).length === 0 && dotnetInternals.interopExportsTable) { + if (Object.keys(interopExports).length === 0 && dotnetInternals.interopJavaScriptNativeExportsTable) { interopExports = {}; - interopExportsFromTable(dotnetInternals.interopExportsTable, interopExports); + interopJavaScriptNativeExportsFromTable(dotnetInternals.interopJavaScriptNativeExportsTable, interopExports); } } /** @@ -79,12 +65,17 @@ var libSystemRuntimeInteropServicesJavaScriptNativeBrowserJS = (function (export 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 loaderExportsFromTable(table, logger, assert, loaderExports) { + function loaderExportsFromTable(table, logger, assert, jsEngine, loaderExports) { const loggerLocal = { info: table[0], warn: table[1], @@ -94,13 +85,26 @@ var libSystemRuntimeInteropServicesJavaScriptNativeBrowserJS = (function (export check: table[3], }; const loaderExportsLocal = { - browserHostResolveMain: table[4], - browserHostRejectMain: table[5], - getRunMainPromise: table[6], + 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(loaderExports, loaderExportsLocal); + Object.assign(jsEngine, jsEngineLocal); } // eslint-disable-next-line @typescript-eslint/no-unused-vars function runtimeExportsToTable(map) { @@ -109,13 +113,13 @@ var libSystemRuntimeInteropServicesJavaScriptNativeBrowserJS = (function (export function runtimeExportsFromTable(table, runtime) { Object.assign(runtime, {}); } - function nativeExportsToTable(map) { + function hostNativeExportsToTable(map) { return [ map.registerDllBytes, map.isSharedArrayBuffer, ]; } - function nativeExportsFromTable(table, native) { + function hostNativeExportsFromTable(table, native) { const nativeLocal = { registerDllBytes: table[0], isSharedArrayBuffer: table[1], @@ -123,10 +127,18 @@ var libSystemRuntimeInteropServicesJavaScriptNativeBrowserJS = (function (export Object.assign(native, nativeLocal); } // eslint-disable-next-line @typescript-eslint/no-unused-vars - function interopExportsToTable(map) { + function interopJavaScriptNativeExportsToTable(map) { return []; } - function interopExportsFromTable(table, interop) { + function interopJavaScriptNativeExportsFromTable(table, interop) { + const interopLocal = {}; + Object.assign(interop, interopLocal); + } + // eslint-disable-next-line @typescript-eslint/no-unused-vars + function nativeBrowserExportsToTable(map) { + return []; + } + function nativeBrowserExportsFromTable(table, interop) { const interopLocal = {}; Object.assign(interop, interopLocal); } @@ -142,15 +154,17 @@ var libSystemRuntimeInteropServicesJavaScriptNativeBrowserJS = (function (export get Module() { return Module; }, get dotnetInternals() { return dotnetInternals; }, getInternals: getInternals, + hostNativeExportsFromTable: hostNativeExportsFromTable, + hostNativeExportsToTable: hostNativeExportsToTable, get interopExports() { return interopExports; }, - interopExportsFromTable: interopExportsFromTable, - interopExportsToTable: interopExportsToTable, + interopJavaScriptNativeExportsFromTable: interopJavaScriptNativeExportsFromTable, + interopJavaScriptNativeExportsToTable: interopJavaScriptNativeExportsToTable, get loaderExports() { return loaderExports; }, loaderExportsFromTable: loaderExportsFromTable, loaderExportsToTable: loaderExportsToTable, + nativeBrowserExportsFromTable: nativeBrowserExportsFromTable, + nativeBrowserExportsToTable: nativeBrowserExportsToTable, get nativeExports() { return nativeExports; }, - nativeExportsFromTable: nativeExportsFromTable, - nativeExportsToTable: nativeExportsToTable, get runtimeApi() { return runtimeApi; }, get runtimeExports() { return runtimeExports; }, runtimeExportsFromTable: runtimeExportsFromTable, @@ -160,53 +174,39 @@ var libSystemRuntimeInteropServicesJavaScriptNativeBrowserJS = (function (export updateInternalsImpl: updateInternalsImpl }); - // Licensed to the .NET Foundation under one or more agreements. - // The .NET Foundation licenses this file to you under the MIT license. - async function initialize(internals) { - const interopExportsFunctions = {}; - Object.assign(interopExports, interopExportsFunctions); - internals.interopExportsTable = [...interopExportsToTable(interopExportsFunctions)]; - internals.updates.push(updateInternalsImpl); - updateInternals(); - } - - var nativeExchange = /*#__PURE__*/Object.freeze({ - __proto__: null, - initialize: initialize - }); - // 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 + // WASM-TODO implementation Logger.error("SystemInteropJS_InvokeJSImportST called"); return -1; } - SystemInteropJS_InvokeJSImportST["__deps"] = ["loadedAssemblies"]; + function initialize(internals) { + const interopJavaScriptNativeExportsLocal = {}; + setInternals(internals); + internals.interopJavaScriptNativeExportsTable = [...interopJavaScriptNativeExportsToTable(interopJavaScriptNativeExportsLocal)]; + internals.updates.push(updateInternalsImpl); + updateInternals(); + } - var trimmableExports = /*#__PURE__*/Object.freeze({ - __proto__: null, - SystemInteropJS_InvokeJSImportST: SystemInteropJS_InvokeJSImportST - }); + exports.SystemInteropJS_InvokeJSImportST = SystemInteropJS_InvokeJSImportST; + exports.cross = crossModule; + exports.initialize = initialize; - // 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 DotnetInteropLibFactory() { - // Symbols that would be protected from emscripten linker - const moduleDeps = ["$DOTNET"]; - const trimmableDeps = {}; - for (const exportName of Reflect.ownKeys(trimmableExports)) { - const emName = exportName.toString() + "__deps"; - const deps = trimmableExports[exportName]["__deps"]; - if (deps) { - trimmableDeps[emName] = deps; - } - } + 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: () => { @@ -215,22 +215,34 @@ var libSystemRuntimeInteropServicesJavaScriptNativeBrowserJS = (function (export DOTNET_INTEROP.initialize(dotnetInternals); } }, - initialize: initialize, }, - "$DOTNET_INTEROP__deps": moduleDeps, + "$DOTNET_INTEROP__deps": ["$DOTNET"], "$DOTNET_INTEROP__postset": "DOTNET_INTEROP.selfInitialize();", - ...trimmableExports, - ...trimmableDeps, }; + + // this executes the function at compile time in order to capture exports + const exports = libInteropJavaScriptNative({}); + 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; + 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); } - DotnetInteropLibFactory(); - - exports.commonInfra = crossModule; - exports.exchange = nativeExchange; - exports.trimmableExports = trimmableExports; - + libFactory(); return exports; - })({}); diff --git a/src/native/package.json b/src/native/package.json index 335505703723b8..c67c0721191489 100644 --- a/src/native/package.json +++ b/src/native/package.json @@ -10,6 +10,7 @@ "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", diff --git a/src/native/rollup.config.defines.js b/src/native/rollup.config.defines.js deleted file mode 100644 index 5c3fb8096fdc7d..00000000000000 --- a/src/native/rollup.config.defines.js +++ /dev/null @@ -1,33 +0,0 @@ -//! Licensed to the .NET Foundation under one or more agreements. -//! The .NET Foundation licenses this file to you under the MIT license. - -import gitCommitInfo from "git-commit-info"; - -export const configuration = process.argv[2] || "Debug"; -export const productVersion = process.argv[3] || "10.0.0-dev"; -export const isContinuousIntegrationBuild = process.argv[4] === "true" ? true : false; - -console.log(`Rollup configuration: Configuration=${configuration}, ProductVersion=${productVersion}, ContinuousIntegrationBuild=${isContinuousIntegrationBuild}`); - -export const banner = "//! Licensed to the .NET Foundation under one or more agreements.\n//! The .NET Foundation licenses this file to you under the MIT license.\n//! This is generated file, see src/native/libs/Browser/rollup.config.defines.js\n\n"; -export const banner_dts = banner + "//! This is not considered public API with backward compatibility guarantees. \n"; -export const keep_classnames = /(ManagedObject|ManagedError|Span|ArraySegment)/; -export const reserved = ["Assert", "JSEngine", "Logger", "Module", "dotnetInternals", "interopExports", "loaderExports", "nativeExports", "runtimeApi", "runtimeExports"]; -export const externalDependencies = ["module", "process", "perf_hooks", "node:crypto"]; -export const artifactsObjDir = "../../artifacts/obj"; -export const isDebug = configuration !== "Release"; - -let gitHash; -try { - const gitInfo = gitCommitInfo(); - gitHash = gitInfo.hash; -} catch (e) { - gitHash = "unknown"; -} - -export const envConstants = { - productVersion, - configuration, - gitHash, - isContinuousIntegrationBuild, -}; diff --git a/src/native/rollup.config.plugins.js b/src/native/rollup.config.plugins.js deleted file mode 100644 index 6cab1709b6e9ab..00000000000000 --- a/src/native/rollup.config.plugins.js +++ /dev/null @@ -1,153 +0,0 @@ -//! Licensed to the .NET Foundation under one or more agreements. -//! The .NET Foundation licenses this file to you under the MIT license. - -import { createHash } from "crypto"; -import { readFile, writeFile, mkdir } from "fs/promises"; -import virtual from "@rollup/plugin-virtual"; -import * as fs from "fs"; -import * as path from "path"; -import terser from "@rollup/plugin-terser"; - -import { isContinuousIntegrationBuild, keep_classnames, reserved } from "./rollup.config.defines.js" - -export const terserPlugin = () => terser({ - compress: { - defaults: true, - passes: 2, - drop_debugger: false, // we invoke debugger - drop_console: false, // we log to console - keep_classnames, - ecma: "2015", - toplevel: true, - module: true, - }, - }, - mangle: { - keep_classnames, - reserved, - toplevel: true, - module: true, - }, -}); - -// this would create .sha256 file next to the output file, so that we do not touch datetime of the file if it's same -> faster incremental build. -export const writeOnChangePlugin = () => ({ - name: "writeOnChange", - generateBundle: writeWhenChanged -}); - -// Drop invocation from IIFE -export function iife2fe() { - return { - name: "iife2fe", - generateBundle: (options, bundle) => { - const name = Object.keys(bundle)[0]; - if (name.endsWith(".map")) return; - const asset = bundle[name]; - const code = asset.code; - //throw new Error("iife2fe " + code); - asset.code = code - .replace(/}\({}\);/, "};") // }({}); ->}; - .replace(/}\)\({}\);/, "});") // })({}); ->}); - ; - } - }; -} - -// force always unix line ending -export const alwaysLF = () => ({ - name: "writeOnChange", - generateBundle: (options, bundle) => { - const name = Object.keys(bundle)[0]; - const asset = bundle[name]; - const code = asset.code; - asset.code = code.replace(/\r/g, ""); - } -}); - -async function writeWhenChanged(options, bundle) { - try { - const name = Object.keys(bundle)[0]; - const asset = bundle[name]; - const code = asset.code; - const hashFileName = options.file + ".sha256"; - const oldHashExists = await checkFileExists(hashFileName); - const oldFileExists = await checkFileExists(options.file); - - const newHash = createHash("sha256").update(code).digest("hex"); - - let isOutputChanged = true; - if (oldHashExists && oldFileExists) { - const oldHash = await readFile(hashFileName, { encoding: "ascii" }); - isOutputChanged = oldHash !== newHash; - } - if (isOutputChanged) { - const dir = path.dirname(options.file); - if (!await checkFileExists(dir)) { - await mkdir(dir, { recursive: true }); - } - await writeFile(hashFileName, newHash); - } else { - // this.warn('No change in ' + options.file) - delete bundle[name]; - } - } catch (ex) { - this.warn(ex.toString()); - } -} - -function checkFileExists(file) { - return fs.promises.access(file, fs.constants.F_OK) - .then(() => true) - .catch(() => false); -} - -export function onwarn(warning) { - if (warning.code === "CIRCULAR_DEPENDENCY") { - return; - } - - if (warning.code === "UNRESOLVED_IMPORT" && warning.exporter === "process") { - return; - } - - if (warning.code === "PLUGIN_WARNING" && warning.message.indexOf("sourcemap") !== -1) { - return; - } - - // eslint-disable-next-line no-console - console.warn(`(!) ${warning.toString()} ${warning.code}`); -} - -export function consts(dict) { - // implement rollup-plugin-const in terms of @rollup/plugin-virtual - // It's basically the same thing except "consts" names all its modules with a "consts:" prefix, - // and the virtual module always exports a single default binding (the const value). - - let newDict = {}; - for (const k in dict) { - const newKey = "consts:" + k; - const newVal = JSON.stringify(dict[k]); - newDict[newKey] = `export default ${newVal}`; - } - return virtual(newDict); -} - -const locationCache = {}; -export function sourcemapPathTransform(relativeSourcePath, sourcemapPath) { - let res = locationCache[relativeSourcePath]; - if (res === undefined) { - if (!isContinuousIntegrationBuild) { - const sourcePath = path.resolve( - path.dirname(sourcemapPath), - relativeSourcePath - ); - res = `file:///${sourcePath.replace(/\\/g, "/")}`; - } else { - relativeSourcePath = relativeSourcePath.substring(12); - res = `https://raw.githubusercontent.com/dotnet/runtime/${gitHash}/${relativeSourcePath}`; - } - locationCache[relativeSourcePath] = res; - } - return res; -} diff --git a/src/native/rollup.config.js b/src/native/rollup.stub.js similarity index 81% rename from src/native/rollup.config.js rename to src/native/rollup.stub.js index 11f582e39e38e5..4f9c7d86a0d39a 100644 --- a/src/native/rollup.config.js +++ b/src/native/rollup.stub.js @@ -3,12 +3,19 @@ import { promises as fs } from "fs"; import path from "path"; -import { artifactsObjDir, configuration } from "./rollup.config.defines.js" /** * 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`], From 7ffcf3fc5215145def0fd07b3a58f1ffce8a7bac Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Mon, 22 Sep 2025 15:17:46 +0200 Subject: [PATCH 14/25] improve readme --- src/native/corehost/browserhost/ReadMe.md | 9 +++++++-- src/native/libs/System.Native.Browser/ReadMe.md | 8 +++++--- .../ReadMe.md | 12 +++++++----- 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/src/native/corehost/browserhost/ReadMe.md b/src/native/corehost/browserhost/ReadMe.md index d408e16e6ea438..e6b447418c01ea 100644 --- a/src/native/corehost/browserhost/ReadMe.md +++ b/src/native/corehost/browserhost/ReadMe.md @@ -7,7 +7,6 @@ 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 TypeScript project that is compiled via `src\native\rollup.config.js`. It's **JavaScript ES6 module** - `loader/dotnet.ts` compiled -> `dotnet.js` @@ -17,9 +16,15 @@ It's **JavaScript ES6 module** 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. -- `libBrowserHost.js` linked -> `dotnet.native.js` +- `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` +Emscripten compilations is part of `src/native/corehost/CMakeLists.txt` +Final app static linking happens here in `CMakeLists.txt` diff --git a/src/native/libs/System.Native.Browser/ReadMe.md b/src/native/libs/System.Native.Browser/ReadMe.md index fa7aed78fc516e..2fad74c882e493 100644 --- a/src/native/libs/System.Native.Browser/ReadMe.md +++ b/src/native/libs/System.Native.Browser/ReadMe.md @@ -1,15 +1,17 @@ # System.Native.Browser This library implements PAL for the VM/runtime. -It also implements part of public JS API related to memory and runtime hosting. 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 -- `libSystem.Native.Browser.ts` compiled -> `libSystem.Native.Browser.js` linked ->`dotnet.native.js` +- `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` -TypeScript is driven by `src/native/rollup.config.js` +## Build +TypeScript is compiled by `src/native/rollup.config.js` 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/ReadMe.md b/src/native/libs/System.Runtime.InteropServices.JavaScript.Native/ReadMe.md index 216bd296a24960..b7e67946b25dba 100644 --- a/src/native/libs/System.Runtime.InteropServices.JavaScript.Native/ReadMe.md +++ b/src/native/libs/System.Runtime.InteropServices.JavaScript.Native/ReadMe.md @@ -1,15 +1,17 @@ # System.Runtime.InteropServices.JavaScript.Native This library implements interop between JS and .NET -It also implements public JS API related JS interop. +This library also implements public JS API related JS interop. -## Emscripten library -- `libSystem.Runtime.InteropServices.JavaScript.Native.ts` compiled -> `libSystem.Runtime.InteropServices.JavaScript.Native.js` linked -> `dotnet.native.js` +## 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` -## ES6 JavaScript module +## JavaScript interop helpers - `dotnet.runtime.ts` compiled -> `dotnet.runtime.js` -TypeScript is driven by `src/native/rollup.config.js` +## Build +TypeScript is compiled by `src/native/rollup.config.js` Emscripten compilations is part of `/src/native/libs/CMakeLists.txt` Final static linking happens in `/src/native/corehost/browserhost/CMakeLists.txt` From 8972a87080e98f6e61444a1bffb42f3930ee353e Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Mon, 22 Sep 2025 15:22:47 +0200 Subject: [PATCH 15/25] docs --- docs/workflow/building/coreclr/wasm.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/docs/workflow/building/coreclr/wasm.md b/docs/workflow/building/coreclr/wasm.md index 0024aa758d0eee..c5d0d291202305 100644 --- a/docs/workflow/building/coreclr/wasm.md +++ b/docs/workflow/building/coreclr/wasm.md @@ -71,6 +71,19 @@ node ./corerun.js -c /runtime3/artifacts/bin/coreclr/browser.wasm.Debug/IL /runt 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 /runtime3/artifacts/bin/microsoft.netcore.app.runtime.browser-wasm/Debug/runtimes/browser-wasm/lib/net10.0/*.dll /runtime3/artifacts/bin/coreclr/browser.wasm.Debug/corehost +cp helloworld.dll /runtime3/artifacts/bin/coreclr/browser.wasm.Debug/corehost +cd /runtime3/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 ### Chrome DevTools with DWARF Support From b5eb4255e8d02230b7465187dad050a7bf15c2a9 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Mon, 22 Sep 2025 17:27:04 +0200 Subject: [PATCH 16/25] improve rollup + npm install --- .../libs/System.Native.Browser/CMakeLists.txt | 49 +++++++++---------- src/native/rollup.stub.js | 6 ++- 2 files changed, 29 insertions(+), 26 deletions(-) diff --git a/src/native/libs/System.Native.Browser/CMakeLists.txt b/src/native/libs/System.Native.Browser/CMakeLists.txt index a4d4e947876735..ef53459c67af5a 100644 --- a/src/native/libs/System.Native.Browser/CMakeLists.txt +++ b/src/native/libs/System.Native.Browser/CMakeLists.txt @@ -13,34 +13,35 @@ add_library(System.Native.Browser-Static 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) - -file(GLOB_RECURSE ROLLUP_TS_SOURCES - "${CMAKE_CURRENT_SOURCE_DIR}/*.ts" - "${CMAKE_CURRENT_SOURCE_DIR}/*.js" - "${CMAKE_CURRENT_SOURCE_DIR}/../System.Runtime.InteropServices.JavaScript.Native/*.ts" - "${CMAKE_CURRENT_SOURCE_DIR}/../System.Runtime.InteropServices.JavaScript.Native/*.js" - "${CMAKE_CURRENT_SOURCE_DIR}/../Common/JavaScript/*.ts" - "${CMAKE_CURRENT_SOURCE_DIR}/../Common/JavaScript/*.js" - "${CMAKE_CURRENT_SOURCE_DIR}/../../corehost/browserhost/*.ts" - "${CMAKE_CURRENT_SOURCE_DIR}/../../corehost/browserhost/*.js" - "${CMAKE_CURRENT_SOURCE_DIR}../../package.json" - "${CMAKE_CURRENT_SOURCE_DIR}../../tsconfig.json" - "${CMAKE_CURRENT_SOURCE_DIR}/../../node_modules/.npm-stamp" +# 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" - # WASM-TODO "${CLR_ARTIFACTS_OBJ_DIR}/coreclr/browser.wasm.${CMAKE_BUILD_TYPE}/corehost/dotnet.js.map" "${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" - # WASM-TODO "${CLR_ARTIFACTS_OBJ_DIR}/coreclr/browser.wasm.${CMAKE_BUILD_TYPE}/corehost/libBrowserHost.js.map" "${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Native.Browser/libSystem.Native.Browser.js" - # WASM-TODO "${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Native.Browser/libSystem.Native.Browser.js.map" "${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Native.Browser/dotnet.runtime.js" - # WASM-TODO "${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Native.Browser/dotnet.runtime.js.map" "${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Runtime.InteropServices.JavaScript.Native/libSystem.Runtime.InteropServices.JavaScript.Native.js" - # WASM-TODO "${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Runtime.InteropServices.JavaScript.Native/libSystem.Runtime.InteropServices.JavaScript.Native.js.map" ) + +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") @@ -51,7 +52,8 @@ if(NOT CI_BUILD_JS) endif() add_custom_command( - OUTPUT ${ROLLUP_OUTPUTS} + 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" @@ -59,18 +61,15 @@ add_custom_command( VERBATIM ) +# WASM-TODO fixme: make this incremental add_custom_target(System.Native.Browser-Rollup - DEPENDS ${ROLLUP_OUTPUTS} + DEPENDS ${ROLLUP_STAMP} ) add_dependencies(System.Native.Browser-Static System.Native.Browser-Rollup) set(NPM_INSTALL_OUTPUTS - "${CMAKE_CURRENT_SOURCE_DIR}/../../node_modules/.bin/rollup" - "${CMAKE_CURRENT_SOURCE_DIR}/../../node_modules/.bin/terser" - "${CMAKE_CURRENT_SOURCE_DIR}/../../node_modules/.bin/tsc" - "${CMAKE_CURRENT_SOURCE_DIR}/../../node_modules/.bin/eslint" - "${CMAKE_CURRENT_SOURCE_DIR}/../../node_modules/.npm-stamp" + "${CMAKE_CURRENT_SOURCE_DIR}/../../node_modules/.package-lock.json" ) set(NPM_INSTALL_SOURCES diff --git a/src/native/rollup.stub.js b/src/native/rollup.stub.js index 4f9c7d86a0d39a..938a562735d72b 100644 --- a/src/native/rollup.stub.js +++ b/src/native/rollup.stub.js @@ -31,10 +31,14 @@ const copies = [ `${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, dest); + await fs.copyFile(absoluteSrc, absoluteDest); + // await fs.utimes(absoluteDest, now, now); } +await fs.writeFile(`${artifactsObjDir}/coreclr/browser.wasm.${configuration}/corehost/.rollup.stamp`, new Date().toISOString()); From be0178ce0ffeb428e75470adf2079bc234aeb214 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Mon, 22 Sep 2025 20:17:03 +0200 Subject: [PATCH 17/25] feedback from kg --- src/coreclr/hosts/corerun/CMakeLists.txt | 8 +++- src/coreclr/hosts/corewasmrun/CMakeLists.txt | 9 +++- .../corehost/browserhost/CMakeLists.txt | 44 ++++++++++++++++--- src/native/libs/CMakeLists.txt | 2 + .../libs/Common/JavaScript/types/internal.ts | 4 +- 5 files changed, 54 insertions(+), 13 deletions(-) diff --git a/src/coreclr/hosts/corerun/CMakeLists.txt b/src/coreclr/hosts/corerun/CMakeLists.txt index 813740797aff53..7b6683629b50e9 100644 --- a/src/coreclr/hosts/corerun/CMakeLists.txt +++ b/src/coreclr/hosts/corerun/CMakeLists.txt @@ -54,9 +54,13 @@ else(CLR_CMAKE_HOST_WIN32) 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 "${CMAKE_CURRENT_SOURCE_DIR}/libCorerun.pre.js;${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Native.Browser/libSystem.Native.Browser.js;" - LINK_FLAGS "--pre-js ${CMAKE_CURRENT_SOURCE_DIR}/libCorerun.pre.js --js-library ${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Native.Browser/libSystem.Native.Browser.js" + 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 diff --git a/src/coreclr/hosts/corewasmrun/CMakeLists.txt b/src/coreclr/hosts/corewasmrun/CMakeLists.txt index 3f83f398cc8373..600866a94201f6 100644 --- a/src/coreclr/hosts/corewasmrun/CMakeLists.txt +++ b/src/coreclr/hosts/corewasmrun/CMakeLists.txt @@ -17,9 +17,14 @@ 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 "${CMAKE_CURRENT_SOURCE_DIR}/libCorewasmrun.pre.js;${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Native.Browser/libSystem.Native.Browser.js;" - LINK_FLAGS "--pre-js ${CMAKE_CURRENT_SOURCE_DIR}/libCorewasmrun.pre.js --js-library ${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Native.Browser/libSystem.Native.Browser.js" + 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 diff --git a/src/native/corehost/browserhost/CMakeLists.txt b/src/native/corehost/browserhost/CMakeLists.txt index b08a1f2886732a..3594c31dac136b 100644 --- a/src/native/corehost/browserhost/CMakeLists.txt +++ b/src/native/corehost/browserhost/CMakeLists.txt @@ -43,25 +43,55 @@ LIST(APPEND NATIVE_LIBS # WASM-TODO set(RUNTIMEINFO_LIB runtimeinfo) -target_compile_options(browserhost PRIVATE -fwasm-exceptions) +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 "${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.Runtime.InteropServices.JavaScript.Native/libSystem.Runtime.InteropServices.JavaScript.Native.js;${CLR_ARTIFACTS_OBJ_DIR}/coreclr/browser.wasm.${CMAKE_BUILD_TYPE}/corehost/libBrowserHost.js;${CMAKE_CURRENT_SOURCE_DIR}/../../libs/System.Native.Browser/libSystem.Native.Browser.extpost.js;" - LINK_FLAGS "--js-library ${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Native.Browser/libSystem.Native.Browser.js --js-library ${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Runtime.InteropServices.JavaScript.Native/libSystem.Runtime.InteropServices.JavaScript.Native.js --js-library ${CLR_ARTIFACTS_OBJ_DIR}/coreclr/browser.wasm.${CMAKE_BUILD_TYPE}/corehost/libBrowserHost.js --extern-post-js ${CMAKE_CURRENT_SOURCE_DIR}/../../libs/System.Native.Browser/libSystem.Native.Browser.extpost.js " + 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}") -# WASM-TODO -Oz -sVERBOSE +if (UPPERCASE_CMAKE_BUILD_TYPE STREQUAL RELEASE) + target_link_options(browserhost PRIVATE + -sVERBOSE + -sASSERTIONS=1 + --emit-symbol-map + ) +endif () + target_link_options(browserhost PRIVATE -fwasm-exceptions -sEXIT_RUNTIME=0 -sINITIAL_MEMORY=134217728 + -sMAXIMUM_MEMORY=2147483648 + -sALLOW_MEMORY_GROWTH=1 + -sALLOW_TABLE_GROWTH=1 -sSTACK_SIZE=5MB -sMODULARIZE=1 -sEXPORT_ES6=1 + -sWASM_BIGINT=1 -sEXPORTED_RUNTIME_METHODS=UTF8ToString,cwrap,ccall,HEAPU8,HEAPU32,HEAPU64,BROWSER_HOST - -sEXPORTED_FUNCTIONS=_posix_memalign,_free,stackAlloc,stackRestore,stackSave,_browserHostInitializeCoreCLR,_browserHostExecuteAssembly + -sEXPORTED_FUNCTIONS=_posix_memalign,_free,stackAlloc,stackRestore,stackSave,_browserHostInitializeCoreCLR,_browserHostExecuteAssembly,___cpp_exception -sEXPORT_NAME=createDotnetRuntime + -msimd128 + -fwasm-exceptions -lnodefs.js + -emit-llvm + --source-map-base http://microsoft.com + -sLLD_REPORT_UNDEFINED + -sERROR_ON_UNDEFINED_SYMBOLS=1 + -Wno-unused-command-line-argument -Wl,-error-limit=0) target_link_libraries( @@ -88,9 +118,9 @@ set(SAMPLE_ASSETS # ${CLR_ARTIFACTS_OBJ_DIR}/sfx-finish/${CMAKE_BUILD_TYPE}/net10.0-browser/illink-wasm/System.Threading.dll # ${CLR_ARTIFACTS_BIN_DIR}/artifacts/bin/HelloWorld/${CMAKE_BUILD_TYPE}/net10.0/win-x64/HelloWorld.dll ${CLR_ARTIFACTS_OBJ_DIR}/coreclr/browser.wasm.${CMAKE_BUILD_TYPE}/corehost/dotnet.js - # WASM-TODO ${CLR_ARTIFACTS_OBJ_DIR}/coreclr/browser.wasm.${CMAKE_BUILD_TYPE}/corehost/dotnet.js.map + ${CLR_ARTIFACTS_OBJ_DIR}/coreclr/browser.wasm.${CMAKE_BUILD_TYPE}/corehost/dotnet.js.map ${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 - # WASM-TODO ${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Runtime.InteropServices.JavaScript.Native/dotnet.runtime.js.map + ${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Runtime.InteropServices.JavaScript.Native/dotnet.runtime.js.map ) install(FILES ${SAMPLE_ASSETS} DESTINATION corehost COMPONENT runtime) diff --git a/src/native/libs/CMakeLists.txt b/src/native/libs/CMakeLists.txt index 75cc2055d6e1fb..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 () diff --git a/src/native/libs/Common/JavaScript/types/internal.ts b/src/native/libs/Common/JavaScript/types/internal.ts index d8f6432ff182d6..d05e1f8f0e8305 100644 --- a/src/native/libs/Common/JavaScript/types/internal.ts +++ b/src/native/libs/Common/JavaScript/types/internal.ts @@ -3,7 +3,7 @@ import type { DotnetModuleConfig, RuntimeAPI, AssetEntry, LoaderConfig, LoadingResource } from "./public-api"; import type { CharPtr, EmscriptenModule, ManagedPointer, NativePointer, VoidPtr } from "./emscripten"; -import { InteropJavaScriptNativeExportsTable, LoaderExportsTable, HostNativeExportsTable, RuntimeExportsTable, NativeBrowserExports } from "./exchange"; +import { InteropJavaScriptNativeExportsTable, LoaderExportsTable, HostNativeExportsTable, RuntimeExportsTable, NativeBrowserExportsTable } from "./exchange"; export type GCHandle = { __brand: "GCHandle" @@ -112,7 +112,7 @@ export type InternalApis = { loaderExportsTable: LoaderExportsTable, hostNativeExportsTable: HostNativeExportsTable, interopJavaScriptNativeExportsTable: InteropJavaScriptNativeExportsTable, - nativeBrowserExportsTable: NativeBrowserExports, + nativeBrowserExportsTable: NativeBrowserExportsTable, config: LoaderConfigInternal, updates: (() => void)[], } From 3b3c95da9f96ab6c753931851f6f9634c35fc106 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Mon, 22 Sep 2025 20:43:05 +0200 Subject: [PATCH 18/25] update generated JS --- .../corehost/browserhost/CMakeLists.txt | 2 +- .../corehost/browserhost/libBrowserHost.js | 58 +++++++------ .../corehost/browserhost/loader/dotnet.js | 57 +++++++------ .../libSystem.Native.Browser.js | 78 +++++++++--------- .../dotnet.runtime.js | 49 ++++++----- ...ntime.InteropServices.JavaScript.Native.js | 81 ++++++++++--------- 6 files changed, 176 insertions(+), 149 deletions(-) diff --git a/src/native/corehost/browserhost/CMakeLists.txt b/src/native/corehost/browserhost/CMakeLists.txt index 3594c31dac136b..0aaafa964602bf 100644 --- a/src/native/corehost/browserhost/CMakeLists.txt +++ b/src/native/corehost/browserhost/CMakeLists.txt @@ -64,7 +64,7 @@ set_target_properties(browserhost PROPERTIES if (UPPERCASE_CMAKE_BUILD_TYPE STREQUAL RELEASE) target_link_options(browserhost PRIVATE - -sVERBOSE +# -sVERBOSE -sASSERTIONS=1 --emit-symbol-map ) diff --git a/src/native/corehost/browserhost/libBrowserHost.js b/src/native/corehost/browserhost/libBrowserHost.js index af9dbbca77b04d..4707bd40fcd310 100644 --- a/src/native/corehost/browserhost/libBrowserHost.js +++ b/src/native/corehost/browserhost/libBrowserHost.js @@ -15,8 +15,9 @@ var libBrowserHost = (function (exports) { let JSEngine = {}; let loaderExports = {}; let runtimeExports = {}; - let nativeExports = {}; + let hostExports = {}; let interopExports = {}; + let nativeBrowserExports = {}; let dotnetInternals; function getInternals() { return dotnetInternals; @@ -26,7 +27,7 @@ var libBrowserHost = (function (exports) { runtimeApi = dotnetInternals.runtimeApi; Module = dotnetInternals.runtimeApi.Module; } - function updateInternals() { + function updateAllInternals() { if (dotnetInternals.updates === undefined) { dotnetInternals.updates = []; } @@ -34,32 +35,36 @@ var libBrowserHost = (function (exports) { updateImpl(); } } - function updateInternalsImpl() { + function updateMyInternals() { if (Object.keys(loaderExports).length === 0 && dotnetInternals.loaderExportsTable) { loaderExports = {}; Logger = {}; Assert = {}; JSEngine = {}; - loaderExportsFromTable(dotnetInternals.loaderExportsTable, Logger, Assert, JSEngine, loaderExports); + expandLE(dotnetInternals.loaderExportsTable, Logger, Assert, JSEngine, loaderExports); } if (Object.keys(runtimeExports).length === 0 && dotnetInternals.runtimeExportsTable) { runtimeExports = {}; - runtimeExportsFromTable(dotnetInternals.runtimeExportsTable, runtimeExports); + expandRE(dotnetInternals.runtimeExportsTable, runtimeExports); } - if (Object.keys(nativeExports).length === 0 && dotnetInternals.hostNativeExportsTable) { - nativeExports = {}; - hostNativeExportsFromTable(dotnetInternals.hostNativeExportsTable, nativeExports); + if (Object.keys(hostExports).length === 0 && dotnetInternals.hostNativeExportsTable) { + hostExports = {}; + expandHE(dotnetInternals.hostNativeExportsTable, hostExports); } if (Object.keys(interopExports).length === 0 && dotnetInternals.interopJavaScriptNativeExportsTable) { interopExports = {}; - interopJavaScriptNativeExportsFromTable(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 loaderExportsToTable(logger, assert, loaderExports) { + function tabulateLE(logger, assert, loaderExports) { return [ logger.info, logger.warn, @@ -75,7 +80,7 @@ var libBrowserHost = (function (exports) { loaderExports.getRunMainPromise, ]; } - function loaderExportsFromTable(table, logger, assert, jsEngine, loaderExports) { + function expandLE(table, logger, assert, jsEngine, loaderExports) { const loggerLocal = { info: table[0], warn: table[1], @@ -107,19 +112,19 @@ var libBrowserHost = (function (exports) { Object.assign(jsEngine, jsEngineLocal); } // eslint-disable-next-line @typescript-eslint/no-unused-vars - function runtimeExportsToTable(map) { + function tabulateRE(map) { return []; } - function runtimeExportsFromTable(table, runtime) { + function expandRE(table, runtime) { Object.assign(runtime, {}); } - function hostNativeExportsToTable(map) { + function tabulateHE(map) { return [ map.registerDllBytes, map.isSharedArrayBuffer, ]; } - function hostNativeExportsFromTable(table, native) { + function expandHE(table, native) { const nativeLocal = { registerDllBytes: table[0], isSharedArrayBuffer: table[1], @@ -127,18 +132,18 @@ var libBrowserHost = (function (exports) { Object.assign(native, nativeLocal); } // eslint-disable-next-line @typescript-eslint/no-unused-vars - function interopJavaScriptNativeExportsToTable(map) { + function tabulateJSNE(map) { return []; } - function interopJavaScriptNativeExportsFromTable(table, interop) { + function expandJSNE(table, interop) { const interopLocal = {}; Object.assign(interop, interopLocal); } // eslint-disable-next-line @typescript-eslint/no-unused-vars - function nativeBrowserExportsToTable(map) { + function tabulateNBE(map) { return []; } - function nativeBrowserExportsFromTable(table, interop) { + function expandNBE(table, interop) { const interopLocal = {}; Object.assign(interop, interopLocal); } @@ -462,9 +467,9 @@ var libBrowserHost = (function (exports) { }; setInternals(internals); Object.assign(internals.runtimeApi, runtimeApiLocal); - internals.hostNativeExportsTable = [...hostNativeExportsToTable(hostNativeExportsLocal)]; - internals.updates.push(updateInternalsImpl); - updateInternals(); + internals.hostNativeExportsTable = [...tabulateHE(hostNativeExportsLocal)]; + internals.updates.push(updateMyInternals); + updateAllInternals(); } exports.browserHostExternalAssemblyProbe = browserHostExternalAssemblyProbe; @@ -491,7 +496,7 @@ var libBrowserHost = (function (exports) { if (typeof dotnetInternals !== "undefined") { BROWSER_HOST.dotnetInternals = dotnetInternals; - const exports = libBrowserHost(BROWSER_HOST); + const exports = libBrowserHostFn(BROWSER_HOST); exports.initialize(dotnetInternals); BROWSER_HOST.assignExports(exports, BROWSER_HOST); @@ -510,13 +515,13 @@ var libBrowserHost = (function (exports) { } }, }, - "$libBrowserHost": libBrowserHost, + "$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 = ["$libBrowserHost", "$DOTNET", "$DOTNET_INTEROP", "browserHostInitializeCoreCLR", "browserHostExecuteAssembly"]; + let commonDeps = ["$libBrowserHostFn", "$DOTNET", "$DOTNET_INTEROP"]; let assignExportsBuilder = ""; for (const exportName of Reflect.ownKeys(exports)) { const name = String(exportName); @@ -526,7 +531,7 @@ var libBrowserHost = (function (exports) { assignExportsBuilder += `_${String(name)} = exports.${String(name)};\n`; } lib.$BROWSER_HOST.assignExports = new Function("exports", assignExportsBuilder); - lib["$DOTNET_INTEROP__deps"] = commonDeps; + lib["$BROWSER_HOST__deps"] = commonDeps; autoAddDeps(lib, "$BROWSER_HOST"); addToLibrary(lib); @@ -534,3 +539,4 @@ var libBrowserHost = (function (exports) { libFactory(); return exports; })({}); +//# sourceMappingURL=libBrowserHost.js.map diff --git a/src/native/corehost/browserhost/loader/dotnet.js b/src/native/corehost/browserhost/loader/dotnet.js index 2e1e30eb469d86..a40a98de007e66 100644 --- a/src/native/corehost/browserhost/loader/dotnet.js +++ b/src/native/corehost/browserhost/loader/dotnet.js @@ -14,8 +14,9 @@ let Assert = {}; let JSEngine = {}; let loaderExports = {}; let runtimeExports = {}; -let nativeExports = {}; +let hostExports = {}; let interopExports = {}; +let nativeBrowserExports = {}; let dotnetInternals; function getInternals() { return dotnetInternals; @@ -25,7 +26,7 @@ function setInternals(internal) { runtimeApi = dotnetInternals.runtimeApi; Module = dotnetInternals.runtimeApi.Module; } -function updateInternals() { +function updateAllInternals() { if (dotnetInternals.updates === undefined) { dotnetInternals.updates = []; } @@ -33,32 +34,36 @@ function updateInternals() { updateImpl(); } } -function updateInternalsImpl() { +function updateMyInternals() { if (Object.keys(loaderExports).length === 0 && dotnetInternals.loaderExportsTable) { loaderExports = {}; Logger = {}; Assert = {}; JSEngine = {}; - loaderExportsFromTable(dotnetInternals.loaderExportsTable, Logger, Assert, JSEngine, loaderExports); + expandLE(dotnetInternals.loaderExportsTable, Logger, Assert, JSEngine, loaderExports); } if (Object.keys(runtimeExports).length === 0 && dotnetInternals.runtimeExportsTable) { runtimeExports = {}; - runtimeExportsFromTable(dotnetInternals.runtimeExportsTable, runtimeExports); + expandRE(dotnetInternals.runtimeExportsTable, runtimeExports); } - if (Object.keys(nativeExports).length === 0 && dotnetInternals.hostNativeExportsTable) { - nativeExports = {}; - hostNativeExportsFromTable(dotnetInternals.hostNativeExportsTable, nativeExports); + if (Object.keys(hostExports).length === 0 && dotnetInternals.hostNativeExportsTable) { + hostExports = {}; + expandHE(dotnetInternals.hostNativeExportsTable, hostExports); } if (Object.keys(interopExports).length === 0 && dotnetInternals.interopJavaScriptNativeExportsTable) { interopExports = {}; - interopJavaScriptNativeExportsFromTable(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 loaderExportsToTable(logger, assert, loaderExports) { +function tabulateLE(logger, assert, loaderExports) { return [ logger.info, logger.warn, @@ -74,7 +79,7 @@ function loaderExportsToTable(logger, assert, loaderExports) { loaderExports.getRunMainPromise, ]; } -function loaderExportsFromTable(table, logger, assert, jsEngine, loaderExports) { +function expandLE(table, logger, assert, jsEngine, loaderExports) { const loggerLocal = { info: table[0], warn: table[1], @@ -106,19 +111,19 @@ function loaderExportsFromTable(table, logger, assert, jsEngine, loaderExports) Object.assign(jsEngine, jsEngineLocal); } // eslint-disable-next-line @typescript-eslint/no-unused-vars -function runtimeExportsToTable(map) { +function tabulateRE(map) { return []; } -function runtimeExportsFromTable(table, runtime) { +function expandRE(table, runtime) { Object.assign(runtime, {}); } -function hostNativeExportsToTable(map) { +function tabulateHE(map) { return [ map.registerDllBytes, map.isSharedArrayBuffer, ]; } -function hostNativeExportsFromTable(table, native) { +function expandHE(table, native) { const nativeLocal = { registerDllBytes: table[0], isSharedArrayBuffer: table[1], @@ -126,18 +131,18 @@ function hostNativeExportsFromTable(table, native) { Object.assign(native, nativeLocal); } // eslint-disable-next-line @typescript-eslint/no-unused-vars -function interopJavaScriptNativeExportsToTable(map) { +function tabulateJSNE(map) { return []; } -function interopJavaScriptNativeExportsFromTable(table, interop) { +function expandJSNE(table, interop) { const interopLocal = {}; Object.assign(interop, interopLocal); } // eslint-disable-next-line @typescript-eslint/no-unused-vars -function nativeBrowserExportsToTable(map) { +function tabulateNBE(map) { return []; } -function nativeBrowserExportsFromTable(table, interop) { +function expandNBE(table, interop) { const interopLocal = {}; Object.assign(interop, interopLocal); } @@ -386,7 +391,7 @@ const modulesUniqueQuery = queryIndex > 0 ? scriptUrlQuery.substring(queryIndex) const scriptUrl = normalizeFileUrl(scriptUrlQuery); const scriptDirectory = normalizeDirectoryUrl(scriptUrl); const nativeModulePromiseController = createPromiseController(() => { - updateInternals(); + updateAllInternals(); }); // WASM-TODO: retry logic // WASM-TODO: throttling logic @@ -437,7 +442,7 @@ async function fetchDll(asset) { } const bytes = await fetchBytes(asset); await nativeModulePromiseController.promise; - nativeExports.registerDllBytes(bytes, asset); + hostExports.registerDllBytes(bytes, asset); } async function fetchBytes(asset) { Assert.check(asset && asset.resolvedUrl, "Bad asset.resolvedUrl"); @@ -825,7 +830,7 @@ var ProductVersion = "10.0.0-dev"; var BuildConfiguration = "Debug"; -var GitHash = "b45b9a54d6619520903f5be728767b66e5a37429"; +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. @@ -836,7 +841,7 @@ async function invokeLibraryInitializers(functionName, args) { // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -// WASM-TODO inline the code +// WASMTODO inline the code function check(condition, messageFactory) { if (!condition) { const message = typeof messageFactory === "string" ? messageFactory : messageFactory(); @@ -928,9 +933,9 @@ function initialize() { Object.assign(Assert, assert); Object.assign(JSEngine, jsEngine); Object.assign(loaderExports, loaderFunctions); - dotnetInternals.loaderExportsTable = [...loaderExportsToTable(Logger, Assert, loaderExports)]; - updates.push(updateInternalsImpl); - updateInternals(); + dotnetInternals.loaderExportsTable = [...tabulateLE(Logger, Assert, loaderExports)]; + updates.push(updateMyInternals); + updateAllInternals(); return runtimeApi; } diff --git a/src/native/libs/System.Native.Browser/libSystem.Native.Browser.js b/src/native/libs/System.Native.Browser/libSystem.Native.Browser.js index 9d2459ba4ce4c6..42dae127fd3568 100644 --- a/src/native/libs/System.Native.Browser/libSystem.Native.Browser.js +++ b/src/native/libs/System.Native.Browser/libSystem.Native.Browser.js @@ -15,8 +15,9 @@ var libNativeBrowser = (function (exports) { let JSEngine = {}; let loaderExports = {}; let runtimeExports = {}; - let nativeExports = {}; + let hostExports = {}; let interopExports = {}; + let nativeBrowserExports = {}; let dotnetInternals; function getInternals() { return dotnetInternals; @@ -26,7 +27,7 @@ var libNativeBrowser = (function (exports) { runtimeApi = dotnetInternals.runtimeApi; Module = dotnetInternals.runtimeApi.Module; } - function updateInternals() { + function updateAllInternals() { if (dotnetInternals.updates === undefined) { dotnetInternals.updates = []; } @@ -34,32 +35,36 @@ var libNativeBrowser = (function (exports) { updateImpl(); } } - function updateInternalsImpl() { + function updateMyInternals() { if (Object.keys(loaderExports).length === 0 && dotnetInternals.loaderExportsTable) { loaderExports = {}; Logger = {}; Assert = {}; JSEngine = {}; - loaderExportsFromTable(dotnetInternals.loaderExportsTable, Logger, Assert, JSEngine, loaderExports); + expandLE(dotnetInternals.loaderExportsTable, Logger, Assert, JSEngine, loaderExports); } if (Object.keys(runtimeExports).length === 0 && dotnetInternals.runtimeExportsTable) { runtimeExports = {}; - runtimeExportsFromTable(dotnetInternals.runtimeExportsTable, runtimeExports); + expandRE(dotnetInternals.runtimeExportsTable, runtimeExports); } - if (Object.keys(nativeExports).length === 0 && dotnetInternals.hostNativeExportsTable) { - nativeExports = {}; - hostNativeExportsFromTable(dotnetInternals.hostNativeExportsTable, nativeExports); + if (Object.keys(hostExports).length === 0 && dotnetInternals.hostNativeExportsTable) { + hostExports = {}; + expandHE(dotnetInternals.hostNativeExportsTable, hostExports); } if (Object.keys(interopExports).length === 0 && dotnetInternals.interopJavaScriptNativeExportsTable) { interopExports = {}; - interopJavaScriptNativeExportsFromTable(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 loaderExportsToTable(logger, assert, loaderExports) { + function tabulateLE(logger, assert, loaderExports) { return [ logger.info, logger.warn, @@ -75,7 +80,7 @@ var libNativeBrowser = (function (exports) { loaderExports.getRunMainPromise, ]; } - function loaderExportsFromTable(table, logger, assert, jsEngine, loaderExports) { + function expandLE(table, logger, assert, jsEngine, loaderExports) { const loggerLocal = { info: table[0], warn: table[1], @@ -107,19 +112,19 @@ var libNativeBrowser = (function (exports) { Object.assign(jsEngine, jsEngineLocal); } // eslint-disable-next-line @typescript-eslint/no-unused-vars - function runtimeExportsToTable(map) { + function tabulateRE(map) { return []; } - function runtimeExportsFromTable(table, runtime) { + function expandRE(table, runtime) { Object.assign(runtime, {}); } - function hostNativeExportsToTable(map) { + function tabulateHE(map) { return [ map.registerDllBytes, map.isSharedArrayBuffer, ]; } - function hostNativeExportsFromTable(table, native) { + function expandHE(table, native) { const nativeLocal = { registerDllBytes: table[0], isSharedArrayBuffer: table[1], @@ -127,18 +132,18 @@ var libNativeBrowser = (function (exports) { Object.assign(native, nativeLocal); } // eslint-disable-next-line @typescript-eslint/no-unused-vars - function interopJavaScriptNativeExportsToTable(map) { + function tabulateJSNE(map) { return []; } - function interopJavaScriptNativeExportsFromTable(table, interop) { + function expandJSNE(table, interop) { const interopLocal = {}; Object.assign(interop, interopLocal); } // eslint-disable-next-line @typescript-eslint/no-unused-vars - function nativeBrowserExportsToTable(map) { + function tabulateNBE(map) { return []; } - function nativeBrowserExportsFromTable(table, interop) { + function expandNBE(table, interop) { const interopLocal = {}; Object.assign(interop, interopLocal); } @@ -153,25 +158,26 @@ var libNativeBrowser = (function (exports) { get Logger() { return Logger; }, get Module() { return Module; }, get dotnetInternals() { return dotnetInternals; }, + expandHE: expandHE, + expandJSNE: expandJSNE, + expandLE: expandLE, + expandNBE: expandNBE, + expandRE: expandRE, getInternals: getInternals, - hostNativeExportsFromTable: hostNativeExportsFromTable, - hostNativeExportsToTable: hostNativeExportsToTable, + get hostExports() { return hostExports; }, get interopExports() { return interopExports; }, - interopJavaScriptNativeExportsFromTable: interopJavaScriptNativeExportsFromTable, - interopJavaScriptNativeExportsToTable: interopJavaScriptNativeExportsToTable, get loaderExports() { return loaderExports; }, - loaderExportsFromTable: loaderExportsFromTable, - loaderExportsToTable: loaderExportsToTable, - nativeBrowserExportsFromTable: nativeBrowserExportsFromTable, - nativeBrowserExportsToTable: nativeBrowserExportsToTable, - get nativeExports() { return nativeExports; }, + get nativeBrowserExports() { return nativeBrowserExports; }, get runtimeApi() { return runtimeApi; }, get runtimeExports() { return runtimeExports; }, - runtimeExportsFromTable: runtimeExportsFromTable, - runtimeExportsToTable: runtimeExportsToTable, setInternals: setInternals, - updateInternals: updateInternals, - updateInternalsImpl: updateInternalsImpl + tabulateHE: tabulateHE, + tabulateJSNE: tabulateJSNE, + tabulateLE: tabulateLE, + tabulateNBE: tabulateNBE, + tabulateRE: tabulateRE, + updateAllInternals: updateAllInternals, + updateMyInternals: updateMyInternals }); // Licensed to the .NET Foundation under one or more agreements. @@ -191,7 +197,7 @@ var libNativeBrowser = (function (exports) { 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 = nativeExports.isSharedArrayBuffer(memoryView.buffer); + const needsCopy = hostExports.isSharedArrayBuffer(memoryView.buffer); const targetBuffer = needsCopy ? new Uint8Array(bufferLength) : targetView; @@ -211,9 +217,9 @@ var libNativeBrowser = (function (exports) { function initialize(internals) { const nativeBrowserExportsLocal = {}; setInternals(internals); - internals.nativeBrowserExportsTable = [...nativeBrowserExportsToTable(nativeBrowserExportsLocal)]; - internals.updates.push(updateInternalsImpl); - updateInternals(); + internals.nativeBrowserExportsTable = [...tabulateNBE(nativeBrowserExportsLocal)]; + internals.updates.push(updateMyInternals); + updateAllInternals(); } exports.SystemJS_RandomBytes = SystemJS_RandomBytes; 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 index d359657c4cdc38..eb2e761bf9984b 100644 --- a/src/native/libs/System.Runtime.InteropServices.JavaScript.Native/dotnet.runtime.js +++ b/src/native/libs/System.Runtime.InteropServices.JavaScript.Native/dotnet.runtime.js @@ -12,8 +12,9 @@ let Assert = {}; let JSEngine = {}; let loaderExports = {}; let runtimeExports = {}; -let nativeExports = {}; +let hostExports = {}; let interopExports = {}; +let nativeBrowserExports = {}; let dotnetInternals; function getInternals() { return dotnetInternals; @@ -23,7 +24,7 @@ function setInternals(internal) { runtimeApi = dotnetInternals.runtimeApi; Module = dotnetInternals.runtimeApi.Module; } -function updateInternals() { +function updateAllInternals() { if (dotnetInternals.updates === undefined) { dotnetInternals.updates = []; } @@ -31,32 +32,36 @@ function updateInternals() { updateImpl(); } } -function updateInternalsImpl() { +function updateMyInternals() { if (Object.keys(loaderExports).length === 0 && dotnetInternals.loaderExportsTable) { loaderExports = {}; Logger = {}; Assert = {}; JSEngine = {}; - loaderExportsFromTable(dotnetInternals.loaderExportsTable, Logger, Assert, JSEngine, loaderExports); + expandLE(dotnetInternals.loaderExportsTable, Logger, Assert, JSEngine, loaderExports); } if (Object.keys(runtimeExports).length === 0 && dotnetInternals.runtimeExportsTable) { runtimeExports = {}; - runtimeExportsFromTable(dotnetInternals.runtimeExportsTable, runtimeExports); + expandRE(dotnetInternals.runtimeExportsTable, runtimeExports); } - if (Object.keys(nativeExports).length === 0 && dotnetInternals.hostNativeExportsTable) { - nativeExports = {}; - hostNativeExportsFromTable(dotnetInternals.hostNativeExportsTable, nativeExports); + if (Object.keys(hostExports).length === 0 && dotnetInternals.hostNativeExportsTable) { + hostExports = {}; + expandHE(dotnetInternals.hostNativeExportsTable, hostExports); } if (Object.keys(interopExports).length === 0 && dotnetInternals.interopJavaScriptNativeExportsTable) { interopExports = {}; - interopJavaScriptNativeExportsFromTable(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 loaderExportsToTable(logger, assert, loaderExports) { +function tabulateLE(logger, assert, loaderExports) { return [ logger.info, logger.warn, @@ -72,7 +77,7 @@ function loaderExportsToTable(logger, assert, loaderExports) { loaderExports.getRunMainPromise, ]; } -function loaderExportsFromTable(table, logger, assert, jsEngine, loaderExports) { +function expandLE(table, logger, assert, jsEngine, loaderExports) { const loggerLocal = { info: table[0], warn: table[1], @@ -104,19 +109,19 @@ function loaderExportsFromTable(table, logger, assert, jsEngine, loaderExports) Object.assign(jsEngine, jsEngineLocal); } // eslint-disable-next-line @typescript-eslint/no-unused-vars -function runtimeExportsToTable(map) { +function tabulateRE(map) { return []; } -function runtimeExportsFromTable(table, runtime) { +function expandRE(table, runtime) { Object.assign(runtime, {}); } -function hostNativeExportsToTable(map) { +function tabulateHE(map) { return [ map.registerDllBytes, map.isSharedArrayBuffer, ]; } -function hostNativeExportsFromTable(table, native) { +function expandHE(table, native) { const nativeLocal = { registerDllBytes: table[0], isSharedArrayBuffer: table[1], @@ -124,18 +129,18 @@ function hostNativeExportsFromTable(table, native) { Object.assign(native, nativeLocal); } // eslint-disable-next-line @typescript-eslint/no-unused-vars -function interopJavaScriptNativeExportsToTable(map) { +function tabulateJSNE(map) { return []; } -function interopJavaScriptNativeExportsFromTable(table, interop) { +function expandJSNE(table, interop) { const interopLocal = {}; Object.assign(interop, interopLocal); } // eslint-disable-next-line @typescript-eslint/no-unused-vars -function nativeBrowserExportsToTable(map) { +function tabulateNBE(map) { return []; } -function nativeBrowserExportsFromTable(table, interop) { +function expandNBE(table, interop) { const interopLocal = {}; Object.assign(interop, interopLocal); } @@ -153,9 +158,9 @@ function initialize(internals) { const runtimeExportsLocal = {}; setInternals(internals); Object.assign(internals.runtimeApi, runtimeApiLocal); - internals.runtimeExportsTable = [...runtimeExportsToTable(runtimeExportsLocal)]; - internals.updates.push(updateInternalsImpl); - updateInternals(); + internals.runtimeExportsTable = [...tabulateRE(runtimeExportsLocal)]; + internals.updates.push(updateMyInternals); + updateAllInternals(); } // eslint-disable-next-line @typescript-eslint/no-unused-vars async function getAssemblyExports(assemblyName) { 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 index a335f11f1dffe3..84efa97500a1ec 100644 --- 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 @@ -15,8 +15,9 @@ var libInteropJavaScriptNative = (function (exports) { let JSEngine = {}; let loaderExports = {}; let runtimeExports = {}; - let nativeExports = {}; + let hostExports = {}; let interopExports = {}; + let nativeBrowserExports = {}; let dotnetInternals; function getInternals() { return dotnetInternals; @@ -26,7 +27,7 @@ var libInteropJavaScriptNative = (function (exports) { runtimeApi = dotnetInternals.runtimeApi; Module = dotnetInternals.runtimeApi.Module; } - function updateInternals() { + function updateAllInternals() { if (dotnetInternals.updates === undefined) { dotnetInternals.updates = []; } @@ -34,32 +35,36 @@ var libInteropJavaScriptNative = (function (exports) { updateImpl(); } } - function updateInternalsImpl() { + function updateMyInternals() { if (Object.keys(loaderExports).length === 0 && dotnetInternals.loaderExportsTable) { loaderExports = {}; Logger = {}; Assert = {}; JSEngine = {}; - loaderExportsFromTable(dotnetInternals.loaderExportsTable, Logger, Assert, JSEngine, loaderExports); + expandLE(dotnetInternals.loaderExportsTable, Logger, Assert, JSEngine, loaderExports); } if (Object.keys(runtimeExports).length === 0 && dotnetInternals.runtimeExportsTable) { runtimeExports = {}; - runtimeExportsFromTable(dotnetInternals.runtimeExportsTable, runtimeExports); + expandRE(dotnetInternals.runtimeExportsTable, runtimeExports); } - if (Object.keys(nativeExports).length === 0 && dotnetInternals.hostNativeExportsTable) { - nativeExports = {}; - hostNativeExportsFromTable(dotnetInternals.hostNativeExportsTable, nativeExports); + if (Object.keys(hostExports).length === 0 && dotnetInternals.hostNativeExportsTable) { + hostExports = {}; + expandHE(dotnetInternals.hostNativeExportsTable, hostExports); } if (Object.keys(interopExports).length === 0 && dotnetInternals.interopJavaScriptNativeExportsTable) { interopExports = {}; - interopJavaScriptNativeExportsFromTable(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 loaderExportsToTable(logger, assert, loaderExports) { + function tabulateLE(logger, assert, loaderExports) { return [ logger.info, logger.warn, @@ -75,7 +80,7 @@ var libInteropJavaScriptNative = (function (exports) { loaderExports.getRunMainPromise, ]; } - function loaderExportsFromTable(table, logger, assert, jsEngine, loaderExports) { + function expandLE(table, logger, assert, jsEngine, loaderExports) { const loggerLocal = { info: table[0], warn: table[1], @@ -107,19 +112,19 @@ var libInteropJavaScriptNative = (function (exports) { Object.assign(jsEngine, jsEngineLocal); } // eslint-disable-next-line @typescript-eslint/no-unused-vars - function runtimeExportsToTable(map) { + function tabulateRE(map) { return []; } - function runtimeExportsFromTable(table, runtime) { + function expandRE(table, runtime) { Object.assign(runtime, {}); } - function hostNativeExportsToTable(map) { + function tabulateHE(map) { return [ map.registerDllBytes, map.isSharedArrayBuffer, ]; } - function hostNativeExportsFromTable(table, native) { + function expandHE(table, native) { const nativeLocal = { registerDllBytes: table[0], isSharedArrayBuffer: table[1], @@ -127,18 +132,18 @@ var libInteropJavaScriptNative = (function (exports) { Object.assign(native, nativeLocal); } // eslint-disable-next-line @typescript-eslint/no-unused-vars - function interopJavaScriptNativeExportsToTable(map) { + function tabulateJSNE(map) { return []; } - function interopJavaScriptNativeExportsFromTable(table, interop) { + function expandJSNE(table, interop) { const interopLocal = {}; Object.assign(interop, interopLocal); } // eslint-disable-next-line @typescript-eslint/no-unused-vars - function nativeBrowserExportsToTable(map) { + function tabulateNBE(map) { return []; } - function nativeBrowserExportsFromTable(table, interop) { + function expandNBE(table, interop) { const interopLocal = {}; Object.assign(interop, interopLocal); } @@ -153,41 +158,42 @@ var libInteropJavaScriptNative = (function (exports) { get Logger() { return Logger; }, get Module() { return Module; }, get dotnetInternals() { return dotnetInternals; }, + expandHE: expandHE, + expandJSNE: expandJSNE, + expandLE: expandLE, + expandNBE: expandNBE, + expandRE: expandRE, getInternals: getInternals, - hostNativeExportsFromTable: hostNativeExportsFromTable, - hostNativeExportsToTable: hostNativeExportsToTable, + get hostExports() { return hostExports; }, get interopExports() { return interopExports; }, - interopJavaScriptNativeExportsFromTable: interopJavaScriptNativeExportsFromTable, - interopJavaScriptNativeExportsToTable: interopJavaScriptNativeExportsToTable, get loaderExports() { return loaderExports; }, - loaderExportsFromTable: loaderExportsFromTable, - loaderExportsToTable: loaderExportsToTable, - nativeBrowserExportsFromTable: nativeBrowserExportsFromTable, - nativeBrowserExportsToTable: nativeBrowserExportsToTable, - get nativeExports() { return nativeExports; }, + get nativeBrowserExports() { return nativeBrowserExports; }, get runtimeApi() { return runtimeApi; }, get runtimeExports() { return runtimeExports; }, - runtimeExportsFromTable: runtimeExportsFromTable, - runtimeExportsToTable: runtimeExportsToTable, setInternals: setInternals, - updateInternals: updateInternals, - updateInternalsImpl: updateInternalsImpl + 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) { - // WASM-TODO implementation + // WASMTODO implementation Logger.error("SystemInteropJS_InvokeJSImportST called"); return -1; } function initialize(internals) { const interopJavaScriptNativeExportsLocal = {}; setInternals(internals); - internals.interopJavaScriptNativeExportsTable = [...interopJavaScriptNativeExportsToTable(interopJavaScriptNativeExportsLocal)]; - internals.updates.push(updateInternalsImpl); - updateInternals(); + internals.interopJavaScriptNativeExportsTable = [...tabulateJSNE(interopJavaScriptNativeExportsLocal)]; + internals.updates.push(updateMyInternals); + updateAllInternals(); } exports.SystemInteropJS_InvokeJSImportST = SystemInteropJS_InvokeJSImportST; @@ -216,13 +222,12 @@ var libInteropJavaScriptNative = (function (exports) { } }, }, - "$DOTNET_INTEROP__deps": ["$DOTNET"], "$DOTNET_INTEROP__postset": "DOTNET_INTEROP.selfInitialize();", }; // this executes the function at compile time in order to capture exports const exports = libInteropJavaScriptNative({}); - let commonDeps = []; + let commonDeps = ["$DOTNET"]; for (const exportName of Reflect.ownKeys(exports.cross)) { const name = String(exportName); if (name === "dotnetInternals") continue; From 0651a9419e3092ef985eb0f3be7dc214c4c6496a Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Mon, 22 Sep 2025 22:29:23 +0200 Subject: [PATCH 19/25] feedback from kg --- .../corehost/browserhost/CMakeLists.txt | 19 +------ src/native/corehost/browserhost/ReadMe.md | 2 + .../corehost/browserhost/browserhost.cpp | 15 +++--- .../browserhost/sample/CMakeLists.txt | 24 +++++++++ .../corehost/browserhost/sample/ReadMe.md | 8 ++- .../browserhost/sample/dotnet.boot.js | 51 +------------------ .../hostpolicy/hostpolicy_context.cpp | 6 +-- .../libs/System.Native.Browser/ReadMe.md | 2 + .../ReadMe.md | 2 + src/native/rollup.stub.js | 1 + 10 files changed, 52 insertions(+), 78 deletions(-) create mode 100644 src/native/corehost/browserhost/sample/CMakeLists.txt diff --git a/src/native/corehost/browserhost/CMakeLists.txt b/src/native/corehost/browserhost/CMakeLists.txt index 0aaafa964602bf..eea307bde422a1 100644 --- a/src/native/corehost/browserhost/CMakeLists.txt +++ b/src/native/corehost/browserhost/CMakeLists.txt @@ -106,21 +106,4 @@ target_link_libraries( ${END_WHOLE_ARCHIVE} ) -# WASM-TODO: this is temporary locations -set(SAMPLE_ASSETS - sample/index.html - sample/main.mjs - sample/dotnet.boot.js - # ${CLR_ARTIFACTS_OBJ_DIR}/sfx-finish/${CMAKE_BUILD_TYPE}/net10.0-browser/illink-wasm/System.Console.dll - # ${CLR_ARTIFACTS_OBJ_DIR}/sfx-finish/${CMAKE_BUILD_TYPE}/net10.0-browser/illink-wasm/System.Private.CoreLib.dll - # ${CLR_ARTIFACTS_OBJ_DIR}/sfx-finish/${CMAKE_BUILD_TYPE}/net10.0-browser/illink-wasm/System.Runtime.dll - # ${CLR_ARTIFACTS_OBJ_DIR}/sfx-finish/${CMAKE_BUILD_TYPE}/net10.0-browser/illink-wasm/System.Runtime.InteropServices.dll - # ${CLR_ARTIFACTS_OBJ_DIR}/sfx-finish/${CMAKE_BUILD_TYPE}/net10.0-browser/illink-wasm/System.Threading.dll - # ${CLR_ARTIFACTS_BIN_DIR}/artifacts/bin/HelloWorld/${CMAKE_BUILD_TYPE}/net10.0/win-x64/HelloWorld.dll - ${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.js.map - ${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 - ${CLR_ARTIFACTS_OBJ_DIR}/native/browser-${CMAKE_BUILD_TYPE}-wasm/System.Runtime.InteropServices.JavaScript.Native/dotnet.runtime.js.map -) -install(FILES ${SAMPLE_ASSETS} DESTINATION corehost COMPONENT runtime) +add_subdirectory(sample) diff --git a/src/native/corehost/browserhost/ReadMe.md b/src/native/corehost/browserhost/ReadMe.md index e6b447418c01ea..6f9478ec92a5ac 100644 --- a/src/native/corehost/browserhost/ReadMe.md +++ b/src/native/corehost/browserhost/ReadMe.md @@ -26,5 +26,7 @@ It is **Emscripten application** statically linked from libraries. ## 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 index ed128cadb5b753..2bfd4850e3ede0 100644 --- a/src/native/corehost/browserhost/browserhost.cpp +++ b/src/native/corehost/browserhost/browserhost.cpp @@ -85,14 +85,15 @@ static const void* pinvoke_override(const char* library_name, const char* entry_ { return SystemJSInteropResolveDllImport(entry_point_name); } - if (strcmp(library_name, "libSystem.Globalization.Native") == 0) - { - return GlobalizationResolveDllImport(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; } @@ -104,7 +105,7 @@ 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 buffer[STRING_LENGTH("0xffffffffffffffff")]; +static pal::char_t ptr_to_string_buffer[STRING_LENGTH("0xffffffffffffffff") + 1]; extern "C" int browserHostInitializeCoreCLR(void) { @@ -125,10 +126,10 @@ extern "C" int browserHostInitializeCoreCLR(void) host_contract.pinvoke_override = &pinvoke_override; host_contract.external_assembly_probe = &external_assembly_probe; - pal::snwprintf(buffer, ARRAY_SIZE(buffer), _X("0x%zx"), (size_t)(&host_contract)); + 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(buffer); + propertyValues.push_back(ptr_to_string_buffer); coreclr_set_error_writer(log_error_info); 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/ReadMe.md b/src/native/corehost/browserhost/sample/ReadMe.md index efd26667a528fc..9f87c04d56bbba 100644 --- a/src/native/corehost/browserhost/sample/ReadMe.md +++ b/src/native/corehost/browserhost/sample/ReadMe.md @@ -1,3 +1,9 @@ # Demo files -This is simple demo customer code that uses dotnet.js \ No newline at end of file +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 index 7042b99ae1caa3..52971a6be1143b 100644 --- a/src/native/corehost/browserhost/sample/dotnet.boot.js +++ b/src/native/corehost/browserhost/sample/dotnet.boot.js @@ -1,7 +1,7 @@ // 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 WASM SDK for corehost +// 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", @@ -22,20 +22,6 @@ export const config = /*json-start*/{ "name": "dotnet.native.wasm", } ], - "icu": [ - { - "virtualPath": "icudt_CJK.dat", - "name": "icudt_CJK.dat", - }, - { - "virtualPath": "icudt_EFIGS.dat", - "name": "icudt_EFIGS.dat", - }, - { - "virtualPath": "icudt_no_CJK.dat", - "name": "icudt_no_CJK.dat", - } - ], "coreAssembly": [ { "virtualPath": "/System.Private.CoreLib.dll", @@ -62,40 +48,7 @@ export const config = /*json-start*/{ { "virtualPath": "/HelloWorld.dll", "name": "HelloWorld.dll" - }, - { - "virtualPath": "/System.Runtime.InteropServices.JavaScript.dll", - "name": "System.Runtime.InteropServices.JavaScript.dll" - }, - ] - }, - "debugLevel": -1, - "globalizationMode": "sharded", - "runtimeConfig": { - "runtimeOptions": { - "configProperties": { - "System.Net.Http.dllEnableStreamingResponse": true, - "Microsoft.Extensions.DependencyInjection.VerifyOpenGenericServiceTrimmability": true, - "System.ComponentModel.DefaultValueAttribute.IsSupported": false, - "System.ComponentModel.Design.IDesignerHost.IsSupported": false, - "System.ComponentModel.TypeConverter.EnableUnsafeBinaryFormatterInDesigntimeLicenseContextSerialization": false, - "System.ComponentModel.TypeDescriptor.IsComObjectDescriptorSupported": false, - "System.Data.DataSet.XmlSerializationIsSupported": false, - "System.Diagnostics.Metrics.Meter.IsSupported": false, - "System.Reflection.Metadata.MetadataUpdater.IsSupported": false, - "System.Resources.ResourceManager.AllowCustomResourceTypes": false, - "System.Resources.UseSystemResourceKeys": false, - "System.Runtime.CompilerServices.RuntimeFeature.IsDynamicCodeSupported": true, - "System.Runtime.InteropServices.BuiltInComInterop.IsSupported": false, - "System.Runtime.InteropServices.EnableConsumingManagedCodeFromNativeHosting": false, - "System.Runtime.InteropServices.EnableCppCLIHostActivation": false, - "System.Runtime.InteropServices.Marshalling.EnableGeneratedComInterfaceComImportInterop": false, - "System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": false, - "System.StartupHookProvider.IsSupported": false, - "System.Text.Encoding.EnableUnsafeUTF7Encoding": false, - "System.Text.Json.JsonSerializer.IsReflectionEnabledByDefault": false, - "System.Threading.Thread.EnableAutoreleasePool": false } - } + ] } }/*json-end*/; \ No newline at end of file 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/System.Native.Browser/ReadMe.md b/src/native/libs/System.Native.Browser/ReadMe.md index 2fad74c882e493..451e98fcf5c972 100644 --- a/src/native/libs/System.Native.Browser/ReadMe.md +++ b/src/native/libs/System.Native.Browser/ReadMe.md @@ -13,5 +13,7 @@ And a native library compiled by CMake into `libSystem.Native.Browser.a` as part ## 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/ReadMe.md b/src/native/libs/System.Runtime.InteropServices.JavaScript.Native/ReadMe.md index b7e67946b25dba..ab6654c6591648 100644 --- a/src/native/libs/System.Runtime.InteropServices.JavaScript.Native/ReadMe.md +++ b/src/native/libs/System.Runtime.InteropServices.JavaScript.Native/ReadMe.md @@ -13,5 +13,7 @@ This library also implements public JS API related JS interop. ## 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/rollup.stub.js b/src/native/rollup.stub.js index 938a562735d72b..1b59e429abce59 100644 --- a/src/native/rollup.stub.js +++ b/src/native/rollup.stub.js @@ -39,6 +39,7 @@ for (const [src, dest] of copies) { 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()); From a44cc9522b133bdec2c049e9f7b72f5155e91ecc Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Mon, 22 Sep 2025 22:32:03 +0200 Subject: [PATCH 20/25] whitespace --- src/native/corehost/browserhost/ReadMe.md | 2 +- src/native/libs/System.Native.Browser/ReadMe.md | 2 +- .../System.Runtime.InteropServices.JavaScript.Native/ReadMe.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/native/corehost/browserhost/ReadMe.md b/src/native/corehost/browserhost/ReadMe.md index 6f9478ec92a5ac..ddc3ca082eced7 100644 --- a/src/native/corehost/browserhost/ReadMe.md +++ b/src/native/corehost/browserhost/ReadMe.md @@ -26,7 +26,7 @@ It is **Emscripten application** statically linked from libraries. ## Build TypeScript is compiled by `src/native/rollup.config.js` -JavaScript tools like `npm`, `tsc`, `rollup` are installed in `src/native/package.json`. +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/libs/System.Native.Browser/ReadMe.md b/src/native/libs/System.Native.Browser/ReadMe.md index 451e98fcf5c972..aa24964b1fa381 100644 --- a/src/native/libs/System.Native.Browser/ReadMe.md +++ b/src/native/libs/System.Native.Browser/ReadMe.md @@ -13,7 +13,7 @@ And a native library compiled by CMake into `libSystem.Native.Browser.a` as part ## Build TypeScript is compiled by `src/native/rollup.config.js` -JavaScript tools like `npm`, `tsc`, `rollup` are installed in `src/native/package.json`. +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/ReadMe.md b/src/native/libs/System.Runtime.InteropServices.JavaScript.Native/ReadMe.md index ab6654c6591648..13db2c03f231d8 100644 --- a/src/native/libs/System.Runtime.InteropServices.JavaScript.Native/ReadMe.md +++ b/src/native/libs/System.Runtime.InteropServices.JavaScript.Native/ReadMe.md @@ -13,7 +13,7 @@ This library also implements public JS API related JS interop. ## Build TypeScript is compiled by `src/native/rollup.config.js` -JavaScript tools like `npm`, `tsc`, `rollup` are installed in `src/native/package.json`. +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` From e8e29d33ffcc8c5a2d360c2fac1021c93c591768 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Mon, 22 Sep 2025 22:50:56 +0200 Subject: [PATCH 21/25] feedback from kg --- .../corehost/browserhost/libBrowserHost.js | 34 ++++++++++++------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/src/native/corehost/browserhost/libBrowserHost.js b/src/native/corehost/browserhost/libBrowserHost.js index 4707bd40fcd310..62ee5e1f434835 100644 --- a/src/native/corehost/browserhost/libBrowserHost.js +++ b/src/native/corehost/browserhost/libBrowserHost.js @@ -166,7 +166,7 @@ var libBrowserHost = (function (exports) { if (Module._posix_memalign(ptrPtr, 16, bytes.length)) { throw new Error("posix_memalign failed"); } - const ptr = Module.HEAPU32[ptrPtr >> 2]; + const ptr = Module.HEAPU32[ptrPtr >>> 2]; Module.HEAPU8.set(bytes, ptr); loadedAssemblies[asset.name] = { ptr, length: bytes.length }; } @@ -178,13 +178,17 @@ var libBrowserHost = (function (exports) { function browserHostExternalAssemblyProbe(pathPtr, outDataStartPtr, outSize) { const path = Module.UTF8ToString(pathPtr); const assembly = loadedAssemblies[path]; - if (!assembly) { - return false; + 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] = assembly.ptr; - // upper bits are cleared by the C caller - Module.HEAPU32[outSize >> 2] = assembly.length; - 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); @@ -192,6 +196,11 @@ var libBrowserHost = (function (exports) { 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) { @@ -508,10 +517,10 @@ var libBrowserHost = (function (exports) { const config = dotnetInternals.config; const assemblyPaths = config.resources.assembly.map(a => a.virtualPath); const coreAssemblyPaths = config.resources.coreAssembly.map(a => a.virtualPath); - config.environmentVariables[HOST_PROPERTY_TRUSTED_PLATFORM_ASSEMBLIES] = [...coreAssemblyPaths, assemblyPaths].join(":"); - config.environmentVariables[HOST_PROPERTY_NATIVE_DLL_SEARCH_DIRECTORIES] = config.virtualWorkingDirectory; - config.environmentVariables[HOST_PROPERTY_APP_PATHS] = config.virtualWorkingDirectory; - config.environmentVariables[HOST_PROPERTY_ENTRY_ASSEMBLY_NAME] = config.mainAssemblyName; + 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; } }, }, @@ -521,7 +530,7 @@ var libBrowserHost = (function (exports) { // this executes the function at compile time in order to capture export names const exports = libBrowserHost({}); - let commonDeps = ["$libBrowserHostFn", "$DOTNET", "$DOTNET_INTEROP"]; + let commonDeps = ["$libBrowserHostFn", "$DOTNET", "$DOTNET_INTEROP", "$ENV"]; let assignExportsBuilder = ""; for (const exportName of Reflect.ownKeys(exports)) { const name = String(exportName); @@ -539,4 +548,3 @@ var libBrowserHost = (function (exports) { libFactory(); return exports; })({}); -//# sourceMappingURL=libBrowserHost.js.map From 151df04f0b86c3b57a115bdad234436782fe954e Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Mon, 22 Sep 2025 23:42:52 +0200 Subject: [PATCH 22/25] runtime3 feedback --- docs/workflow/building/coreclr/wasm.md | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/docs/workflow/building/coreclr/wasm.md b/docs/workflow/building/coreclr/wasm.md index c5d0d291202305..b2c6caa2d495d6 100644 --- a/docs/workflow/building/coreclr/wasm.md +++ b/docs/workflow/building/coreclr/wasm.md @@ -61,24 +61,23 @@ 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 /runtime3/artifacts/bin/microsoft.netcore.app.runtime.browser-wasm/Debug/runtimes/browser-wasm/lib/net10.0/*.dll /runtime3/artifacts/bin/coreclr/browser.wasm.Debug/corehost -cp helloworld.dll /runtime3/artifacts/bin/coreclr/browser.wasm.Debug/corehost -cd /runtime3/artifacts/bin/coreclr/browser.wasm.Debug/corehost +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 ``` @@ -110,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", @@ -124,10 +126,10 @@ 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/" }, From 85ab30b2d385ebed438608c80b77bbc737969796 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Tue, 23 Sep 2025 01:33:01 +0200 Subject: [PATCH 23/25] fixes --- src/coreclr/hosts/corerun/CMakeLists.txt | 1 - .../corehost/browserhost/CMakeLists.txt | 27 +++++++++---------- .../corehost/browserhost/libBrowserHost.js | 2 +- .../corehost/browserhost/loader/dotnet.js | 1 - 4 files changed, 14 insertions(+), 17 deletions(-) diff --git a/src/coreclr/hosts/corerun/CMakeLists.txt b/src/coreclr/hosts/corerun/CMakeLists.txt index 7b6683629b50e9..9dec6dcc2cdbaa 100644 --- a/src/coreclr/hosts/corerun/CMakeLists.txt +++ b/src/coreclr/hosts/corerun/CMakeLists.txt @@ -64,7 +64,6 @@ else(CLR_CMAKE_HOST_WIN32) 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 diff --git a/src/native/corehost/browserhost/CMakeLists.txt b/src/native/corehost/browserhost/CMakeLists.txt index eea307bde422a1..27e06b2299c42d 100644 --- a/src/native/corehost/browserhost/CMakeLists.txt +++ b/src/native/corehost/browserhost/CMakeLists.txt @@ -62,35 +62,34 @@ set_target_properties(browserhost PROPERTIES 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 RELEASE) +if (UPPERCASE_CMAKE_BUILD_TYPE STREQUAL DEBUG) target_link_options(browserhost PRIVATE # -sVERBOSE - -sASSERTIONS=1 +# -sASSERTIONS=1 --emit-symbol-map + -sLLD_REPORT_UNDEFINED + -sERROR_ON_UNDEFINED_SYMBOLS=1 ) endif () target_link_options(browserhost PRIVATE - -fwasm-exceptions - -sEXIT_RUNTIME=0 - -sINITIAL_MEMORY=134217728 - -sMAXIMUM_MEMORY=2147483648 - -sALLOW_MEMORY_GROWTH=1 - -sALLOW_TABLE_GROWTH=1 + -sINITIAL_MEMORY=33554432 +# TODO-WASM -sMAXIMUM_MEMORY=2147483648 +# TODO-WASM -sALLOW_MEMORY_GROWTH=1 +# TODO-WASM -sALLOW_TABLE_GROWTH=1 -sSTACK_SIZE=5MB -sMODULARIZE=1 -sEXPORT_ES6=1 - -sWASM_BIGINT=1 +# TODO-WASM -sWASM_BIGINT=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 - -msimd128 +# TODO-WASM -msimd128 -fwasm-exceptions -lnodefs.js - -emit-llvm - --source-map-base http://microsoft.com - -sLLD_REPORT_UNDEFINED - -sERROR_ON_UNDEFINED_SYMBOLS=1 +# TODO-WASM -emit-llvm +# TODO-WASM --source-map-base http://microsoft.com -Wno-unused-command-line-argument -Wl,-error-limit=0) diff --git a/src/native/corehost/browserhost/libBrowserHost.js b/src/native/corehost/browserhost/libBrowserHost.js index 62ee5e1f434835..b9b27dd9436849 100644 --- a/src/native/corehost/browserhost/libBrowserHost.js +++ b/src/native/corehost/browserhost/libBrowserHost.js @@ -517,7 +517,7 @@ var libBrowserHost = (function (exports) { 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_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; diff --git a/src/native/corehost/browserhost/loader/dotnet.js b/src/native/corehost/browserhost/loader/dotnet.js index a40a98de007e66..9b96e58e74ef0c 100644 --- a/src/native/corehost/browserhost/loader/dotnet.js +++ b/src/native/corehost/browserhost/loader/dotnet.js @@ -406,7 +406,6 @@ async function createRuntime(downloadOnly, loadBootResource) { 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); - fetchWasm(config.resources.wasmNative[0]); // start loading early, no await const nativeModule = await nativeModulePromise; const modulePromise = nativeModule.initialize(getInternals()); nativeModulePromiseController.propagateFrom(modulePromise); From efb1ced9bf12cac808e72cc5e744c6b656cdb812 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Tue, 23 Sep 2025 09:39:48 +0200 Subject: [PATCH 24/25] reorg todos --- src/native/corehost/browserhost/CMakeLists.txt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/native/corehost/browserhost/CMakeLists.txt b/src/native/corehost/browserhost/CMakeLists.txt index 27e06b2299c42d..89893682ee8236 100644 --- a/src/native/corehost/browserhost/CMakeLists.txt +++ b/src/native/corehost/browserhost/CMakeLists.txt @@ -72,24 +72,24 @@ if (UPPERCASE_CMAKE_BUILD_TYPE STREQUAL DEBUG) ) endif () -target_link_options(browserhost PRIVATE - -sINITIAL_MEMORY=33554432 # TODO-WASM -sMAXIMUM_MEMORY=2147483648 # TODO-WASM -sALLOW_MEMORY_GROWTH=1 # TODO-WASM -sALLOW_TABLE_GROWTH=1 +# TODO-WASM -sWASM_BIGINT=1 +# TODO-WASM -msimd128 +# TODO-WASM -emit-llvm +# TODO-WASM --source-map-base http://microsoft.com +target_link_options(browserhost PRIVATE + -sINITIAL_MEMORY=33554432 -sSTACK_SIZE=5MB -sMODULARIZE=1 -sEXPORT_ES6=1 -# TODO-WASM -sWASM_BIGINT=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 -# TODO-WASM -msimd128 -fwasm-exceptions -lnodefs.js -# TODO-WASM -emit-llvm -# TODO-WASM --source-map-base http://microsoft.com -Wno-unused-command-line-argument -Wl,-error-limit=0) From eaa8d708a48bcf13a43806b0cb75e7d96aac7484 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Tue, 23 Sep 2025 13:17:08 +0200 Subject: [PATCH 25/25] link flags back --- src/native/corehost/browserhost/CMakeLists.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/native/corehost/browserhost/CMakeLists.txt b/src/native/corehost/browserhost/CMakeLists.txt index 89893682ee8236..bd3b54b9ffb521 100644 --- a/src/native/corehost/browserhost/CMakeLists.txt +++ b/src/native/corehost/browserhost/CMakeLists.txt @@ -72,15 +72,14 @@ if (UPPERCASE_CMAKE_BUILD_TYPE STREQUAL DEBUG) ) endif () -# TODO-WASM -sMAXIMUM_MEMORY=2147483648 -# TODO-WASM -sALLOW_MEMORY_GROWTH=1 -# TODO-WASM -sALLOW_TABLE_GROWTH=1 # TODO-WASM -sWASM_BIGINT=1 -# TODO-WASM -msimd128 # TODO-WASM -emit-llvm # TODO-WASM --source-map-base http://microsoft.com target_link_options(browserhost PRIVATE - -sINITIAL_MEMORY=33554432 + -sINITIAL_MEMORY=134217728 + -sMAXIMUM_MEMORY=2147483648 + -sALLOW_MEMORY_GROWTH=1 + -sALLOW_TABLE_GROWTH=1 -sSTACK_SIZE=5MB -sMODULARIZE=1 -sEXPORT_ES6=1 @@ -89,6 +88,7 @@ target_link_options(browserhost PRIVATE -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)