snapshot before legacy cleanup

This commit is contained in:
Naeel
2026-04-27 07:36:06 +03:00
parent 9461026546
commit 7cfe20bf76
25 changed files with 1430 additions and 261 deletions
-3
View File
@@ -7,7 +7,6 @@ package runtime
// - nodejs: "main" → имя экспортированной default-функции в main.js
// - php: "main.php::handler" → имя файла + "::" + имя функции
// - ruby: "handler" → имя метода в загруженном файле
// - perl: "handler" → имя функции в загруженном файле
// - go: "Handler" → экспортированная Go-функция (с большой буквы)
func DefaultEntrypoint(lang string) string {
switch lang {
@@ -18,8 +17,6 @@ func DefaultEntrypoint(lang string) string {
return "main.php::handler"
case "ruby":
return "handler"
case "perl":
return "handler"
case "go":
// Go: экспортированная функция (заглавная) — go/plugin требует экспорт
return "Handler"
+1 -1
View File
@@ -6,7 +6,7 @@ import (
)
// buildZip создаёт zip-архив с одним файлом fileName и содержимым content.
// Вспомогательная функция: используется в buildScriptZip (PHP/Ruby/Perl),
// Вспомогательная функция: используется в buildScriptZip (PHP/Ruby),
// а также как основа для buildGoSourceZip и buildJSDeployZip.
func buildZip(fileName string, content []byte) ([]byte, error) {
var buf bytes.Buffer
+9 -1
View File
@@ -22,6 +22,11 @@ import (
// Результат: zip с двумя файлами:
// - package.json: {"type":"module"}
// - main.js: ESM wrapper + инлайн пользовательский код через new Function
//
// Совместимость entrypoint:
// UI исторически отправлял entrypoint="handler", а backend по умолчанию использует
// entrypoint="main". Чтобы specialization не ломался из-за несовпадения,
// wrapper экспортирует обе точки входа: named exports main и handler, а также default.
func BuildJSDeployZip(code string) ([]byte, error) {
// Сериализуем пользовательский код в JSON строку чтобы безопасно инлайнить
// в JavaScript-литерал — экранирует кавычки, переводы строк, спецсимволы.
@@ -38,7 +43,7 @@ func BuildJSDeployZip(code string) ([]byte, error) {
(new Function('module', 'exports', %s))(__mod, __mod.exports);
const _fn = __mod.exports;
export default async function(ctx) {
async function __invoke(ctx) {
const fn = typeof _fn === 'function' ? _fn : (_fn.default || _fn.handler || _fn.main);
if (!fn) throw new Error('no exported function found in user code');
const result = await fn(ctx);
@@ -46,6 +51,9 @@ export default async function(ctx) {
if (typeof result.status !== 'undefined') return result;
return { status: 200, ...result };
}
export { __invoke as main, __invoke as handler };
export default __invoke;
`, string(codeJSON))
var buf bytes.Buffer
+50
View File
@@ -0,0 +1,50 @@
package runtime
import (
"archive/zip"
"bytes"
"io"
"strings"
"testing"
)
func TestBuildJSDeployZipExportsMainAndHandler(t *testing.T) {
zipBytes, err := BuildJSDeployZip(`module.exports = async function () { return { status: 200, body: "ok" }; }`)
if err != nil {
t.Fatalf("BuildJSDeployZip() error = %v", err)
}
zr, err := zip.NewReader(bytes.NewReader(zipBytes), int64(len(zipBytes)))
if err != nil {
t.Fatalf("zip.NewReader() error = %v", err)
}
files := map[string]string{}
for _, file := range zr.File {
rc, openErr := file.Open()
if openErr != nil {
t.Fatalf("open %q: %v", file.Name, openErr)
}
content, readErr := io.ReadAll(rc)
_ = rc.Close()
if readErr != nil {
t.Fatalf("read %q: %v", file.Name, readErr)
}
files[file.Name] = string(content)
}
if files["package.json"] != `{"type":"module"}` {
t.Fatalf("package.json = %q, want ESM marker", files["package.json"])
}
mainJS := files["main.js"]
if !strings.Contains(mainJS, `export { __invoke as main, __invoke as handler };`) {
t.Fatalf("main.js does not export both main and handler: %s", mainJS)
}
if !strings.Contains(mainJS, `export default __invoke;`) {
t.Fatalf("main.js does not export default invoke: %s", mainJS)
}
if !strings.Contains(mainJS, `_fn.default || _fn.handler || _fn.main`) {
t.Fatalf("main.js lost user export resolution: %s", mainJS)
}
}
+1 -1
View File
@@ -1,7 +1,7 @@
package runtime
// BuildScriptZip создаёт zip-архив с одним файлом fileName и содержимым code.
// Используется для PHP, Ruby, Perl — языков где среда Fission ожидает
// Используется для PHP и Ruby — языков где среда Fission ожидает
// именованный файл (handler.rb, handler.pl, main.php и т.д.) внутри архива.
//
// Почему zip, а не просто literal: