Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[browser] Separate hybrid globalization JS code to es6 module #101543

Merged
merged 33 commits into from
May 17, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
0c17d0c
dotnet.hybrid.js module creation when MT is off
ilonatommy Apr 25, 2024
2f8cbcc
Improvement but not fix.
ilonatommy Apr 25, 2024
e6dcc49
More improvements, still failing.
ilonatommy Apr 25, 2024
aafd997
Importing module
ilonatommy Apr 26, 2024
27ea4c4
Flip condition - load HG with ST only.
ilonatommy Apr 26, 2024
192bef5
Remove globalization code from main module, create the globalization …
ilonatommy Apr 26, 2024
66c074d
Missing change.
ilonatommy Apr 26, 2024
825c6ae
Fix for `blazor.boot.config` ST/MT. Still errors in the runtime.
ilonatommy Apr 26, 2024
eb2c26d
Fix: `runtimeHelper` is not null if we cache it on module init.
ilonatommy May 7, 2024
8669727
Fix: `segmentationRules` throwing "Cannot convert undefined or null t…
ilonatommy May 7, 2024
07154e6
Change flag to HG.
ilonatommy May 7, 2024
40f292a
Merge branch 'main' into 98483-hg-modularization
ilonatommy May 7, 2024
08df581
Fix MT.
ilonatommy May 13, 2024
faea49d
Merge branch 'main' into 98483-hg-modularization
ilonatommy May 13, 2024
f577ac3
Cleanup.
ilonatommy May 13, 2024
6bcad7d
Remove duplicates.
ilonatommy May 13, 2024
759803a
Export functions used by hybrid globalization only when HG is on.
ilonatommy May 13, 2024
602c1f9
Do not try to call when methods are not initialized.
ilonatommy May 13, 2024
a6a36b6
Fix previous commit.
ilonatommy May 13, 2024
e6f81d7
`mono_wasm_get_locale_info` is used also in non-HG mode, add it to th…
ilonatommy May 13, 2024
ff3c1d4
Feedback - cleanup.
ilonatommy May 13, 2024
43f0fbf
Check WBT for presence of globalization module if HG is switched on.
ilonatommy May 13, 2024
b0bc1fe
Fix MT globalization tests - NativeName is fixed there.
ilonatommy May 14, 2024
be4ad97
Missing change to the prev commit.
ilonatommy May 14, 2024
f0b442d
Trying to fix WBT.
ilonatommy May 14, 2024
c91b076
Merge branch 'main' into 98483-hg-modularization
ilonatommy May 14, 2024
2881009
Semicolon should not be in the souce name.
ilonatommy May 14, 2024
64bb2ea
Fix.
ilonatommy May 14, 2024
586cc37
Fix hybrid change case.
ilonatommy May 14, 2024
4051775
Globalization module is not expected to change on relink.
ilonatommy May 14, 2024
265d39c
Fix blazor's assets + remove duplicated asset entry.
ilonatommy May 15, 2024
b1e7448
Merge remote-tracking branch 'origin/main' into 98483-hg-modularization
ilonatommy May 15, 2024
96ab2f1
Feedback
ilonatommy May 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/mono/browser/runtime/corebindings.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,9 @@ void bindings_initialize_internals (void)
mono_add_internal_call ("Interop/Runtime::AssemblyGetEntryPoint", mono_wasm_assembly_get_entry_point);
mono_add_internal_call ("Interop/Runtime::BindAssemblyExports", mono_wasm_bind_assembly_exports);
mono_add_internal_call ("Interop/Runtime::GetAssemblyExport", mono_wasm_get_assembly_export);
mono_add_internal_call ("System.ConsolePal::Clear", mono_wasm_console_clear);

