Sfoglia il codice sorgente

Initialize ICU when initializing Intl in order to catch data file issues early

If ICU can't load the data file, it will report back U_FILE_ACCESS_ERROR or U_MISSING_RESOURCE_ERROR on calls to ICU APIs that require the data file. When using Windows ICU, the only reason we wouldn't be able to load the data file is if we are out of memory (with bundled ICU, the data should be statically or dynamically linked, and this shouldn't be an issue). As such, to reduce noise from ICU_ASSERT, we can load the data file as soon as we initialize Intl using u_init, and if that fails with a known error code, we can treat it as OOM.
Jack Horton (CHAKRA) 8 anni fa
parent
commit
e1ae09d736
1 ha cambiato i file con 18 aggiunte e 0 eliminazioni
  1. 18 0
      lib/Runtime/Library/IntlEngineInterfaceExtensionObject.cpp

+ 18 - 0
lib/Runtime/Library/IntlEngineInterfaceExtensionObject.cpp

@@ -454,6 +454,24 @@ namespace Js
             {
                 library->AddMember(library->GetIntlObject(), PropertyIds::platform, this->intlNativeInterfaces);
             }
+
+#ifdef INTL_ICU
+            // when using ICU, we need to call u_init to ensure that ICU is functioning properly before allowing Intl to continue.
+            // u_init will cause the data file to be loaded, and if we don't have enough memory to do so, we can throw OutOfMemory here.
+            // This is to protect against spurious U_MISSING_RESOURCE_ERRORs and U_FILE_ACCESS_ERRORs coming from early-lifecycle
+            // functions that require ICU data.
+            // See OS#16897150, OS#16896933, and others relating to bad statuses returned by GetLocaleData and IsLocaleAvailable
+            UErrorCode status = U_ZERO_ERROR;
+            u_init(&status);
+            if (status == U_MEMORY_ALLOCATION_ERROR || status == U_FILE_ACCESS_ERROR || status == U_MISSING_RESOURCE_ERROR)
+            {
+                // Trace that this happens in case there are build system changes that actually cause the data file to be not found
+                INTL_TRACE("Could not initialize ICU - u_init returned status %S", u_errorName(status));
+                Throw::OutOfMemory();
+            }
+
+            AssertOrFailFastMsg(U_SUCCESS(status), "u_init returned non-OOM failure");
+#endif
         }
         wasInitialized = true;
     }