js_engine

package
v0.0.8 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 14, 2026 License: MIT Imports: 11 Imported by: 0

README

AutoGo JavaScript Engine

AutoGo JavaScript Engine 是一个高性能的 JavaScript 脚本引擎,为 AutoGo 框架提供了完整的 JavaScript 脚本支持。

特性

  • 完整的 API 注入: 将 AutoGo 的所有功能模块注入到 JavaScript 引擎中
  • 模块化设计: 支持按需加载模块
  • 线程安全: 所有操作都是线程安全的
  • 文件系统支持: 支持真实文件系统和虚拟文件系统 (embed.FS)
  • 模块导入: 支持 CommonJS 风格的 require 功能

快速开始

初始化引擎
import "github.com/ZingYao/autogo_scriptengine/js_engine"

func main() {
    // 使用默认配置创建引擎(自动注入所有方法)
    engine := js_engine.NewEngine(&js_engine.DefaultConfig())
    defer engine.Close()
    
    // 使用引擎...
}
引擎配置选项
import (
    "embed"
    "os"
    "github.com/ZingYao/autogo_scriptengine/js_engine"
)

//go:embed scripts/*
var scriptsFS embed.FS

func main() {
    // 使用自定义配置
    config := js_engine.DefaultConfig()
    config.AutoInjectMethods = false  // 禁用自动注入
    config.FileSystem = scriptsFS      // 设置虚拟文件系统
    
    engine := js_engine.NewEngine(&config)
    defer engine.Close()
    
    // 按需注入模块
    engine.InjectModule("app")
    engine.InjectModule("device")
}
执行 JavaScript 代码
// 执行 JavaScript 字符串
err := engine.ExecuteString(`
    console.log("Hello, JavaScript!");
    const packageName = app.currentPackage();
    console.log("当前应用包名: " + packageName);
`)

// 执行 JavaScript 文件(从真实文件系统)
err = engine.ExecuteFile("/sdcard/script.js")

// 执行 JavaScript 文件(从虚拟文件系统)
err = engine.ExecuteFile("scripts/script.js")

模块列表

模块 说明 详细文档
app 应用管理 README
device 设备信息 README
motion 触摸操作 README
files 文件操作 README
images 图像处理 README
storages 数据存储 README
system 系统功能 README
http 网络请求 README
media 媒体控制 README
opencv 计算机视觉 README
ppocr OCR 文字识别 README
console 控制台窗口 README
coroutine 协程管理 README
dotocr 点字 OCR README
hud HUD 悬浮显示 README
ime 输入法控制 README
plugin 插件加载 README
rhino JavaScript 执行引擎 README
uiacc 无障碍 UI 操作 README
utils 工具方法 README
vdisplay 虚拟显示 README
yolo YOLO 目标检测 README
imgui Dear ImGui GUI 库 README

DemoCode

1. 加载网络的脚本并执行
package main

import (
    "fmt"
    "io"
    "net/http"
    "github.com/ZingYao/autogo_scriptengine/js_engine"
    "github.com/ZingYao/autogo_scriptengine/js_engine/define/safe_models"
)

func main() {
    // 注册 JavaScript 引擎模块
    js_engine.RegisterModule(safe_models.SafeModules...)
    
    // 创建引擎
    engine := js_engine.NewEngine(&js_engine.DefaultConfig())
    defer engine.Close()
    
    // 从网络下载脚本
    resp, err := http.Get("https://example.com/script.js")
    if err != nil {
        fmt.Printf("下载脚本失败: %v\n", err)
        return
    }
    defer resp.Body.Close()
    
    // 读取脚本内容
    script, err := io.ReadAll(resp.Body)
    if err != nil {
        fmt.Printf("读取脚本失败: %v\n", err)
        return
    }
    
    // 执行脚本
    err = engine.ExecuteString(string(script))
    if err != nil {
        fmt.Printf("执行脚本失败: %v\n", err)
    } else {
        fmt.Println("脚本执行成功")
    }
}
2. 加载真实文件系统的脚本并执行
package main

import (
    "fmt"
    "os"
    "github.com/ZingYao/autogo_scriptengine/js_engine"
    "github.com/ZingYao/autogo_scriptengine/js_engine/define/safe_models"
)

func main() {
    // 注册 JavaScript 引擎模块
    js_engine.RegisterModule(safe_models.SafeModules...)
    
    // 创建引擎,配置真实文件系统
    config := js_engine.DefaultConfig()
    config.FileSystem = os.DirFS("/sdcard/script")  // 设置真实文件系统目录
    engine := js_engine.NewEngine(&config)
    defer engine.Close()
    
    // 执行脚本文件
    err := engine.ExecuteFile("main.js")
    if err != nil {
        fmt.Printf("执行脚本失败: %v\n", err)
    } else {
        fmt.Println("脚本执行成功")
    }
}
3. 加载虚拟文件系统的脚本并运行
package main

