Skip to content

Commit 8c0e6ef

Browse files
committed
feat: return string for nsstring by default.
1 parent 081bbcb commit 8c0e6ef

26 files changed

+251
-115
lines changed

dart_native/example/ios/Podfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ EXTERNAL SOURCES:
2323

2424
SPEC CHECKSUMS:
2525
CocoaLumberjack: e8955b9d337ac307103b0a34fd141c32f27e53c5
26-
dart_native: e10848b23206739fc16a2455f41847418a8ceb3d
26+
dart_native: ba4adc85a5cf6faafbfa7de2252397388d9480da
2727
Flutter: 0e3d915762c693b495b44d77113d4970485de6ec
2828

2929
PODFILE CHECKSUM: f10e42e188a012076f9d5e111f499229a501832a

dart_native/example/ios/Runner.xcodeproj/project.pbxproj

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -276,12 +276,10 @@
276276
inputPaths = (
277277
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
278278
"${PODS_ROOT}/../Flutter/Flutter.framework",
279-
"${PODS_ROOT}/../.symlinks/plugins/dart_native/ios/DartNative.framework",
280279
);
281280
name = "[CP] Embed Pods Frameworks";
282281
outputPaths = (
283282
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework",
284-
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DartNative.framework",
285283
);
286284
runOnlyForDeploymentPostprocessing = 0;
287285
shellPath = /bin/sh;

dart_native/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@
4343
buildConfiguration = "Debug"
4444
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
4545
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
46+
enableAddressSanitizer = "YES"
47+
enableASanStackUseAfterReturn = "YES"
4648
launchStyle = "0"
4749
useCustomWorkingDirectory = "NO"
4850
ignoresPersistentStateOnLaunch = "NO"

dart_native/example/lib/ios/runtimestub.dart

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -244,9 +244,7 @@ class RuntimeStub extends NSObject {
244244
}
245245

246246
String fooNSString(String str) {
247-
Pointer<Void> result =
248-
perform(SEL('fooNSString:'), args: [str], decodeRetVal: false);
249-
return NSString.fromPointer(result).raw;
247+
return perform(SEL('fooNSString:'), args: [str]);
250248
}
251249

