react-native-nitro-cookies 1.0.3 → 1.0.4

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.
@@ -187,6 +187,45 @@ public class HybridNitroCookies: HybridNitroCookiesSpec {
187
187
  return url
188
188
  }
189
189
 
190
+ // MARK: - WebKit Main-Thread Helpers
191
+
192
+ /**
193
+ * Run a WKHTTPCookieStore operation on the main thread and return a result.
194
+ *
195
+ * All WKHTTPCookieStore interactions must happen on the main thread to avoid
196
+ * EXC_BREAKPOINT crashes in WebKit's non-thread-safe internal data structures.
197
+ */
198
+ @available(iOS 11.0, *)
199
+ private func withWebKitStore<T>(
200
+ _ operation: @escaping (WKHTTPCookieStore, @escaping (T) -> Void) -> Void
201
+ ) async -> T {
202
+ await withCheckedContinuation { continuation in
203
+ DispatchQueue.main.async {
204
+ let store = WKWebsiteDataStore.default().httpCookieStore
205
+ operation(store) { result in
206
+ continuation.resume(returning: result)
207
+ }
208
+ }
209
+ }
210
+ }
211
+
212
+ /**
213
+ * Run a void WKHTTPCookieStore operation on the main thread.
214
+ */
215
+ @available(iOS 11.0, *)
216
+ private func withWebKitStoreVoid(
217
+ _ operation: @escaping (WKHTTPCookieStore, @escaping () -> Void) -> Void
218
+ ) async {
219
+ await withCheckedContinuation { (continuation: CheckedContinuation<Void, Never>) in
220
+ DispatchQueue.main.async {
221
+ let store = WKWebsiteDataStore.default().httpCookieStore
222
+ operation(store) {
223
+ continuation.resume(returning: ())
224
+ }
225
+ }
226
+ }
227
+ }
228
+
190
229
  // MARK: - Synchronous Cookie Operations
191
230
 
192
231
  /**
@@ -267,18 +306,8 @@ public class HybridNitroCookies: HybridNitroCookiesSpec {
267
306
  if useWebKit == true {
268
307
  // Use WKHTTPCookieStore
269
308
  if #available(iOS 11.0, *) {
270
- // Accessing WKWebsiteDataStore.default() inside MainActor.run is necessary for iOS 11-12 compatibility,
271
- // since it is not marked @MainActor in those versions.
272
- // For iOS 13+, WKWebsiteDataStore.default() is already @MainActor, so wrapping in MainActor.run is redundant.
273
- // This workaround is safe for iOS 13+ and does not introduce any performance penalty or behavioral change,
274
- // as MainActor.run is a no-op when already on the main actor. This ensures compatibility across all supported iOS versions.
275
- let store = await MainActor.run {
276
- WKWebsiteDataStore.default().httpCookieStore
277
- }
278
- await withCheckedContinuation { continuation in
279
- store.setCookie(httpCookie) {
280
- continuation.resume(returning: ())
281
- }
309
+ await self.withWebKitStoreVoid { store, done in
310
+ store.setCookie(httpCookie) { done() }
282
311
  }
283
312
  return true
284
313
  } else {
@@ -303,13 +332,8 @@ public class HybridNitroCookies: HybridNitroCookiesSpec {
303
332
 
304
333
  if useWebKit == true {
305
334
  if #available(iOS 11.0, *) {
306
- let store = await MainActor.run {
307
- WKWebsiteDataStore.default().httpCookieStore
308
- }
309
- let httpCookies = await withCheckedContinuation { continuation in
310
- store.getAllCookies { cookies in
311
- continuation.resume(returning: cookies)
312
- }
335
+ let httpCookies: [HTTPCookie] = await self.withWebKitStore { store, done in
336
+ store.getAllCookies { cookies in done(cookies) }
313
337
  }
314
338
  let filteredCookies = httpCookies.filter { cookie in
315
339
  self.isMatchingDomain(cookieDomain: cookie.domain,
@@ -339,20 +363,16 @@ public class HybridNitroCookies: HybridNitroCookiesSpec {
339
363
  return Promise.async {
340
364
  if useWebKit == true {
341
365
  if #available(iOS 11.0, *) {
342
- let store = await MainActor.run {
343
- WKWebsiteDataStore.default().httpCookieStore
366
+ let cookies: [HTTPCookie] = await self.withWebKitStore { store, done in
367
+ store.getAllCookies { cookies in done(cookies) }
344
368
  }
345
- let cookies = await withCheckedContinuation { continuation in
346
- store.getAllCookies { cookies in
347
- continuation.resume(returning: cookies)
348
- }
349
- }
350
- for cookie in cookies {
351
- await withCheckedContinuation { continuation in
352
- store.delete(cookie) {
353
- continuation.resume(returning: ())
354
- }
369
+ await self.withWebKitStoreVoid { store, done in
370
+ let group = DispatchGroup()
371
+ for cookie in cookies {
372
+ group.enter()
373
+ store.delete(cookie) { group.leave() }
355
374
  }
375
+ group.notify(queue: .main) { done() }
356
376
  }
357
377
  return true
358
378
  } else {
@@ -416,13 +436,8 @@ public class HybridNitroCookies: HybridNitroCookiesSpec {
416
436
  return Promise.async {
417
437
  if useWebKit == true {
418
438
  if #available(iOS 11.0, *) {
419
- let store = await MainActor.run {
420
- WKWebsiteDataStore.default().httpCookieStore
421
- }
422
- let cookies = await withCheckedContinuation { continuation in
423
- store.getAllCookies { cookies in
424
- continuation.resume(returning: cookies)
425
- }
439
+ let cookies: [HTTPCookie] = await self.withWebKitStore { store, done in
440
+ store.getAllCookies { cookies in done(cookies) }
426
441
  }
427
442
  return cookies.map { self.createCookieData(from: $0) }
428
443
  } else {
@@ -446,13 +461,8 @@ public class HybridNitroCookies: HybridNitroCookiesSpec {
446
461
 
447
462
  if useWebKit == true {
448
463
  if #available(iOS 11.0, *) {
449
- let store = await MainActor.run {
450
- WKWebsiteDataStore.default().httpCookieStore
451
- }
452
- let cookies = await withCheckedContinuation { continuation in
453
- store.getAllCookies { cookies in
454
- continuation.resume(returning: cookies)
455
- }
464
+ let cookies: [HTTPCookie] = await self.withWebKitStore { store, done in
465
+ store.getAllCookies { cookies in done(cookies) }
456
466
  }
457
467
  let matchingCookie = cookies.first { cookie in
458
468
  cookie.name == name &&
@@ -461,10 +471,8 @@ public class HybridNitroCookies: HybridNitroCookiesSpec {
461
471
  }
462
472
 
463
473
  if let cookie = matchingCookie {
464
- await withCheckedContinuation { continuation in
465
- store.delete(cookie) {
466
- continuation.resume(returning: ())
467
- }
474
+ await self.withWebKitStoreVoid { store, done in
475
+ store.delete(cookie) { done() }
468
476
  }
469
477
  return true
470
478
  } else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-nitro-cookies",
3
- "version": "1.0.3",
3
+ "version": "1.0.4",
4
4
  "description": "Fetch, Get Cookies 🍪 at the Speed of Nitro",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",