import (
    "embed"
    "fmt"
    "github.com/ZingYao/autogo_scriptengine/js_engine"
    "github.com/ZingYao/autogo_scriptengine/js_engine/define/safe_models"
)

//go:embed scripts/*
var scriptsFS embed.FS

func main() {
    // 注册 JavaScript 引擎模块
    js_engine.RegisterModule(safe_models.SafeModules...)
    
    // 创建引擎,配置虚拟文件系统
    config := js_engine.DefaultConfig()
    config.FileSystem = scriptsFS      // 设置虚拟文件系统
    engine := js_engine.NewEngine(&config)
    defer engine.Close()
    
    // 执行脚本文件
    err := engine.ExecuteFile("scripts/main.js")
    if err != nil {
        fmt.Printf("执行脚本失败: %v\n", err)
    } else {
        fmt.Println("脚本执行成功")
    }
}
4. Main 脚本加载 Model 脚本并运行

main.js (主脚本)

// main.js - 主脚本,加载并调用 model 脚本

console.log("=== 主脚本开始执行 ===");

// 导入 model 脚本
const model = require("./model");

// 调用 model 中的函数
model.init();
model.process("测试数据");

console.log("=== 主脚本执行完成 ===");

model.js (模型脚本)

// model.js - 模型脚本

function init() {
    console.log("模型初始化完成");
}

function process(data) {
    console.log("处理数据: " + data);
    // 在这里添加具体的处理逻辑
}

// 导出函数
module.exports = {
    init,
    process
};

Go 代码

package main

import (
    "embed"
    "fmt"
    "github.com/ZingYao/autogo_scriptengine/js_engine"
    "github.com/ZingYao/autogo_scriptengine/js_engine/define/safe_models"
)

//go:embed scripts/*
var scriptsFS embed.FS

func main() {
    // 注册 JavaScript 引擎模块
    js_engine.RegisterModule(safe_models.SafeModules...)
    
    // 创建引擎,配置虚拟文件系统
    config := js_engine.DefaultConfig()
    config.FileSystem = scriptsFS
    engine := js_engine.NewEngine(&config)
    defer engine.Close()
    
    // 执行主脚本,主脚本会自动加载 model 脚本
    err := engine.ExecuteFile("scripts/main.js")
    if err != nil {
        fmt.Printf("执行脚本失败: %v\n", err)
    } else {
        fmt.Println("脚本执行成功")
    }
}

API 参考

引擎方法
方法 说明
NewEngine(config *EngineConfig) *JSEngine 创建新的 JavaScript 引擎实例
GetVM() *goja.Runtime 获取 JavaScript 运行时对象
InjectModule(moduleName string) 注入指定模块
InjectModules(modules []string) 注入多个模块
GetAvailableModules() []string 获取所有可用模块列表
InjectAllMethods() 注入所有模块的方法
RegisterMethod(name, description string, goFunc interface{}, overridable bool) 注册自定义方法
ExecuteString(script string, dir ...string) error 执行 JavaScript 字符串(可指定目录)
ExecuteFile(path string) error 执行 JavaScript 文件
Close() 关闭引擎
GetRegistry() *MethodRegistry 获取方法注册表
方法详细说明
NewEngine

创建新的 JavaScript 引擎实例。

config := js_engine.DefaultConfig()
engine := js_engine.NewEngine(&config)
GetVM

获取 JavaScript 运行时对象,用于直接操作 JavaScript 虚拟机。

vm := engine.GetVM()
InjectModule

注入指定模块的方法到引擎中。

engine.InjectModule("app")
engine.InjectModule("device")

支持的模块:app, device, motion, files, images, storages, system, http, media, opencv, ppocr, console, coroutine, dotocr, hud, ime, plugin, rhino, uiacc, utils, vdisplay, yolo, imgui

InjectModules

注入多个模块的方法到引擎中。

engine.InjectModules([]string{"app", "device", "motion"})
GetAvailableModules

获取所有可用模块列表。

modules := engine.GetAvailableModules()
fmt.Println(modules)
// 输出: [app device motion files images storages system http media opencv ppocr console coroutine dotocr hud ime plugin rhino uiacc utils vdisplay yolo imgui]
InjectAllMethods

注入所有模块的方法到引擎中。