252250
Future<dynamic> fooNSStringAsync(String str) async {
@@ -257,9 +255,7 @@ class RuntimeStub extends NSObject {
257255

258256
String fooNSMutableString(String str) {
259257
NSMutableString _str = NSMutableString(str);
260-
Pointer<Void> result =
261-
perform(SEL('fooNSMutableString:'), args: [_str], decodeRetVal: false);
262-
return NSMutableString.fromPointer(result).raw;
258+
return perform(SEL('fooNSMutableString:'), args: [_str]);
263259
}
264260

265261
bool fooWithError(NSObjectRef<NSError> error) {

dart_native/example/lib/ios/unit_test.dart

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,9 +148,7 @@ testIOS(RuntimeStub stub, DelegateStub delegate) {
148148
Class('NSThread')
149149
.performAsync(SEL('currentThread'), onQueue: DispatchQueue.global())
150150
.then((currentThread) {
151-
NSObject description = currentThread.perform(SEL('description'));
152-
String threadResult = NSString.fromPointer(description.pointer).raw;
153-
print('currentThread: $threadResult');
151+
print('currentThread: ${currentThread.description}');
154152
});
155153

156154
NSNotificationCenter.defaultCenter.addObserver(

dart_native/ios/Classes/DNInvocation.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ - (void *)_copyPointer:(void **)pointer encode:(const char *)encode key:(NSNumbe
157157
}
158158

159159
- (void)_retainPointer:(void **)pointer encode:(const char *)encode key:(NSNumber *)key {
160-
if (!pointer) {
160+
if (!pointer || *encode == 'v') {
161161
return;
162162
}
163163
void *p = *pointer;

dart_native/ios/Classes/DNObjectDealloc.m

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,19 +54,27 @@ + (void)attachHost:(NSObject *)host
5454
}
5555
}
5656

57+
static int64_t fuxk;
58+
5759
- (instancetype)initWithHost:(NSObject *)host
5860
dartPort:(Dart_Port)dartPort {
5961
self = [super init];
6062
if (self) {
6163
_host = host;
6264
_hostAddress = (int64_t)host;
65+
if ([host isKindOfClass:NSClassFromString(@"Fuck")]) {
66+
fuxk = _hostAddress;
67+
}
6368
_dartPort = dartPort;
6469
objc_setAssociatedObject(host, _cmd, self, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
6570
}
6671
return self;
6772
}
6873

6974
- (void)dealloc {
75+
if (_hostAddress == fuxk) {
76+
77+
}
7078
NotifyDeallocToDart(_hostAddress, _dartPort);
7179
}
7280

dart_native/ios/Classes/native_runtime.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,15 @@ native_get_class(const char *className, Class superclass);
4141
/// @param queue dispatch queue for async method.
4242
/// @param args arguments passed to method.
4343
/// @param dartPort port for dart isolate.
44-
/// @param stringTypeBitmask bitmask for checking if an argument is a string.
44+
/// @param stringTypeBitmaskPtr bitmask for checking if an argument is a string.
4545
DN_EXTERN void * _Nullable
46-
native_instance_invoke(id object, SEL selector, NSMethodSignature *signature, dispatch_queue_t queue, void * _Nonnull * _Nullable args, void (^callback)(void *), Dart_Port dartPort, int64_t stringTypeBitmask);
46+
native_instance_invoke(id object, SEL selector, NSMethodSignature *signature, dispatch_queue_t queue, void * _Nonnull * _Nullable args, void (^callback)(void *), Dart_Port dartPort, int64_t *stringTypeBitmaskPtr);
4747

4848
DN_EXTERN void *
4949
native_block_create(char *types, void *callback, Dart_Port dartPort);
5050

5151
DN_EXTERN void *
52-
native_block_invoke(void *block, void * _Nonnull * _Nullable args, Dart_Port dartPort, int64_t stringTypeBitmask);
52+
native_block_invoke(void *block, void * _Nonnull * _Nullable args, Dart_Port dartPort, int64_t *stringTypeBitmaskPtr);
5353

5454
DN_EXTERN const char * _Nonnull * _Nonnull
5555
native_all_type_encodings(void);

dart_native/ios/Classes/native_runtime.mm

Lines changed: 53 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@
104104
}
105105

106106
void
107-
_fillArgsToInvocation(NSMethodSignature *signature, void **args, NSInvocation *invocation, NSUInteger offset, int64_t stringTypeBitmask, NSMutableArray<NSString *> *stringTypeBucket) {
107+
_fillArgsToInvocation(NSMethodSignature *signature, void **args, NSInvocation *invocation, NSUInteger offset, int64_t *stringTypeBitmaskPtr, NSMutableArray<NSString *> *stringTypeBucket) {
108108
for (NSUInteger i = offset; i < signature.numberOfArguments; i++) {
109109
const char *argType = [signature getArgumentTypeAtIndex:i];
110110
NSUInteger argsIndex = i - offset;
@@ -119,16 +119,16 @@
119119
// Already put struct in pointer on Dart side.
120120
[invocation setArgument:args[argsIndex] atIndex:i];
121121
} else if (argType[0] == '@' &&
122-
(stringTypeBitmask >> argsIndex & 0x1) == 1) {
122+
(*stringTypeBitmaskPtr >> (argsIndex + 1) & 0x1) == 1) {
123123
const unichar *data = ((const unichar **)args)[argsIndex];
124124
// First four uint16_t is for data length.
125-
const NSUInteger dataOffset = 4;
125+
const NSUInteger lengthDataSize = 4;
126126
uint64_t length = data[0];
127-
for (int i = 1; i < dataOffset; i++) {
127+
for (int i = 1; i < lengthDataSize; i++) {
128128
length <<= 16;
129129
length |= data[i];
130130
}
131-
NSString *realArg = [NSString stringWithCharacters:data + dataOffset length:length];
131+
NSString *realArg = [NSString stringWithCharacters:data + lengthDataSize length:length];
132132
[stringTypeBucket addObject:realArg];
133133
free((void *)data); // Malloc data on dart side, need free here.
134134
[invocation setArgument:&realArg atIndex:i];
@@ -138,16 +138,40 @@
138138
}
139139
}
140140

141+
142+
/// Return data for NSString: [--dataLength(64bit--)][--dataContent(utf16 without BOM)--]
143+
/// @param retVal origin return value
144+
/// @param stringTypeBitmaskPtr pointer to bitmask
145+
void *_dataForNSStringReturnValue(NSString *retVal, int64_t *stringTypeBitmaskPtr) {
146+
// first bit is for return value.
147+
*stringTypeBitmaskPtr |= 0x1;
148+
NSUInteger length = 0;
149+
const uint16_t *utf16BufferPtr = native_convert_nsstring_to_utf16(retVal, &length);
150+
size_t size = sizeof(uint16_t) * length;
151+
const size_t lengthDataSize = 4;
152+
// free memory on dart side.
153+
uint16_t *dataPtr = (uint16_t *)malloc(size + sizeof(uint16_t) * lengthDataSize);
154+
memcpy(dataPtr + lengthDataSize, utf16BufferPtr, size);
155+
uint16_t lengthData[4] = {
156+
static_cast<uint16_t>(length >> 48 & 0xffff),
157+
static_cast<uint16_t>(length >> 32 & 0xffff),
158+
static_cast<uint16_t>(length >> 16 & 0xffff),
159+
static_cast<uint16_t>(length & 0xffff)
160+
};
161+
memcpy(dataPtr, lengthData, sizeof(uint16_t) * lengthDataSize);
162+
return dataPtr;
163+
}
164+
141165
void *
142-
native_instance_invoke(id object, SEL selector, NSMethodSignature *signature, dispatch_queue_t queue, void **args, void (^callback)(void *), Dart_Port dartPort, int64_t stringTypeBitmask) {
143-
if (!object || !selector || !signature) {
166+
native_instance_invoke(id object, SEL selector, NSMethodSignature *signature, dispatch_queue_t queue, void **args, void (^callback)(void *), Dart_Port dartPort, int64_t *stringTypeBitmaskPtr) {
167+
if (!object || !selector || !signature || !stringTypeBitmaskPtr) {
144168
return NULL;
145169
}
146170
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
147171
invocation.target = object;
148172
invocation.selector = selector;
149173
NSMutableArray<NSString *> *stringTypeBucket = [NSMutableArray array];
150-
_fillArgsToInvocation(signature, args, invocation, 2, stringTypeBitmask, stringTypeBucket);
174+
_fillArgsToInvocation(signature, args, invocation, 2, stringTypeBitmaskPtr, stringTypeBucket);
151175

152176
void *(^resultBlock)() = ^() {
153177
void *result = NULL;
@@ -159,8 +183,16 @@
159183
} else {
160184
[invocation getReturnValue:&result];
161185
if (returnType == '@') {
162-
[DNObjectDealloc attachHost:(__bridge id)result
163-
dartPort:dartPort];
186+
BOOL isNSString = [(__bridge id)result isKindOfClass:NSString.class];
187+
// highest bit is a flag for decode.
188+
BOOL decodeRetVal = (*stringTypeBitmaskPtr & (1LL << 63)) != 0;
189+
// return value is a NSString and needs decode.
190+
if (isNSString && decodeRetVal) {
191+
result = _dataForNSStringReturnValue((__bridge NSString *)result, stringTypeBitmaskPtr);
192+
} else {
193+
[DNObjectDealloc attachHost:(__bridge id)result
194+
dartPort:dartPort];
195+
}
164196
}
165197
}
166198
}
@@ -198,12 +230,15 @@
198230
}
199231

200232
void *
201-
native_block_invoke(void *block, void **args, Dart_Port dartPort, int64_t stringTypeBitmask) {
233+
native_block_invoke(void *block, void **args, Dart_Port dartPort, int64_t *stringTypeBitmaskPtr) {
234+
if (!block || !stringTypeBitmaskPtr) {
235+
return nullptr;
236+
}
202237
const char *typeString = DNBlockTypeEncodeString((__bridge id)block);
203238
NSMethodSignature *signature = [NSMethodSignature signatureWithObjCTypes:typeString];
204239
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
205240
NSMutableArray<NSString *> *stringTypeBucket = [NSMutableArray array];
206-
_fillArgsToInvocation(signature, args, invocation, 1, stringTypeBitmask, stringTypeBucket);
241+
_fillArgsToInvocation(signature, args, invocation, 1, stringTypeBitmaskPtr, stringTypeBucket);
207242
[invocation invokeWithTarget:(__bridge id)block];
208243
void *result = NULL;
209244
const char returnType = signature.methodReturnType[0];
@@ -213,7 +248,12 @@
213248
[invocation getReturnValue:result];
214249
} else {
215250
[invocation getReturnValue:&result];
216-
if (returnType == '@') {
251+
BOOL isNSString = [(__bridge id)result isKindOfClass:NSString.class];
252+
BOOL decodeRetVal = (*stringTypeBitmaskPtr & (1LL << 63)) != 0;
253+
// return value is a NSString and needs decode.
254+
if (isNSString && decodeRetVal) {
255+
result = _dataForNSStringReturnValue((__bridge NSString *)result, stringTypeBitmaskPtr);
256+
} else {
217257
[DNObjectDealloc attachHost:(__bridge id)result
218258
dartPort:dartPort];
219259
}
216 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)