diff --git a/src/NativeScript/CMakeLists.txt b/src/NativeScript/CMakeLists.txt index 93d00bc09..f5b25be1a 100644 --- a/src/NativeScript/CMakeLists.txt +++ b/src/NativeScript/CMakeLists.txt @@ -59,7 +59,7 @@ set(HEADER_FILES ObjC/Inheritance/ObjCClassBuilder.h ObjC/Inheritance/ObjCExtend.h ObjC/Inheritance/ObjCTypeScriptExtend.h - ObjC/NSErrorWrapperConstructor.h + ObjC/NativeErrorWrapperConstructor.h ObjC/ObjCMethodCall.h ObjC/ObjCMethodCallback.h ObjC/ObjCPrimitiveTypes.h @@ -89,12 +89,12 @@ set(HEADER_FILES ) set(SOURCE_FILES - Calling/FFICall.cpp + Calling/FFICall.mm Calling/FFICallPrototype.cpp Calling/FFIFunctionCall.mm Calling/FFIFunctionCallback.cpp GlobalObject.mm - GlobalObject.moduleLoader.mm + GlobalObject.moduleLoader.mm inspector/CachedResource.mm inspector/DomainBackendDispatcher.cpp inspector/DomainInspectorAgent.cpp @@ -143,7 +143,7 @@ set(SOURCE_FILES ObjC/Inheritance/ObjCClassBuilder.mm ObjC/Inheritance/ObjCExtend.mm ObjC/Inheritance/ObjCTypeScriptExtend.mm - ObjC/NSErrorWrapperConstructor.mm + ObjC/NativeErrorWrapperConstructor.mm ObjC/ObjCMethodCall.mm ObjC/ObjCMethodCallback.mm ObjC/ObjCPrimitiveTypes.mm diff --git a/src/NativeScript/Calling/FFICall.cpp b/src/NativeScript/Calling/FFICall.mm similarity index 96% rename from src/NativeScript/Calling/FFICall.cpp rename to src/NativeScript/Calling/FFICall.mm index cc232e250..a99e6e3eb 100644 --- a/src/NativeScript/Calling/FFICall.cpp +++ b/src/NativeScript/Calling/FFICall.mm @@ -11,6 +11,8 @@ #include #include #include +#include "JSErrors.h" +#include "Interop.h" namespace NativeScript { using namespace JSC; @@ -93,9 +95,11 @@ EncodedJSValue JSC_HOST_CALL FFICall::call(ExecState* execState) { return JSValue::encode(execState->exception()); } - { + @try { JSLock::DropAllLocks locksDropper(execState); ffi_call(callee->_cif, FFI_FN(invocation.function), invocation._buffer + callee->_returnOffset, reinterpret_cast(invocation._buffer + callee->_argsArrayOffset)); + } @catch (NSException* localException) { + reportFatalErrorBeforeShutdown(execState, Exception::create(execState->vm(), interop(execState)->wrapException(execState, localException))); } JSValue result = callee->_returnType.read(execState, invocation._buffer + callee->_returnOffset, callee->_returnTypeCell.get()); diff --git a/src/NativeScript/Interop.h b/src/NativeScript/Interop.h index 2717145f3..65d5dad7d 100644 --- a/src/NativeScript/Interop.h +++ b/src/NativeScript/Interop.h @@ -15,7 +15,7 @@ namespace NativeScript { class PointerInstance; class ReferenceInstance; -class NSErrorWrapperConstructor; +class NativeErrorWrapperConstructor; void* tryHandleofValue(const JSC::JSValue&, bool*); @@ -61,6 +61,8 @@ class Interop : public JSC::JSObject { #ifdef __OBJC__ JSC::ErrorInstance* wrapError(JSC::ExecState*, NSError*) const; + + JSC::ErrorInstance* wrapException(JSC::ExecState*, NSException*) const; #endif private: @@ -80,7 +82,7 @@ class Interop : public JSC::JSObject { JSC::WriteBarrier _functionReferenceInstanceStructure; - JSC::WriteBarrier _nsErrorWrapperConstructor; + JSC::WriteBarrier _nsErrorWrapperConstructor; JSC::WeakGCMap _pointerToInstance; diff --git a/src/NativeScript/Interop.mm b/src/NativeScript/Interop.mm index b4ca6961d..044cf9b82 100644 --- a/src/NativeScript/Interop.mm +++ b/src/NativeScript/Interop.mm @@ -38,7 +38,7 @@ #include "FunctionReferenceTypeInstance.h" #include "FunctionReferenceTypeConstructor.h" #include "ObjCTypes.h" -#include "NSErrorWrapperConstructor.h" +#include "NativeErrorWrapperConstructor.h" namespace NativeScript { using namespace JSC; @@ -244,8 +244,8 @@ static EncodedJSValue JSC_HOST_CALL interopFuncBufferFromData(ExecState* execSta this->putDirect(vm, Identifier::fromString(&vm, functionReferenceConstructor->name(globalObject->globalExec())), functionReferenceConstructor, ReadOnly | DontDelete); functionReferencePrototype->putDirect(vm, vm.propertyNames->constructor, functionReferenceConstructor, DontEnum); - this->_nsErrorWrapperConstructor.set(vm, this, NSErrorWrapperConstructor::create(vm, NSErrorWrapperConstructor::createStructure(vm, globalObject, globalObject->functionPrototype()))); - this->putDirect(vm, Identifier::fromString(&vm, "NSErrorWrapper"), this->_nsErrorWrapperConstructor.get()); + this->_nsErrorWrapperConstructor.set(vm, this, NativeErrorWrapperConstructor::create(vm, NativeErrorWrapperConstructor::createStructure(vm, globalObject, globalObject->functionPrototype()))); + this->putDirect(vm, Identifier::fromString(&vm, "NativeErrorWrapper"), this->_nsErrorWrapperConstructor.get()); this->putDirectNativeFunction(vm, globalObject, Identifier::fromString(&vm, WTF::ASCIILiteral("alloc")), 0, &interopFuncAlloc, NoIntrinsic, ReadOnly | DontDelete); this->putDirectNativeFunction(vm, globalObject, Identifier::fromString(&vm, WTF::ASCIILiteral("free")), 0, &interopFuncFree, NoIntrinsic, ReadOnly | DontDelete); @@ -335,10 +335,15 @@ static EncodedJSValue JSC_HOST_CALL interopFuncBufferFromData(ExecState* execSta visitor.append(&interop->_nsErrorWrapperConstructor); } +#ifdef __OBJC__ ErrorInstance* Interop::wrapError(ExecState* execState, NSError* error) const { return this->_nsErrorWrapperConstructor->createError(execState, error); } +ErrorInstance* Interop::wrapException(ExecState* execState, NSException* exception) const { + return this->_nsErrorWrapperConstructor->createError(execState, exception); +} + JSArrayBuffer* Interop::bufferFromData(ExecState* execState, NSData* data) const { JSArrayBuffer* arrayBuffer = JSArrayBuffer::create(execState->vm(), execState->lexicalGlobalObject()->arrayBufferStructure(), ArrayBuffer::createAdopted([data bytes], [data length], false)); @@ -346,4 +351,5 @@ static EncodedJSValue JSC_HOST_CALL interopFuncBufferFromData(ExecState* execSta arrayBuffer->putDirect(execState->vm(), execState->propertyNames().homeObjectPrivateName, NativeScript::toValue(execState, data)); return arrayBuffer; } +#endif } diff --git a/src/NativeScript/ObjC/NSErrorWrapperConstructor.mm b/src/NativeScript/ObjC/NSErrorWrapperConstructor.mm deleted file mode 100644 index 9e59669f2..000000000 --- a/src/NativeScript/ObjC/NSErrorWrapperConstructor.mm +++ /dev/null @@ -1,67 +0,0 @@ -// -// NSErrorWrapperConstructor.mm -// NativeScript -// -// Created by Yavor Georgiev on 30.12.15 г.. -// Copyright (c) 2015 Telerik. All rights reserved. -// - -#include "NSErrorWrapperConstructor.h" -#include "ObjCTypes.h" -#include - -namespace NativeScript { -using namespace JSC; - -const ClassInfo NSErrorWrapperConstructor::s_info = { "NSErrorWrapper", &Base::s_info, 0, CREATE_METHOD_TABLE(NSErrorWrapperConstructor) }; - -void NSErrorWrapperConstructor::destroy(JSCell* cell) { - jsCast(cell)->~NSErrorWrapperConstructor(); -} - -void NSErrorWrapperConstructor::finishCreation(VM& vm, JSGlobalObject* globalObject) { - Base::finishCreation(vm, WTF::ASCIILiteral("NSError")); - - ErrorPrototype* prototype = ErrorPrototype::create(vm, globalObject, ErrorPrototype::createStructure(vm, globalObject, globalObject->errorPrototype())); - prototype->putDirect(vm, vm.propertyNames->constructor, this); - this->putDirect(vm, vm.propertyNames->prototype, prototype); - prototype->putDirect(vm, vm.propertyNames->name, jsString(&vm, WTF::ASCIILiteral("NSErrorWrapper"))); - - this->_errorStructure.set(vm, this, ErrorInstance::createStructure(vm, globalObject, prototype)); -} - -void NSErrorWrapperConstructor::visitChildren(JSCell* cell, SlotVisitor& slotVisitor) { - Base::visitChildren(cell, slotVisitor); - - NSErrorWrapperConstructor* self = jsCast(cell); - slotVisitor.append(&self->_errorStructure); -} - -ErrorInstance* NSErrorWrapperConstructor::createError(ExecState* execState, NSError* error) const { - ErrorInstance* wrappedError = ErrorInstance::create(execState, this->errorStructure(), jsString(execState, error.localizedDescription)); - wrappedError->putDirect(execState->vm(), Identifier::fromString(execState, "error"), NativeScript::toValue(execState, error)); - - return wrappedError; -} - -static EncodedJSValue JSC_HOST_CALL constructErrorWrapper(ExecState* execState) { - NSErrorWrapperConstructor* self = jsCast(execState->callee()); - NSError* error = NativeScript::toObject(execState, execState->argument(0)); - - if (!error || ![error isKindOfClass:[NSError class]]) { - return throwVMTypeError(execState); - } - - return JSValue::encode(self->createError(execState, error)); -} - -ConstructType NSErrorWrapperConstructor::getConstructData(JSCell*, ConstructData& constructData) { - constructData.native.function = &constructErrorWrapper; - return ConstructTypeHost; -} - -CallType NSErrorWrapperConstructor::getCallData(JSCell*, CallData& callData) { - callData.native.function = &constructErrorWrapper; - return CallTypeHost; -} -} \ No newline at end of file diff --git a/src/NativeScript/ObjC/NSErrorWrapperConstructor.h b/src/NativeScript/ObjC/NativeErrorWrapperConstructor.h similarity index 69% rename from src/NativeScript/ObjC/NSErrorWrapperConstructor.h rename to src/NativeScript/ObjC/NativeErrorWrapperConstructor.h index 4fc4b1cfa..31166ad3b 100644 --- a/src/NativeScript/ObjC/NSErrorWrapperConstructor.h +++ b/src/NativeScript/ObjC/NativeErrorWrapperConstructor.h @@ -1,5 +1,5 @@ // -// NSErrorWrapperConstructor.h +// NativeErrorWrapperConstructor.h // NativeScript // // Created by Yavor Georgiev on 30.12.15 г.. @@ -11,12 +11,12 @@ @class NSError; namespace NativeScript { -class NSErrorWrapperConstructor : public JSC::InternalFunction { +class NativeErrorWrapperConstructor : public JSC::InternalFunction { public: typedef JSC::InternalFunction Base; - static NSErrorWrapperConstructor* create(JSC::VM& vm, JSC::Structure* structure) { - NSErrorWrapperConstructor* cell = new (NotNull, JSC::allocateCell(vm.heap)) NSErrorWrapperConstructor(vm, structure); + static NativeErrorWrapperConstructor* create(JSC::VM& vm, JSC::Structure* structure) { + NativeErrorWrapperConstructor* cell = new (NotNull, JSC::allocateCell(vm.heap)) NativeErrorWrapperConstructor(vm, structure); cell->finishCreation(vm, structure->globalObject()); return cell; } @@ -33,8 +33,10 @@ class NSErrorWrapperConstructor : public JSC::InternalFunction { JSC::ErrorInstance* createError(JSC::ExecState*, NSError*) const; + JSC::ErrorInstance* createError(JSC::ExecState*, NSException*) const; + private: - NSErrorWrapperConstructor(JSC::VM& vm, JSC::Structure* structure) + NativeErrorWrapperConstructor(JSC::VM& vm, JSC::Structure* structure) : Base(vm, structure) { } diff --git a/src/NativeScript/ObjC/NativeErrorWrapperConstructor.mm b/src/NativeScript/ObjC/NativeErrorWrapperConstructor.mm new file mode 100644 index 000000000..c924d8542 --- /dev/null +++ b/src/NativeScript/ObjC/NativeErrorWrapperConstructor.mm @@ -0,0 +1,72 @@ +// +// NativeErrorWrapperConstructor.mm +// NativeScript +// +// Created by Yavor Georgiev on 30.12.15 г.. +// Copyright (c) 2015 Telerik. All rights reserved. +// + +#include "NativeErrorWrapperConstructor.h" +#include "ObjCTypes.h" +#include + +namespace NativeScript { +using namespace JSC; + +const ClassInfo NativeErrorWrapperConstructor::s_info = { "NativeException", &Base::s_info, 0, CREATE_METHOD_TABLE(NativeErrorWrapperConstructor) }; + +void NativeErrorWrapperConstructor::destroy(JSCell* cell) { + jsCast(cell)->~NativeErrorWrapperConstructor(); +} + +void NativeErrorWrapperConstructor::finishCreation(VM& vm, JSGlobalObject* globalObject) { + Base::finishCreation(vm, WTF::ASCIILiteral("NativeException")); + + ErrorPrototype* prototype = ErrorPrototype::create(vm, globalObject, ErrorPrototype::createStructure(vm, globalObject, globalObject->errorPrototype())); + prototype->putDirect(vm, vm.propertyNames->constructor, this); + this->putDirect(vm, vm.propertyNames->prototype, prototype); + prototype->putDirect(vm, vm.propertyNames->name, jsString(&vm, WTF::ASCIILiteral("NativeException"))); + + this->_errorStructure.set(vm, this, ErrorInstance::createStructure(vm, globalObject, prototype)); +} + +void NativeErrorWrapperConstructor::visitChildren(JSCell* cell, SlotVisitor& slotVisitor) { + Base::visitChildren(cell, slotVisitor); + + NativeErrorWrapperConstructor* self = jsCast(cell); + slotVisitor.append(&self->_errorStructure); +} + +ErrorInstance* NativeErrorWrapperConstructor::createError(ExecState* execState, NSError* error) const { + ErrorInstance* wrappedError = ErrorInstance::create(execState, this->errorStructure(), jsString(execState, error.localizedDescription)); + wrappedError->putDirect(execState->vm(), Identifier::fromString(execState, "nativeException"), NativeScript::toValue(execState, error)); + return wrappedError; +} + +ErrorInstance* NativeErrorWrapperConstructor::createError(ExecState* execState, NSException* exception) const { + ErrorInstance* wrappedError = ErrorInstance::create(execState, this->errorStructure(), jsString(execState, exception.reason)); + wrappedError->putDirect(execState->vm(), Identifier::fromString(execState, "nativeException"), NativeScript::toValue(execState, exception)); + return wrappedError; +} + +static EncodedJSValue JSC_HOST_CALL constructErrorWrapper(ExecState* execState) { + NativeErrorWrapperConstructor* self = jsCast(execState->callee()); + NSError* error = NativeScript::toObject(execState, execState->argument(0)); + + if (!error || ![error isKindOfClass:[NSError class]]) { + return throwVMTypeError(execState); + } + + return JSValue::encode(self->createError(execState, error)); +} + +ConstructType NativeErrorWrapperConstructor::getConstructData(JSCell*, ConstructData& constructData) { + constructData.native.function = &constructErrorWrapper; + return ConstructTypeHost; +} + +CallType NativeErrorWrapperConstructor::getCallData(JSCell*, CallData& callData) { + callData.native.function = &constructErrorWrapper; + return CallTypeHost; +} +} \ No newline at end of file diff --git a/tests/TestFixtures/exported-symbols.txt b/tests/TestFixtures/exported-symbols.txt index 839513523..f5072b36b 100644 --- a/tests/TestFixtures/exported-symbols.txt +++ b/tests/TestFixtures/exported-symbols.txt @@ -5,6 +5,7 @@ functionReturningFunctionPtrAsVoidPtr functionReturnsCFRetained functionReturnsNSRetained functionReturnsUnmanaged +functionThrowsException functionWhichReturnsSimpleFunctionPointer functionWith_BoolPtr functionWith_VoidPtr diff --git a/tests/TestRunner/app/ApiTests.js b/tests/TestRunner/app/ApiTests.js index d2f2f148a..11a7bc247 100644 --- a/tests/TestRunner/app/ApiTests.js +++ b/tests/TestRunner/app/ApiTests.js @@ -239,7 +239,7 @@ describe(module.id, function () { TNSApi.new().methodError(1); } catch (e) { isThrown = true; - expect(e instanceof interop.NSErrorWrapper).toBe(true); + expect(e instanceof interop.NativeErrorWrapper).toBe(true); expect(e.stack).toEqual(jasmine.any(String)); } finally { expect(isThrown).toBe(true); @@ -435,7 +435,7 @@ describe(module.id, function () { var api = TNSApi.new(); api.methodError.async(api, [1]) .catch(error => { - expect(error).toEqual(jasmine.any(interop.NSErrorWrapper)); + expect(error).toEqual(jasmine.any(interop.NativeErrorWrapper)); done(); }); });