news 2026/10/16 2:35:40

MooTool Next 原生版 JSON 工作区与独立解析引擎:SwiftUI + JavaScriptCore 的安全架构解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
MooTool Next 原生版 JSON 工作区与独立解析引擎:SwiftUI + JavaScriptCore 的安全架构解析
  • 桌面应用
  • 开发工具

【免费下载链接】MooTool

Handy tool set for developers

项目地址:https://gitcode.com/gh_mirrors/mo/MooTool
点击查看免费下载

导读

本文聚焦 MooTool 跨平台新一代产品线next-macos-native中 JSON 工具的核心设计:一个由 SwiftUI / AppKit 构建的完整 JSON 工作区,以及一套基于系统 JavaScriptCore、运行在独立辅助进程中的 JSON 解析引擎。阅读本文后,你将理解 MooTool 如何在不依赖 Node.js、Electron 与网络服务的条件下,将 Electron 版 JSON 工具的格式化、JSONPath 查询、XML / JavaBean 转换与查找替换能力完整移植到 macOS 原生平台,并掌握其进程隔离、超时控制、三语文案与能力边界的实现细节。该产品线的完整对齐口径见 parity.md,本主题的官方说明见 json-engine.md。

JSON 工作区的界面骨架

MooTool Next 原生版 0.4.0 起,JSON 工具采用与 Electron 版对应的工作区布局,由以下核心区域组成:

  • 工具栏:承载格式化、压缩、查找、检查器开关等主要操作;
  • 主编辑器:基于原生 NSTextView 的 JSON 正文编辑区;
  • 可折叠检查器:用于结构树、路径选择与值预览;
  • 查找替换栏:支持 JavaScript 正则语义的查找与替换;
  • 路径选择器与转换结果弹窗:展示 JSONPath 查询结果与转换输出。

这一布局明确以 Electron 端的 JsonTool.tsx、JsonToolbar.tsx、JsonInspector.tsx、JsonToolDialogs.tsx 为参照实现,面板顺序与主要操作语义保持一致,但控件全部采用 macOS 原生组件。

在窄编辑区场景下,部分工具栏操作会被收纳进"更多"菜单,检查器通过弹出面板打开;整体交互遵循 macOS 的菜单、分栏与弹窗惯例,而非逐像素复刻 Electron 页面。

操作语义:哪些操作原地生效,哪些进入结果弹窗

JSON 工具的操作按"是否直接修改正文"分为两类,这是理解该工作区行为的关键:

直接更新主编辑器的操作(可撤销/重做,并保存到当前文档):

  • 格式化(format):以 2 空格缩进重新序列化正文;
  • 压缩(compress):移除所有空白的最紧凑形式;
  • 高级格式化(advanced):支持自定义缩进、按键排序、忽略大小写排序与重复键检测;
  • 键值互换(swap):仅针对 JSON 对象执行,交换键与值(值必须是可作键的类型);
  • 转义 / 反转义(escape / unescape,含 Java 字符串风格的 escapeText / unescapeText)。

在结果弹窗中展示的操作(可复制、导出、使用结果,使用前不替换正文):

  • JSONPath 查询(query):路径选择器填入 JSONPath 后执行;
  • JSON → XML(jsonToXml);
  • JSON → JavaBean(jsonToBean):生成 Java 类源码。

先输入来源、再替换正文的操作:

  • XML → JSON(xmlToJson):先在弹窗中粘贴 XML,转换成功后替换主编辑器正文;
  • JavaBean → JSON(beanToJson):同样先输入 Java 字段声明源码,再生成 JSON 替换正文。

这些 action 的分发逻辑集中在随包发布的 JSONDispatch.js 的runJSONRequest(payload)中,每个 case 对应一种操作语义,错误信息通过translate()按请求携带的language返回 zh-CN / en-US / ja-JP 三种语言。

查找替换:沿袭 JavaScript 正则语义

