diff --git a/src/coreclr/hosts/corerun/corerun.cpp b/src/coreclr/hosts/corerun/corerun.cpp index a5ce53aedd8b44..d6032091a94adc 100644 --- a/src/coreclr/hosts/corerun/corerun.cpp +++ b/src/coreclr/hosts/corerun/corerun.cpp @@ -286,6 +286,10 @@ size_t HOST_CONTRACT_CALLTYPE get_runtime_property( static char* s_core_libs_path = nullptr; static char* s_core_root_path = nullptr; +#ifdef TARGET_BROWSER +extern "C" bool BrowserHost_ExternalAssemblyProbe(const char* pathPtr, /*out*/ void **outDataStartPtr, /*out*/ int64_t* outSize); +#endif // TARGET_BROWSER + static bool HOST_CONTRACT_CALLTYPE get_native_code_data( const host_runtime_contract_native_code_context* context, host_runtime_contract_native_code_data* data) @@ -343,6 +347,11 @@ static bool HOST_CONTRACT_CALLTYPE external_assembly_probe( void** data_start, int64_t* size) { +#ifdef TARGET_BROWSER + if (BrowserHost_ExternalAssemblyProbe(path, data_start, size)) + return true; +#endif // TARGET_BROWSER + // Get just the file name const char* name = path; const char* pos = strrchr(name, '/'); @@ -424,6 +433,9 @@ static int run(const configuration& config) string_t tpa_list; string_t app_assemblies_env = pal::getenv(envvar::appAssemblies); bool use_external_assembly_probe = false; +#ifdef TARGET_BROWSER + use_external_assembly_probe = true; +#endif // TARGET_BROWSER if (app_assemblies_env.empty() || app_assemblies_env == W("PROPERTY")) { // Use the TRUSTED_PLATFORM_ASSEMBLIES property to pass the app assemblies to the runtime. diff --git a/src/coreclr/hosts/corerun/wasm/libCorerun.js b/src/coreclr/hosts/corerun/wasm/libCorerun.js index 122ed7e217028d..31d051f8b75cf0 100644 --- a/src/coreclr/hosts/corerun/wasm/libCorerun.js +++ b/src/coreclr/hosts/corerun/wasm/libCorerun.js @@ -8,7 +8,7 @@ function libCoreRunFactory() { "$ENV", "$FS", "corerun_shutdown", - "BrowserHost_ShutdownDotnet", + "$UTF8ToString" ]; if (LibraryManager.library.$NODEFS) { commonDeps.push("$NODEFS"); @@ -35,6 +35,62 @@ function libCoreRunFactory() { $CORERUN__postset: "CORERUN.selfInitialize()", $CORERUN__deps: commonDeps, BrowserHost_ShutdownDotnet: (exitCode) => _corerun_shutdown(exitCode), + BrowserHost_ExternalAssemblyProbe: (pathPtr, outDataStartPtr, outSize) => { + const path = UTF8ToString(pathPtr); + let wasmPath; + if (path.endsWith('.dll')) { + wasmPath = path.slice(0, -4) + '.wasm'; + } else if (path.endsWith('.wasm')) { + wasmPath = path; + } else { + return false; + } + + let wasmBytes; + try { + wasmBytes = FS.readFile(wasmPath); + } catch (e) { + return false; + } + + // Synchronously instantiate the webcil WebAssembly module + const wasmModule = new WebAssembly.Module(wasmBytes); + const wasmInstance = new WebAssembly.Instance(wasmModule, { + webcil: { memory: wasmMemory } + }); + + const webcilVersion = wasmInstance.exports.webcilVersion.value; + if (webcilVersion !== 0) { + throw new Error(`Unsupported Webcil version: ${webcilVersion}`); + } + + const sp = stackSave(); + try { + const sizePtr = stackAlloc(4); + wasmInstance.exports.getWebcilSize(sizePtr); + const payloadSize = HEAPU32[sizePtr >>> 2]; + if (payloadSize === 0) { + throw new Error("Webcil payload size is 0"); + } + + const ptrPtr = stackAlloc(4); + if (_posix_memalign(ptrPtr, 16, payloadSize)) { + throw new Error("posix_memalign failed for Webcil payload"); + } + const payloadPtr = HEAPU32[ptrPtr >>> 2]; + + wasmInstance.exports.getWebcilPayload(payloadPtr, payloadSize); + + // Write out parameters: void** data_start, int64_t* size + HEAPU32[outDataStartPtr >>> 2] = payloadPtr; + HEAPU32[outSize >>> 2] = payloadSize; + HEAPU32[(outSize + 4) >>> 2] = 0; + + return true; + } finally { + stackRestore(sp); + } + } }; const patchNODERAWFS = { cwd: () => {