11package goja
22
33import (
4- "context "
4+ "encoding/json "
55 "errors"
6+ "fmt"
67 "io"
78 "net/http"
89 "path/filepath"
@@ -14,6 +15,7 @@ import (
1415 "github.com/dop251/goja_nodejs/eventloop"
1516 "github.com/dop251/goja_nodejs/require"
1617 "github.com/dop251/goja_nodejs/url"
18+ "go.uber.org/zap"
1719 "gopkg.d7z.net/gitea-pages/pkg/core"
1820)
1921
@@ -47,75 +49,102 @@ func FilterInstGoJa(gl core.Params) (core.FilterInstance, error) {
4749 if err != nil {
4850 return err
4951 }
50- prg , err := goja .Compile ("main.js" , js , false )
52+
53+ debug := NewDebug (global .EnableDebug && param .Debug && request .URL .Query ().
54+ Get ("debug" ) == "true" , request , w )
55+ program , err := goja .Compile ("main.js" , js , false )
5156 if err != nil {
52- return err
57+ return debug . Flush ( err )
5358 }
54- debug := NewDebug (global .EnableDebug && param .Debug && request .URL .Query ().Get ("debug" ) == "true" , request , w )
55- registry := newRegistry (ctx )
56- registry .RegisterNativeModule (console .ModuleName , console .RequireWithPrinter (debug ))
57- loop := eventloop .NewEventLoop (eventloop .WithRegistry (registry ), eventloop .EnableConsole (true ))
58- stop := make (chan struct {}, 1 )
59- shutdown := make (chan struct {}, 1 )
60- defer close (shutdown )
61- timeout , timeoutCancelFunc := context .WithTimeout (ctx , global .Timeout )
62- defer timeoutCancelFunc ()
63- count := 0
59+ registry := newRegistry (ctx , debug )
60+ jsLoop := eventloop .NewEventLoop (eventloop .WithRegistry (registry ),
61+ eventloop .EnableConsole (true ))
62+
63+ jsLoop .Start ()
64+ defer jsLoop .Stop ()
65+
6466 closers := NewClosers ()
6567 defer closers .Close ()
66- go func () {
67- defer func () {
68- shutdown <- struct {}{}
68+
69+ stop := make (chan error , 1 )
70+ defer close (stop )
71+
72+ jsLoop .RunOnLoop (func (vm * goja.Runtime ) {
73+ err := func () error {
74+ url .Enable (vm )
75+ if err = RequestInject (ctx , vm , request ); err != nil {
76+ return err
77+ }
78+ if err = ResponseInject (vm , debug , request ); err != nil {
79+ return err
80+ }
81+ if err = KVInject (ctx , vm ); err != nil {
82+ return err
83+ }
84+ if err = EventInject (ctx , vm , jsLoop ); err != nil {
85+ return err
86+ }
87+ if global .EnableWebsocket {
88+ var closer io.Closer
89+ closer , err = WebsocketInject (ctx , vm , debug , request , jsLoop )
90+ if err != nil {
91+ return err
92+ }
93+ closers .AddCloser (closer .Close )
94+ }
95+ return nil
6996 }()
70- select {
71- case <- timeout .Done ():
72- case <- stop :
73- }
74- count = loop .Stop ()
75- }()
76- loop .Run (func (vm * goja.Runtime ) {
77- url .Enable (vm )
78- if err = RequestInject (ctx , vm , request ); err != nil {
79- panic (err )
97+ if err != nil {
98+ stop <- errors .Join (err , errors .New ("js init failed" ))
99+ return
80100 }
81- if err = ResponseInject (vm , debug , request ); err != nil {
82- panic (err )
101+ result , err := vm .RunProgram (program )
102+ if err != nil {
103+ stop <- err
104+ return
83105 }
84- if err = KVInject (ctx , vm ); err != nil {
85- panic (err )
86- }
87- if err = EventInject (ctx , vm ); err != nil {
88- panic (err )
89- }
90- if global .EnableWebsocket {
91- var closer io.Closer
92- closer , err = WebsocketInject (ctx , vm , debug , request , loop , timeoutCancelFunc )
93- if err != nil {
94- panic (err )
106+ export := result .Export ()
107+ if export != nil {
108+ if promise , ok := export .(* goja.Promise ); ok {
109+ go func () {
110+ for {
111+ switch promise .State () {
112+ case goja .PromiseStateFulfilled , goja .PromiseStateRejected :
113+ result := promise .Result ().Export ()
114+ switch data := result .(type ) {
115+ case error :
116+ stop <- data
117+ default :
118+ marshal , _ := json .Marshal (result )
119+ zap .L ().Debug (fmt .Sprintf ("js promise result %s" , string (marshal )),
120+ zap .Any ("result" , promise .Result ().ExportType ()))
121+ stop <- nil
122+ }
123+ return
124+ default :
125+ time .Sleep (time .Millisecond * 5 )
126+ }
127+ }
128+ }()
95129 }
96- closers .AddCloser (closer .Close )
97130 }
98- _ , err = vm .RunProgram (prg )
99131 })
100- stop <- struct {}{}
101- close (stop )
102- <- shutdown
103- if count != 0 {
104- err = errors .Join (context .DeadlineExceeded , err )
105- }
106- return debug .Flush (err )
132+ resultErr := <- stop
133+ return debug .Flush (resultErr )
107134 }, nil
108135 }, nil
109136}
110137
111- func newRegistry (ctx core.FilterContext ) * require.Registry {
138+ func newRegistry (ctx core.FilterContext , printer console. Printer ) * require.Registry {
112139 registry := require .NewRegistry (
113140 require .WithLoader (func (path string ) ([]byte , error ) {
114141 return ctx .PageVFS .Read (ctx , path )
115142 }),
116143 require .WithPathResolver (func (base , path string ) string {
117144 return filepath .Join (base , filepath .FromSlash (path ))
118145 }))
146+ registry .RegisterNativeModule (console .ModuleName , console .RequireWithPrinter (printer ))
147+
119148 return registry
120149}
121150
0 commit comments