9fa205
From 0028cc74dac4dd24b8599ade85cb49fdafa9f559 Mon Sep 17 00:00:00 2001
0ba478
From: Stephen Gallagher <sgallagh@redhat.com>
0ba478
Date: Fri, 6 Dec 2019 16:40:25 -0500
9fa205
Subject: [PATCH] build: auto-load ICU data from --with-icu-default-data-dir
0ba478
0ba478
When compiled with `--with-intl=small` and
0ba478
`--with-icu-default-data-dir=PATH`, Node.js will use PATH as a
0ba478
fallback location for the ICU data.
0ba478
0ba478
We will first perform an access check using fopen(PATH, 'r') to
0ba478
ensure that the file is readable. If it is, we'll set the
0ba478
icu_data_directory and proceed. There's a slight overhead for the
0ba478
fopen() check, but it should be barely measurable.
0ba478
0ba478
This will be useful for Linux distribution packagers who want to
0ba478
be able to ship a minimal node binary in a container image but
0ba478
also be able to add on the full i18n support where needed. With
0ba478
this patch, it becomes possible to ship the interpreter as
0ba478
/usr/bin/node in one package for the distribution and to ship the
0ba478
data files in another package (without a strict dependency
0ba478
between the two). This means that users of the distribution will
0ba478
not need to explicitly direct Node.js to locate the ICU data. It
0ba478
also means that in environments where full internationalization is
0ba478
not required, they do not need to carry the extra content (with
0ba478
the associated storage costs).
0ba478
0ba478
Refs: https://github.com/nodejs/node/issues/3460
0ba478
0ba478
Signed-off-by: Stephen Gallagher <sgallagh@redhat.com>
9fa205
Signed-off-by: rpm-build <rpm-build>
0ba478
---
0ba478
 configure.py |  9 +++++++++
0ba478
 node.gypi    |  7 +++++++
0ba478
 src/node.cc  | 20 ++++++++++++++++++++
0ba478
 3 files changed, 36 insertions(+)
0ba478
0ba478
diff --git a/configure.py b/configure.py
9fa205
index 89f7bf5..d611a88 100755
0ba478
--- a/configure.py
0ba478
+++ b/configure.py
0ba478
@@ -433,6 +433,14 @@ intl_optgroup.add_option('--with-icu-source',
0ba478
         'the icu4c source archive. '
0ba478
         'v%d.x or later recommended.' % icu_versions['minimum_icu'])
9fa205
 
0ba478
+intl_optgroup.add_option('--with-icu-default-data-dir',
0ba478
+    action='store',
0ba478
+    dest='with_icu_default_data_dir',
0ba478
+    help='Path to the icuXXdt{lb}.dat file. If unspecified, ICU data will '
0ba478
+         'only be read if the NODE_ICU_DATA environment variable or the '
0ba478
+         '--icu-data-dir runtime argument is used. This option has effect '
0ba478
+         'only when Node.js is built with --with-intl=small-icu.')
0ba478
+
0ba478
 parser.add_option('--with-ltcg',
0ba478
     action='store_true',
0ba478
     dest='with_ltcg',
9fa205
@@ -1359,6 +1367,7 @@ def configure_intl(o):
0ba478
     locs.add('root')  # must have root
0ba478
     o['variables']['icu_locales'] = string.join(locs,',')
0ba478
     # We will check a bit later if we can use the canned deps/icu-small
0ba478
+    o['variables']['icu_default_data'] = options.with_icu_default_data_dir or ''
0ba478
   elif with_intl == 'full-icu':
0ba478
     # full ICU
0ba478
     o['variables']['v8_enable_i18n_support'] = 1
0ba478
diff --git a/node.gypi b/node.gypi
9fa205
index 466a174..65b97d6 100644
0ba478
--- a/node.gypi
0ba478
+++ b/node.gypi
0ba478
@@ -113,6 +113,13 @@
0ba478
       'conditions': [
0ba478
         [ 'icu_small=="true"', {
0ba478
           'defines': [ 'NODE_HAVE_SMALL_ICU=1' ],
0ba478
+          'conditions': [
0ba478
+            [ 'icu_default_data!=""', {
0ba478
+              'defines': [
0ba478
+                'NODE_ICU_DEFAULT_DATA_DIR="<(icu_default_data)"',
0ba478
+              ],
0ba478
+            }],
0ba478
+          ],
0ba478
       }]],
0ba478
     }],
0ba478
     [ 'node_use_bundled_v8=="true" and \
0ba478
diff --git a/src/node.cc b/src/node.cc
9fa205
index 7c01187..c9840e3 100644
0ba478
--- a/src/node.cc
0ba478
+++ b/src/node.cc
0ba478
@@ -92,6 +92,7 @@
9fa205
 
0ba478
 #if defined(NODE_HAVE_I18N_SUPPORT)
0ba478
 #include <unicode/uvernum.h>
0ba478
+#include <unicode/utypes.h>
0ba478
 #endif
9fa205
 
0ba478
 #if defined(LEAK_SANITIZER)
0ba478
@@ -2643,6 +2644,25 @@ void Init(std::vector<std::string>* argv,
0ba478
   // If the parameter isn't given, use the env variable.
0ba478
   if (per_process_opts->icu_data_dir.empty())
0ba478
     SafeGetenv("NODE_ICU_DATA", &per_process_opts->icu_data_dir);
0ba478
+
0ba478
+#ifdef NODE_ICU_DEFAULT_DATA_DIR
0ba478
+  // If neither the CLI option nor the environment variable was specified,
0ba478
+  // fall back to the configured default
0ba478
+  if (per_process_opts->icu_data_dir.empty()) {
0ba478
+    // Check whether the NODE_ICU_DEFAULT_DATA_DIR contains the right data
0ba478
+    // file and can be read.
0ba478
+    static const char full_path[] =
0ba478
+        NODE_ICU_DEFAULT_DATA_DIR "/" U_ICUDATA_NAME ".dat";
0ba478
+
0ba478
+    FILE* f = fopen(full_path, "rb");
0ba478
+
0ba478
+    if (f != nullptr) {
0ba478
+      fclose(f);
0ba478
+      per_process_opts->icu_data_dir = NODE_ICU_DEFAULT_DATA_DIR;
0ba478
+    }
0ba478
+  }
0ba478
+#endif  // NODE_ICU_DEFAULT_DATA_DIR
0ba478
+
0ba478
   // Initialize ICU.
0ba478
   // If icu_data_dir is empty here, it will load the 'minimal' data.
0ba478
   if (!i18n::InitializeICUDirectory(per_process_opts->icu_data_dir)) {
9fa205
-- 
9fa205
2.26.2
0ba478