@geastack/apple 0.2.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/README.md +54 -0
- package/dist/index.d.ts +127 -0
- package/dist/index.js +3076 -0
- package/generated/AVFoundation.d.ts +112 -0
- package/generated/ActivityKit.d.ts +7 -0
- package/generated/AppKit.d.ts +268 -0
- package/generated/CoreGraphics.d.ts +18 -0
- package/generated/CoreLocation.d.ts +28 -0
- package/generated/CoreMedia.d.ts +8 -0
- package/generated/Dispatch.d.ts +2 -0
- package/generated/Foundation.d.ts +13 -0
- package/generated/MapKit.d.ts +28 -0
- package/generated/Metal.d.ts +91 -0
- package/generated/MetalKit.d.ts +22 -0
- package/generated/Photos.d.ts +5 -0
- package/generated/QuartzCore.d.ts +12 -0
- package/generated/SwiftData.d.ts +11 -0
- package/generated/UIKit.d.ts +187 -0
- package/package.json +123 -0
- package/runtime/AVFoundation.js +136 -0
- package/runtime/ActivityKit.js +18 -0
- package/runtime/AppKit.js +313 -0
- package/runtime/CoreGraphics.js +15 -0
- package/runtime/CoreLocation.js +30 -0
- package/runtime/CoreMedia.js +7 -0
- package/runtime/Dispatch.js +11 -0
- package/runtime/Foundation.js +21 -0
- package/runtime/MapKit.js +22 -0
- package/runtime/Metal.js +126 -0
- package/runtime/MetalKit.js +15 -0
- package/runtime/Photos.js +9 -0
- package/runtime/QuartzCore.js +9 -0
- package/runtime/SwiftData.js +29 -0
- package/runtime/UIKit.js +242 -0
- package/runtime/empty.js +1 -0
- package/targets/ios/Info.plist.in +25 -0
- package/targets/ios/README.md +46 -0
- package/targets/ios/build-ios.sh +395 -0
- package/targets/ios/detect-development-team.mjs +109 -0
- package/targets/ios/generate-resident-entry.mjs +67 -0
- package/targets/ios/generate-resident-registry.mjs +162 -0
- package/targets/ios/generate-xcode-project.mjs +520 -0
- package/targets/ios/main/canvas_view.h +7 -0
- package/targets/ios/main/canvas_view.mm +94 -0
- package/targets/ios/main/font_registry.h +17 -0
- package/targets/ios/main/font_registry.mm +129 -0
- package/targets/ios/main/image_bridge.h +13 -0
- package/targets/ios/main/image_bridge.mm +53 -0
- package/targets/ios/main/ios_apps.c +28 -0
- package/targets/ios/main/ios_camera.mm +446 -0
- package/targets/ios/main/ios_display.mm +344 -0
- package/targets/ios/main/ios_main.mm +811 -0
- package/targets/ios/main/ios_memory.cpp +55 -0
- package/targets/ios/main/ios_renderer.h +20 -0
- package/targets/ios/main/ios_renderer.mm +27 -0
- package/targets/ios/main/ios_root_background.cpp +20 -0
- package/targets/ios/main/ios_root_background.h +11 -0
- package/targets/ios/main/ios_sensors.mm +244 -0
- package/targets/ios/main/ios_timers.mm +53 -0
- package/targets/ios/main/renderer/ios_renderer_internal.h +65 -0
- package/targets/ios/main/renderer/ios_renderer_support.mm +111 -0
- package/targets/ios/main/renderer/native_button.mm +179 -0
- package/targets/ios/main/renderer/native_label.mm +161 -0
- package/targets/ios/main/renderer/native_scroll_container.mm +279 -0
- package/targets/ios/main/renderer/view_reconciler.mm +274 -0
- package/targets/macos/Info.plist.in +26 -0
- package/targets/macos/README.md +131 -0
- package/targets/macos/build-child-lifecycle.sh +119 -0
- package/targets/macos/build-macos.sh +2156 -0
- package/targets/macos/check-module-graph-freshness.mjs +82 -0
- package/targets/macos/compiler-input-fingerprint.mjs +32 -0
- package/targets/macos/finalize-apple-native-output.mjs +77 -0
- package/targets/macos/generate-resident-entry.mjs +80 -0
- package/targets/macos/generate-resident-registry.mjs +141 -0
- package/targets/macos/heavy-build-lock.sh +176 -0
- package/targets/macos/main/canvas_view.h +9 -0
- package/targets/macos/main/canvas_view.mm +176 -0
- package/targets/macos/main/color_convert.h +18 -0
- package/targets/macos/main/color_convert.mm +39 -0
- package/targets/macos/main/font_registry.h +35 -0
- package/targets/macos/main/font_registry.mm +350 -0
- package/targets/macos/main/image_bridge.h +16 -0
- package/targets/macos/main/image_bridge.mm +52 -0
- package/targets/macos/main/macos_app_platform.mm +95 -0
- package/targets/macos/main/macos_apps.c +31 -0
- package/targets/macos/main/macos_device_control.mm +56 -0
- package/targets/macos/main/macos_display.mm +484 -0
- package/targets/macos/main/macos_host_device_control.mm +95 -0
- package/targets/macos/main/macos_main.mm +839 -0
- package/targets/macos/main/macos_memory.cpp +31 -0
- package/targets/macos/main/macos_native_shell.h +31 -0
- package/targets/macos/main/macos_native_shell.mm +396 -0
- package/targets/macos/main/macos_network.mm +253 -0
- package/targets/macos/main/macos_renderer.h +39 -0
- package/targets/macos/main/macos_renderer.mm +1969 -0
- package/targets/macos/main/macos_sensors.cpp +148 -0
- package/targets/macos/main/macos_smoke_app.cpp +65 -0
- package/targets/macos/main/macos_timers.mm +52 -0
- package/targets/macos/main/press_bridge.h +21 -0
- package/targets/macos/main/press_bridge.mm +72 -0
- package/targets/macos/main/thermalright_hid_display.h +14 -0
- package/targets/macos/main/thermalright_hid_display.mm +995 -0
- package/targets/macos/native-artifact-provenance.mjs +421 -0
- package/targets/macos/order-compile-edges.mjs +64 -0
- package/targets/macos/preflight-hard-muted-artifact.mjs +93 -0
- package/targets/macos/prune-generated-modules.mjs +147 -0
- package/targets/macos/sync-resources.mjs +153 -0
- package/targets/shared/analyze-audio-capture.mjs +131 -0
- package/targets/shared/apple_audio.mm +1194 -0
- package/targets/shared/apple_audio_selftest.mm +602 -0
- package/targets/shared/apple_audio_testing.h +34 -0
- package/targets/shared/build-audio-selftest.sh +50 -0
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
/* targets/macos/main/macos_network.mm
|
|
2
|
+
* Real HTTP(S) for the framework's fetch facade, via NSURLSession.
|
|
3
|
+
*
|
|
4
|
+
* core's host/host/fetch.cpp has three arms: browser (emscripten), ESP-IDF,
|
|
5
|
+
* and a desktop fallback that calls two WEAK hooks —
|
|
6
|
+
* test_record_request(url, init) then test_canned_response(url)
|
|
7
|
+
* — and returns whatever the latter produces (empty by default). The Android
|
|
8
|
+
* and Raspberry Pi OS targets strong-override that seam to inject real
|
|
9
|
+
* responses; this file does the same with NSURLSession, the canonical macOS
|
|
10
|
+
* networking stack (system proxy/PAC settings, HTTP/2, TLS session reuse,
|
|
11
|
+
* and connection keep-alive all come from the shared session's pool).
|
|
12
|
+
*
|
|
13
|
+
* The fetch seam is synchronous, so each request parks its calling thread on
|
|
14
|
+
* a semaphore until the session's completion handler fires — the callers are
|
|
15
|
+
* tile-loader workers, detached fetchAsync threads, or the frame thread for
|
|
16
|
+
* a synchronous app fetch, and the session's delegate queue is its own, so
|
|
17
|
+
* the wait cannot deadlock. test_canned_response only receives the URL, so
|
|
18
|
+
* test_record_request stashes the request init in a thread_local for it to
|
|
19
|
+
* pick up (both hooks run back-to-back on the same thread).
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
#import <Foundation/Foundation.h>
|
|
23
|
+
|
|
24
|
+
#include "host/fetch.h"
|
|
25
|
+
#include "wifi.h"
|
|
26
|
+
|
|
27
|
+
#include <cstdio>
|
|
28
|
+
#include <mutex>
|
|
29
|
+
#include <string>
|
|
30
|
+
#include <vector>
|
|
31
|
+
|
|
32
|
+
#include <CoreFoundation/CoreFoundation.h>
|
|
33
|
+
#include <SystemConfiguration/SystemConfiguration.h>
|
|
34
|
+
|
|
35
|
+
#include <arpa/inet.h>
|
|
36
|
+
#include <ifaddrs.h>
|
|
37
|
+
#include <net/if_dl.h>
|
|
38
|
+
#include <netinet/in.h>
|
|
39
|
+
|
|
40
|
+
namespace {
|
|
41
|
+
|
|
42
|
+
thread_local gea::host::FetchRequestInit t_pending_init;
|
|
43
|
+
thread_local bool t_has_pending_init = false;
|
|
44
|
+
|
|
45
|
+
// One shared session for every caller: NSURLSession is thread-safe and pools
|
|
46
|
+
// keep-alive connections per host across threads, so sequential tile fetches
|
|
47
|
+
// pay the TCP + TLS handshake once (same effect the ESP backend gets from its
|
|
48
|
+
// per-task esp_http_client) while worker threads still fetch in parallel.
|
|
49
|
+
NSURLSession *sharedSession()
|
|
50
|
+
{
|
|
51
|
+
static NSURLSession *session;
|
|
52
|
+
static dispatch_once_t once;
|
|
53
|
+
dispatch_once(&once, ^{
|
|
54
|
+
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
|
|
55
|
+
config.HTTPAdditionalHeaders = @{ @"User-Agent": @"gea-macos/1.0" };
|
|
56
|
+
config.timeoutIntervalForRequest = 30.0;
|
|
57
|
+
session = [NSURLSession sessionWithConfiguration:config];
|
|
58
|
+
});
|
|
59
|
+
return session;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
gea::host::FetchResponse sessionFetch(const std::string &url, const gea::host::FetchRequestInit &init)
|
|
63
|
+
{
|
|
64
|
+
gea::host::FetchResponse response;
|
|
65
|
+
NSURL *requestUrl = [NSURL URLWithString:[NSString stringWithUTF8String:url.c_str()] ?: @""];
|
|
66
|
+
if (!requestUrl) {
|
|
67
|
+
std::fprintf(stderr, "[macos net] fetch rejected malformed url %s\n", url.c_str());
|
|
68
|
+
return response;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:requestUrl];
|
|
72
|
+
const std::string method = init.method.empty() ? "GET" : init.method;
|
|
73
|
+
request.HTTPMethod = [NSString stringWithUTF8String:method.c_str()] ?: @"GET";
|
|
74
|
+
if (init.timeout_ms > 0) request.timeoutInterval = init.timeout_ms / 1000.0;
|
|
75
|
+
for (const auto &kv : init.headers) {
|
|
76
|
+
NSString *name = [NSString stringWithUTF8String:kv.first.c_str()];
|
|
77
|
+
NSString *value = [NSString stringWithUTF8String:kv.second.c_str()];
|
|
78
|
+
if (name && value) [request setValue:value forHTTPHeaderField:name];
|
|
79
|
+
}
|
|
80
|
+
if (!init.body.empty() && method != "GET" && method != "HEAD") {
|
|
81
|
+
request.HTTPBody = [NSData dataWithBytes:init.body.data() length:init.body.size()];
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Park this thread until the completion handler fires on the session's own
|
|
85
|
+
// delegate queue. Redirects are followed and gzip/deflate bodies decoded by
|
|
86
|
+
// the session before the handler runs.
|
|
87
|
+
dispatch_semaphore_t done = dispatch_semaphore_create(0);
|
|
88
|
+
__block NSData *body = nil;
|
|
89
|
+
__block NSHTTPURLResponse *httpResponse = nil;
|
|
90
|
+
__block NSError *error = nil;
|
|
91
|
+
NSURLSessionDataTask *task = [sharedSession()
|
|
92
|
+
dataTaskWithRequest:request
|
|
93
|
+
completionHandler:^(NSData *taskData, NSURLResponse *taskResponse, NSError *taskError) {
|
|
94
|
+
body = taskData;
|
|
95
|
+
if ([taskResponse isKindOfClass:[NSHTTPURLResponse class]]) {
|
|
96
|
+
httpResponse = (NSHTTPURLResponse *)taskResponse;
|
|
97
|
+
}
|
|
98
|
+
error = taskError;
|
|
99
|
+
dispatch_semaphore_signal(done);
|
|
100
|
+
}];
|
|
101
|
+
[task resume];
|
|
102
|
+
dispatch_semaphore_wait(done, DISPATCH_TIME_FOREVER);
|
|
103
|
+
|
|
104
|
+
if (error) {
|
|
105
|
+
std::fprintf(stderr, "[macos net] fetch %s failed: %s\n", url.c_str(),
|
|
106
|
+
error.localizedDescription.UTF8String ?: "unknown error");
|
|
107
|
+
return response;
|
|
108
|
+
}
|
|
109
|
+
if (httpResponse) {
|
|
110
|
+
const NSInteger code = httpResponse.statusCode;
|
|
111
|
+
response.status = static_cast<double>(code);
|
|
112
|
+
response.ok = code >= 200 && code < 300;
|
|
113
|
+
response.status_text = std::string([NSHTTPURLResponse localizedStringForStatusCode:code].UTF8String ?: "");
|
|
114
|
+
NSDictionary *headerFields = httpResponse.allHeaderFields;
|
|
115
|
+
for (id name in headerFields) {
|
|
116
|
+
id value = headerFields[name];
|
|
117
|
+
if ([name isKindOfClass:[NSString class]] && [value isKindOfClass:[NSString class]]) {
|
|
118
|
+
response.headers[std::string([(NSString *)name UTF8String] ?: "")] =
|
|
119
|
+
std::string([(NSString *)value UTF8String] ?: "");
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
if (body.length > 0) {
|
|
124
|
+
const auto *bytes = static_cast<const std::uint8_t *>(body.bytes);
|
|
125
|
+
response.body.assign(bytes, bytes + body.length);
|
|
126
|
+
}
|
|
127
|
+
return response;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
} // namespace
|
|
131
|
+
|
|
132
|
+
namespace gea::framework::host {
|
|
133
|
+
|
|
134
|
+
// Strong overrides of the weak desktop-fallback hooks in host/host/fetch.cpp.
|
|
135
|
+
void test_record_request(const std::string &, const gea::host::FetchRequestInit &init)
|
|
136
|
+
{
|
|
137
|
+
t_pending_init = init;
|
|
138
|
+
t_has_pending_init = true;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
gea::host::FetchResponse test_canned_response(const std::string &url)
|
|
142
|
+
{
|
|
143
|
+
gea::host::FetchRequestInit init;
|
|
144
|
+
if (t_has_pending_init) {
|
|
145
|
+
init = std::move(t_pending_init);
|
|
146
|
+
t_pending_init = {};
|
|
147
|
+
t_has_pending_init = false;
|
|
148
|
+
}
|
|
149
|
+
return sessionFetch(url, init);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
} // namespace gea::framework::host
|
|
153
|
+
|
|
154
|
+
namespace {
|
|
155
|
+
|
|
156
|
+
// WiFi *status* driver. Several apps gate remote fetches on
|
|
157
|
+
// `wifi().connected()` (e.g. maps skips tile downloads without it), so the
|
|
158
|
+
// desktop must report its real link state even though fetch itself just uses
|
|
159
|
+
// the host TCP stack. "Connected" = configd has a primary (default-route)
|
|
160
|
+
// IPv4 interface — true for wired Ethernet too, which is the honest answer
|
|
161
|
+
// to "can I reach the network". Scanning/configuration are desktop no-ops
|
|
162
|
+
// (the system owns the link).
|
|
163
|
+
class MacWifiDriver final : public gea::framework::network::WifiDriver {
|
|
164
|
+
public:
|
|
165
|
+
bool init() override { return true; }
|
|
166
|
+
bool enabled() const override { return true; }
|
|
167
|
+
void setEnabled(bool) override {}
|
|
168
|
+
bool connected() const override { return !primaryInterface().empty(); }
|
|
169
|
+
int rssi() override { return connected() ? -50 : 0; }
|
|
170
|
+
std::string ssid() override { return primaryInterface(); }
|
|
171
|
+
std::string ip() const override
|
|
172
|
+
{
|
|
173
|
+
const std::string iface = primaryInterface();
|
|
174
|
+
if (iface.empty()) return "";
|
|
175
|
+
std::string result;
|
|
176
|
+
struct ifaddrs *addrs = nullptr;
|
|
177
|
+
if (getifaddrs(&addrs) != 0) return "";
|
|
178
|
+
for (struct ifaddrs *a = addrs; a; a = a->ifa_next) {
|
|
179
|
+
if (!a->ifa_addr || a->ifa_addr->sa_family != AF_INET) continue;
|
|
180
|
+
if (iface != a->ifa_name) continue;
|
|
181
|
+
char buf[INET_ADDRSTRLEN] = {0};
|
|
182
|
+
const auto *sin = reinterpret_cast<const struct sockaddr_in *>(a->ifa_addr);
|
|
183
|
+
if (inet_ntop(AF_INET, &sin->sin_addr, buf, sizeof(buf))) result = buf;
|
|
184
|
+
break;
|
|
185
|
+
}
|
|
186
|
+
freeifaddrs(addrs);
|
|
187
|
+
return result;
|
|
188
|
+
}
|
|
189
|
+
std::string mac() override
|
|
190
|
+
{
|
|
191
|
+
const std::string iface = primaryInterface();
|
|
192
|
+
if (iface.empty()) return "";
|
|
193
|
+
std::string result;
|
|
194
|
+
struct ifaddrs *addrs = nullptr;
|
|
195
|
+
if (getifaddrs(&addrs) != 0) return "";
|
|
196
|
+
for (struct ifaddrs *a = addrs; a; a = a->ifa_next) {
|
|
197
|
+
if (!a->ifa_addr || a->ifa_addr->sa_family != AF_LINK) continue;
|
|
198
|
+
if (iface != a->ifa_name) continue;
|
|
199
|
+
const auto *sdl = reinterpret_cast<const struct sockaddr_dl *>(a->ifa_addr);
|
|
200
|
+
if (sdl->sdl_alen == 6) {
|
|
201
|
+
const auto *ll = reinterpret_cast<const unsigned char *>(LLADDR(sdl));
|
|
202
|
+
char buf[18];
|
|
203
|
+
std::snprintf(buf, sizeof(buf), "%02x:%02x:%02x:%02x:%02x:%02x",
|
|
204
|
+
ll[0], ll[1], ll[2], ll[3], ll[4], ll[5]);
|
|
205
|
+
result = buf;
|
|
206
|
+
}
|
|
207
|
+
break;
|
|
208
|
+
}
|
|
209
|
+
freeifaddrs(addrs);
|
|
210
|
+
return result;
|
|
211
|
+
}
|
|
212
|
+
void configure(const std::string &, const std::string &) override {}
|
|
213
|
+
void scan() override {}
|
|
214
|
+
bool scanning() const override { return false; }
|
|
215
|
+
int scanCount() const override { return 0; }
|
|
216
|
+
gea::framework::network::WifiNetwork networkAt(int) const override { return {}; }
|
|
217
|
+
std::vector<gea::framework::network::WifiNetwork> scanResults() const override { return {}; }
|
|
218
|
+
|
|
219
|
+
private:
|
|
220
|
+
// Interface of the system default route: configd publishes it as
|
|
221
|
+
// State:/Network/Global/IPv4 → PrimaryInterface (absent while offline).
|
|
222
|
+
static std::string primaryInterface()
|
|
223
|
+
{
|
|
224
|
+
SCDynamicStoreRef store = SCDynamicStoreCreate(kCFAllocatorDefault, CFSTR("gea-macos-network"), nullptr, nullptr);
|
|
225
|
+
if (!store) return "";
|
|
226
|
+
std::string result;
|
|
227
|
+
CFPropertyListRef value = SCDynamicStoreCopyValue(store, CFSTR("State:/Network/Global/IPv4"));
|
|
228
|
+
if (value) {
|
|
229
|
+
if (CFGetTypeID(value) == CFDictionaryGetTypeID()) {
|
|
230
|
+
const void *iface = CFDictionaryGetValue((CFDictionaryRef)value, CFSTR("PrimaryInterface"));
|
|
231
|
+
if (iface && CFGetTypeID((CFTypeRef)iface) == CFStringGetTypeID()) {
|
|
232
|
+
char buf[64] = {0};
|
|
233
|
+
if (CFStringGetCString((CFStringRef)iface, buf, sizeof(buf), kCFStringEncodingUTF8)) result = buf;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
CFRelease(value);
|
|
237
|
+
}
|
|
238
|
+
CFRelease(store);
|
|
239
|
+
return result;
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
} // namespace
|
|
244
|
+
|
|
245
|
+
namespace gea::macos {
|
|
246
|
+
|
|
247
|
+
void installWifiDriver()
|
|
248
|
+
{
|
|
249
|
+
static MacWifiDriver driver;
|
|
250
|
+
gea::framework::network::WifiAdapter::setDriver(&driver);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
} // namespace gea::macos
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#ifdef __OBJC__
|
|
4
|
+
@class NSView;
|
|
5
|
+
@class NSArray;
|
|
6
|
+
#else
|
|
7
|
+
struct NSView;
|
|
8
|
+
struct NSArray;
|
|
9
|
+
#endif
|
|
10
|
+
|
|
11
|
+
namespace gea::macos {
|
|
12
|
+
|
|
13
|
+
class MacosRenderer {
|
|
14
|
+
public:
|
|
15
|
+
static MacosRenderer &instance();
|
|
16
|
+
|
|
17
|
+
// Walks the laid-out node tree rooted at rootNodeId and updates a
|
|
18
|
+
// parallel NSView tree under parentForRoot: creating views for new
|
|
19
|
+
// nodes, removing views for nodes that disappeared, reparenting where
|
|
20
|
+
// the tree shape changed, and applying frame/style.
|
|
21
|
+
void sync(NSView *parentForRoot, int rootNodeId);
|
|
22
|
+
|
|
23
|
+
// Multi-root variant for the native split shell: each pane is its own
|
|
24
|
+
// layout root rendered into its own container view. paneViews[i] hosts
|
|
25
|
+
// the subtree rooted at rootNodeIds[i]. A single combined unseen-sweep
|
|
26
|
+
// runs across ALL panes so per-pane syncing never evicts another pane's
|
|
27
|
+
// views (which a naive loop of sync() calls would, since each sync()
|
|
28
|
+
// sweeps every map entry it didn't touch).
|
|
29
|
+
void syncPanes(NSArray *paneViews, const int *rootNodeIds);
|
|
30
|
+
|
|
31
|
+
// Drop all NSView associations and detach them from their parents.
|
|
32
|
+
// Called on app teardown / tree clear.
|
|
33
|
+
void teardown();
|
|
34
|
+
|
|
35
|
+
private:
|
|
36
|
+
MacosRenderer() = default;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
} // namespace gea::macos
|