Skip to content

Node-API: async-work complete callback runs without an entered context #441

Description

@edusperoni

Found while porting #437 to Android (NativeScript/android#2004) by an independent review of the port; the defect is shared with the iOS original.

CompleteAsyncWork in NativeScript/napi/NodeApiEmbed.mm calls env->CallIntoModule(...) with no v8::Context::Scope (and no HandleScope of its own) — the event-loop entry it runs in supplies only Locker + Isolate::Scope + HandleScope. Every sibling entry path opens the context scope itself (NapiEnv::CallFinalizer, the TSFN dispatch in NapiThreadSafeFunction.mm), but the async-work completion path does not.

Consequences:

  • Node guarantees the complete callback runs with the env's context entered; addon code that touches the engine directly (or any napi call that reads isolate->GetCurrentContext()) observes an empty current context.
  • If the complete callback throws JS-side (e.g. the documented napi_throw_error failure-reporting pattern), the exception handler runs against an empty current context — on the Android port this was a null-deref/CHECK crash in the error reporter; the iOS reporter may or may not survive it, but the contract violation is the same.

Fix is the same one-liner the Android port applied in review: open v8::HandleScope + v8::Context::Scope(env->context()) in CompleteAsyncWork before CallIntoModule, mirroring NapiEnv::CallFinalizer.

Android-side fix: NativeScript/android#2004 (CompleteAsyncWork in test-app/runtime/src/main/cpp/napi/NodeApiEmbed.cpp).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions