diff --git a/NativeScript/inspector/JsV8InspectorClient.mm b/NativeScript/inspector/JsV8InspectorClient.mm index fafe0c68..a6a19538 100644 --- a/NativeScript/inspector/JsV8InspectorClient.mm +++ b/NativeScript/inspector/JsV8InspectorClient.mm @@ -22,6 +22,20 @@ namespace v8_inspector { +namespace { +// Build an 8-bit `StringView` directly over a `std::string`'s storage. +// V8 inspector messages on this side are ASCII/UTF-8 JSON, so the +// previous `std::string -> std::vector -> StringView` path +// inflated each byte to two and then handed it to a 16-bit constructor. +// Going straight through the 8-bit constructor avoids that doubling AND +// dodges the libc++ deprecation that prompted the inspector's +// `UChar = uint16_t -> char16_t` switch. +StringView Make8BitStringView(const std::string& value) { + return StringView(reinterpret_cast(value.data()), + value.size()); +} +} // namespace + #define NOTIFICATION(name) \ [[NSString stringWithFormat:@"%@:NativeScript.Debug.%s", \ [[NSBundle mainBundle] bundleIdentifier], name] UTF8String] @@ -257,8 +271,7 @@ } void JsV8InspectorClient::dispatchMessage(const std::string& message) { - std::vector vector = tns::ToVector(message); - StringView messageView(vector.data(), vector.size()); + StringView messageView = Make8BitStringView(message); Isolate* isolate = isolate_; v8::Locker locker(isolate); Isolate::Scope isolate_scope(isolate); @@ -343,8 +356,7 @@ auto returnString = GetReturnMessageFromDomainHandlerResult(result, requestId); if (returnString.size() > 0) { - std::vector vector = tns::ToVector(returnString); - StringView messageView(vector.data(), vector.size()); + StringView messageView = Make8BitStringView(returnString); auto msg = StringBuffer::create(messageView); this->sendNotification(std::move(msg)); } @@ -486,8 +498,7 @@ Local arg = args[0].As(); std::string message = tns::ToString(isolate, arg); - std::vector vector = tns::ToVector(message); - StringView messageView(vector.data(), vector.size()); + StringView messageView = Make8BitStringView(message); auto msg = StringBuffer::create(messageView); client->sendNotification(std::move(msg)); } diff --git a/NativeScript/inspector/src/inspector/string-16.h b/NativeScript/inspector/src/inspector/string-16.h index 7dfc5e34..85505a66 100644 --- a/NativeScript/inspector/src/inspector/string-16.h +++ b/NativeScript/inspector/src/inspector/string-16.h @@ -17,7 +17,13 @@ namespace v8_inspector { -using UChar = uint16_t; +// Xcode 26.x libc++ deprecates `std::basic_string` +// (and any `char_traits` specialization for non-standard char types). +// Switch to `char16_t` so `std::basic_string` resolves to the +// fully supported `std::u16string`. The V8 inspector public API still +// takes `uint16_t*`, so call sites that cross that boundary now use +// `reinterpret_cast` (see string-util.h). +using UChar = char16_t; class String16 { public: diff --git a/NativeScript/inspector/src/inspector/string-util.h b/NativeScript/inspector/src/inspector/string-util.h index 7f427d9b..66834746 100644 --- a/NativeScript/inspector/src/inspector/string-util.h +++ b/NativeScript/inspector/src/inspector/string-util.h @@ -30,13 +30,17 @@ class StringUtil { } static String fromUTF16LE(const uint16_t* data, size_t length) { - return String16::fromUTF16LE(data, length); + // V8 inspector protocol passes `uint16_t*` over its public API but + // `String16` is now backed by `std::u16string` (UChar = char16_t). + // The two are bit-identical 16-bit codepoints, so a reinterpret_cast + // is sound at the API boundary. + return String16::fromUTF16LE(reinterpret_cast(data), length); } static const uint8_t* CharactersLatin1(const String& s) { return nullptr; } static const uint8_t* CharactersUTF8(const String& s) { return nullptr; } static const uint16_t* CharactersUTF16(const String& s) { - return s.characters16(); + return reinterpret_cast(s.characters16()); } static size_t CharacterCount(const String& s) { return s.length(); } }; diff --git a/NativeScript/inspector/utils.mm b/NativeScript/inspector/utils.mm index d078e525..edba76ae 100644 --- a/NativeScript/inspector/utils.mm +++ b/NativeScript/inspector/utils.mm @@ -35,17 +35,22 @@ } std::string v8_inspector::ToStdString(const StringView& value) { - std::vector buffer(value.length()); + // Build the std::u16string directly. The previous version went via + // std::vector + a copy-construct into u16string, which on + // Xcode 26.x's libc++ tripped the `char_traits` + // deprecation through the construct-from-iterator path. Writing + // char16_t straight into the destination avoids the + // non-standard char-traits specialization entirely. + std::u16string value16; + value16.resize(value.length()); for (size_t i = 0; i < value.length(); i++) { if (value.is8Bit()) { - buffer[i] = value.characters8()[i]; + value16[i] = static_cast(value.characters8()[i]); } else { - buffer[i] = value.characters16()[i]; + value16[i] = static_cast(value.characters16()[i]); } } - std::u16string value16(buffer.begin(), buffer.end()); - #pragma GCC diagnostic ignored "-Wdeprecated-declarations" // FIXME: std::codecvt_utf8_utf16 is deprecated std::wstring_convert, char16_t> convert; diff --git a/NativeScript/v8runtime/V8Runtime.cpp b/NativeScript/v8runtime/V8Runtime.cpp index 42355bdf..8829cd52 100644 --- a/NativeScript/v8runtime/V8Runtime.cpp +++ b/NativeScript/v8runtime/V8Runtime.cpp @@ -431,7 +431,12 @@ std::shared_ptr V8Runtime::prepareJavaScript( jsi::Value V8Runtime::evaluatePreparedJavaScript( const std::shared_ptr& js) { - return evaluateJavaScript(nullptr, nullptr); + // The second arg is a `std::string` sourceURL; newer Clang (Xcode 26.x) + // enforces `-Wnonnull` on its non-null `const char*` constructor, so we + // can no longer pass `nullptr`. Empty string is the documented "unknown + // source URL" value and matches the existing `prepareJavaScript` no-op + // (which already returns nullptr above). + return evaluateJavaScript(nullptr, ""); } void V8Runtime::queueMicrotask(const jsi::Function& callback) { diff --git a/metadata-generator/CMakeLists.txt b/metadata-generator/CMakeLists.txt index a8974978..4ae9950d 100644 --- a/metadata-generator/CMakeLists.txt +++ b/metadata-generator/CMakeLists.txt @@ -1,6 +1,7 @@ cmake_minimum_required(VERSION 3.20) project(MetadataGenerator) include(CheckCCompilerFlag) +include(CheckCXXCompilerFlag) #set(CMAKE_VERBOSE_MAKEFILE ON) @@ -36,6 +37,23 @@ if (HAS_UNUSED_BUT_SET_VARIABLE) add_compile_options(-Wno-unused-but-set-variable) endif() +# Newer Apple toolchains (Xcode 26.x with Clang 17+) emit two diagnostics +# inside LLVM 17.0.6's own headers (e.g. `-Wunnecessary-virtual-specifier` +# on `virtual void anchor()` in classes declared `final` in +# `clang/AST/Decl.h`, and `-Wpreferred-type-bitfield-enum-conversion` on +# bitfield-to-enum stores). These are upstream-known issues that don't +# affect generator behavior. Keep `-Werror` for *our* code, but downgrade +# these two to warnings so the build succeeds without bumping LLVM. +check_cxx_compiler_flag(-Wno-error=preferred-type-bitfield-enum-conversion HAS_NO_ERROR_PREFERRED_TYPE_BITFIELD_ENUM_CONVERSION) +if (HAS_NO_ERROR_PREFERRED_TYPE_BITFIELD_ENUM_CONVERSION) + add_compile_options(-Wno-error=preferred-type-bitfield-enum-conversion) +endif() + +check_cxx_compiler_flag(-Wno-error=unnecessary-virtual-specifier HAS_NO_ERROR_UNNECESSARY_VIRTUAL_SPECIFIER) +if (HAS_NO_ERROR_UNNECESSARY_VIRTUAL_SPECIFIER) + add_compile_options(-Wno-error=unnecessary-virtual-specifier) +endif() + set(LLVM_LINKER_FLAGS "${LLVM_LINKER_FLAGS} ${LLVM_SYSTEM_LIBS} ${LLVM_LIBS}") set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin/lib)