Skip to content

Commit dd774a7

Browse files
committed
wip
1 parent cec3cbd commit dd774a7

File tree

8 files changed

+102
-22
lines changed

8 files changed

+102
-22
lines changed

src/coreclr/hosts/corerun/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ else()
7676
-sSTACK_SIZE=5MB
7777
-sMODULARIZE=1
7878
-sEXPORT_ES6=1
79-
-sEXPORTED_RUNTIME_METHODS=${CMAKE_EMCC_EXPORTED_RUNTIME_METHODS}
79+
-sEXPORTED_RUNTIME_METHODS=ENV,${CMAKE_EMCC_EXPORTED_RUNTIME_METHODS}
8080
-sEXPORTED_FUNCTIONS=_main,${CMAKE_EMCC_EXPORTED_FUNCTIONS}
8181
-sEXPORT_NAME=createDotnetRuntime
8282
-sENVIRONMENT=node,shell,web

src/native/corehost/browserhost/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,6 @@ target_link_options(browserhost PRIVATE
110110
-sMAXIMUM_MEMORY=2147483648
111111
-sALLOW_MEMORY_GROWTH=1
112112
-sSTACK_SIZE=5MB
113-
-sWASM_BIGINT=1
114113
-sMODULARIZE=1
115114
-sEXPORT_ES6=1
116115
-sEXIT_RUNTIME=0

src/native/corehost/browserhost/libBrowserHost.footer.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@
4545
!config.environmentVariables) {
4646
throw new Error("Invalid runtime config, cannot initialize the runtime.");
4747
}
48-
const assemblyPaths = config.resources.assembly.map(a => "/" + a.virtualPath);
49-
const coreAssemblyPaths = config.resources.coreAssembly.map(a => "/" + a.virtualPath);
48+
const assemblyPaths = config.resources.assembly.map(a => a.virtualPath);
49+
const coreAssemblyPaths = config.resources.coreAssembly.map(a => a.virtualPath);
5050
ENV[HOST_PROPERTY_TRUSTED_PLATFORM_ASSEMBLIES] = config.environmentVariables[HOST_PROPERTY_TRUSTED_PLATFORM_ASSEMBLIES] = [...coreAssemblyPaths, ...assemblyPaths].join(":");
5151
ENV[HOST_PROPERTY_NATIVE_DLL_SEARCH_DIRECTORIES] = config.environmentVariables[HOST_PROPERTY_NATIVE_DLL_SEARCH_DIRECTORIES] = config.virtualWorkingDirectory;
5252
ENV[HOST_PROPERTY_APP_PATHS] = config.environmentVariables[HOST_PROPERTY_APP_PATHS] = config.virtualWorkingDirectory;

src/native/corehost/browserhost/loader/bootstrap.ts

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4-
import type { LoadBootResourceCallback, JsModuleExports, JsAsset, AssemblyAsset, PdbAsset, WasmAsset, IcuAsset, EmscriptenModuleInternal } from "./types";
4+
import type { LoadBootResourceCallback, JsModuleExports, JsAsset, AssemblyAsset, PdbAsset, WasmAsset, IcuAsset, EmscriptenModuleInternal, LoaderConfig, DotnetHostBuilder } from "./types";
55

66
import { dotnetAssert, dotnetGetInternals, dotnetBrowserHostExports, dotnetUpdateInternals } from "./cross-module";
77
import { ENVIRONMENT_IS_NODE, ENVIRONMENT_IS_SHELL } from "./per-module";
88
import { getLoaderConfig } from "./config";
99
import { BrowserHost_InitializeCoreCLR } from "./run";
1010
import { createPromiseController } from "./promise-controller";
11+
import { node_fs, node_url } from "./polyfills";
1112

