Files
what 7fb8d0f966 test: 测试用的最小扩展
本库不带内置扩展——扩展该由用引擎的人按自己的场景定义,引擎只给接口。
但测「作用域共享状态」「扩展改名」「VM 复用后状态还在不在」这些行为,
手上得有一个真的扩展,所以放一个最小的在 internal 下。

Incr 用 float64 而不是整数:JS 的数字就是 float64,脚本写进来的值也是
这个类型,用整数会让「Go 侧读回来」的断言在类型上对不上。
2026-09-05 22:12:14 +08:00

103 lines
2.6 KiB
Go

// 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
`