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

[wasm] Throw exception if culture data does not exist in icu #47301

Merged
merged 27 commits into from
Mar 10, 2021

Conversation

tqiu8
Copy link
Contributor

@tqiu8 tqiu8 commented Jan 21, 2021

Fix #47068
Fix #46327

Throw exception if culture data doesn't exist. Currently defaults to en-us.

@ghost
Copy link

ghost commented Jan 21, 2021

Tagging subscribers to this area: @tarekgh, @safern, @krwq
See info in area-owners.md if you want to be subscribed.

Issue Details

Fix #47068
Fix #46327

Throw exception if culture data doesn't exist. Currently defaults to en-us.

Author: tqiu8
Assignees: -
Labels:

area-System.Globalization

Milestone: -

@tarekgh tarekgh added the NO-MERGE The PR is not ready for merge yet (see discussion for detailed reasons) label Jan 21, 2021
@tqiu8 tqiu8 marked this pull request as draft January 22, 2021 18:38
Add PredefinedOnly GlobalizationMode
Modified tests if Culture Data not found
@@ -11,6 +11,8 @@ internal static partial class GlobalizationMode

internal static bool UseNls => false;

internal static bool PredefinedOnly { get; } = GetSwitchValue("System.Globalization.PredefinedOnly", "DOTNET_SYSTEM_GLOBALIZATION_PREDEFINED_ONLY");
Copy link
Member

@tarekgh tarekgh Jan 22, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PredefinedOnly [](start = 29, length = 14)

are you adding this for Linux only? looks the calling site will call it even running on Windows. maybe you need to move this to the file GlobalizationMode.cs?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is for Browser only.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why we need to restrict this to the browser only? We may enable this flag globally if we need to. Note the calling site of this property is called from shared code which runs with ICU and Nls. Give me a few minutes and I can send you what I propose.

Also, does the browser always runs with Icu?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess I just assumed only Browser would need this use case, but I can definitely move to GlobalizationMode.cs. And yes, the browser always runs with icu.

Copy link
Member

@tarekgh tarekgh Jan 22, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest to move the checks

if (CultureData.GetLocaleInfoExInt(name, Interop.Kernel32.LOCALE_ICONSTRUCTEDLOCALE) == 1)

and
if (!Interop.Globalization.IsPredefinedLocale(name))

to its own methods, something like

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static IcuIsEnsurePredefinedLocaleName(string name) // may put this in CultureData.Icu.cs
{
    Debug.Assert(!GlobalizationMode.UseNls);

    if (!Interop.Globalization.IsPredefinedLocale(name))
    {
        throw new CultureNotFoundException(nameof(name), SR.Format(SR.Argument_InvalidPredefinedCultureName, name));
    }
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static NlsIsEnsurePredefinedLocaleName(string name) // may put this in CultureData.Nls.cs
{
       Debug.Assert(GlobalizationMode.UseNls);

       if (CultureData.GetLocaleInfoExInt(name, Interop.Kernel32.LOCALE_ICONSTRUCTEDLOCALE) == 1)
       {
           throw new CultureNotFoundException(nameof(name), SR.Format(SR.Argument_InvalidPredefinedCultureName, name));
       }
}

Then replace the code here with

 if (GlobalizationMode.PredefinedOnly)
{
    if (GlobalizationMode.UseNls)
    {  
        NlsIsEnsurePredefinedLocaleName(cultureName);
    }
    else
    {  
        IcuIsEnsurePredefinedLocaleName(cultureName);
    }
}

Last, replace the checks in the links I mentioned above with the new methods calls. and move the code in GlobalizationMode.Unix.cs to GlobalizationMode.cs.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok yes that makes sense.

@tqiu8 tqiu8 marked this pull request as ready for review January 22, 2021 22:33
@@ -1904,6 +1904,9 @@ var MonoSupportLib = {

if (invariantMode)
this.mono_wasm_setenv ("DOTNET_SYSTEM_GLOBALIZATION_INVARIANT", "1");

// Set globalization mode to PredefinedOnly
this.mono_wasm_setenv ("DOTNET_SYSTEM_GLOBALIZATION_PREDEFINED_ONLY", "1");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is it env variable if it's always set?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just leaving the option open if we don't want it always set.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This won't be easy to change and it'll cost us on size. I think we should just compile the setting in

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We want it always set for wasm but I'm not sure if other OS want this option by default. @tarekgh

Copy link
Member

@tarekgh tarekgh Jan 25, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

outside WASM, we shouldn't turn this option on by default. Whoever need it would need to opt-in to get it.

Copy link
Member

@safern safern Jan 29, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could do this by setting a default value for the flag and making that default value be true for wasm based on an OS check when you are setting the PredefinedCulturesOnly flag. Or, just if def the code for WASM to always be ON.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is a place where we do something similar for WASM:

So we could do something like:

GetSwitchValue("System.Globalization.PredefinedCulturesOnly", "DOTNET_SYSTEM_GLOBALIZATION_PREDEFINED_CULTURES_ONLY") || OperatingSystem.IsBrowser()

@tarekgh
Copy link
Member

tarekgh commented Jan 22, 2021

CC @safern

@tarekgh
Copy link
Member

tarekgh commented Jan 22, 2021

Could you please replace the checks in

if (CultureData.GetLocaleInfoExInt(name, Interop.Kernel32.LOCALE_ICONSTRUCTEDLOCALE) == 1)

and
if (!Interop.Globalization.IsPredefinedLocale(name))

with the new introduced method calls?

thank you!

@tarekgh
Copy link
Member

tarekgh commented Jan 22, 2021

One last ask, could you please add a new test (not specific to the browser) to test the new environment variable? here is some test example which doing similar idea (testing setting environment variable).

Modify Globalization tests to catch unsupported locales
Change var names
@tqiu8
Copy link
Contributor Author

tqiu8 commented Jan 25, 2021

You need to do this test with RemoteExecutor as I pointed before in my comment #47301 (comment). Otherwise this test can easily fail and also will cause other problems for other tests running after it.

I don't think RemoteExcutor or System.Diagnostics.Process are supported on wasm right now. I'm going to store the current env var and reset it back to that after the test?

@tarekgh
Copy link
Member

tarekgh commented Jan 25, 2021

I don't think RemoteExcutor or System.Diagnostics.Process are supported on wasm right now. I'm going to store the current env var and reset it back to that after the test?

Yes, just exclude the added test from running on WASM. just mark the test with the attribute [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]

@tqiu8 tqiu8 requested review from tarekgh and lewing March 3, 2021 16:58
@tarekgh tarekgh removed the NO-MERGE The PR is not ready for merge yet (see discussion for detailed reasons) label Mar 3, 2021
Copy link
Member

@tarekgh tarekgh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tqiu8 I have added one more comment I hope you address it.
Also, please track documenting the new environment variable too. Thanks!

@tqiu8
Copy link
Contributor Author

tqiu8 commented Mar 3, 2021

@tqiu8 I have added one more comment I hope you address it.
Also, please track documenting the new environment variable too. Thanks!

Thank you so much for your feedback!

@lewing
Copy link
Member

lewing commented Mar 5, 2021

This is looking good but the failures look like they might be related.

@tqiu8 tqiu8 merged commit 128c757 into dotnet:main Mar 10, 2021
radical added a commit to radical/runtime that referenced this pull request Mar 12, 2021
@ghost ghost locked as resolved and limited conversation to collaborators Apr 9, 2021
@karelz karelz added this to the 6.0.0 milestone May 20, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
7 participants