| // Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| #include "protocol.h" |
| |
| #import <Foundation/NSDictionary.h> |
| #import <Foundation/NSInvocation.h> |
| #import <Foundation/NSValue.h> |
| #import <objc/runtime.h> |
| |
| #if !__has_feature(objc_arc) |
| #error "This file must be compiled with ARC enabled" |
| #endif |
| |
| @implementation DOBJCDartProtocolBuilder { |
| @public NSMutableDictionary *methods; |
| Class clazz; |
| } |
| |
| - (instancetype)initWithClassName: (const char*)name { |
| methods = [NSMutableDictionary new]; |
| clazz = objc_allocateClassPair([DOBJCDartProtocol class], name, 0); |
| return self; |
| } |
| |
| - (void)implementMethod:(SEL)sel withBlock:(void*)block |
| withTrampoline:(void*)trampoline withSignature:(char*)signature { |
| class_addMethod(clazz, sel, trampoline, signature); |
| NSValue* key = [NSValue valueWithPointer:sel]; |
| @synchronized(methods) { |
| [methods setObject:(__bridge id)block forKey:key]; |
| } |
| } |
| |
| - (void)addProtocol:(Protocol*) protocol { |
| class_addProtocol(clazz, protocol); |
| } |
| |
| - (void)registerClass { |
| objc_registerClassPair(clazz); |
| } |
| |
| - (DOBJCDartProtocol*)buildInstance: (Dart_Port)port { |
| DOBJCDartProtocol* inst = [clazz alloc]; |
| return [inst initDOBJCDartProtocolFromDartProtocolBuilder:self |
| withDisposePort:port]; |
| } |
| |
| - (void)dealloc { |
| objc_disposeClassPair(clazz); |
| } |
| |
| @end |
| |
| @implementation DOBJCDartProtocol { |
| DOBJCDartProtocolBuilder* builder; |
| Dart_Port dispose_port; |
| } |
| |
| - (id)getDOBJCDartProtocolMethodForSelector:(SEL)sel { |
| return [builder->methods objectForKey:[NSValue valueWithPointer:sel]]; |
| } |
| |
| - (instancetype)initDOBJCDartProtocolFromDartProtocolBuilder: |
| (DOBJCDartProtocolBuilder*)builder_ |
| withDisposePort:(Dart_Port)port { |
| builder = builder_; |
| dispose_port = port; |
| return self; |
| } |
| |
| - (void)dealloc { |
| if (dispose_port != ILLEGAL_PORT) { |
| Dart_PostInteger_DL(dispose_port, 0); |
| } |
| } |
| |
| @end |