napi backend: JSMethodCallback runs napi calls on the invoking thread — JS IMPs crash when ObjC calls them on foreign threads
Mantenedores costumam responder em até 1 dia
Ninguém assumiu esta issue ainda.
Avaliação
- Dificuldade
- 4/5
- Tempo estimado
- 3-5 dias
- Facilidade para iniciantes
- 18/100
- Tipo de issue
- Bug
- Clareza
- Razoavelmente clara
- Status de atividade
- Ativa
- Stack de tecnologia
- c, cpp, macos, nodejs, objective-c
- Domínio
- backend
Direção de pesquisa
Start in NativeScript/ffi/napi/Closure.mm and compare JSMethodCallback with JSBlockCallback, which already checks closure->jsThreadId and marshals foreign-thread calls onto the JS run loop or threadsafe function. The repro needs a macOS arm64 build with -DNS_FFI_BACKEND=napi, so the first check is whether the spawned-thread ping call crashes in ObjCBridgeState::getObject. Done means that call either blocks until the JS thread returns 42 or fails with a clear error, without a SIGSEGV.
Escrita pelo modelo de indexação a partir do texto da issue.
Descrição
Summary
JSMethodCallback (NativeScript/ffi/napi/Closure.mm) performs napi calls — ObjCBridgeState::getObject, napi_get_named_property, napi_call_function — directly on whatever thread invoked the ffi closure, with no thread check. When a JS-backed ObjC method IMP is invoked on a non-JS thread, the bridge calls into the JS engine off-thread and crashes.
JSBlockCallback in the same file does check the calling thread (currentThreadId == closure->jsThreadId) and marshals foreign-thread invocations onto the JS side (napi_call_threadsafe_function for generic-napi builds; CFRunLoopPerformBlock(jsRunLoop, kCFRunLoopCommonModes) for embedded-runtime builds). Method IMPs get no equivalent handling. JSFunctionCallback (C-function-pointer callbacks) has the same unguarded shape.
Concrete hit in the wild: NSPrintOperation with canSpawnSeparateThread=YES invokes the operation's didRunSelector on the spawned print thread — a JS didRun IMP there crashes inside ObjCBridgeState::getObject → tryResolveBridgedClassConstructor (SIGSEGV).
Reproduction
macOS arm64, NativeScript.framework built at 5b697b39 with -DTARGET_ENGINE=none -DNS_FFI_BACKEND=napi (code identical on main), env owned by the main thread:
var Delegate = NSObject.extend(
{ ping: function () { return 42; } },
{ exposedMethods: { ping: { returns: interop.types.int32 } } }
);
var obj = Delegate.new();
obj.respondsToSelector(NSSelectorFromString("ping")); // true
NSThread.detachNewThreadSelectorToTargetWithObject(NSSelectorFromString("ping"), obj, null);
→ EXC_BAD_ACCESS (SIGSEGV) on the spawned thread:
nativescript::ObjCBridgeState::tryResolveBridgedClassConstructor(napi_env*, napi_value*, objc_class**)
nativescript::ObjCBridgeState::getObject(napi_env*, objc_object*, napi_value*, ObjectOwnership)
nativescript::JSMethodCallback(ffi_cif*, void*, void**, void*)
ffi_closure_SYSV_inner
__NSThread__start__
_pthread_start
Expected
Foreign-thread IMP/closure invocations should be marshalled to the JS thread the way JSBlockCallback already does — the caller blocks until the return value is produced, which suits synchronous IMPs — or fail deterministically with a clear error rather than corrupting engine state. As it stands, delegate methods that Apple legitimately invokes off the main thread (spawned NSPrintOperation threads, some AVFoundation/UN delegate calls on background queues) cannot be implemented in JS at all, and a missed-thread dispatch takes down the whole process.
Environment
NativeScript/runtimesmain(verified identical at5b697b39)- Generic napi backend,
TARGET_PLATFORM=macos, arm64; the sameffi/napicode path ships in the iOS napi runtime.
- Linguagem predominante
- C++
- Estrelas
- 27
- Forks
- 5
- Merge médio
- 5d 11h
- PRs com merge (30d)
- 12
Preparar o ambiente
- Sem Dockerfile nem arquivo Docker Compose
- Sem modelo de pull request
- Ler o guia de contribuição
Primeiros passos
- Leia a issue inteira e depois o guia de contribuição do projeto.
- Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
- Faça um fork do repositório e trabalhe em uma branch.
- Abra um pull request que referencie o número da issue.
Mais de NativeScript/runtimes
-
Dificuldade 4/5 3-5 dias Facilidade para iniciantes 30/100
NativeScript/runtimes#111 ·
Mantenedores costumam responder em até 1 dia
-
Dificuldade 5/5 Mais de uma semana Facilidade para iniciantes 22/100
NativeScript/runtimes#110 ·
Mantenedores costumam responder em até 1 dia
-
Dificuldade 4/5 3-5 dias Facilidade para iniciantes 32/100
NativeScript/runtimes#109 ·
Mantenedores costumam responder em até 1 dia
-
Dificuldade 3/5 1-2 dias Facilidade para iniciantes 40/100
NativeScript/runtimes#107 ·
Mantenedores costumam responder em até 1 dia
-
Dificuldade 3/5 1-2 dias Facilidade para iniciantes 42/100
NativeScript/runtimes#106 ·
Mantenedores costumam responder em até 1 dia
Todas as issues de NativeScript/runtimes
Issues semelhantes
-
Bug Testing
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 78/100
SCIInstitute/SCIRun#2931 ·
Mantenedores costumam responder em até 1 dia
-
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 76/100
Mantenedores costumam responder em até 5 dias
-
Docs: CREATE GRAPH page says `USE my_graph`, but the working statement is `USE GRAPH my_graph`Aberta
Dificuldade 1/5 1-3 horas Facilidade para iniciantes 85/100
Mantenedores costumam responder em até 1 dia
-
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 72/100
godotengine/godot#125272 ·
Mantenedores costumam responder em até 1 dia
-
bug impact: performance priority: med review: 2026-11 severity: med
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 78/100
mgradwohl/ModernLife#67 ·