7/26/2024, 7:51:53 PM
说来惭愧,工作这么久一直是伸手党,最近解决工作中突发 bug,才有机会第一次参与开源组件的贡献。
事情经过比较简单,升级开源组件marked
到 最新 13 版本之后,突然线上收到了"Maximum call stack size exceeded"的错误日志,废了一点时间才发现是作者为了兼容老的行为,不小心引入了一种类似递归爆栈的 bug。比较难复现,兼容写法,累积执行很多次才会报错。
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); }
定位到了 bug,提了 issue 就下班了。。。
回去洗完澡觉得既然已经发现问题了,应该直接帮忙修复呀,第二天才修复完提交了 pull request,review 一次,再次修复就算过了。也算对这个行当做了点小小贡献。
最终发布 V13.0.3 版本。
最后,错误大致是类似下面的写法导致的,大家可以发现么?哈哈(≧ω≦)
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) } }