// HybridGlobalization
mono_add_internal_call ("Interop/JsGlobalization::ChangeCaseInvariant", mono_wasm_change_case_invariant);
mono_add_internal_call ("Interop/JsGlobalization::ChangeCase", mono_wasm_change_case);
mono_add_internal_call ("Interop/JsGlobalization::CompareString", mono_wasm_compare_string);
Expand All @@ -113,7 +115,6 @@ void bindings_initialize_internals (void)
mono_add_internal_call ("Interop/JsGlobalization::GetCultureInfo", mono_wasm_get_culture_info);
mono_add_internal_call ("Interop/JsGlobalization::GetFirstDayOfWeek", mono_wasm_get_first_day_of_week);
mono_add_internal_call ("Interop/JsGlobalization::GetFirstWeekOfYear", mono_wasm_get_first_week_of_year);
mono_add_internal_call ("System.ConsolePal::Clear", mono_wasm_console_clear);
}

static MonoAssembly* _mono_wasm_assembly_load (char *assembly_name)
Expand Down
57 changes: 51 additions & 6 deletions src/mono/browser/runtime/exports-binding.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,6 @@ import { mono_wasm_diagnostic_server_on_runtime_server_init, mono_wasm_event_pip
import { mono_wasm_diagnostic_server_stream_signal_work_available } from "./diagnostics/server_pthread/stream-queue";
import { mono_log_warn, mono_wasm_console_clear, mono_wasm_trace_logger } from "./logging";
import { mono_wasm_profiler_leave, mono_wasm_profiler_enter } from "./profiler";
import { mono_wasm_change_case, mono_wasm_change_case_invariant } from "./hybrid-globalization/change-case";
import { mono_wasm_compare_string, mono_wasm_ends_with, mono_wasm_starts_with, mono_wasm_index_of } from "./hybrid-globalization/collations";
import { mono_wasm_get_calendar_info } from "./hybrid-globalization/calendar";

import { mono_wasm_get_culture_info } from "./hybrid-globalization/culture-info";
import { mono_wasm_get_locale_info, mono_wasm_get_first_day_of_week, mono_wasm_get_first_week_of_year } from "./hybrid-globalization/locales";
import { mono_wasm_browser_entropy } from "./crypto";
import { mono_wasm_cancel_promise } from "./cancelable-promise";

Expand All @@ -33,6 +27,8 @@ import {
} from "./pthreads";
import { mono_wasm_dump_threads } from "./pthreads/ui-thread";
import { mono_wasm_schedule_synchronization_context } from "./pthreads/shared";
import { Int32Ptr, VoidPtr } from "./types/emscripten";
import { runtimeHelpers } from "./globals";

// the JS methods would be visible to EMCC linker and become imports of the WASM module

Expand Down Expand Up @@ -101,6 +97,53 @@ export const mono_wasm_imports = [
mono_wasm_invoke_jsimport_ST,
mono_wasm_resolve_or_reject_promise,
mono_wasm_cancel_promise,
];

function mono_wasm_change_case_invariant (src: number, srcLength: number, dst: number, dstLength: number, toUpper: number) : VoidPtr {
return runtimeHelpers.mono_wasm_change_case_invariant(src, srcLength, dst, dstLength, toUpper);
}

function mono_wasm_change_case (culture: number, cultureLength: number, src: number, srcLength: number, dst: number, dstLength: number, toUpper: number) : VoidPtr {
return runtimeHelpers.mono_wasm_change_case(culture, cultureLength, src, srcLength, dst, dstLength, toUpper);
}

function mono_wasm_compare_string (culture: number, cultureLength: number, str1: number, str1Length: number, str2: number, str2Length: number, options: number, resultPtr: Int32Ptr) : VoidPtr {
return runtimeHelpers.mono_wasm_compare_string(culture, cultureLength, str1, str1Length, str2, str2Length, options, resultPtr);
}

function mono_wasm_starts_with (culture: number, cultureLength: number, str1: number, str1Length: number, str2: number, str2Length: number, options: number, resultPtr: Int32Ptr): VoidPtr {
return runtimeHelpers.mono_wasm_starts_with(culture, cultureLength, str1, str1Length, str2, str2Length, options, resultPtr);
}

function mono_wasm_ends_with (culture: number, cultureLength: number, str1: number, str1Length: number, str2: number, str2Length: number, options: number, resultPtr: Int32Ptr): VoidPtr {
return runtimeHelpers.mono_wasm_ends_with(culture, cultureLength, str1, str1Length, str2, str2Length, options, resultPtr);
}

function mono_wasm_index_of (culture: number, cultureLength: number, needlePtr: number, needleLength: number, srcPtr: number, srcLength: number, options: number, fromBeginning: number, resultPtr: Int32Ptr): VoidPtr {
return runtimeHelpers.mono_wasm_index_of(culture, cultureLength, needlePtr, needleLength, srcPtr, srcLength, options, fromBeginning, resultPtr);
}

function mono_wasm_get_calendar_info (culture: number, cultureLength: number, calendarId: number, dst: number, dstMaxLength: number, dstLength: Int32Ptr): VoidPtr {
return runtimeHelpers.mono_wasm_get_calendar_info(culture, cultureLength, calendarId, dst, dstMaxLength, dstLength);
}

function mono_wasm_get_culture_info (culture: number, cultureLength: number, dst: number, dstMaxLength: number, dstLength: Int32Ptr): VoidPtr {
return runtimeHelpers.mono_wasm_get_culture_info(culture, cultureLength, dst, dstMaxLength, dstLength);
}

function mono_wasm_get_locale_info (culture: number, cultureLength: number, locale: number, localeLength: number, dst: number, dstMaxLength: number, dstLength: Int32Ptr): VoidPtr {
return runtimeHelpers.mono_wasm_get_locale_info(culture, cultureLength, locale, localeLength, dst, dstMaxLength, dstLength);
}

function mono_wasm_get_first_day_of_week (culture: number, cultureLength: number, resultPtr: Int32Ptr): VoidPtr {
return runtimeHelpers.mono_wasm_get_first_day_of_week(culture, cultureLength, resultPtr);
}

function mono_wasm_get_first_week_of_year (culture: number, cultureLength: number, resultPtr: Int32Ptr): VoidPtr {
return runtimeHelpers.mono_wasm_get_first_week_of_year(culture, cultureLength, resultPtr);
}

export const mono_wasm_hybrid_globalization_imports = WasmEnableThreads ? [] : [ // ToDo: change it to rely on HybridGlobalization
mono_wasm_change_case_invariant,
mono_wasm_change_case,
mono_wasm_compare_string,
Expand All @@ -118,6 +161,8 @@ const wasmImports: Function[] = [
...mono_wasm_imports,
// threading exports, if threading is enabled
...mono_wasm_threads_imports,
// hybrid globalization exports, if HG is enabled (curently if MT is disabled)
...mono_wasm_hybrid_globalization_imports,
];

export function replace_linker_placeholders (imports: WebAssembly.Imports) {
Expand Down
10 changes: 10 additions & 0 deletions src/mono/browser/runtime/exports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import { forceDisposeProxies } from "./gc-handles";
import { mono_wasm_dump_threads } from "./pthreads";

import { threads_c_functions as tcwraps } from "./cwraps";
import { stringToUTF16, stringToUTF16Ptr, utf16ToString } from "./strings";
import { localHeapViewU16, setI32, setU16_local } from "./memory";

export let runtimeList: RuntimeList;

Expand All @@ -47,6 +49,14 @@ function initializeExports (globalObjects: GlobalObjects): RuntimeAPI {
rh.dumpThreads = mono_wasm_dump_threads;
rh.mono_wasm_print_thread_dump = () => tcwraps.mono_wasm_print_thread_dump();
}
// if HG is on:
rh.stringToUTF16 = stringToUTF16;
rh.stringToUTF16Ptr = stringToUTF16Ptr;
rh.utf16ToString = utf16ToString;
rh.localHeapViewU16 = localHeapViewU16;
rh.setU16_local = setU16_local;
rh.setI32 = setI32;

Object.assign(runtimeHelpers, rh);

const API = export_api();
Expand Down
11 changes: 5 additions & 6 deletions src/mono/browser/runtime/hybrid-globalization/calendar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@
// The .NET Foundation licenses this file to you under the MIT license.

/* eslint-disable no-inner-declarations */
import { stringToUTF16, stringToUTF16Ptr, utf16ToString } from "../strings";
import { VoidPtrNull } from "../types/internal";
import { runtimeHelpers } from "../globals";
import { Int32Ptr, VoidPtr } from "../types/emscripten";
import { INNER_SEPARATOR, OUTER_SEPARATOR, normalizeSpaces } from "./helpers";
import { setI32 } from "../memory";

const MONTH_CODE = "MMMM";
const YEAR_CODE = "yyyy";
Expand All @@ -15,7 +14,7 @@ const DAY_CODE = "d";
// this function joins all calendar info with OUTER_SEPARATOR into one string and returns it back to managed code
export function mono_wasm_get_calendar_info (culture: number, cultureLength: number, calendarId: number, dst: number, dstMaxLength: number, dstLength: Int32Ptr): VoidPtr {
try {
const cultureName = utf16ToString(<any>culture, <any>(culture + 2 * cultureLength));
const cultureName = runtimeHelpers.utf16ToString(<any>culture, <any>(culture + 2 * cultureLength));
const locale = cultureName ? cultureName : undefined;
const calendarInfo = {
EnglishName: "",
Expand Down Expand Up @@ -56,11 +55,11 @@ export function mono_wasm_get_calendar_info (culture: number, cultureLength: num
if (result.length > dstMaxLength) {
throw new Error(`Calendar info exceeds length of ${dstMaxLength}.`);
}
stringToUTF16(dst, dst + 2 * result.length, result);
setI32(dstLength, result.length);
runtimeHelpers.stringToUTF16(dst, dst + 2 * result.length, result);
runtimeHelpers.setI32(dstLength, result.length);
return VoidPtrNull;
} catch (ex: any) {
return stringToUTF16Ptr(ex.toString());
return runtimeHelpers.stringToUTF16Ptr(ex.toString());
}
}

Expand Down
33 changes: 16 additions & 17 deletions src/mono/browser/runtime/hybrid-globalization/change-case.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,24 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

import { utf16ToStringLoop, stringToUTF16, stringToUTF16Ptr, utf16ToString } from "../strings";
import { VoidPtrNull } from "../types/internal";
import { runtimeHelpers } from "../globals";
import { VoidPtr } from "../types/emscripten";
import { localHeapViewU16, setU16_local } from "../memory";
import { isSurrogate } from "./helpers";

export function mono_wasm_change_case_invariant (src: number, srcLength: number, dst: number, dstLength: number, toUpper: number): VoidPtr {
try {
const input = utf16ToStringLoop(src, src + 2 * srcLength);
const input = runtimeHelpers.utf16ToString(<any>src, <any>(src + 2 * srcLength));
const result = toUpper ? input.toUpperCase() : input.toLowerCase();
// Unicode defines some codepoints which expand into multiple codepoints,
// originally we do not support this expansion
if (result.length <= dstLength) {
stringToUTF16(dst, dst + 2 * dstLength, result);
runtimeHelpers.stringToUTF16(dst, dst + 2 * dstLength, result);
return VoidPtrNull;
}

// workaround to maintain the ICU-like behavior
const heapI16 = localHeapViewU16();
const heapI16 = runtimeHelpers.localHeapViewU16();
let jump = 1;
if (toUpper) {
for (let i = 0; i < input.length; i += jump) {
Expand All @@ -35,7 +34,7 @@ export function mono_wasm_change_case_invariant (src: number, srcLength: number,
jump = 1;
const upperChar = input[i].toUpperCase();
const appendedChar = upperChar.length > 1 ? input[i] : upperChar;
setU16_local(heapI16, dst + i * 2, appendedChar.charCodeAt(0));
runtimeHelpers.setU16_local(heapI16, dst + i * 2, appendedChar.charCodeAt(0));
}
}
} else {
Expand All @@ -51,30 +50,30 @@ export function mono_wasm_change_case_invariant (src: number, srcLength: number,
jump = 1;
const upperChar = input[i].toLowerCase();
const appendedChar = upperChar.length > 1 ? input[i] : upperChar;
setU16_local(heapI16, dst + i * 2, appendedChar.charCodeAt(0));
runtimeHelpers.setU16_local(heapI16, dst + i * 2, appendedChar.charCodeAt(0));
}
}
}
return VoidPtrNull;
} catch (ex: any) {
return stringToUTF16Ptr(ex.toString());
return runtimeHelpers.stringToUTF16Ptr(ex.toString());
}
}

export function mono_wasm_change_case (culture: number, cultureLength: number, src: number, srcLength: number, dst: number, dstLength: number, toUpper: number): VoidPtr {
try {
const cultureName = utf16ToString(<any>culture, <any>(culture + 2 * cultureLength));
const cultureName = runtimeHelpers.utf16ToString(<any>culture, <any>(culture + 2 * cultureLength));
if (!cultureName)
throw new Error("Cannot change case, the culture name is null.");
const input = utf16ToStringLoop(src, src + 2 * srcLength);
const input = runtimeHelpers.utf16ToString(<any>src, <any>(src + 2 * srcLength));
const result = toUpper ? input.toLocaleUpperCase(cultureName) : input.toLocaleLowerCase(cultureName);

if (result.length <= input.length) {
stringToUTF16(dst, dst + 2 * dstLength, result);
runtimeHelpers.stringToUTF16(dst, dst + 2 * dstLength, result);
return VoidPtrNull;
}
// workaround to maintain the ICU-like behavior
const heapI16 = localHeapViewU16();
const heapI16 = runtimeHelpers.localHeapViewU16();
let jump = 1;
if (toUpper) {
for (let i = 0; i < input.length; i += jump) {
Expand All @@ -90,7 +89,7 @@ export function mono_wasm_change_case (culture: number, cultureLength: number, s
jump = 1;
const upperChar = input[i].toLocaleUpperCase(cultureName);
const appendedChar = upperChar.length > 1 ? input[i] : upperChar;
setU16_local(heapI16, dst + i * 2, appendedChar.charCodeAt(0));
runtimeHelpers.setU16_local(heapI16, dst + i * 2, appendedChar.charCodeAt(0));
}
}
} else {
Expand All @@ -106,17 +105,17 @@ export function mono_wasm_change_case (culture: number, cultureLength: number, s
jump = 1;
const lowerChar = input[i].toLocaleLowerCase(cultureName);
const appendedChar = lowerChar.length > 1 ? input[i] : lowerChar;
setU16_local(heapI16, dst + i * 2, appendedChar.charCodeAt(0));
runtimeHelpers.setU16_local(heapI16, dst + i * 2, appendedChar.charCodeAt(0));
}
}
}
return VoidPtrNull;
} catch (ex: any) {
return stringToUTF16Ptr(ex.toString());
return runtimeHelpers.stringToUTF16Ptr(ex.toString());
}
}

function appendSurrogateToMemory (heapI16: Uint16Array, dst: number, surrogate: string, idx: number) {
setU16_local(heapI16, dst + idx * 2, surrogate.charCodeAt(0));
setU16_local(heapI16, dst + (idx + 1) * 2, surrogate.charCodeAt(1));
runtimeHelpers.setU16_local(heapI16, dst + idx * 2, surrogate.charCodeAt(0));
runtimeHelpers.setU16_local(heapI16, dst + (idx + 1) * 2, surrogate.charCodeAt(1));
}
Loading
Loading