Skip to content

Commit 90c6d1b

Browse files
authored
[compiler][snap] More minimization improvements (#35689)
* A few new minimization strategies, removing function params and array/object pattern elements * Ensure that we preserve the same set of errors based on not just category+reason but also description.
1 parent f84ce5a commit 90c6d1b

File tree

1 file changed

+133
-3
lines changed

1 file changed

+133
-3
lines changed

compiler/packages/snap/src/minimize.ts

Lines changed: 133 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ type CompileSuccess = {kind: 'success'};
1818
type CompileParseError = {kind: 'parse_error'; message: string};
1919
type CompileErrors = {
2020
kind: 'errors';
21-
errors: Array<{category: string; reason: string}>;
21+
errors: Array<{category: string; reason: string; description: string | null}>;
2222
};
2323
type CompileResult = CompileSuccess | CompileParseError | CompileErrors;
2424

@@ -70,7 +70,11 @@ function compileAndGetError(
7070
return {kind: 'success'};
7171
} catch (e: unknown) {
7272
const error = e as Error & {
73-
details?: Array<{category: string; reason: string}>;
73+
details?: Array<{
74+
category: string;
75+
reason: string;
76+
description: string | null;
77+
}>;
7478
};
7579
// Check if this is a CompilerError with details
7680
if (error.details && error.details.length > 0) {
@@ -79,6 +83,7 @@ function compileAndGetError(
7983
errors: error.details.map(detail => ({
8084
category: detail.category,
8185
reason: detail.reason,
86+
description: detail.description,
8287
})),
8388
};
8489
}
@@ -89,6 +94,7 @@ function compileAndGetError(
8994
{
9095
category: error.name ?? 'Error',
9196
reason: error.message,
97+
description: null,
9298
},
9399
],
94100
};
@@ -108,7 +114,8 @@ function errorsMatch(a: CompileErrors, b: CompileResult): boolean {
108114
for (let i = 0; i < a.errors.length; i++) {
109115
if (
110116
a.errors[i].category !== b.errors[i].category ||
111-
a.errors[i].reason !== b.errors[i].reason
117+
a.errors[i].reason !== b.errors[i].reason ||
118+
a.errors[i].description !== b.errors[i].description
112119
) {
113120
return false;
114121
}
@@ -217,6 +224,45 @@ function* removeCallArguments(ast: t.File): Generator<t.File> {
217224
}
218225
}
219226

227+
/**
228+
* Generator that yields ASTs with function parameters removed one at a time
229+
*/
230+
function* removeFunctionParameters(ast: t.File): Generator<t.File> {
231+
// Collect all functions with parameters
232+
const funcSites: Array<{funcIndex: number; paramCount: number}> = [];
233+
let funcIndex = 0;
234+
t.traverseFast(ast, node => {
235+
if (t.isFunction(node) && node.params.length > 0) {
236+
funcSites.push({funcIndex, paramCount: node.params.length});
237+
funcIndex++;
238+
}
239+
});
240+
241+
// For each function, try removing each parameter (from end to start)
242+
for (const {funcIndex: targetFuncIdx, paramCount} of funcSites) {
243+
for (let paramIdx = paramCount - 1; paramIdx >= 0; paramIdx--) {
244+
const cloned = cloneAst(ast);
245+
let idx = 0;
246+
let modified = false;
247+
248+
t.traverseFast(cloned, node => {
249+
if (modified) return;
250+
if (t.isFunction(node) && node.params.length > 0) {
251+
if (idx === targetFuncIdx && paramIdx < node.params.length) {
252+
node.params.splice(paramIdx, 1);
253+
modified = true;
254+
}
255+
idx++;
256+
}
257+
});
258+
259+
if (modified) {
260+
yield cloned;
261+
}
262+
}
263+
}
264+
}
265+
220266
/**
221267
* Generator that simplifies call expressions by replacing them with their arguments.
222268
* For single argument: foo(x) -> x
@@ -1566,6 +1612,84 @@ function* removeObjectProperties(ast: t.File): Generator<t.File> {
15661612
}
15671613
}
15681614

1615+
/**
1616+
* Generator that removes elements from array destructuring patterns one at a time
1617+
*/
1618+
function* removeArrayPatternElements(ast: t.File): Generator<t.File> {
1619+
// Collect all array patterns with elements
1620+
const patternSites: Array<{patternIndex: number; elementCount: number}> = [];
1621+
let patternIndex = 0;
1622+
t.traverseFast(ast, node => {
1623+
if (t.isArrayPattern(node) && node.elements.length > 0) {
1624+
patternSites.push({patternIndex, elementCount: node.elements.length});
1625+
patternIndex++;
1626+
}
1627+
});
1628+
1629+
// For each pattern, try removing each element (from end to start)
1630+
for (const {patternIndex: targetPatternIdx, elementCount} of patternSites) {
1631+
for (let elemIdx = elementCount - 1; elemIdx >= 0; elemIdx--) {
1632+
const cloned = cloneAst(ast);
1633+
let idx = 0;
1634+
let modified = false;
1635+
1636+
t.traverseFast(cloned, node => {
1637+
if (modified) return;
1638+
if (t.isArrayPattern(node) && node.elements.length > 0) {
1639+
if (idx === targetPatternIdx && elemIdx < node.elements.length) {
1640+
node.elements.splice(elemIdx, 1);
1641+
modified = true;
1642+
}
1643+
idx++;
1644+
}
1645+
});
1646+
1647+
if (modified) {
1648+
yield cloned;
1649+
}
1650+
}
1651+
}
1652+
}
1653+
1654+
/**
1655+
* Generator that removes properties from object destructuring patterns one at a time
1656+
*/
1657+
function* removeObjectPatternProperties(ast: t.File): Generator<t.File> {
1658+
// Collect all object patterns with properties
1659+
const patternSites: Array<{patternIndex: number; propCount: number}> = [];
1660+
let patternIndex = 0;
1661+
t.traverseFast(ast, node => {
1662+
if (t.isObjectPattern(node) && node.properties.length > 0) {
1663+
patternSites.push({patternIndex, propCount: node.properties.length});
1664+
patternIndex++;
1665+
}
1666+
});
1667+
1668+
// For each pattern, try removing each property (from end to start)
1669+
for (const {patternIndex: targetPatternIdx, propCount} of patternSites) {
1670+
for (let propIdx = propCount - 1; propIdx >= 0; propIdx--) {
1671+
const cloned = cloneAst(ast);
1672+
let idx = 0;
1673+
let modified = false;
1674+
1675+
t.traverseFast(cloned, node => {
1676+
if (modified) return;
1677+
if (t.isObjectPattern(node) && node.properties.length > 0) {
1678+
if (idx === targetPatternIdx && propIdx < node.properties.length) {
1679+
node.properties.splice(propIdx, 1);
1680+
modified = true;
1681+
}
1682+
idx++;
1683+
}
1684+
});
1685+
1686+
if (modified) {
1687+
yield cloned;
1688+
}
1689+
}
1690+
}
1691+
}
1692+
15691693
/**
15701694
* Generator that simplifies assignment expressions (a = b) -> a or b
15711695
*/
@@ -1852,8 +1976,14 @@ function* simplifyIdentifiersRenameRef(ast: t.File): Generator<t.File> {
18521976
const simplificationStrategies = [
18531977
{name: 'removeStatements', generator: removeStatements},
18541978
{name: 'removeCallArguments', generator: removeCallArguments},
1979+
{name: 'removeFunctionParameters', generator: removeFunctionParameters},
18551980
{name: 'removeArrayElements', generator: removeArrayElements},
18561981
{name: 'removeObjectProperties', generator: removeObjectProperties},
1982+
{name: 'removeArrayPatternElements', generator: removeArrayPatternElements},
1983+
{
1984+
name: 'removeObjectPatternProperties',
1985+
generator: removeObjectPatternProperties,
1986+
},
18571987
{name: 'removeJSXAttributes', generator: removeJSXAttributes},
18581988
{name: 'removeJSXChildren', generator: removeJSXChildren},
18591989
{name: 'removeJSXFragmentChildren', generator: removeJSXFragmentChildren},

0 commit comments

Comments
 (0)