Repository: dotnet/runtime
File: src/native/libs/Common/JavaScript/loader/bootstrap.ts (TypeScript)

Code before:
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

import { exceptions, simd } from "wasm-feature-detect";

import { ENVIRONMENT_IS_NODE, ENVIRONMENT_IS_SHELL, globalThisAny } from "./per-module";
import { dotnetAssert } from "./cross-module";

const scriptUrlQuery = /*! webpackIgnore: true */import.meta.url;
const queryIndex = scriptUrlQuery.indexOf("?");
const modulesUniqueQuery = queryIndex > 0 ? scriptUrlQuery.substring(queryIndex) : "";
const scriptUrl = normalizeFileUrl(scriptUrlQuery);
const scriptDirectory = normalizeDirectoryUrl(scriptUrl);

export async function validateWasmFeatures(): Promise<void> {
    dotnetAssert.check(await exceptions(), "This browser/engine doesn't support WASM exception handling. Please use a modern version. See also https://learn.microsoft.com/en-us/aspnet/core/blazor/supported-platforms");
    dotnetAssert.check(await simd(), "This browser/engine doesn't support WASM SIMD. Please use a modern version. See also https://learn.microsoft.com/en-us/aspnet/core/blazor/supported-platforms");
    if (ENVIRONMENT_IS_NODE) {
        const nodeMajorVersion = parseInt(globalThisAny.process.versions.node.split(".")[0], 10);
        dotnetAssert.check(nodeMajorVersion >= 18, `Node.js version ${globalThisAny.process.versions.node} is not supported. Please use Node.js 18 or later. See also https://learn.microsoft.com/en-us/aspnet/core/blazor/supported-platforms`);
    } else if (ENVIRONMENT_IS_SHELL) {
        if (typeof globalThisAny.version === "function" && globalThisAny.d8) {
            const v8v = globalThisAny.version();
            const v8MajorVersion = parseInt(v8v.split(".")[0], 10);
            dotnetAssert.check(v8MajorVersion >= 14, "This V8 shell is too old. Please use a modern version. See also https://learn.microsoft.com/en-us/aspnet/core/blazor/supported-platforms");
        }
    }
}

export function locateFile(path: string, isModule = false): string {
    let res;
    if (isPathAbsolute(path)) {
        res = path;
    } else if (globalThis.URL) {
        res = new globalThis.URL(path, scriptDirectory).href;
    } else {
        res = scriptDirectory + path;
    }

    if (isModule) {
        res += modulesUniqueQuery;
    }

    return res;
}

Review comment (suggestion):
```suggestion
        dotnetAssert.check(nodeMajorVersion >= 18, `Node.js version ${globalThisAny.process.versions.node} is not supported. Please use Node.js 18 or later.`);
```

Code after:
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

import { exceptions, simd } from "wasm-feature-detect";

import { ENVIRONMENT_IS_NODE, ENVIRONMENT_IS_SHELL, globalThisAny } from "./per-module";
import { dotnetAssert } from "./cross-module";

const scriptUrlQuery = /*! webpackIgnore: true */import.meta.url;
const queryIndex = scriptUrlQuery.indexOf("?");
const modulesUniqueQuery = queryIndex > 0 ? scriptUrlQuery.substring(queryIndex) : "";
const scriptUrl = normalizeFileUrl(scriptUrlQuery);
const scriptDirectory = normalizeDirectoryUrl(scriptUrl);

export async function validateWasmFeatures(): Promise<void> {
    dotnetAssert.check(await exceptions(), "This browser/engine doesn't support WASM exception handling. Please use a modern version. See also https://learn.microsoft.com/aspnet/core/blazor/supported-platforms");
    dotnetAssert.check(await simd(), "This browser/engine doesn't support WASM SIMD. Please use a modern version. See also https://learn.microsoft.com/aspnet/core/blazor/supported-platforms");
    if (ENVIRONMENT_IS_NODE) {
        const nodeMajorVersion = parseInt(globalThisAny.process.versions.node.split(".")[0], 10);
        dotnetAssert.check(nodeMajorVersion >= 18, `Node.js version ${globalThisAny.process.versions.node} is not supported. Please use Node.js 18 or later.`);
    } else if (ENVIRONMENT_IS_SHELL) {
        if (typeof globalThisAny.version === "function" && globalThisAny.d8) {
            const v8v = globalThisAny.version();
            const v8MajorVersion = parseInt(v8v.split(".")[0], 10);
            dotnetAssert.check(v8MajorVersion >= 14, "This V8 shell is too old. Please use a modern version.");
        }
    }
}

export function locateFile(path: string, isModule = false): string {
    let res;
    if (isPathAbsolute(path)) {
        res = path;
    } else if (globalThis.URL) {
        res = new globalThis.URL(path, scriptDirectory).href;
    } else {
        res = scriptDirectory + path;
    }

    if (isModule) {
        res += modulesUniqueQuery;
    }

    return res;
}