惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

The GitHub Blog
The GitHub Blog
Google Online Security Blog
Google Online Security Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
酷 壳 – CoolShell
酷 壳 – CoolShell
Y
Y Combinator Blog
L
LangChain Blog
博客园_首页
云风的 BLOG
云风的 BLOG
博客园 - 叶小钗
月光博客
月光博客
S
Schneier on Security
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
C
CXSECURITY Database RSS Feed - CXSecurity.com
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
D
DataBreaches.Net
Vercel News
Vercel News
P
Privacy International News Feed
D
Darknet – Hacking Tools, Hacker News & Cyber Security
C
Cyber Attacks, Cyber Crime and Cyber Security
J
Java Code Geeks
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
人人都是产品经理
人人都是产品经理
G
GRAHAM CLULEY
有赞技术团队
有赞技术团队
A
Arctic Wolf
I
InfoQ
T
Tor Project blog
Attack and Defense Labs
Attack and Defense Labs
Microsoft Security Blog
Microsoft Security Blog
博客园 - 司徒正美
K
Kaspersky official blog
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Recent Announcements
Recent Announcements
D
Docker
TaoSecurity Blog
TaoSecurity Blog
G
Google Developers Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
爱范儿
爱范儿
T
Troy Hunt's Blog
Help Net Security
Help Net Security
量子位
罗磊的独立博客
C
Cisco Blogs
Hacker News - Newest:
Hacker News - Newest: "LLM"
博客园 - 【当耐特】
腾讯CDC
Webroot Blog
Webroot Blog
N
News and Events Feed by Topic
小众软件
小众软件
N
Netflix TechBlog - Medium

博客园 - 悠哉大斌

AI Agent 安全沙箱技术对比:E2B、Cube Sandbox 与 Docker Sandboxes linux 升级 claude code的坑 debian(WSL) apt 代理配置 linux内核之Namespaces、Cgroups、Capabilities、Seccomp和Landlock 大语言模型推理中的隐藏瓶颈及其解决方法 Docker Sandboxes 技术是什么,和docker容器有什么区别 什么是 Docker Agent以及一个Docker Agent示例 windows wsl 安装 Temurin® JDK claude Code 和 codex 作为编程代理,前者使用typescript开发,后者使用rust,他们的决策依据是什么 Java 并发编程发展史与 java.util.concurrent 全景解析 LLM 真的改变了编码风格吗? 如果人工智能会犯错且不精确,为什么它正在改变世界? Python 的协程模型和 JavaScript 的 async/await python闭包和function.__closure__特殊属性 python 的 dunder name和 sunder name 基于nodejs设计REST API的知名开源框架 windows上使用node-oracledb Thick 模式连接 Oracle 11g Claude Code CLI连接 DeepSeek V4模型后调用报400错误 python里对象(object)到底是什么 Python 泛型演变史 Python 类型别名的演变 Python 类型提示的演变史 PEP 593 新增的Annotated 类型 Alibaba AgentScope 和 microsoft agent framework 详细对比分析 spring AI Alibaba Agent Framework 和 agentscope有什么区别和联系 AI Agent协作模式以及主流开源框架对协作模式的支持 Tailscale 是如何接管 DNS 的? Agent = Model + Harness TypeScript/JavaScript 中的异步迭代语句 js中的生成器函数 Tailscale Serve and Funnel openclaw gateway的网络绑定模式 websocket协议和http协议有何依赖关系? MCP通信的双方是谁? claude code MCP 安装范围 如何在wsl2环境下给claude code cli 配置 playwright-mcp wsl的网络模式有哪几种,有哪些区别? AI Agent memory是什么? ai agent skills是什么? Go测试生态系统工具与最佳实践深度调研(聚焦认证授权系统) 线性代数中常见矩阵类型的概念关系思维导图 三种主流授权策略
使用rust编写typescript编译器的难点在什么地方,哪些数据结构是rust不擅长的?
悠哉大斌 · 2026-02-12 · via 博客园 - 悠哉大斌

用Rust写TS编译器总体可行(SWC已证明),但确实有特定痛点和“反直觉”的数据结构。下面拆解为“Rust不擅长的数据结构”和“TS编译器架构难点”两个层面:

一、Rust绝对不擅长:带环/共享可变的数据结构
这是编译器最难、最绕不开的坎。TS源码本质是(AST节点多父引用、符号表循环引用),而Rust所有权是,直接冲突:

  • 双向链接结构:安全Rust写双向链表是本科难题但被称为“噩梦”级。用 Rc<RefCell<...>> 能糊但性能差且极易运行时panic(borrow()冲突);改用index(竞技场)或unsafe裸指针才是工程常态。
  • 图与任意循环:类型定义互相引用(A->B, B->A)、带父指针的AST。Rust无GC,学术界都承认这是顽疾,靠纯Rc会内存泄漏,需手动破环或Weak。
  • 共享所有权:多个分析阶段共用一个节点并可能修改。C++直接指针,Rust必须套Rc<RefCell>导致代码里全是.borrow_mut(),臃肿且心智负担重。

