diff --git a/common.gypi b/common.gypi index 953a1448d4baa5..5e1d6d8b695f2f 100644 --- a/common.gypi +++ b/common.gypi @@ -38,7 +38,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.17', + 'v8_embedder_string': '-node.18', ##### V8 defaults for Node.js ##### diff --git a/configure.py b/configure.py index 9ec5b2fc4694c6..f763e44161a05e 100755 --- a/configure.py +++ b/configure.py @@ -1156,6 +1156,11 @@ default=None, help='Enable the built-in snapshot compression in V8.') +parser.add_argument('--v8-disable-temporal-support', + action='store_true', + dest='v8_disable_temporal_support', + default=None, + help='Disable Temporal support in V8.') parser.add_argument('--v8-enable-temporal-support', action='store_true', @@ -1450,11 +1455,7 @@ def get_cargo_version(cargo): stdin=subprocess.PIPE, stderr=subprocess.PIPE, stdout=subprocess.PIPE) except OSError: - error('''No acceptable cargo found! - - Please make sure you have cargo installed on your system and/or - consider adjusting the CARGO environment variable if you have installed - it in a non-standard prefix.''') + return '0.0' with proc: cargo_ret = to_utf8(proc.communicate()[0]) @@ -1473,11 +1474,7 @@ def get_rustc_version(rustc): stdin=subprocess.PIPE, stderr=subprocess.PIPE, stdout=subprocess.PIPE) except OSError: - error('''No acceptable rustc compiler found! - - Please make sure you have a rust compiler installed on your system and/or - consider adjusting the RUSTC environment variable if you have installed - it in a non-standard prefix.''') + return '0.0' with proc: rustc_ret = to_utf8(proc.communicate()[0]) @@ -1538,23 +1535,51 @@ def check_compiler(o): o['variables']['llvm_version'] = get_llvm_version(CC) if is_clang else '0.0' # cargo and rustc are needed for Temporal. - if options.v8_enable_temporal_support and not options.shared_temporal_capi: + if not options.v8_disable_temporal_support or not options.shared_temporal_capi: # Minimum cargo and rustc versions should match values in BUILDING.md. min_cargo_ver_tuple = (1, 82) min_rustc_ver_tuple = (1, 82) cargo = os.environ.get('CARGO', 'cargo') cargo_ver = get_cargo_version(cargo) print_verbose(f'Detected cargo (CARGO={cargo}): {cargo_ver}') - cargo_ver_tuple = tuple(map(int, cargo_ver.split('.'))) - if cargo_ver_tuple < min_cargo_ver_tuple: - warn(f'cargo {cargo_ver} too old, need cargo {".".join(map(str, min_cargo_ver_tuple))}') + if cargo_ver == '0.0': + # Error if --v8-enable-temporal-support is explicitly set, + # otherwise disable support for Temporal. + if options.v8_enable_temporal_support: + error('''No acceptable cargo found! + + Enabling Temporal support requires cargo. + Please make sure you have cargo installed on your system and/or + consider adjusting the CARGO environment variable if you have installed + it in a non-standard prefix.''') + else: + warn('cargo not found! Support for Temporal will be disabled.') + options.v8_disable_temporal_support = True + else: + cargo_ver_tuple = tuple(map(int, cargo_ver.split('.'))) + if cargo_ver_tuple < min_cargo_ver_tuple: + warn(f'cargo {cargo_ver} too old, need cargo {".".join(map(str, min_cargo_ver_tuple))}') # cargo supports RUSTC environment variable to override "rustc". rustc = os.environ.get('RUSTC', 'rustc') rustc_ver = get_rustc_version(rustc) - print_verbose(f'Detected rustc (RUSTC={rustc}): {rustc_ver}') - rust_ver_tuple = tuple(map(int, rustc_ver.split('.'))) - if rust_ver_tuple < min_rustc_ver_tuple: - warn(f'rustc {rustc_ver} too old, need rustc {".".join(map(str, min_rustc_ver_tuple))}') + if rustc_ver == '0.0': + # Error if --v8-enable-temporal-support is explicitly set, + # otherwise disable support for Temporal. + if options.v8_enable_temporal_support: + error('''No acceptable rustc compiler found! + + Enabling Temporal support requires a Rust toolchain. + Please make sure you have a Rust compiler installed on your system and/or + consider adjusting the RUSTC environment variable if you have installed + it in a non-standard prefix.''') + else: + warn(f'{rustc} not found! Support for Temporal will be disabled.') + options.v8_disable_temporal_support = True + else: + print_verbose(f'Detected rustc (RUSTC={rustc}): {rustc_ver}') + rust_ver_tuple = tuple(map(int, rustc_ver.split('.'))) + if rust_ver_tuple < min_rustc_ver_tuple: + warn(f'rustc {rustc_ver} too old, need rustc {".".join(map(str, min_rustc_ver_tuple))}') # Need xcode_version or gas_version when openssl asm files are compiled. if options.without_ssl or options.openssl_no_asm or options.shared_openssl: @@ -1780,6 +1805,14 @@ def configure_node(o): o['variables']['target_arch'] = target_arch o['variables']['node_byteorder'] = sys.byteorder + # On Windows, cargo may default to the GNU target (e.g. x86_64-pc-windows-gnu) + # but Node.js requires MSVC-compatible libraries. Set explicit Rust target + # triple for the target architecture. + o['variables']['cargo_rust_target'] = '' + if flavor == 'win': + o['variables']['cargo_rust_target'] = \ + 'aarch64-pc-windows-msvc' if target_arch == 'arm64' else 'x86_64-pc-windows-msvc' + # Allow overriding the compiler - needed by embedders. if options.use_clang: o['variables']['clang'] = 1 @@ -2057,7 +2090,7 @@ def configure_v8(o, configs): o['variables']['v8_enable_external_code_space'] = 1 if options.enable_pointer_compression else 0 o['variables']['v8_enable_31bit_smis_on_64bit_arch'] = 1 if options.enable_pointer_compression else 0 o['variables']['v8_enable_extensible_ro_snapshot'] = 0 - o['variables']['v8_enable_temporal_support'] = 1 if options.v8_enable_temporal_support else 0 + o['variables']['v8_enable_temporal_support'] = 0 if options.v8_disable_temporal_support else 1 o['variables']['v8_trace_maps'] = 1 if options.trace_maps else 0 o['variables']['node_use_v8_platform'] = b(not options.without_v8_platform) o['variables']['node_use_bundled_v8'] = b(not options.without_bundled_v8) @@ -2089,6 +2122,10 @@ def configure_v8(o, configs): raise Exception( 'Only one of the --v8-enable-object-print or --v8-disable-object-print options ' 'can be specified at a time.') + if all(opt in sys.argv for opt in ['--v8-enable-temporal-support', '--v8-disable-temporal-support']): + raise Exception( + 'Only one of the --v8-enable-temporal-support or --v8-disable-temporal-support options ' + 'can be specified at a time.') if sys.platform != 'darwin': if o['variables']['v8_enable_webassembly'] and o['variables']['target_arch'] == 'x64': o['variables']['v8_enable_wasm_simd256_revec'] = 1 @@ -2754,7 +2791,7 @@ def make_bin_override(): # will fail to run python scripts. gyp_args += ['-Dpython=' + python] -if options.v8_enable_temporal_support and not options.shared_temporal_capi: +if not options.v8_disable_temporal_support or not options.shared_temporal_capi: cargo = os.environ.get('CARGO') if cargo: gyp_args += ['-Dcargo=' + cargo] diff --git a/deps/crates/cargo_build.py b/deps/crates/cargo_build.py new file mode 100644 index 00000000000000..eaac737c77cc5f --- /dev/null +++ b/deps/crates/cargo_build.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python3 + +"""Invoke cargo with the correct Rust target on Windows cross-compilation. + +Works around three issues: GYP's MSVS generator mangles executable names in +host-toolset actions (breaking direct cargo calls), GYP cannot set different +variable values per toolset, and cargo's output directory layout uses Rust +target triples while MSBuild expects platform names (x64/arm64). This script +reads MSBuild's $(Platform) to select the right Rust target and copies the +built library to a path MSBuild can resolve per-project. +""" + +import os +import shutil +import subprocess +import sys + + +def main(): + # Arguments: [cargo_args...] + if len(sys.argv) < 3: + print('Usage: cargo_build.py [cargo_args...]', file=sys.stderr) + sys.exit(1) + + platform = sys.argv[1] # x64 or arm64 + output_dir = sys.argv[2] # SHARED_INTERMEDIATE_DIR + cargo_args = sys.argv[3:] + build_profile = 'release' if '--release' in cargo_args else 'debug' + + cargo = os.environ.get('CARGO', 'cargo') + if not os.path.isabs(cargo) and shutil.which(cargo) is None: + home = os.environ.get('USERPROFILE', '') + cargo_home = os.path.join(home, '.cargo', 'bin', 'cargo.exe') + if os.path.isfile(cargo_home): + cargo = cargo_home + + rust_target_map = { + 'x64': 'x86_64-pc-windows-msvc', + 'arm64': 'aarch64-pc-windows-msvc', + } + rust_target = rust_target_map.get(platform) + if rust_target is None: + print(f'Unsupported platform: {platform}', file=sys.stderr) + sys.exit(1) + + cmd = [cargo, 'rustc', '--target', rust_target, '--target-dir', output_dir] + cargo_args + ret = subprocess.call(cmd) + if ret != 0: + sys.exit(ret) + + # Copy output to the platform-specific directory that MSBuild expects. + src = os.path.join(output_dir, rust_target, build_profile, 'node_crates.lib') + dst_dir = os.path.join(output_dir, platform, build_profile) + os.makedirs(dst_dir, exist_ok=True) + dst = os.path.join(dst_dir, 'node_crates.lib') + shutil.copy2(src, dst) + + +if __name__ == '__main__': + main() diff --git a/deps/crates/crates.gyp b/deps/crates/crates.gyp index 106000028ea794..fa2387281839f2 100644 --- a/deps/crates/crates.gyp +++ b/deps/crates/crates.gyp @@ -2,24 +2,46 @@ 'variables': { 'cargo%': 'cargo', 'cargo_vendor_dir': './vendor', + 'cargo_rust_target%': '', }, 'conditions': [ ['build_type == "Release"', { 'variables': { 'cargo_build_flags': ['--release'], - 'node_crates_libpath': '<(SHARED_INTERMEDIATE_DIR)/release/<(STATIC_LIB_PREFIX)node_crates<(STATIC_LIB_SUFFIX)', }, + 'conditions': [ + ['cargo_rust_target!=""', { + 'variables': { + 'node_crates_libpath': '<(SHARED_INTERMEDIATE_DIR)/$(Platform)/release/node_crates.lib', + }, + }, { + 'variables': { + 'node_crates_libpath': '<(SHARED_INTERMEDIATE_DIR)/release/<(STATIC_LIB_PREFIX)node_crates<(STATIC_LIB_SUFFIX)', + }, + }], + ], }, { 'variables': { 'cargo_build_flags': [], - 'node_crates_libpath': '<(SHARED_INTERMEDIATE_DIR)/debug/<(STATIC_LIB_PREFIX)node_crates<(STATIC_LIB_SUFFIX)', }, + 'conditions': [ + ['cargo_rust_target!=""', { + 'variables': { + 'node_crates_libpath': '<(SHARED_INTERMEDIATE_DIR)/$(Platform)/debug/node_crates.lib', + }, + }, { + 'variables': { + 'node_crates_libpath': '<(SHARED_INTERMEDIATE_DIR)/debug/<(STATIC_LIB_PREFIX)node_crates<(STATIC_LIB_SUFFIX)', + }, + }], + ], }] ], 'targets': [ { 'target_name': 'node_crates', 'type': 'none', + 'toolsets': ['host', 'target'], 'hard_dependency': 1, 'sources': [ 'Cargo.toml', @@ -39,29 +61,54 @@ }], ], }, - 'actions': [ - { - 'action_name': 'cargo_build', - 'inputs': [ - '<@(_sources)' - ], - 'outputs': [ - '<(node_crates_libpath)' + 'conditions': [ + ['cargo_rust_target!=""', { + 'actions': [ + { + 'action_name': 'cargo_build', + 'inputs': [ + '<@(_sources)' + ], + 'outputs': [ + '<(node_crates_libpath)' + ], + 'action': [ + '<(python)', + 'cargo_build.py', + '$(Platform)', + '<(SHARED_INTERMEDIATE_DIR)', + '<@(cargo_build_flags)', + '--frozen', + ], + } ], - 'action': [ - '<(cargo)', - 'rustc', - '<@(cargo_build_flags)', - '--frozen', - '--target-dir', - '<(SHARED_INTERMEDIATE_DIR)' + }, { + 'actions': [ + { + 'action_name': 'cargo_build', + 'inputs': [ + '<@(_sources)' + ], + 'outputs': [ + '<(node_crates_libpath)' + ], + 'action': [ + '<(cargo)', + 'rustc', + '<@(cargo_build_flags)', + '--frozen', + '--target-dir', + '<(SHARED_INTERMEDIATE_DIR)' + ], + } ], - } + }], ], }, { 'target_name': 'temporal_capi', 'type': 'none', + 'toolsets': ['host', 'target'], 'sources': [], 'dependencies': [ 'node_crates', diff --git a/deps/v8/src/objects/js-temporal-zoneinfo64.cc b/deps/v8/src/objects/js-temporal-zoneinfo64.cc index 99dd3a84c1e54f..2bb9e1f5ba8c59 100644 --- a/deps/v8/src/objects/js-temporal-zoneinfo64.cc +++ b/deps/v8/src/objects/js-temporal-zoneinfo64.cc @@ -11,12 +11,44 @@ #include "temporal_rs/TimeZone.hpp" #ifdef V8_INTL_SUPPORT -#include "udatamem.h" +#include "unicode/udata.h" +typedef struct { + uint16_t headerSize; + uint8_t magic1; + uint8_t magic2; +} MappedData; +typedef struct { + MappedData dataHeader; + UDataInfo info; +} DataHeader; +typedef struct { + void* Lookup; + void* NumEntries; +} commonDataFuncs; +struct UDataMemory { + const commonDataFuncs *vFuncs; /* Function Pointers for accessing TOC */ + + const DataHeader *pHeader; /* Header of the memory being described by this */ + /* UDataMemory object. */ + const void *toc; /* For common memory, table of contents for */ + /* the pieces within. */ + UBool heapAllocated; /* True if this UDataMemory Object is on the */ + /* heap and thus needs to be deleted when closed. */ + + void *mapAddr; /* For mapped or allocated memory, the start addr. */ + /* Only non-null if a close operation should unmap */ + /* the associated data. */ + void *map; /* Handle, or other data, OS dependent. */ + /* Only non-null if a close operation should unmap */ + /* the associated data, and additional info */ + /* beyond the mapAddr is needed to do that. */ + int32_t length; /* Length of the data in bytes; -1 if unknown. */ +}; #else // Defined in builtins-temporal-zoneinfo64-data.cc, generated by // include-file-as-bytes.py -extern "C" uint32_t zoneinfo64_static_data[]; -extern "C" size_t zoneinfo64_static_data_len; +static uint32_t zoneinfo64_static_data[] = {}; +static size_t zoneinfo64_static_data_len = 0; #endif namespace v8::internal { @@ -33,7 +65,7 @@ ZoneInfo64Provider::ZoneInfo64Provider() { // NOT udata_getLength: this ignores the header, // and we're parsing resb files with the header auto length = memory->length; - const void* data = udata_getRawMemory(memory); + const void* data = udata_getMemory(memory); DCHECK_WITH_MSG(length % 4 == 0, "ICU4C should align udata to uint32_t"); if (length % 4 != 0) { // This really shouldn't happen: ICU4C aligns these files