|
6 | 6 | #include "js_native_api_types.h" |
7 | 7 | #include "node_api_util.h" |
8 | 8 | #include "objc/runtime.h" |
| 9 | +#include <cstring> |
9 | 10 |
|
10 | 11 | struct Block_descriptor_1 { |
11 | 12 | unsigned long int reserved; // NULL |
|
27 | 28 | nativescript::Closure* closure; |
28 | 29 | }; |
29 | 30 |
|
30 | | -void block_copy(void* dest, void* src) {} |
31 | | -void block_release(void* src) {} |
| 31 | +namespace { |
| 32 | + |
| 33 | +constexpr int kBlockNeedsFree = (1 << 24); |
| 34 | +constexpr int kBlockHasCopyDispose = (1 << 25); |
| 35 | +constexpr int kBlockRefCountOne = (1 << 1); |
| 36 | + |
| 37 | +void block_copy(void* dest, void* src) { |
| 38 | + auto dst = static_cast<Block_literal_1*>(dest); |
| 39 | + auto source = static_cast<Block_literal_1*>(src); |
| 40 | + dst->closure = source->closure; |
| 41 | +} |
| 42 | + |
| 43 | +void block_release(void* src) { |
| 44 | + auto block = static_cast<Block_literal_1*>(src); |
| 45 | + if (block == nullptr) { |
| 46 | + return; |
| 47 | + } |
| 48 | + |
| 49 | + if (block->closure != nullptr) { |
| 50 | + delete block->closure; |
| 51 | + block->closure = nullptr; |
| 52 | + } |
| 53 | +} |
| 54 | + |
| 55 | +Block_descriptor_1 kBlockDescriptor = { |
| 56 | + .reserved = 0, |
| 57 | + .size = sizeof(Block_literal_1), |
| 58 | + .copy_helper = block_copy, |
| 59 | + .dispose_helper = block_release, |
| 60 | + .signature = nullptr, |
| 61 | +}; |
| 62 | + |
| 63 | +} // namespace |
32 | 64 |
|
33 | 65 | void block_finalize(napi_env env, void* data, void* hint) { |
34 | | - auto block = (Block_literal_1*)data; |
35 | | - delete block->closure; |
36 | | - delete block; |
| 66 | + auto block = static_cast<Block_literal_1*>(data); |
| 67 | + if (block == nullptr) { |
| 68 | + return; |
| 69 | + } |
| 70 | + |
| 71 | + if (block->closure != nullptr) { |
| 72 | + delete block->closure; |
| 73 | + block->closure = nullptr; |
| 74 | + } |
| 75 | + |
| 76 | + free(block); |
37 | 77 | } |
38 | 78 |
|
39 | 79 | namespace nativescript { |
40 | 80 |
|
| 81 | +void* mallocBlockISA = nullptr; |
41 | 82 | void* stackBlockISA = nullptr; |
42 | 83 |
|
43 | 84 | id registerBlock(napi_env env, Closure* closure, napi_value callback) { |
44 | | - auto block = new Block_literal_1(); |
| 85 | + auto block = static_cast<Block_literal_1*>(malloc(sizeof(Block_literal_1))); |
| 86 | + memset(block, 0, sizeof(Block_literal_1)); |
| 87 | + |
| 88 | + if (mallocBlockISA == nullptr) { |
| 89 | + mallocBlockISA = dlsym(RTLD_DEFAULT, "_NSConcreteMallocBlock"); |
| 90 | + } |
| 91 | + |
45 | 92 | if (stackBlockISA == nullptr) { |
46 | 93 | stackBlockISA = dlsym(RTLD_DEFAULT, "_NSConcreteStackBlock"); |
47 | 94 | } |
48 | | - block->isa = stackBlockISA; |
49 | | - block->flags = (1 << 29) | (1 << 25); |
| 95 | + |
| 96 | + block->isa = mallocBlockISA != nullptr ? mallocBlockISA : stackBlockISA; |
| 97 | + block->flags = kBlockNeedsFree | kBlockHasCopyDispose | kBlockRefCountOne; |
50 | 98 | block->reserved = 0; |
51 | 99 | block->invoke = closure->fnptr; |
52 | | - block->descriptor = new Block_descriptor_1(); |
| 100 | + block->descriptor = &kBlockDescriptor; |
53 | 101 | block->closure = closure; |
54 | 102 |
|
55 | | - block->descriptor->reserved = 0; |
56 | | - block->descriptor->size = sizeof(Block_literal_1); |
57 | | - block->descriptor->copy_helper = block_copy; |
58 | | - block->descriptor->dispose_helper = block_release; |
59 | | - block->descriptor->signature = nullptr; |
60 | | - |
61 | | - napi_remove_wrap(env, callback, nullptr); |
62 | | - napi_ref ref = nullptr; |
63 | | - // TODO: fix memory management of objc blocks here |
64 | | - // napi_wrap(env, callback, block, block_finalize, nullptr, &ref); |
65 | | - // if (ref == nullptr) { |
66 | | - // Deno doesn't handle napi_wrap properly. |
67 | | - ref = make_ref(env, callback, 1); |
68 | | - // } else { |
69 | | - // uint32_t refCount; |
70 | | - // napi_reference_ref(env, ref, &refCount); |
71 | | - // } |
72 | | - closure->func = ref; |
| 103 | + closure->func = make_ref(env, callback, 1); |
73 | 104 |
|
74 | 105 | auto bridgeState = ObjCBridgeState::InstanceData(env); |
75 | 106 |
|
|
0 commit comments