Skip to content

Commit

Permalink
add keepClassName as separate options (fix #298) (#311)
Browse files Browse the repository at this point in the history
* add keepClassName as separate options (fix #298)

* remove options test

* add keepClassName tests back
  • Loading branch information
vigneshshanmugam authored and kangax committed Dec 5, 2016
1 parent a0922fc commit b8bac37
Show file tree
Hide file tree
Showing 9 changed files with 98 additions and 17 deletions.
Expand Up @@ -69,3 +69,4 @@ require("babel-core").transform("code", {

+ `keepFnName` - prevent plugin from removing function name. Useful for code depending on `fn.name`
+ `keepFnArgs` - prevent plugin from removing function args. Useful for code depending on `fn.length`
+ `keepClassName` - prevent mangler from altering class names.
Expand Up @@ -1292,12 +1292,12 @@ describe("dce-plugin", () => {
expect(transform(source)).toBe(expected);
});

it("should preserve fn/class names when keepFnName is true", () => {
it("should preserve fn names when keepFnName is true", () => {
const source = unpad(`
(function () {
function A() {}
exports.A = A;
var B = class B {};
var B = function B() {};
exports.B = B;
onClick(function C() {});
})();
Expand All @@ -1306,13 +1306,34 @@ describe("dce-plugin", () => {
(function () {
exports.A = function A() {};
exports.B = class B {};
exports.B = function B() {};
onClick(function C() {});
})();
`);
expect(transform(source, { keepFnName: true })).toBe(expected);
});

it("should preserve class names when keepClassName is true", () => {
const source = unpad(`
(function () {
class A {}
exports.A = A;
var B = class B {};
exports.B = B;
class AA {} new AA()
})();
`);
const expected = unpad(`
(function () {
exports.A = class A {};
exports.B = class B {};
new class AA {}();
})();
`);
expect(transform(source, { keepClassName: true })).toBe(expected);
});

// NCE = Named Class Expressions
it("should remove name from NCE", () => {
const source = unpad(`
Expand Down
11 changes: 10 additions & 1 deletion packages/babel-plugin-minify-dead-code-elimination/src/index.js
Expand Up @@ -636,12 +636,19 @@ module.exports = ({ types: t, traverse }) => {

// Remove named function expression name. While this is dangerous as it changes
// `function.name` all minifiers do it and hence became a standard.
"FunctionExpression|ClassExpression"(path) {
"FunctionExpression"(path) {
if (!this.keepFnName) {
removeUnreferencedId(path);
}
},

// remove class names
"ClassExpression"(path) {
if (!this.keepClassName) {
removeUnreferencedId(path);
}
},

// Put the `var` in the left if feasible.
ForInStatement(path) {
const left = path.get("left");
Expand Down Expand Up @@ -696,6 +703,7 @@ module.exports = ({ types: t, traverse }) => {
// set defaults
optimizeRawSize = false,
keepFnName = false,
keepClassName = false,
keepFnArgs = false,
} = {}
} = {}) {
Expand All @@ -707,6 +715,7 @@ module.exports = ({ types: t, traverse }) => {
functionToBindings: new Map(),
optimizeRawSize,
keepFnName,
keepClassName,
keepFnArgs,
});
}
Expand Down
1 change: 1 addition & 0 deletions packages/babel-plugin-minify-mangle-names/README.md
Expand Up @@ -71,3 +71,4 @@ require("babel-core").transform("code", {
+ `blacklist` - A plain JS Object with keys as identifier names and values indicating whether to exclude
+ `eval` - mangle identifiers in scopes accessible by eval
+ `keepFnName` - prevent mangler from altering function names. Useful for code depending on `fn.name`
+ `keepClassName` - prevent mangler from altering class names.
Expand Up @@ -756,11 +756,9 @@ describe("mangle-names", () => {
expect(actual).toBe(expected);
});

it("should NOT mangle functions & classes when keepFnName is true", () => {
it("should NOT mangle functions when keepFnName is true", () => {
const source = unpad(`
(function() {
class Foo {}
const Bar = class Bar extends Foo {}
var foo = function foo() {
foo();
}
Expand All @@ -774,22 +772,46 @@ describe("mangle-names", () => {
`);
const expected = unpad(`
(function () {
class Foo {}
const a = class Bar extends Foo {};
var b = function foo() {
var a = function foo() {
foo();
};
function bar() {
b();
a();
}
bar();
var c = b;
c();
var b = a;
b();
})();
`);
expect(transform(source, {keepFnName: true})).toBe(expected);
});

it("should NOT mangle classes when keepClassName is true", () => {
const source = unpad(`
(function() {
class Foo {}
const Bar = class Bar extends Foo {}
var foo = class Baz {}
function bar() {
new foo();
}
bar();
})();
`);
const expected = unpad(`
(function () {
class Foo {}
const b = class Bar extends Foo {};
var c = class Baz {};
function a() {
new c();
}
a();
})();
`);
expect(transform(source, {keepClassName: true})).toBe(expected);
});

it("should mangle variable re-declaration / K violations", () => {
const source = unpad(`
!function () {
Expand Down
12 changes: 10 additions & 2 deletions packages/babel-plugin-minify-mangle-names/src/index.js
Expand Up @@ -5,12 +5,14 @@ module.exports = ({ types: t }) => {
constructor(charset, program, {
blacklist = {},
keepFnName = false,
keepClassName = false,
eval: _eval = false
} = {}) {
this.charset = charset;
this.program = program;
this.blacklist = blacklist;
this.keepFnName = keepFnName;
this.keepClassName = keepClassName;
this.eval = _eval;

this.unsafeScopes = new Set;
Expand Down Expand Up @@ -127,6 +129,8 @@ module.exports = ({ types: t }) => {
|| mangler.isBlacklist(oldName)
// function names
|| (mangler.keepFnName ? isFunction(binding.path) : false)
// class names
|| (mangler.keepClassName ? isClass(binding.path) : false)
) {
continue;
}
Expand Down Expand Up @@ -280,8 +284,12 @@ class Charset {
// for keepFnName
function isFunction(path) {
return path.isFunctionExpression()
|| path.isFunctionDeclaration()
|| path.isClassExpression()
|| path.isFunctionDeclaration();
}

// for keepClassName
function isClass(path) {
return path.isClassExpression()
|| path.isClassDeclaration();
}

Expand Down
Expand Up @@ -56,13 +56,15 @@ Object {
exports[`preset-options should handle options that are delegated to multiple other options 1`] = `
Object {
"input": Object {
"keepClassName": false,
"keepFnName": false,
},
"output": Array [
"babel-plugin-minify-constant-folding",
Array [
"babel-plugin-minify-dead-code-elimination",
Object {
"keepClassName": false,
"keepFnName": false,
},
],
Expand All @@ -74,6 +76,7 @@ Object {
Array [
"babel-plugin-minify-mangle-names",
Object {
"keepClassName": false,
"keepFnName": false,
},
],
Expand All @@ -95,6 +98,7 @@ Object {
exports[`preset-options should handle options that are delegated to multiple other options 2`] = `
Object {
"input": Object {
"keepClassName": true,
"keepFnName": true,
"mangle": Object {
"blacklist": Array [
Expand All @@ -108,6 +112,7 @@ Object {
Array [
"babel-plugin-minify-dead-code-elimination",
Object {
"keepClassName": true,
"keepFnName": true,
},
],
Expand All @@ -123,6 +128,7 @@ Object {
"foo",
"bar",
],
"keepClassName": true,
"keepFnName": true,
},
],
Expand All @@ -144,11 +150,13 @@ Object {
exports[`preset-options should handle options that are delegated to multiple other options 3`] = `
Object {
"input": Object {
"keepClassName": true,
"keepFnName": true,
"mangle": Object {
"blacklist": Array [
"baz",
],
"keepClassName": false,
"keepFnName": false,
},
},
Expand All @@ -157,6 +165,7 @@ Object {
Array [
"babel-plugin-minify-dead-code-elimination",
Object {
"keepClassName": true,
"keepFnName": true,
},
],
Expand All @@ -171,6 +180,7 @@ Object {
"blacklist": Array [
"baz",
],
"keepClassName": false,
"keepFnName": false,
},
],
Expand Down
8 changes: 6 additions & 2 deletions packages/babel-preset-babili/__tests__/options-tests.js
Expand Up @@ -85,19 +85,23 @@ describe("preset-options", () => {

it("should handle options that are delegated to multiple other options", () => {
testOpts({
keepFnName: false
keepFnName: false,
keepClassName: false
});
testOpts({
keepFnName: true,
keepClassName: true,
mangle: {
blacklist: ["foo", "bar"]
}
});
testOpts({
keepFnName: true,
keepClassName: true,
mangle: {
blacklist: ["baz"],
keepFnName: false
keepFnName: false,
keepClassName: false,
}
});
});
Expand Down
5 changes: 5 additions & 0 deletions packages/babel-preset-babili/src/index.js
Expand Up @@ -85,6 +85,11 @@ function preset(context, _opts = {}) {
proxy("keepFnName", [
optionsMap.mangle,
optionsMap.deadcode
]),

proxy("keepClassName", [
optionsMap.mangle,
optionsMap.deadcode
])
],
"some"
Expand Down

0 comments on commit b8bac37

Please sign in to comment.