Skip to content

Commit c87898c

Browse files
BenBen
authored andcommitted
fix(verbose): don't replace verbose:X with verbose:true in destructure
Commit 23e65fb broadened verboseProperty to match CC 2.1.113's new shape where spinner props are a destructured function parameter. The replacement 'verbose:true' is a SyntaxError in that context — you can't use a literal as a destructure binding target. cli.js fails to parse with 'Invalid destructuring assignment target' (node) or 'Expected CommonJS module to have a function wrapper' (bun). For createElement object-literal context (older CC): keep the original replacement. For destructured-param context: leave the destructure alone and inject 'Y=!0;' at the start of the function body, forcing the local variable true regardless of caller.
1 parent 3c08e0c commit c87898c

1 file changed

Lines changed: 53 additions & 41 deletions

File tree

src/patches/verboseProperty.ts

Lines changed: 53 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,72 @@
11
// Please see the note about writing patches in ./index
22

3-
import { LocationResult, showDiff } from './index';
3+
import { showDiff } from './index';
44

5-
const getVerbosePropertyLocation = (oldFile: string): LocationResult | null => {
6-
// Older CC shape: createElement(X, {...spinnerTip...overrideMessage...})
5+
interface VerboseEdit {
6+
startIndex: number;
7+
endIndex: number;
8+
replacement: string;
9+
}
10+
11+
const getVerbosePropertyEdit = (oldFile: string): VerboseEdit | null => {
12+
// Older CC shape: createElement(X, {...spinnerTip...overrideMessage...}).
13+
// Here, `verbose:X` is an object-literal value and can be safely replaced
14+
// with the literal `verbose:true`.
715
const createElementPattern =
816
/createElement\([$\w]+,\{[^}]+spinnerTip[^}]+overrideMessage[^}]+\}/;
9-
// CC >= 2.1.113: the spinner component receives its props as a destructured
10-
// function parameter rather than a createElement object literal, and
11-
// spinnerTip is no longer on the same object (it's pulled from state
12-
// separately). Anchor on overrideMessage + verbose instead.
13-
const destructurePattern =
14-
/\{[^{}]{0,400}overrideMessage:[$\w]+,[^{}]{0,200}verbose:[^,}]+[^{}]{0,200}\}/;
15-
16-
const createElementMatch =
17-
oldFile.match(createElementPattern) || oldFile.match(destructurePattern);
18-
19-
if (!createElementMatch || createElementMatch.index === undefined) {
20-
console.error(
21-
'patch: verbose: failed to find spinner props containing overrideMessage and verbose'
22-
);
23-
return null;
17+
const objLitMatch = oldFile.match(createElementPattern);
18+
if (objLitMatch && objLitMatch.index !== undefined) {
19+
const verboseMatch = objLitMatch[0].match(/verbose:[^,}]+/);
20+
if (!verboseMatch || verboseMatch.index === undefined) {
21+
console.error('patch: verbose: failed to find verbose property');
22+
return null;
23+
}
24+
const start = objLitMatch.index + verboseMatch.index;
25+
return {
26+
startIndex: start,
27+
endIndex: start + verboseMatch[0].length,
28+
replacement: 'verbose:true',
29+
};
2430
}
2531

26-
const extractedString = createElementMatch[0];
27-
28-
const verbosePattern = /verbose:[^,}]+/;
29-
const verboseMatch = extractedString.match(verbosePattern);
30-
31-
if (!verboseMatch || verboseMatch.index === undefined) {
32-
console.error('patch: verbose: failed to find verbose property');
33-
return null;
32+
// CC >= 2.1.113: props are a destructured function parameter
33+
// function X({...,overrideMessage:z,spinnerSuffix:M,verbose:Y,...}){...}
34+
// Replacing `verbose:Y` with `verbose:true` is a SyntaxError in this
35+
// context (the right-hand side of a destructure binding must be an
36+
// assignment target, not a literal). Instead: leave the destructure alone
37+
// and inject `Y=!0;` at the start of the function body so the local
38+
// variable is always forced true regardless of caller.
39+
const destructurePattern =
40+
/\{[^{}]{0,400}overrideMessage:[$\w]+,[^{}]{0,200}verbose:([$\w]+)[^{}]{0,200}\}\)\{/;
41+
const destructureMatch = oldFile.match(destructurePattern);
42+
if (destructureMatch && destructureMatch.index !== undefined) {
43+
const varName = destructureMatch[1];
44+
// Position right after the `){` that opens the function body
45+
const bodyStart = destructureMatch.index + destructureMatch[0].length;
46+
return {
47+
startIndex: bodyStart,
48+
endIndex: bodyStart,
49+
replacement: `${varName}=!0;`,
50+
};
3451
}
3552

36-
// Calculate absolute positions in the original file
37-
const absoluteVerboseStart = createElementMatch.index + verboseMatch.index;
38-
const absoluteVerboseEnd = absoluteVerboseStart + verboseMatch[0].length;
39-
40-
return {
41-
startIndex: absoluteVerboseStart,
42-
endIndex: absoluteVerboseEnd,
43-
};
53+
console.error(
54+
'patch: verbose: failed to find spinner props containing overrideMessage and verbose'
55+
);
56+
return null;
4457
};
4558

4659
export const writeVerboseProperty = (oldFile: string): string | null => {
47-
const location = getVerbosePropertyLocation(oldFile);
48-
if (!location) {
60+
const edit = getVerbosePropertyEdit(oldFile);
61+
if (!edit) {
4962
return null;
5063
}
5164

52-
const newCode = 'verbose:true';
5365
const newFile =
54-
oldFile.slice(0, location.startIndex) +
55-
newCode +
56-
oldFile.slice(location.endIndex);
66+
oldFile.slice(0, edit.startIndex) +
67+
edit.replacement +
68+
oldFile.slice(edit.endIndex);
5769

58-
showDiff(oldFile, newFile, newCode, location.startIndex, location.endIndex);
70+
showDiff(oldFile, newFile, edit.replacement, edit.startIndex, edit.endIndex);
5971
return newFile;
6072
};

0 commit comments

Comments
 (0)