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