Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
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
8 changes: 4 additions & 4 deletions src/native/corehost/browserhost/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,9 @@ if (UPPERCASE_CMAKE_BUILD_TYPE STREQUAL DEBUG)
)
endif ()

# TODO-WASM -sWASM_BIGINT=1
# TODO-WASM -emit-llvm
# TODO-WASM --source-map-base http://microsoft.com
# WASM-TODO -sWASM_BIGINT=1
# WASM-TODO -emit-llvm
# WASM-TODO --source-map-base http://microsoft.com
target_link_options(browserhost PRIVATE
-sINITIAL_MEMORY=134217728
-sMAXIMUM_MEMORY=2147483648
Expand All @@ -85,7 +85,7 @@ target_link_options(browserhost PRIVATE
-sEXPORT_ES6=1
-sEXIT_RUNTIME=0
-sEXPORTED_RUNTIME_METHODS=UTF8ToString,cwrap,ccall,HEAPU8,HEAPU32,HEAPU64,BROWSER_HOST
-sEXPORTED_FUNCTIONS=_posix_memalign,_free,stackAlloc,stackRestore,stackSave,_browserHostInitializeCoreCLR,_browserHostExecuteAssembly,___cpp_exception
-sEXPORTED_FUNCTIONS=_posix_memalign,_free,stackAlloc,stackRestore,stackSave,_BrowserHost_InitializeCoreCLR,_BrowserHost_ExecuteAssembly,___cpp_exception
-sEXPORT_NAME=createDotnetRuntime
-fwasm-exceptions
-msimd128
Expand Down
28 changes: 12 additions & 16 deletions src/native/corehost/browserhost/browserhost.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ extern "C"
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);
bool BrowserHost_ExternalAssemblyProbe(const char* pathPtr, /*out*/ void **outDataStartPtr, /*out*/ int64_t* outSize);
void BrowserHost_ResolveMain(int exitCode);
void BrowserHost_RejectMain(const char *reason);
}

// The current CoreCLR instance details.
Expand All @@ -64,13 +64,6 @@ 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)
Expand Down Expand Up @@ -107,9 +100,11 @@ static std::vector<const char*> propertyKeys;
static std::vector<const char*> propertyValues;
static pal::char_t ptr_to_string_buffer[STRING_LENGTH("0xffffffffffffffff") + 1];

extern "C" int browserHostInitializeCoreCLR(void)
// WASM-TODO: pass TPA via argument, not env
// WASM-TODO: pass app_path via argument, not env
// WASM-TODO: pass search_paths via argument, not env
extern "C" int BrowserHost_InitializeCoreCLR(void)
{
//WASM-TODO: does getenv return UTF8 ?
pal::getenv(HOST_PROPERTY_APP_PATHS, &app_path);
pal::getenv(HOST_PROPERTY_NATIVE_DLL_SEARCH_DIRECTORIES, &search_paths);
pal::getenv(HOST_PROPERTY_TRUSTED_PLATFORM_ASSEMBLIES, &tpa);
Expand All @@ -124,7 +119,7 @@ extern "C" int browserHostInitializeCoreCLR(void)

host_runtime_contract host_contract = { sizeof(host_runtime_contract), nullptr };
host_contract.pinvoke_override = &pinvoke_override;
host_contract.external_assembly_probe = &external_assembly_probe;
host_contract.external_assembly_probe = &BrowserHost_ExternalAssemblyProbe;

pal::snwprintf(ptr_to_string_buffer, ARRAY_SIZE(ptr_to_string_buffer), _X("0x%zx"), (size_t)(&host_contract));

Expand All @@ -144,7 +139,8 @@ extern "C" int browserHostInitializeCoreCLR(void)
}

// WASM-TODO: browser needs async entrypoint
extern "C" int browserHostExecuteAssembly(const char* assemblyPath)
// WASM-TODO: don't coreclr_shutdown_2 when browser
extern "C" int BrowserHost_ExecuteAssembly(const char* assemblyPath)
{
int exit_code;
int retval = coreclr_execute_assembly(CurrentClrInstance, CurrentAppDomainId, 0, nullptr, assemblyPath, (uint32_t*)&exit_code);
Expand All @@ -164,11 +160,11 @@ extern "C" int browserHostExecuteAssembly(const char* assemblyPath)
std::fprintf(stderr, "coreclr_shutdown_2 failed - Error: 0x%08x\n", retval);
exit_code = -1;
// WASM-TODO: this is too trivial
browserHostRejectMain("coreclr_shutdown_2 failed");
BrowserHost_RejectMain("coreclr_shutdown_2 failed");
}

// WASM-TODO: this is too trivial
// because nothing runs continuations yet and also coreclr_execute_assembly is sync looping
browserHostResolveMain(exit_code);
BrowserHost_ResolveMain(exit_code);
return retval;
}
4 changes: 4 additions & 0 deletions src/native/corehost/browserhost/cross-module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

export * from "../../libs/Common/JavaScript/cross-module";
5 changes: 5 additions & 0 deletions src/native/corehost/browserhost/host/cross-linked.ts
Original file line number Diff line number Diff line change
@@ -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.

