test: 测试用的最小扩展
本库不带内置扩展——扩展该由用引擎的人按自己的场景定义,引擎只给接口。 但测「作用域共享状态」「扩展改名」「VM 复用后状态还在不在」这些行为, 手上得有一个真的扩展,所以放一个最小的在 internal 下。 Incr 用 float64 而不是整数:JS 的数字就是 float64,脚本写进来的值也是 这个类型,用整数会让「Go 侧读回来」的断言在类型上对不上。
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
// Package testext 给本库自己的测试提供一个**有状态的**扩展。
|
||||
//
|
||||
// 本库只定义 Extension 接口,不带任何内置扩展——扩展该由用引擎的人按自己的
|
||||
// 场景定义(框架侧的那套见 framework 的 internal/jscript/ext)。但测"作用域
|
||||
// 共享状态""扩展改名""VM 复用后状态还在不在"这些行为,手上得有一个真的扩展,
|
||||
// 所以这里放一个最小的。
|
||||
//
|
||||
// 它只为测试存在,不是给外部用的示范——真要写扩展看 Extension 接口的文档。
|
||||
package testext
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"git.fsdpf.net/go/jscriptx"
|
||||
)
|
||||
|
||||
// Store 是一份并发安全的键值表,同时也是一个 jscriptx 扩展。
|
||||
type Store struct {
|
||||
name string
|
||||
|
||||
mu sync.RWMutex
|
||||
data map[string]any
|
||||
}
|
||||
|
||||
// New 造一个,全局名默认叫 store。
|
||||
func New() *Store { return &Store{name: "store", data: map[string]any{}} }
|
||||
|
||||
// Named 造一个用别的全局名的,用来测改名。
|
||||
func Named(name string) *Store { return &Store{name: name, data: map[string]any{}} }
|
||||
|
||||
func (s *Store) Name() string { return s.name }
|
||||
|
||||
func (s *Store) Module() (string, string) { return "@jscriptx/store", typings }
|
||||
|
||||
func (s *Store) Bindings() map[string]any {
|
||||
return map[string]any{
|
||||
"Get": s.Get,
|
||||
"GetOr": s.GetOr,
|
||||
"Set": s.Set,
|
||||
"Incr": s.Incr,
|
||||
"Len": s.Len,
|
||||
}
|
||||
}
|
||||
|
||||
// Get 取值,没有返回 nil(到脚本里是 null)。
|
||||
func (s *Store) Get(key string) any {
|
||||
s.mu.RLock()
|
||||
defer s.mu.RUnlock()
|
||||
return s.data[key]
|
||||
}
|
||||
|
||||
// GetOr 取值,没有返回 fallback。
|
||||
func (s *Store) GetOr(key string, fallback any) any {
|
||||
s.mu.RLock()
|
||||
defer s.mu.RUnlock()
|
||||
if v, ok := s.data[key]; ok {
|
||||
return v
|
||||
}
|
||||
return fallback
|
||||
}
|
||||
|
||||
// Set 写值。
|
||||
func (s *Store) Set(key string, v any) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
s.data[key] = v
|
||||
}
|
||||
|
||||
// Incr 累加,返回加完的值。键不存在按 0 算。
|
||||
//
|
||||
// 用 float64 而不是整数:JS 的数字就是 float64,脚本写进来的值也是这个类型,
|
||||
// 用整数会让"Go 侧读回来"的断言在类型上对不上。
|
||||
func (s *Store) Incr(key string, delta float64) float64 {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
n, _ := s.data[key].(float64)
|
||||
n += delta
|
||||
s.data[key] = n
|
||||
return n
|
||||
}
|
||||
|
||||
// Len 返回键的个数。
|
||||
func (s *Store) Len() int {
|
||||
s.mu.RLock()
|
||||
defer s.mu.RUnlock()
|
||||
return len(s.data)
|
||||
}
|
||||
|
||||
var _ jscriptx.Extension = (*Store)(nil)
|
||||
|
||||
const typings = `export interface Store {
|
||||
Get(key: string): any
|
||||
GetOr(key: string, fallback: any): any
|
||||
Set(key: string, value: any): void
|
||||
Incr(key: string, delta: number): number
|
||||
Len(): number
|
||||
}
|
||||
|
||||
declare const store: Store
|
||||
export default store
|
||||
`
|
||||
Reference in New Issue
Block a user