|
8 | 8 | #include "MetadataReader.h" |
9 | 9 | #include "ObjCBridge.h" |
10 | 10 | #include "ffi.h" |
| 11 | +#include "ffi/Struct.h" |
11 | 12 | #include "js_native_api.h" |
12 | 13 | #include "js_native_api_types.h" |
13 | 14 | #include "node_api_util.h" |
|
18 | 19 | #include <stdbool.h> |
19 | 20 | #include <memory> |
20 | 21 | #include <string> |
21 | | -#include <vector> |
22 | | -#include <unordered_set> |
23 | 22 | #include <unordered_map> |
| 23 | +#include <unordered_set> |
| 24 | +#include <vector> |
24 | 25 |
|
25 | 26 | namespace nativescript { |
26 | 27 |
|
|
44 | 45 | ffi_type* typeFromStruct(napi_env env, const char** encoding) { |
45 | 46 | // Extract struct name for cycle detection |
46 | 47 | std::string structname; |
47 | | - const char* nameStart = *encoding + 1; // skip '{' |
| 48 | + const char* nameStart = *encoding + 1; // skip '{' |
48 | 49 | const char* c = nameStart; |
49 | 50 | while (*c != '=') { |
50 | 51 | structname += *c; |
|
59 | 60 | forwardType->size = 0; |
60 | 61 | forwardType->alignment = 0; |
61 | 62 | forwardType->elements = nullptr; |
62 | | - |
| 63 | + |
63 | 64 | // Cache this forward declaration for later resolution |
64 | 65 | forwardDeclaredEncodingStructs[structname] = forwardType; |
65 | | - |
| 66 | + |
66 | 67 | // Skip the struct encoding |
67 | 68 | (*encoding)++; // skip '{' |
68 | 69 | while (**encoding != '}') { |
69 | 70 | (*encoding)++; |
70 | 71 | } |
71 | 72 | (*encoding)++; // skip '}' |
72 | | - |
| 73 | + |
73 | 74 | return forwardType; |
74 | 75 | } |
75 | 76 |
|
|
82 | 83 | (*encoding)++; |
83 | 84 | } |
84 | 85 | (*encoding)++; // skip '}' |
85 | | - |
| 86 | + |
86 | 87 | return forwardIt->second; |
87 | 88 | } |
88 | 89 |
|
|
126 | 127 | forwardType->size = type->size; |
127 | 128 | forwardType->alignment = type->alignment; |
128 | 129 | forwardType->elements = type->elements; |
129 | | - |
| 130 | + |
130 | 131 | // Clean up the temporary type and use the forward declaration |
131 | 132 | delete type; |
132 | 133 | type = forwardType; |
|
149 | 150 | forwardType->size = 0; |
150 | 151 | forwardType->alignment = 0; |
151 | 152 | forwardType->elements = nullptr; |
152 | | - |
| 153 | + |
153 | 154 | // Cache this forward declaration for later resolution |
154 | 155 | forwardDeclaredStructs[structOffset] = forwardType; |
155 | 156 | return forwardType; |
|
174 | 175 | auto name = reader->resolveString(nameOffset); |
175 | 176 | bool next = true; |
176 | 177 | MDSectionOffset currentOffset = structOffset + sizeof(MDSectionOffset); // skip name |
177 | | - currentOffset += sizeof(uint16_t); // skip size |
| 178 | + currentOffset += sizeof(uint16_t); // skip size |
178 | 179 |
|
179 | 180 | std::vector<ffi_type*> elements; |
180 | 181 |
|
|
205 | 206 | forwardType->size = type->size; |
206 | 207 | forwardType->alignment = type->alignment; |
207 | 208 | forwardType->elements = type->elements; |
208 | | - |
| 209 | + |
209 | 210 | // Clean up the temporary type and use the forward declaration |
210 | 211 | delete type; |
211 | 212 | type = forwardType; |
@@ -583,6 +584,9 @@ void toNative(napi_env env, napi_value value, void* result, bool* shouldFree, |
583 | 584 | double val; |
584 | 585 | napi_coerce_to_number(env, value, &value); |
585 | 586 | napi_get_value_double(env, value, &val); |
| 587 | + if (std::isnan(val) || std::isinf(val)) { |
| 588 | + val = 0.0; |
| 589 | + } |
586 | 590 | *(double*)result = val; |
587 | 591 | } |
588 | 592 |
|
@@ -723,6 +727,15 @@ void toNative(napi_env env, napi_value value, void* result, bool* shouldFree, |
723 | 727 | return; |
724 | 728 | } |
725 | 729 |
|
| 730 | + if (StructObject::isInstance(env, value)) { |
| 731 | + StructObject* structObj = StructObject::unwrap(env, value); |
| 732 | + if (structObj != nullptr) { |
| 733 | + *res = structObj->data; |
| 734 | + } else |
| 735 | + *res = nullptr; |
| 736 | + return; |
| 737 | + } |
| 738 | + |
726 | 739 | void* wrapped; |
727 | 740 | status = napi_unwrap(env, value, &wrapped); |
728 | 741 | if (status == napi_ok) { |
@@ -957,7 +970,7 @@ void toNative(napi_env env, napi_value value, void* result, bool* shouldFree, |
957 | 970 | StringTypeConv() { type = &ffi_type_pointer; } |
958 | 971 |
|
959 | 972 | napi_value toJS(napi_env env, void* cont, uint32_t flags) override { |
960 | | - void *value = *((void**)cont); |
| 973 | + void* value = *((void**)cont); |
961 | 974 | napi_value result; |
962 | 975 | napi_create_string_utf8(env, (char*)value, NAPI_AUTO_LENGTH, &result); |
963 | 976 | return result; |
@@ -1677,23 +1690,23 @@ void toNative(napi_env env, napi_value value, void* result, bool* shouldFree, |
1677 | 1690 | structname += *c; |
1678 | 1691 | c++; |
1679 | 1692 | } |
1680 | | - |
| 1693 | + |
1681 | 1694 | // Check if we already have a cached StructTypeConv for this encoding-based struct |
1682 | 1695 | auto cacheIt = encodingStructCache.find(structname); |
1683 | 1696 | if (cacheIt != encodingStructCache.end()) { |
1684 | 1697 | return cacheIt->second; |
1685 | 1698 | } |
1686 | | - |
| 1699 | + |
1687 | 1700 | auto bridgeState = ObjCBridgeState::InstanceData(env); |
1688 | 1701 | // NSLog(@"struct: %s, %d", structname.c_str(), |
1689 | 1702 | // bridgeState->structOffsets[structname]); |
1690 | 1703 | auto structOffset = bridgeState->structOffsets[structname]; |
1691 | 1704 | auto type = typeFromStruct(env, encoding); |
1692 | 1705 | auto structTypeConv = std::make_shared<StructTypeConv>(StructTypeConv(structOffset, type)); |
1693 | | - |
| 1706 | + |
1694 | 1707 | // Cache the StructTypeConv |
1695 | 1708 | encodingStructCache[structname] = structTypeConv; |
1696 | | - |
| 1709 | + |
1697 | 1710 | return structTypeConv; |
1698 | 1711 | } |
1699 | 1712 | case 'b': { |
@@ -1865,26 +1878,26 @@ void toNative(napi_env env, napi_value value, void* result, bool* shouldFree, |
1865 | 1878 | } |
1866 | 1879 | structOffset += isUnion ? reader->unionsOffset : reader->structsOffset; |
1867 | 1880 | auto structName = reader->getString(structOffset); |
1868 | | - |
| 1881 | + |
1869 | 1882 | // Check if we already have a cached StructTypeConv for this struct |
1870 | 1883 | auto cacheIt = structTypeCache.find(structOffset); |
1871 | 1884 | if (cacheIt != structTypeCache.end()) { |
1872 | 1885 | return cacheIt->second; |
1873 | 1886 | } |
1874 | | - |
| 1887 | + |
1875 | 1888 | // Check if we're currently processing this struct (recursion detection) |
1876 | 1889 | bool isRecursive = processingStructs.find(structOffset) != processingStructs.end(); |
1877 | | - |
| 1890 | + |
1878 | 1891 | ffi_type* type = nullptr; |
1879 | 1892 | if (opaquePointers != 2 && !isRecursive) { |
1880 | 1893 | type = typeFromStruct(env, reader, structOffset, isUnion); |
1881 | 1894 | } |
1882 | | - |
| 1895 | + |
1883 | 1896 | auto structTypeConv = std::make_shared<StructTypeConv>(structOffset, type); |
1884 | | - |
| 1897 | + |
1885 | 1898 | // Cache the StructTypeConv to handle recursion and avoid duplicates |
1886 | 1899 | structTypeCache[structOffset] = structTypeConv; |
1887 | | - |
| 1900 | + |
1888 | 1901 | return structTypeConv; |
1889 | 1902 | } |
1890 | 1903 |
|
|
0 commit comments