Skip to content

Commit

Permalink
[browser] detect and assert engine features (#88846)
Browse files Browse the repository at this point in the history
  • Loading branch information
pavelsavara authored Jul 14, 2023
1 parent 24f5cbb commit 4a880ef
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 2 deletions.
14 changes: 13 additions & 1 deletion src/mono/wasm/runtime/http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,26 @@
// The .NET Foundation licenses this file to you under the MIT license.

import { wrap_as_cancelable_promise } from "./cancelable-promise";
import { Module, loaderHelpers } from "./globals";
import { ENVIRONMENT_IS_NODE, Module, loaderHelpers } from "./globals";
import { MemoryViewType, Span } from "./marshal";
import type { VoidPtr } from "./types/emscripten";


function verifyEnvironment() {
if (typeof globalThis.fetch !== "function" || typeof globalThis.AbortController !== "function") {
const message = ENVIRONMENT_IS_NODE
? "Please install `node-fetch` and `node-abort-controller` npm packages to enable HTTP client support."
: "This browser doesn't support fetch API. Please use a modern browser.";
throw new Error(message);
}
}

export function http_wasm_supports_streaming_response(): boolean {
return typeof Response !== "undefined" && "body" in Response.prototype && typeof ReadableStream === "function";
}

export function http_wasm_create_abort_controler(): AbortController {
verifyEnvironment();
return new AbortController();
}

Expand Down Expand Up @@ -38,6 +49,7 @@ export function http_wasm_fetch_bytes(url: string, header_names: string[], heade
}

export function http_wasm_fetch(url: string, header_names: string[], header_values: string[], option_names: string[], option_values: any[], abort_controller: AbortController, body: string | Uint8Array | null): Promise<ResponseExtension> {
verifyEnvironment();
mono_assert(url && typeof url === "string", "expected url string");
mono_assert(header_names && header_values && Array.isArray(header_names) && Array.isArray(header_values) && header_names.length === header_values.length, "expected headerNames and headerValues arrays");
mono_assert(option_names && option_values && Array.isArray(option_names) && Array.isArray(option_values) && option_names.length === option_values.length, "expected headerNames and headerValues arrays");
Expand Down
3 changes: 3 additions & 0 deletions src/mono/wasm/runtime/loader/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@

import type { DotnetHostBuilder } from "../types";
import { mono_exit } from "./exit";
import { verifyEnvironment } from "./polyfills";
import { HostBuilder, createEmscripten } from "./run";

// export external API
const dotnet: DotnetHostBuilder = new HostBuilder();
const exit = mono_exit;
const legacyEntrypoint = createEmscripten;

verifyEnvironment();

export { dotnet, exit };
export default legacyEntrypoint;
17 changes: 17 additions & 0 deletions src/mono/wasm/runtime/loader/polyfills.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

import MonoWasmThreads from "consts:monoWasmThreads";

import type { DotnetModuleInternal } from "../types/internal";
import { INTERNAL, ENVIRONMENT_IS_NODE, ENVIRONMENT_IS_SHELL, loaderHelpers, ENVIRONMENT_IS_WEB } from "./globals";
Expand All @@ -14,6 +18,19 @@ const URLPolyfill = class URL {
}
};

export function verifyEnvironment() {
mono_assert(ENVIRONMENT_IS_SHELL || typeof globalThis.URL === "function", "This browser/engine doesn't support URL API. Please use a modern version.");
mono_assert(typeof globalThis.BigInt64Array === "function", "This browser/engine doesn't support BigInt64Array API. Please use a modern version.");
if (MonoWasmThreads) {
mono_assert(!ENVIRONMENT_IS_SHELL && !ENVIRONMENT_IS_NODE, "This build of dotnet is multi-threaded, it doesn't support shell environments like V8 or NodeJS.");
mono_assert(globalThis.SharedArrayBuffer !== undefined, "SharedArrayBuffer is not enabled on this page. Please use a modern browser and set Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy http headers. See also https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer#security_requirements");
mono_assert(typeof globalThis.EventTarget === "function", "This browser/engine doesn't support EventTarget API. Please use a modern version.");
}

// TODO detect other (WASM) features that are required for the runtime
// See https://github.com/dotnet/runtime/issues/84574
}

export async function detect_features_and_polyfill(module: DotnetModuleInternal): Promise<void> {

const scriptUrlQuery =/* webpackIgnore: true */import.meta.url;
Expand Down
3 changes: 3 additions & 0 deletions src/mono/wasm/runtime/loader/worker.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

import { MonoConfig } from "../types";
import { MonoConfigInternal } from "../types/internal";
import { deep_merge_config, normalizeConfig } from "./config";
Expand Down
15 changes: 14 additions & 1 deletion src/mono/wasm/runtime/web-socket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import MonoWasmThreads from "consts:monoWasmThreads";

import { prevent_timer_throttling } from "./scheduling";
import { Queue } from "./queue";
import { createPromiseController } from "./globals";
import { ENVIRONMENT_IS_NODE, ENVIRONMENT_IS_SHELL, createPromiseController } from "./globals";
import { setI32, localHeapViewU8 } from "./memory";
import { VoidPtr } from "./types/emscripten";
import { PromiseController } from "./types/internal";
Expand All @@ -26,7 +26,20 @@ let mono_wasm_web_socket_close_warning = false;
const ws_send_buffer_blocking_threshold = 65536;
const emptyBuffer = new Uint8Array();

function verifyEnvironment() {
if (ENVIRONMENT_IS_SHELL) {
throw new Error("WebSockets are not supported in shell JS engine.");
}
if (typeof globalThis.WebSocket !== "function") {
const message = ENVIRONMENT_IS_NODE
? "Please install `ws` npm package to enable networking support."
: "This browser doesn't support WebSocket API. Please use a modern browser.";
throw new Error(message);
}
}

export function ws_wasm_create(uri: string, sub_protocols: string[] | null, receive_status_ptr: VoidPtr, onClosed: (code: number, reason: string) => void): WebSocketExtension {
verifyEnvironment();
mono_assert(uri && typeof uri === "string", () => `ERR12: Invalid uri ${typeof uri}`);

const ws = new globalThis.WebSocket(uri, sub_protocols || undefined) as WebSocketExtension;
Expand Down

0 comments on commit 4a880ef

Please sign in to comment.