node-mac-recorder 2.21.46 → 2.21.48

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-mac-recorder",
3
- "version": "2.21.46",
3
+ "version": "2.21.48",
4
4
  "description": "Native macOS screen recording package for Node.js applications",
5
5
  "main": "index.js",
6
6
  "keywords": [
@@ -1223,49 +1223,90 @@ static void LoadCursorMappingOverrides(void) {
1223
1223
 
1224
1224
  // Runtime seed mapping - built dynamically on first use
1225
1225
  // Seeds change between app launches, so we build the mapping at runtime by querying NSCursor objects
1226
+ // SAFETY: Protected with try-catch to prevent crashes in Electron environments
1227
+ static BOOL g_enableSeedLearning = YES; // Runtime seed learning enabled with crash protection
1226
1228
  static NSMutableDictionary<NSNumber*, NSString*> *g_seedToTypeMap = nil;
1227
1229
  static dispatch_once_t g_seedMapInitToken;
1228
1230
 
1229
1231
  static void buildRuntimeSeedMapping() {
1230
1232
  dispatch_once(&g_seedMapInitToken, ^{
1231
- g_seedToTypeMap = [NSMutableDictionary dictionary];
1233
+ @try {
1234
+ @autoreleasepool {
1235
+ g_seedToTypeMap = [[NSMutableDictionary alloc] init];
1232
1236
 
1233
- // Instead of trying to build mapping upfront (which crashes),
1234
- // we'll build it lazily as we encounter cursors during actual usage
1235
- // For now, just initialize the empty map
1237
+ // Instead of trying to build mapping upfront (which crashes),
1238
+ // we'll build it lazily as we encounter cursors during actual usage
1239
+ // For now, just initialize the empty map
1236
1240
 
1237
- NSLog(@"✅ Runtime seed mapping initialized (will build lazily)");
1241
+ NSLog(@"✅ Runtime seed mapping initialized (will build lazily)");
1242
+ }
1243
+ } @catch (NSException *exception) {
1244
+ NSLog(@"⚠️ Failed to initialize runtime seed mapping: %@", exception.reason);
1245
+ g_seedToTypeMap = nil;
1246
+ }
1238
1247
  });
1239
1248
  }
1240
1249
 
1241
1250
  // Add a cursor seed to the runtime mapping
1242
- static void addCursorToSeedMap(NSCursor *cursor, NSString *detectedType, int seed) {
1243
- if (seed <= 0 || !cursor || !detectedType) return;
1251
+ // NOTE: We don't pass cursor object to avoid potential crashes - we only need seed and type
1252
+ static void addCursorToSeedMap(NSString *detectedType, int seed) {
1253
+ // Safety: Check if learning is enabled
1254
+ if (!g_enableSeedLearning) return;
1244
1255
 
1245
- buildRuntimeSeedMapping(); // Ensure map is initialized
1256
+ if (seed <= 0 || !detectedType || [detectedType length] == 0) return;
1246
1257
 
1247
- // Only add if we don't have this seed yet
1248
- if (![g_seedToTypeMap objectForKey:@(seed)]) {
1249
- g_seedToTypeMap[@(seed)] = detectedType;
1250
- // Log only first 10 learned mappings to avoid spam
1251
- if ([g_seedToTypeMap count] <= 10) {
1252
- NSLog(@"📝 Learned seed mapping: %d -> %@", seed, detectedType);
1258
+ @try {
1259
+ @autoreleasepool {
1260
+ buildRuntimeSeedMapping(); // Ensure map is initialized
1261
+
1262
+ // If initialization failed, don't proceed
1263
+ if (!g_seedToTypeMap) return;
1264
+
1265
+ NSNumber *key = @(seed);
1266
+
1267
+ // Only add if we don't have this seed yet
1268
+ if (![g_seedToTypeMap objectForKey:key]) {
1269
+ [g_seedToTypeMap setObject:detectedType forKey:key];
1270
+ // Log only first 10 learned mappings to avoid spam
1271
+ if ([g_seedToTypeMap count] <= 10) {
1272
+ NSLog(@"📝 Learned seed mapping: %d -> %@", seed, detectedType);
1273
+ }
1274
+ }
1253
1275
  }
1276
+ } @catch (NSException *exception) {
1277
+ // Silently fail - don't crash the app for cursor learning
1278
+ NSLog(@"⚠️ Failed to add cursor seed mapping: %@", exception.reason);
1279
+ } @catch (...) {
1280
+ NSLog(@"⚠️ Failed to add cursor seed mapping (unknown exception)");
1254
1281
  }
1255
1282
  }
1256
1283
 
1257
1284
  static NSString* cursorTypeFromSeed(int seed) {
1258
1285
  if (seed > 0) {
1259
- NSNumber *key = @(seed);
1260
- NSString *override = [g_seedOverrides objectForKey:key];
1261
- if (override) {
1262
- return override;
1263
- }
1286
+ @try {
1287
+ @autoreleasepool {
1288
+ NSNumber *key = @(seed);
1289
+ NSString *override = [g_seedOverrides objectForKey:key];
1290
+ if (override) {
1291
+ return override;
1292
+ }
1264
1293
 
1265
- buildRuntimeSeedMapping();
1266
- NSString *runtime = [g_seedToTypeMap objectForKey:key];
1267
- if (runtime) {
1268
- return runtime;
1294
+ // Only check runtime mappings if learning is enabled
1295
+ if (g_enableSeedLearning) {
1296
+ buildRuntimeSeedMapping();
1297
+ if (g_seedToTypeMap) {
1298
+ NSString *runtime = [g_seedToTypeMap objectForKey:key];
1299
+ if (runtime) {
1300
+ return runtime;
1301
+ }
1302
+ }
1303
+ }
1304
+ }
1305
+ } @catch (NSException *exception) {
1306
+ // Silently fail - don't crash for cursor lookup
1307
+ NSLog(@"⚠️ Exception in cursorTypeFromSeed: %@", exception.reason);
1308
+ } @catch (...) {
1309
+ NSLog(@"⚠️ Unknown exception in cursorTypeFromSeed");
1269
1310
  }
1270
1311
  }
1271
1312
  switch(seed) {
@@ -1716,8 +1757,8 @@ static NSString* detectSystemCursorType(void) {
1716
1757
  dispatch_sync(dispatch_get_main_queue(), fetchCursorBlock);
1717
1758
  }
1718
1759
 
1719
- if (cursorType && ![cursorType isEqualToString:@"default"] && cursorSeed > 0 && detectedCursor) {
1720
- addCursorToSeedMap(detectedCursor, cursorType, cursorSeed);
1760
+ if (cursorType && ![cursorType isEqualToString:@"default"] && cursorSeed > 0) {
1761
+ addCursorToSeedMap(cursorType, cursorSeed);
1721
1762
  }
1722
1763
 
1723
1764
  return cursorType;