diff --git a/NativeScript/NativeScript-Prefix.pch b/NativeScript/NativeScript-Prefix.pch index 3c3afdbf..6623fa25 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.5.1" +#define NATIVESCRIPT_VERSION "8.5.2-alpha.3" #ifdef DEBUG #define SIZEOF_OFF_T 8 diff --git a/NativeScript/NativeScript.mm b/NativeScript/NativeScript.mm index 29e4e01a..5e7fd101 100644 --- a/NativeScript/NativeScript.mm +++ b/NativeScript/NativeScript.mm @@ -46,8 +46,7 @@ - (instancetype)initWithConfig:(Config*)config { runtime_->Init(isolate); std::chrono::high_resolution_clock::time_point t2 = std::chrono::high_resolution_clock::now(); auto duration = std::chrono::duration_cast(t2 - t1).count(); - printf("Runtime initialization took %llims\n", duration); - printf("Runtime V8 Version %s\n", V8::GetVersion()); + printf("Runtime initialization took %llims (version %s, V8 version %s)\n", duration, NATIVESCRIPT_VERSION, V8::GetVersion()); if (config.IsDebug) { Isolate::Scope isolate_scope(isolate); diff --git a/NativeScript/inspector/JsV8InspectorClient.cpp b/NativeScript/inspector/JsV8InspectorClient.cpp deleted file mode 100644 index 62600d26..00000000 --- a/NativeScript/inspector/JsV8InspectorClient.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include -#include "JsV8InspectorClient.h" -//#include "src/inspector/v8-inspector-session-impl.h" -#include "Helpers.h" - -using namespace v8; - -namespace v8_inspector { - -void JsV8InspectorClient::inspectorSendEventCallback(const FunctionCallbackInfo& args) { - Local data = args.Data().As(); - v8_inspector::JsV8InspectorClient* client = static_cast(data->Value()); - Isolate* isolate = args.GetIsolate(); - Local arg = args[0].As(); - std::string message = tns::ToString(isolate, arg); - -// if (message.find("\"Network.") != std::string::npos) { -// // The Network domain is handled directly by the corresponding backend -// V8InspectorSessionImpl* session = (V8InspectorSessionImpl*)client->session_.get(); -// session->networkArgent()->dispatch(message); -// return; -// } -// -// if (message.find("\"DOM.") != std::string::npos) { -// // The DOM domain is handled directly by the corresponding backend -// V8InspectorSessionImpl* session = (V8InspectorSessionImpl*)client->session_.get(); -// session->domArgent()->dispatch(message); -// return; -// } - - client->dispatchMessage(message); -} - -} diff --git a/NativeScript/inspector/JsV8InspectorClient.h b/NativeScript/inspector/JsV8InspectorClient.h index 79b5fb1b..510d284b 100644 --- a/NativeScript/inspector/JsV8InspectorClient.h +++ b/NativeScript/inspector/JsV8InspectorClient.h @@ -10,6 +10,7 @@ #include "include/v8-inspector.h" #include "src/inspector/v8-console-message.h" +#include "ns-v8-tracing-agent-impl.h" #include "runtime/Runtime.h" namespace v8_inspector { @@ -46,14 +47,18 @@ class JsV8InspectorClient : V8InspectorClient, V8Inspector::Channel { v8::Persistent context_; std::unique_ptr session_; tns::Runtime* runtime_; + v8::Isolate* isolate_; bool terminated_; - std::vector messages_; + std::queue messages_; bool runningNestedLoops_; dispatch_queue_t messagesQueue_; dispatch_queue_t messageLoopQueue_; dispatch_semaphore_t messageArrived_; std::function sender_; bool isWaitingForDebugger_; + bool hasScheduledDebugBreak_; + + std::unique_ptr tracing_agent_; // Override of V8InspectorClient v8::Local ensureDefaultContextInGroup(int contextGroupId) override; @@ -67,6 +72,14 @@ class JsV8InspectorClient : V8InspectorClient, V8Inspector::Channel { static void registerDomainDispatcherCallback(const v8::FunctionCallbackInfo& args); static void inspectorSendEventCallback(const v8::FunctionCallbackInfo& args); static void inspectorTimestampCallback(const v8::FunctionCallbackInfo& args); + + // {N} specific helpers + bool CallDomainHandlerFunction(v8::Local context, + v8::Local domainMethodFunc, + const v8::Local& arg, + v8::Local& domainDebugger, + v8::Local& result); + std::string GetReturnMessageFromDomainHandlerResult(const v8::Local& result, const v8::Local& requestId); }; } diff --git a/NativeScript/inspector/JsV8InspectorClient.mm b/NativeScript/inspector/JsV8InspectorClient.mm index 0c03e4d2..25c0c54f 100644 --- a/NativeScript/inspector/JsV8InspectorClient.mm +++ b/NativeScript/inspector/JsV8InspectorClient.mm @@ -13,6 +13,7 @@ #include "include/libplatform/libplatform.h" #include "Helpers.h" #include "utils.h" +#include "Caches.h" using namespace v8; @@ -24,6 +25,16 @@ #define LOG_DEBUGGER_PORT(port) NSLog(@"NativeScript debugger has opened inspector socket on port %d for %@.", port, [[NSBundle mainBundle] bundleIdentifier]) +JsV8InspectorClient::JsV8InspectorClient(tns::Runtime* runtime) + : runtime_(runtime), + isolate_(runtime_->GetIsolate()), + messages_(), + runningNestedLoops_(false) { + this->messagesQueue_ = dispatch_queue_create("NativeScript.v8.inspector.message_queue", DISPATCH_QUEUE_SERIAL); + this->messageLoopQueue_ = dispatch_queue_create("NativeScript.v8.inspector.message_loop_queue", DISPATCH_QUEUE_SERIAL); + this->messageArrived_ = dispatch_semaphore_create(0); +} + void JsV8InspectorClient::enableInspector(int argc, char** argv) { int waitForDebuggerSubscription; notify_register_dispatch(NOTIFICATION("WaitForDebugger"), &waitForDebuggerSubscription, dispatch_get_main_queue(), ^(int token) { @@ -84,15 +95,6 @@ notify_cancel(waitForDebuggerSubscription); } -JsV8InspectorClient::JsV8InspectorClient(tns::Runtime* runtime) - : runtime_(runtime), - messages_(), - runningNestedLoops_(false) { - this->messagesQueue_ = dispatch_queue_create("NativeScript.v8.inspector.message_queue", DISPATCH_QUEUE_SERIAL); - this->messageLoopQueue_ = dispatch_queue_create("NativeScript.v8.inspector.message_loop_queue", DISPATCH_QUEUE_SERIAL); - this->messageArrived_ = dispatch_semaphore_create(0); -} - void JsV8InspectorClient::onFrontendConnected(std::function sender) { if (this->isWaitingForDebugger_) { this->isWaitingForDebugger_ = NO; @@ -105,11 +107,15 @@ } this->sender_ = sender; + + // this triggers a reconnection from the devtools so Debugger.scriptParsed etc. are all fired again + this->disconnect(); + this->isConnected_ = true; } void JsV8InspectorClient::onFrontendMessageReceived(std::string message) { dispatch_sync(this->messagesQueue_, ^{ - this->messages_.push_back(message); + this->messages_.push(message); dispatch_semaphore_signal(messageArrived_); }); @@ -136,7 +142,7 @@ return; } - Isolate* isolate = runtime_->GetIsolate(); + Isolate* isolate = isolate_; Local context = isolate->GetEnteredOrMicrotaskContext(); @@ -147,6 +153,8 @@ context_.Reset(isolate, context); this->createInspectorSession(); + + tracing_agent_.reset(new tns::inspector::TracingAgentImpl()); } void JsV8InspectorClient::connect(int argc, char** argv) { @@ -159,7 +167,7 @@ } void JsV8InspectorClient::disconnect() { - Isolate* isolate = runtime_->GetIsolate(); + Isolate* isolate = isolate_; v8::Locker locker(isolate); Isolate::Scope isolate_scope(isolate); HandleScope handle_scope(isolate); @@ -198,7 +206,7 @@ } std::shared_ptr platform = tns::Runtime::GetPlatform(); - Isolate* isolate = runtime_->GetIsolate(); + Isolate* isolate = isolate_; platform::PumpMessageLoop(platform.get(), isolate, platform::MessageLoopBehavior::kDoNotWait); if(shouldWait && !terminated_) { dispatch_semaphore_wait(messageArrived_, dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_MSEC)); // 1ms @@ -240,24 +248,89 @@ void JsV8InspectorClient::dispatchMessage(const std::string& message) { std::vector vector = tns::ToVector(message); StringView messageView(vector.data(), vector.size()); - Isolate* isolate = this->runtime_->GetIsolate(); + Isolate* isolate = isolate_; v8::Locker locker(isolate); + Isolate::Scope isolate_scope(isolate); + v8::HandleScope handle_scope(isolate); + Local context = tns::Caches::Get(isolate)->GetContext(); + bool success; + + // livesync uses the inspector socket for HMR/LiveSync... + if(message.find("Page.reload") != std::string::npos) { + success = tns::LiveSync(this->isolate_); + if (!success) { + NSLog(@"LiveSync failed"); + } + // todo: should we return here, or is it OK to pass onto a possible Page.reload domain handler? + } + + if(message.find("Tracing.start") != std::string::npos) { + tracing_agent_->start(); + + // echo back the request to notify frontend the action was a success + // todo: send an empty response for the incoming message id instead. + this->sendNotification(StringBuffer::create(messageView)); + return; + } + + if(message.find("Tracing.end") != std::string::npos) { + tracing_agent_->end(); + std::string res = tracing_agent_->getLastTrace(); + tracing_agent_->SendToDevtools(context, res); + return; + } + + // parse incoming message as JSON + Local arg; + success = v8::JSON::Parse(context, tns::ToV8String(isolate, message)).ToLocal(&arg); + + // stop processing invalid messages + if(!success) { + NSLog(@"Inspector failed to parse incoming message: %s", message.c_str()); + // ignore failures to parse. + return; + } + + // Pass incoming message to a registerd domain handler if any + if(!arg.IsEmpty() && arg->IsObject()) { + Local domainDebugger; + Local argObject = arg.As(); + Local domainMethodFunc = v8_inspector::GetDebuggerFunctionFromObject(context, argObject, domainDebugger); + + Local result; + success = this->CallDomainHandlerFunction(context, domainMethodFunc, argObject, domainDebugger, result); + + if(success) { + auto requestId = arg.As()->Get(context, tns::ToV8String(isolate, "id")).ToLocalChecked(); + auto returnString = GetReturnMessageFromDomainHandlerResult(result, requestId); + + if(returnString.size() > 0) { + std::vector vector = tns::ToVector(returnString); + StringView messageView(vector.data(), vector.size()); + auto msg = StringBuffer::create(messageView); + this->sendNotification(std::move(msg)); + } + return; + } + } + + // if no handler handled the message successfully, fall-through to the default V8 implementation this->session_->dispatchProtocolMessage(messageView); + // TODO: check why this is needed (it should trigger automatically when script depth is 0) isolate->PerformMicrotaskCheckpoint(); } Local JsV8InspectorClient::ensureDefaultContextInGroup(int contextGroupId) { - Isolate* isolate = runtime_->GetIsolate(); - return context_.Get(isolate); + return context_.Get(isolate_); } std::string JsV8InspectorClient::PumpMessage() { __block std::string result; dispatch_sync(this->messagesQueue_, ^{ if (this->messages_.size() > 0) { - result = this->messages_.back(); - this->messages_.pop_back(); + result = this->messages_.front(); + this->messages_.pop(); } }); @@ -265,15 +338,25 @@ } void JsV8InspectorClient::scheduleBreak() { - Isolate* isolate = runtime_->GetIsolate(); + Isolate* isolate = isolate_; v8::Locker locker(isolate); Isolate::Scope isolate_scope(isolate); HandleScope handle_scope(isolate); + auto context = isolate->GetCurrentContext(); + Context::Scope context_scope(context); + + if(!this->hasScheduledDebugBreak_) { + this->hasScheduledDebugBreak_ = true; + // hack: force a debugger; statement in ModuleInternal to actually break before loading the next (main) script... + // FIXME: find a proper fix to not need to resort to this hack. + context->Global()->Set(context, tns::ToV8String(isolate, "__pauseOnNextRequire"), v8::Boolean::New(isolate, true)).ToChecked(); + } + this->session_->schedulePauseOnNextStatement({}, {}); } void JsV8InspectorClient::registerModules() { - Isolate* isolate = runtime_->GetIsolate(); + Isolate* isolate = isolate_; Local context = isolate->GetEnteredOrMicrotaskContext(); Local global = context->Global(); Local inspectorObject = Object::New(isolate); @@ -317,6 +400,20 @@ } } +void JsV8InspectorClient::inspectorSendEventCallback(const FunctionCallbackInfo& args) { + Local data = args.Data().As(); + v8_inspector::JsV8InspectorClient* client = static_cast(data->Value()); + Isolate* isolate = args.GetIsolate(); + Local arg = args[0].As(); + std::string message = tns::ToString(isolate, arg); + + + std::vector vector = tns::ToVector(message); + StringView messageView(vector.data(), vector.size()); + auto msg = StringBuffer::create(messageView); + client->sendNotification(std::move(msg)); +} + void JsV8InspectorClient::inspectorTimestampCallback(const FunctionCallbackInfo& args) { double timestamp = std::chrono::seconds(std::chrono::seconds(std::time(NULL))).count(); args.GetReturnValue().Set(timestamp); @@ -332,6 +429,11 @@ auto* impl = reinterpret_cast(inspector_.get()); auto* session = reinterpret_cast(session_.get()); + if(impl->isolate() != isolate) { + // we don't currently support logging from a worker thread/isolate + return; + } + v8::Local stack = v8::StackTrace::CurrentStackTrace( isolate, 1, v8::StackTrace::StackTraceOptions::kDetailed); std::unique_ptr stackImpl = impl->debugger()->createStackTrace(stack); @@ -347,6 +449,87 @@ session->runtimeAgent()->messageAdded(msg.get()); } +bool JsV8InspectorClient::CallDomainHandlerFunction(Local context, Local domainMethodFunc, const Local& arg, Local& domainDebugger, Local& result) { + if(domainMethodFunc.IsEmpty() || !domainMethodFunc->IsFunction()) { + return false; + } + + bool success; + Isolate* isolate = this->isolate_; + TryCatch tc(isolate); + + Local params; + success = arg.As()->Get(context, tns::ToV8String(isolate, "params")).ToLocal(¶ms); + + if(!success) { + return false; + } + + Local args[2] = { params, arg }; + success = domainMethodFunc->Call(context, domainDebugger, 2, args).ToLocal(&result); + + if (tc.HasCaught()) { + std::string error = tns::ToString(isolate, tc.Message()->Get()); + + // backwards compatibility + if(error.find("may be enabled at a time") != std::string::npos) { + // not returning false here because we are catching bogus errors from core... + // Uncaught Error: One XXX may be enabled at a time... + result = v8::Boolean::New(isolate, true); + return true; + } + + // log any other errors - they are caught, but still make them visible to the user. + tns::LogError(isolate, tc); + + return false; + } + + return success; +} + +std::string JsV8InspectorClient::GetReturnMessageFromDomainHandlerResult(const Local& result, const Local& requestId) { + if(result.IsEmpty() || !(result->IsBoolean() || result->IsObject() || result->IsNullOrUndefined())) { + return ""; + } + + Isolate* isolate = this->isolate_; + + if(!result->IsObject()) { + // if there return value is a "true" boolean or undefined/null we send back an "ack" response with an empty result object + if(result->IsNullOrUndefined() || result->BooleanValue(isolate_)) { + return "{ \"id\":" + tns::ToString(isolate, requestId) + ", \"result\": {} }"; + } + + return ""; + } + + Local context = tns::Caches::Get(isolate)->GetContext(); + Local resObject = result.As(); + Local stringified; + + bool success = true; + // already a { result: ... } object + if(resObject->Has(context, tns::ToV8String(isolate, "result")).ToChecked()) { + success = JSON::Stringify(context, result).ToLocal(&stringified); + } else { + // backwards compatibility - we wrap the response in a new object with the { id, result } keys + // since the returned response only contained the result part. + Context::Scope context_scope(context); + + Local newResObject = v8::Object::New(isolate); + success = success && newResObject->Set(context, tns::ToV8String(isolate, "id"), requestId).ToChecked(); + success = success && newResObject->Set(context, tns::ToV8String(isolate, "result"), resObject).ToChecked(); + success = success && JSON::Stringify(context, newResObject).ToLocal(&stringified); + } + + if(!success) { + return ""; + } + + return tns::ToString(isolate, stringified); +} + std::map*> JsV8InspectorClient::Domains; } diff --git a/NativeScript/inspector/ns-v8-tracing-agent-impl.h b/NativeScript/inspector/ns-v8-tracing-agent-impl.h new file mode 100644 index 00000000..02d347a4 --- /dev/null +++ b/NativeScript/inspector/ns-v8-tracing-agent-impl.h @@ -0,0 +1,60 @@ +// +// ns-v8-tracing-agent-impl.hpp +// NativeScript +// +// Created by Igor Randjelovic on 2023. 04. 03.. +// Copyright © 2023. Progress. All rights reserved. +// + +#ifndef ns_v8_tracing_agent_impl_hpp +#define ns_v8_tracing_agent_impl_hpp + +#include + +#include "libplatform/v8-tracing.h" +#include "v8.h" + +namespace tns { +namespace inspector { + +using v8::platform::tracing::TraceBuffer; +using v8::platform::tracing::TraceBufferChunk; +using v8::platform::tracing::TraceWriter; +using v8::platform::tracing::TraceObject; +using v8::platform::tracing::TracingController; +using v8::platform::tracing::TraceConfig; + +class NSInMemoryTraceWriter: public TraceWriter { +public: + NSInMemoryTraceWriter(): stream_() {}; + void AppendTraceEvent(TraceObject *trace_event); + void Flush(); + std::string getTrace(); +private: + int total_traces_ = 0; + std::stringstream stream_; + std::unique_ptr json_trace_writer_; +}; + +class TracingAgentImpl { +public: + TracingAgentImpl(); + bool start(); + bool end(); + std::string getLastTrace() { + return lastTrace_; + } + void SendToDevtools(v8::Local context, std::string jsonData); +private: + bool tracing_ = false; + TracingController* tracing_controller_; + NSInMemoryTraceWriter* current_trace_writer_; + + std::string lastTrace_; +}; + +} // namespace inspector +} // namespace tns + + +#endif /* ns_v8_tracing_agent_impl_hpp */ diff --git a/NativeScript/inspector/ns-v8-tracing-agent-impl.mm b/NativeScript/inspector/ns-v8-tracing-agent-impl.mm new file mode 100644 index 00000000..0fd8d44d --- /dev/null +++ b/NativeScript/inspector/ns-v8-tracing-agent-impl.mm @@ -0,0 +1,168 @@ +// +// ns-v8-tracing-agent-impl.cpp +// NativeScript +// +// Created by Igor Randjelovic on 2023. 04. 03.. +// Copyright © 2023. Progress. All rights reserved. +// + +//#include +//#include +//#include +#include + +#include "ns-v8-tracing-agent-impl.h" +#include "Runtime.h" +#include "Helpers.h" + +namespace tns { +namespace inspector { + +using v8::platform::tracing::TraceBuffer; +using v8::platform::tracing::TraceBufferChunk; +using v8::platform::tracing::TraceWriter; +using v8::platform::tracing::TraceObject; +using v8::platform::tracing::TracingController; +using v8::platform::tracing::TraceConfig; +using v8::platform::tracing::TraceRecordMode; + +void NSInMemoryTraceWriter::AppendTraceEvent(TraceObject *trace_event) { + if(total_traces_ == 0) { + // create a v8 JSON trace writer + json_trace_writer_.reset(TraceWriter::CreateJSONTraceWriter(stream_)); + } + + ++total_traces_; + json_trace_writer_->AppendTraceEvent(trace_event); +} + +void NSInMemoryTraceWriter::Flush() { + if(json_trace_writer_.get() != nullptr) { + json_trace_writer_->Flush(); + } +} + +std::string NSInMemoryTraceWriter::getTrace() { + if(total_traces_ == 0) { + return ""; + } + + // ensures the trace json is closed + json_trace_writer_.reset(); + std::string str = stream_.str(); + + // clear stream? + stream_.str(""); + stream_.clear(); + + return str; +} + + +TracingAgentImpl::TracingAgentImpl() { + tracing_controller_ = reinterpret_cast(tns::Runtime::GetPlatform()->GetTracingController()); +} + +bool TracingAgentImpl::start() { + if(!tracing_) { + tracing_ = true; + + // start tracing... + current_trace_writer_ = new NSInMemoryTraceWriter(); + tracing_controller_->Initialize( + TraceBuffer::CreateTraceBufferRingBuffer( + TraceBuffer::kRingBufferChunks, + current_trace_writer_ + ) + ); + // todo: create TraceConfig based on params. + TraceConfig* config = TraceConfig::CreateDefaultTraceConfig(); + config->AddIncludedCategory("disabled-by-default-v8.cpu_profiler"); + config->SetTraceRecordMode(TraceRecordMode::RECORD_CONTINUOUSLY); + tracing_controller_->StartTracing(config); + } + + return true; +} + +bool TracingAgentImpl::end() { + if(tracing_) { + tracing_controller_->StopTracing(); + + if(current_trace_writer_ != nullptr) { + // store last trace on the agent. + lastTrace_ = current_trace_writer_->getTrace(); + current_trace_writer_ = nullptr; + } + tracing_controller_->Initialize(nullptr); + + tracing_ = false; + } + + return true; +} + +void TracingAgentImpl::SendToDevtools(v8::Local context, std::string jsonData) { + std::string source = R"( + (() => { + function processTraceData(traceJSON) { + + try { + // handle empty traces (e.g. when the user cancels the trace immediately) + if(!traceJSON || traceJSON.trim().length === 0) { + traceJSON = "{}"; + } + const data = JSON.parse(traceJSON); + + for (let i = 0; i < data.traceEvents?.length; i = i + 20) { + const chunk = data.traceEvents.slice(i, i + 20); + + __inspectorSendEvent( + JSON.stringify({ + method: "Tracing.dataCollected", + params: { + value: chunk, + }, + }) + ); + } + + __inspectorSendEvent( + JSON.stringify({ + method: "Tracing.tracingComplete", + params: { + dataLossOccurred: false, + }, + }) + ); + } catch (err) { + console.log("[Inspector] Failed to parse trace data", err, traceJSON); + } + } + return processTraceData; + })(); + )"; + + v8::Isolate* isolate = context->GetIsolate(); + v8::Locker locker(isolate); + v8::Isolate::Scope isolate_scope(isolate); + v8::HandleScope handle_scope(isolate); + + v8::Local script; + bool success = v8::Script::Compile(context, tns::ToV8String(isolate, source)).ToLocal(&script); + tns::Assert(success && !script.IsEmpty(), isolate); + + v8::Local result; + success = script->Run(context).ToLocal(&result); + tns::Assert(success, isolate); + + v8::Local processTraceData = result.As(); + + v8::Local args[1] = { tns::ToV8String(isolate, jsonData) }; + success = processTraceData->Call(context, processTraceData, 1, args).ToLocal(&result); + tns::Assert(success, isolate); +} + + +} // namespace inspector +} // namespace tns diff --git a/NativeScript/inspector/utils.h b/NativeScript/inspector/utils.h index ea0cc800..e2e971cc 100644 --- a/NativeScript/inspector/utils.h +++ b/NativeScript/inspector/utils.h @@ -8,7 +8,7 @@ namespace v8_inspector { std::string GetMIMEType(std::string filePath); std::string ToStdString(const v8_inspector::StringView& value); v8::Local GetDebuggerFunction(v8::Local context, std::string domain, std::string functionName, v8::Local& domainDebugger); -std::string GetDomainMethod(v8::Isolate* isolate, const v8::Local& arg, std::string domain); +v8::Local GetDebuggerFunctionFromObject(v8::Local context, const v8::Local& object, v8::Local& domainDebugger); class NetworkRequestData { public: diff --git a/NativeScript/inspector/utils.mm b/NativeScript/inspector/utils.mm index 520e66e5..dd7158de 100644 --- a/NativeScript/inspector/utils.mm +++ b/NativeScript/inspector/utils.mm @@ -45,6 +45,8 @@ 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; std::string result = convert.to_bytes(value16); @@ -69,20 +71,17 @@ return Local(); } -std::string v8_inspector::GetDomainMethod(Isolate* isolate, const Local& arg, std::string domain) { - Local context = isolate->GetCurrentContext(); - Local value; - assert(arg->Get(context, tns::ToV8String(isolate, "method")).ToLocal(&value)); - std::string method = tns::ToString(isolate, value); - - if (method.empty()) { - return ""; - } - - size_t pos = method.find(domain); - if (pos == std::string::npos) { - return ""; +Local v8_inspector::GetDebuggerFunctionFromObject(Local context, const Local& object, Local& domainDebugger) { + Isolate* isolate = context->GetIsolate(); + auto method = object->Get(context, tns::ToV8String(isolate, "method")).ToLocalChecked(); + auto methodString = tns::ToString(isolate, method); + auto domainSeparatorIndex = methodString.find("."); + auto domain = methodString.substr(0, domainSeparatorIndex); + auto domainMethod = methodString.substr(domainSeparatorIndex + 1, methodString.size()); + + if(domain.size() > 0) { + return v8_inspector::GetDebuggerFunction(context, domain, domainMethod, domainDebugger); } - return method.substr(pos + domain.length()); + return Local(); } diff --git a/NativeScript/runtime/Helpers.mm b/NativeScript/runtime/Helpers.mm index 4dba607a..f98b005d 100644 --- a/NativeScript/runtime/Helpers.mm +++ b/NativeScript/runtime/Helpers.mm @@ -24,6 +24,8 @@ std::u16string tns::ToUtf16String(Isolate* isolate, const Local& value) { std::string valueStr = tns::ToString(isolate, value); +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + // FIXME: std::codecvt_utf8_utf16 is deprecated std::wstring_convert, char16_t> convert; std::u16string value16 = convert.from_bytes(valueStr); @@ -31,6 +33,8 @@ } std::vector tns::ToVector(const std::string& value) { +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + // FIXME: std::codecvt_utf8_utf16 is deprecated std::wstring_convert, char16_t> convert; std::u16string value16 = convert.from_bytes(value); diff --git a/NativeScript/runtime/ModuleInternal.mm b/NativeScript/runtime/ModuleInternal.mm index ab5890ed..1fd5196b 100644 --- a/NativeScript/runtime/ModuleInternal.mm +++ b/NativeScript/runtime/ModuleInternal.mm @@ -16,6 +16,7 @@ "(function() { " " function require_factory(requireInternal, dirName) { " " return function require(modulePath) { " + " if(global.__pauseOnNextRequire) { debugger; global.__pauseOnNextRequire = false; }" " return requireInternal(modulePath, dirName); " " } " " } " diff --git a/metadata-generator/CMakeLists.txt b/metadata-generator/CMakeLists.txt index 175c461c..757a0d45 100644 --- a/metadata-generator/CMakeLists.txt +++ b/metadata-generator/CMakeLists.txt @@ -1,5 +1,6 @@ project(MetadataGenerator) cmake_minimum_required(VERSION 3.20) +include(CheckCCompilerFlag) #set(CMAKE_VERBOSE_MAKEFILE ON) @@ -26,6 +27,13 @@ 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") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -target ${METADATA_BINARY_ARCH}-apple-darwin -std=c++17 -fno-rtti ${LLVM_PREPROCESSOR_FLAGS}") + +# Disable unused-but-set-variable error because it's triggered by LLVM code +check_c_compiler_flag(-Wno-unused-but-set-variable HAS_UNUSED_BUT_SET_VARIABLE) +if (HAS_UNUSED_BUT_SET_VARIABLE) + add_compile_options(-Wno-unused-but-set-variable) +endif() + set(LLVM_LINKER_FLAGS "${LLVM_LINKER_FLAGS} ${LLVM_SYSTEM_LIBS} ${LLVM_LIBS}") set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin/lib) diff --git a/package.json b/package.json index c4ed2aed..a584edde 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@nativescript/ios", "description": "NativeScript Runtime for iOS", - "version": "8.5.1", + "version": "8.5.2-alpha.3", "keywords": [ "NativeScript", "iOS", diff --git a/v8ios.xcodeproj/project.pbxproj b/v8ios.xcodeproj/project.pbxproj index 9181feeb..e55e9090 100644 --- a/v8ios.xcodeproj/project.pbxproj +++ b/v8ios.xcodeproj/project.pbxproj @@ -37,6 +37,8 @@ 6573B9ED291FE5B700B0ED7C /* JSIRuntime.h in Headers */ = {isa = PBXBuildFile; fileRef = 6573B9EB291FE5B700B0ED7C /* JSIRuntime.h */; }; 6573B9EE291FE5B700B0ED7C /* JSIRuntime.m in Sources */ = {isa = PBXBuildFile; fileRef = 6573B9EC291FE5B700B0ED7C /* JSIRuntime.m */; }; 9160C065291ED41F000641C0 /* SpinLock.h in Headers */ = {isa = PBXBuildFile; fileRef = 9160C064291ED41F000641C0 /* SpinLock.h */; }; + 91B25A0A29DAC83D00E3CE04 /* ns-v8-tracing-agent-impl.mm in Sources */ = {isa = PBXBuildFile; fileRef = 91B25A0829DAC83D00E3CE04 /* ns-v8-tracing-agent-impl.mm */; }; + 91B25A0B29DAC83D00E3CE04 /* ns-v8-tracing-agent-impl.h in Headers */ = {isa = PBXBuildFile; fileRef = 91B25A0929DAC83D00E3CE04 /* ns-v8-tracing-agent-impl.h */; }; C205257F2577D6F900C12A5C /* NativeScript.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C2DDEB32229EAB3B00345BFE /* NativeScript.framework */; }; C20525802577D6F900C12A5C /* NativeScript.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = C2DDEB32229EAB3B00345BFE /* NativeScript.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; C20525A82577D86600C12A5C /* TNSWidgets.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = C20525A72577D86600C12A5C /* TNSWidgets.xcframework */; }; @@ -311,7 +313,6 @@ C2FEA16F22A3C75C00A5C0FC /* InlineFunctions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2FEA16D22A3C75C00A5C0FC /* InlineFunctions.cpp */; }; C2FEA17022A3C75C00A5C0FC /* InlineFunctions.h in Headers */ = {isa = PBXBuildFile; fileRef = C2FEA16E22A3C75C00A5C0FC /* InlineFunctions.h */; }; F6191AAE29C0FCE8003F588F /* JsV8InspectorClient.h in Headers */ = {isa = PBXBuildFile; fileRef = F6191AA629C0FCE7003F588F /* JsV8InspectorClient.h */; }; - F6191AAF29C0FCE8003F588F /* JsV8InspectorClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F6191AA729C0FCE7003F588F /* JsV8InspectorClient.cpp */; settings = {COMPILER_FLAGS = "-fobjc-arc"; }; }; F6191AB029C0FCE8003F588F /* JsV8InspectorClient.mm in Sources */ = {isa = PBXBuildFile; fileRef = F6191AA829C0FCE7003F588F /* JsV8InspectorClient.mm */; }; F6191AB129C0FCE8003F588F /* InspectorServer.h in Headers */ = {isa = PBXBuildFile; fileRef = F6191AA929C0FCE7003F588F /* InspectorServer.h */; }; F6191AB229C0FCE8003F588F /* InspectorServer.mm in Sources */ = {isa = PBXBuildFile; fileRef = F6191AAA29C0FCE7003F588F /* InspectorServer.mm */; settings = {COMPILER_FLAGS = "-fobjc-arc"; }; }; @@ -447,6 +448,8 @@ 6573B9EB291FE5B700B0ED7C /* JSIRuntime.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JSIRuntime.h; sourceTree = ""; }; 6573B9EC291FE5B700B0ED7C /* JSIRuntime.m */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; path = JSIRuntime.m; sourceTree = ""; }; 9160C064291ED41F000641C0 /* SpinLock.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SpinLock.h; path = NativeScript/runtime/SpinLock.h; sourceTree = ""; }; + 91B25A0829DAC83D00E3CE04 /* ns-v8-tracing-agent-impl.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = "ns-v8-tracing-agent-impl.mm"; sourceTree = ""; }; + 91B25A0929DAC83D00E3CE04 /* ns-v8-tracing-agent-impl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ns-v8-tracing-agent-impl.h"; sourceTree = ""; }; C2003F9E23FA78CD0043B815 /* TNSDerivedClass.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TNSDerivedClass.h; sourceTree = ""; }; C20525A72577D86600C12A5C /* TNSWidgets.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = TNSWidgets.xcframework; sourceTree = ""; }; C20AB5E426E1015200E2B41D /* OneByteStringResource.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = OneByteStringResource.cpp; sourceTree = ""; }; @@ -788,7 +791,6 @@ C2FF301C2252062A00933782 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; C2FF301F2252065E00933782 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; F6191AA629C0FCE7003F588F /* JsV8InspectorClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JsV8InspectorClient.h; sourceTree = ""; }; - F6191AA729C0FCE7003F588F /* JsV8InspectorClient.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JsV8InspectorClient.cpp; sourceTree = ""; }; F6191AA829C0FCE7003F588F /* JsV8InspectorClient.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = JsV8InspectorClient.mm; sourceTree = ""; }; F6191AA929C0FCE7003F588F /* InspectorServer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorServer.h; sourceTree = ""; }; F6191AAA29C0FCE7003F588F /* InspectorServer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = InspectorServer.mm; sourceTree = ""; }; @@ -1437,10 +1439,11 @@ F6191AB429C0FF86003F588F /* utils.h */, F6191AB529C0FF86003F588F /* utils.mm */, F6191AA629C0FCE7003F588F /* JsV8InspectorClient.h */, - F6191AA729C0FCE7003F588F /* JsV8InspectorClient.cpp */, F6191AA829C0FCE7003F588F /* JsV8InspectorClient.mm */, F6191AA929C0FCE7003F588F /* InspectorServer.h */, F6191AAA29C0FCE7003F588F /* InspectorServer.mm */, + 91B25A0829DAC83D00E3CE04 /* ns-v8-tracing-agent-impl.mm */, + 91B25A0929DAC83D00E3CE04 /* ns-v8-tracing-agent-impl.h */, ); path = inspector; sourceTree = ""; @@ -1514,6 +1517,7 @@ C2DDEB9F229EAC8300345BFE /* Tasks.h in Headers */, C27E5D8622F2FDDB00498ED0 /* KnownUnknownClassPair.h in Headers */, C247C16922F82842001D2CA2 /* v8-tracing.h in Headers */, + 91B25A0B29DAC83D00E3CE04 /* ns-v8-tracing-agent-impl.h in Headers */, 6573B9E9291FE2A700B0ED7C /* threadsafe.h in Headers */, 3CD1D9C229AA2C14004C1C21 /* DisposerPHV.h in Headers */, C22536B7241A318900192740 /* ffitarget.h in Headers */, @@ -2075,7 +2079,6 @@ C2DDEB99229EAC8300345BFE /* Metadata.mm in Sources */, 6573B9D4291FE29F00B0ED7C /* V8RuntimeFactory.cpp in Sources */, C2DDEBB4229EAC8300345BFE /* DictionaryAdapter.mm in Sources */, - F6191AAF29C0FCE8003F588F /* JsV8InspectorClient.cpp in Sources */, C298C027233C9AEA000DDF54 /* TSHelpers.cpp in Sources */, C2FEA16F22A3C75C00A5C0FC /* InlineFunctions.cpp in Sources */, C2DDEB9A229EAC8300345BFE /* MetadataBuilder.mm in Sources */, @@ -2090,6 +2093,7 @@ C23E8F7622CDE88D0078FD4C /* WorkerWrapper.mm in Sources */, C266567B22AA630F00EE15CC /* NSDataAdapter.mm in Sources */, 3CD1D9C129AA2C14004C1C21 /* DisposerPHV.mm in Sources */, + 91B25A0A29DAC83D00E3CE04 /* ns-v8-tracing-agent-impl.mm in Sources */, C2DDEBA6229EAC8300345BFE /* Helpers.mm in Sources */, C26656B322B3768C00EE15CC /* InteropTypes.mm in Sources */, C2F4D0AD232F85E20008A2EB /* SymbolIterator.mm in Sources */,