From b4c0ae11df9c58b6896cdb43cf9836bc4305a5b5 Mon Sep 17 00:00:00 2001 From: ExplodingDragon Date: Sun, 1 Feb 2026 00:06:47 +0800 Subject: [PATCH] feat(goja): implement localStorage API and add global types --- global-types/globals.d.ts | 15 ++++++++++++ pkg/filters/goja/var_kv.go | 46 ++++++++++++++++++++++++++++++++++- tests/filter_goja_ls_test.go | 47 ++++++++++++++++++++++++++++++++++++ 3 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 tests/filter_goja_ls_test.go diff --git a/global-types/globals.d.ts b/global-types/globals.d.ts index fbc4d3d..0fba508 100644 --- a/global-types/globals.d.ts +++ b/global-types/globals.d.ts @@ -146,6 +146,21 @@ declare global { const kv: KVSystem; + // localStorage 模拟 + interface Storage { + getItem(key: string): string | null; + + setItem(key: string, value: string): void; + + removeItem(key: string): void; + + clear(): void; + + key(index: number): string | null; + } + + const localStorage: Storage; + // Console 相关 (假设通过 require 引入) interface Console { log(...args: any[]): void; diff --git a/pkg/filters/goja/var_kv.go b/pkg/filters/goja/var_kv.go index 5fc21fe..e2e811e 100644 --- a/pkg/filters/goja/var_kv.go +++ b/pkg/filters/goja/var_kv.go @@ -11,13 +11,57 @@ import ( ) func KVInject(ctx core.FilterContext, jsCtx *goja.Runtime) error { - return jsCtx.GlobalObject().Set("kv", map[string]interface{}{ + if err := jsCtx.GlobalObject().Set("kv", map[string]interface{}{ "repo": func(group ...string) (goja.Value, error) { return kvResult(ctx.RepoDB)(ctx, jsCtx, group...) }, "org": func(group ...string) (goja.Value, error) { return kvResult(ctx.OrgDB)(ctx, jsCtx, group...) }, + }); err != nil { + return err + } + + // 注入 localStorage 模拟 + lsDB := ctx.RepoDB.Child("local_storage") + return jsCtx.GlobalObject().Set("localStorage", map[string]interface{}{ + "getItem": func(key string) (goja.Value, error) { + get, err := lsDB.Get(ctx, key) + if err != nil { + if !errors.Is(err, os.ErrNotExist) { + return nil, err + } + return goja.Null(), nil + } + return jsCtx.ToValue(get), nil + }, + "setItem": func(key, value string) error { + return lsDB.Put(ctx, key, value, kv.TTLKeep) + }, + "removeItem": func(key string) (bool, error) { + return lsDB.Delete(ctx, key) + }, + "clear": func() error { + // 简单的清除逻辑:列出并删除 + list, err := lsDB.ListCurrentCursor(ctx, &kv.ListOptions{Limit: 1000}) + if err != nil { + return err + } + for _, k := range list.Keys { + _, _ = lsDB.Delete(ctx, k) + } + return nil + }, + "key": func(index int) (goja.Value, error) { + list, err := lsDB.ListCurrentCursor(ctx, &kv.ListOptions{Limit: int64(index + 1)}) + if err != nil { + return nil, err + } + if len(list.Keys) > index { + return jsCtx.ToValue(list.Keys[index]), nil + } + return goja.Null(), nil + }, }) } diff --git a/tests/filter_goja_ls_test.go b/tests/filter_goja_ls_test.go new file mode 100644 index 0000000..bfb7521 --- /dev/null +++ b/tests/filter_goja_ls_test.go @@ -0,0 +1,47 @@ +package tests + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "gopkg.d7z.net/gitea-pages/tests/core" +) + +func Test_GoJa_LocalStorage(t *testing.T) { + server := core.NewDefaultTestServer() + defer server.Close() + server.AddFile("org1/repo1/gh-pages/index.html", "hello world") + server.AddFile("org1/repo1/gh-pages/index.js", ` +localStorage.setItem('foo', 'bar'); +const val = localStorage.getItem('foo'); +localStorage.removeItem('nonexistent'); +response.write(val); +`) + server.AddFile("org1/repo1/gh-pages/.pages.yaml", ` +routes: +- path: "test" + js: + exec: "index.js" +`) + + data, _, err := server.OpenFile("https://org1.example.com/repo1/test") + assert.NoError(t, err) + assert.Equal(t, "bar", string(data)) + + // 验证持久化 + server.AddFile("org1/repo1/gh-pages/index2.js", ` +response.write(localStorage.getItem('foo')); +`) + server.AddFile("org1/repo1/gh-pages/.pages.yaml", ` +routes: +- path: "test" + js: + exec: "index.js" +- path: "check" + js: + exec: "index2.js" +`) + data, _, err = server.OpenFile("https://org1.example.com/repo1/check") + assert.NoError(t, err) + assert.Equal(t, "bar", string(data)) +}