objcjs-types 0.5.0 → 0.5.2
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/dist/AVFAudio/index.js +74 -74
- package/dist/AVFoundation/index.js +269 -269
- package/dist/AVKit/index.js +7 -7
- package/dist/AVRouting/index.js +7 -7
- package/dist/Accessibility/index.js +29 -29
- package/dist/AccessorySetupKit/index.js +12 -12
- package/dist/Accounts/index.js +5 -5
- package/dist/AdServices/index.js +2 -2
- package/dist/AdSupport/index.js +2 -2
- package/dist/AddressBook/index.js +11 -11
- package/dist/AppKit/constants.d.ts +8 -0
- package/dist/AppKit/constants.js +9 -0
- package/dist/AppKit/index.js +317 -317
- package/dist/AppTrackingTransparency/index.js +2 -2
- package/dist/AppleScriptKit/index.js +2 -2
- package/dist/AudioToolbox/index.js +10 -10
- package/dist/AudioVideoBridging/index.js +18 -18
- package/dist/AuthenticationServices/index.js +79 -79
- package/dist/AutomaticAssessmentConfiguration/index.js +5 -5
- package/dist/Automator/index.js +9 -9
- package/dist/BackgroundAssets/index.js +8 -8
- package/dist/BackgroundTasks/index.js +12 -12
- package/dist/BrowserEngineCore/index.js +2 -2
- package/dist/BrowserEngineKit/index.js +19 -19
- package/dist/BusinessChat/index.js +3 -3
- package/dist/CalendarStore/index.js +11 -11
- package/dist/CallKit/index.js +22 -22
- package/dist/Cinematic/index.js +17 -17
- package/dist/ClassKit/index.js +10 -10
- package/dist/CloudKit/index.js +90 -90
- package/dist/Collaboration/index.js +6 -6
- package/dist/Contacts/index.js +36 -36
- package/dist/ContactsUI/index.js +3 -3
- package/dist/CoreAudio/index.js +2 -2
- package/dist/CoreAudioKit/index.js +9 -9
- package/dist/CoreBluetooth/index.js +17 -17
- package/dist/CoreData/index.js +63 -63
- package/dist/CoreHaptics/index.js +8 -8
- package/dist/CoreImage/index.js +31 -31
- package/dist/CoreLocation/index.js +24 -24
- package/dist/CoreMIDI/index.js +20 -20
- package/dist/CoreML/index.js +52 -52
- package/dist/CoreMediaIO/index.js +13 -13
- package/dist/CoreMotion/index.js +38 -38
- package/dist/CoreSpotlight/index.js +14 -14
- package/dist/CoreTelephony/index.js +12 -12
- package/dist/CoreText/index.js +1 -1
- package/dist/CoreWLAN/index.js +9 -9
- package/dist/CryptoTokenKit/index.js +36 -36
- package/dist/DataDetection/index.js +10 -10
- package/dist/DeviceCheck/index.js +3 -3
- package/dist/DeviceDiscoveryExtension/index.js +4 -4
- package/dist/DiscRecording/index.js +12 -12
- package/dist/DiscRecordingUI/index.js +6 -6
- package/dist/EventKit/index.js +18 -18
- package/dist/ExceptionHandling/index.js +2 -2
- package/dist/ExecutionPolicy/index.js +3 -3
- package/dist/ExtensionKit/index.js +3 -3
- package/dist/ExternalAccessory/index.js +6 -6
- package/dist/FSKit/index.js +28 -28
- package/dist/FileProvider/index.js +10 -10
- package/dist/FileProviderUI/index.js +3 -3
- package/dist/FinderSync/index.js +3 -3
- package/dist/Foundation/constants.d.ts +3 -0
- package/dist/Foundation/constants.js +4 -0
- package/dist/Foundation/index.js +275 -275
- package/dist/GLKit/index.js +16 -16
- package/dist/GameController/index.js +39 -39
- package/dist/GameKit/index.js +44 -44
- package/dist/GameSave/index.js +4 -4
- package/dist/GameplayKit/constants.d.ts +2 -0
- package/dist/GameplayKit/constants.js +3 -0
- package/dist/GameplayKit/index.js +59 -59
- package/dist/HealthKit/constants.d.ts +1 -0
- package/dist/HealthKit/constants.js +2 -0
- package/dist/HealthKit/index.js +109 -109
- package/dist/IOSurface/index.js +2 -2
- package/dist/IOUSBHost/index.js +12 -12
- package/dist/IdentityLookup/index.js +15 -15
- package/dist/ImageCaptureCore/index.js +19 -19
- package/dist/InputMethodKit/index.js +4 -4
- package/dist/InstallerPlugins/index.js +4 -4
- package/dist/InstantMessage/index.js +7 -7
- package/dist/Intents/index.js +310 -310
- package/dist/IntentsUI/index.js +4 -4
- package/dist/JavaRuntimeSupport/index.js +6 -6
- package/dist/JavaScriptCore/index.js +5 -5
- package/dist/Kernel/index.js +1 -1
- package/dist/LinkPresentation/index.js +4 -4
- package/dist/LocalAuthentication/index.js +19 -19
- package/dist/LocalAuthenticationEmbeddedUI/index.js +2 -2
- package/dist/MLCompute/index.js +57 -57
- package/dist/MailKit/index.js +17 -17
- package/dist/MapKit/index.js +75 -75
- package/dist/Matter/index.js +1331 -1331
- package/dist/MediaAccessibility/index.js +4 -4
- package/dist/MediaExtension/index.js +19 -19
- package/dist/MediaLibrary/index.js +5 -5
- package/dist/MediaPlayer/index.js +49 -49
- package/dist/Metal/constants.d.ts +2 -0
- package/dist/Metal/constants.js +3 -0
- package/dist/Metal/index.js +150 -150
- package/dist/MetalFX/index.js +5 -5
- package/dist/MetalKit/index.js +7 -7
- package/dist/MetalPerformanceShaders/index.js +1 -1
- package/dist/MetalPerformanceShadersGraph/index.js +29 -29
- package/dist/MetricKit/index.js +38 -38
- package/dist/ModelIO/index.js +67 -67
- package/dist/MultipeerConnectivity/index.js +7 -7
- package/dist/NaturalLanguage/index.js +10 -10
- package/dist/NearbyInteraction/index.js +10 -10
- package/dist/NetworkExtension/index.js +89 -89
- package/dist/NotificationCenter/index.js +4 -4
- package/dist/OSAKit/index.js +6 -6
- package/dist/OSLog/index.js +10 -10
- package/dist/OpenDirectory/index.js +10 -10
- package/dist/PDFKit/index.js +30 -30
- package/dist/PHASE/index.js +60 -60
- package/dist/ParavirtualizedGraphics/index.js +4 -4
- package/dist/PassKit/index.js +74 -74
- package/dist/PencilKit/index.js +14 -14
- package/dist/Photos/index.js +44 -44
- package/dist/PhotosUI/index.js +18 -18
- package/dist/PreferencePanes/index.js +2 -2
- package/dist/PushKit/index.js +4 -4
- package/dist/QuartzCore/index.js +32 -32
- package/dist/QuickLookThumbnailing/index.js +7 -7
- package/dist/QuickLookUI/index.js +7 -7
- package/dist/ReplayKit/index.js +8 -8
- package/dist/SafariServices/index.js +15 -15
- package/dist/SafetyKit/index.js +4 -4
- package/dist/SceneKit/index.js +67 -67
- package/dist/ScreenCaptureKit/index.js +16 -16
- package/dist/ScreenSaver/index.js +3 -3
- package/dist/ScreenTime/index.js +5 -5
- package/dist/ScriptingBridge/index.js +4 -4
- package/dist/SecurityFoundation/index.js +2 -2
- package/dist/SecurityInterface/index.js +10 -10
- package/dist/SecurityUI/index.js +2 -2
- package/dist/SensitiveContentAnalysis/index.js +4 -4
- package/dist/SensorKit/index.js +39 -39
- package/dist/ServiceManagement/index.js +2 -2
- package/dist/SharedWithYou/index.js +11 -11
- package/dist/SharedWithYouCore/index.js +14 -14
- package/dist/ShazamKit/index.js +11 -11
- package/dist/Social/index.js +3 -3
- package/dist/SoundAnalysis/index.js +7 -7
- package/dist/Speech/index.js +14 -14
- package/dist/SpriteKit/index.js +49 -49
- package/dist/StoreKit/index.js +28 -28
- package/dist/Symbols/index.js +19 -19
- package/dist/SyncServices/index.js +9 -9
- package/dist/SystemExtensions/index.js +6 -6
- package/dist/ThreadNetwork/index.js +3 -3
- package/dist/UniformTypeIdentifiers/index.js +2 -2
- package/dist/UserNotifications/index.js +22 -22
- package/dist/UserNotificationsUI/index.js +1 -1
- package/dist/VideoSubscriberAccount/index.js +14 -14
- package/dist/VideoToolbox/index.js +18 -18
- package/dist/Virtualization/index.js +111 -111
- package/dist/Vision/constants.d.ts +54 -0
- package/dist/Vision/constants.js +55 -0
- package/dist/Vision/index.js +92 -92
- package/dist/WebKit/index.js +166 -166
- package/dist/bind.js +4 -0
- package/dist/helpers.d.ts +26 -0
- package/dist/helpers.js +44 -0
- package/dist/iTunesLibrary/index.js +9 -9
- package/generator/ast-parser.ts +132 -0
- package/generator/discover.ts +26 -1
- package/generator/emitter.ts +34 -3
- package/generator/frameworks.ts +4 -0
- package/generator/index.ts +62 -10
- package/generator/parse-worker.ts +9 -2
- package/generator/templates/bind.ts +4 -0
- package/generator/templates/helpers.ts +53 -0
- package/generator/worker-pool.ts +12 -5
- package/package.json +9 -4
package/dist/helpers.js
CHANGED
|
@@ -54,4 +54,48 @@ export function NSDictionaryFromKeysAndValues(keys, values) {
|
|
|
54
54
|
const valuesArray = NSArrayFromObjects(values);
|
|
55
55
|
return NSDictionary.dictionaryWithObjects$forKeys$(valuesArray, keysArray);
|
|
56
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* Returns the key name for a given numeric value in a const enum-like object.
|
|
59
|
+
*
|
|
60
|
+
* @param enumObj - A const object mapping string keys to numeric values.
|
|
61
|
+
* @param value - The numeric value to look up.
|
|
62
|
+
* @returns The matching key name, or `undefined` if not found.
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```ts
|
|
66
|
+
* const state = enumFromValue(
|
|
67
|
+
* ASAuthorizationWebBrowserPublicKeyCredentialManagerAuthorizationState,
|
|
68
|
+
* rawValue
|
|
69
|
+
* ); // e.g. "Authorized" | "Denied" | "NotDetermined" | undefined
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
72
|
+
export function enumFromValue(enumObj, value) {
|
|
73
|
+
return Object.keys(enumObj).find((key) => enumObj[key] === value);
|
|
74
|
+
}
|
|
75
|
+
function PromiseWithResolvers() {
|
|
76
|
+
let resolve;
|
|
77
|
+
let reject;
|
|
78
|
+
const promise = new Promise((res, rej) => {
|
|
79
|
+
resolve = res;
|
|
80
|
+
reject = rej;
|
|
81
|
+
});
|
|
82
|
+
return { promise, resolve: resolve, reject: reject };
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Converts a callback-based function with a single result parameter into a Promise.
|
|
86
|
+
*
|
|
87
|
+
* @template TArgs - The argument types of the original function (excluding the callback)
|
|
88
|
+
* @template TResult - The type of the result passed to the callback
|
|
89
|
+
* @param func - A function that takes arguments and a callback with a single result parameter
|
|
90
|
+
* @param args - The arguments to pass to the function (excluding the callback)
|
|
91
|
+
* @returns A Promise that resolves with the result passed to the callback
|
|
92
|
+
*/
|
|
93
|
+
export function makePromise1Result(func, ...args) {
|
|
94
|
+
const { promise, resolve } = PromiseWithResolvers();
|
|
95
|
+
const callback = (result) => {
|
|
96
|
+
resolve(result);
|
|
97
|
+
};
|
|
98
|
+
func(...args, callback);
|
|
99
|
+
return promise;
|
|
100
|
+
}
|
|
57
101
|
export { isKindOfClass } from "./bind.js";
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
// AUTO-GENERATED by objcjs-types generator — DO NOT EDIT
|
|
2
2
|
import { NobjcLibrary } from "objc-js";
|
|
3
3
|
import { _bindClass } from "../bind.js";
|
|
4
|
-
export const iTunesLibrary = new NobjcLibrary("/System/Library/Frameworks/iTunesLibrary.framework/iTunesLibrary");
|
|
5
|
-
export const ITLibAlbum = _bindClass(iTunesLibrary, "ITLibAlbum");
|
|
6
|
-
export const ITLibArtist = _bindClass(iTunesLibrary, "ITLibArtist");
|
|
7
|
-
export const ITLibArtwork = _bindClass(iTunesLibrary, "ITLibArtwork");
|
|
8
|
-
export const ITLibMediaEntity = _bindClass(iTunesLibrary, "ITLibMediaEntity");
|
|
9
|
-
export const ITLibMediaItem = _bindClass(iTunesLibrary, "ITLibMediaItem");
|
|
10
|
-
export const ITLibMediaItemVideoInfo = _bindClass(iTunesLibrary, "ITLibMediaItemVideoInfo");
|
|
11
|
-
export const ITLibPlaylist = _bindClass(iTunesLibrary, "ITLibPlaylist");
|
|
12
|
-
export const ITLibrary = _bindClass(iTunesLibrary, "ITLibrary");
|
|
4
|
+
export const iTunesLibrary = /* @__PURE__ */ new NobjcLibrary("/System/Library/Frameworks/iTunesLibrary.framework/iTunesLibrary");
|
|
5
|
+
export const ITLibAlbum = /* @__PURE__ */ _bindClass(iTunesLibrary, "ITLibAlbum");
|
|
6
|
+
export const ITLibArtist = /* @__PURE__ */ _bindClass(iTunesLibrary, "ITLibArtist");
|
|
7
|
+
export const ITLibArtwork = /* @__PURE__ */ _bindClass(iTunesLibrary, "ITLibArtwork");
|
|
8
|
+
export const ITLibMediaEntity = /* @__PURE__ */ _bindClass(iTunesLibrary, "ITLibMediaEntity");
|
|
9
|
+
export const ITLibMediaItem = /* @__PURE__ */ _bindClass(iTunesLibrary, "ITLibMediaItem");
|
|
10
|
+
export const ITLibMediaItemVideoInfo = /* @__PURE__ */ _bindClass(iTunesLibrary, "ITLibMediaItemVideoInfo");
|
|
11
|
+
export const ITLibPlaylist = /* @__PURE__ */ _bindClass(iTunesLibrary, "ITLibPlaylist");
|
|
12
|
+
export const ITLibrary = /* @__PURE__ */ _bindClass(iTunesLibrary, "ITLibrary");
|
|
13
13
|
export { ITLibArtworkFormat } from "./ITLibArtworkFormat.js";
|
|
14
14
|
export { ITLibDistinguishedPlaylistKind } from "./ITLibDistinguishedPlaylistKind.js";
|
|
15
15
|
export { ITLibExportFeature } from "./ITLibExportFeature.js";
|
package/generator/ast-parser.ts
CHANGED
|
@@ -122,6 +122,17 @@ export interface ObjCFunction {
|
|
|
122
122
|
frameworkName: string;
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
+
// --- Numeric constant types ---
|
|
126
|
+
|
|
127
|
+
export interface ObjCNumericConstant {
|
|
128
|
+
/** The constant name (e.g., "NSVariableStatusItemLength") */
|
|
129
|
+
name: string;
|
|
130
|
+
/** The numeric value */
|
|
131
|
+
value: number;
|
|
132
|
+
/** Whether the value is a floating-point type (CGFloat, double, float) vs integer (NSInteger, etc.) */
|
|
133
|
+
isFloat: boolean;
|
|
134
|
+
}
|
|
135
|
+
|
|
125
136
|
// --- Helpers for extracting doc comments and deprecation info ---
|
|
126
137
|
|
|
127
138
|
/**
|
|
@@ -1399,6 +1410,127 @@ function extractIntegerValue(node: ClangASTNode): string | null {
|
|
|
1399
1410
|
return val !== null ? String(val) : null;
|
|
1400
1411
|
}
|
|
1401
1412
|
|
|
1413
|
+
/**
|
|
1414
|
+
* Extract a numeric value (integer or floating-point) from a VarDecl's initializer expression tree.
|
|
1415
|
+
* Handles IntegerLiteral, FloatingLiteral, UnaryOperator("-"), and ImplicitCastExpr wrappers.
|
|
1416
|
+
* Returns the numeric value, or null if it can't be extracted.
|
|
1417
|
+
*/
|
|
1418
|
+
function extractNumericValue(node: ClangASTNode): number | null {
|
|
1419
|
+
if (!node.inner) return null;
|
|
1420
|
+
|
|
1421
|
+
function evaluate(n: ClangASTNode): number | null {
|
|
1422
|
+
if (n.kind === "IntegerLiteral" && n.value !== undefined) {
|
|
1423
|
+
return parseInt(n.value, 10);
|
|
1424
|
+
}
|
|
1425
|
+
if (n.kind === "FloatingLiteral" && n.value !== undefined) {
|
|
1426
|
+
return parseFloat(n.value);
|
|
1427
|
+
}
|
|
1428
|
+
if (n.kind === "UnaryOperator" && (n as any).opcode === "-" && n.inner?.length === 1) {
|
|
1429
|
+
const operand = evaluate(n.inner[0]!);
|
|
1430
|
+
return operand !== null ? -operand : null;
|
|
1431
|
+
}
|
|
1432
|
+
// Walk through transparent wrappers (ImplicitCastExpr, ParenExpr, ConstantExpr, etc.)
|
|
1433
|
+
if (n.inner?.length === 1) {
|
|
1434
|
+
return evaluate(n.inner[0]!);
|
|
1435
|
+
}
|
|
1436
|
+
// Try all children for multi-child wrappers
|
|
1437
|
+
if (n.inner) {
|
|
1438
|
+
for (const child of n.inner) {
|
|
1439
|
+
const val = evaluate(child);
|
|
1440
|
+
if (val !== null) return val;
|
|
1441
|
+
}
|
|
1442
|
+
}
|
|
1443
|
+
return null;
|
|
1444
|
+
}
|
|
1445
|
+
|
|
1446
|
+
return evaluate(node);
|
|
1447
|
+
}
|
|
1448
|
+
|
|
1449
|
+
/**
|
|
1450
|
+
* Parse a clang AST root node and extract standalone numeric constants.
|
|
1451
|
+
*
|
|
1452
|
+
* These are `static const` VarDecl nodes with numeric types (CGFloat, double, float,
|
|
1453
|
+
* NSInteger, NSUInteger, NSTimeInterval, int, long) that are NOT linked to a
|
|
1454
|
+
* NS_TYPED_EXTENSIBLE_ENUM typedef via `typeAliasDeclId`.
|
|
1455
|
+
*
|
|
1456
|
+
* Examples:
|
|
1457
|
+
* - `static const CGFloat NSVariableStatusItemLength = -1;`
|
|
1458
|
+
* - `static const NSInteger NSSearchFieldRecentsTitleMenuItemTag = 1000;`
|
|
1459
|
+
*
|
|
1460
|
+
* @param targetConstants - Set of constant names to extract (from discovery)
|
|
1461
|
+
*/
|
|
1462
|
+
export function parseNumericConstants(
|
|
1463
|
+
root: ClangASTNode,
|
|
1464
|
+
targetConstants: Set<string>
|
|
1465
|
+
): Map<string, ObjCNumericConstant> {
|
|
1466
|
+
const constants = new Map<string, ObjCNumericConstant>();
|
|
1467
|
+
if (targetConstants.size === 0) return constants;
|
|
1468
|
+
|
|
1469
|
+
// Collect all TypedefDecl ids that are NS_TYPED_EXTENSIBLE_ENUM / NS_TYPED_ENUM
|
|
1470
|
+
// so we can exclude VarDecls that are already handled by parseIntegerTypedEnums.
|
|
1471
|
+
const typedEnumIds = new Set<string>();
|
|
1472
|
+
function walkForTypedEnumTypedefs(node: ClangASTNode): void {
|
|
1473
|
+
if (node.kind === "TypedefDecl" && node.id) {
|
|
1474
|
+
const hasSwiftNewType = node.inner?.some((child) => child.kind === "SwiftNewTypeAttr") ?? false;
|
|
1475
|
+
if (hasSwiftNewType) {
|
|
1476
|
+
typedEnumIds.add(node.id);
|
|
1477
|
+
}
|
|
1478
|
+
}
|
|
1479
|
+
if (node.inner) {
|
|
1480
|
+
for (const child of node.inner) {
|
|
1481
|
+
walkForTypedEnumTypedefs(child);
|
|
1482
|
+
}
|
|
1483
|
+
}
|
|
1484
|
+
}
|
|
1485
|
+
|
|
1486
|
+
function walkForConstants(node: ClangASTNode): void {
|
|
1487
|
+
if (node.kind === "VarDecl" && node.name && node.storageClass === "static" && targetConstants.has(node.name)) {
|
|
1488
|
+
// Skip VarDecls linked to NS_TYPED_EXTENSIBLE_ENUM typedefs (handled by parseIntegerTypedEnums)
|
|
1489
|
+
if (node.type?.typeAliasDeclId && typedEnumIds.has(node.type.typeAliasDeclId)) {
|
|
1490
|
+
return;
|
|
1491
|
+
}
|
|
1492
|
+
|
|
1493
|
+
// Check that the type is a const numeric type
|
|
1494
|
+
const qualType = node.type?.qualType ?? "";
|
|
1495
|
+
const desugared = node.type?.desugaredQualType ?? "";
|
|
1496
|
+
const isConstNumeric =
|
|
1497
|
+
/\bconst\b/.test(qualType) &&
|
|
1498
|
+
(/\b(CGFloat|double|float|NSInteger|NSUInteger|NSTimeInterval|int|long)\b/.test(qualType) ||
|
|
1499
|
+
/\b(double|float|long|int|unsigned long)\b/.test(desugared));
|
|
1500
|
+
|
|
1501
|
+
if (!isConstNumeric) return;
|
|
1502
|
+
|
|
1503
|
+
const value = extractNumericValue(node);
|
|
1504
|
+
if (value === null) return;
|
|
1505
|
+
|
|
1506
|
+
// Determine if this is a float type
|
|
1507
|
+
const isFloat =
|
|
1508
|
+
/\b(CGFloat|double|float|NSTimeInterval)\b/.test(qualType) || /\b(double|float)\b/.test(desugared);
|
|
1509
|
+
|
|
1510
|
+
if (!constants.has(node.name)) {
|
|
1511
|
+
constants.set(node.name, {
|
|
1512
|
+
name: node.name,
|
|
1513
|
+
value,
|
|
1514
|
+
isFloat
|
|
1515
|
+
});
|
|
1516
|
+
}
|
|
1517
|
+
}
|
|
1518
|
+
|
|
1519
|
+
if (node.inner) {
|
|
1520
|
+
for (const child of node.inner) {
|
|
1521
|
+
walkForConstants(child);
|
|
1522
|
+
}
|
|
1523
|
+
}
|
|
1524
|
+
}
|
|
1525
|
+
|
|
1526
|
+
// First pass: find typed enum typedef IDs to exclude
|
|
1527
|
+
walkForTypedEnumTypedefs(root);
|
|
1528
|
+
// Second pass: find matching VarDecl constants
|
|
1529
|
+
walkForConstants(root);
|
|
1530
|
+
|
|
1531
|
+
return constants;
|
|
1532
|
+
}
|
|
1533
|
+
|
|
1402
1534
|
// --- Struct parsing ---
|
|
1403
1535
|
|
|
1404
1536
|
/**
|
package/generator/discover.ts
CHANGED
|
@@ -15,6 +15,8 @@ export interface DiscoveryResult {
|
|
|
15
15
|
integerEnums: Map<string, string>;
|
|
16
16
|
/** Maps string enum name → header file name (without .h extension) */
|
|
17
17
|
stringEnums: Map<string, string>;
|
|
18
|
+
/** Maps numeric constant name → header file name (without .h extension) */
|
|
19
|
+
numericConstants: Map<string, string>;
|
|
18
20
|
}
|
|
19
21
|
|
|
20
22
|
/** Matches `@interface ClassName` — captures class name */
|
|
@@ -58,6 +60,18 @@ const NS_INTEGER_TYPED_ENUM_RE = /typedef\s+NSU?Integer\s+(\w+)\s+NS_(?:TYPED_EX
|
|
|
58
60
|
*/
|
|
59
61
|
const NS_ERROR_ENUM_RE = /typedef\s+NS_ERROR_ENUM\s*\(\s*\w+\s*,\s*(\w+)\s*\)/;
|
|
60
62
|
|
|
63
|
+
/**
|
|
64
|
+
* Matches standalone `static const` numeric variable declarations.
|
|
65
|
+
* These are constants like `NSVariableStatusItemLength`, `NSEventDurationForever`, etc.
|
|
66
|
+
* Captures the constant name from declarations like:
|
|
67
|
+
* `static const CGFloat NSVariableStatusItemLength = -1;`
|
|
68
|
+
* `static const NSInteger NSSearchFieldRecentsTitleMenuItemTag = 1000;`
|
|
69
|
+
* `static const CGFloat NSStackViewSpacingUseDefault API_AVAILABLE(macos(10.9)) = FLT_MAX;`
|
|
70
|
+
* Allows optional API_AVAILABLE / NS_AVAILABLE / etc. attributes between name and `=`.
|
|
71
|
+
*/
|
|
72
|
+
const STATIC_CONST_NUMERIC_RE =
|
|
73
|
+
/static\s+(?:const\s+)?(?:CGFloat|double|float|NSInteger|NSUInteger|NSTimeInterval|int|long)\s+(?:const\s+)?(\w+)\b[^;]*=/;
|
|
74
|
+
|
|
61
75
|
/**
|
|
62
76
|
* Scan all .h files in a framework's Headers directory and discover
|
|
63
77
|
* every ObjC class and protocol declaration, mapping each to its header file.
|
|
@@ -71,6 +85,7 @@ export async function discoverFramework(headersPath: string): Promise<DiscoveryR
|
|
|
71
85
|
const protocols = new Map<string, string>();
|
|
72
86
|
const integerEnums = new Map<string, string>();
|
|
73
87
|
const stringEnums = new Map<string, string>();
|
|
88
|
+
const numericConstants = new Map<string, string>();
|
|
74
89
|
|
|
75
90
|
const entries = await readdir(headersPath);
|
|
76
91
|
const headerFiles = entries.filter((f) => f.endsWith(".h")).sort();
|
|
@@ -141,8 +156,18 @@ export async function discoverFramework(headersPath: string): Promise<DiscoveryR
|
|
|
141
156
|
integerEnums.set(name, headerName);
|
|
142
157
|
}
|
|
143
158
|
}
|
|
159
|
+
|
|
160
|
+
// --- Standalone numeric constants ---
|
|
161
|
+
// e.g., `static const CGFloat NSVariableStatusItemLength = -1;`
|
|
162
|
+
const numericConstMatch = STATIC_CONST_NUMERIC_RE.exec(line);
|
|
163
|
+
if (numericConstMatch) {
|
|
164
|
+
const name = numericConstMatch[1]!;
|
|
165
|
+
if (!numericConstants.has(name)) {
|
|
166
|
+
numericConstants.set(name, headerName);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
144
169
|
}
|
|
145
170
|
}
|
|
146
171
|
|
|
147
|
-
return { classes, protocols, integerEnums, stringEnums };
|
|
172
|
+
return { classes, protocols, integerEnums, stringEnums, numericConstants };
|
|
148
173
|
}
|
package/generator/emitter.ts
CHANGED
|
@@ -10,7 +10,8 @@ import type {
|
|
|
10
10
|
ObjCIntegerEnum,
|
|
11
11
|
ObjCStringEnum,
|
|
12
12
|
ObjCStringEnumValue,
|
|
13
|
-
ObjCFunction
|
|
13
|
+
ObjCFunction,
|
|
14
|
+
ObjCNumericConstant
|
|
14
15
|
} from "./ast-parser.ts";
|
|
15
16
|
import type { FrameworkConfig } from "./frameworks.ts";
|
|
16
17
|
import {
|
|
@@ -1809,6 +1810,36 @@ export function emitFunctionsFile(
|
|
|
1809
1810
|
return lines.join("\n");
|
|
1810
1811
|
}
|
|
1811
1812
|
|
|
1813
|
+
/**
|
|
1814
|
+
* Generate a constants.ts file for a framework.
|
|
1815
|
+
* Emits `export const NAME: number = VALUE;` for each standalone numeric constant.
|
|
1816
|
+
*
|
|
1817
|
+
* Example output:
|
|
1818
|
+
* ```ts
|
|
1819
|
+
* // AUTO-GENERATED by objcjs-types generator — DO NOT EDIT
|
|
1820
|
+
*
|
|
1821
|
+
* export const NSVariableStatusItemLength: number = -1;
|
|
1822
|
+
* export const NSSquareStatusItemLength: number = -2;
|
|
1823
|
+
* ```
|
|
1824
|
+
*/
|
|
1825
|
+
export function emitConstantsFile(constants: ObjCNumericConstant[]): string {
|
|
1826
|
+
const lines: string[] = [];
|
|
1827
|
+
lines.push(AUTOGEN_HEADER);
|
|
1828
|
+
lines.push("");
|
|
1829
|
+
|
|
1830
|
+
// Sort constants alphabetically for deterministic output
|
|
1831
|
+
const sorted = [...constants].sort((a, b) => a.name.localeCompare(b.name));
|
|
1832
|
+
|
|
1833
|
+
for (const constant of sorted) {
|
|
1834
|
+
// Format the value: use integer representation when possible for cleaner output
|
|
1835
|
+
const valueStr = Number.isInteger(constant.value) ? String(constant.value) : String(constant.value);
|
|
1836
|
+
lines.push(`export const ${constant.name}: number = ${valueStr};`);
|
|
1837
|
+
}
|
|
1838
|
+
lines.push("");
|
|
1839
|
+
|
|
1840
|
+
return lines.join("\n");
|
|
1841
|
+
}
|
|
1842
|
+
|
|
1812
1843
|
/**
|
|
1813
1844
|
* Extract class, struct, and enum references from a mapped TS type string
|
|
1814
1845
|
* (used by emitFunctionsFile for collecting imports).
|
|
@@ -1878,7 +1909,7 @@ export function emitFrameworkIndex(
|
|
|
1878
1909
|
// as the framework (e.g. IOSurface framework has an IOSurface class)
|
|
1879
1910
|
const classNames = new Set(generatedClasses);
|
|
1880
1911
|
const libVar = classNames.has(framework.name) ? `${framework.name}_lib` : framework.name;
|
|
1881
|
-
lines.push(`export const ${libVar} = new NobjcLibrary("${framework.libraryPath}");`);
|
|
1912
|
+
lines.push(`export const ${libVar} = /* @__PURE__ */ new NobjcLibrary("${framework.libraryPath}");`);
|
|
1882
1913
|
lines.push("");
|
|
1883
1914
|
|
|
1884
1915
|
// Build a reverse lookup: className → canonical filename for collision groups
|
|
@@ -1894,7 +1925,7 @@ export function emitFrameworkIndex(
|
|
|
1894
1925
|
for (const className of generatedClasses) {
|
|
1895
1926
|
const fileName = classToFile.get(className) ?? className;
|
|
1896
1927
|
lines.push(`import type { _${className} } from "./${fileName}.js";`);
|
|
1897
|
-
lines.push(`export const ${className} = _bindClass<typeof _${className}>(${libVar}, "${className}");`);
|
|
1928
|
+
lines.push(`export const ${className} = /* @__PURE__ */ _bindClass<typeof _${className}>(${libVar}, "${className}");`);
|
|
1898
1929
|
lines.push(`export type { _${className} };`);
|
|
1899
1930
|
lines.push("");
|
|
1900
1931
|
}
|
package/generator/frameworks.ts
CHANGED
|
@@ -31,6 +31,8 @@ export interface FrameworkConfig extends FrameworkBase {
|
|
|
31
31
|
integerEnums: string[];
|
|
32
32
|
/** All discovered string enum names (NS_TYPED_EXTENSIBLE_ENUM etc.) */
|
|
33
33
|
stringEnums: string[];
|
|
34
|
+
/** All discovered standalone numeric constant names */
|
|
35
|
+
numericConstants: string[];
|
|
34
36
|
/** Maps class name → header file name (without .h) */
|
|
35
37
|
classHeaders: Map<string, string>;
|
|
36
38
|
/** Maps protocol name → header file name (without .h) */
|
|
@@ -39,6 +41,8 @@ export interface FrameworkConfig extends FrameworkBase {
|
|
|
39
41
|
integerEnumHeaders: Map<string, string>;
|
|
40
42
|
/** Maps string enum name → header file name (without .h) */
|
|
41
43
|
stringEnumHeaders: Map<string, string>;
|
|
44
|
+
/** Maps numeric constant name → header file name (without .h) */
|
|
45
|
+
numericConstantHeaders: Map<string, string>;
|
|
42
46
|
}
|
|
43
47
|
|
|
44
48
|
export const SDK_PATH =
|
package/generator/index.ts
CHANGED
|
@@ -24,7 +24,8 @@ import type {
|
|
|
24
24
|
ObjCStringEnum,
|
|
25
25
|
ObjCStruct,
|
|
26
26
|
ObjCStructAlias,
|
|
27
|
-
ObjCFunction
|
|
27
|
+
ObjCFunction,
|
|
28
|
+
ObjCNumericConstant
|
|
28
29
|
} from "./ast-parser.ts";
|
|
29
30
|
import {
|
|
30
31
|
setKnownClasses,
|
|
@@ -51,6 +52,7 @@ import {
|
|
|
51
52
|
emitIntegerEnumFile,
|
|
52
53
|
emitStringEnumFile,
|
|
53
54
|
emitFunctionsFile,
|
|
55
|
+
emitConstantsFile,
|
|
54
56
|
groupCaseCollisions
|
|
55
57
|
} from "./emitter.ts";
|
|
56
58
|
import type { StructDef, StructFieldDef } from "./emitter.ts";
|
|
@@ -123,7 +125,8 @@ async function main(): Promise<void> {
|
|
|
123
125
|
discovery.classes.size === 0 &&
|
|
124
126
|
discovery.protocols.size === 0 &&
|
|
125
127
|
discovery.integerEnums.size === 0 &&
|
|
126
|
-
discovery.stringEnums.size === 0
|
|
128
|
+
discovery.stringEnums.size === 0 &&
|
|
129
|
+
discovery.numericConstants.size === 0
|
|
127
130
|
)
|
|
128
131
|
continue;
|
|
129
132
|
|
|
@@ -133,15 +136,20 @@ async function main(): Promise<void> {
|
|
|
133
136
|
protocols: [...discovery.protocols.keys()].sort(),
|
|
134
137
|
integerEnums: [...discovery.integerEnums.keys()].sort(),
|
|
135
138
|
stringEnums: [...discovery.stringEnums.keys()].sort(),
|
|
139
|
+
numericConstants: [...discovery.numericConstants.keys()].sort(),
|
|
136
140
|
classHeaders: discovery.classes,
|
|
137
141
|
protocolHeaders: discovery.protocols,
|
|
138
142
|
integerEnumHeaders: discovery.integerEnums,
|
|
139
|
-
stringEnumHeaders: discovery.stringEnums
|
|
143
|
+
stringEnumHeaders: discovery.stringEnums,
|
|
144
|
+
numericConstantHeaders: discovery.numericConstants
|
|
140
145
|
};
|
|
141
146
|
frameworks.push(fw);
|
|
142
147
|
|
|
143
148
|
const enumCount = fw.integerEnums.length + fw.stringEnums.length;
|
|
144
|
-
|
|
149
|
+
const constStr = fw.numericConstants.length > 0 ? `, ${fw.numericConstants.length} constants` : "";
|
|
150
|
+
console.log(
|
|
151
|
+
` ${fw.name}: ${fw.classes.length} classes, ${fw.protocols.length} protocols, ${enumCount} enums${constStr}`
|
|
152
|
+
);
|
|
145
153
|
}
|
|
146
154
|
const discoveryTime = ((performance.now() - globalStart) / 1000).toFixed(1);
|
|
147
155
|
console.log(` Discovery completed in ${discoveryTime}s\n`);
|
|
@@ -209,6 +217,7 @@ async function main(): Promise<void> {
|
|
|
209
217
|
protocolTargets: string[];
|
|
210
218
|
integerEnumTargets: string[];
|
|
211
219
|
stringEnumTargets: string[];
|
|
220
|
+
numericConstantTargets: string[];
|
|
212
221
|
preIncludes: string[];
|
|
213
222
|
}
|
|
214
223
|
|
|
@@ -239,6 +248,7 @@ async function main(): Promise<void> {
|
|
|
239
248
|
const protocolTargets: string[] = [];
|
|
240
249
|
const integerEnumTargets: string[] = [];
|
|
241
250
|
const stringEnumTargets: string[] = [];
|
|
251
|
+
const numericConstantTargets: string[] = [];
|
|
242
252
|
|
|
243
253
|
// --- Class targets ---
|
|
244
254
|
for (const className of fw.classes) {
|
|
@@ -284,13 +294,21 @@ async function main(): Promise<void> {
|
|
|
284
294
|
stringEnumTargets.push(enumName);
|
|
285
295
|
}
|
|
286
296
|
|
|
297
|
+
// --- Numeric constant targets ---
|
|
298
|
+
// No header validation needed — constants are discovered from the same headers
|
|
299
|
+
// that are already included in allFrameworkHeaders.
|
|
300
|
+
for (const constName of fw.numericConstants) {
|
|
301
|
+
numericConstantTargets.push(constName);
|
|
302
|
+
}
|
|
303
|
+
|
|
287
304
|
// Only create a batch task if there are targets to parse
|
|
288
305
|
if (
|
|
289
306
|
allFrameworkHeaders.length > 0 &&
|
|
290
307
|
(classTargets.length > 0 ||
|
|
291
308
|
protocolTargets.length > 0 ||
|
|
292
309
|
integerEnumTargets.length > 0 ||
|
|
293
|
-
stringEnumTargets.length > 0
|
|
310
|
+
stringEnumTargets.length > 0 ||
|
|
311
|
+
numericConstantTargets.length > 0)
|
|
294
312
|
) {
|
|
295
313
|
batchTasks.push({
|
|
296
314
|
frameworkName: fw.name,
|
|
@@ -299,6 +317,7 @@ async function main(): Promise<void> {
|
|
|
299
317
|
protocolTargets,
|
|
300
318
|
integerEnumTargets,
|
|
301
319
|
stringEnumTargets,
|
|
320
|
+
numericConstantTargets,
|
|
302
321
|
preIncludes
|
|
303
322
|
});
|
|
304
323
|
}
|
|
@@ -329,7 +348,7 @@ async function main(): Promise<void> {
|
|
|
329
348
|
// The actual per-task bottleneck is clang execution + JSON.parse (~95% of
|
|
330
349
|
// task time), not the AST walk passes (~5%). Any Xcode-capable Mac with
|
|
331
350
|
// 32+GB RAM handles 8 workers comfortably.
|
|
332
|
-
const cpuCount = navigator.hardwareConcurrency
|
|
351
|
+
const cpuCount = navigator.hardwareConcurrency || 4;
|
|
333
352
|
const poolSize = Math.min(cpuCount, 8);
|
|
334
353
|
const pool = new WorkerPool(poolSize);
|
|
335
354
|
const totalBatchTasks = batchTasks.length;
|
|
@@ -365,7 +384,8 @@ async function main(): Promise<void> {
|
|
|
365
384
|
task.integerEnumTargets,
|
|
366
385
|
task.stringEnumTargets,
|
|
367
386
|
task.preIncludes,
|
|
368
|
-
task.frameworkName
|
|
387
|
+
task.frameworkName,
|
|
388
|
+
task.numericConstantTargets
|
|
369
389
|
)
|
|
370
390
|
.then((result) => {
|
|
371
391
|
trackProgress(task.frameworkName);
|
|
@@ -544,6 +564,22 @@ async function main(): Promise<void> {
|
|
|
544
564
|
}
|
|
545
565
|
}
|
|
546
566
|
|
|
567
|
+
// Organize parsed numeric constants by framework
|
|
568
|
+
const frameworkNumericConstants = new Map<string, Map<string, ObjCNumericConstant>>();
|
|
569
|
+
for (const entry of allResults) {
|
|
570
|
+
if (entry.isExtra) continue;
|
|
571
|
+
if (entry.error || !entry.result) continue;
|
|
572
|
+
if (entry.result.numericConstants.size === 0) continue;
|
|
573
|
+
|
|
574
|
+
if (!frameworkNumericConstants.has(entry.task.frameworkName)) {
|
|
575
|
+
frameworkNumericConstants.set(entry.task.frameworkName, new Map());
|
|
576
|
+
}
|
|
577
|
+
const fwConsts = frameworkNumericConstants.get(entry.task.frameworkName)!;
|
|
578
|
+
for (const [name, constant] of entry.result.numericConstants) {
|
|
579
|
+
fwConsts.set(name, constant);
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
|
|
547
583
|
// Collect all parsed structs and struct aliases across all headers
|
|
548
584
|
const allParsedStructs = new Map<string, ObjCStruct>();
|
|
549
585
|
const allStructAliases: ObjCStructAlias[] = [];
|
|
@@ -1228,6 +1264,15 @@ async function main(): Promise<void> {
|
|
|
1228
1264
|
hasFunctions = true;
|
|
1229
1265
|
}
|
|
1230
1266
|
|
|
1267
|
+
// Emit constants file (standalone numeric constants)
|
|
1268
|
+
const fwConsts = frameworkNumericConstants.get(framework.name);
|
|
1269
|
+
let hasConstants = false;
|
|
1270
|
+
if (fwConsts && fwConsts.size > 0) {
|
|
1271
|
+
const constantsContent = emitConstantsFile([...fwConsts.values()]);
|
|
1272
|
+
await writeFile(join(frameworkDir, "constants.ts"), constantsContent);
|
|
1273
|
+
hasConstants = true;
|
|
1274
|
+
}
|
|
1275
|
+
|
|
1231
1276
|
// Emit framework index
|
|
1232
1277
|
const indexContent = emitFrameworkIndex(
|
|
1233
1278
|
framework,
|
|
@@ -1246,8 +1291,9 @@ async function main(): Promise<void> {
|
|
|
1246
1291
|
const totalEnumCount =
|
|
1247
1292
|
generatedIntegerEnums.length + generatedStringEnums.length + generatedStringEnumsTypeOnly.length;
|
|
1248
1293
|
const funcCountStr = hasFunctions ? ` + ${fwFuncs!.size} functions` : "";
|
|
1294
|
+
const constCountStr = hasConstants ? ` + ${fwConsts!.size} constants` : "";
|
|
1249
1295
|
console.log(
|
|
1250
|
-
` ${framework.name}: ${generatedClasses.length} class files + ${generatedProtocols.length} protocol files + ${totalEnumCount} enum files${funcCountStr} + index.ts`
|
|
1296
|
+
` ${framework.name}: ${generatedClasses.length} class files + ${generatedProtocols.length} protocol files + ${totalEnumCount} enum files${funcCountStr}${constCountStr} + index.ts`
|
|
1251
1297
|
);
|
|
1252
1298
|
}
|
|
1253
1299
|
|
|
@@ -1307,21 +1353,27 @@ async function main(): Promise<void> {
|
|
|
1307
1353
|
let totalProtocols = 0;
|
|
1308
1354
|
let totalEnums = 0;
|
|
1309
1355
|
let totalFunctions = 0;
|
|
1356
|
+
let totalConstants = 0;
|
|
1310
1357
|
for (const fw of frameworksToProcess) {
|
|
1311
1358
|
const dir = join(SRC_DIR, fw.name);
|
|
1312
1359
|
const classCount = fw.classes.filter((c) => existsSync(join(dir, `${c}.ts`))).length;
|
|
1313
1360
|
const protoCount = fw.protocols.filter((p) => existsSync(join(dir, `${p}.ts`))).length;
|
|
1314
1361
|
const enumCount = [...fw.integerEnums, ...fw.stringEnums].filter((e) => existsSync(join(dir, `${e}.ts`))).length;
|
|
1315
1362
|
const funcCount = frameworkFunctions.get(fw.name)?.size ?? 0;
|
|
1363
|
+
const constCount = frameworkNumericConstants.get(fw.name)?.size ?? 0;
|
|
1316
1364
|
const funcStr = funcCount > 0 ? `, ${funcCount} functions` : "";
|
|
1317
|
-
|
|
1365
|
+
const constStr = constCount > 0 ? `, ${constCount} constants` : "";
|
|
1366
|
+
console.log(
|
|
1367
|
+
` ${fw.name}: ${classCount} classes, ${protoCount} protocols, ${enumCount} enums${funcStr}${constStr}`
|
|
1368
|
+
);
|
|
1318
1369
|
totalClasses += classCount;
|
|
1319
1370
|
totalProtocols += protoCount;
|
|
1320
1371
|
totalEnums += enumCount;
|
|
1321
1372
|
totalFunctions += funcCount;
|
|
1373
|
+
totalConstants += constCount;
|
|
1322
1374
|
}
|
|
1323
1375
|
console.log(
|
|
1324
|
-
` Total: ${totalClasses} classes, ${totalProtocols} protocols, ${totalEnums} enums, ${totalFunctions} functions`
|
|
1376
|
+
` Total: ${totalClasses} classes, ${totalProtocols} protocols, ${totalEnums} enums, ${totalFunctions} functions, ${totalConstants} constants`
|
|
1325
1377
|
);
|
|
1326
1378
|
|
|
1327
1379
|
// Clean up the compiled ObjC helper binary
|
|
@@ -18,7 +18,8 @@ import {
|
|
|
18
18
|
parseStringEnums,
|
|
19
19
|
parseStructs,
|
|
20
20
|
parseTypedefs,
|
|
21
|
-
parseFunctions
|
|
21
|
+
parseFunctions,
|
|
22
|
+
parseNumericConstants
|
|
22
23
|
} from "./ast-parser.ts";
|
|
23
24
|
|
|
24
25
|
/**
|
|
@@ -95,6 +96,10 @@ self.onmessage = async (event: MessageEvent) => {
|
|
|
95
96
|
const frameworkHeaderPathSet = new Set<string>(headerPaths);
|
|
96
97
|
const functions = parseFunctions(ast, frameworkHeaderPathSet, msg.frameworkName ?? "");
|
|
97
98
|
|
|
99
|
+
// Parse standalone numeric constants
|
|
100
|
+
const numericConstantTargetSet = new Set<string>(msg.numericConstantTargets ?? []);
|
|
101
|
+
const numericConstants = parseNumericConstants(ast, numericConstantTargetSet);
|
|
102
|
+
|
|
98
103
|
postMessage({
|
|
99
104
|
id: msg.id,
|
|
100
105
|
type: "batch-result",
|
|
@@ -106,6 +111,7 @@ self.onmessage = async (event: MessageEvent) => {
|
|
|
106
111
|
structAliases: structResult.aliases,
|
|
107
112
|
typedefs: [...typedefs.entries()],
|
|
108
113
|
functions: [...functions.entries()],
|
|
114
|
+
numericConstants: [...numericConstants.entries()],
|
|
109
115
|
// Report what was found vs expected for logging
|
|
110
116
|
foundClasses: classes.size,
|
|
111
117
|
foundProtocols: protocols.size,
|
|
@@ -209,7 +215,8 @@ self.onmessage = async (event: MessageEvent) => {
|
|
|
209
215
|
structs: [...structResult.structs.entries()],
|
|
210
216
|
structAliases: structResult.aliases,
|
|
211
217
|
typedefs: [...typedefs.entries()],
|
|
212
|
-
functions: [] // parse-all is used for extra headers which don't need function parsing
|
|
218
|
+
functions: [], // parse-all is used for extra headers which don't need function parsing
|
|
219
|
+
numericConstants: [] // parse-all is used for extra headers which don't need constant parsing
|
|
213
220
|
});
|
|
214
221
|
} else if (msg.type === "parse-classes") {
|
|
215
222
|
const targetSet = new Set<string>(msg.targets);
|
|
@@ -93,6 +93,10 @@ export function isKindOfClass<T extends NobjcObject>(obj: NobjcObject, cls: any)
|
|
|
93
93
|
*/
|
|
94
94
|
export function _bindClass<T>(lib: any, name: string): T {
|
|
95
95
|
const cls = lib[name];
|
|
96
|
+
if (!cls) {
|
|
97
|
+
// Very unlikely to happen, but just in case, return undefined.
|
|
98
|
+
return undefined as unknown as T;
|
|
99
|
+
}
|
|
96
100
|
Object.defineProperty(cls, Symbol.hasInstance, {
|
|
97
101
|
value: (obj: any) => _isKindOfClass(obj, cls)
|
|
98
102
|
});
|
|
@@ -67,4 +67,57 @@ export function NSDictionaryFromKeysAndValues(keys: NobjcObject[], values: Nobjc
|
|
|
67
67
|
return NSDictionary.dictionaryWithObjects$forKeys$(valuesArray, keysArray);
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
+
/**
|
|
71
|
+
* Returns the key name for a given numeric value in a const enum-like object.
|
|
72
|
+
*
|
|
73
|
+
* @param enumObj - A const object mapping string keys to numeric values.
|
|
74
|
+
* @param value - The numeric value to look up.
|
|
75
|
+
* @returns The matching key name, or `undefined` if not found.
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* ```ts
|
|
79
|
+
* const state = enumFromValue(
|
|
80
|
+
* ASAuthorizationWebBrowserPublicKeyCredentialManagerAuthorizationState,
|
|
81
|
+
* rawValue
|
|
82
|
+
* ); // e.g. "Authorized" | "Denied" | "NotDetermined" | undefined
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
85
|
+
export function enumFromValue<T extends Record<string, number>>(enumObj: T, value: number): keyof T | undefined {
|
|
86
|
+
return (Object.keys(enumObj) as (keyof T)[]).find((key) => enumObj[key] === value);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function PromiseWithResolvers<T = void>(): {
|
|
90
|
+
promise: Promise<T>;
|
|
91
|
+
resolve: (value: T | PromiseLike<T>) => void;
|
|
92
|
+
reject: (reason?: unknown) => void;
|
|
93
|
+
} {
|
|
94
|
+
let resolve: (value: T | PromiseLike<T>) => void;
|
|
95
|
+
let reject: (reason?: unknown) => void;
|
|
96
|
+
const promise = new Promise<T>((res, rej) => {
|
|
97
|
+
resolve = res;
|
|
98
|
+
reject = rej;
|
|
99
|
+
});
|
|
100
|
+
return { promise, resolve: resolve!, reject: reject! };
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Converts a callback-based function with a single result parameter into a Promise.
|
|
104
|
+
*
|
|
105
|
+
* @template TArgs - The argument types of the original function (excluding the callback)
|
|
106
|
+
* @template TResult - The type of the result passed to the callback
|
|
107
|
+
* @param func - A function that takes arguments and a callback with a single result parameter
|
|
108
|
+
* @param args - The arguments to pass to the function (excluding the callback)
|
|
109
|
+
* @returns A Promise that resolves with the result passed to the callback
|
|
110
|
+
*/
|
|
111
|
+
export function makePromise1Result<TArgs extends any[], TResult>(
|
|
112
|
+
func: (...args: [...TArgs, (result: TResult) => void]) => void,
|
|
113
|
+
...args: TArgs
|
|
114
|
+
): Promise<TResult> {
|
|
115
|
+
const { promise, resolve } = PromiseWithResolvers<TResult>();
|
|
116
|
+
const callback = (result: TResult) => {
|
|
117
|
+
resolve(result);
|
|
118
|
+
};
|
|
119
|
+
func(...args, callback);
|
|
120
|
+
return promise;
|
|
121
|
+
}
|
|
122
|
+
|
|
70
123
|
export { isKindOfClass } from "./bind.js";
|