支持 await/async
This commit is contained in:
@@ -7,6 +7,10 @@
|
||||
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||
<style>
|
||||
.clear{
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 0;
|
||||
@@ -70,7 +74,7 @@
|
||||
<div class="section">
|
||||
<div class="section-header">控制台日志</div>
|
||||
<div class="section-content">
|
||||
<div class="log">{{- range .Logs }}<p>{{ .Time.Format "2006/01/02 15:04:05" }} - {{ .Level }} : {{ .Message }}</p>{{- end }}</div>
|
||||
<div class="log">{{- range .Logs }}<p class="clear">{{ .Time.Format "2006/01/02 15:04:05" }} - {{ .Level }} : {{ .Message }}</p>{{- end }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -2,15 +2,16 @@ package goja
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/dop251/goja"
|
||||
"github.com/dop251/goja_nodejs/console"
|
||||
"github.com/dop251/goja_nodejs/eventloop"
|
||||
"github.com/dop251/goja_nodejs/require"
|
||||
"github.com/dop251/goja_nodejs/url"
|
||||
"github.com/pkg/errors"
|
||||
"gopkg.d7z.net/gitea-pages/pkg/core"
|
||||
)
|
||||
|
||||
@@ -23,40 +24,56 @@ var FilterInstGoJa core.FilterInstance = func(config core.FilterParams) (core.Fi
|
||||
return nil, err
|
||||
}
|
||||
if param.Exec == "" {
|
||||
return nil, errors.Errorf("no exec specified")
|
||||
return nil, errors.New("no exec specified")
|
||||
}
|
||||
return func(ctx core.FilterContext, w http.ResponseWriter, request *http.Request, next core.NextCall) error {
|
||||
js, err := ctx.ReadString(ctx, param.Exec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
prg, err := goja.Compile("main.js", js, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
debug := NewDebug(param.Debug && request.URL.Query().Get("debug") == "true", request, w)
|
||||
registry := newRegistry(ctx)
|
||||
registry.RegisterNativeModule(console.ModuleName, console.RequireWithPrinter(debug))
|
||||
vm := goja.New()
|
||||
_ = registry.Enable(vm)
|
||||
console.Enable(vm)
|
||||
url.Enable(vm)
|
||||
if err = RequestInject(ctx, vm, request); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = ResponseInject(vm, debug, request); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = KVInject(ctx, vm); err != nil {
|
||||
return err
|
||||
}
|
||||
coreCtx, cancel := context.WithTimeout(ctx, 3*time.Second)
|
||||
defer cancel()
|
||||
loop := eventloop.NewEventLoop(eventloop.WithRegistry(registry), eventloop.EnableConsole(true))
|
||||
stop := make(chan struct{}, 1)
|
||||
shutdown := make(chan struct{}, 1)
|
||||
timeout, cancelFunc := context.WithTimeout(ctx, 3*time.Second)
|
||||
defer cancelFunc()
|
||||
count := 0
|
||||
go func() {
|
||||
defer func() {
|
||||
shutdown <- struct{}{}
|
||||
close(shutdown)
|
||||
}()
|
||||
select {
|
||||
case <-coreCtx.Done():
|
||||
vm.Interrupt(coreCtx.Err())
|
||||
return
|
||||
case <-timeout.Done():
|
||||
case <-stop:
|
||||
}
|
||||
count = loop.Stop()
|
||||
}()
|
||||
_, err = vm.RunScript(param.Exec, js)
|
||||
cancel()
|
||||
loop.Run(func(vm *goja.Runtime) {
|
||||
url.Enable(vm)
|
||||
if err = RequestInject(ctx, vm, request); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err = ResponseInject(vm, debug, request); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err = KVInject(ctx, vm); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
_, err = vm.RunProgram(prg)
|
||||
})
|
||||
stop <- struct{}{}
|
||||
close(stop)
|
||||
<-shutdown
|
||||
if count != 0 {
|
||||
err = errors.Join(context.DeadlineExceeded, err)
|
||||
}
|
||||
return debug.Flush(err)
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ func kvResult(db kv.CursorPagedKV) func(ctx core.FilterContext, jsCtx *goja.Runt
|
||||
}
|
||||
return jsCtx.ToValue(get)
|
||||
},
|
||||
"set": func(key string, value string) {
|
||||
"set": func(key, value string) {
|
||||
err := db.Put(ctx, key, value, kv.TTLKeep)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@@ -52,6 +52,20 @@ func kvResult(db kv.CursorPagedKV) func(ctx core.FilterContext, jsCtx *goja.Runt
|
||||
}
|
||||
return b
|
||||
},
|
||||
"putIfNotExists": func(key, value string) bool {
|
||||
exists, err := db.PutIfNotExists(ctx, key, value, kv.TTLKeep)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return exists
|
||||
},
|
||||
"compareAndSwap": func(key, oldValue, newValue string) bool {
|
||||
swap, err := db.CompareAndSwap(ctx, key, oldValue, newValue)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return swap
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
func ResponseInject(jsCtx *goja.Runtime, writer http.ResponseWriter, req *http.Request) error {
|
||||
return jsCtx.GlobalObject().Set("response", map[string]any{
|
||||
// 响应头操作
|
||||
"setHeader": func(key string, value string) {
|
||||
"setHeader": func(key, value string) {
|
||||
writer.Header().Set(key, value)
|
||||
},
|
||||
|
||||
@@ -97,7 +97,7 @@ func ResponseInject(jsCtx *goja.Runtime, writer http.ResponseWriter, req *http.R
|
||||
},
|
||||
|
||||
// 设置 cookie
|
||||
"setCookie": func(name string, value string, options ...map[string]interface{}) {
|
||||
"setCookie": func(name, value string, options ...map[string]interface{}) {
|
||||
cookie := &http.Cookie{
|
||||
Name: name,
|
||||
Value: value,
|
||||
|
||||
Reference in New Issue
Block a user