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
11 changes: 8 additions & 3 deletions build/project-template/internal/main.m
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <Foundation/Foundation.h>
#include <JavaScriptCore/JavaScriptCore.h>
#include <NativeScript.h>
#include <TNSExceptionHandler.h>

#if DEBUG
#include <TNSDebugging.h>
Expand All @@ -20,9 +21,11 @@ int main(int argc, char *argv[]) {
#if DEBUG
NSString *libraryPath = [NSSearchPathForDirectoriesInDomains(
NSLibraryDirectory, NSUserDomainMask, YES) firstObject];
NSString *liveSyncPath =
[NSString pathWithComponents:
@[ libraryPath, @"Application Support", @"LiveSync" ]];
NSString *liveSyncPath = [NSString pathWithComponents:@[
libraryPath,
@"Application Support",
@"LiveSync"
]];
NSString *appFolderPath =
[NSString pathWithComponents:@[ liveSyncPath, @"app" ]];

Expand All @@ -35,6 +38,8 @@ int main(int argc, char *argv[]) {
#endif

[TNSRuntime initializeMetadata:&startOfMetadataSection];
TNSInstallExceptionHandler();

runtime = [[TNSRuntime alloc] initWithApplicationPath:applicationPath];
[runtime scheduleInRunLoop:[NSRunLoop currentRunLoop]
forMode:NSRunLoopCommonModes];
Expand Down
3 changes: 2 additions & 1 deletion build/scripts/build-runtime.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@ PACKAGE_DIR="$DIST_DIR/package"
FRAMEWORK_DIR="$PACKAGE_DIR/framework"
INTERNAL_DIR="$FRAMEWORK_DIR/internal"

. "$WORKSPACE/build/scripts/build.sh"
. "$WORKSPACE/build/scripts/build.sh"

mkdir -p "$INTERNAL_DIR/NativeScript/Frameworks"

cp -R "$DIST_DIR/NativeScript/" "$INTERNAL_DIR/NativeScript"
cp -R "$DIST_DIR/NativeScript.framework" "$INTERNAL_DIR/NativeScript/Frameworks"
cp -R "$WORKSPACE/src/debugging/TNSDebugging.h" "$INTERNAL_DIR"
cp -R "$WORKSPACE/src/NativeScript/ObjC/TNSExceptionHandler.h" "$INTERNAL_DIR"
cp -R "$DIST_DIR/metadataGenerator" "$INTERNAL_DIR/metadata-generator"
cp -R "$BUILD_DIR/project-template/" "$FRAMEWORK_DIR"
cp -R "$BUILD_DIR/npm/runtime_package.json" "$PACKAGE_DIR/package.json"
Expand Down
1 change: 1 addition & 0 deletions build/scripts/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ NATIVESCRIPT_DIR="$WORKSPACE/src/NativeScript/"
cp \
"$NATIVESCRIPT_DIR/NativeScript.h" \
"$NATIVESCRIPT_DIR/TNSRuntime.h" \
"$NATIVESCRIPT_DIR/TNSRuntime+Diagnostics.h" \
"$NATIVESCRIPT_DIR/TNSRuntime+Inspector.h" \
"$WORKSPACE/dist/NativeScript/include"

Expand Down
3 changes: 2 additions & 1 deletion cmake/CreateNativeScriptApp.cmake
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
function(CreateNativeScriptApp _target _main _plist _resources)
include_directories(${RUNTIME_DIR} ${NATIVESCRIPT_DEBUGGING_DIR})
include_directories("${RUNTIME_DIR}/**" ${NATIVESCRIPT_DEBUGGING_DIR})
link_directories(${WEBKIT_LINK_DIRECTORIES} "${LIBFFI_LIB_DIR}")

add_executable(${_target} ${_main} ${_resources})

target_link_libraries(${_target}
"-ObjC"
"-framework CoreGraphics"
"-framework UIKit"
"-framework MobileCoreServices"
Expand Down
3 changes: 3 additions & 0 deletions cmake/main.m
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#import <NativeScript.h>
#import <TNSExceptionHandler.h>

#ifndef NDEBUG
#include <TNSDebugging.h>
Expand All @@ -16,6 +17,8 @@ int main(int argc, char *argv[]) {
forMode:NSRunLoopCommonModes];
TNSRuntimeInspector.logsToSystemConsole = YES;

TNSInstallExceptionHandler();

#ifndef NDEBUG
TNSEnableRemoteInspector(argc, argv);
#endif
Expand Down
3 changes: 3 additions & 0 deletions examples/BlankApp/main.m
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#import <Foundation/Foundation.h>
#import <JavaScriptCore/JavaScriptCore.h>
#import <NativeScript.h>
#import <TNSExceptionHandler.h>

static NSString *toString(JSContextRef context, JSValueRef value) {
JSStringRef errorMessageRef = JSValueToStringCopy(context, value, NULL);
Expand Down Expand Up @@ -36,6 +37,8 @@ int main(int argc, char *argv[]) {
return 1;
}

TNSInstallExceptionHandler();

JSValueRef errorRef = NULL;

JSStringRef scriptRef = JSStringCreateWithUTF8CString(script.UTF8String);
Expand Down
1 change: 1 addition & 0 deletions src/NativeScript/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ set(SOURCE_FILES

set(NativeScript_PUBLIC_HEADERS
NativeScript.h
TNSRuntime+Diagnostics.h
TNSRuntime+Inspector.h
TNSRuntime.h
)
Expand Down
2 changes: 1 addition & 1 deletion src/NativeScript/JSErrors.mm
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ void TNSSetUncaughtErrorHandler(TNSUncaughtErrorHandler handler) {
using namespace JSC;

static void handleJsUncaughtErrorCallback(ExecState* execState, Exception* exception) {
JSValue callback = execState->lexicalGlobalObject()->get(execState, Identifier::fromString(execState, "__onUncaughtError"));
JSValue callback = execState->lexicalGlobalObject()->get(execState, Identifier::fromString(execState, "__onUncaughtError")); // Keep in sync with TNSExceptionHandler.h

CallData callData;
CallType callType = getCallData(callback, callData);
Expand Down
1 change: 1 addition & 0 deletions src/NativeScript/NativeScript.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@
//

#import "TNSRuntime.h"
#import "TNSRuntime+Diagnostics.h"
#import "TNSRuntime+Inspector.h"
63 changes: 63 additions & 0 deletions src/NativeScript/ObjC/TNSExceptionHandler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
//
// TNSExceptionHandler.h
// NativeScript
//
// Created by Jason Zhekov on 2/1/16.
// Copyright © 2016 Telerik. All rights reserved.
//

#ifndef TNSExceptionHandler_h
#define TNSExceptionHandler_h

#import <JavaScriptCore/JavaScriptCore.h>
#import <NativeScript.h>

TNSRuntime* runtime;

static NSUncaughtExceptionHandler* oldExceptionHandler = NULL;

static void TNSObjectiveCUncaughtExceptionHandler(NSException* currentException) {
JSGlobalContextRef context = runtime.globalContext;
JSObjectRef globalObject = JSContextGetGlobalObject(context);

JSStringRef uncaughtPropertyName = JSStringCreateWithUTF8CString("__onUncaughtError"); // Keep in sync with JSErrors.mm
JSValueRef uncaughtCallback = JSObjectGetProperty(context, globalObject, uncaughtPropertyName, NULL);
JSStringRelease(uncaughtPropertyName);

if (!JSValueIsUndefined(context, uncaughtCallback)) {
JSStringRef reason = JSStringCreateWithUTF8CString(currentException.reason.UTF8String);
JSObjectRef error = JSObjectMakeError(
context, 1, (JSValueRef[]){ JSValueMakeString(context, reason) }, NULL);
JSStringRelease(reason);

JSValueRef wrappedException = [runtime convertObject:currentException];
JSStringRef nativeExceptionPropertyName = JSStringCreateWithUTF8CString("nativeException");
JSObjectSetProperty(context, error, nativeExceptionPropertyName,
wrappedException, kJSPropertyAttributeNone, NULL);
JSStringRelease(nativeExceptionPropertyName);

JSValueRef callError = NULL;
JSObjectCallAsFunction(context, (JSObjectRef)uncaughtCallback, NULL, 1,
(JSValueRef[]){ error }, &callError);
if (callError) {
JSStringRef callErrorMessage = JSValueToStringCopy(context, callError, NULL);
NSLog(@"Error executing uncaught error handler: %@",
CFBridgingRelease(JSStringCopyCFString(CFAllocatorGetDefault(),
callErrorMessage)));
JSStringRelease(callErrorMessage);
}
}

NSLog(@"*** JavaScript call stack:\n(\n%@\n)", [runtime getCurrentStack]);

if (oldExceptionHandler) {
oldExceptionHandler(currentException);
}
}

static void TNSInstallExceptionHandler() {
oldExceptionHandler = NSGetUncaughtExceptionHandler();
NSSetUncaughtExceptionHandler(TNSObjectiveCUncaughtExceptionHandler);
}

#endif /* TNSExceptionHandler_h */
3 changes: 1 addition & 2 deletions src/NativeScript/TNSRuntime+Diagnostics.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@

@interface TNSRuntime (Diagnostics)

+ (void)_printCurrentStack;
+ (NSString*)_getCurrentStack;
- (NSString*)getCurrentStack;

@end
49 changes: 21 additions & 28 deletions src/NativeScript/TNSRuntime+Diagnostics.mm
Original file line number Diff line number Diff line change
Expand Up @@ -7,44 +7,37 @@
//

#import "TNSRuntime+Diagnostics.h"
#include <iostream>
#include <iomanip>
#include <sstream>
#include <JavaScriptCore/APICast.h>
#include <JavaScriptCore/ScriptCallStack.h>
#include <JavaScriptCore/ScriptCallStackFactory.h>
#import "TNSRuntime+Private.h"

#import <Foundation/NSString.h>

using namespace JSC;
using namespace NativeScript;

@implementation TNSRuntime (Diagnostics)

struct StackTraceFunctor {
public:
StackTraceFunctor(WTF::StringBuilder& trace)
: _trace(trace)
, line(0) {
}

StackVisitor::Status operator()(StackVisitor& visitor) {
if (line++) {
_trace.append("\n");
}
this->_trace.append(visitor->toString().utf8().data());
return StackVisitor::Continue;
}

private:
WTF::StringBuilder& _trace;
int line;
};

+ (void)_printCurrentStack {
NSLog(@"--> JavaScript Stack trace:\n%@", [self _getCurrentStack]);
NSLog(@"%s is deprecated - use [runtime getCurrentStack] instead.", __FUNCTION__);
}

+ (NSString*)_getCurrentStack {
WTF::StringBuilder trace;
StackTraceFunctor functor(trace);
static_cast<TNSRuntime*>(WTF::wtfThreadData().m_apiData)->_vm->topCallFrame->iterate(functor);
return (NSString*)trace.toString().createCFString().autorelease();
- (NSString*)getCurrentStack {
std::stringstream output;
RefPtr<Inspector::ScriptCallStack> callStack = Inspector::createScriptCallStack(self->_vm->topCallFrame, Inspector::ScriptCallStack::maxCallStackSizeToCapture);
for (size_t i = 0; i < callStack->size(); ++i) {
Inspector::ScriptCallFrame frame = callStack->at(i);
output << "\t" << std::setw(4) << std::setfill(' ') << std::left << i << frame.functionName().utf8().data() << "@" << frame.sourceURL().utf8().data();
if (frame.lineNumber() && frame.columnNumber()) {
output << ":" << frame.lineNumber() << ":" << frame.columnNumber();
}
if (i != callStack->size() - 1) {
output << "\n";
}
}
return [NSString stringWithUTF8String:output.str().c_str()];
}

@end
4 changes: 3 additions & 1 deletion src/NativeScript/TNSRuntime.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ FOUNDATION_EXTERN void TNSSetUncaughtErrorHandler(TNSUncaughtErrorHandler handle

@interface TNSRuntime : NSObject

@property(nonatomic, retain) NSString* applicationPath;
@property(nonatomic, retain, readonly) NSString* applicationPath;

+ (void)initializeMetadata:(void*)metadataPtr;

Expand All @@ -29,4 +29,6 @@ FOUNDATION_EXTERN void TNSSetUncaughtErrorHandler(TNSUncaughtErrorHandler handle

- (void)executeModule:(NSString*)entryPointModuleIdentifier;

- (JSValueRef)convertObject:(id)object;

@end
6 changes: 6 additions & 0 deletions src/NativeScript/TNSRuntime.mm
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#import "TNSRuntime+Private.h"
#include "JSErrors.h"
#include "Metadata/Metadata.h"
#include "ObjCTypes.h"

using namespace JSC;
using namespace NativeScript;
Expand Down Expand Up @@ -118,6 +119,11 @@ - (void)executeModule:(NSString*)entryPointModuleIdentifier {
}
}

- (JSValueRef)convertObject:(id)object {
JSLockHolder lock(*self->_vm);
return toRef(self->_globalObject->globalExec(), toValue(self->_globalObject->globalExec(), object));
}

- (void)dealloc {
[self->_applicationPath release];
#if PLATFORM(IOS)
Expand Down
4 changes: 2 additions & 2 deletions src/debugging/TNSDebugging.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ static dispatch_source_t TNSCreateInspectorServer(
return listenSource;
}

static void TNSObjectiveCUncaughtExceptionHandler(NSException *exception) {
static void TNSInspectorUncaughtExceptionHandler(NSException *exception) {
JSStringRef exceptionMessage =
JSStringCreateWithUTF8CString(exception.description.UTF8String);

Expand Down Expand Up @@ -211,7 +211,7 @@ static void TNSEnableRemoteInspector(int argc, char **argv) {

inspector = [runtime attachInspectorWithHandler:sendMessageToFrontend];

NSSetUncaughtExceptionHandler(&TNSObjectiveCUncaughtExceptionHandler);
NSSetUncaughtExceptionHandler(&TNSInspectorUncaughtExceptionHandler);

if (isWaitingForDebugger) {
isWaitingForDebugger = NO;
Expand Down
1 change: 1 addition & 0 deletions tests/TestFixtures/exported-symbols.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ functionReturningFunctionPtrAsVoidPtr
functionReturnsCFRetained
functionReturnsNSRetained
functionReturnsUnmanaged
functionThrowsException
functionWhichReturnsSimpleFunctionPointer
functionWith_BoolPtr
functionWith_VoidPtr
Expand Down