engine.InjectAllMethods()
RegisterMethod

注册自定义方法到引擎中。

engine.RegisterMethod("myFunction", "我的自定义函数", func(call goja.FunctionCall) goja.Value {
    // 实现自定义逻辑
    return nil
}, true)

参数:

  • name: 方法名称
  • description: 方法描述
  • goFunc: Go 函数
  • overridable: 是否允许被 JavaScript 函数重写
ExecuteString

执行 JavaScript 代码字符串。

// 基本用法
err := engine.ExecuteString(`
    console.log("Hello, JavaScript!");
`)

// 指定目录(用于 require)
err = engine.ExecuteString(`
    const model = require("./model");
    model.init();
`, "scripts")

参数:

  • script: 要执行的 JavaScript 代码
  • dir: 可选参数,指定工作目录(用于 require)
ExecuteFile

执行 JavaScript 文件。

// 从真实文件系统执行
err := engine.ExecuteFile("/sdcard/script.js")

// 从虚拟文件系统执行
err = engine.ExecuteFile("scripts/script.js")

参数:

  • path: 文件路径
Close

关闭引擎,释放资源。

defer engine.Close()
GetRegistry

获取方法注册表,用于管理已注册的方法。

registry := engine.GetRegistry()
配置选项
选项 类型 说明
AutoInjectMethods bool 是否自动注入所有方法,默认为 true
WhiteList []string 白名单:只加载这些模块
BlackList []string 黑名单:跳过这些模块
FailFast bool 是否在模块加载失败时立即失败,false = 跳过失败模块继续
FileSystem fs.FS 虚拟文件系统 (embed.FS),用于从嵌入文件中加载模块

兼容性说明

Android 版本兼容性

某些依赖包在特定的 Android 版本下可能会出现内存引用错误(Memory Reference Error)。如果遇到此类问题,可以尝试以下解决方案:

  1. 修改引入的包:根据您的 Android 版本,可以修改项目中引入的相关包
  2. 禁用问题模块:在引擎配置中使用黑名单禁用导致问题的特定模块
  3. 使用替代方案:某些功能可能有多种实现方式,可以尝试使用替代方案

示例:禁用可能导致问题的模块

config := js_engine.DefaultConfig()
config.BlackList = []string{"opencv", "ppocr"}  // 禁用可能导致内存问题的模块
engine := js_engine.NewEngine(&config)
Windows 开发环境

在 Windows 环境下开发时,如果引入了某些使用 C 语言的包,可能会遇到以下错误:

The command line is too long.

这是 Windows 命令行长度限制导致的。解决方案:

  1. 避免引入问题包:尽量减少使用包含 C 代码的依赖包
  2. 使用 WSL:在 Windows Subsystem for Linux (WSL) 环境中开发
  3. 调整项目结构:将项目拆分为多个子项目,减少单个项目的依赖复杂度
常见问题处理

如果遇到兼容性问题,建议:

  1. 检查您的 Android 设备版本和 SDK 版本
  2. 查看项目的 GitHub Issues,了解已知的兼容性问题
  3. 根据错误信息调整配置或代码
  4. 如有必要,可以 Fork 项目并根据您的环境进行修改

License

MIT License

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Close

func Close()

func ExecuteFile

func ExecuteFile(path string) error

func ExecuteString

func ExecuteString(script string, dir ...string) error

ExecuteString 执行 JavaScript 代码字符串(全局函数) script: 要执行的 JavaScript 代码 dir: 可选参数,指定 __dirname(用于 require),如果为空则使用默认值 "scripts"

func RegisterMethod

func RegisterMethod(name, description string, goFunc interface{}, overridable bool)

func RegisterModule

func RegisterModule(modules ...model.Module)

RegisterModule 注册一个或多个模块到引擎 用户可以在自己的代码中调用此方法来注册需要的模块 支持可变长参数,可以一次注册多个模块

Types

type DocumentationGenerator

type DocumentationGenerator struct {
	// contains filtered or unexported fields
}

func NewDocumentationGenerator

func NewDocumentationGenerator() *DocumentationGenerator

func (*DocumentationGenerator) GenerateJSDocumentation

func (dg *DocumentationGenerator) GenerateJSDocumentation() string

func (*DocumentationGenerator) GenerateMarkdownDocumentation

func (dg *DocumentationGenerator) GenerateMarkdownDocumentation() string

func (*DocumentationGenerator) SaveJSDocumentation

func (dg *DocumentationGenerator) SaveJSDocumentation(path string) error

func (*DocumentationGenerator) SaveMarkdownDocumentation

func (dg *DocumentationGenerator) SaveMarkdownDocumentation(path string) error

