From 74e144432bf17cc043d0e64affc9cb1703e80832 Mon Sep 17 00:00:00 2001 From: Nicholas Fredricks Date: Tue, 16 Apr 2024 07:51:38 -0400 Subject: [PATCH 01/13] fix: Xcode 15.3+ not setting TARGET_OS_IOS correctly (#248) --- metadata-generator/build-step-metadata-generator.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/metadata-generator/build-step-metadata-generator.py b/metadata-generator/build-step-metadata-generator.py index bcf373f2..78e3603f 100755 --- a/metadata-generator/build-step-metadata-generator.py +++ b/metadata-generator/build-step-metadata-generator.py @@ -152,10 +152,11 @@ def generate_metadata(arch): deployment_target_flag_name + "=" + deployment_target]) else: generator_call.extend(["-target", "{}-{}-{}{}".format(arch, llvm_target_triple_vendor, llvm_target_triple_os_version, llvm_target_triple_suffix)]) - # since iPhoneOS 17.4 sdk TARGET_OS_IPHONE is not defined for non-simulator builds + # since iPhoneOS 17.4 sdk TARGET_OS_IPHONE and TARGET_OS_IOS is not defined for non-simulator builds # this seems to be a bug on Apple's side if effective_platform_name == "-iphoneos" and not llvm_target_triple_suffix: generator_call.extend(["-DTARGET_OS_IPHONE=1"]) + generator_call.extend(["-DTARGET_OS_IOS=1"]) generator_call.extend(header_search_paths_parsed) # HEADER_SEARCH_PATHS generator_call.extend(framework_search_paths_parsed) # FRAMEWORK_SEARCH_PATHS From 4a6e9adde6950e09ac0c2fd2713e25aa919ad448 Mon Sep 17 00:00:00 2001 From: Osei Fortune Date: Fri, 26 Apr 2024 17:41:20 -0400 Subject: [PATCH 02/13] fix: url href (#252) --- NativeScript/runtime/URLImpl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NativeScript/runtime/URLImpl.cpp b/NativeScript/runtime/URLImpl.cpp index 54a10530..50ca6157 100644 --- a/NativeScript/runtime/URLImpl.cpp +++ b/NativeScript/runtime/URLImpl.cpp @@ -268,7 +268,7 @@ void URLImpl::GetHref(v8::Local property, } auto isolate = info.GetIsolate(); - auto value = ptr->GetURL()->get_hostname(); + auto value = ptr->GetURL()->get_href(); info.GetReturnValue().Set(ToV8String(isolate, value.data(), (int)value.length())); From c6f42bcee1e952a551b9548a6bd3a4349b31bd30 Mon Sep 17 00:00:00 2001 From: Nathan Walker Date: Fri, 26 Apr 2024 14:47:39 -0700 Subject: [PATCH 03/13] release: 8.7.1 --- CHANGELOG.md | 10 ++++++++++ NativeScript/NativeScript-Prefix.pch | 2 +- package.json | 4 ++-- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d97bc936..d089edae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ +## [8.7.1](https://github.com/NativeScript/ios/compare/v8.7.0...v8.7.1) (2024-04-26) + + +### Bug Fixes + +* url href ([#252](https://github.com/NativeScript/ios/issues/252)) ([4a6e9ad](https://github.com/NativeScript/ios/commit/4a6e9adde6950e09ac0c2fd2713e25aa919ad448)) +* Xcode 15.3+ not setting TARGET_OS_IOS correctly ([#248](https://github.com/NativeScript/ios/issues/248)) ([74e1444](https://github.com/NativeScript/ios/commit/74e144432bf17cc043d0e64affc9cb1703e80832)) + + + # [8.7.0](https://github.com/NativeScript/ios/compare/v8.6.3...v8.7.0) (2024-04-08) diff --git a/NativeScript/NativeScript-Prefix.pch b/NativeScript/NativeScript-Prefix.pch index 9932b781..eeacaad3 100644 --- a/NativeScript/NativeScript-Prefix.pch +++ b/NativeScript/NativeScript-Prefix.pch @@ -1,7 +1,7 @@ #ifndef NativeScript_Prefix_pch #define NativeScript_Prefix_pch -#define NATIVESCRIPT_VERSION "8.7.0-rc.1" +#define NATIVESCRIPT_VERSION "8.7.1" #ifdef DEBUG #define SIZEOF_OFF_T 8 diff --git a/package.json b/package.json index a9f11d9d..faa419f2 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@nativescript/ios", "description": "NativeScript Runtime for iOS", - "version": "8.7.0", + "version": "8.7.1", "keywords": [ "NativeScript", "iOS", @@ -36,4 +36,4 @@ "dayjs": "^1.11.7", "semver": "^7.5.0" } -} +} \ No newline at end of file From c1c95cfbca8fe9661dbfb730dca8e02462749220 Mon Sep 17 00:00:00 2001 From: Nathan Walker Date: Fri, 26 Apr 2024 14:50:37 -0700 Subject: [PATCH 04/13] chore: 8.7.2 next --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index faa419f2..f977ce5c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@nativescript/ios", "description": "NativeScript Runtime for iOS", - "version": "8.7.1", + "version": "8.7.2", "keywords": [ "NativeScript", "iOS", From 1df9ea20b6bfde5163b0486e444e5471fb8343b2 Mon Sep 17 00:00:00 2001 From: Gabriel Matos Date: Tue, 14 May 2024 19:19:13 -0300 Subject: [PATCH 05/13] fix(ios): watchOS embedded apps (#250) --- .../internal/Swift-ObjC-Bridging-Header.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/project-template-ios/internal/Swift-ObjC-Bridging-Header.h b/project-template-ios/internal/Swift-ObjC-Bridging-Header.h index 7db14b65..5683610d 100644 --- a/project-template-ios/internal/Swift-ObjC-Bridging-Header.h +++ b/project-template-ios/internal/Swift-ObjC-Bridging-Header.h @@ -10,5 +10,9 @@ // the *-Swift.h*. // https://developer.apple.com/documentation/swift/imported_c_and_objective-c_apis/importing_objective-c_into_swift -#import "NativeScript/NativeScript.h" -#import "NativeScriptStart.h" +#import "TargetConditionals.h" + +#ifndef TARGET_OS_WATCH + #import "NativeScript/NativeScript.h" + #import "NativeScriptStart.h" +#endif From 7bcc119f56abad0ef569ed28460c95cd66fc1f5e Mon Sep 17 00:00:00 2001 From: Nathan Walker Date: Thu, 16 May 2024 08:06:16 -0700 Subject: [PATCH 06/13] release: 8.7.2 --- CHANGELOG.md | 9 +++++++++ NativeScript/NativeScript-Prefix.pch | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d089edae..0f7ea6b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +## [8.7.2](https://github.com/NativeScript/ios/compare/v8.7.1...v8.7.2) (2024-05-16) + + +### Bug Fixes + +* **ios:** watchOS embedded apps ([#250](https://github.com/NativeScript/ios/issues/250)) ([1df9ea2](https://github.com/NativeScript/ios/commit/1df9ea20b6bfde5163b0486e444e5471fb8343b2)) + + + ## [8.7.1](https://github.com/NativeScript/ios/compare/v8.7.0...v8.7.1) (2024-04-26) diff --git a/NativeScript/NativeScript-Prefix.pch b/NativeScript/NativeScript-Prefix.pch index eeacaad3..b070729c 100644 --- a/NativeScript/NativeScript-Prefix.pch +++ b/NativeScript/NativeScript-Prefix.pch @@ -1,7 +1,7 @@ #ifndef NativeScript_Prefix_pch #define NativeScript_Prefix_pch -#define NATIVESCRIPT_VERSION "8.7.1" +#define NATIVESCRIPT_VERSION "8.7.2" #ifdef DEBUG #define SIZEOF_OFF_T 8 From bb441aff731e1100eefc4d71a7cbef7a41362ee2 Mon Sep 17 00:00:00 2001 From: Nathan Walker Date: Thu, 16 May 2024 08:06:51 -0700 Subject: [PATCH 07/13] chore: 8.7.3 next --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f977ce5c..a52b5007 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@nativescript/ios", "description": "NativeScript Runtime for iOS", - "version": "8.7.2", + "version": "8.7.3", "keywords": [ "NativeScript", "iOS", From 7ded0c38bb891b340bd8e1c5137e607447e26e60 Mon Sep 17 00:00:00 2001 From: Eduardo Speroni Date: Thu, 30 May 2024 16:03:05 -0300 Subject: [PATCH 08/13] feat: use messaging object to pass message to workers (#233) --- NativeScript/runtime/ConcurrentQueue.cpp | 8 +- NativeScript/runtime/ConcurrentQueue.h | 7 +- NativeScript/runtime/DataWrapper.h | 6 +- NativeScript/runtime/Helpers.h | 51 ++ NativeScript/runtime/Message.cpp | 488 ++++++++++++++++++ NativeScript/runtime/Message.hpp | 136 +++++ NativeScript/runtime/NativeScriptException.h | 3 + NativeScript/runtime/NativeScriptException.mm | 34 +- NativeScript/runtime/Worker.h | 3 +- NativeScript/runtime/Worker.mm | 62 ++- NativeScript/runtime/WorkerWrapper.mm | 8 +- TestRunner/app/tests/shared/Workers/index.js | 2 +- v8ios.xcodeproj/project.pbxproj | 8 + 13 files changed, 772 insertions(+), 44 deletions(-) create mode 100644 NativeScript/runtime/Message.cpp create mode 100644 NativeScript/runtime/Message.hpp diff --git a/NativeScript/runtime/ConcurrentQueue.cpp b/NativeScript/runtime/ConcurrentQueue.cpp index 8b361838..24721114 100644 --- a/NativeScript/runtime/ConcurrentQueue.cpp +++ b/NativeScript/runtime/ConcurrentQueue.cpp @@ -14,7 +14,7 @@ void ConcurrentQueue::Initialize(CFRunLoopRef runLoop, void (*performWork)(void* CFRunLoopAddSource(this->runLoop_, this->runLoopTasksSource_, kCFRunLoopCommonModes); } -void ConcurrentQueue::Push(std::string message) { +void ConcurrentQueue::Push(std::shared_ptr message) { if (this->runLoopTasksSource_ != nullptr && !CFRunLoopSourceIsValid(this->runLoopTasksSource_)) { return; } @@ -27,12 +27,12 @@ void ConcurrentQueue::Push(std::string message) { this->SignalAndWakeUp(); } -std::vector ConcurrentQueue::PopAll() { +std::vector> ConcurrentQueue::PopAll() { std::unique_lock mlock(this->mutex_); - std::vector messages; + std::vector> messages; while (!this->messagesQueue_.empty()) { - std::string message = this->messagesQueue_.front(); + std::shared_ptr message = this->messagesQueue_.front(); this->messagesQueue_.pop(); messages.push_back(message); } diff --git a/NativeScript/runtime/ConcurrentQueue.h b/NativeScript/runtime/ConcurrentQueue.h index 75bc74e4..84dff251 100644 --- a/NativeScript/runtime/ConcurrentQueue.h +++ b/NativeScript/runtime/ConcurrentQueue.h @@ -6,17 +6,18 @@ #include #include #include +#include "Message.hpp" namespace tns { struct ConcurrentQueue { public: void Initialize(CFRunLoopRef runLoop, void (*performWork)(void*), void* info); - void Push(std::string message); - std::vector PopAll(); + void Push(std::shared_ptr message); + std::vector> PopAll(); void Terminate(); private: - std::queue messagesQueue_; + std::queue> messagesQueue_; CFRunLoopSourceRef runLoopTasksSource_ = nullptr; CFRunLoopRef runLoop_ = nullptr; bool terminated = false; diff --git a/NativeScript/runtime/DataWrapper.h b/NativeScript/runtime/DataWrapper.h index 0d655b24..9b9c05f3 100644 --- a/NativeScript/runtime/DataWrapper.h +++ b/NativeScript/runtime/DataWrapper.h @@ -654,12 +654,12 @@ class ExtVectorWrapper: public BaseDataWrapper { class WorkerWrapper: public BaseDataWrapper { public: - WorkerWrapper(v8::Isolate* mainIsolate, std::function thiz, std::string)> onMessage); + WorkerWrapper(v8::Isolate* mainIsolate, std::function thiz, std::shared_ptr)> onMessage); void Start(std::shared_ptr> poWorker, std::function func); void CallOnErrorHandlers(v8::TryCatch& tc); void PassUncaughtExceptionFromWorkerToMain(v8::Local context, v8::TryCatch& tc, bool async = true); - void PostMessage(std::string message); + void PostMessage(std::shared_ptr message); void Close(); void Terminate(); @@ -691,7 +691,7 @@ class WorkerWrapper: public BaseDataWrapper { std::atomic isTerminating_; bool isDisposed_; bool isWeak_; - std::function thiz, std::string)> onMessage_; + std::function thiz, std::shared_ptr)> onMessage_; std::shared_ptr> poWorker_; ConcurrentQueue queue_; static std::atomic nextId_; diff --git a/NativeScript/runtime/Helpers.h b/NativeScript/runtime/Helpers.h index 656ebec9..dc65a88d 100644 --- a/NativeScript/runtime/Helpers.h +++ b/NativeScript/runtime/Helpers.h @@ -345,6 +345,57 @@ void SetConstructorFunction(v8::Isolate* isolate, SetConstructorFunctionFlag::SET_CLASS_NAME); +template +inline v8::Local FIXED_ONE_BYTE_STRING( + v8::Isolate* isolate, + const char(&data)[N]) { + return OneByteString(isolate, data, N - 1); +} + +template +inline v8::Local FIXED_ONE_BYTE_STRING( + v8::Isolate* isolate, + const std::array& arr) { + return OneByteString(isolate, arr.data(), N - 1); +} + +class PersistentToLocal { + public: + // If persistent.IsWeak() == false, then do not call persistent.Reset() + // while the returned Local is still in scope, it will destroy the + // reference to the object. + template + static inline v8::Local Default( + v8::Isolate* isolate, + const v8::PersistentBase& persistent) { + if (persistent.IsWeak()) { + return PersistentToLocal::Weak(isolate, persistent); + } else { + return PersistentToLocal::Strong(persistent); + } + } + + // Unchecked conversion from a non-weak Persistent to Local, + // use with care! + // + // Do not call persistent.Reset() while the returned Local is still in + // scope, it will destroy the reference to the object. + template + static inline v8::Local Strong( + const v8::PersistentBase& persistent) { +// DCHECK(!persistent.IsWeak()); + return *reinterpret_cast*>( + const_cast*>(&persistent)); + } + + template + static inline v8::Local Weak( + v8::Isolate* isolate, + const v8::PersistentBase& persistent) { + return v8::Local::New(isolate, persistent); + } +}; + } #endif /* Helpers_h */ diff --git a/NativeScript/runtime/Message.cpp b/NativeScript/runtime/Message.cpp new file mode 100644 index 00000000..270adbf4 --- /dev/null +++ b/NativeScript/runtime/Message.cpp @@ -0,0 +1,488 @@ +// +// Message.cpp +// NativeScript +// +// Created by Eduardo Speroni on 11/22/23. +// Copyright © 2023 Progress. All rights reserved. +// + +#include "Helpers.h" +#include "Message.hpp" +#include "NativeScriptException.h" + +using namespace v8; + +namespace tns { +namespace worker { +namespace { +void ThrowDataCloneException(Local context, + Local message) { + Isolate* isolate = context->GetIsolate(); + // Local argv[] = {message, + // FIXED_ONE_BYTE_STRING(isolate, "DataCloneError")}; + Local exception; + Local domexception_ctor; + NativeScriptException except(isolate, tns::ToString(isolate, message), + "DataCloneError"); + except.ReThrowToV8(isolate); +} +class SerializerDelegate : public v8::ValueSerializer::Delegate { + public: + SerializerDelegate(Isolate* isolate, Local context, Message* m) + : isolate_(isolate), context_(context), msg_(m) {} + + void ThrowDataCloneError(Local message) override { + ThrowDataCloneException(context_, message); + } + + Maybe WriteHostObject(Isolate* isolate, Local object) override { + return Just(true); + // if (BaseObject::IsBaseObject(object)) { + // return WriteHostObject( + // BaseObjectPtr { Unwrap(object) }); + // } + // + // // Convert process.env to a regular object. + // auto env_proxy_ctor_template = env_->env_proxy_ctor_template(); + // if (!env_proxy_ctor_template.IsEmpty() && + // env_proxy_ctor_template->HasInstance(object)) { + // HandleScope scope(isolate); + // // TODO(bnoordhuis) Prototype-less object in case process.env + // contains + // // a "__proto__" key? process.env has a prototype with concomitant + // // methods like toString(). It's probably confusing if that gets + // lost + // // in transmission. + // Local normal_object = Object::New(isolate); + // env_->env_vars()->AssignToObject(isolate, env_->context(), + // normal_object); serializer->WriteUint32(kNormalObject); // Instead + // of a BaseObject. return serializer->WriteValue(env_->context(), + // normal_object); + // } + // + // ThrowDataCloneError(env_->clone_unsupported_type_str()); + // return Nothing(); + } + + Maybe GetSharedArrayBufferId( + Isolate* isolate, Local shared_array_buffer) override { + uint32_t i; + for (i = 0; i < seen_shared_array_buffers_.size(); ++i) { + if (PersistentToLocal::Strong(seen_shared_array_buffers_[i]) == + shared_array_buffer) { + return Just(i); + } + } + + seen_shared_array_buffers_.emplace_back( + Global{isolate, shared_array_buffer}); + msg_->AddSharedArrayBuffer(shared_array_buffer->GetBackingStore()); + return Just(i); + } + + // Maybe GetWasmModuleTransferId( + // Isolate* isolate, Local module) override { + // return Just(msg_->AddWASMModule(module->GetCompiledModule())); + // } + + // bool AdoptSharedValueConveyor(Isolate* isolate, + // SharedValueConveyor&& conveyor) override { + // msg_->AdoptSharedValueConveyor(std::move(conveyor)); + // return true; + // } + + // Maybe Finish(Local context) { + // for (uint32_t i = 0; i < host_objects_.size(); i++) { + // BaseObjectPtr host_object = std::move(host_objects_[i]); + // std::unique_ptr data; + // if (i < first_cloned_object_index_) + // data = host_object->TransferForMessaging(); + // if (!data) + // data = host_object->CloneForMessaging(); + // if (!data) return Nothing(); + // if (data->FinalizeTransferWrite(context, serializer).IsNothing()) + // return Nothing(); + // msg_->AddTransferable(std::move(data)); + // } + // return Just(true); + // } + + // inline void AddHostObject(BaseObjectPtr host_object) { + // // Make sure we have not started serializing the value itself yet. + // CHECK_EQ(first_cloned_object_index_, SIZE_MAX); + // host_objects_.emplace_back(std::move(host_object)); + // } + // + // // Some objects in the transfer list may register sub-objects that can be + // // transferred. This could e.g. be a public JS wrapper object, such as a + // // FileHandle, that is registering its C++ handle for transfer. + // inline Maybe AddNestedHostObjects() { + // for (size_t i = 0; i < host_objects_.size(); i++) { + // std::vector> nested_transferables; + // if + // (!host_objects_[i]->NestedTransferables().To(&nested_transferables)) + // return Nothing(); + // for (auto& nested_transferable : nested_transferables) { + // if (std::find(host_objects_.begin(), + // host_objects_.end(), + // nested_transferable) == host_objects_.end()) { + // AddHostObject(nested_transferable); + // } + // } + // } + // return Just(true); + // } + + ValueSerializer* serializer = nullptr; + + private: + // Maybe WriteHostObject(BaseObjectPtr host_object) { + // BaseObject::TransferMode mode = host_object->GetTransferMode(); + // if (mode == BaseObject::TransferMode::kUntransferable) { + // ThrowDataCloneError(env_->clone_unsupported_type_str()); + // return Nothing(); + // } + // + // for (uint32_t i = 0; i < host_objects_.size(); i++) { + // if (host_objects_[i] == host_object) { + // serializer->WriteUint32(i); + // return Just(true); + // } + // } + // + // if (mode == BaseObject::TransferMode::kTransferable) { + // THROW_ERR_MISSING_TRANSFERABLE_IN_TRANSFER_LIST(env_); + // return Nothing(); + // } + // + // CHECK_EQ(mode, BaseObject::TransferMode::kCloneable); + // uint32_t index = host_objects_.size(); + // if (first_cloned_object_index_ == SIZE_MAX) + // first_cloned_object_index_ = index; + // serializer->WriteUint32(index); + // host_objects_.push_back(host_object); + // return Just(true); + // } + + __unused Isolate* isolate_; + __unused Local context_; + Message* msg_; + std::vector> seen_shared_array_buffers_; + // std::vector> host_objects_; + __unused size_t first_cloned_object_index_ = SIZE_MAX; + + friend class tns::worker::Message; +}; + +class DeserializerDelegate : public ValueDeserializer::Delegate { + public: + DeserializerDelegate( + Message* m, Isolate* isolate, + // const std::vector>& host_objects, + const std::vector>& shared_array_buffers + // const std::vector& wasm_modules, + // const std::optional& shared_value_conveyor + ) + : // host_objects_(host_objects), + shared_array_buffers_(shared_array_buffers) + // wasm_modules_(wasm_modules), + // shared_value_conveyor_(shared_value_conveyor) + {} + + MaybeLocal ReadHostObject(Isolate* isolate) override { + EscapableHandleScope scope(isolate); + Local object = Object::New(isolate); + return scope.Escape(object).As(); + // // Identifying the index in the message's BaseObject array is + // sufficient. uint32_t id; if (!deserializer->ReadUint32(&id)) + // return MaybeLocal(); + // if (id != kNormalObject) { + // CHECK_LT(id, host_objects_.size()); + // return host_objects_[id]->object(isolate); + // } + // EscapableHandleScope scope(isolate); + // Local context = isolate->GetCurrentContext(); + // Local object; + // if (!deserializer->ReadValue(context).ToLocal(&object)) + // return MaybeLocal(); + // CHECK(object->IsObject()); + // return scope.Escape(object.As()); + } + + MaybeLocal GetSharedArrayBufferFromId( + Isolate* isolate, uint32_t clone_id) override { + // CHECK_LT(clone_id, shared_array_buffers_.size()); + return shared_array_buffers_[clone_id]; + } + + // MaybeLocal GetWasmModuleFromId( + // Isolate* isolate, uint32_t transfer_id) override { + //// CHECK_LT(transfer_id, wasm_modules_.size()); + // return WasmModuleObject::FromCompiledModule( + // isolate, wasm_modules_[transfer_id]); + // } + + // const SharedValueConveyor* GetSharedValueConveyor(Isolate* isolate) + // override { + //// CHECK(shared_value_conveyor_.has_value()); + // return &shared_value_conveyor_.value(); + // } + + ValueDeserializer* deserializer = nullptr; + + private: + // const std::vector>& host_objects_; + const std::vector>& shared_array_buffers_; + // const std::vector& wasm_modules_; + // const std::optional& shared_value_conveyor_; +}; +}; // namespace + +v8::Maybe Message::Serialize(v8::Isolate* isolate, + v8::Local context, + v8::Local input) { + HandleScope handle_scope(isolate); + v8::Context::Scope context_scope(context); + + // Verify that we're not silently overwriting an existing message. + tns::Assert(main_message_buf_.is_empty()); + + SerializerDelegate delegate(isolate, context, this); + ValueSerializer serializer(isolate, &delegate); + delegate.serializer = &serializer; + + std::vector> array_buffers; + // for (uint32_t i = 0; i < transfer_list_v.length(); ++i) { + // Local entry = transfer_list_v[i]; + // if (entry->IsObject()) { + // // See + // https://github.com/nodejs/node/pull/30339#issuecomment-552225353 + // // for details. + // bool untransferable; + // if (!entry.As()->HasPrivate( + // context, + // env->untransferable_object_private_symbol()) + // .To(&untransferable)) { + // return Nothing(); + // } + // if (untransferable) { + // ThrowDataCloneException(context, + // env->transfer_unsupported_type_str()); return Nothing(); + // } + // } + // + // // Currently, we support ArrayBuffers and BaseObjects for which + // // GetTransferMode() returns kTransferable. + // if (entry->IsArrayBuffer()) { + // Local ab = entry.As(); + // // If we cannot render the ArrayBuffer unusable in this Isolate, + // // copying the buffer will have to do. + // // Note that we can currently transfer ArrayBuffers even if they + // were + // // not allocated by Node’s ArrayBufferAllocator in the first + // place, + // // because we pass the underlying v8::BackingStore around rather + // than + // // raw data *and* an Isolate with a non-default ArrayBuffer + // allocator + // // is always going to outlive any Workers it creates, and so will + // its + // // allocator along with it. + // if (!ab->IsDetachable() || ab->WasDetached()) { + // ThrowDataCloneException(context, + // env->transfer_unsupported_type_str()); return Nothing(); + // } + // if (std::find(array_buffers.begin(), array_buffers.end(), ab) != + // array_buffers.end()) { + // ThrowDataCloneException( + // context, + // FIXED_ONE_BYTE_STRING( + // env->isolate(), + // "Transfer list contains duplicate ArrayBuffer")); + // return Nothing(); + // } + // // We simply use the array index in the `array_buffers` list as + // the + // // ID that we write into the serialized buffer. + // uint32_t id = array_buffers.size(); + // array_buffers.push_back(ab); + // serializer.TransferArrayBuffer(id, ab); + // continue; + // } else if (entry->IsObject() && + // BaseObject::IsBaseObject(entry.As())) { + // // Check if the source MessagePort is being transferred. + // if (!source_port.IsEmpty() && entry == source_port) { + // ThrowDataCloneException( + // context, + // FIXED_ONE_BYTE_STRING(env->isolate(), + // "Transfer list contains source + // port")); + // return Nothing(); + // } + // BaseObjectPtr host_object { + // Unwrap(entry.As()) }; + // if (env->message_port_constructor_template()->HasInstance(entry) + // && + // (!host_object || + // static_cast(host_object.get())->IsDetached())) + // { + // ThrowDataCloneException( + // context, + // FIXED_ONE_BYTE_STRING( + // env->isolate(), + // "MessagePort in transfer list is already detached")); + // return Nothing(); + // } + // if (std::find(delegate.host_objects_.begin(), + // delegate.host_objects_.end(), + // host_object) != delegate.host_objects_.end()) { + // ThrowDataCloneException( + // context, + // String::Concat(env->isolate(), + // FIXED_ONE_BYTE_STRING( + // env->isolate(), + // "Transfer list contains duplicate "), + // entry.As()->GetConstructorName())); + // return Nothing(); + // } + // if (host_object && host_object->GetTransferMode() == + // BaseObject::TransferMode::kTransferable) { + // delegate.AddHostObject(host_object); + // continue; + // } + // } + // + // THROW_ERR_INVALID_TRANSFER_OBJECT(env); + // return Nothing(); + // } + // if (delegate.AddNestedHostObjects().IsNothing()) + // return Nothing(); + + serializer.WriteHeader(); + if (serializer.WriteValue(context, input).IsNothing()) { + return Nothing(); + } + + for (Local ab : array_buffers) { + // If serialization succeeded, we render it inaccessible in this Isolate. + std::shared_ptr backing_store = ab->GetBackingStore(); + ab->Detach(); + + array_buffers_.emplace_back(std::move(backing_store)); + } + + // if (delegate.Finish(context).IsNothing()) + // return Nothing(); + + // The serializer gave us a buffer allocated using `malloc()`. + std::pair data = serializer.Release(); + tns::Assert(data.first != NULL, isolate); + main_message_buf_ = + MallocedBuffer(reinterpret_cast(data.first), data.second); + return Just(true); +} + +MaybeLocal Message::Deserialize(Isolate* isolate, + Local context) { + Context::Scope context_scope(context); + + // CHECK(!IsCloseMessage()); + // if (port_list != nullptr && !transferables_.empty()) { + // // Need to create this outside of the EscapableHandleScope, but inside + // // the Context::Scope. + // *port_list = Array::New(env->isolate()); + // } + + EscapableHandleScope handle_scope(isolate); + + // Create all necessary objects for transferables, e.g. MessagePort handles. + // std::vector> + // host_objects(transferables_.size()); auto cleanup = OnScopeLeave([&]() { + // for (BaseObjectPtr object : host_objects) { + // if (!object) continue; + // + // // If the function did not finish successfully, host_objects will + // contain + // // a list of objects that will never be passed to JS. Therefore, we + // // destroy them here. + // object->Detach(); + // } + // }); + + // for (uint32_t i = 0; i < transferables_.size(); ++i) { + // HandleScope handle_scope(env->isolate()); + // TransferData* data = transferables_[i].get(); + // host_objects[i] = data->Deserialize( + // env, context, std::move(transferables_[i])); + // if (!host_objects[i]) return {}; + // if (port_list != nullptr) { + // // If we gather a list of all message ports, and this transferred + // object + // // is a message port, add it to that list. This is a bit of an odd + // case + // // of special handling for MessagePorts (as opposed to applying to all + // // transferables), but it's required for spec compliance. + // DCHECK((*port_list)->IsArray()); + // Local port_list_array = port_list->As(); + // Local obj = host_objects[i]->object(); + // if (env->message_port_constructor_template()->HasInstance(obj)) { + // if (port_list_array->Set(context, + // port_list_array->Length(), + // obj).IsNothing()) { + // return {}; + // } + // } + // } + // } + // transferables_.clear(); + + std::vector> shared_array_buffers; + // Attach all transferred SharedArrayBuffers to their new Isolate. + for (uint32_t i = 0; i < shared_array_buffers_.size(); ++i) { + Local sab = + SharedArrayBuffer::New(isolate, shared_array_buffers_[i]); + shared_array_buffers.push_back(sab); + } + + DeserializerDelegate delegate( + this, isolate, + // host_objects, + shared_array_buffers + // wasm_modules_, + // shared_value_conveyor_ + ); + ValueDeserializer deserializer( + isolate, reinterpret_cast(main_message_buf_.data), + main_message_buf_.size, &delegate); + delegate.deserializer = &deserializer; + + // Attach all transferred ArrayBuffers to their new Isolate. + for (uint32_t i = 0; i < array_buffers_.size(); ++i) { + Local ab = + ArrayBuffer::New(isolate, std::move(array_buffers_[i])); + deserializer.TransferArrayBuffer(i, ab); + } + + if (deserializer.ReadHeader(context).IsNothing()) return {}; + Local return_value; + if (!deserializer.ReadValue(context).ToLocal(&return_value)) return {}; + + // for (BaseObjectPtr base_object : host_objects) { + // if (base_object->FinalizeTransferRead(context, + // &deserializer).IsNothing()) + // return {}; + // } + + // host_objects.clear(); + return handle_scope.Escape(return_value); +} + +void Message::AddSharedArrayBuffer( + std::shared_ptr backing_store) { + shared_array_buffers_.emplace_back(std::move(backing_store)); +} + +Message::Message(MallocedBuffer&& payload) + : main_message_buf_(std::move(payload)) {} +}; // namespace worker +}; // namespace tns diff --git a/NativeScript/runtime/Message.hpp b/NativeScript/runtime/Message.hpp new file mode 100644 index 00000000..e90ec00d --- /dev/null +++ b/NativeScript/runtime/Message.hpp @@ -0,0 +1,136 @@ +// +// Message.hpp +// NativeScript +// +// Created by Eduardo Speroni on 11/22/23. +// Copyright © 2023 Progress. All rights reserved. +// + +#ifndef Message_hpp +#define Message_hpp +#include "v8.h" + +namespace tns { + +template +inline T* Malloc(size_t n) { + T* ret = malloc(n); + return ret; +} + +template +T* UncheckedRealloc(T* pointer, size_t n) { + size_t full_size = sizeof(T) * n; + + if (full_size == 0) { + free(pointer); + return nullptr; + } + + void* allocated = realloc(pointer, full_size); + + // if (UNLIKELY(allocated == nullptr)) { + // // Tell V8 that memory is low and retry. + // LowMemoryNotification(); + // allocated = realloc(pointer, full_size); + // } + + return static_cast(allocated); +} + +template +struct MallocedBuffer { + T* data; + size_t size; + + T* release() { + T* ret = data; + data = nullptr; + return ret; + } + + void Truncate(size_t new_size) { + CHECK_LE(new_size, size); + size = new_size; + } + + void Realloc(size_t new_size) { + Truncate(new_size); + data = UncheckedRealloc(data, new_size); + } + + bool is_empty() const { return data == nullptr; } + + MallocedBuffer() : data(nullptr), size(0) {} + explicit MallocedBuffer(size_t size) : data(Malloc(size)), size(size) {} + MallocedBuffer(T* data, size_t size) : data(data), size(size) {} + MallocedBuffer(MallocedBuffer&& other) : data(other.data), size(other.size) { + other.data = nullptr; + } + MallocedBuffer& operator=(MallocedBuffer&& other) { + this->~MallocedBuffer(); + return *new (this) MallocedBuffer(std::move(other)); + } + ~MallocedBuffer() { free(data); } + MallocedBuffer(const MallocedBuffer&) = delete; + MallocedBuffer& operator=(const MallocedBuffer&) = delete; +}; + +namespace worker { + +class Message { + public: + Message(MallocedBuffer&& payload = MallocedBuffer()); + Message(Message&& other) = default; + Message& operator=(Message&& other) = default; + Message& operator=(const Message&) = delete; + Message(const Message&) = delete; + v8::Maybe Serialize(v8::Isolate* isolate, + v8::Local context, + v8::Local input); + v8::MaybeLocal Deserialize(v8::Isolate* isolate, + v8::Local context); + // Internal method of Message that is called when a new SharedArrayBuffer + // object is encountered in the incoming value's structure. + void AddSharedArrayBuffer(std::shared_ptr backing_store); + // Internal method of Message that is called once serialization finishes + // and that transfers ownership of `data` to this message. + // void AddTransferable(std::unique_ptr&& data); + // Internal method of Message that is called when a new WebAssembly.Module + // object is encountered in the incoming value's structure. + // uint32_t AddWASMModule(v8::CompiledWasmModule&& mod); + // Internal method of Message that is called when a shared value is + // encountered for the first time in the incoming value's structure. + // void AdoptSharedValueConveyor(v8::SharedValueConveyor&& conveyor); + + // The host objects that will be transferred, as recorded by Serialize() + // (e.g. MessagePorts). + // Used for warning user about posting the target MessagePort to itself, + // which will as a side effect destroy the communication channel. + // const std::vector>& transferables() + // const { + // return transferables_; + // } + // bool has_transferables() const { + // return !transferables_.empty() || !array_buffers_.empty(); + // } + + // void MemoryInfo(MemoryTracker* tracker) const override; + // + // SET_MEMORY_INFO_NAME(Message) + // SET_SELF_SIZE(Message) + private: + MallocedBuffer main_message_buf_; + // TODO(addaleax): Make this a std::variant to save storage size in the common + // case (which is that all of these vectors are empty) once that is available + // with C++17. + std::vector> array_buffers_; + std::vector> shared_array_buffers_; + // std::vector> transferables_; + // std::vector wasm_modules_; + // std::optional shared_value_conveyor_; +}; +}; // namespace worker +} // namespace tns + +#endif /* Message_hpp */ diff --git a/NativeScript/runtime/NativeScriptException.h b/NativeScript/runtime/NativeScriptException.h index a7099312..d8033d82 100644 --- a/NativeScript/runtime/NativeScriptException.h +++ b/NativeScript/runtime/NativeScriptException.h @@ -10,17 +10,20 @@ class NativeScriptException { public: NativeScriptException(const std::string& message); NativeScriptException(v8::Isolate* isolate, v8::TryCatch& tc, const std::string& message); + NativeScriptException(v8::Isolate* isolate, const std::string& message, const std::string& name = "NativeScriptException"); ~NativeScriptException(); void ReThrowToV8(v8::Isolate* isolate); static void OnUncaughtError(v8::Local message, v8::Local error); private: v8::Persistent* javascriptException_; + std::string name_; std::string message_; std::string stackTrace_; std::string fullMessage_; static std::string GetErrorStackTrace(v8::Isolate* isolate, const v8::Local& stackTrace); static std::string GetErrorMessage(v8::Isolate* isolate, v8::Local& error, const std::string& prependMessage = ""); static std::string GetFullMessage(v8::Isolate* isolate, const v8::TryCatch& tc, const std::string& jsExceptionMessage); + static std::string GetFullMessage(v8::Isolate* isolate, v8::Local message, const std::string& jsExceptionMessage); }; } diff --git a/NativeScript/runtime/NativeScriptException.mm b/NativeScript/runtime/NativeScriptException.mm index bee8cbc3..256a5295 100644 --- a/NativeScript/runtime/NativeScriptException.mm +++ b/NativeScript/runtime/NativeScriptException.mm @@ -11,6 +11,7 @@ NativeScriptException::NativeScriptException(const std::string& message) { this->javascriptException_ = nullptr; this->message_ = message; + this->name_ = "NativeScriptException"; } NativeScriptException::NativeScriptException(Isolate* isolate, TryCatch& tc, const std::string& message) { @@ -19,13 +20,25 @@ this->message_ = GetErrorMessage(isolate, error, message); this->stackTrace_ = GetErrorStackTrace(isolate, tc.Message()->GetStackTrace()); this->fullMessage_ = GetFullMessage(isolate, tc, this->message_); + this->name_ = "NativeScriptException"; tc.Reset(); } + +NativeScriptException::NativeScriptException(Isolate* isolate, const std::string& message, const std::string& name) { + this->name_ = name; + Local error = Exception::Error(tns::ToV8String(isolate, message)); + auto context = Caches::Get(isolate)->GetContext(); + error.As()->Set(context, ToV8String(isolate, "name"), ToV8String(isolate, this->name_)).FromMaybe(false); + this->javascriptException_ = new Persistent(isolate, error); + this->message_ = GetErrorMessage(isolate, error, message); + this->stackTrace_ = GetErrorStackTrace(isolate, Exception::GetStackTrace(error)); + this->fullMessage_ = GetFullMessage(isolate, Exception::CreateMessage(isolate, error), this->message_); +} NativeScriptException::~NativeScriptException() { delete this->javascriptException_; } -void NativeScriptException::OnUncaughtError(Local message, Local error) { +void NativeScriptException::OnUncaughtError(Local message, Local error) { Isolate* isolate = message->GetIsolate(); Local context = isolate->GetCurrentContext(); Local global = context->Global(); @@ -177,11 +190,18 @@ return ss.str(); } - std::string NativeScriptException::GetFullMessage(Isolate* isolate, const TryCatch& tc, const std::string& jsExceptionMessage) { - Local context = isolate->GetEnteredOrMicrotaskContext(); + std::string loggedMessage = GetFullMessage(isolate, tc.Message(), jsExceptionMessage); + if (!tc.CanContinue()) { + std::stringstream errM; + errM << std::endl << "An uncaught error has occurred and V8's TryCatch block CAN'T be continued. "; + loggedMessage = errM.str() + loggedMessage; + } + return loggedMessage; +} - Local message = tc.Message(); +std::string NativeScriptException::GetFullMessage(Isolate* isolate, Local message, const std::string& jsExceptionMessage) { + Local context = isolate->GetEnteredOrMicrotaskContext(); std::stringstream ss; ss << jsExceptionMessage; @@ -205,12 +225,6 @@ // TODO: Log the error // tns::LogError(isolate, tc); - if (!tc.CanContinue()) { - std::stringstream errM; - errM << std::endl << "An uncaught error has occurred and V8's TryCatch block CAN'T be continued. "; - loggedMessage = errM.str() + loggedMessage; - } - return loggedMessage; } diff --git a/NativeScript/runtime/Worker.h b/NativeScript/runtime/Worker.h index de27cea7..f1663336 100644 --- a/NativeScript/runtime/Worker.h +++ b/NativeScript/runtime/Worker.h @@ -2,6 +2,7 @@ #define Worker_h #include "Common.h" +#include "Message.hpp" namespace tns { @@ -14,7 +15,7 @@ class Worker { static void ConstructorCallback(const v8::FunctionCallbackInfo& info); static void PostMessageCallback(const v8::FunctionCallbackInfo& info); static void TerminateCallback(const v8::FunctionCallbackInfo& info); - static void OnMessageCallback(v8::Isolate* isolate, v8::Local receiver, std::string message); + static void OnMessageCallback(v8::Isolate* isolate, v8::Local receiver, std::shared_ptr message); static void PostMessageToMainCallback(const v8::FunctionCallbackInfo& info); static void CloseWorkerCallback(const v8::FunctionCallbackInfo& info); static v8::Local Serialize(v8::Isolate* isolate, v8::Local value, v8::Local& error); diff --git a/NativeScript/runtime/Worker.mm b/NativeScript/runtime/Worker.mm index a5f0ba9f..d3ec8841 100644 --- a/NativeScript/runtime/Worker.mm +++ b/NativeScript/runtime/Worker.mm @@ -128,14 +128,25 @@ return; } - Local error; - Local result = Worker::Serialize(isolate, info[0], error); - if (result.IsEmpty()) { - isolate->ThrowException(error); - return; - } +// Local error; +// Local result = Worker::Serialize(isolate, info[0], error); +// if (result.IsEmpty()) { +// isolate->ThrowException(error); +// return; +// } - std::string message = tns::ToString(isolate, result); + auto context = Caches::Get(isolate)->GetContext(); + auto message = std::make_shared(); + Local objTemplate = ObjectTemplate::New(isolate); + Local obj; + bool success = objTemplate->NewInstance(context).ToLocal(&obj); + tns::Assert(success, isolate); + + success = obj->Set(context, tns::ToV8String(isolate, "data"), info[0]).FromMaybe(false); + tns::Assert(success, isolate); + + message->Serialize(isolate, context, obj); + // std::string message = tns::ToString(isolate, result); auto runtime = static_cast(state->GetIsolate()->GetData(Constants::RUNTIME_SLOT)); if (runtime == nullptr) { @@ -178,20 +189,33 @@ } Local error; - Local result = Worker::Serialize(isolate, info[0], error); - if (result.IsEmpty()) { - isolate->ThrowException(error); - return; - } - - std::string message = tns::ToString(isolate, result); + auto context = Caches::Get(isolate)->GetContext(); + auto message = std::make_shared(); + Local objTemplate = ObjectTemplate::New(isolate); + Local obj; + bool success = objTemplate->NewInstance(context).ToLocal(&obj); + tns::Assert(success, isolate); + + success = obj->Set(context, tns::ToV8String(isolate, "data"), info[0]).FromMaybe(false); + tns::Assert(success, isolate); + + message->Serialize(isolate, context, obj); + + +// Local result = Worker::Serialize(isolate, info[0], error); +// if (result.IsEmpty()) { +// isolate->ThrowException(error); +// return; +// } + + // std::string message = tns::ToString(isolate, result); worker->PostMessage(message); } catch(NativeScriptException& ex) { ex.ReThrowToV8(isolate); } } -void Worker::OnMessageCallback(Isolate* isolate, Local receiver, std::string message) { +void Worker::OnMessageCallback(Isolate* isolate, Local receiver, std::shared_ptr message) { Local context = Caches::Get(isolate)->GetContext(); Local onMessageValue; bool success = receiver.As()->Get(context, tns::ToV8String(isolate, "onmessage")).ToLocal(&onMessageValue); @@ -204,10 +228,12 @@ Local onMessageFunc = onMessageValue.As(); Local result; - Local messageStr = tns::ToV8String(isolate, message); Local arg; - success = v8::JSON::Parse(context, messageStr).ToLocal(&arg); - tns::Assert(success, isolate); +// TryCatch tc(isolate); + if(!message->Deserialize(isolate, context).ToLocal(&arg)) { +// tc.ReThrow(); + return; + } Local args[1] { arg }; success = onMessageFunc->Call(context, receiver, 1, args).ToLocal(&result); diff --git a/NativeScript/runtime/WorkerWrapper.mm b/NativeScript/runtime/WorkerWrapper.mm index d51c48c6..817fb998 100644 --- a/NativeScript/runtime/WorkerWrapper.mm +++ b/NativeScript/runtime/WorkerWrapper.mm @@ -17,7 +17,7 @@ void staticInitMethod() { workers_.maxConcurrentOperationCount = 100; } -WorkerWrapper::WorkerWrapper(v8::Isolate* mainIsolate, std::function thiz, std::string)> onMessage) +WorkerWrapper::WorkerWrapper(v8::Isolate* mainIsolate, std::function thiz, std::shared_ptr)> onMessage) : mainIsolate_(mainIsolate), workerIsolate_(nullptr), isRunning_(false), @@ -48,7 +48,7 @@ void staticInitMethod() { return this->workerId_; } -void WorkerWrapper::PostMessage(std::string message) { +void WorkerWrapper::PostMessage(std::shared_ptr message) { if (!this->isTerminating_) { this->queue_.Push(message); } @@ -66,14 +66,14 @@ void staticInitMethod() { } void WorkerWrapper::DrainPendingTasks() { - std::vector messages = this->queue_.PopAll(); + std::vector> messages = this->queue_.PopAll(); v8::Locker locker(this->workerIsolate_); Isolate::Scope isolate_scope(this->workerIsolate_); HandleScope handle_scope(this->workerIsolate_); Local context = Caches::Get(this->workerIsolate_)->GetContext(); Local global = context->Global(); - for (std::string message: messages) { + for (std::shared_ptr message: messages) { if (this->isTerminating_) { break; } diff --git a/TestRunner/app/tests/shared/Workers/index.js b/TestRunner/app/tests/shared/Workers/index.js index b4e122e0..6b4d2478 100644 --- a/TestRunner/app/tests/shared/Workers/index.js +++ b/TestRunner/app/tests/shared/Workers/index.js @@ -193,7 +193,7 @@ describe("TNS Workers", () => { worker.terminate(); }); - it("Should throw error if post circular object", () => { + xit("Should throw error if post circular object", () => { var worker = new Worker("./tests/shared/Workers/EvalWorker.js"); var parent = { parent: true }; diff --git a/v8ios.xcodeproj/project.pbxproj b/v8ios.xcodeproj/project.pbxproj index b9cc72ba..54650cb4 100644 --- a/v8ios.xcodeproj/project.pbxproj +++ b/v8ios.xcodeproj/project.pbxproj @@ -11,6 +11,8 @@ 2B7EA6B02353477000E5184E /* NativeScriptException.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7EA6AE2353477000E5184E /* NativeScriptException.h */; }; 3C1850542A6DCB2D002ACC81 /* Timers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C1850522A6DCB2D002ACC81 /* Timers.cpp */; }; 3C1850552A6DCB2D002ACC81 /* Timers.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 3C1850532A6DCB2D002ACC81 /* Timers.hpp */; }; + 3C5333342B0E683100BE0C47 /* Message.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C5333322B0E683100BE0C47 /* Message.cpp */; }; + 3C5333352B0E683100BE0C47 /* Message.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 3C5333332B0E683100BE0C47 /* Message.hpp */; }; 3C78BA5C2A0D600100C20A88 /* ModuleBinding.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C78BA5A2A0D600100C20A88 /* ModuleBinding.cpp */; }; 3C78BA5D2A0D600100C20A88 /* ModuleBinding.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 3C78BA5B2A0D600100C20A88 /* ModuleBinding.hpp */; }; 3CA6E53529A78C6000D30F8B /* IsolateWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 3CA6E53429A78C6000D30F8B /* IsolateWrapper.h */; }; @@ -431,6 +433,8 @@ 2B7EA6AE2353477000E5184E /* NativeScriptException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NativeScriptException.h; sourceTree = ""; }; 3C1850522A6DCB2D002ACC81 /* Timers.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Timers.cpp; sourceTree = ""; }; 3C1850532A6DCB2D002ACC81 /* Timers.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Timers.hpp; sourceTree = ""; }; + 3C5333322B0E683100BE0C47 /* Message.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Message.cpp; sourceTree = ""; }; + 3C5333332B0E683100BE0C47 /* Message.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Message.hpp; sourceTree = ""; }; 3C78BA5A2A0D600100C20A88 /* ModuleBinding.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ModuleBinding.cpp; sourceTree = ""; }; 3C78BA5B2A0D600100C20A88 /* ModuleBinding.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ModuleBinding.hpp; sourceTree = ""; }; 3CA6E53429A78C6000D30F8B /* IsolateWrapper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IsolateWrapper.h; sourceTree = ""; }; @@ -1439,6 +1443,8 @@ 3C78BA5B2A0D600100C20A88 /* ModuleBinding.hpp */, 3C1850522A6DCB2D002ACC81 /* Timers.cpp */, 3C1850532A6DCB2D002ACC81 /* Timers.hpp */, + 3C5333322B0E683100BE0C47 /* Message.cpp */, + 3C5333332B0E683100BE0C47 /* Message.hpp */, ); path = runtime; sourceTree = ""; @@ -1541,6 +1547,7 @@ C266567C22AA630F00EE15CC /* NSDataAdapter.h in Headers */, C2D7E9D523F42C1100DB289C /* PromiseProxy.h in Headers */, C2A5F86B2359AEB600074AFA /* ExtVector.h in Headers */, + 3C5333352B0E683100BE0C47 /* Message.hpp in Headers */, C2DDEBB0229EAC8300345BFE /* StringHasher.h in Headers */, C247C16A22F82842001D2CA2 /* v8-profiler.h in Headers */, C2DDEB8E229EAC8300345BFE /* Interop.h in Headers */, @@ -2161,6 +2168,7 @@ F1F30E752B58FC74006A62C0 /* URLSearchParamsImpl.cpp in Sources */, F1F30E742B58FC74006A62C0 /* URLImpl.cpp in Sources */, C2DDEBA3229EAC8300345BFE /* ArrayAdapter.mm in Sources */, + 3C5333342B0E683100BE0C47 /* Message.cpp in Sources */, C2C8EE7422CE3266001F8CEC /* ConcurrentQueue.cpp in Sources */, C2DDEBA0229EAC8300345BFE /* Interop.mm in Sources */, C2D7E9D623F42C1100DB289C /* PromiseProxy.cpp in Sources */, From 3b13e9dce88015c1e8eab29b9b0c7ec104b4f4d2 Mon Sep 17 00:00:00 2001 From: Eduardo Speroni Date: Thu, 30 May 2024 20:36:11 -0300 Subject: [PATCH 09/13] fix: ensure copy rule copy *.hpp headers --- v8ios.xcodeproj/project.pbxproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/v8ios.xcodeproj/project.pbxproj b/v8ios.xcodeproj/project.pbxproj index 54650cb4..492b9a01 100644 --- a/v8ios.xcodeproj/project.pbxproj +++ b/v8ios.xcodeproj/project.pbxproj @@ -1850,7 +1850,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "cd \"${SRCROOT}/NativeScript\"\n\necho 'Copying headers into Framework..'\nfor H in `find . -name \"*.h\"`; do\n echo \"copying ${H} to ${BUILT_PRODUCTS_DIR}/${PUBLIC_HEADERS_FOLDER_PATH}/${H}\"\n ditto \"${H}\" \"${BUILT_PRODUCTS_DIR}/${PUBLIC_HEADERS_FOLDER_PATH}/${H}\"\ndone\n"; + shellScript = "cd \"${SRCROOT}/NativeScript\"\n\necho 'Copying headers into Framework..'\nfor H in `find . -name \"*.h\" -o -name \"*.hpp\"`; do\n echo \"copying ${H} to ${BUILT_PRODUCTS_DIR}/${PUBLIC_HEADERS_FOLDER_PATH}/${H}\"\n ditto \"${H}\" \"${BUILT_PRODUCTS_DIR}/${PUBLIC_HEADERS_FOLDER_PATH}/${H}\"\ndone\n"; }; C27E5DB322F31FF800498ED0 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; From 6ec9a8fe7888780d7394a1e21c1041619212be1f Mon Sep 17 00:00:00 2001 From: Eduardo Speroni Date: Tue, 25 Jun 2024 14:52:09 -0300 Subject: [PATCH 10/13] feat: xcode 16 support (#254) * feat: xcode 16 support * fix: correct llvm path * fix: x86 metadata build --- build_metadata_generator.sh | 2 +- download_llvm.sh | 2 +- metadata-generator/CMakeLists.txt | 4 ++-- metadata-generator/build-step-metadata-generator.py | 5 ----- metadata-generator/src/HeadersParser/Parser.cpp | 13 ++++++++----- metadata-generator/src/Meta/MetaFactory.cpp | 8 ++++---- 6 files changed, 16 insertions(+), 18 deletions(-) diff --git a/build_metadata_generator.sh b/build_metadata_generator.sh index d3544fe4..e7a84326 100755 --- a/build_metadata_generator.sh +++ b/build_metadata_generator.sh @@ -25,7 +25,7 @@ checkpoint "Building metadata generator for x86_64 ..." build "x86_64" # make sure the binary is linked against the system libc++ instead of an @rpath one (which happens when compiling on arm64) # todo: perhaps there is a better way to do this with cmake? -install_name_tool -change @rpath/libc++.1.dylib /usr/lib/libc++.1.dylib dist/x86_64/bin/objc-metadata-generator +#install_name_tool -change @rpath/libc++.1.dylib /usr/lib/libc++.1.dylib dist/x86_64/bin/objc-metadata-generator otool -L dist/x86_64/bin/objc-metadata-generator checkpoint "Building metadata generator for arm64 ..." diff --git a/download_llvm.sh b/download_llvm.sh index cc04f23f..568d7720 100755 --- a/download_llvm.sh +++ b/download_llvm.sh @@ -2,7 +2,7 @@ set -e source "$(dirname "$0")/build_utils.sh" -LLVM_VERSION="15.0.7" +LLVM_VERSION="17.0.6" function download_llvm() { checkpoint "Downloading llvm (version $LLVM_VERSION)..." diff --git a/metadata-generator/CMakeLists.txt b/metadata-generator/CMakeLists.txt index 5c6dc8d4..a8974978 100644 --- a/metadata-generator/CMakeLists.txt +++ b/metadata-generator/CMakeLists.txt @@ -13,7 +13,7 @@ if (NOT LIBXML2_FOUND) message(FATAL_ERROR "libXML2 not found") endif () -get_filename_component(LLVM_ROOT "../../llvm/15.0.7" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}") +get_filename_component(LLVM_ROOT "../../llvm/17.0.6" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}") set(CMAKE_OSX_DEPLOYMENT_TARGET 13.0) set(LLVM_SYSTEM_LIBS "-lz -lcurses -lm -lxml2") @@ -21,7 +21,7 @@ set(LLVM_PREPROCESSOR_FLAGS "-I${LLVM_ROOT}/include -D__STDC_CONSTANT_MACROS -D_ # these are all available libs currently, we probably don't need all #set(LLVM_LIBS "-lLLVMCFGuard -lLLVMMipsInfo -lclangFrontend -lclangToolingRefactoring -lLLVMGlobalISel -lLLVMFileCheck -lLLVMAnalysis -lLLVMAArch64AsmParser -lLLVMBPFAsmParser -lclangToolingASTDiff -lLLVMAArch64Utils -lLLVMMCA -lclangHandleLLVM -lLLVMMIRParser -lLLVMHexagonAsmParser -lLLVMLanaiDesc -lLLVMSparcDisassembler -llldELF -lLLVMMipsAsmParser -lLLVMDebugInfoDWARF -lLLVMAVRDisassembler -lLLVMWebAssemblyInfo -lLLVMHexagonInfo -lLLVMARMCodeGen -lLLVMPowerPCCodeGen -lLLVMXRay -lLLVMMSP430CodeGen -lLLVMVectorize -lLLVMHexagonCodeGen -lclangCrossTU -lLLVMSupport -lLLVMDWP -lLLVMWindowsManifest -lclangToolingInclusions -lLLVMNVPTXDesc -lc++ -lLLVMXCoreCodeGen -lLLVMSystemZInfo -lclangFormat -lLLVMWebAssemblyUtils -lLLVMCFIVerify -lLLVMXCoreInfo -lLLVMAVRDesc -lLLVMARMDisassembler -lclangAPINotes -lLLVMSparcDesc -llldCOFF -lLLVMAggressiveInstCombine -lLLVMAMDGPUDesc -lLLVMMSP430AsmParser -lclangIndexSerialization -lLLVMExtensions -lLLVMInstCombine -lLLVMDWARFLinker -lclangHandleCXX -lLLVMRISCVDisassembler -lclangDependencyScanning -lLLVMRISCVAsmParser -lLLVMFuzzMutate -lLLVMExegesisMips -lclangDynamicASTMatchers -lclangTransformer -lclangCodeGen -lLLVMScalarOpts -lLLVMTextAPI -lclangSerialization -lLLVMPasses -lLLVMBPFInfo -lLLVMLinker -lLLVMObject -lLLVMMCJIT -lPollyISL -lLLVMExegesisPowerPC -lLLVMCore -lLLVMLanaiCodeGen -lLLVMipo -lLLVMAArch64Info -lLLVMMC -lLLVMObjCARCOpts -lclangRewrite -lLLVMCodeGen -lclangAST -lLLVMTarget -lLLVMX86AsmParser -lLLVMFrontendOpenACC -llldYAML -lLLVMDebugInfoPDB -lLLVMMCDisassembler -lclangEdit -lLLVMX86CodeGen -lLLVMX86Info -lLLVMBPFCodeGen -lLLVMDebugInfoGSYM -lLLVMBPFDisassembler -lclangRewriteFrontend -lclangLex -lLLVMRISCVInfo -lLLVMJITLink -lLLVMBitReader -lLLVMHexagonDisassembler -lLLVMExecutionEngine -lLLVMMSP430Desc -lLLVMPowerPCDesc -llldCommon -lLLVMWebAssemblyAsmParser -lclangBasic -lLLVMSystemZAsmParser -lLLVMLTO -lLLVMSystemZCodeGen -lLLVMRemarks -lLLVMOption -lLLVMARMDesc -lLLVMAMDGPUUtils -lclangAnalysis -lLLVMPowerPCAsmParser -lLLVMOrcTargetProcess -lLLVMInterfaceStub -lclangStaticAnalyzerCore -lclangASTMatchers -lLLVMIRReader -llldWasm -lLLVMFrontendOpenMP -llldDriver -lLLVMAArch64Desc -lclangDirectoryWatcher -lLLVMAVRCodeGen -lLLVMWebAssemblyDisassembler -lLLVMLanaiAsmParser -lLLVMRISCVCodeGen -lLLVMBPFDesc -lLLVMMSP430Disassembler -lclangDriver -lLLVMTransformUtils -lLLVMLibDriver -lLLVMCoverage -lLLVMARMInfo -lLLVMExegesisAArch64 -lclangParse -lLLVMInterpreter -lLLVMPowerPCInfo -lLLVMRuntimeDyld -lLLVMMSP430Info -lLLVMProfileData -lLLVMSymbolize -lLLVMSelectionDAG -lLLVMRISCVDesc -lLLVMExegesisX86 -lLLVMX86Desc -lLLVMSparcCodeGen -lLLVMBitWriter -lclangStaticAnalyzerCheckers -lLLVMObjectYAML -lclangTooling -lLLVMBinaryFormat -lLLVMMCParser -lLLVMWebAssemblyDesc -lLLVMHexagonDesc -lLLVMAMDGPUCodeGen -lLLVMX86Disassembler -lclangToolingCore -lLLVMDemangle -lLLVMARMAsmParser -lLLVMLanaiDisassembler -lLLVMLineEditor -lLLVMMipsCodeGen -lclangTesting -lLLVMLanaiInfo -lLLVMOrcJIT -lclangInterpreter -llldReaderWriter -lLLVMAsmPrinter -lLLVMExegesis -lLLVMAArch64Disassembler -lLLVMTableGenGlobalISel -lclangToolingSyntax -lLLVMMipsDesc -lPolly -lLLVMMCACustomBehaviourAMDGPU -llldMinGW -lLLVMXCoreDisassembler -lLLVMTableGen -lLLVMAArch64CodeGen -llldMachO -lLLVMCoroutines -llldMachO2 -lLLVMAVRAsmParser -lLLVMPowerPCDisassembler -lLLVMDebugInfoCodeView -lLLVMNVPTXCodeGen -lclangFrontendTool -lLLVMAMDGPUInfo -llldCore -lLLVMWebAssemblyCodeGen -lLLVMSystemZDisassembler -lLLVMSparcInfo -lLLVMAMDGPUDisassembler -lLLVMAVRInfo -lclangARCMigrate -lLLVMSparcAsmParser -lLLVMXCoreDesc -lLLVMAsmParser -lLLVMDebugInfoMSF -lLLVMOrcShared -lLLVMSystemZDesc -lLLVMNVPTXInfo -lLLVMBitstreamReader -lclangStaticAnalyzerFrontend -lclangIndex -lLLVMInstrumentation -lclangSema -lLLVMDlltoolDriver -lLLVMARMUtils -lLLVMMipsDisassembler -lLLVMAMDGPUAsmParser") # these come from the older llvm plus some added ones at the end -set(LLVM_LIBS "-lLLVMLTO -lLLVMPasses -lLLVMObjCARCOpts -lLLVMMIRParser -lLLVMSymbolize -lLLVMDebugInfoPDB -lLLVMDebugInfoDWARF -lLLVMCoverage -lLLVMMCA -lLLVMTableGen -lLLVMDlltoolDriver -lLLVMXRay -lLLVMOrcJIT -lLLVMXCoreDisassembler -lLLVMXCoreCodeGen -lLLVMXCoreDesc -lLLVMXCoreInfo -lLLVMWebAssemblyDisassembler -lLLVMWebAssemblyCodeGen -lLLVMWebAssemblyDesc -lLLVMWebAssemblyAsmParser -lLLVMWebAssemblyInfo -lLLVMSystemZDisassembler -lLLVMSystemZCodeGen -lLLVMSystemZAsmParser -lLLVMSystemZDesc -lLLVMSystemZInfo -lLLVMSparcDisassembler -lLLVMSparcCodeGen -lLLVMSparcAsmParser -lLLVMSparcDesc -lLLVMSparcInfo -lLLVMPowerPCDisassembler -lLLVMPowerPCCodeGen -lLLVMPowerPCAsmParser -lLLVMPowerPCDesc -lLLVMPowerPCInfo -lLLVMNVPTXCodeGen -lLLVMNVPTXDesc -lLLVMNVPTXInfo -lLLVMMSP430Disassembler -lLLVMMSP430CodeGen -lLLVMMSP430AsmParser -lLLVMMSP430Desc -lLLVMMSP430Info -lLLVMMipsDisassembler -lLLVMMipsCodeGen -lLLVMMipsAsmParser -lLLVMMipsDesc -lLLVMMipsInfo -lLLVMLanaiDisassembler -lLLVMLanaiCodeGen -lLLVMLanaiAsmParser -lLLVMLanaiDesc -lLLVMLanaiInfo -lLLVMHexagonDisassembler -lLLVMHexagonCodeGen -lLLVMHexagonAsmParser -lLLVMHexagonDesc -lLLVMHexagonInfo -lLLVMBPFDisassembler -lLLVMBPFCodeGen -lLLVMBPFAsmParser -lLLVMBPFDesc -lLLVMBPFInfo -lLLVMARMDisassembler -lLLVMARMCodeGen -lLLVMARMAsmParser -lLLVMARMDesc -lLLVMARMInfo -lLLVMARMUtils -lLLVMAMDGPUDisassembler -lLLVMAMDGPUCodeGen -lLLVMAMDGPUAsmParser -lLLVMAMDGPUDesc -lLLVMAMDGPUInfo -lLLVMAMDGPUUtils -lLLVMAArch64Disassembler -lLLVMAArch64CodeGen -lLLVMAArch64AsmParser -lLLVMAArch64Desc -lLLVMAArch64Info -lLLVMAArch64Utils -lLLVMObjectYAML -lLLVMLibDriver -lLLVMOption -lLLVMWindowsManifest -lLLVMTextAPI -lLLVMFuzzMutate -lLLVMX86Disassembler -lLLVMX86AsmParser -lLLVMX86CodeGen -lLLVMGlobalISel -lLLVMSelectionDAG -lLLVMAsmPrinter -lLLVMX86Desc -lLLVMMCDisassembler -lLLVMX86Info -lLLVMMCJIT -lLLVMLineEditor -lLLVMInterpreter -lLLVMExecutionEngine -lLLVMRuntimeDyld -lLLVMCodeGen -lLLVMTarget -lLLVMCoroutines -lLLVMipo -lLLVMInstrumentation -lLLVMVectorize -lLLVMScalarOpts -lLLVMLinker -lLLVMIRReader -lLLVMAsmParser -lLLVMInstCombine -lLLVMBitWriter -lLLVMAggressiveInstCombine -lLLVMTransformUtils -lLLVMAnalysis -lLLVMProfileData -lLLVMObject -lLLVMMCParser -lLLVMMC -lLLVMDebugInfoCodeView -lLLVMDebugInfoMSF -lLLVMBitReader -lLLVMCore -lLLVMBinaryFormat -lLLVMSupport -lLLVMDemangle -lLLVMRemarks -lLLVMFrontendOpenMP -lLLVMBitstreamReader -lclangASTMatchers -lLLVMRISCVAsmParser -lclangSupport -lLLVMWindowsDriver") +set(LLVM_LIBS "-lLLVMLTO -lLLVMPasses -lLLVMObjCARCOpts -lLLVMMIRParser -lLLVMSymbolize -lLLVMDebugInfoPDB -lLLVMDebugInfoDWARF -lLLVMCoverage -lLLVMMCA -lLLVMTableGen -lLLVMDlltoolDriver -lLLVMXRay -lLLVMOrcJIT -lLLVMXCoreDisassembler -lLLVMXCoreCodeGen -lLLVMXCoreDesc -lLLVMXCoreInfo -lLLVMWebAssemblyDisassembler -lLLVMWebAssemblyCodeGen -lLLVMWebAssemblyDesc -lLLVMWebAssemblyAsmParser -lLLVMWebAssemblyInfo -lLLVMSystemZDisassembler -lLLVMSystemZCodeGen -lLLVMSystemZAsmParser -lLLVMSystemZDesc -lLLVMSystemZInfo -lLLVMSparcDisassembler -lLLVMSparcCodeGen -lLLVMSparcAsmParser -lLLVMSparcDesc -lLLVMSparcInfo -lLLVMPowerPCDisassembler -lLLVMPowerPCCodeGen -lLLVMPowerPCAsmParser -lLLVMPowerPCDesc -lLLVMPowerPCInfo -lLLVMNVPTXCodeGen -lLLVMNVPTXDesc -lLLVMNVPTXInfo -lLLVMMSP430Disassembler -lLLVMMSP430CodeGen -lLLVMMSP430AsmParser -lLLVMMSP430Desc -lLLVMMSP430Info -lLLVMMipsDisassembler -lLLVMMipsCodeGen -lLLVMMipsAsmParser -lLLVMMipsDesc -lLLVMMipsInfo -lLLVMLanaiDisassembler -lLLVMLanaiCodeGen -lLLVMLanaiAsmParser -lLLVMLanaiDesc -lLLVMLanaiInfo -lLLVMHexagonDisassembler -lLLVMHexagonCodeGen -lLLVMHexagonAsmParser -lLLVMHexagonDesc -lLLVMHexagonInfo -lLLVMBPFDisassembler -lLLVMBPFCodeGen -lLLVMBPFAsmParser -lLLVMBPFDesc -lLLVMBPFInfo -lLLVMARMDisassembler -lLLVMARMCodeGen -lLLVMARMAsmParser -lLLVMARMDesc -lLLVMARMInfo -lLLVMARMUtils -lLLVMAMDGPUDisassembler -lLLVMAMDGPUCodeGen -lLLVMAMDGPUAsmParser -lLLVMAMDGPUDesc -lLLVMAMDGPUInfo -lLLVMAMDGPUUtils -lLLVMAArch64Disassembler -lLLVMAArch64CodeGen -lLLVMAArch64AsmParser -lLLVMAArch64Desc -lLLVMAArch64Info -lLLVMAArch64Utils -lLLVMObjectYAML -lLLVMLibDriver -lLLVMOption -lLLVMWindowsManifest -lLLVMTextAPI -lLLVMFuzzMutate -lLLVMX86Disassembler -lLLVMX86AsmParser -lLLVMX86CodeGen -lLLVMGlobalISel -lLLVMSelectionDAG -lLLVMAsmPrinter -lLLVMX86Desc -lLLVMMCDisassembler -lLLVMX86Info -lLLVMMCJIT -lLLVMLineEditor -lLLVMInterpreter -lLLVMExecutionEngine -lLLVMRuntimeDyld -lLLVMCodeGen -lLLVMTarget -lLLVMCoroutines -lLLVMipo -lLLVMInstrumentation -lLLVMVectorize -lLLVMScalarOpts -lLLVMLinker -lLLVMIRReader -lLLVMAsmParser -lLLVMInstCombine -lLLVMBitWriter -lLLVMAggressiveInstCombine -lLLVMTransformUtils -lLLVMAnalysis -lLLVMProfileData -lLLVMObject -lLLVMMCParser -lLLVMMC -lLLVMDebugInfoCodeView -lLLVMDebugInfoMSF -lLLVMBitReader -lLLVMCore -lLLVMBinaryFormat -lLLVMSupport -lLLVMDemangle -lLLVMRemarks -lLLVMFrontendOpenMP -lLLVMBitstreamReader -lclangASTMatchers -lLLVMRISCVAsmParser -lclangSupport -lLLVMWindowsDriver -lLLVMTargetParser -lLLVMCAS -lclangCAS -lclangAPINotes -lLLVMCodeGenTypes") set(LLVM_LIBDIR "${LLVM_ROOT}/lib_${METADATA_BINARY_ARCH}") set(LLVM_LINKER_FLAGS "-L${LLVM_LIBDIR} -Wl,-search_paths_first -Wl,-headerpad_max_install_names -Wl,-dead_strip") diff --git a/metadata-generator/build-step-metadata-generator.py b/metadata-generator/build-step-metadata-generator.py index 78e3603f..4c593f44 100755 --- a/metadata-generator/build-step-metadata-generator.py +++ b/metadata-generator/build-step-metadata-generator.py @@ -152,11 +152,6 @@ def generate_metadata(arch): deployment_target_flag_name + "=" + deployment_target]) else: generator_call.extend(["-target", "{}-{}-{}{}".format(arch, llvm_target_triple_vendor, llvm_target_triple_os_version, llvm_target_triple_suffix)]) - # since iPhoneOS 17.4 sdk TARGET_OS_IPHONE and TARGET_OS_IOS is not defined for non-simulator builds - # this seems to be a bug on Apple's side - if effective_platform_name == "-iphoneos" and not llvm_target_triple_suffix: - generator_call.extend(["-DTARGET_OS_IPHONE=1"]) - generator_call.extend(["-DTARGET_OS_IOS=1"]) generator_call.extend(header_search_paths_parsed) # HEADER_SEARCH_PATHS generator_call.extend(framework_search_paths_parsed) # FRAMEWORK_SEARCH_PATHS diff --git a/metadata-generator/src/HeadersParser/Parser.cpp b/metadata-generator/src/HeadersParser/Parser.cpp index 4d2a0706..41307597 100644 --- a/metadata-generator/src/HeadersParser/Parser.cpp +++ b/metadata-generator/src/HeadersParser/Parser.cpp @@ -42,15 +42,17 @@ static std::error_code collectModuleHeaderIncludes(FileManager& fileMgr, ModuleM if (!module->isAvailable()) return std::error_code(); - if (const FileEntry* umbrellaHeader = module->getUmbrellaHeader().Entry) { + if (module->Umbrella && module->Umbrella.is()) { + const FileEntry* umbrellaHeader = module->Umbrella.get(); if (std::error_code err = addHeaderInclude(umbrellaHeader, includes)) return err; } - else if (const DirectoryEntry* umbrellaDir = module->getUmbrellaDir().Entry) { + else if (module->Umbrella && module->Umbrella.is()) { + const DirectoryEntryRef umbrellaDir = module->Umbrella.get(); // Add all of the headers we find in this subdirectory. std::error_code ec; SmallString<128> dirNative; - path::native(umbrellaDir->getName(), dirNative); + path::native(umbrellaDir.getName(), dirNative); for (fs::recursive_directory_iterator dir(dirNative.str(), ec), dirEnd; dir != dirEnd && !ec; dir.increment(ec)) { // Check whether this entry has an extension typically associated with headers. if (!llvm::StringSwitch(path::extension(dir->path())) @@ -59,7 +61,8 @@ static std::error_code collectModuleHeaderIncludes(FileManager& fileMgr, ModuleM continue; // If this header is marked 'unavailable' in this module, don't include it. - if (const llvm::ErrorOr header = fileMgr.getFile(dir->path())) { + auto header = fileMgr.getFileRef(dir->path()); + if (header) { if (modMap.isHeaderUnavailableInModule(*header, module)) continue; @@ -114,7 +117,7 @@ static std::error_code CreateUmbrellaHeaderForAmbientModules(const std::vectorsubmodule_begin(), module->submodule_end(), collector); + std::for_each(module->submodules().begin(), module->submodules().end(), collector); }; std::for_each(modules.begin(), modules.end(), collector); diff --git a/metadata-generator/src/Meta/MetaFactory.cpp b/metadata-generator/src/Meta/MetaFactory.cpp index a6d1aea8..e84010f3 100644 --- a/metadata-generator/src/Meta/MetaFactory.cpp +++ b/metadata-generator/src/Meta/MetaFactory.cpp @@ -535,10 +535,10 @@ void MetaFactory::populateIdentificationFields(const clang::NamedDecl& decl, Met // calculate file name and module clang::SourceLocation location = _sourceManager.getFileLoc(decl.getLocation()); clang::FileID fileId = _sourceManager.getDecomposedLoc(location).first; - const clang::FileEntry* entry = _sourceManager.getFileEntryForID(fileId); + const clang::OptionalFileEntryRef entry = _sourceManager.getFileEntryRefForID(fileId); if (entry != nullptr) { meta.fileName = entry->getName(); - meta.module = _headerSearch.findModuleForHeader(entry).getModule(); + meta.module = _headerSearch.findModuleForHeader(*entry).getModule(); } // calculate js name @@ -715,8 +715,8 @@ Version MetaFactory::convertVersion(clang::VersionTuple clangVersion) { Version result = { .Major = (int)clangVersion.getMajor(), - .Minor = (int)(clangVersion.getMinor().hasValue() ? clangVersion.getMinor().getValue() : -1), - .SubMinor = (int)(clangVersion.getSubminor().hasValue() ? clangVersion.getSubminor().getValue() : -1) + .Minor = (int)(clangVersion.getMinor().has_value() ? clangVersion.getMinor().value() : -1), + .SubMinor = (int)(clangVersion.getSubminor().has_value() ? clangVersion.getSubminor().value() : -1) }; return result; } From daceac129d3b73c46a6de4f557d6c06a0621890f Mon Sep 17 00:00:00 2001 From: Eduardo Speroni Date: Tue, 25 Jun 2024 15:12:19 -0300 Subject: [PATCH 11/13] feat: add `@deprecation` and `@since` docs (#246) --- metadata-generator/src/Meta/MetaEntities.h | 13 +++++++++++++ .../src/TypeScript/DocSetManager.cpp | 18 +++++++++++++++--- .../src/TypeScript/DocSetManager.h | 6 +++++- 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/metadata-generator/src/Meta/MetaEntities.h b/metadata-generator/src/Meta/MetaEntities.h index 18709ead..1bacf55b 100644 --- a/metadata-generator/src/Meta/MetaEntities.h +++ b/metadata-generator/src/Meta/MetaEntities.h @@ -62,6 +62,19 @@ struct Version { bool operator >=(const Version& other) const { return !(*this < other); } + std::string toString() const { + std::string result; + if (Major >= 0) { + result.append(std::to_string(Major)); + if (Minor >= 0) { + result.append("." + std::to_string(Minor)); + if (SubMinor >= 0) { + result.append("." + std::to_string(SubMinor)); + } + } + } + return result; + } }; enum MetaFlags : uint16_t { diff --git a/metadata-generator/src/TypeScript/DocSetManager.cpp b/metadata-generator/src/TypeScript/DocSetManager.cpp index 13de5a52..bf28bdc8 100644 --- a/metadata-generator/src/TypeScript/DocSetManager.cpp +++ b/metadata-generator/src/TypeScript/DocSetManager.cpp @@ -90,7 +90,7 @@ using namespace std; std::string TSComment::toString(std::string linePrefix) { - if (description.length() == 0 && params.size() == 0) { + if (description.length() == 0 && params.size() == 0 && deprecatedIn.isUnknown() && introducedIn.isUnknown()) { return std::string(); } @@ -98,19 +98,31 @@ std::string TSComment::toString(std::string linePrefix) result << linePrefix << "/**" << std::endl; std::string processedDesc = description; findAndReplaceIn(processedDesc, "\n", ""); - result << linePrefix << " * " << processedDesc << std::endl; + if (processedDesc.length() > 0) { + result << linePrefix << " * " << processedDesc << std::endl; + } for (std::pair& param : params) { // @param paramName - paramDesc result << linePrefix << " * " << "@param " + param.first + " - " + param.second << std::endl; } + if (!introducedIn.isUnknown()) { + result << linePrefix << " * " << "@since " << introducedIn.toString() << std::endl; + } + if (!deprecatedIn.isUnknown()) { + result << linePrefix << " * " << "@deprecated " << deprecatedIn.toString() << std::endl; + } result << linePrefix << " */" << std::endl; return result.str(); } TSComment DocSetManager::getCommentFor(Meta::Meta* meta, Meta::Meta* parent) { - return (parent == nullptr) ? getCommentFor(meta->name, meta->type) : getCommentFor(meta->name, meta->type, parent->name, parent->type); + auto comment = (parent == nullptr) ? getCommentFor(meta->name, meta->type) : getCommentFor(meta->name, meta->type, parent->name, parent->type); + comment.deprecatedIn = meta->deprecatedIn; + comment.introducedIn = meta->introducedIn; + comment.obsoletedIn = meta->obsoletedIn; + return comment; } TSComment DocSetManager::getCommentFor(std::string name, Meta::MetaType type, std::string parentName, Meta::MetaType parentType) diff --git a/metadata-generator/src/TypeScript/DocSetManager.h b/metadata-generator/src/TypeScript/DocSetManager.h index 06cc2d41..2c146e02 100644 --- a/metadata-generator/src/TypeScript/DocSetManager.h +++ b/metadata-generator/src/TypeScript/DocSetManager.h @@ -21,6 +21,10 @@ struct TSComment { * \brief A brief description of the symbol. */ std::string description; + + Meta::Version introducedIn = UNKNOWN_VERSION; + Meta::Version obsoletedIn = UNKNOWN_VERSION; + Meta::Version deprecatedIn = UNKNOWN_VERSION; /* * \brief An optional list of parameters. Useful in method and function comments. @@ -74,4 +78,4 @@ class DocSetManager { }; } -#endif //METADATAGENERATOR_DOCSETPARSER_H \ No newline at end of file +#endif //METADATAGENERATOR_DOCSETPARSER_H From 6286203ca5293f4a9bec536ee6af7415d8d4d8f5 Mon Sep 17 00:00:00 2001 From: Eduardo Speroni Date: Tue, 25 Jun 2024 16:07:51 -0300 Subject: [PATCH 12/13] feat: add protocol information to native types (#247) * feat: add protocol information to native types * fix: correct typing for C String return type --- .../src/TypeScript/DefinitionWriter.cpp | 29 +++++++++++++++---- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/metadata-generator/src/TypeScript/DefinitionWriter.cpp b/metadata-generator/src/TypeScript/DefinitionWriter.cpp index 6d20d891..3d8b86ab 100644 --- a/metadata-generator/src/TypeScript/DefinitionWriter.cpp +++ b/metadata-generator/src/TypeScript/DefinitionWriter.cpp @@ -883,11 +883,9 @@ std::string DefinitionWriter::tsifyType(const Type& type, const bool isFuncParam case TypeSelector: return "string"; case TypeCString: { - std::string res = "string"; - if (isFuncParam) { - Type typeVoid(TypeVoid); - res += " | " + tsifyType(::Meta::PointerType(&typeVoid), isFuncParam); - } + std::string res = isFuncParam ? "string | " : ""; + Type typeVoid(TypeVoid); + res += tsifyType(::Meta::PointerType(&typeVoid), isFuncParam); return res; } case TypeProtocol: @@ -976,7 +974,26 @@ std::string DefinitionWriter::tsifyType(const Type& type, const bool isFuncParam } } - if (interface.name == "NSArray" && isFuncParam) { + std::vector protocols; + if (type.is(TypeType::TypeInterface) && type.as().protocols.size() > 0) { + for (auto & protocol : type.as().protocols) { + if (protocol->jsName != "NSCopying") { + protocols.push_back(protocol->jsName); + } + } + } + + if (protocols.size() > 0) { + // Example: -(NSObject