---
title: "记一次开源贡献"
description: "说来惭愧，工作这么久一直是伸手党，最近解决工作中突发 bug，才有机会第一次参与开源组件的贡献。"
url: "https://hicc.pro/p/bf/first-pull-request"
author: "tyler wang"
published: "2024-07-26T11:51:53.000Z"
updated: "2025-12-14T07:35:25.000Z"
category: "Front End"
tags:
  - "开源贡献"
  - "markedjs"
image: "https://image.hicc.pro/pro/20240726201724FgUWKF5EnqHWY5B1nWq3rQyH6TWqmy3cVXAvtZoUjWY65qdPN.jpg"
lang: "zh-CN"
site: "Hipo日志"
---

# 记一次开源贡献

说来惭愧，工作这么久一直是伸手党，最近解决工作中突发 bug，才有机会第一次参与开源组件的贡献。

事情经过比较简单，升级开源组件[`marked`](https://github.com/markedjs/marked)到 最新 13 版本之后，突然线上收到了"Maximum call stack size exceeded"的错误日志，废了一点时间才发现是作者为了兼容老的行为，不小心引入了一种类似递归爆栈的 bug。比较难复现，兼容写法，累积执行很多次才会报错。

```js
const marked = require('marked')

const content = '\n## 1. some title\n\nsimple content'

marked.use({
	renderer: {
		heading(text, level) {
			const escapedText = encodeURIComponent(text).replaceAll('%', '.');
			return `<h${level} id="${escapedText}">
									${text}
					</h${level}>`;
					
		},
	},
});

for (const _ of new Array(10000).fill(0)) {
	marked.parse(content);
}
```

![](https://image.hicc.pro/pro/20240726202349Fp6uymKV6Tn-73kBaKEUoxmKR21KG65KjlQpDBWom2hBWxNPQ.png)

定位到了 bug，提了 [issue](https://github.com/markedjs/marked/issues/3379) 就下班了。。。

回去洗完澡觉得既然已经发现问题了，应该直接帮忙修复呀，第二天才修复完提交了 [pull request](https://github.com/markedjs/marked/pull/3380)，review 一次，再次修复就算过了。也算对这个行当做了点小小贡献。

![](https://image.hicc.pro/pro/20240726202814FqROvysBOO7aEAL0-WkODbXiY5TP0EXGpeDJJ8ATZqu2ENMfg.png)

最终发布 [V13.0.3](https://github.com/markedjs/marked/releases/tag/v13.0.3) 版本。

![](https://image.hicc.pro/pro/20240729101822FuPw0iDtKps8lF_GuxpqISbk8h9H2qHD0KADjBHopXfUTsPUH.png)

***

最后，错误大致是类似下面的写法导致的，大家可以发现么？哈哈(≧ω≦)

```js
const marked = {
	renderer:{},
	use({renderer}){
		let renderFun = renderer.heading;
		this.renderer.heading = (...args) => {
			renderFun = this.convertRendererFunction(renderer.heading)
			return renderFun.apply(renderer,args)
		}
	},
	convertRendererFunction(func) {
		return (token) => func.call(this, token)
	},
	parse(txt) {
		return this.renderer.heading(txt)
	}
}

marked.use({
	renderer:{
		heading(text) {
			return text + 1
		}
	}
});
for (const _ of new Array(1000000).fill(0)) {
	try {
		marked.parse('11')
	} catch(e) {
		console.log(e)
	}
}
```

---

原文 / Source: <https://hicc.pro/p/bf/first-pull-request>