import { } from "../../../libs/Common/JavaScript/cross-linked";

95 changes: 95 additions & 0 deletions src/native/corehost/browserhost/host/host.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

import type { CharPtr, VoidPtr, VoidPtrPtr } from "./types";
import { } from "./cross-linked"; // ensure ambient symbols are declared

const loadedAssemblies : Map<string, { ptr: number, length: number }> = new Map();

export function registerDllBytes(bytes: Uint8Array, asset: { name: string }) {
const sp = Module.stackSave();
try {
const sizeOfPtr = 4;
const ptrPtr = Module.stackAlloc(sizeOfPtr);
if (Module._posix_memalign(ptrPtr as any, 16, bytes.length)) {
throw new Error("posix_memalign failed");
}

const ptr = Module.HEAPU32[ptrPtr as any >>> 2];
Module.HEAPU8.set(bytes, ptr);
loadedAssemblies.set(asset.name, { ptr, length: bytes.length });
} finally {
Module.stackRestore(sp);
}
}

// bool BrowserHost_ExternalAssemblyProbe(const char* pathPtr, /*out*/ void **outDataStartPtr, /*out*/ int64_t* outSize);
export function BrowserHost_ExternalAssemblyProbe(pathPtr:CharPtr, outDataStartPtr:VoidPtrPtr, outSize:VoidPtr) {
const path = Module.UTF8ToString(pathPtr);
const assembly = loadedAssemblies.get(path);
if (assembly) {
Module.HEAPU32[outDataStartPtr as any >>> 2] = assembly.ptr;
// int64_t target
Module.HEAPU32[outSize as any >>> 2] = assembly.length;
Module.HEAPU32[((outSize as any) + 4) >>> 2] = 0;
return true;
}
Module.HEAPU32[outDataStartPtr as any >>> 2] = 0;
Module.HEAPU32[outSize as any >>> 2] = 0;
Module.HEAPU32[((outSize as any) + 4) >>> 2] = 0;
return false;
}

export function BrowserHost_ResolveMain(exitCode:number) {
dotnetLoaderExports.resolveRunMainPromise(exitCode);
}

export function BrowserHost_RejectMain(reason:any) {
dotnetLoaderExports.rejectRunMainPromise(reason);
}

// WASM-TODO: 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
// - raise ExceptionHandling.RaiseAppDomainUnhandledExceptionEvent()
export function exit(exit_code: number, reason: any): void {
const reasonStr = reason ? (reason.stack ? reason.stack || reason.message : reason.toString()) : "";
if (exit_code !== 0) {
dotnetLogger.error(`Exit with code ${exit_code} ${reason ? "and reason: " + reasonStr : ""}`);
}
if (dotnetJSEngine.IS_NODE) {
(globalThis as any).process.exit(exit_code);
}
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
export async function runMain(mainAssemblyName?: string, args?: string[]): Promise<number> {
// int BrowserHost_ExecuteAssembly(char * assemblyPath)
const res = Module.ccall("BrowserHost_ExecuteAssembly", "number", ["string"], [mainAssemblyName]) as number;
if (res != 0) {
const reason = new Error("Failed to execute assembly");
exit(res, reason);
throw reason;
}

return dotnetLoaderExports.getRunMainPromise();
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
export async function runMainAndExit(mainAssemblyName?: string, args?: string[]): Promise<number> {
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
export function setEnvironmentVariable(name: string, value: string): void {
throw new Error("Not implemented");
}
47 changes: 47 additions & 0 deletions src/native/corehost/browserhost/host/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

import type { InternalExchange, BrowserHostExports, RuntimeAPI, BrowserHostExportsTable } from "./types";
import { InternalExchangeIndex } from "./types";
import { } from "./cross-linked"; // ensure ambient symbols are declared

import { exit, runMain, runMainAndExit, setEnvironmentVariable, registerDllBytes } from "./host";
import {
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,
isSharedArrayBuffer,
} from "./memory";

export function dotnetInitializeModule(internals: InternalExchange): void {
const runtimeApiLocal: Partial<RuntimeAPI> = {
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: BrowserHostExports = {
registerDllBytes,
isSharedArrayBuffer
};
dotnetSetInternals(internals);
Object.assign(internals[InternalExchangeIndex.RuntimeAPI], runtimeApiLocal);
internals[InternalExchangeIndex.BrowserHostExportsTable] = tabulateBrowserHostExports(hostNativeExportsLocal);
const updates = internals[InternalExchangeIndex.InternalUpdatesCallbacks];
if (!updates.includes(dotnetUpdateModuleInternals)) updates.push(dotnetUpdateModuleInternals);
dotnetUpdateAllInternals();

function tabulateBrowserHostExports(map:BrowserHostExports):BrowserHostExportsTable {
// keep in sync with dotnetUpdateModuleInternals()
return [
map.registerDllBytes,
map.isSharedArrayBuffer,
];
}
}

export { BrowserHost_ExternalAssemblyProbe, BrowserHost_ResolveMain, BrowserHost_RejectMain } from "./host";
Loading
Loading