@@ -54,7 +54,14 @@ static void ngx_engine_njs_destroy(ngx_engine_t *e, ngx_js_ctx_t *ctx,
5454 ngx_js_loc_conf_t * conf );
5555static ngx_int_t ngx_js_init_preload_vm (njs_vm_t * vm , ngx_js_loc_conf_t * conf );
5656
57+ static ngx_int_t ngx_njs_execute_pending_jobs (njs_vm_t * vm , ngx_log_t * log );
58+ static njs_int_t ngx_njs_await (njs_vm_t * vm , ngx_log_t * log ,
59+ njs_value_t * value );
60+
5761#if (NJS_HAVE_QUICKJS )
62+ static ngx_int_t ngx_qjs_execute_pending_jobs (JSContext * cx , ngx_log_t * log );
63+ static ngx_int_t ngx_qjs_await (JSContext * cx , ngx_log_t * log ,
64+ JSValueConst * value );
5865static ngx_int_t ngx_engine_qjs_init (ngx_engine_t * engine ,
5966 ngx_engine_opts_t * opts );
6067static ngx_int_t ngx_engine_qjs_compile (ngx_js_loc_conf_t * conf , ngx_log_t * log ,
@@ -657,10 +664,61 @@ ngx_engine_njs_compile(ngx_js_loc_conf_t *conf, ngx_log_t *log, u_char *start,
657664}
658665
659666
667+ static ngx_int_t
668+ ngx_njs_execute_pending_jobs (njs_vm_t * vm , ngx_log_t * log )
669+ {
670+ njs_int_t ret ;
671+ njs_str_t exception ;
672+
673+ for ( ;; ) {
674+ ret = njs_vm_execute_pending_job (vm );
675+ if (ret <= NJS_OK ) {
676+ if (ret == NJS_ERROR ) {
677+ njs_vm_exception_string (vm , & exception );
678+ ngx_log_error (NGX_LOG_ERR , log , 0 , "js job exception: %V" ,
679+ & exception );
680+ return NGX_ERROR ;
681+ }
682+
683+ break ;
684+ }
685+ }
686+
687+ return NGX_OK ;
688+ }
689+
690+
691+ static njs_int_t
692+ ngx_njs_await (njs_vm_t * vm , ngx_log_t * log , njs_value_t * value )
693+ {
694+ ngx_int_t ret ;
695+ njs_promise_type_t state ;
696+
697+ ret = ngx_njs_execute_pending_jobs (vm , log );
698+ if (ret != NGX_OK ) {
699+ return NGX_ERROR ;
700+ }
701+
702+ if (njs_value_is_promise (value )) {
703+ state = njs_promise_state (value );
704+
705+ if (state == NJS_PROMISE_FULFILL ) {
706+ njs_value_assign (value , njs_promise_result (value ));
707+
708+ } else if (state == NJS_PROMISE_REJECTED ) {
709+ njs_vm_throw (vm , njs_promise_result (value ));
710+ }
711+ }
712+
713+ return NGX_OK ;
714+ }
715+
716+
660717ngx_engine_t *
661718ngx_njs_clone (ngx_js_ctx_t * ctx , ngx_js_loc_conf_t * cf , void * external )
662719{
663720 njs_vm_t * vm ;
721+ njs_int_t ret ;
664722 ngx_engine_t * engine ;
665723 njs_opaque_value_t retval ;
666724
@@ -671,8 +729,7 @@ ngx_njs_clone(ngx_js_ctx_t *ctx, ngx_js_loc_conf_t *cf, void *external)
671729
672730 engine = njs_mp_alloc (njs_vm_memory_pool (vm ), sizeof (ngx_engine_t ));
673731 if (engine == NULL ) {
674- njs_vm_destroy (vm );
675- return NULL ;
732+ goto destroy ;
676733 }
677734
678735 memcpy (engine , cf -> engine , sizeof (ngx_engine_t ));
@@ -681,13 +738,21 @@ ngx_njs_clone(ngx_js_ctx_t *ctx, ngx_js_loc_conf_t *cf, void *external)
681738
682739 if (njs_vm_start (vm , njs_value_arg (& retval )) == NJS_ERROR ) {
683740 ngx_js_log_exception (vm , ctx -> log , "exception" );
741+ goto destroy ;
742+ }
684743
685- njs_vm_destroy ( vm );
686-
687- return NULL ;
744+ ret = ngx_njs_await ( vm , ctx -> log , njs_value_arg ( & retval ) );
745+ if ( ret == NGX_ERROR ) {
746+ goto destroy ;
688747 }
689748
690749 return engine ;
750+
751+ destroy :
752+
753+ njs_vm_destroy (vm );
754+
755+ return NULL ;
691756}
692757
693758
@@ -720,17 +785,9 @@ ngx_engine_njs_call(ngx_js_ctx_t *ctx, ngx_str_t *fname,
720785 return NGX_ERROR ;
721786 }
722787
723- for ( ;; ) {
724- ret = njs_vm_execute_pending_job (vm );
725- if (ret <= NJS_OK ) {
726- if (ret == NJS_ERROR ) {
727- ngx_js_log_exception (vm , ctx -> log , "exception" );
728-
729- return NGX_ERROR ;
730- }
731-
732- break ;
733- }
788+ ret = ngx_njs_await (vm , ctx -> log , njs_value_arg (& ctx -> retval ));
789+ if (ret == NGX_ERROR ) {
790+ return NGX_ERROR ;
734791 }
735792
736793 return njs_rbtree_is_empty (& ctx -> waiting_events ) ? NGX_OK : NGX_AGAIN ;
@@ -807,6 +864,66 @@ ngx_engine_njs_destroy(ngx_engine_t *e, ngx_js_ctx_t *ctx,
807864
808865#if (NJS_HAVE_QUICKJS )
809866
867+ static ngx_int_t
868+ ngx_qjs_execute_pending_jobs (JSContext * cx , ngx_log_t * log )
869+ {
870+ int rc ;
871+ JSValue value ;
872+ JSContext * cx1 ;
873+ const char * exception ;
874+
875+ for ( ;; ) {
876+ rc = JS_ExecutePendingJob (JS_GetRuntime (cx ), & cx1 );
877+ if (rc <= 0 ) {
878+ if (rc == 0 ) {
879+ break ;
880+ }
881+
882+ value = JS_GetException (cx );
883+ exception = JS_ToCString (cx , value );
884+ JS_FreeValue (cx , value );
885+
886+ ngx_log_error (NGX_LOG_ERR , log , 0 , "js job exception: %s" ,
887+ exception );
888+
889+ JS_FreeCString (cx , exception );
890+
891+ return NGX_ERROR ;
892+ }
893+ }
894+
895+ return NGX_OK ;
896+ }
897+
898+
899+ static ngx_int_t
900+ ngx_qjs_await (JSContext * cx , ngx_log_t * log , JSValue * value )
901+ {
902+ JSValue ret ;
903+ ngx_int_t rc ;
904+ JSPromiseStateEnum state ;
905+
906+ rc = ngx_qjs_execute_pending_jobs (cx , log );
907+ if (rc != NGX_OK ) {
908+ return NGX_ERROR ;
909+ }
910+
911+ state = JS_PromiseState (cx , * value );
912+ if (state == JS_PROMISE_FULFILLED ) {
913+ ret = JS_PromiseResult (cx , * value );
914+ JS_FreeValue (cx , * value );
915+ * value = ret ;
916+
917+ } else if (state == JS_PROMISE_REJECTED ) {
918+ ret = JS_Throw (cx , JS_PromiseResult (cx , * value ));
919+ JS_FreeValue (cx , * value );
920+ * value = ret ;
921+ }
922+
923+ return NGX_OK ;
924+ }
925+
926+
810927static ngx_int_t
811928ngx_engine_qjs_init (ngx_engine_t * engine , ngx_engine_opts_t * opts )
812929{
@@ -871,48 +988,13 @@ ngx_engine_qjs_compile(ngx_js_loc_conf_t *conf, ngx_log_t *log, u_char *start,
871988}
872989
873990
874- static JSValue
875- js_std_await (JSContext * ctx , JSValue obj )
876- {
877- int state , err ;
878- JSValue ret ;
879- JSContext * ctx1 ;
880-
881- for (;;) {
882- state = JS_PromiseState (ctx , obj );
883- if (state == JS_PROMISE_FULFILLED ) {
884- ret = JS_PromiseResult (ctx , obj );
885- JS_FreeValue (ctx , obj );
886- break ;
887-
888- } else if (state == JS_PROMISE_REJECTED ) {
889- ret = JS_Throw (ctx , JS_PromiseResult (ctx , obj ));
890- JS_FreeValue (ctx , obj );
891- break ;
892-
893- } else if (state == JS_PROMISE_PENDING ) {
894- err = JS_ExecutePendingJob (JS_GetRuntime (ctx ), & ctx1 );
895- if (err < 0 ) {
896- /* js_std_dump_error(ctx1); */
897- }
898-
899- } else {
900- /* not a promise */
901- ret = obj ;
902- break ;
903- }
904- }
905-
906- return ret ;
907- }
908-
909-
910991ngx_engine_t *
911992ngx_qjs_clone (ngx_js_ctx_t * ctx , ngx_js_loc_conf_t * cf , void * external )
912993{
913994 JSValue rv ;
914995 njs_mp_t * mp ;
915996 uint32_t i , length ;
997+ ngx_int_t rc ;
916998 JSRuntime * rt ;
917999 JSContext * cx ;
9181000 ngx_engine_t * engine ;
@@ -990,14 +1072,13 @@ ngx_qjs_clone(ngx_js_ctx_t *ctx, ngx_js_loc_conf_t *cf, void *external)
9901072 goto destroy ;
9911073 }
9921074
993- rv = js_std_await (cx , rv );
994- if (JS_IsException (rv )) {
995- ngx_qjs_log_exception (engine , ctx -> log , "eval exception" );
1075+ rc = ngx_qjs_await (cx , ctx -> log , & rv );
1076+ JS_FreeValue (cx , rv );
1077+ if (rc == NGX_ERROR ) {
1078+ ngx_qjs_log_exception (engine , ctx -> log , "await exception" );
9961079 goto destroy ;
9971080 }
9981081
999- JS_FreeValue (cx , rv );
1000-
10011082 return engine ;
10021083
10031084destroy :
@@ -1014,10 +1095,9 @@ static ngx_int_t
10141095ngx_engine_qjs_call (ngx_js_ctx_t * ctx , ngx_str_t * fname ,
10151096 njs_opaque_value_t * args , njs_uint_t nargs )
10161097{
1017- int rc ;
10181098 JSValue fn , val ;
1019- JSRuntime * rt ;
1020- JSContext * cx , * cx1 ;
1099+ ngx_int_t rc ;
1100+ JSContext * cx ;
10211101
10221102 cx = ctx -> engine -> u .qjs .ctx ;
10231103
@@ -1041,19 +1121,10 @@ ngx_engine_qjs_call(ngx_js_ctx_t *ctx, ngx_str_t *fname,
10411121 JS_FreeValue (cx , ngx_qjs_arg (ctx -> retval ));
10421122 ngx_qjs_arg (ctx -> retval ) = val ;
10431123
1044- rt = JS_GetRuntime (cx );
1045-
1046- for ( ;; ) {
1047- rc = JS_ExecutePendingJob (rt , & cx1 );
1048- if (rc <= 0 ) {
1049- if (rc == -1 ) {
1050- ngx_qjs_log_exception (ctx -> engine , ctx -> log , "job exception" );
1051-
1052- return NGX_ERROR ;
1053- }
1054-
1055- break ;
1056- }
1124+ rc = ngx_qjs_await (cx , ctx -> log , & ngx_qjs_arg (ctx -> retval ));
1125+ if (rc == NGX_ERROR ) {
1126+ ngx_qjs_log_exception (ctx -> engine , ctx -> log , "await exception" );
1127+ return NGX_ERROR ;
10571128 }
10581129
10591130 return njs_rbtree_is_empty (& ctx -> waiting_events ) ? NGX_OK : NGX_AGAIN ;
@@ -1365,10 +1436,8 @@ ngx_qjs_dump_obj(ngx_engine_t *e, JSValueConst val, ngx_str_t *dst)
13651436ngx_int_t
13661437ngx_qjs_call (JSContext * cx , JSValue fn , JSValue * argv , int argc )
13671438{
1368- int rc ;
13691439 JSValue ret ;
1370- JSRuntime * rt ;
1371- JSContext * cx1 ;
1440+ ngx_int_t rc ;
13721441 ngx_js_ctx_t * ctx ;
13731442
13741443 ctx = ngx_qjs_external_ctx (cx , JS_GetContextOpaque (cx ));
@@ -1382,19 +1451,9 @@ ngx_qjs_call(JSContext *cx, JSValue fn, JSValue *argv, int argc)
13821451
13831452 JS_FreeValue (cx , ret );
13841453
1385- rt = JS_GetRuntime (cx );
1386-
1387- for ( ;; ) {
1388- rc = JS_ExecutePendingJob (rt , & cx1 );
1389- if (rc <= 0 ) {
1390- if (rc == -1 ) {
1391- ngx_qjs_log_exception (ctx -> engine , ctx -> log , "job exception" );
1392-
1393- return NGX_ERROR ;
1394- }
1395-
1396- break ;
1397- }
1454+ rc = ngx_qjs_execute_pending_jobs (cx , ctx -> log );
1455+ if (rc != NGX_OK ) {
1456+ return NGX_ERROR ;
13981457 }
13991458
14001459 return NGX_OK ;
@@ -2202,6 +2261,7 @@ ngx_js_call(njs_vm_t *vm, njs_function_t *func, njs_opaque_value_t *args,
22022261 njs_uint_t nargs )
22032262{
22042263 njs_int_t ret ;
2264+ ngx_js_ctx_t * ctx ;
22052265 ngx_connection_t * c ;
22062266
22072267 ret = njs_vm_call (vm , func , njs_value_arg (args ), nargs );
@@ -2214,19 +2274,11 @@ ngx_js_call(njs_vm_t *vm, njs_function_t *func, njs_opaque_value_t *args,
22142274 return NGX_ERROR ;
22152275 }
22162276
2217- for ( ;; ) {
2218- ret = njs_vm_execute_pending_job (vm );
2219- if (ret <= NJS_OK ) {
2220- c = ngx_external_connection (vm , njs_vm_external_ptr (vm ));
2221-
2222- if (ret == NJS_ERROR ) {
2223- ngx_js_log_exception (vm , c -> log , "job exception" );
2224-
2225- return NGX_ERROR ;
2226- }
2277+ ctx = ngx_external_ctx (vm , njs_vm_external_ptr (vm ));
22272278
2228- break ;
2229- }
2279+ ret = ngx_njs_execute_pending_jobs (vm , ctx -> log );
2280+ if (ret != NGX_OK ) {
2281+ return NGX_ERROR ;
22302282 }
22312283
22322284 return NGX_OK ;
0 commit comments