Skip to content

Commit 5d801d7

Browse files
committed
interesting stuff
1 parent 5b642d9 commit 5d801d7

File tree

9 files changed

+604
-0
lines changed

9 files changed

+604
-0
lines changed
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# Licensed to the .NET Foundation under one or more agreements.
2+
# The .NET Foundation licenses this file to you under the MIT license.
3+
4+
project(browserhost)
5+
set(DOTNET_PROJECT_NAME "browserhost")
6+
7+
include_directories(..)
8+
include_directories(../hostmisc)
9+
#WASMTODO include_directories(../hostpolicy)
10+
#WASMTODO include_directories(../json)
11+
include_directories(${CLR_SRC_NATIVE_DIR}/libs/System.JavaScript)
12+
include_directories(${CLR_SRC_NATIVE_DIR}/libs/System.Runtime.InteropServices.JavaScript)
13+
include_directories(${CLR_SRC_NATIVE_DIR}/libs/System.IO.Compression.Native)
14+
include_directories(${CLR_SRC_NATIVE_DIR}/libs/Common)
15+
include_directories(${CLR_ARTIFACTS_OBJ_DIR}) # Generated version files
16+
17+
add_subdirectory(../hostmisc hostmisc)
18+
19+
configure_file(${CLR_SRC_NATIVE_DIR}/corehost/configure.h.in ${GENERATED_INCLUDE_DIR}/corehost/configure.h)
20+
target_include_directories(hostmisc_interface INTERFACE ${GENERATED_INCLUDE_DIR}/corehost)
21+
22+
set(SOURCES
23+
./browserhost.cpp
24+
native.rc
25+
)
26+
set(HEADERS
27+
)
28+
29+
add_compile_definitions(FEATURE_APPHOST)
30+
add_definitions(-DFEATURE_APPHOST=1)
31+
add_definitions(-DFEATURE_STATIC_HOST=1)
32+
33+
add_executable(browserhost ${SOURCES})
34+
set_target_properties(browserhost PROPERTIES OUTPUT_NAME dotnet.native)
35+
set(CMAKE_EXECUTABLE_SUFFIX ".js")
36+
37+
install(TARGETS browserhost DESTINATION corehost COMPONENT runtime)
38+
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/dotnet.native.wasm DESTINATION corehost COMPONENT runtime)
39+
40+
include(configure.cmake)
41+
42+
LIST(APPEND NATIVE_LIBS
43+
coreclr_static
44+
System.JavaScript-Static
45+
System.Runtime.InteropServices.JavaScript-Static
46+
System.Native-Static
47+
System.Globalization.Native-Static
48+
System.IO.Compression.Native-Static
49+
nativeresourcestring
50+
gcinfo
51+
# WASMTODO do not link icudata and download shard at runtime
52+
# WASMTODO respect $(InvariantTimezone)
53+
# System.Native.TimeZoneData.Invariant
54+
System.Native.TimeZoneData
55+
)
56+
57+
# WASMTODO set(RUNTIMEINFO_LIB runtimeinfo)
58+
59+
target_compile_options(browserhost PRIVATE -fwasm-exceptions)
60+
61+
set_target_properties(browserhost PROPERTIES
62+
LINK_DEPENDS "${CLR_SRC_NATIVE_DIR}/libs/System.JavaScript/System.JavaScript.extpost.js;${CLR_SRC_NATIVE_DIR}/libs/System.JavaScript/System.JavaScript.js;${CLR_SRC_NATIVE_DIR}/libs/System.Runtime.InteropServices.JavaScript/System.Runtime.InteropServices.JavaScript.js;"
63+
LINK_FLAGS "--js-library ${CLR_SRC_NATIVE_DIR}/libs/System.JavaScript/System.JavaScript.js --js-library ${CLR_SRC_NATIVE_DIR}/libs/System.Runtime.InteropServices.JavaScript/System.Runtime.InteropServices.JavaScript.js --extern-post-js ${CLR_SRC_NATIVE_DIR}/libs/System.JavaScript/System.JavaScript.extpost.js"
64+
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
65+
66+
# WASMTODO linker options for NodeJs for now
67+
# WASMTODO -Oz -sVERBOSE
68+
target_link_options(browserhost PRIVATE
69+
-fwasm-exceptions
70+
-sEXPORTED_RUNTIME_METHODS=FS
71+
-sEXIT_RUNTIME=1
72+
-sINITIAL_MEMORY=134217728
73+
-sSTACK_SIZE=5MB
74+
-sMODULARIZE=1
75+
-sEXPORT_ES6=1
76+
-s EXPORT_NAME=createDotnetRuntime
77+
-lnoderawfs.js
78+
-lnodefs.js
79+
-Wl,-error-limit=0)
80+
81+
target_link_libraries(
82+
browserhost
83+
PRIVATE
84+
hostmisc
85+
clrinterpreter
86+
${NATIVE_LIBS}
87+
88+
${START_WHOLE_ARCHIVE}
89+
${RUNTIMEINFO_LIB}
90+
${END_WHOLE_ARCHIVE}
91+
)
92+
93+
# TODOWASM: this is temporary NodeJS host until we TypeScript projects
94+
set(TEST_ASSETS
95+
${CLR_ARTIFACTS_OBJ_DIR}/System.JavaScript/index.html
96+
${CLR_ARTIFACTS_OBJ_DIR}/System.JavaScript/main.mjs
97+
${CLR_ARTIFACTS_OBJ_DIR}/System.JavaScript/dotnet.js
98+
${CLR_ARTIFACTS_OBJ_DIR}/System.JavaScript/dotnet.runtime.js
99+
)
100+
install(FILES ${TEST_ASSETS} DESTINATION corehost COMPONENT runtime)
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
//
4+
5+
#include <cstdio>
6+
#include <vector>
7+
#include <emscripten.h>
8+
9+
#include <pal.h>
10+
#include <minipal/utils.h>
11+
#include <host_runtime_contract.h>
12+
13+
static void log_error_info(const char* line)
14+
{
15+
std::fprintf(stderr, "log error: %s\n", line);
16+
}
17+
18+
// The current CoreCLR instance details.
19+
static void* CurrentClrInstance;
20+
static unsigned int CurrentAppDomainId;
21+
22+
typedef void (*coreclr_error_writer_callback_fn)(const char* line);
23+
extern "C"
24+
{
25+
pal::hresult_t coreclr_initialize(
26+
const char* exePath,
27+
const char* appDomainFriendlyName,
28+
int propertyCount,
29+
const char** propertyKeys,
30+
const char** propertyValues,
31+
void** hostHandle,
32+
unsigned int* domainId);
33+
34+
pal::hresult_t coreclr_shutdown_2(
35+
void* hostHandle,
36+
unsigned int domainId,
37+
int* latchedExitCode);
38+
39+
pal::hresult_t coreclr_execute_assembly(
40+
void* hostHandle,
41+
unsigned int domainId,
42+
int argc,
43+
const char** argv,
44+
const char* managedAssemblyPath,
45+
unsigned int* exitCode);
46+
47+
pal::hresult_t coreclr_create_delegate(
48+
void* hostHandle,
49+
unsigned int domainId,
50+
const char* entryPointAssemblyName,
51+
const char* entryPointTypeName,
52+
const char* entryPointMethodName,
53+
void** delegate);
54+
55+
pal::hresult_t coreclr_set_error_writer(
56+
coreclr_error_writer_callback_fn error_writer);
57+
58+
const void* SystemResolveDllImport(const char* name);
59+
const void* SystemJSResolveDllImport(const char* name);
60+
const void* SystemJSInteropResolveDllImport(const char* name);
61+
const void* GlobalizationResolveDllImport(const char* name);
62+
const void* CompressionResolveDllImport(const char* name);
63+
}
64+
65+
bool bundle_probe(const char* path, int64_t* offset, int64_t* size, int64_t* compressedSize)
66+
{
67+
// WASMTODO: Not implemented
68+
return false;
69+
}
70+
71+
bool external_assembly_probe(const char* path, /*out*/ void **data_start, /*out*/ int64_t* size)
72+
{
73+
// WASMTODO: Not implemented
74+
return false;
75+
}
76+
77+
size_t get_runtime_property(const char* key, char* value_buffer, size_t value_buffer_size, void* contract_context)
78+
{
79+
// WASMTODO: Not implemented
80+
return -1;
81+
}
82+
83+
const void* pinvoke_override(const char* library_name, const char* entry_point_name)
84+
{
85+
if (strcmp(library_name, "libSystem.Native") == 0)
86+
{
87+
return SystemResolveDllImport(entry_point_name);
88+
}
89+
if (strcmp(library_name, "libSystem.JavaScript") == 0)
90+
{
91+
return SystemJSResolveDllImport(entry_point_name);
92+
}
93+
if (strcmp(library_name, "libSystem.Runtime.InteropServices.JavaScript") == 0)
94+
{
95+
return SystemJSInteropResolveDllImport(entry_point_name);
96+
}
97+
if (strcmp(library_name, "libSystem.Globalization.Native") == 0)
98+
{
99+
return GlobalizationResolveDllImport(entry_point_name);
100+
}
101+
if (strcmp(library_name, "libSystem.IO.Compression.Native") == 0)
102+
{
103+
return CompressionResolveDllImport(entry_point_name);
104+
}
105+
106+
return nullptr;
107+
}
108+
109+
static int run()
110+
{
111+
pal::string_t exe_path;
112+
pal::string_t tpa;
113+
pal::string_t app;
114+
pal::getenv("CWD", &exe_path);
115+
pal::getenv("TRUSTED_PLATFORM_ASSEMBLIES", &tpa);
116+
pal::getenv("APP", &app);
117+
const pal::string_t app_domain_name = "corehost";
118+
119+
// Set base initialization properties.
120+
std::vector<const char*> propertyKeys;
121+
std::vector<const char*> propertyValues;
122+
123+
propertyKeys.push_back(HOST_PROPERTY_TRUSTED_PLATFORM_ASSEMBLIES);
124+
propertyValues.push_back(tpa.c_str());
125+
propertyKeys.push_back(HOST_PROPERTY_NATIVE_DLL_SEARCH_DIRECTORIES);
126+
propertyValues.push_back(exe_path.c_str());
127+
128+
host_runtime_contract host_contract = { sizeof(host_runtime_contract), nullptr };
129+
host_contract.get_runtime_property = &get_runtime_property;
130+
host_contract.bundle_probe = &bundle_probe;
131+
host_contract.pinvoke_override = &pinvoke_override;
132+
host_contract.external_assembly_probe = &external_assembly_probe;
133+
134+
pal::char_t buffer[STRING_LENGTH("0xffffffffffffffff")];
135+
pal::snwprintf(buffer, ARRAY_SIZE(buffer), _X("0x%zx"), (size_t)(&host_contract));
136+
137+
propertyKeys.push_back(HOST_PROPERTY_RUNTIME_CONTRACT);
138+
propertyValues.push_back(buffer);
139+
140+
coreclr_set_error_writer(log_error_info);
141+
142+
// printf("BEGIN: call coreclr_initialize\n");
143+
int retval = coreclr_initialize(exe_path.c_str(), app_domain_name.c_str(), (int)propertyKeys.size(), propertyKeys.data(), propertyValues.data(), &CurrentClrInstance, &CurrentAppDomainId);
144+
// printf("END: call coreclr_initialize\n");
145+
146+
if (retval < 0)
147+
{
148+
std::fprintf(stderr, "coreclr_initialize failed - Error: 0x%08x\n", retval);
149+
return -1;
150+
}
151+
else
152+
{
153+
// printf("coreclr_initialize succeeded - retval: 0x%08x\n", retval);
154+
}
155+
156+
int exit_code;
157+
// printf("BEGIN: call coreclr_execute_assembly\n");
158+
retval = coreclr_execute_assembly(CurrentClrInstance, CurrentAppDomainId, 0, nullptr, app.c_str(), (uint32_t*)&exit_code);
159+
// printf("END: call coreclr_execute_assembly\n");
160+
161+
if (retval < 0)
162+
{
163+
std::fprintf(stderr, "coreclr_execute_assembly failed - Error: 0x%08x\n", retval);
164+
return -1;
165+
}
166+
167+
int latched_exit_code = 0;
168+
// printf("BEGIN: call coreclr_shutdown_2\n");
169+
retval = coreclr_shutdown_2(CurrentClrInstance, CurrentAppDomainId, &latched_exit_code);
170+
// printf("END: call coreclr_shutdown_2\n");
171+
if (retval < 0)
172+
{
173+
std::fprintf(stderr, "coreclr_shutdown_2 failed - Error: 0x%08x\n", retval);
174+
exit_code = -1;
175+
}
176+
177+
return retval;
178+
}
179+
180+
int main()
181+
{
182+
int retval = run();
183+
184+
return retval;
185+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
import { dotnet, exit } from './dotnet.js'
4+
import fs from 'fs';
5+
6+
try {
7+
// TODOWASM: this is temporary NodeJS host until we have proper host
8+
const env = {};
9+
for (const [key, value] of Object.entries(process.env)) {
10+
env[key] = value;
11+
}
12+
const cwd = process.cwd().replaceAll('\\', '/').replace(/[a-zA-Z]:[\\/]/, '/'); // unix vs windows, remove drive letter
13+
const app = process.argv[2] || "HelloWorld.dll";
14+
const args = process.argv.slice(2);
15+
const dlls = fs.readdirSync(cwd).filter(f => f.endsWith('.dll'));
16+
const tpa = dlls.map(f => `${cwd}/${f}`).join(':');
17+
env["CWD"] = cwd;
18+
env["ARGS"] = args;
19+
env["APP"] = `${cwd}/${app}`;
20+
env["TRUSTED_PLATFORM_ASSEMBLIES"] = tpa;
21+
22+
await dotnet
23+
.withEnvironmentVariables(env)
24+
.run();
25+
}
26+
catch (err) {
27+
console.error(err);
28+
exit(2, err);
29+
}
30+
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//! Licensed to the .NET Foundation under one or more agreements.
2+
//! The .NET Foundation licenses this file to you under the MIT license.
3+
4+
// TODOWASM: this is dummy implementation to allow build to succeed
5+
6+
/* eslint-disable no-console */
7+
/* eslint-disable space-before-function-paren */
8+
import { initialize as initializeRuntime } from "./dotnet.runtime.js"; // TODOWASM: this will be dynamic import
9+
import { initialize as initializeNative } from "./dotnet.native.js"; // TODOWASM: this will be dynamic import
10+
11+
const config = {
12+
environmentVariables: {}
13+
};
14+
const Module = {
15+
};
16+
const runtimeApi = {
17+
Module,
18+
exit,
19+
};
20+
const dotnetInternals = {
21+
config,
22+
runtimeApi,
23+
};
24+
Module.dotnetInternals = dotnetInternals;
25+
26+
export function exit(exit_code, reason) {
27+
const reasonStr = reason ? (reason.stack ? reason.stack || reason.message : reason.toString()) : "";
28+
console.error(`Exit with code ${exit_code} ${reason ? "and reason: " + reasonStr : ""}`);
29+
process.exit(exit_code);
30+
}
31+
32+
export const dotnet = {
33+
withEnvironmentVariables: (env) => {
34+
Object.assign(config.environmentVariables, env);
35+
return dotnet;
36+
},
37+
run: async () => {
38+
await initializeRuntime(dotnetInternals);
39+
await initializeNative(dotnetInternals);
40+
return runtimeApi;
41+
}
42+
};
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
//! Licensed to the .NET Foundation under one or more agreements.
2+
//! The .NET Foundation licenses this file to you under the MIT license.
3+
4+
// TODOWASM: this is dummy implementation to allow build to succeed
5+
6+
/* eslint-disable @typescript-eslint/no-unused-vars */
7+
export async function initialize(internalApis) {
8+
return Promise.resolve();
9+
}

0 commit comments

Comments
 (0)