Skip to content

Commit

Permalink
Merge branch 'NativeScript:main' into teodor/embedding
Browse files Browse the repository at this point in the history
  • Loading branch information
tdermendjiev authored Oct 19, 2023
2 parents deabadf + 5700ff6 commit 41d55f5
Show file tree
Hide file tree
Showing 9 changed files with 129 additions and 7 deletions.
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,25 @@
## [8.6.0](https://github.com/NativeScript/ios/compare/v8.5.2...v8.6.1) (2023-10-09)


### Bug Fixes

* bridge release adapters ([#224](https://github.com/NativeScript/ios/issues/224)) ([70b1802](https://github.com/NativeScript/ios/commit/70b180202dc0752d01ae5b9249cbaabae65f53cc))
* delay isolate disposal when isolate is in use ([5a6c2ee](https://github.com/NativeScript/ios/commit/5a6c2ee5efa0c557c94ae56da0d3b3a31911d1b8))
* don't suppress timer exceptions ([0c4b819](https://github.com/NativeScript/ios/commit/0c4b819941b0327e572772018298cf9cf181436e))
* fix setInterval not repeating correctly ([022893f](https://github.com/NativeScript/ios/commit/022893f1dcd9a7649db73e9735ff12e9246b3585))
* prevent JS function to native block leak ([#223](https://github.com/NativeScript/ios/issues/223)) ([a6d7332](https://github.com/NativeScript/ios/commit/a6d73323718a1de12c5a9f4865a6abfe06fd6e03))


### Features

* add interop.stringFromCString ([#228](https://github.com/NativeScript/ios/issues/228)) ([185c12d](https://github.com/NativeScript/ios/commit/185c12dc85e86747f266867fb208c71caf5fc6b3))
* add native timers ([#221](https://github.com/NativeScript/ios/issues/221)) ([119470f](https://github.com/NativeScript/ios/commit/119470f249c5aa85c4c2d0b1c9b5b691003c1ec7))
* add timer strong retainer annotation ([efef961](https://github.com/NativeScript/ios/commit/efef961a67519aed881637ac0291894f3325b111))
* log the fullMessage with more details about the error ([#229](https://github.com/NativeScript/ios/issues/229)) ([d67588c](https://github.com/NativeScript/ios/commit/d67588cb3866212ccd86b105edf1207fddde2db9))
* use node logic for globals and modules ([#215](https://github.com/NativeScript/ios/issues/215)) ([a66cc42](https://github.com/NativeScript/ios/commit/a66cc42c768ee7712d1c1f441b8c4e8e88a19eca))



## [8.5.2](https://github.com/NativeScript/ios/compare/v8.5.1...v8.5.2) (2023-05-24)


Expand Down
2 changes: 1 addition & 1 deletion NativeScript/NativeScript-Prefix.pch
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#ifndef NativeScript_Prefix_pch
#define NativeScript_Prefix_pch

#define NATIVESCRIPT_VERSION "8.5.2-alpha.3"
#define NATIVESCRIPT_VERSION "8.6.1"

#ifdef DEBUG
#define SIZEOF_OFF_T 8
Expand Down
1 change: 1 addition & 0 deletions NativeScript/runtime/Interop.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ class Interop {
static void InitializeStruct(v8::Local<v8::Context> context, void* destBuffer, std::vector<StructField> fields, v8::Local<v8::Value> inititalizer, ptrdiff_t& position);
static void RegisterInteropType(v8::Local<v8::Context> context, v8::Local<v8::Object> types, std::string name, PrimitiveDataWrapper* wrapper, bool autoDelete = true);
static void RegisterBufferFromDataFunction(v8::Local<v8::Context> context, v8::Local<v8::Object> interop);
static void RegisterStringFromCString(v8::Local<v8::Context> context, v8::Local<v8::Object> interop);
static void RegisterHandleOfFunction(v8::Local<v8::Context> context, v8::Local<v8::Object> interop);
static void RegisterAllocFunction(v8::Local<v8::Context> context, v8::Local<v8::Object> interop);
static void RegisterFreeFunction(v8::Local<v8::Context> context, v8::Local<v8::Object> interop);
Expand Down
55 changes: 55 additions & 0 deletions NativeScript/runtime/InteropTypes.mm
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
Pointer::Register(context, interop);
FunctionReference::Register(context, interop);
RegisterBufferFromDataFunction(context, interop);
RegisterStringFromCString(context, interop);
RegisterHandleOfFunction(context, interop);
RegisterAllocFunction(context, interop);
RegisterFreeFunction(context, interop);
Expand Down Expand Up @@ -140,6 +141,60 @@
tns::Assert(success, isolate);
}

void Interop::RegisterStringFromCString(Local<Context> context, Local<Object> interop) {
Local<v8::Function> func;
bool success = v8::Function::New(context, [](const FunctionCallbackInfo<Value>& info) {
Isolate* isolate = info.GetIsolate();
tns::Assert(info.Length() >= 1 && info[0]->IsObject(), isolate);
Local<Object> arg = info[0].As<Object>();
int stringLength = -1;
if(info.Length() >= 2 && !info[1].IsEmpty() && !info[1]->IsNullOrUndefined()) {
auto desiredLength = ToNumber(isolate, info[1]);
if (desiredLength != NAN) {
stringLength = desiredLength;
}
}
tns::Assert(arg->InternalFieldCount() > 0 && arg->GetInternalField(0)->IsExternal(), isolate);

Local<External> ext = arg->GetInternalField(0).As<External>();
BaseDataWrapper* wrapper = static_cast<BaseDataWrapper*>(ext->Value());
tns::Assert(wrapper != nullptr);
char* data = nullptr;
switch (wrapper->Type()) {
case WrapperType::Pointer:
{
PointerWrapper* pointerWrapper = static_cast<PointerWrapper*>(wrapper);
data = static_cast<char*>(pointerWrapper->Data());
}
break;
case WrapperType::Reference:
{
ReferenceWrapper* referenceWrapper = static_cast<ReferenceWrapper*>(wrapper);
if (referenceWrapper->Data() != nullptr) {
data = static_cast<char*>(referenceWrapper->Data());
break;
}
auto wrappedValue = referenceWrapper->Value()->Get(isolate);
auto wrappedWrapper = tns::GetValue(isolate, wrappedValue);
tns::Assert(wrappedWrapper->Type() == WrapperType::Pointer);
data = static_cast<char*>((static_cast<PointerWrapper*>(wrappedWrapper))->Data());
}
default:
break;
}
tns::Assert(data != nullptr);

auto result = v8::String::NewFromUtf8(isolate, data, v8::NewStringType::kNormal, stringLength).ToLocalChecked();
info.GetReturnValue().Set(result);
}).ToLocal(&func);

Isolate* isolate = context->GetIsolate();
tns::Assert(success, isolate);

success = interop->Set(context, tns::ToV8String(isolate, "stringFromCString"), func).FromMaybe(false);
tns::Assert(success, isolate);
}

void Interop::RegisterHandleOfFunction(Local<Context> context, Local<Object> interop) {
Local<v8::Function> func;
bool success = v8::Function::New(context, [](const FunctionCallbackInfo<Value>& info) {
Expand Down
2 changes: 1 addition & 1 deletion NativeScript/runtime/MetadataInlines.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const InterfaceMeta* GlobalTable<TYPE>::findInterfaceMeta(const char* identifier

// Meta should be an interface, but it could also be a protocol in case of a
// private interface having the same name as a public protocol
assert(meta->type() == MetaType::Interface || (meta->type() == MetaType::ProtocolType && objc_getClass(meta->name()) != nullptr && objc_getProtocol(meta->name()) != nullptr));
ASSERT(meta->type() == MetaType::Interface || (meta->type() == MetaType::ProtocolType && objc_getClass(meta->name()) != nullptr && objc_getProtocol(meta->name()) != nullptr));

if (meta->type() != MetaType::Interface) {
return nullptr;
Expand Down
18 changes: 15 additions & 3 deletions NativeScript/runtime/NativeScriptException.mm
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,20 @@
bool success = global->Get(context, tns::ToV8String(isolate, cbName)).ToLocal(&handler);

std::string stackTrace = GetErrorStackTrace(isolate, message->GetStackTrace());
std::string fullMessage;

auto errObject = error.As<Object>();
auto fullMessageString = tns::ToV8String(isolate, "fullMessage");
if(errObject->HasOwnProperty(context, fullMessageString).ToChecked()) {
// check if we have a "fullMessage" on the error, and log that instead - since it includes more info about the exception.
auto fullMessage_ = errObject->Get(context, fullMessageString).ToLocalChecked();
fullMessage = tns::ToString(isolate, fullMessage_);
} else {
Local<v8::String> messageV8String = message->Get();
std::string messageString = tns::ToString(isolate, messageV8String);
fullMessage = messageString + "\n at \n" + stackTrace;
}

if (success && handler->IsFunction()) {
if (error->IsObject()) {
tns::Assert(error.As<Object>()->Set(context, tns::ToV8String(isolate, "stackTrace"), tns::ToV8String(isolate, stackTrace)).FromMaybe(false), isolate);
Expand All @@ -56,9 +70,7 @@
}

if (!isDiscarded) {
Local<v8::String> messageV8String = message->Get();
std::string messageString = tns::ToString(isolate, messageV8String);
NSString* name = [NSString stringWithFormat:@"NativeScript encountered a fatal error: %s\n at \n%s", messageString.c_str(), stackTrace.c_str()];
NSString* name = [NSString stringWithFormat:@"NativeScript encountered a fatal error:\n\n%s", fullMessage.c_str()];
// we throw the exception on main thread
// otherwise it seems that when getting NSException info from NSSetUncaughtExceptionHandler
// we are missing almost all data. No explanation for why yet
Expand Down
2 changes: 1 addition & 1 deletion NativeScript/runtime/robin_hood.h
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ static Counts& counts() {
// workaround missing "is_trivially_copyable" in g++ < 5.0
// See https://stackoverflow.com/a/31798726/48181
#if defined(__GNUC__) && __GNUC__ < 5
# define ROBIN_HOOD_IS_TRIVIALLY_COPYABLE(...) __has_trivial_copy(__VA_ARGS__)
# define ROBIN_HOOD_IS_TRIVIALLY_COPYABLE(...) __is_trivially_copyable(__VA_ARGS__)
#else
# define ROBIN_HOOD_IS_TRIVIALLY_COPYABLE(...) std::is_trivially_copyable<__VA_ARGS__>::value
#endif
Expand Down
32 changes: 32 additions & 0 deletions TestRunner/app/tests/Marshalling/ReferenceTests.js
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,38 @@ describe(module.id, function () {
expect(TNSGetOutput()).toBe(str);
expect(interop.handleof(result).toNumber() == interop.handleof(ptr).toNumber());
expect(NSString.stringWithUTF8String(result).toString()).toBe(str);
interop.free(ptr);
});

it("interops string from CString", function () {
const str = "test";
const ptr = interop.alloc((str.length + 1) * interop.sizeof(interop.types.uint8));
var reference = new interop.Reference(interop.types.uint8, ptr);
for (ii in str) {
const i = parseInt(ii);
reference[i] = str.charCodeAt(i);
}
reference[str.length] = 0;
expect(interop.stringFromCString(ptr)).toBe(str);
expect(interop.stringFromCString(reference)).toBe(str);
interop.free(ptr);
});

it("interops string from CString with fixed length", function () {
const str = "te\0st";
const ptr = interop.alloc((str.length + 1) * interop.sizeof(interop.types.uint8));
var reference = new interop.Reference(interop.types.uint8, ptr);
for (ii in str) {
const i = parseInt(ii);
reference[i] = str.charCodeAt(i);
}
reference[str.length] = 0;
// no length means it will go until it finds \0
expect(interop.stringFromCString(ptr)).toBe('te');
expect(interop.stringFromCString(ptr, 1)).toBe('t');
expect(interop.stringFromCString(ptr, str.length)).toBe(str);
expect(interop.stringFromCString(reference, str.length)).toBe(str);
interop.free(ptr);
});

it("CString should be passed as its UTF8 encoding and returned as a reference to unsigned characters", function () {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@nativescript/ios",
"description": "NativeScript Runtime for iOS",
"version": "8.5.2",
"version": "8.6.1",
"keywords": [
"NativeScript",
"iOS",
Expand Down

0 comments on commit 41d55f5

Please sign in to comment.