Support ICU (#603)

Co-authored-by: Kunihiro Ishiguro <kunihiro@zebra.dev>
This commit is contained in:
Ryan Dahl 2021-02-09 09:17:02 -05:00 committed by GitHub
parent c22b0d3e38
commit d60489c395
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 107 additions and 1 deletions

3
.gitmodules vendored
View File

@ -22,3 +22,6 @@
[submodule "third_party/zlib"]
path = third_party/zlib
url = https://chromium.googlesource.com/chromium/src/third_party/zlib.git
[submodule "third_party/icu"]
path = third_party/icu
url = https://chromium.googlesource.com/chromium/deps/icu.git

1
.gn
View File

@ -28,7 +28,6 @@ default_args = {
# https://cs.chromium.org/chromium/src/docs/ccache_mac.md
clang_use_chrome_plugins = false
v8_enable_i18n_support = false
v8_monolithic = false
v8_use_external_startup_data = false
v8_use_snapshot = true

46
src/icu.rs Normal file
View File

@ -0,0 +1,46 @@
extern "C" {
fn udata_setCommonData_68(this: *const u8, error_code: *mut i32);
}
/// This function bypasses the normal ICU data loading process and allows you to force ICU's system
/// data to come out of a user-specified area in memory.
///
/// ICU data must be at least 8-aligned, and should be 16-aligned. See
/// https://unicode-org.github.io/icu/userguide/icudata
///
/// The format of this data is that of the icu common data file, as is generated by the pkgdata
/// tool with mode=common or mode=dll. You can read in a whole common mode file and pass the
/// address to the start of the data, or (with the appropriate link options) pass in the pointer to
/// the data that has been loaded from a dll by the operating system, as shown in this code:
///
/// extern const char U_IMPORT U_ICUDATA_ENTRY_POINT [];
/// // U_ICUDATA_ENTRY_POINT is same as entry point specified to pkgdata tool
/// UErrorCode status = U_ZERO_ERROR;
///
/// udata_setCommonData(&U_ICUDATA_ENTRY_POINT, &status);
///
/// It is important that the declaration be as above. The entry point must not be declared as an
/// extern void*.
///
/// Starting with ICU 4.4, it is possible to set several data packages, one per call to this
/// function. udata_open() will look for data in the multiple data packages in the order in which
/// they were set. The position of the linked-in or default-name ICU .data package in the search
/// list depends on when the first data item is loaded that is not contained in the already
/// explicitly set packages. If data was loaded implicitly before the first call to this function
/// (for example, via opening a converter, constructing a UnicodeString from default-codepage data,
/// using formatting or collation APIs, etc.), then the default data will be first in the list.
///
/// This function has no effect on application (non ICU) data. See udata_setAppData() for similar
/// functionality for application data.
// TODO(ry) Map error code to something useful.
pub fn set_common_data(data: &'static [u8]) -> Result<(), i32> {
let mut error_code = 0i32;
unsafe {
udata_setCommonData_68(data.as_ptr(), &mut error_code);
}
if error_code == 0 {
Ok(())
} else {
Err(error_code)
}
}

View File

@ -45,6 +45,7 @@ mod external_references;
mod fixed_array;
mod function;
mod handle;
pub mod icu;
mod isolate;
mod isolate_create_params;
mod module;

View File

@ -4715,3 +4715,59 @@ fn prepare_stack_trace_callback() {
v8::Integer::new(scope, 42).into()
}
}
const ICU_DATA: &[u8; 10413584] =
include_bytes!("../third_party/icu/common/icudtl.dat");
#[test]
fn icu_date() {
assert!(v8::icu::set_common_data(ICU_DATA).is_ok());
let _setup_guard = setup();
let isolate = &mut v8::Isolate::new(Default::default());
{
let scope = &mut v8::HandleScope::new(isolate);
let context = v8::Context::new(scope);
let scope = &mut v8::ContextScope::new(scope, context);
let source = r#"
(new Date(Date.UTC(2020, 5, 26, 7, 0, 0))).toLocaleString("de-DE", {
weekday: "long",
year: "numeric",
month: "long",
day: "numeric",
});
"#;
let value = eval(scope, source).unwrap();
let date_de_val = v8::String::new(scope, "Freitag, 26. Juni 2020").unwrap();
assert!(value.is_string());
assert!(value.strict_equals(date_de_val.into()));
}
}
#[test]
fn icu_set_common_data_fail() {
const BAD_DATA: &[u8; 3] = &[1, 2, 3];
assert!(v8::icu::set_common_data(BAD_DATA).is_err());
}
#[test]
fn icu_format() {
assert!(v8::icu::set_common_data(ICU_DATA).is_ok());
let _setup_guard = setup();
let isolate = &mut v8::Isolate::new(Default::default());
{
let scope = &mut v8::HandleScope::new(isolate);
let context = v8::Context::new(scope);
let scope = &mut v8::ContextScope::new(scope, context);
let source = r#"
new Intl.NumberFormat("ja-JP", { style: "currency", currency: "JPY" }).format(
1230000,
);
"#;
let value = eval(scope, source).unwrap();
let currency_jpy_val = v8::String::new(scope, "¥1,230,000").unwrap();
assert!(value.is_string());
assert!(value.strict_equals(currency_jpy_val.into()));
}
}

1
third_party/icu vendored Submodule

@ -0,0 +1 @@
Subproject commit f4147b227f174e03f273053bb49fde33426d05bc