1213
const scriptUrlQuery = /*! webpackIgnore: true */import.meta.url;
1314
const queryIndex = scriptUrlQuery.indexOf("?");
@@ -143,3 +144,49 @@ function isPathAbsolute(path: string): boolean {
143144
// windows http://C:/x.json
144145
return protocolRx.test(path);
145146
}
147+
148+
export function isShellHosted(): boolean {
149+
return ENVIRONMENT_IS_SHELL && typeof (globalThis as any).arguments !== "undefined";
150+
}
151+
152+
export function isNodeHosted(): boolean {
153+
if (!ENVIRONMENT_IS_NODE || globalThis.process.argv.length < 3) {
154+
return false;
155+
}
156+
const argv1 = globalThis.process.argv[1].toLowerCase();
157+
const argScript = normalizeFileUrl("file:///" + locateFile(argv1));
158+
const importScript = normalizeFileUrl(locateFile(scriptUrl.toLowerCase()));
159+
160+
return argScript === importScript;
161+
}
162+
163+
export async function findResources(dotnet: DotnetHostBuilder): Promise<void> {
164+
if (!ENVIRONMENT_IS_NODE) {
165+
return;
166+
}
167+
const fs = await node_fs();
168+
const url = await node_url();
169+
const scriptDir = url.fileURLToPath(scriptDirectory).replace(windowsAbsoluteRx, "/").replace(/\\/g, "/");
170+
const files: string[] = await fs.promises.readdir(scriptDir);
171+
const assemblies = files
172+
// TODO-WASM: webCIL
173+
.filter(file => file.endsWith(".dll"))
174+
.map(filename => {
175+
// filename without path
176+
const name = filename.substring(filename.lastIndexOf("/") + 1);
177+
return { virtualPath: scriptDir + filename, name };
178+
});
179+
const config: LoaderConfig = {
180+
mainAssemblyName: globalThis.process.argv[2],
181+
virtualWorkingDirectory: scriptDir,
182+
resources: {
183+
jsModuleNative: [{ name: "dotnet.native.js" }],
184+
jsModuleRuntime: [{ name: "dotnet.runtime.js" }],
185+
wasmNative: [{ name: "dotnet.native.wasm", }],
186+
coreAssembly: [{ virtualPath: scriptDir + "System.Private.CoreLib.dll", name: "System.Private.CoreLib.dll" },],
187+
assembly: assemblies,
188+
}
189+
};
190+
dotnet.withConfig(config);
191+
dotnet.withApplicationArguments(...globalThis.process.argv.slice(3));
192+
}

src/native/corehost/browserhost/loader/dotnet.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,14 @@ import { HostBuilder } from "./host-builder";
1414
import { initPolyfills, initPolyfillsAsync } from "./polyfills";
1515
import { exit } from "./exit";
1616
import { dotnetInitializeModule } from ".";
17+
import { selfHostNodeJS } from "./run";
1718

1819
initPolyfills();
1920
dotnetInitializeModule();
2021
await initPolyfillsAsync();
2122

2223
export const dotnet: DotnetHostBuilder | undefined = new HostBuilder() as DotnetHostBuilder;
2324
export { exit };
25+
26+
// Auto-start when in Node.js or Shell environment
27+
selfHostNodeJS(dotnet!);

src/native/corehost/browserhost/loader/polyfills.ts

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -48,30 +48,43 @@ export async function initPolyfillsAsync(): Promise<void> {
4848
// WASM-TODO: performance polyfill for V8
4949
}
5050