二、TS编译器架构的具体难点(不止是数据结构)

  • 生命周期与自引用:词法环境需引用自身。若用&引用,Rust会卡死在自反结构上(无法构造);最终要么全用arena(typed-arena)分配后存索引,要么用pin
  • 增量编译与持久化缓存:TS支持--watch,难点不是代码逻辑,而是如何把Rust内存结构序列化存盘。图结构反序列化后要恢复完整引用,极难处理(主流方案偏向存计算hash而非存AST)。
  • 中间层类型擦除:写通用分析时想存“要么是标识符要么是字面量”,C++用std::variant,Rust枚举极强但无法向上转型。若定义enum AstNode { Expr(Expr), Stmt(Stmt) },传入具体Expr时无法直接塞进这个枚举,必须手动wrap,大量样板。
  • 原地修改/压缩:优化阶段如“常量折叠”,C++习惯覆写节点(变长变短)。Rust借用检查器不允许你持有引用时乱改内存,若强求极省内存则非常别扭。

三、速判:到底能不能忍?
。SWC证明了Rust写TS解析器+转换器可达“最快之一”。但心态要切换:不要试图在安全Rust里精妙建模“完美的共享图”,该用usize下标时就用,该写unsafe封装内部可变性时就写,用C++思维强套安全Rust只会崩溃。


Rolldown背后的Oxc

Rolldown之所以能“躲开”所有权地狱,正是因为它站在Oxc肩上。Oxc parser + semantic喂给它的是已经算好的、干净的结构,而Oxc semantic自己,正面撞上了你第一轮提的所有雷区。

一、Oxc semantic干了什么?

看文档就明白了:符号表、作用域树、引用跟踪、控制流图。这正是TypeScript编译器最核心的语义分析层,也是Rust所有权模型最讨厌的“带环共享图”。它不是“只解析”,而是真正维护了全程序的变量绑定关系——哪个标识符是声明、哪个是引用、作用域怎么嵌套、闭包捕获了谁。

二、它是怎么在Rust里活下来的?

关键技巧:用索引代替指针,用arena控制生命周期。

Oxc semantic的核心数据结构长这样:SymbolTable就是一个大仓库,里面全是VecHashMap;查询不靠引用,靠SymbolIdReferenceId这两个整数下标。AST节点里存的不是指针,是Cell<Option<ReferenceId>>。ScopeId是u32的包装。

这正是我第一轮说的“该用下标就用下标,该写unsafe就写”的现实范本。他们把图拍平了存进连续数组,所有权归arena统一管理,节点之间只存整数ID。没有共享所有权,只有共享索引

三、更狠的:连AST设计都在给借用检查器“减负”

Oxc parser明确说:我们不用estree,因为estree节点太模糊。他们自己手写了BindingIdentifierIdentifierReferenceIdentifierName三个完全不同的类型。

这不是为了“规范”,这是为了让类型系统替你保证“不会把表达式节点当声明节点用”。你之前问的“无法向上转型”痛点,Oxc的解法是根本不转——没有泛型父节点,每条路径都是具体的、已知的。编译期就定死。

四、性能压榨到了“作弊”级别

他们为了省一次HashMap扩容,会先遍历一遍AST数清楚每个作用域有几个变量,然后把计数临时塞进scope_id字段(反正第一遍时这个字段是空的),第二遍再用这个数字预分配容量。

这是典型的“Rust工业代码”——不追求完美抽象,能跑、够快就是赢。

五、所以,Oxc是“TS编译器”吗?

不是完全的,但非常接近了。

Oxc semantic能做作用域分析、符号解析、引用跟踪,这是编译器后端的语义模型层。它缺的是真正的类型推导和类型检查——类型兼容性、泛型实例化、条件类型展开这些微软Go版tsc的核心逻辑。

Oxlint现在实现类型感知linting,方式是包装并调用Go版tsc,不是自己重写。这是个极其务实的选择:把自己不擅长的“类型代数”外包,只做自己擅长的“图遍历+模式匹配”

给你的结论:

你直觉是对的。Oxc确实干了“最复杂”的那部分——所有Rust不擅长的共享图结构,它全扛了,而且用索引+arena+预遍历+unsafe封装,扛得极其漂亮

它不是“绕过”了问题,是正面击穿了问题。这才是Oxc在Rust生态里真正牛逼的地方。