查找替换(find / replace / replaceAll)在 JSONTools.js 中实现,与 Electron 版完全同源:

  • 支持大小写匹配(matchCase)、全词匹配(wholeWord,用\b包裹)、正则模式(regex);
  • 支持向前 / 向后导航、捕获组替换模板与换行替换(\n、\r、\t);
  • 正则标志使用gu/giu,因此matchAll返回的索引是代码点级别的 UTF-16 偏移;
  • 替换选中区时,仅当选区恰好整体等于唯一匹配时才原地替换该选区;
  • 高亮使用 NSTextView 的临时属性实现,不写入文档内容。

在CoreTests.swift中有对应验证:如testJSONNativeFindReplaceUnicodeAndFlags断言item(\d+)正则替换$1\n能正确生成换行、反向查找返回正确起始偏移、非法正则[会抛出错误(见 CoreTests.swift)。

路径选择器:字面路径优先,复杂表达式交给 JSONPath-Plus

路径选择器生成两类路径:

  • 字面路径(literal path):如$.store.books[0]、$["特殊 键名"],由 JSONDispatch.js 的literalPathTokens()解析,逐段保留数字、引号、方括号、反斜杠转义与换行等特殊键名,不做表达式求值;
  • 复杂表达式:如通配符、递归、筛选、切片、联合查询,交给 JSONPath-Plus 10.4.0 求值;
  • 严格 JSON Pointer:以/开头的路径走pointerQuery(),支持~0(~)与~1(/)转义、数组下标合法性校验与路径存在性校验。

右侧菜单仍可复制 JSON Pointer。结构树节点同时携带pointer(JSON Pointer)与queryPath(JSONPath 形式)两个标识,见 JSONStructure.swift 的JSONTreeNode,测试testJSONNativePathsMatchElectronQueries中$["0"]与$.array[0]的映射关系即由此而来。

独立解析引擎:Swift 宿主 + JavaScriptCore + JS 算法副本

MooTool 原生版没有在 macOS 应用内重写全部 JSON 算法,而是采用"独立解析引擎"架构:

  1. 算法层:JSONTools.js是 MooTool 对应纯算法的独立副本,在本产品内维护,并包含 Java 字段名 / 类名冲突处理等原生版修正;
  2. 执行层:系统 [JavaScriptCore] 的JSContext在随应用打包的MooToolJSONWorker辅助进程中执行这些算法;
  3. 分发层:JSONDispatch.js负责把 Swift 结构化请求转换为具体算法调用,并统一本地化错误信息;
  4. 宿主层:Swift 侧 JSONEngine.swift 负责请求构造、进程生命周期与结果回传。

三个 Swift target 的关系记录在 Package.swift:MooToolJSONWorker是独立可执行文件,依赖MooToolNextCore;MooToolNextApp是主应用;MooToolNextCore同时被两者依赖,承担算法资源封装。

请求-响应协议

请求由 JSONEngineRequest 描述,核心字段包括:

字段默认值说明
action无操作类型(format / compress / advanced / swap / escape / unescape / query / jsonToXml / xmlToJson / beanToJson / jsonToBean / find / replace / replaceAll / duplicates / validate 等)
input无正文输入(最大 10 MB UTF-8)
path$JSONPath 或 JSON Pointer
classNameRootJSON → JavaBean 的根类名(最长 240 字符)
indent2高级格式化缩进空格数
sortKeys/ignoreCasefalse排序开关与排序时的大小写不敏感
checkDuplicateKeystrue高级格式化时是否检测重复键
query/replacement空查找内容与替换内容(替换最长 1 MB)
matchCase/wholeWord/regexfalse查找替换三个标志
selectionStart/selectionEnd0当前光标 / 选区位置(UTF-16)
forwardtrue导航方向
languagezh-CN错误信息语言

响应为 JSONEngineReply:value(结果正文)、error(错误信息)、count(命中数)、match/matches(查找定位信息)。

数据传参:JSON 请求文件,而非脚本源码

一个关键的安全设计是:用户输入永远作为数据传入,绝不拼接为脚本源码。

JSONEngine.runWorker会为每次调用创建独立的临时目录(命名前缀为产品ID-json-<UUID>,目录权限 0700、文件权限 0600),把编码后的请求写入input文件,worker 从标准输入读取、结果写入output文件。worker 进程的环境变量被简化为LANG=en_US.UTF-8,不继承 shell 启动路径、注入的运行时路径与用户环境密钥(见 JSONEngine.swift)。

JSONDispatch.js首行注释也明确写着:// Native-product boundary: all caller text is data, never script source.。JSONPath 求值使用eval: 'safe',禁用动态表达式求值,测试 CoreTests.swift 专门断言@.constructor.constructor('return process')()这类注入表达式会被拒绝。辅助进程不向脚本暴露任何原生文件、网络或进程对象。

超时与取消:双层保险

辅助进程的终止由两层机制兜底:

  • 父进程 3 秒超时:JSONEngine.execute(_:timeout:)默认 3 秒,轮询期间一旦超过deadline就对 worker 发送SIGKILL并抛出超时错误(json.engine.timeout);
  • worker 自身 4 秒硬终止:main.swift 中signal(SIGALRM, SIG_DFL)后调用alarm(4),即使主应用异常退出,耗时表达式也会在 4 秒后被系统信号终止;
  • 用户取消:withTaskCancellationHandler+WorkerCancellation在任务取消时同样SIGKILL终止进行中的进程并抛CancellationError。

输出文件也会被监控,一旦超过 16 MB 即终止本次调用。每次调用结束都会删除临时目录。测试testJSONWorkerTimeoutCancellationAndIsolation用灾难性正则(a+)+$验证了超时与取消路径。

多窗口与文档切换语义:关闭无关窗口不会取消另一窗口的操作;切换文档、恢复工作区或修改正文后,旧的异步结果不会自动覆盖新内容。

依赖与产品边界

查询与 XML 转换依赖两个第三方库,版本与校验信息集中在 parser-versions.json:

依赖版本用途发行文件 SHA-256
JSONPath-Plus10.4.0JSONPath 查询(含 jsep 表达式解析)ed2274eecaf6c8209eab8ebf991ef9319e23f4886296a257e84aaa055bfed097
fast-xml-parser5.10.1XML 解析 / 构建(含 fast-xml-builder、strnum、is-unsafe 等子依赖)fa2f3be3e78aab26a7a04be70fdceb7dede6981a4d1a0e2ca25c30bcef194f2e

浏览器发行文件与许可副本全部位于本产品Sources/MooToolNextCore/Resources/,包括jsonpath-plus.js、fast-xml-parser.js、JSONTools.js、JSONDispatch.js、QuickNoteTools.js、ReformatTools.js及各库的 LICENSE 文件。这意味着:

  • 构建和运行不读取nextElectron 源码或node_modules;
  • 不要求 Node.js、Electron、浏览器或任何网络服务;
  • JSON 数据不会发送到远端,所有解析都在本机辅助进程中完成;
  • 产物本身随包分发,离线可用。

JSONTools.js是本产品内维护的独立算法副本,与 Electron 版next/src/features/json/jsonTools.ts同源,但针对原生版需求做了一处显著修正:Java 字段名 / 类名冲突处理(详见下文 JavaBean 一节)。

能力边界与限制

为保持与 Electron 版一致的解析语义并保证辅助进程安全,引擎设定如下边界(原文见 json-engine.md 能力边界一节,实现见 JSONEngine.swift 与 JSONDispatch.js):

维度限制
单次正文最多 10 MB(evaluateLocally校验)
请求 / 结果最多 16 MB(编码后二进制大小)
JSON 规模最多 10 万节点、128 层(checkShape遍历计数)
结构树 / 查询 / 查找结果最多 2 万项(JSONStructure的nodeLimit与 query / find 的count上限)
父进程超时默认 3 秒
worker 终止计时独立 4 秒(alarm(4))
替换模板最多 1 MB(UTF-8)
JSONPath / 查询文本最多 16 KB(UTF-8)
类名最多 240 字符(UTF-8)

超过任一限制即返回本地化错误(如json.error.nodeLimit:JSON 最多处理 10 万节点、128 层;json.error.queryTooManyResults:查询结果超过 2 万项)。

JSON 数字语义:JavaScript Number

JSON 数字按 JavaScript 的 Number 语义处理,与 Electron 一致——例如大整数超过Number.MAX_SAFE_INTEGER时精度会丢失。引擎不提供任意精度数字保证,这一行为对齐 Electron 基线,属于有意边界而非缺陷。

XML 转换规则

  • 输入使用严格语法校验(XMLValidator.validate),不接收 DTD 或实体声明(<![DOCTYPE / ENTITY ...]>会直接拒绝,测试用file:///etc/hosts实体注入用例验证);
  • XML → JSON 的属性使用@_前缀(如@_enabled),重复元素合并为数组,值的数值 / 布尔推断沿用 fast-xml-parser 的解析行为;
  • JSON → XML 自动转义特殊字符(如&转&amp;);
  • 解析器抛出的英文msg仍可能透传(如 XML 语法错误的原始消息)。

JavaBean 双向转换规则

JavaBean → JSON(javaBeanToJson):用正则解析字段声明(支持public/protected/private、static/final/transient/volatile修饰符与泛型类型),为每个字段生成示例值(mockJavaValue:String 生成空串、int 生成 0、List 生成空数组等),跳过serialVersionUID。它不执行 Java 代码,也不做完整 Java 编译器级类型分析。

JSON → JavaBean(jsonToBean):生成字段与嵌套类源码,核心逻辑在 JSONTools.js 的buildNativeJavaClass:

  • 自动加入import java.util.List;;
  • 类型推断:null →Object、整数 →Long、小数 →Double、布尔 →Boolean、字符串 →String、数组按元素类型推导List<T>;
  • 混合类型数组使用Object(List<Object>);
  • 关键字处理:字段名命中 Java 关键字(class、new、record等,内置javaKeywords集合)时,转换为合法标识符(如class→classValue);
  • 命名冲突处理:字段重名追加数字后缀(a_b与a-b都转成下划线形式时,后者变为a_b2);类名与String、List、Object、Boolean、Long、Double等内置类型冲突时追加数字后缀(Root与List冲突时生成List2,嵌套String类变成String2),逻辑由unique(base, used)与occupiedTypes集合实现;
  • 嵌套对象生成为public static class内部类,类名遵循驼峰命名(toPascalCase)。

测试 CoreTests.swift 的testJSONNativeXMLAndJavaConversions与testJSONNativeEscapesAndKeyValueSwap完整覆盖了上述规则,包括{"string":{...},"list":[...],"object":{...}}用类名List时的多层重命名。仓库本机另用javac实际编译辅助进程生成的 Java 文件,覆盖关键字、字段重名、嵌套类型、混合数组和 String/List/Object 命名冲突,确保生成源码可编译。

工作区与文档库边界

  • 窗口间同步正文:多个窗口编辑同一文档时正文保持同步;撤销记录属于当前编辑器,其他窗口写入正文时会清理本窗口可能已过期的撤销记录;重启不恢复撤销栈;
  • Monaco 尚未移植:Monaco 编辑器的全部快捷操作、折叠和编辑装饰尚未移植到原生版;
  • 文档库生态:JSON 文档支持镜像到json-vault/、FSEvents 监听外部改动、Finder 定位,以及 Vault Git 面板(Diff、丢弃、合并 / 变基与冲突处理),与 Electron 的差异见 parity.md。

验证体系

原生 JSON 引擎的验证分三层:

  1. 核心测试:MooToolNextCoreTests对照 Electron 输入输出用例,覆盖通配符、递归、筛选、切片、联合查询、特殊键路径、重复键、XML 拒绝项(DTD / 实体 / 语法错误)、Java 命名、Unicode 查找替换、工作区兼容,以及辅助进程超时和取消(见 CoreTests.swift 的testJSONNativePathsMatchElectronQueries、testJSONNativeXMLAndJavaConversions、testJSONNativeFindReplaceUnicodeAndFlags、testJSONWorkerTimeoutCancellationAndIsolation等用例);
  2. javac 实编译:对jsonToBean生成的 Java 文件用本机javac实际编译,覆盖关键字、字段重名、嵌套类型、混合数组与命名冲突场景;
  3. 原生验收:发送格式化快捷键并操作实际编辑器,验证原地修改、自动保存、撤销/重做、结果弹窗、使用结果、输入转换及文档切换;再通过新进程检查工作区恢复。界面截图覆盖检查器、查找栏、路径选择器、结果弹窗及深浅色 / 窄窗口。需要说明的是,截图成功不等于所有菜单和系统对话框均已做端到端验证。

小结

MooTool Next 原生版的 JSON 引擎是一套"算法同源、执行隔离、行为对齐"的架构:算法层直接继承 Electron 版的jsonTools.ts逻辑并以JSONTools.js独立维护,执行层利用系统 JavaScriptCore 与独立辅助进程实现离线解析与安全隔离,交互层以 SwiftUI / AppKit 原生控件对齐 Electron 工作区。对于需要移植复杂 Web 工具到桌面原生平台的开发者,其"浏览器发行文件随包分发 + 临时文件传参 + 双层超时 + 三语错误"的组合方案具有直接的参考价值。完整边界说明见 json-engine.md,功能对齐总表见 parity.md。

  • 桌面应用
  • 开发工具

【免费下载链接】MooTool

Handy tool set for developers

项目地址:https://gitcode.com/gh_mirrors/mo/MooTool
点击查看免费下载

相关推荐

上一篇:3个问题帮你判断:思源笔记是否值得你投入时间学习?
下一篇:B站视频永久保存终极指南:10分钟掌握m4s转mp4专业技巧

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/16 2:33:31

Sicar-Training-show-V16实训程序解析:状态机、参数模型与避坑指南

简介&#xff1a;Sicar-Training-show-V16程序包是一套面向汽车行业自动化产线场景的Sicar标准程序培训演示资源&#xff0c;聚焦设备控制、工位逻辑与安全联锁等典型应用&#xff0c;适用于PLC编程工程师、产线调试人员以及希望系统学习西门子标准化编程理念的初学者与进阶者。…

作者头像 李华
网站建设 2026/10/16 2:32:49

十分钟生成 OpenCore EFI:OpCore-Simplify 黑苹果引导配置完整实战

十分钟生成 OpenCore EFI&#xff1a;OpCore-Simplify 黑苹果引导配置完整实战 【免费下载链接】OpCore-Simplify A tool designed to simplify the creation of OpenCore EFI 项目地址: https://gitcode.com/GitHub_Trending/op/OpCore-Simplify 装黑苹果最劝退的往往不…

作者头像 李华
网站建设 2026/10/16 2:31:48

HugAgentOS MCP工具生态:8个内置服务解析+自定义MCP接入完全指南

【免费下载链接】HugAgentOS HugAgentOS: The Self-Evolving AgentOS for Ontology-Grounded Trustworthy Reasoning 项目地址&#xff1a; https://gitcode.com/gh_mirrors/hu/HugAgentOS 点击查看 免费下载 HugAgentOS 是一款面向可信推理的自进化 AgentOS&#xff0c;其工具…

作者头像 李华
网站建设 2026/10/16 2:31:41

基于MP2642GR-Z与PIC32的串联电池双向主动均衡系统设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华