Skip to content

Commit

Permalink
fix: babel-plugin-minify-mangle-names default parameter error (#42)
Browse files Browse the repository at this point in the history
  • Loading branch information
j4k0xb committed Dec 31, 2023
1 parent 40d3eb0 commit fdf2137
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 6 deletions.
5 changes: 4 additions & 1 deletion packages/webcrack/src/ast-utils/matcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ import { Binding, NodePath } from '@babel/traverse';
import * as t from '@babel/types';
import * as m from '@codemod/matchers';

export const anyLiteral: m.Matcher<t.Literal> = m.matcher(
/**
* Matches any literal except for template literals with expressions (that could have side effects)
*/
export const safeLiteral: m.Matcher<t.Literal> = m.matcher(
(node) =>
t.isLiteral(node) &&
(!t.isTemplateLiteral(node) || node.expressions.length === 0),
Expand Down
4 changes: 2 additions & 2 deletions packages/webcrack/src/deobfuscate/merge-object-assignments.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Binding } from '@babel/traverse';
import * as t from '@babel/types';
import * as m from '@codemod/matchers';
import { Transform, anyLiteral, constObjectProperty } from '../ast-utils';
import { Transform, constObjectProperty, safeLiteral } from '../ast-utils';

/**
* Merges object assignments into the object expression.
Expand Down Expand Up @@ -109,7 +109,7 @@ function hasCircularReference(node: t.Node, binding: Binding) {
const inlineableObject: m.Matcher<t.Expression> = m.matcher((node) =>
m
.or(
anyLiteral,
safeLiteral,
m.arrayExpression(m.arrayOf(inlineableObject)),
m.objectExpression(m.arrayOf(constObjectProperty(inlineableObject))),
)
Expand Down
44 changes: 41 additions & 3 deletions packages/webcrack/src/transforms/mangle.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,41 @@
import traverse, { NodePath } from '@babel/traverse';
import { statement } from '@babel/template';
import traverse, { NodePath, Visitor, visitors } from '@babel/traverse';
import * as t from '@babel/types';
import mangle from 'babel-plugin-minify-mangle-names';
import { Transform } from '../ast-utils';
import { Transform, safeLiteral } from '../ast-utils';

// See https://github.com/j4k0xb/webcrack/issues/41 and https://github.com/babel/minify/issues/1023
const fixDefaultParamError: Visitor = {
Function(path) {
const { params } = path.node;

for (let i = params.length - 1; i >= 0; i--) {
const param = params[i];
if (!t.isAssignmentPattern(param) || safeLiteral.match(param.right))
continue;

if (!t.isBlockStatement(path.node.body)) {
path.node.body = t.blockStatement([t.returnStatement(path.node.body)]);
}

const body = path.get('body') as NodePath<t.BlockStatement>;
if (t.isIdentifier(param.left)) {
body.unshiftContainer(
'body',
statement`if (${param.left} === undefined) ${param.left} = ${param.right}`(),
);
} else {
const tempId = path.scope.generateUidIdentifier();
body.unshiftContainer(
'body',
statement`var ${param.left} = ${tempId} === undefined ? ${param.right} : ${tempId}`(),
);
param.left = tempId;
}
param.right = t.identifier('undefined');
}
},
};

export default {
name: 'mangle',
Expand All @@ -12,8 +46,12 @@ export default {
// eslint-disable-next-line @typescript-eslint/unbound-method
const { getSource } = NodePath.prototype;
NodePath.prototype.getSource = () => '';
const visitor = visitors.merge([
fixDefaultParamError,
mangle({ types: t, traverse }).visitor,
]);

traverse(ast, mangle({ types: t, traverse }).visitor, undefined, {
traverse(ast, visitor, undefined, {
opts: {
eval: true,
topLevel: true,
Expand Down
45 changes: 45 additions & 0 deletions packages/webcrack/test/mangle.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { test } from 'vitest';
import { testTransform } from '.';
import mangle from '../src/transforms/mangle';

const expectJS = testTransform(mangle);

// https://github.com/j4k0xb/webcrack/issues/41
test('rename default parameters of function', () => {
expectJS(`
function func(arg1, arg2 = 0, arg3 = arg1, arg4 = arg1) {
return arg1;
}
`).toMatchInlineSnapshot(`
function a(a, b = 0, c = undefined, d = undefined) {
if (c === undefined) c = a;
if (d === undefined) d = a;
return a;
}
`);
});

test('rename default parameters of arrow function', () => {
expectJS(`
const func = (arg1, arg2 = 0, arg3 = arg1, arg4 = arg1) => arg1;
`).toMatchInlineSnapshot(`
const a = (a, b = 0, c = undefined, d = undefined) => {
if (c === undefined) c = a;
if (d === undefined) d = a;
return a;
};
`);
});

test('rename default destructuring parameters', () => {
expectJS(`
function func(arg1, [arg2] = arg1) {
return arg2;
}
`).toMatchInlineSnapshot(`
function a(a, b = undefined) {
var [c] = b === undefined ? a : b;
return c;
}
`);
});

0 comments on commit fdf2137

Please sign in to comment.