type EngineConfig

type EngineConfig struct {
	AutoInjectMethods bool     // 是否自动注入所有方法,默认为 true
	WhiteList         []string // 白名单:只加载这些模块,空列表 = 加载所有
	BlackList         []string // 黑名单:跳过这些模块,空列表 = 不跳过任何
	FailFast          bool     // 是否在模块加载失败时立即失败,false = 跳过失败模块继续
	FileSystem        fs.FS    // 文件系统,用于 require 功能
}

EngineConfig 引擎配置选项

func DefaultConfig

func DefaultConfig() EngineConfig

DefaultConfig 返回默认配置

type JSEngine

type JSEngine struct {
	// contains filtered or unexported fields
}

JSEngine JavaScript 引擎

func GetEngine

func GetEngine() *JSEngine

GetEngine 获取默认引擎实例(GetJSEngine 的别名)

func GetJSEngine

func GetJSEngine() *JSEngine

GetJSEngine 获取默认引擎实例(使用默认配置,自动注入所有方法)

func NewEngine

func NewEngine(config *EngineConfig) *JSEngine

NewEngine 创建新的引擎实例(NewJSEngine 的别名)

func NewJSEngine

func NewJSEngine(config *EngineConfig) *JSEngine

NewJSEngine 创建新的引擎实例 config: 引擎配置,传入 nil 使用默认配置

func (*JSEngine) Close

func (e *JSEngine) Close()

func (*JSEngine) ExecuteFile

func (e *JSEngine) ExecuteFile(path string) error

func (*JSEngine) ExecuteString

func (e *JSEngine) ExecuteString(script string, dir ...string) error

ExecuteString 执行 JavaScript 代码字符串 script: 要执行的 JavaScript 代码 dir: 可选参数,指定 __dirname(用于 require),如果为空则使用默认值 "scripts"

func (*JSEngine) GetAvailableModules

func (e *JSEngine) GetAvailableModules() []string

GetAvailableModules 获取所有可用模块列表

func (*JSEngine) GetRegistry

func (e *JSEngine) GetRegistry() *MethodRegistry

func (*JSEngine) GetVM

func (e *JSEngine) GetVM() *goja.Runtime

func (*JSEngine) InjectAllMethods

func (e *JSEngine) InjectAllMethods()

InjectAllMethods 注入所有方法(公开方法,允许手动调用)

func (*JSEngine) InjectModule

func (e *JSEngine) InjectModule(moduleName string)

InjectModule 注入指定模块的方法 module: 模块名称,支持: app, device, motion, files, images, storages, system, http, media, opencv, ppocr, console, dotocr, hud, ime, plugin, rhino, uiacc, utils, vdisplay, yolo, imgui

func (*JSEngine) InjectModules

func (e *JSEngine) InjectModules(modules []string)

InjectModules 注入多个模块的方法

func (*JSEngine) RegisterMethod

func (e *JSEngine) RegisterMethod(name, description string, goFunc interface{}, overridable bool)

type MethodInfo

type MethodInfo struct {
	Name        string
	Description string
	GoFunc      interface{}
	Overridable bool
	Overridden  bool
	JSFunc      goja.Callable
}

type MethodRegistry

type MethodRegistry struct {
	// contains filtered or unexported fields
}

func GetRegistry

func GetRegistry() *MethodRegistry

func (*MethodRegistry) Clear

func (r *MethodRegistry) Clear()

func (*MethodRegistry) Contains

func (r *MethodRegistry) Contains(name string) bool

func (*MethodRegistry) Count

func (r *MethodRegistry) Count() int

func (*MethodRegistry) ExportMethodsJSON

func (r *MethodRegistry) ExportMethodsJSON() (string, error)

func (*MethodRegistry) ExportMethodsJSObject

func (r *MethodRegistry) ExportMethodsJSObject() string

func (*MethodRegistry) GenerateJSDocumentation

func (r *MethodRegistry) GenerateJSDocumentation() string

func (*MethodRegistry) GetMethod

func (r *MethodRegistry) GetMethod(name string) (MethodInfo, bool)

func (*MethodRegistry) ListMethods

func (r *MethodRegistry) ListMethods() []MethodInfo

func (*MethodRegistry) OverrideMethod

func (r *MethodRegistry) OverrideMethod(name string, jsFunc goja.Callable) bool

func (*MethodRegistry) RemoveMethod

func (r *MethodRegistry) RemoveMethod(name string) bool

func (*MethodRegistry) RestoreMethod

func (r *MethodRegistry) RestoreMethod(name string) bool

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL