@@ -265,7 +265,6 @@ typedef struct napi_env__ {
265265 JsAtoms atoms ;
266266 ExternalInfo * gcBefore ;
267267 ExternalInfo * gcAfter ;
268- int js_enter_state ;
269268 int64_t usedMemory ;
270269} napi_env__ ;
271270
@@ -296,21 +295,14 @@ typedef struct ExternalBufferInfo {
296295} ExternalBufferInfo ;
297296
298297/**
299- * -------------------------------------
300- * MICROTASK HANDLING
301- * -------------------------------------
298+ * MICROTASK HANDLING
299+ *
300+ * The microtask queue is drained by NapiScope (see quickjs/jsr.h) once the
301+ * native call stack fully unwinds back out of JS — the same scope-depth model
302+ * used by the Hermes and PrimJS engines. qjs_execute_pending_jobs below is the
303+ * pump it calls; there is no longer any per-napi-call js_enter/js_exit here.
302304 */
303305
304- static inline void js_enter (napi_env env ) {
305- env -> js_enter_state ++ ;
306- }
307-
308- static inline void js_exit (napi_env env ) {
309- if (-- env -> js_enter_state <= 0 ) {
310- qjs_execute_pending_jobs (env );
311- }
312- }
313-
314306/**
315307 * --------------------------------------
316308 * NAPI DATA FINALIZERS
@@ -3133,7 +3125,6 @@ napi_status napi_call_function(napi_env env, napi_value thisValue, napi_value fu
31333125 jsThis = JS_GetGlobalObject (env -> context );
31343126 }
31353127
3136- js_enter (env );
31373128 JSValue * args = NULL ;
31383129 JSValue returnValue ;
31393130
@@ -3159,8 +3150,6 @@ napi_status napi_call_function(napi_env env, napi_value thisValue, napi_value fu
31593150 NULL );
31603151 }
31613152
3162- js_exit (env );
3163-
31643153 if (useGlobal ) JS_FreeValue (env -> context , jsThis );
31653154
31663155 if (JS_IsException (returnValue )) {
@@ -3339,7 +3328,6 @@ napi_new_instance(napi_env env, napi_value constructor, size_t argc, const napi_
33393328 CHECK_ARG (constructor )
33403329 CHECK_ARG (result )
33413330
3342- js_enter (env );
33433331 JSValue * args = NULL ;
33443332 JSValue returnValue ;
33453333
@@ -3364,8 +3352,6 @@ napi_new_instance(napi_env env, napi_value constructor, size_t argc, const napi_
33643352 args );
33653353 }
33663354
3367- js_exit (env );
3368-
33693355
33703356 if (JS_IsException (returnValue )) {
33713357 JS_Throw (env -> context , returnValue );
@@ -3412,10 +3398,11 @@ CallConstructor(JSContext *context, JSValueConst newTarget, int argc, JSValueCon
34123398 JSValue returnValue = JS_UNDEFINED ;
34133399
34143400 if (result ) {
3415- returnValue = * ((JSValue * ) result );
3416- JS_DupValue (env -> context , returnValue );
3417- JS_FreeValue (env -> context , thisValue );
3401+ returnValue = JS_DupValue (env -> context , * ((JSValue * ) result ));
34183402 }
3403+ // Always release the trampoline-created `this`; a null result (callback
3404+ // returned undefined or bailed) previously leaked it.
3405+ JS_FreeValue (env -> context , thisValue );
34193406
34203407 assert (LIST_FIRST (& env -> handleScopeList ) == & handleScope &&
34213408 "napi_close_handle_scope() or napi_close_escapable_handle_scope() should follow FILO rule." );
@@ -3517,7 +3504,7 @@ napi_wrap(napi_env env, napi_value jsObject, void *nativeObject, napi_finalize f
35173504
35183505 externalInfo -> data = nativeObject ;
35193506 externalInfo -> finalizeHint = finalize_hint ;
3520- externalInfo -> finalizeCallback = NULL ;
3507+ externalInfo -> finalizeCallback = finalize_cb ;
35213508
35223509 JSValue external = JS_NewObjectClass (env -> context , (int ) env -> runtime -> externalClassId );
35233510
@@ -3751,10 +3738,8 @@ napi_status napi_resolve_deferred(napi_env env, napi_deferred deferred, napi_val
37513738 if (resolution != NULL ) {
37523739 value = * ((JSValue * ) resolution );
37533740 }
3754- js_enter (env );
37553741 JSValue jsResult = JS_Call (env -> context , * ((JSValue * ) deferred -> resolve ), JS_UNDEFINED , 1 ,
37563742 & value );
3757- js_exit (env );
37583743 JS_FreeValue (env -> context , jsResult );
37593744
37603745 return napi_clear_last_error (env );
@@ -3768,10 +3753,8 @@ napi_status napi_reject_deferred(napi_env env, napi_deferred deferred, napi_valu
37683753 if (rejection != NULL ) {
37693754 value = * ((JSValue * ) rejection );
37703755 }
3771- js_enter (env );
37723756 JSValue jsResult = JS_Call (env -> context , * ((JSValue * ) deferred -> reject ), JS_UNDEFINED , 1 ,
37733757 & value );
3774- js_exit (env );
37753758 JS_FreeValue (env -> context , jsResult );
37763759
37773760 return napi_clear_last_error (env );
@@ -4196,8 +4179,6 @@ napi_status qjs_create_napi_env(napi_env *env, napi_runtime runtime) {
41964179
41974180 (* env )-> context = context ;
41984181
4199- (* env )-> js_enter_state = 0 ;
4200-
42014182 JS_SetRuntimeOpaque (runtime -> runtime , * env );
42024183
42034184 // Create runtime atoms
@@ -4389,10 +4370,8 @@ napi_status qjs_execute_script(napi_env env,
43894370
43904371 JSValue eval_result ;
43914372 const char * cScript = JS_ToCString (env -> context , * ((JSValue * ) script ));
4392- js_enter (env );
43934373 eval_result = JS_Eval (env -> context , cScript , strlen (cScript ), file , JS_EVAL_TYPE_GLOBAL );
43944374 JS_FreeCString (env -> context , cScript ) ;
4395- js_exit (env );
43964375 if (JS_IsException (eval_result )) {
43974376 const char * exceptionMessage = JS_ToCString (env -> context , eval_result );
43984377 napi_set_last_error (env , napi_cannot_run_js , exceptionMessage , 0 , NULL );
0 commit comments