From 39a70940bf566183283a9f90ba8197ef7bb1fe35 Mon Sep 17 00:00:00 2001 From: luojiyin Date: Mon, 7 Sep 2026 11:42:05 +0800 Subject: [PATCH] perf(source-map): lazy-build lineStarts in parseMdWithSourceMap computeLineStarts(md) was eagerly called on every parseMdWithSourceMap() invocation, but getRaw() never uses it. Defer to first use in getSourceRange() / getFieldSourceRange() via nullish coalescing assignment. For getRaw()-only callers this skips the full Markdown scan and number[] allocation entirely. --- src/source-map/build-source-map.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/source-map/build-source-map.ts b/src/source-map/build-source-map.ts index 038abac..676dd74 100644 --- a/src/source-map/build-source-map.ts +++ b/src/source-map/build-source-map.ts @@ -540,7 +540,7 @@ export const parseMdWithSourceMap = (md: string): ParsedMarkdownDocument => { }) as unknown as Root; const ast = tree as unknown as PositionedMarkdownRoot; - const lineStarts = computeLineStarts(md); + let lineStarts: number[] | undefined; // The index records ownership and parse-time state for all nodes. // It also builds mappings that the parser extension cannot produce. @@ -707,6 +707,7 @@ export const parseMdWithSourceMap = (md: string): ParsedMarkdownDocument => { } assertUnmodified(node as object); validateBounds(node.value.length); + lineStarts ??= computeLineStarts(md); return resolveSegmentRange({ segments: segs, valueLength: node.value.length, @@ -750,6 +751,7 @@ export const parseMdWithSourceMap = (md: string): ParsedMarkdownDocument => { } assertUrlUnmodified(node as object); validateBounds(node.url.length); + lineStarts ??= computeLineStarts(md); return resolveSegmentRange({ segments: segs, valueLength: node.url.length,