- Introduced a new test context creation function to streamline test setup for assistant operations. - Refactored context structure to replace the deprecated 'Data' field with 'Metadata', improving clarity and consistency. - Updated various methods to utilize the new 'Metadata' field, ensuring proper handling of request metadata across the system. - Adjusted tests to reflect changes in metadata handling, enhancing validation of context fields in JavaScript integration.
116 lines
3.1 KiB
Go
116 lines
3.1 KiB
Go
package context
|
|
|
|
import (
|
|
"sync"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/yaoapp/gou/runtime/v8/bridge"
|
|
"rogchap.com/v8go"
|
|
)
|
|
|
|
var objectsMutex = sync.Mutex{}
|
|
var objects = map[string]*Context{}
|
|
|
|
// JsValue return the JavaScript value of the context
|
|
func (ctx *Context) JsValue(v8ctx *v8go.Context) (*v8go.Value, error) {
|
|
return ctx.NewObject(v8ctx)
|
|
}
|
|
|
|
// NewObject Create a new JavaScript object from the context
|
|
func (ctx *Context) NewObject(v8ctx *v8go.Context) (*v8go.Value, error) {
|
|
|
|
jsObject := v8go.NewObjectTemplate(v8ctx.Isolate())
|
|
|
|
// Set the id and release function
|
|
id := ctx.objectRegister()
|
|
jsObject.Set("__id", id)
|
|
jsObject.Set("__release", ctx.objectRelease(v8ctx.Isolate(), id))
|
|
|
|
// Set primitive fields in template
|
|
jsObject.Set("chat_id", ctx.ChatID)
|
|
jsObject.Set("assistant_id", ctx.AssistantID)
|
|
jsObject.Set("connector", ctx.Connector)
|
|
if ctx.Search != nil {
|
|
jsObject.Set("search", *ctx.Search)
|
|
}
|
|
|
|
jsObject.Set("retry", ctx.Retry)
|
|
jsObject.Set("retry_times", uint32(ctx.RetryTimes))
|
|
jsObject.Set("locale", ctx.Locale)
|
|
jsObject.Set("theme", ctx.Theme)
|
|
jsObject.Set("referer", ctx.Referer)
|
|
jsObject.Set("accept", string(ctx.Accept))
|
|
jsObject.Set("route", ctx.Route)
|
|
|
|
// Create instance
|
|
instance, err := jsObject.NewInstance(v8ctx)
|
|
if err != nil {
|
|
ctx.objectRelease(v8ctx.Isolate(), id)
|
|
return nil, err
|
|
}
|
|
|
|
obj, err := instance.Value.AsObject()
|
|
if err != nil {
|
|
ctx.objectRelease(v8ctx.Isolate(), id)
|
|
return nil, err
|
|
}
|
|
|
|
// Set complex objects (maps, arrays) after instance creation using bridge
|
|
// Args array
|
|
if ctx.Args != nil {
|
|
argsVal, err := bridge.JsValue(v8ctx, ctx.Args)
|
|
if err == nil {
|
|
obj.Set("args", argsVal)
|
|
argsVal.Release() // Release Go-side Persistent handle, V8 internal reference remains
|
|
}
|
|
}
|
|
|
|
// Client object
|
|
clientData := map[string]interface{}{
|
|
"type": ctx.Client.Type,
|
|
"user_agent": ctx.Client.UserAgent,
|
|
"ip": ctx.Client.IP,
|
|
}
|
|
clientVal, err := bridge.JsValue(v8ctx, clientData)
|
|
if err == nil {
|
|
obj.Set("client", clientVal)
|
|
clientVal.Release() // Release Go-side Persistent handle, V8 internal reference remains
|
|
}
|
|
|
|
// Metadata object
|
|
if ctx.Metadata != nil {
|
|
metadataVal, err := bridge.JsValue(v8ctx, ctx.Metadata)
|
|
if err == nil {
|
|
obj.Set("metadata", metadataVal)
|
|
metadataVal.Release() // Release Go-side Persistent handle, V8 internal reference remains
|
|
}
|
|
}
|
|
|
|
// Authorized object
|
|
if ctx.Authorized != nil {
|
|
authorizedVal, err := bridge.JsValue(v8ctx, ctx.Authorized)
|
|
if err == nil {
|
|
obj.Set("authorized", authorizedVal)
|
|
authorizedVal.Release() // Release Go-side Persistent handle, V8 internal reference remains
|
|
}
|
|
}
|
|
|
|
return instance.Value, nil
|
|
}
|
|
|
|
func (ctx *Context) objectRegister() string {
|
|
id := uuid.NewString()
|
|
objectsMutex.Lock()
|
|
defer objectsMutex.Unlock()
|
|
objects[id] = ctx
|
|
return id
|
|
}
|
|
|
|
func (ctx *Context) objectRelease(iso *v8go.Isolate, id string) *v8go.FunctionTemplate {
|
|
return v8go.NewFunctionTemplate(iso, func(info *v8go.FunctionCallbackInfo) *v8go.Value {
|
|
objectsMutex.Lock()
|
|
defer objectsMutex.Unlock()
|
|
delete(objects, id)
|
|
return v8go.Undefined(info.Context().Isolate())
|
|
})
|
|
}
|