
JSDebugger 源码架构梳理一张图看懂 JDEngine、FFI、Plugin 等 10 大核心模块【免费下载链接】JSDebuggerJavaScript-Based Debugger For Inspecting Running State Of Your Application项目地址: https://gitcode.com/gh_mirrors/js/JSDebuggerJSDebugger 是一个基于 JavaScript 的 iOS 应用调试工具它最酷的地方在于你可以用 JS 脚本直接查看和操作正在运行的 Objective-C 对象。想搞懂它的源码架构只需抓住 JDEngine、FFI、Plugin 三大主线再配合 10 大核心模块逐个击破整个设计脉络就会非常清晰。本文用「一张架构图 模块拆解」的方式带你快速读懂这份 iOS 调试器源码。JSDebugger 是什么为什么值得读源码简单说JSDebugger 在 App 内部嵌入了一个 JavaScriptCore 运行时让 JS 可以直接访问 Objective-C 的类、对象、方法、属性。调试时你不用断点、不用 LLDB写几行 JS 就能打印任意对象的属性、调用任意方法。对于想学习iOS 与 JavaScript 互调、Objective-C 运行时Runtime应用、FFI 函数调用的开发者来说这份源码架构堪称教科书级范例。一张图看懂整体架构整个工程分为三层入口层 → 核心运行时层 → 工具/文件监听层核心逻辑几乎全部集中在Source/Core目录下。┌─────────────────────────────────────────────────────┐ │ 入口层 JDEngine / JSDebugger.h │ │ 单例启动、创建 JS 全局上下文、注册插件 │ ├─────────────────────────────────────────────────────┤ │ 核心运行时层Source/Core │ │ ├─ JSDefinition JDClass4JS / JDInstance4JS │ │ │ JDMethod4JS / JDPointer4JS │ │ ├─ Runtime JDMethodBridge / JDEncoding │ │ │ JDJSTypeToOCType / JDOCTypeToJSType│ │ │ JDPropertyCache / JDStruct │ │ ├─ FFI JDFFIContext真正的函数调用 │ │ └─ Plugin JDFunctionPlugin │ │ Plugin/JDChoose / Plugin/JDIntrospect│ ├─────────────────────────────────────────────────────┤ │ 工具/监听层 JDNSStringFromJSString / JDFormatJSFunction│ │ NSObjectJDRuntimeIntrospection │ │ JDLog │ ├─────────────────────────────────────────────────────┤ │ 文件热更新层 FileWatcher/JDLocalFileObserver │ │ FileWatcher/JDLocalFilePresenter │ └─────────────────────────────────────────────────────┘下面按这张图逐一拆解 10 大核心模块。一、JDEngine一切从「入口」开始JDEngine 是整个调试器的单例入口源码在 JDEngine.h 与 JDEngine.m。它的职责非常聚焦创建 JS 全局上下文初始化JSGlobalContextRef并给全局对象挂上getProperty回调。这样你在 JS 里写UIView它就能自动通过NSClassFromString找到对应的 OC 类并包装成 JS 对象。注册插件start方法调用JDFunctionPluginManager把全部插件注册进 JS 上下文。执行脚本提供evaluateScript:和evaluateScriptAtPath:两个 API执行前还会用JSCheckScriptSyntax做语法检查。入口层最大的设计亮点是全局对象被改造成一个「类查找器」代码量不多却是整个 JS 世界的门户。二、JSDefinition 四件套把 OC 对象「翻译」成 JS 对象这一组模块定义了四种 JS 类是 JS 与 OC 互转的基石全部位于 Source/Core/Runtime/JSDefinition模块文件职责JDClass4JSJDClass4JS.m把 OC 类包装成 JS 对象读取属性时通过 Runtime 查找类方法JDInstance4JSJDInstance4JS.h把 OC 实例包装成 JS 对象getProperty时走实例方法JDMethod4JSJDMethod4JS.h把 OC 方法包装成 JS 函数触发调用时进入桥接层JDPointer4JSJDPointer4JS.h封装原始指针让 JS 能持有 C 指针JDClass4JS 的实现很有代表性当 JS 访问MyClass.someMethod时它用NSSelectorFromStringJDFormatJSFunction把 JS 方法名转成 OC selector再通过class_getClassMethod找到方法返回一个 JDMethod4JS 包装对象。三、JDMethodBridgeJS 调用 OC 方法的中转站JDMethodBridge.h 是方法调用的「参数说明书」。它记录了方法签名NSMethodSignature用来解析返回值和参数类型selector 与 IMP 函数指针目标实例instance。当 JS 侧调用一个方法时桥接层会先解析每个参数的类型编码JDEncoding把 JS 值转换成对应的 OC 类型再用objc_msgSend或 FFI 完成真正的调用。四、JDFFIContext底层函数调用的发动机FFI这是整个项目技术含量最高的部分。目录 Source/Core/FFI 下内置了从ffi.h到ffi_arm64.h等多套 libffi 头文件及静态库 libffi.a。JDFFIContext.h 只暴露一个核心函数JDCallFunction(ctx, methodBridge, argumentCount, arguments);它的作用是在运行时动态构造函数调用根据JDMethodBridge里的签名信息用 libffi 把 JS 参数逐个转换成正确的 C 类型并压栈调用。这也是为什么 JSDebugger 能调用任意 OC 方法——它不依赖编译期绑定完全靠运行时描述。五、JDFunctionPlugin可插拔的 JS 能力扩展插件系统让调试器可以零侵入地扩展 JS 全局函数。核心代码在 JDFunctionPlugin.h 与 JDFunctionPlugin.m。用法极其优雅一个宏就能注册插件JD_REGISTER_PLUGIN(IMP, NAME)JDRegisterPlugin在load时自动把插件实例加入单例管理器registerPluginsIntoContext:把插件的function回调以key为名挂到 JS 全局对象上。项目内置了两个典型插件JDChoose.mm提供一个choose()全局函数用来按条件查找 OC 对象JDIntrospect.mm提供一个introspect()函数用来查看对象的类层级与结构。六、JDEncoding 与双向类型转换JS 与 OC 的「翻译官」JS 和 OC 的类型体系完全不同必须有一套双向转换规则JDEncoding.h解析 OC 类型编码如、i、{CGRect...}JDJSTypeToOCType.m把 JS 值number、string、object转成 OC 对象/C 结构体JDOCTypeToJSType.m把 OC 返回值转回 JS 值。加上工具类 JDNSStringFromJSString.m 负责 JSString 与 NSString 互转整条类型链路就闭环了。七、JDPropertyCache属性访问的高性能缓存JDPropertyCache.m 负责缓存类的属性信息。每次 JS 读取 OC 属性时如果都重新遍历class_copyPropertyList会非常慢缓存层把属性名与 getter/setter 的映射存起来第二次访问直接命中大幅提升调试体验。配套的 JDProperty.m 则封装单个属性的读取与写入逻辑。八、NSObjectJDRuntimeIntrospection一行代码打印对象全貌JDIntrospect 是一个 Objective-C 分类给所有 NSObject 增加了jd_logAllProperties方法可以一次性输出对象的所有属性值。这是新手理解 Runtime 自省Introspection的最佳入门代码。九、JDLocalFileObserverJS 脚本热更新目录 Source/FileWatcher 实现了文件监听JDLocalFileObserver.h监听指定 JS 文件文件变化时触发changeBlockJDLocalFilePresenter 配合完成文件的读取与分发。配合JDEngine的evaluateScriptAtPath:你可以在开发时改完 JS 文件立即生效不用重新编译 App这是它作为调试器最爽的体验之一。十、JDStruct 与 JDLog最后两块拼图JDStruct.m在start时注册常用的 C 结构体如 CGRect到 JS 环境让 JS 也能创建和解析结构体JDLog.mm统一日志输出所有调试信息都从这里打印。一次 JS 调用的完整旅程把上面模块串起来当你在 JS 里写[[UIApplication sharedApplication] delegate]时源码架构是这样运转的JDEngine的全局对象回调按名字UIApplication找到 OC 类JDClass4JS把类包装成 JS 对象方法访问返回JDMethod4JS真正调用时进入JDMethodBridge解析签名JDFFIContext用 libffi 动态完成 C 层函数调用返回值经JDOCTypeToJSType转回 JS 值交还给你。整个过程就是「类查找 → 对象包装 → 签名解析 → FFI 调用 → 类型回转」五个环节。总结给源码阅读者的三点建议从入口读起先读 JDEngine.m 的start和evaluateScript:建立全局观跟一条调用链用上面「一次 JS 调用的完整旅程」做主线从 JDClass4JS 一路追到 JDFFIContext对照 Demo 理解仓库自带 JSDebuggerDemo 工程和 demo.js 示例脚本边跑边读理解速度翻倍。想动手研究源码可以 clone 仓库https://gitcode.com/gh_mirrors/js/JSDebugger到本地配合 Xcode 打开 Demo 工程体验「JS 操控 OC」的魔力。掌握了这套源码架构你不仅能看懂 JSDebugger更能举一反三理解所有 JS 引擎嵌入式调试工具的设计思路。【免费下载链接】JSDebuggerJavaScript-Based Debugger For Inspecting Running State Of Your Application项目地址: https://gitcode.com/gh_mirrors/js/JSDebugger创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考