Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/coreclr/hosts/corerun/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ else()
set(JS_SYSTEM_NATIVE_BROWSER
"${STATIC_LIB_DESTINATION}/libSystem.Native.Browser.js")
set(JS_SYSTEM_BROWSER_UTILS
"${STATIC_LIB_DESTINATION}/libSystem.Browser.Utils.js")
"${STATIC_LIB_DESTINATION}/libSystem.Native.Browser.Utils.js")
set(JS_CORE_RUN
"${CMAKE_CURRENT_SOURCE_DIR}/wasm/libCorerun.extpost.js")
set_target_properties(corerun PROPERTIES
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -271,8 +271,8 @@
<PlatformManifestFileEntry Include="libnativeresourcestring.a" IsNative="true" />
<PlatformManifestFileEntry Include="libBrowserHost.js" IsNative="true" />
<PlatformManifestFileEntry Include="libBrowserHost.js.map" IsNative="true" />
<PlatformManifestFileEntry Include="libSystem.Browser.Utils.js" IsNative="true" />
<PlatformManifestFileEntry Include="libSystem.Browser.Utils.js.map" IsNative="true" />
<PlatformManifestFileEntry Include="libSystem.Native.Browser.Utils.js" IsNative="true" />
<PlatformManifestFileEntry Include="libSystem.Native.Browser.Utils.js.map" IsNative="true" />
<PlatformManifestFileEntry Include="libSystem.Native.Browser.js" IsNative="true" />
<PlatformManifestFileEntry Include="libSystem.Native.Browser.js.map" IsNative="true" />
<PlatformManifestFileEntry Include="libSystem.Runtime.InteropServices.JavaScript.Native.js" IsNative="true" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ internal static partial class Interop
{
internal static unsafe partial class JsGlobalization
{
[LibraryImport(Libraries.JavaScriptNative, EntryPoint = "SystemJS_GetLocaleInfo")]
[LibraryImport(Libraries.SystemBrowserNative, EntryPoint = "SystemJS_GetLocaleInfo")]
public static unsafe partial nint GetLocaleInfo(char* locale, int localeLength, char* culture, int cultureLength, char* buffer, int bufferLength, out int resultLength);
}
}
3 changes: 2 additions & 1 deletion src/libraries/Common/src/Interop/Unix/Interop.Libraries.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ internal static partial class Libraries
internal const string CryptoNative = "libSystem.Security.Cryptography.Native.OpenSsl";
internal const string CompressionNative = "libSystem.IO.Compression.Native";
internal const string GlobalizationNative = "libSystem.Globalization.Native";
internal const string JavaScriptNative = "libSystem.Runtime.InteropServices.JavaScript.Native";
internal const string IOPortsNative = "libSystem.IO.Ports.Native";
internal const string HostPolicy = "libhostpolicy";
internal const string JavaScriptNative = "libSystem.JavaScript.Native";
internal const string SystemBrowserNative = "libSystem.Native.Browser";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1378,8 +1378,8 @@
<Compile Include="$(CommonPath)Interop\Browser\Interop.Locale.CoreCLR.cs" Condition="'$(TargetsBrowser)' == 'true' and '$(RuntimeFlavor)' == 'CoreCLR'">
<Link>Common\Interop\Browser\Interop.Locale.CoreCLR.cs</Link>
</Compile>
<Compile Include="$(CommonPath)Interop\Browser\Interop.Locale.cs" Condition="'$(TargetsBrowser)' == 'true' and '$(RuntimeFlavor)' == 'Mono'">
<Link>Common\Interop\Browser\Interop.Locale.cs</Link>
<Compile Include="$(CommonPath)Interop\Browser\Interop.Locale.Mono.cs" Condition="'$(TargetsBrowser)' == 'true' and '$(RuntimeFlavor)' == 'Mono'">
<Link>Common\Interop\Browser\Interop.Locale.Mono.cs</Link>
</Compile>
<Compile Include="$(CommonPath)Interop\Interop.Calendar.cs">
<Link>Common\Interop\Interop.Calendar.cs</Link>
Expand Down
4 changes: 2 additions & 2 deletions src/libraries/externals.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@
<RuntimeFiles Include="@(HostPolicyFile)" Condition="Exists('@(HostPolicyFile)')" />
<RuntimeFiles Include="@(_HostSymbols)" Condition="Exists('@(_HostSymbols)')" IsNative="true" />
<!-- CoreRun is not used for testing anymore, but we still use it for benchmarking and profiling -->
<RuntimeFiles Include="$(CoreCLRArtifactsPath)\corerun*" Condition="'$(TargetsAndroid)' != 'true'" />
<RuntimeFiles Include="$(CoreCLRArtifactsPath)\PDB\corerun*" Condition="'$(TargetsAndroid)' != 'true'" />
<RuntimeFiles Include="$(CoreCLRArtifactsPath)\corerun*" Condition="'$(TargetsAndroid)' != 'true' and '$(TargetsBrowser)' != 'true'" />
<RuntimeFiles Include="$(CoreCLRArtifactsPath)\PDB\corerun*" Condition="'$(TargetsAndroid)' != 'true' and '$(TargetsBrowser)' != 'true'" />
<!-- Include cDAC reader library
TODO: [cdac] Remove once cdacreader is added to shipping shared framework -->
<RuntimeFiles Include="$(CoreCLRArtifactsPath)\*mscordaccore_universal*" />
Expand Down
2 changes: 1 addition & 1 deletion src/native/corehost/browserhost/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ LIST(APPEND NATIVE_LIBS
set(JS_SYSTEM_NATIVE_BROWSER
"${SHARED_LIB_DESTINATION}/libSystem.Native.Browser.js")
set(JS_SYSTEM_BROWSER_UTILS
"${SHARED_LIB_DESTINATION}/libSystem.Browser.Utils.js")
"${SHARED_LIB_DESTINATION}/libSystem.Native.Browser.Utils.js")
set(JS_SYSTEM_RUNTIME_INTEROPSERVICES_JAVASCRIPT_NATIVE
"${SHARED_LIB_DESTINATION}/libSystem.Runtime.InteropServices.JavaScript.Native.js")
set(JS_BROWSER_HOST
Expand Down
2 changes: 1 addition & 1 deletion src/native/corehost/browserhost/ReadMe.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Implements native part of the CoreCLR host and exposes it as an internal JavaScr
It is **Emscripten application** statically linked from libraries.

- `libSystem.Native.Browser.js` linked -> `dotnet.native.js`
- `libSystem.Browser.Utils.js` linked -> `dotnet.native.js`
- `libSystem.Native.Browser.Utils.js` linked -> `dotnet.native.js`
- `libSystem.Runtime.InteropServices.JavaScript.Native.js` linked -> `dotnet.native.js`
- `libSystem.Native.Browser.a` linked -> `dotnet.native.wasm`
- `libSystem.Runtime.InteropServices.JavaScript.Native.a` linked -> `dotnet.native.wasm`
Expand Down
2 changes: 1 addition & 1 deletion src/native/corehost/browserhost/browserhost.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ static const void* pinvoke_override(const char* library_name, const char* entry_
{
return SystemResolveDllImport(entry_point_name);
}
if (strcmp(library_name, "libSystem.JavaScript.Native") == 0)
if (strcmp(library_name, "libSystem.Native.Browser") == 0)
{
return SystemJSResolveDllImport(entry_point_name);
}
Expand Down
15 changes: 9 additions & 6 deletions src/native/corehost/browserhost/libBrowserHost.footer.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,15 @@
!config.environmentVariables) {
throw new Error("Invalid runtime config, cannot initialize the runtime.");
}
const assemblyPaths = config.resources.assembly.map(a => a.virtualPath);
const coreAssemblyPaths = config.resources.coreAssembly.map(a => a.virtualPath);
ENV[HOST_PROPERTY_TRUSTED_PLATFORM_ASSEMBLIES] = config.environmentVariables[HOST_PROPERTY_TRUSTED_PLATFORM_ASSEMBLIES] = [...coreAssemblyPaths, ...assemblyPaths].join(":");
ENV[HOST_PROPERTY_NATIVE_DLL_SEARCH_DIRECTORIES] = config.environmentVariables[HOST_PROPERTY_NATIVE_DLL_SEARCH_DIRECTORIES] = config.virtualWorkingDirectory;
ENV[HOST_PROPERTY_APP_PATHS] = config.environmentVariables[HOST_PROPERTY_APP_PATHS] = config.virtualWorkingDirectory;
ENV[HOST_PROPERTY_ENTRY_ASSEMBLY_NAME] = config.environmentVariables[HOST_PROPERTY_ENTRY_ASSEMBLY_NAME] = config.mainAssemblyName;
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;
for (const key in config.environmentVariables) {
ENV[key] = config.environmentVariables[key];
}

if (ENVIRONMENT_IS_NODE) {
Module.preInit = [() => {
Expand Down
129 changes: 129 additions & 0 deletions src/native/corehost/browserhost/loader/assets.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

import type { LoadBootResourceCallback, JsModuleExports, JsAsset, AssemblyAsset, PdbAsset, WasmAsset, IcuAsset, EmscriptenModuleInternal, InstantiateWasmSuccessCallback } from "./types";

import { dotnetAssert, dotnetGetInternals, dotnetBrowserHostExports, dotnetUpdateInternals } from "./cross-module";
import { getIcuResourceName } from "./icu";
import { getLoaderConfig } from "./config";
import { BrowserHost_InitializeCoreCLR } from "./run";
import { createPromiseCompletionSource } from "./promise-completion-source";
import { locateFile } from "./bootstrap";
import { fetchLike } from "./polyfills";

const nativeModulePromiseController = createPromiseCompletionSource<EmscriptenModuleInternal>(() => {
dotnetUpdateInternals(dotnetGetInternals());
});
let wasmBinaryPromise: any = undefined;

// WASM-TODO: retry logic
// WASM-TODO: throttling logic
// WASM-TODO: invokeLibraryInitializers
// WASM-TODO: webCIL
// WASM-TODO: downloadOnly - blazor render mode auto pre-download. Really no start.
// WASM-TODO: no-cache, force-cache, integrity
// WASM-TODO: LoadBootResourceCallback
// WASM-TODO: fail fast for missing WASM features - SIMD, EH, BigInt detection

export async function createRuntime(downloadOnly: boolean, loadBootResource?: LoadBootResourceCallback): Promise<any> {
if (loadBootResource) throw new Error("TODO: loadBootResource is not implemented yet");
const config = getLoaderConfig();
if (!config.resources || !config.resources.coreAssembly || !config.resources.coreAssembly.length) throw new Error("Invalid config, resources is not set");

const nativeModulePromise = loadJSModule(config.resources.jsModuleNative[0]);
const runtimeModulePromise = loadJSModule(config.resources.jsModuleRuntime[0]);
const wasmNativePromise = fetchWasm(config.resources.wasmNative[0]);

const coreAssembliesPromise = Promise.all(config.resources.coreAssembly.map(fetchDll));
const coreVfsPromise = Promise.all((config.resources.coreVfs || []).map(fetchVfs));
const assembliesPromise = Promise.all(config.resources.assembly.map(fetchDll));
const vfsPromise = Promise.all((config.resources.vfs || []).map(fetchVfs));
const icuResourceName = getIcuResourceName(config);
const icuDataPromise = icuResourceName ? Promise.all((config.resources.icu || []).filter(asset => asset.name === icuResourceName).map(fetchIcu)) : Promise.resolve([]);

const nativeModule = await nativeModulePromise;
const modulePromise = nativeModule.dotnetInitializeModule<EmscriptenModuleInternal>(dotnetGetInternals());
nativeModulePromiseController.propagateFrom(modulePromise);

const runtimeModule = await runtimeModulePromise;
const runtimeModuleReady = runtimeModule.dotnetInitializeModule<void>(dotnetGetInternals());

await nativeModulePromiseController.promise;
await coreAssembliesPromise;
await coreVfsPromise;
await vfsPromise;
await icuDataPromise;
await wasmNativePromise; // this is just to propagate errors
if (!downloadOnly) {
BrowserHost_InitializeCoreCLR();
}

await assembliesPromise;
await runtimeModuleReady;
}

async function loadJSModule(asset: JsAsset): Promise<JsModuleExports> {
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: WasmAsset): Promise<Response> {
if (asset.name && !asset.resolvedUrl) {
asset.resolvedUrl = locateFile(asset.name);
}
if (!asset.resolvedUrl) throw new Error("Invalid config, resources is not set");
wasmBinaryPromise = fetchLike(asset.resolvedUrl);
return wasmBinaryPromise;
}

export async function instantiateWasm(imports: WebAssembly.Imports, successCallback: InstantiateWasmSuccessCallback): Promise<void> {
if (wasmBinaryPromise instanceof globalThis.Response === false || !WebAssembly.instantiateStreaming) {
const res = await wasmBinaryPromise;
const data = await res.arrayBuffer();
const module = await WebAssembly.compile(data);
const instance = await WebAssembly.instantiate(module, imports);
successCallback(instance, module);
} else {
const res = await WebAssembly.instantiateStreaming(wasmBinaryPromise, imports);
successCallback(res.instance, res.module);
}
}

async function fetchIcu(asset: IcuAsset): Promise<void> {
if (asset.name && !asset.resolvedUrl) {
asset.resolvedUrl = locateFile(asset.name);
}
const bytes = await fetchBytes(asset);
await nativeModulePromiseController.promise;
dotnetBrowserHostExports.loadIcuData(bytes);
}

async function fetchDll(asset: AssemblyAsset): Promise<void> {
if (asset.name && !asset.resolvedUrl) {
asset.resolvedUrl = locateFile(asset.name);
}
const bytes = await fetchBytes(asset);
await nativeModulePromiseController.promise;

dotnetBrowserHostExports.registerDllBytes(bytes, asset);
}

async function fetchVfs(asset: AssemblyAsset): Promise<void> {
if (asset.name && !asset.resolvedUrl) {
asset.resolvedUrl = locateFile(asset.name);
}
const bytes = await fetchBytes(asset);
await nativeModulePromiseController.promise;

dotnetBrowserHostExports.installVfsFile(bytes, asset);
}

async function fetchBytes(asset: WasmAsset | AssemblyAsset | PdbAsset | IcuAsset): Promise<Uint8Array> {
dotnetAssert.check(asset && asset.resolvedUrl, "Bad asset.resolvedUrl");
const response = await fetchLike(asset.resolvedUrl);
const buffer = await response.arrayBuffer();
return new Uint8Array(buffer);
}
Loading
Loading