Repository navigation
Fix #5: handle chained-call strip edge cases safely - #12
Conversation
Add chainedCalls policy (skip, warn, error) and line-aware call stripping so member/call chains after a target call are not removed in ways that would break runtime.
| } | ||
|
|
||
| return output; | ||
| function stripConfiguredCallExpressions( |
There was a problem hiding this comment.
Added in 4cbeceb — I added JSDoc for stripConfiguredCallExpressions and analyzeCallExpressionLine to describe responsibilities and behavior.
| chainedCalls: ChainedCallsPolicy, | ||
| moduleId: string | ||
| ): string { | ||
| const lines = code.split(/\r?\n/); |
There was a problem hiding this comment.
please leave high level comments through the body of stripConfiguredCallExpressions, explaining meaning of parts of the code
There was a problem hiding this comment.
Done in 4cbeceb — I added high-level inline comments through stripConfiguredCallExpressions explaining line-pass processing, per-function matching, safe-removal path, chained policy path, and line retention.
| const escaped = escapeRegExp(fn); | ||
| const pattern = new RegExp(`^[ \\t]*${escaped}\\s*\\([^\\n\\r;]*\\)\\s*;?[ \\t]*\\r?\\n?`, "gm"); | ||
| output = output.replace(pattern, ""); | ||
| function analyzeCallExpressionLine(line: string, fn: string): { matched: boolean; safeRemove: boolean } { |
There was a problem hiding this comment.
jsdoc for this and high level comments in the function body
There was a problem hiding this comment.
Added in 4cbeceb — analyzeCallExpressionLine now has JSDoc and I added body-level high-level comments for both analysis and stripping flow.
There was a problem hiding this comment.
there is no high-level comments in this function body
There was a problem hiding this comment.
Addressed in 385680c — I added short step-by-step comments inside analyzeCallExpressionLine (indent check, call shape, paren walk, tail check) so the body reads at a glance.
There was a problem hiding this comment.
Fixed in 385680c — added step-by-step comments inside analyzeCallExpressionLine (indent, call shape, paren walk, tail/safe-remove check).
| const pattern = new RegExp(`^[ \\t]*${escaped}\\s*\\([^\\n\\r;]*\\)\\s*;?[ \\t]*\\r?\\n?`, "gm"); | ||
| output = output.replace(pattern, ""); | ||
| function analyzeCallExpressionLine(line: string, fn: string): { matched: boolean; safeRemove: boolean } { | ||
| const wsMatch = /^[ \t]*/.exec(line); |
There was a problem hiding this comment.
not sure what the ws prefix on these variables mean
There was a problem hiding this comment.
Good call — updated in 4cbeceb. I renamed wsMatch / wsLen to leadingWhitespaceMatch / leadingWhitespaceLength for clarity.
| function findClosingParen(line: string, openParenIndex: number): number { | ||
| let depth = 0; | ||
| for (let i = openParenIndex; i < line.length; i += 1) { | ||
| const c = line[i]; |
There was a problem hiding this comment.
more semantic variable names
There was a problem hiding this comment.
Updated in 385680c — renamed locals in analyzeCallExpressionLine (openingParenIndex, closingParenIndex, remainderAfterCall) and added the inline step comments so intent is clearer.
Add JSDoc and high-level inline comments for call-expression analysis and stripping flow, and rename whitespace-prefixed variables for clarity.
| /** | ||
| * When a configured call is not a whole statement (e.g. `fn().chain()`), | ||
| * stripping would break runtime. Controls behavior for those lines. | ||
| * @default "skip" | ||
| */ |
There was a problem hiding this comment.
don't need this comment in the interface, find another place for it possibly, or just delete it
There was a problem hiding this comment.
Done in 385680c — removed the block comment from StripOptions and documented behavior on the ChainedCallsPolicy type instead (same text, better home for public API docs).
Move chainedCalls documentation to ChainedCallsPolicy, add step comments inside analyzeCallExpressionLine, and use clearer local variable names.
Summary
)for the configured call.;after the call).chainedCallsoption:skip(default),warn(console.warn), orerror(throws fromtransform) when a line matches a configured call but has trailing code after the call (chains like.then, or other expressions).Issues
How to test
npm run checknpm run buildNotes
console.warntoday; wiring to Rolldown/Rollupthis.warncan follow if we extend the transform signature.Learning notes
Fail-safe default for destructive transforms
What it is
When a build transform can change runtime behavior, the default policy should be the least surprising: do nothing ambiguous rather than emit broken code.
Where it appears in this PR
src/index.ts—chainedCallsdefaults toskip, so ambiguous lines are left unchanged unless the user opts intowarnorerror.Why it was the right call here
The alternative default is aggressive stripping (e.g. turning
fn().chaininto invalid or throwing code). Defaultskipmatches the sharp-edge story from@rollup/plugin-stripand keeps production builds safe until the user explicitly chooses stricter behavior.Optional mini snippet (when helpful)
If you want to go deeper
Search: "defensive defaults" and "parse vs replace for code transforms".