Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions NativeScript/runtime/Helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ bool LiveSync(v8::Isolate* isolate);

void Assert(bool condition, v8::Isolate* isolate = nullptr);

void StopExecutionAndLogStackTrace(v8::Isolate* isolate);

}

#endif /* Helpers_h */
4 changes: 4 additions & 0 deletions NativeScript/runtime/Helpers.mm
Original file line number Diff line number Diff line change
Expand Up @@ -691,3 +691,7 @@
Log(@"%s", stack.c_str());
assert(false);
}

void tns::StopExecutionAndLogStackTrace(v8::Isolate* isolate) {
Assert(false, isolate);
}
1 change: 1 addition & 0 deletions NativeScript/runtime/Interop.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ class Interop {
static id ToObject(v8::Local<v8::Context> context, v8::Local<v8::Value> arg);
static v8::Local<v8::Value> GetPrimitiveReturnType(v8::Local<v8::Context> context, BinaryTypeEncodingType type, BaseCall* call);
private:
static void ExecuteWriteValueDebugValidationsIfInDebug(v8::Local<v8::Context> context, const TypeEncoding* typeEncoding, void* dest, v8::Local<v8::Value> arg);
static std::pair<IMP, ffi_closure*> CreateMethodInternal(const uint8_t initialParamIndex, const uint8_t argsCount, const TypeEncoding* typeEncoding, FFIMethodCallback callback, void* userData);
static CFTypeRef CreateBlock(const uint8_t initialParamIndex, const uint8_t argsCount, const TypeEncoding* typeEncoding, FFIMethodCallback callback, void* userData);
template <typename T>
Expand Down
71 changes: 70 additions & 1 deletion NativeScript/runtime/Interop.mm
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "Reference.h"
#include "Pointer.h"
#include "ExtVector.h"
#include "RuntimeConfig.h"
#include "SymbolIterator.h"
#include "UnmanagedType.h"
#include "OneByteStringResource.h"
Expand Down Expand Up @@ -143,7 +144,7 @@

void Interop::WriteValue(Local<Context> context, const TypeEncoding* typeEncoding, void* dest, Local<Value> arg) {
Isolate* isolate = context->GetIsolate();

ExecuteWriteValueDebugValidationsIfInDebug(context, typeEncoding, dest, arg);
if (arg.IsEmpty() || arg->IsNullOrUndefined()) {
ffi_type* ffiType = FFICall::GetArgumentType(typeEncoding, true);
size_t size = ffiType->size;
Expand Down Expand Up @@ -1464,4 +1465,72 @@
return result;
}

// MARK: - Debug Messages for the runtime

void ExecuteWriteValueValidationsAndStopExecutionAndLogStackTrace(Local<Context> context, const TypeEncoding* typeEncoding, void* dest, Local<Value> arg) {
if (!RuntimeConfig.IsDebug) {
return;
}
Isolate* isolate = context->GetIsolate();
std::string destName = typeEncoding->details.interfaceDeclarationReference.name.valuePtr();
Local<Value> originArg = arg;
if (typeEncoding->type == BinaryTypeEncodingType::InterfaceDeclarationReference) {
if (originArg->IsObject()) {
Local<Object> originObj = originArg.As<Object>();
if ((originObj->IsArrayBuffer() || originObj->IsArrayBufferView()) &&
destName != "NSArray") {
tns::StopExecutionAndLogStackTrace(isolate);
}
}
if (destName == "NSString" && tns::IsNumber(originArg)) {
tns::StopExecutionAndLogStackTrace(isolate);
}
if (destName == "NSString" && tns::IsBool(originArg)) {
tns::StopExecutionAndLogStackTrace(isolate);
}
if (destName == "NSString" && tns::IsArrayOrArrayLike(isolate, originArg)) {
tns::StopExecutionAndLogStackTrace(isolate);
}
}
}

bool IsTypeEncondingHandldedByDebugMessages(const TypeEncoding* typeEncoding) {
if (typeEncoding->type != BinaryTypeEncodingType::InterfaceDeclarationReference &&
typeEncoding->type != BinaryTypeEncodingType::StructDeclarationReference &&
typeEncoding->type != BinaryTypeEncodingType::IdEncoding) {
return true;
} else {
return false;
}
}

void LogWriteValueTraceMessage(Local<Context> context, const TypeEncoding* typeEncoding, void* dest, Local<Value> arg) {
if (!RuntimeConfig.IsDebug) {
return;
}
Isolate* isolate = context->GetIsolate();
std::string destName = typeEncoding->details.interfaceDeclarationReference.name.valuePtr();
std::string originName = tns::ToString(isolate, arg);
if (originName == "") {
// empty string
originName = "\"\"";
}
NSString* message = [NSString stringWithFormat:@"Interop::WriteValue: from {%s} to {%s}", originName.c_str(), destName.c_str()];
Log(@"%@", message);
}

void Interop::ExecuteWriteValueDebugValidationsIfInDebug(Local<Context> context, const TypeEncoding* typeEncoding, void* dest, Local<Value> arg) {
if (!RuntimeConfig.IsDebug) {
return;
}
if (arg.IsEmpty() || arg->IsNullOrUndefined()) {
return;
}
if (IsTypeEncondingHandldedByDebugMessages(typeEncoding)) {
return;
}
LogWriteValueTraceMessage(context, typeEncoding, dest, arg);
ExecuteWriteValueValidationsAndStopExecutionAndLogStackTrace(context, typeEncoding, dest, arg);
}

}
25 changes: 25 additions & 0 deletions NativeScript/runtime/Metadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -563,6 +563,31 @@ struct Meta {
return (MetaType)(this->_flags & MetaTypeMask);
}

const char* typeName() const {
switch (type()) {
case Undefined:
return "Undefined";
case Struct:
return "Struct";
case Union:
return "Union";
case Function:
return "Function";
case JsCode:
return "JsCode";
case Var:
return "Var";
case Interface:
return "Interface";
case ProtocolType:
return "ProtocolType";
case Vector:
return "Vector";
default:
return "Unknwon";
}
}

const ModuleMeta* topLevelModule() const {
return this->_topLevelModule.valuePtr();
}
Expand Down
11 changes: 11 additions & 0 deletions NativeScript/runtime/MetadataBuilder.mm
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "Worker.h"
#include "Caches.h"
#include "Tasks.h"
#include "RuntimeConfig.h"

using namespace v8;

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

if (RuntimeConfig.IsDebug) {
NSString* message = [NSString stringWithFormat:@"MetadataBuilder::InvokeMethod class {%s}, selector {%s}, isInitializer {%s}, type {%s}, lib {%s}",
containingClass.c_str(),
meta->selectorAsString(),
meta->isInitializer() ? "true":"false",
meta->typeName(),
meta->topLevelModule()->getName()];
Log(@"%@", message);
}

try {
return ArgConverter::Invoke(context, klass, receiver, args, meta, isMethodCallback);
} catch (NativeScriptException& ex) {
Expand Down