ns-ios-corespotlight
CoreSpotlight without deadlocking V8
CoreSpotlight works great from NativeScript — but the obvious way to call it contains a guaranteed, permanent, main-thread deadlock that ships silently: the app launches fine, then freezes forever ~1–2 s after the data feed loads (typically noticed as "scrolling freezes the app on first install, and it's frozen right after relaunch too").
1. The deadlock: JS arrays are live adapters, not copies
When you pass a JS array where native expects NSArray, the runtime does not copy it. It wraps it in an ArrayAdapter — an NSArray facade backed by the live V8 array. Every count/objectAtIndex: on that adapter re-enters V8 and needs the isolate lock on whatever thread makes the call.
CoreSpotlight's indexSearchableItems: standardizes the items array with dispatch_apply — parallel enumeration across worker threads. Combine the two and you get a three-way deadlock:
- The thread calling
indexSearchableItemsholds the V8 lock for the duration of the synchronous native call, and inside CoreSpotlight blocks waiting for itsdispatch_applyworkers. - Each worker calls
-[ArrayAdapter count]→v8::Locker::Initialize→ waits forever on the lock held by thread 1. - The main thread blocks on the same lock at its next JS callback (the display link fires every frame, so this is instant) → UI frozen, never recovers, eventually a watchdog kill.
Signature in a hang report / sample output — one thread in ArrayAdapter/native enumeration waiting on workers; workers and main thread all parked here: