Skip to content

Commit f0a49c0

Browse files
dgmachadoNathanWalker
authored andcommitted
feat: improve crash report details (#142)
1 parent de6506b commit f0a49c0

File tree

6 files changed

+113
-1
lines changed

6 files changed

+113
-1
lines changed

NativeScript/runtime/Helpers.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ bool LiveSync(v8::Isolate* isolate);
7777

7878
void Assert(bool condition, v8::Isolate* isolate = nullptr, std::string const &reason = std::string());
7979

80+
void StopExecutionAndLogStackTrace(v8::Isolate* isolate);
81+
8082
}
8183

8284
#endif /* Helpers_h */

NativeScript/runtime/Helpers.mm

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -682,3 +682,7 @@
682682
Log(@"%s", stack.c_str());
683683
assert(false);
684684
}
685+
686+
void tns::StopExecutionAndLogStackTrace(v8::Isolate* isolate) {
687+
Assert(false, isolate);
688+
}

NativeScript/runtime/Interop.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ class Interop {
126126
static id ToObject(v8::Local<v8::Context> context, v8::Local<v8::Value> arg);
127127
static v8::Local<v8::Value> GetPrimitiveReturnType(v8::Local<v8::Context> context, BinaryTypeEncodingType type, BaseCall* call);
128128
private:
129+
static void ExecuteWriteValueDebugValidationsIfInDebug(v8::Local<v8::Context> context, const TypeEncoding* typeEncoding, void* dest, v8::Local<v8::Value> arg);
129130
static std::pair<IMP, ffi_closure*> CreateMethodInternal(const uint8_t initialParamIndex, const uint8_t argsCount, const TypeEncoding* typeEncoding, FFIMethodCallback callback, void* userData);
130131
static CFTypeRef CreateBlock(const uint8_t initialParamIndex, const uint8_t argsCount, const TypeEncoding* typeEncoding, FFIMethodCallback callback, void* userData);
131132
template <typename T>

NativeScript/runtime/Interop.mm

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "Reference.h"
1616
#include "Pointer.h"
1717
#include "ExtVector.h"
18+
#include "RuntimeConfig.h"
1819
#include "SymbolIterator.h"
1920
#include "UnmanagedType.h"
2021
#include "OneByteStringResource.h"
@@ -144,7 +145,7 @@
144145

145146
void Interop::WriteValue(Local<Context> context, const TypeEncoding* typeEncoding, void* dest, Local<Value> arg) {
146147
Isolate* isolate = context->GetIsolate();
147-
148+
ExecuteWriteValueDebugValidationsIfInDebug(context, typeEncoding, dest, arg);
148149
if (arg.IsEmpty() || arg->IsNullOrUndefined()) {
149150
ffi_type* ffiType = FFICall::GetArgumentType(typeEncoding, true);
150151
size_t size = ffiType->size;
@@ -1483,4 +1484,72 @@
14831484
return result;
14841485
}
14851486

1487+
// MARK: - Debug Messages for the runtime
1488+
1489+
void ExecuteWriteValueValidationsAndStopExecutionAndLogStackTrace(Local<Context> context, const TypeEncoding* typeEncoding, void* dest, Local<Value> arg) {
1490+
if (!RuntimeConfig.IsDebug) {
1491+
return;
1492+
}
1493+
Isolate* isolate = context->GetIsolate();
1494+
std::string destName = typeEncoding->details.interfaceDeclarationReference.name.valuePtr();
1495+
Local<Value> originArg = arg;
1496+
if (typeEncoding->type == BinaryTypeEncodingType::InterfaceDeclarationReference) {
1497+
if (originArg->IsObject()) {
1498+
Local<Object> originObj = originArg.As<Object>();
1499+
if ((originObj->IsArrayBuffer() || originObj->IsArrayBufferView()) &&
1500+
destName != "NSArray") {
1501+
tns::StopExecutionAndLogStackTrace(isolate);
1502+
}
1503+
}
1504+
if (destName == "NSString" && tns::IsNumber(originArg)) {
1505+
tns::StopExecutionAndLogStackTrace(isolate);
1506+
}
1507+
if (destName == "NSString" && tns::IsBool(originArg)) {
1508+
tns::StopExecutionAndLogStackTrace(isolate);
1509+
}
1510+
if (destName == "NSString" && tns::IsArrayOrArrayLike(isolate, originArg)) {
1511+
tns::StopExecutionAndLogStackTrace(isolate);
1512+
}
1513+
}
1514+
}
1515+
1516+
bool IsTypeEncondingHandldedByDebugMessages(const TypeEncoding* typeEncoding) {
1517+
if (typeEncoding->type != BinaryTypeEncodingType::InterfaceDeclarationReference &&
1518+
typeEncoding->type != BinaryTypeEncodingType::StructDeclarationReference &&
1519+
typeEncoding->type != BinaryTypeEncodingType::IdEncoding) {
1520+
return true;
1521+
} else {
1522+
return false;
1523+
}
1524+
}
1525+
1526+
void LogWriteValueTraceMessage(Local<Context> context, const TypeEncoding* typeEncoding, void* dest, Local<Value> arg) {
1527+
if (!RuntimeConfig.IsDebug) {
1528+
return;
1529+
}
1530+
Isolate* isolate = context->GetIsolate();
1531+
std::string destName = typeEncoding->details.interfaceDeclarationReference.name.valuePtr();
1532+
std::string originName = tns::ToString(isolate, arg);
1533+
if (originName == "") {
1534+
// empty string
1535+
originName = "\"\"";
1536+
}
1537+
NSString* message = [NSString stringWithFormat:@"Interop::WriteValue: from {%s} to {%s}", originName.c_str(), destName.c_str()];
1538+
Log(@"%@", message);
1539+
}
1540+
1541+
void Interop::ExecuteWriteValueDebugValidationsIfInDebug(Local<Context> context, const TypeEncoding* typeEncoding, void* dest, Local<Value> arg) {
1542+
if (!RuntimeConfig.IsDebug) {
1543+
return;
1544+
}
1545+
if (arg.IsEmpty() || arg->IsNullOrUndefined()) {
1546+
return;
1547+
}
1548+
if (IsTypeEncondingHandldedByDebugMessages(typeEncoding)) {
1549+
return;
1550+
}
1551+
LogWriteValueTraceMessage(context, typeEncoding, dest, arg);
1552+
ExecuteWriteValueValidationsAndStopExecutionAndLogStackTrace(context, typeEncoding, dest, arg);
1553+
}
1554+
14861555
}

NativeScript/runtime/Metadata.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,31 @@ struct Meta {
563563
return (MetaType)(this->_flags & MetaTypeMask);
564564
}
565565

566+
const char* typeName() const {
567+
switch (type()) {
568+
case Undefined:
569+
return "Undefined";
570+
case Struct:
571+
return "Struct";
572+
case Union:
573+
return "Union";
574+
case Function:
575+
return "Function";
576+
case JsCode:
577+
return "JsCode";
578+
case Var:
579+
return "Var";
580+
case Interface:
581+
return "Interface";
582+
case ProtocolType:
583+
return "ProtocolType";
584+
case Vector:
585+
return "Vector";
586+
default:
587+
return "Unknwon";
588+
}
589+
}
590+
566591
const ModuleMeta* topLevelModule() const {
567592
return this->_topLevelModule.valuePtr();
568593
}

NativeScript/runtime/MetadataBuilder.mm

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "Worker.h"
1212
#include "Caches.h"
1313
#include "Tasks.h"
14+
#include "RuntimeConfig.h"
1415

1516
using namespace v8;
1617

@@ -810,6 +811,16 @@
810811
Class klass = objc_getClass(containingClass.c_str());
811812
// TODO: Find out if the isMethodCallback property can be determined based on a UITableViewController.prototype.viewDidLoad.call(this) or super.viewDidLoad() call
812813

814+
if (RuntimeConfig.IsDebug) {
815+
NSString* message = [NSString stringWithFormat:@"MetadataBuilder::InvokeMethod class {%s}, selector {%s}, isInitializer {%s}, type {%s}, lib {%s}",
816+
containingClass.c_str(),
817+
meta->selectorAsString(),
818+
meta->isInitializer() ? "true":"false",
819+
meta->typeName(),
820+
meta->topLevelModule()->getName()];
821+
Log(@"%@", message);
822+
}
823+
813824
try {
814825
return ArgConverter::Invoke(context, klass, receiver, args, meta, isMethodCallback);
815826
} catch (NativeScriptException& ex) {

0 commit comments

Comments
 (0)