|
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