51+
let _node_fs: any | undefined = undefined;
52+
let _node_url: any | undefined = undefined;
53+
54+
export async function node_fs(): Promise<any> {
55+
if (ENVIRONMENT_IS_NODE && !_node_fs) {
56+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
57+
// @ts-ignore:
58+
_node_fs = await import(/*! webpackIgnore: true */"fs");
59+
}
60+
return _node_fs;
61+
}
62+
63+
export async function node_url(): Promise<any> {
64+
if (ENVIRONMENT_IS_NODE && !_node_url) {
65+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
66+
// @ts-ignore:
67+
_node_url = await import(/*! webpackIgnore: true */"node:url");
68+
}
69+
return _node_url;
70+
}
71+
5172
export async function fetchLike(url: string, init?: RequestInit): Promise<Response> {
52-
let node_fs: any | undefined = undefined;
53-
let node_url: any | undefined = undefined;
5473
try {
74+
await node_fs();
75+
await node_url();
5576
// this need to be detected only after we import node modules in onConfigLoaded
5677
const hasFetch = typeof (globalThis.fetch) === "function";
5778
if (ENVIRONMENT_IS_NODE) {
5879
const isFileUrl = url.startsWith("file://");
5980
if (!isFileUrl && hasFetch) {
6081
return globalThis.fetch(url, init || { credentials: "same-origin" });
6182
}
62-
if (!node_fs) {
63-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
64-
// @ts-ignore:
65-
node_url = await import(/*! webpackIgnore: true */"url");
66-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
67-
// @ts-ignore:
68-
node_fs = await import(/*! webpackIgnore: true */"fs");
69-
}
7083
if (isFileUrl) {
71-
url = node_url.fileURLToPath(url);
84+
url = _node_url.fileURLToPath(url);
7285
}
7386

74-
const arrayBuffer = await node_fs.promises.readFile(url);
87+
const arrayBuffer = await _node_fs.promises.readFile(url);
7588
return <Response><any>{
7689
ok: true,
7790
headers: {

src/native/corehost/browserhost/loader/run.ts

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
import { DotnetHostBuilder } from "../types";
5+
import { findResources, isNodeHosted, isShellHosted } from "./bootstrap";
46
import { Module, dotnetAssert } from "./cross-module";
57
import { exit } from "./exit";
68
import { createPromiseController } from "./promise-controller";
79

810
let CoreCLRInitialized = false;
911
const runMainPromiseController = createPromiseController<number>();
1012

11-
export function BrowserHost_InitializeCoreCLR():void {
13+
export function BrowserHost_InitializeCoreCLR(): void {
1214
dotnetAssert.check(!CoreCLRInitialized, "CoreCLR should be initialized just once");
1315
CoreCLRInitialized = true;
1416

@@ -22,14 +24,29 @@ export function BrowserHost_InitializeCoreCLR():void {
2224
}
2325
}
2426

25-
export function resolveRunMainPromise(exitCode:number):void {
27+
export function resolveRunMainPromise(exitCode: number): void {
2628
runMainPromiseController.resolve(exitCode);
2729
}
2830

29-
export function rejectRunMainPromise(reason:any):void {
31+
export function rejectRunMainPromise(reason: any): void {
3032
runMainPromiseController.reject(reason);
3133
}
3234

33-
export function getRunMainPromise():Promise<number> {
35+
export function getRunMainPromise(): Promise<number> {
3436
return runMainPromiseController.promise;
3537
}
38+
39+
// Auto-start when in NodeJS environment as a entry script
40+
export async function selfHostNodeJS(dotnet: DotnetHostBuilder): Promise<void> {
41+
try {
42+
if (isNodeHosted()) {
43+
await findResources(dotnet);
44+
await dotnet.run();
45+
} else if (isShellHosted()) {
46+
// because in V8 we can't probe directories to find assemblies
47+
throw new Error("Shell/V8 hosting is not supported");
48+
}
49+
} catch (err: any) {
50+
exit(1, err);
51+
}
52+
}

src/native/rollup.config.defines.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ if (process.env.ProductVersion === undefined) {
1818
export const configuration = process.env.Configuration !== "Release" && process.env.Configuration !== "RELEASE" ? "Debug" : "Release";
1919
export const productVersion = process.env.ProductVersion;
2020
export const isContinuousIntegrationBuild = process.env.ContinuousIntegrationBuild === "true" ? true : false;
21-
export const staticLibDestination = process.env.StaticLibDestination;
21+
export const staticLibDestination = process.env.StaticLibDestination || "../../artifacts/bin/browser-wasm.Debug/corehost"; // TODO "../../artifacts/bin/native/net10.0-browser-Debug-wasm/sharedFramework";
2222

2323
console.log(`Rollup configuration: Configuration=${configuration}, ProductVersion=${productVersion}, ContinuousIntegrationBuild=${isContinuousIntegrationBuild}`);
2424

0 commit comments

Comments
 (0)