From 5d2a532eb4f166a8924f365e93a332ed0f58508a Mon Sep 17 00:00:00 2001 From: Vignesh Shanmugam Date: Thu, 9 Mar 2017 18:16:28 +0100 Subject: [PATCH 1/6] fix builtins plugins from leaking vars --- .../__snapshots__/minify-builtins.js.snap | 10 +++++--- .../babel-plugin-minify-builtins/src/index.js | 25 +++++++++++++++++-- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/packages/babel-plugin-minify-builtins/__tests__/__snapshots__/minify-builtins.js.snap b/packages/babel-plugin-minify-builtins/__tests__/__snapshots__/minify-builtins.js.snap index cd76aa3b7..cce337ca3 100644 --- a/packages/babel-plugin-minify-builtins/__tests__/__snapshots__/minify-builtins.js.snap +++ b/packages/babel-plugin-minify-builtins/__tests__/__snapshots__/minify-builtins.js.snap @@ -10,12 +10,13 @@ function a (){ Math.min(b, a) * Math.floor(b); } }", - "expected": "var _Mathfloor = Math.floor; -var _Mathmax = Math.max; + "expected": "var _Mathmax = Math.max; _Mathmax(a, b) + _Mathmax(a, b); function a() { _Mathmax(b, a); return function b() { + var _Mathfloor = Math.floor; + const a = _Mathfloor(c); Math.min(b, a) * _Mathfloor(b); }; @@ -60,10 +61,11 @@ Object { function a () { return Math.PI + Math.PI + Number.EPSILON + Number.NAN; }", - "expected": "var _MathPI = Math.PI; -var _NumberNAN = Number.NAN; + "expected": "var _NumberNAN = Number.NAN; _NumberNAN + _NumberNAN; function a() { + var _MathPI = Math.PI; + return _MathPI + _MathPI + Number.EPSILON + _NumberNAN; }", } diff --git a/packages/babel-plugin-minify-builtins/src/index.js b/packages/babel-plugin-minify-builtins/src/index.js index fcfe87a6b..564245986 100644 --- a/packages/babel-plugin-minify-builtins/src/index.js +++ b/packages/babel-plugin-minify-builtins/src/index.js @@ -83,8 +83,9 @@ module.exports = function({ types: t }) { for (const path of paths) { path.replaceWith(uniqueIdentifier); } - // hoist the created var to top of the program - this.program.unshiftContainer("body", newNode); + // hoist the created var to the top of the block/program + const path = getPath(this.program, paths[0], paths[paths.length - 1]); + path.unshiftContainer("body", newNode); } } } @@ -126,6 +127,26 @@ module.exports = function({ types: t }) { } }; +// decides the best path to insert the newly created identifier +function getPath(program, firstPath, lastPath) { + let resultPath = program; + // check if occurence of member exp ex - Max.max() is before the + // block statement container + const { start: nodeStart } = firstPath.parent; + const { end: nodeEnd } = lastPath.parent; + + program.traverse({ + BlockStatement(path) { + const { start, end } = path.node; + if (start < nodeStart && end > nodeEnd ) { + resultPath = path; + return; + } + } + }); + return resultPath; +} + function hasPureArgs(path) { const args = path.get("arguments"); for (const arg of args) { From 2dfeaea940ddc754306e674d1967f671694b95f6 Mon Sep 17 00:00:00 2001 From: Vignesh Shanmugam Date: Fri, 10 Mar 2017 12:21:06 +0100 Subject: [PATCH 2/6] use getFunctionParent instead of traversal --- .../babel-plugin-minify-builtins/src/index.js | 39 ++++++++++--------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/packages/babel-plugin-minify-builtins/src/index.js b/packages/babel-plugin-minify-builtins/src/index.js index 564245986..700196b40 100644 --- a/packages/babel-plugin-minify-builtins/src/index.js +++ b/packages/babel-plugin-minify-builtins/src/index.js @@ -84,7 +84,7 @@ module.exports = function({ types: t }) { path.replaceWith(uniqueIdentifier); } // hoist the created var to the top of the block/program - const path = getPath(this.program, paths[0], paths[paths.length - 1]); + const path = getPath(paths[0], paths[paths.length - 1]); path.unshiftContainer("body", newNode); } } @@ -128,23 +128,26 @@ module.exports = function({ types: t }) { }; // decides the best path to insert the newly created identifier -function getPath(program, firstPath, lastPath) { - let resultPath = program; - // check if occurence of member exp ex - Max.max() is before the - // block statement container - const { start: nodeStart } = firstPath.parent; - const { end: nodeEnd } = lastPath.parent; - - program.traverse({ - BlockStatement(path) { - const { start, end } = path.node; - if (start < nodeStart && end > nodeEnd ) { - resultPath = path; - return; - } - } - }); - return resultPath; +function getPath(firstPath, lastPath) { + let resultPath; + // check if occurence of member exp ex - Max.max() is outside of the + // function declaration + const firstParent = firstPath.getFunctionParent(); + const lastParent = lastPath.getFunctionParent(); + const { node: { start : firstStart } } = firstParent; + const { node: { start : lastStart } } = lastParent; + + if (firstStart < lastStart) { + resultPath = firstParent; + } else { + resultPath = lastParent; + } + + if (resultPath.isProgram()) { + return resultPath; + } + // return the block statment if its not program + return resultPath.get("body"); } function hasPureArgs(path) { From cec06b5eb24174262d2d7d7df409b5e8aed7e2dc Mon Sep 17 00:00:00 2001 From: Vignesh Shanmugam Date: Fri, 10 Mar 2017 13:40:59 +0100 Subject: [PATCH 3/6] run mangler on exit[fix #425] --- .../src/index.js | 28 ++++++++++--------- .../__tests__/preset-tests.js | 27 ++++++++++++++++++ 2 files changed, 42 insertions(+), 13 deletions(-) diff --git a/packages/babel-plugin-minify-mangle-names/src/index.js b/packages/babel-plugin-minify-mangle-names/src/index.js index e48a077cd..399eb2b80 100644 --- a/packages/babel-plugin-minify-mangle-names/src/index.js +++ b/packages/babel-plugin-minify-mangle-names/src/index.js @@ -247,19 +247,21 @@ module.exports = ({ types: t, traverse }) => { return { name: "minify-mangle-names", visitor: { - Program(path) { - // If the source code is small then we're going to assume that the user - // is running on this on single files before bundling. Therefore we - // need to achieve as much determinisim and we will not do any frequency - // sorting on the character set. Currently the number is pretty arbitrary. - const shouldConsiderSource = path.getSource().length > 70000; - - const charset = new Charset(shouldConsiderSource); - - const mangler = new Mangler(charset, path, this.opts); - mangler.run(); - } - } + Program: { + exit(path) { + // If the source code is small then we're going to assume that the user + // is running on this on single files before bundling. Therefore we + // need to achieve as much determinisim and we will not do any frequency + // sorting on the character set. Currently the number is pretty arbitrary. + const shouldConsiderSource = path.getSource().length > 70000; + + const charset = new Charset(shouldConsiderSource); + + const mangler = new Mangler(charset, path, this.opts); + mangler.run(); + } + }, + }, }; }; diff --git a/packages/babel-preset-babili/__tests__/preset-tests.js b/packages/babel-preset-babili/__tests__/preset-tests.js index e45132946..70daf4330 100644 --- a/packages/babel-preset-babili/__tests__/preset-tests.js +++ b/packages/babel-preset-babili/__tests__/preset-tests.js @@ -111,4 +111,31 @@ describe("preset", () => { ); expect(transform(source)).toBe(expected); }); + + it("should fix issue#425 - mangles the alaises from builtins transform", () => { + const source = unpad(` + function foo (){ + const d = Math.max(b, a); + return function b() { + const a = Math.floor(c); + Math.max(b, a) * Math.floor(b); + } + } + `); + const expected = unpad(` + function foo() { + var d = Math.max; + d(b, a); + + return function e() { + var f = Math.floor; + + const g = f(c); + d(e, g) * f(e); + }; + } + `); + expect(transform(source)).toBe(expected); + }); + }); From c805afd0b34e8bdb39038277497aa5c57529bd50 Mon Sep 17 00:00:00 2001 From: Vignesh Shanmugam Date: Sat, 11 Mar 2017 18:44:04 +0100 Subject: [PATCH 4/6] find common ancestor fix --- .../babel-plugin-minify-builtins/src/index.js | 15 +++++++---- .../__tests__/preset-tests.js | 26 ++++++++----------- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/packages/babel-plugin-minify-builtins/src/index.js b/packages/babel-plugin-minify-builtins/src/index.js index 700196b40..d01e0283d 100644 --- a/packages/babel-plugin-minify-builtins/src/index.js +++ b/packages/babel-plugin-minify-builtins/src/index.js @@ -84,7 +84,7 @@ module.exports = function({ types: t }) { path.replaceWith(uniqueIdentifier); } // hoist the created var to the top of the block/program - const path = getPath(paths[0], paths[paths.length - 1]); + const path = getLeastCommonFunctionPath(paths[0], paths[paths.length - 1]); path.unshiftContainer("body", newNode); } } @@ -127,21 +127,26 @@ module.exports = function({ types: t }) { } }; -// decides the best path to insert the newly created identifier -function getPath(firstPath, lastPath) { +function getLeastCommonFunctionPath(firstPath, lastPath) { let resultPath; - // check if occurence of member exp ex - Max.max() is outside of the - // function declaration const firstParent = firstPath.getFunctionParent(); const lastParent = lastPath.getFunctionParent(); + const { node: { start : firstStart } } = firstParent; const { node: { start : lastStart } } = lastParent; + // Early optimization that avoids the situation when firstPath + // is too deep in the tree and lastPath is one level deep and vice versa if (firstStart < lastStart) { resultPath = firstParent; } else { resultPath = lastParent; } + // Traverse bottom up till it finds the common ancestor + while (!(firstPath.isDescendant(resultPath) && + lastPath.isDescendant(resultPath))) { + resultPath = resultPath.getFunctionParent(); + } if (resultPath.isProgram()) { return resultPath; diff --git a/packages/babel-preset-babili/__tests__/preset-tests.js b/packages/babel-preset-babili/__tests__/preset-tests.js index 70daf4330..1c5e9cd1b 100644 --- a/packages/babel-preset-babili/__tests__/preset-tests.js +++ b/packages/babel-preset-babili/__tests__/preset-tests.js @@ -114,25 +114,21 @@ describe("preset", () => { it("should fix issue#425 - mangles the alaises from builtins transform", () => { const source = unpad(` - function foo (){ - const d = Math.max(b, a); - return function b() { - const a = Math.floor(c); - Math.max(b, a) * Math.floor(b); + function a (){ + const d = Math.max(foo, bar); + function b() { + Math.max(foo, bar) * Math.floor(baz); + } + function c() { + Math.max(foo, bar) * Math.floor(baz); } } `); const expected = unpad(` - function foo() { - var d = Math.max; - d(b, a); - - return function e() { - var f = Math.floor; - - const g = f(c); - d(e, g) * f(e); - }; + function a() { + var b = Math.floor, + c = Math.max; + c(foo, bar); } `); expect(transform(source)).toBe(expected); From 68ece87529f509f082a330b7297931545d030a4a Mon Sep 17 00:00:00 2001 From: Vignesh Shanmugam Date: Mon, 20 Mar 2017 16:31:10 +0100 Subject: [PATCH 5/6] construct segmented LCA for same level builtins --- .../__snapshots__/minify-builtins.js.snap | 114 ++++++++++++++---- .../__tests__/minify-builtins.js | 51 +++++++- .../babel-plugin-minify-builtins/src/index.js | 101 +++++++++------- .../src/index.js | 4 +- .../__tests__/preset-tests.js | 13 +- 5 files changed, 204 insertions(+), 79 deletions(-) diff --git a/packages/babel-plugin-minify-builtins/__tests__/__snapshots__/minify-builtins.js.snap b/packages/babel-plugin-minify-builtins/__tests__/__snapshots__/minify-builtins.js.snap index cce337ca3..6d298e247 100644 --- a/packages/babel-plugin-minify-builtins/__tests__/__snapshots__/minify-builtins.js.snap +++ b/packages/babel-plugin-minify-builtins/__tests__/__snapshots__/minify-builtins.js.snap @@ -1,25 +1,72 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`minify-builtins should collect and minify in segments if there is no common ancestor 1`] = ` +Object { + "_source": "function a(){ + function d(){ + Math.floor(as, bb); + } +} +function b(){ + Math.floor(as, bb); + function d(){ + Math.floor(as, bb); + } +} +function c(){ + Math.floor(as, bb); + function d(){ + Math.floor(as, bb); + } +}", + "expected": "function a() { + function d() { + Math.floor(as, bb); + } +} +function b() { + var _Mathfloor = Math.floor; + + _Mathfloor(as, bb); + function d() { + _Mathfloor(as, bb); + } +} +function c() { + var _Mathfloor2 = Math.floor; + + _Mathfloor2(as, bb); + function d() { + _Mathfloor2(as, bb); + } +}", +} +`; + exports[`minify-builtins should collect and minify no matter any depth 1`] = ` Object { - "_source": "Math.max(a, b) + Math.max(a, b); -function a (){ + "_source": "function a (){ Math.max(b, a); - return function b() { + function b() { const a = Math.floor(c); Math.min(b, a) * Math.floor(b); + function c() { + Math.floor(c) + Math.min(b, a) + } } }", - "expected": "var _Mathmax = Math.max; -_Mathmax(a, b) + _Mathmax(a, b); -function a() { - _Mathmax(b, a); - return function b() { + "expected": "function a() { + Math.max(b, a); + function b() { + var _Mathmin = Math.min; var _Mathfloor = Math.floor; const a = _Mathfloor(c); - Math.min(b, a) * _Mathfloor(b); - }; + _Mathmin(b, a) * _Mathfloor(b); + function c() { + _Mathfloor(c) + _Mathmin(b, a); + } + } }", } `; @@ -39,17 +86,18 @@ foo(x);", exports[`minify-builtins should minify standard built in methods 1`] = ` Object { - "_source": "Math.max(a, b) + Math.max(b, a); -function c() { + "_source": "function c() { let a = 10; const d = Number.isNaN(a); + Math.max(a, b) + Math.max(b, a); return d && Number.isFinite(a); }", - "expected": "var _Mathmax = Math.max; -_Mathmax(a, b) + _Mathmax(b, a); -function c() { + "expected": "function c() { + var _Mathmax = Math.max; + let a = 10; const d = false; + _Mathmax(a, b) + _Mathmax(b, a); return d && true; }", } @@ -57,15 +105,15 @@ function c() { exports[`minify-builtins should minify standard built in properties 1`] = ` Object { - "_source": "Number.NAN + Number.NAN; -function a () { + "_source": "function a () { + Number.NAN + Number.NAN; return Math.PI + Math.PI + Number.EPSILON + Number.NAN; }", - "expected": "var _NumberNAN = Number.NAN; -_NumberNAN + _NumberNAN; -function a() { + "expected": "function a() { var _MathPI = Math.PI; + var _NumberNAN = Number.NAN; + _NumberNAN + _NumberNAN; return _MathPI + _MathPI + Number.EPSILON + _NumberNAN; }", } @@ -92,13 +140,29 @@ Math[max](1.5);", exports[`minify-builtins should take no of occurences in to account 1`] = ` Object { "_source": "function a() { - return Math.floor(a) + Math.floor(b) + Math.min(a, b); + Math.floor(a) + Math.floor(b) + Math.min(a, b); +}", + "expected": "function a() { + var _Mathfloor = Math.floor; + + _Mathfloor(a) + _Mathfloor(b) + Math.min(a, b); +}", } -Math.floor(a) + Math.max(a, b);", - "expected": "var _Mathfloor = Math.floor; +`; + +exports[`minify-builtins shouldn't minify builtins in the program scope to avoid leaking 1`] = ` +Object { + "_source": "Math.max(c, d) +function a (){ + Math.max(b, a) + Math.max(c, d); +} +Math.max(e, f)", + "expected": "Math.max(c, d); function a() { - return _Mathfloor(a) + _Mathfloor(b) + Math.min(a, b); + var _Mathmax = Math.max; + + _Mathmax(b, a) + _Mathmax(c, d); } -_Mathfloor(a) + Math.max(a, b);", +Math.max(e, f);", } `; diff --git a/packages/babel-plugin-minify-builtins/__tests__/minify-builtins.js b/packages/babel-plugin-minify-builtins/__tests__/minify-builtins.js index 540c0aed8..a03f84177 100644 --- a/packages/babel-plugin-minify-builtins/__tests__/minify-builtins.js +++ b/packages/babel-plugin-minify-builtins/__tests__/minify-builtins.js @@ -14,10 +14,10 @@ describe("minify-builtins", () => { it("should minify standard built in methods", () => { const source = unpad( ` - Math.max(a, b) + Math.max(b, a); function c() { let a = 10; const d = Number.isNaN(a); + Math.max(a, b) + Math.max(b, a); return d && Number.isFinite(a); } ` @@ -29,8 +29,8 @@ describe("minify-builtins", () => { it("should minify standard built in properties", () => { const source = unpad( ` - Number.NAN + Number.NAN; function a () { + Number.NAN + Number.NAN; return Math.PI + Math.PI + Number.EPSILON + Number.NAN; } ` @@ -42,9 +42,8 @@ describe("minify-builtins", () => { const source = unpad( ` function a() { - return Math.floor(a) + Math.floor(b) + Math.min(a, b); + Math.floor(a) + Math.floor(b) + Math.min(a, b); } - Math.floor(a) + Math.max(a, b); ` ); expect({ _source: source, expected: transform(source) }).toMatchSnapshot(); @@ -53,12 +52,52 @@ describe("minify-builtins", () => { it("should collect and minify no matter any depth", () => { const source = unpad( ` - Math.max(a, b) + Math.max(a, b); function a (){ Math.max(b, a); - return function b() { + function b() { const a = Math.floor(c); Math.min(b, a) * Math.floor(b); + function c() { + Math.floor(c) + Math.min(b, a) + } + } + } + ` + ); + expect({ _source: source, expected: transform(source) }).toMatchSnapshot(); + }); + + it("shouldn't minify builtins in the program scope to avoid leaking", () => { + const source = unpad( + ` + Math.max(c, d) + function a (){ + Math.max(b, a) + Math.max(c, d); + } + Math.max(e, f) + ` + ); + expect({ _source: source, expected: transform(source) }).toMatchSnapshot(); + }); + + it("should collect and minify in segments if there is no common ancestor", () => { + const source = unpad( + ` + function a(){ + function d(){ + Math.floor(as, bb); + } + } + function b(){ + Math.floor(as, bb); + function d(){ + Math.floor(as, bb); + } + } + function c(){ + Math.floor(as, bb); + function d(){ + Math.floor(as, bb); } } ` diff --git a/packages/babel-plugin-minify-builtins/src/index.js b/packages/babel-plugin-minify-builtins/src/index.js index d01e0283d..dd42fab5f 100644 --- a/packages/babel-plugin-minify-builtins/src/index.js +++ b/packages/babel-plugin-minify-builtins/src/index.js @@ -29,11 +29,7 @@ module.exports = function({ types: t }) { if (!isComputed(path) && isBuiltin(path)) { const expName = memberToString(path.node); - - if (!context.pathsToUpdate.has(expName)) { - context.pathsToUpdate.set(expName, []); - } - context.pathsToUpdate.get(expName).push(path); + addToMap(context.pathsToUpdate, expName, path); } }, @@ -55,11 +51,7 @@ module.exports = function({ types: t }) { path.replaceWith(t.valueToNode(result.value)); } else { const expName = memberToString(callee.node); - - if (!context.pathsToUpdate.has(expName)) { - context.pathsToUpdate.set(expName, []); - } - context.pathsToUpdate.get(expName).push(callee); + addToMap(context.pathsToUpdate, expName, callee); } } } @@ -71,21 +63,39 @@ module.exports = function({ types: t }) { replace() { for (const [expName, paths] of this.pathsToUpdate) { - // Should only transform if there is more than 1 occurence - if (paths.length > 1) { + // transform only if there is more than 1 occurence + if (paths.length <= 1) { + continue; + } + + // occurences that has program scope are not minified + // to avoid leaking identifiers + const validPaths = paths.filter(p => { + return !p.getFunctionParent().isProgram(); + }); + + // Early exit here as well + if (validPaths.length <= 1) { + continue; + } + + const segmentsMap = getSegmentedSubPaths(expName, validPaths); + for (const [parent, subpaths] of segmentsMap) { + if (subpaths.length <= 1) { + continue; + } const uniqueIdentifier = this.program.scope.generateUidIdentifier( expName ); const newNode = t.variableDeclaration("var", [ - t.variableDeclarator(uniqueIdentifier, paths[0].node) + t.variableDeclarator(uniqueIdentifier, subpaths[0].node) ]); - for (const path of paths) { + for (const path of subpaths) { path.replaceWith(uniqueIdentifier); } - // hoist the created var to the top of the block/program - const path = getLeastCommonFunctionPath(paths[0], paths[paths.length - 1]); - path.unshiftContainer("body", newNode); + // hoist the created var to the top of the function scope + parent.get("body").unshiftContainer("body", newNode); } } } @@ -127,32 +137,41 @@ module.exports = function({ types: t }) { } }; -function getLeastCommonFunctionPath(firstPath, lastPath) { - let resultPath; - const firstParent = firstPath.getFunctionParent(); - const lastParent = lastPath.getFunctionParent(); - - const { node: { start : firstStart } } = firstParent; - const { node: { start : lastStart } } = lastParent; - - // Early optimization that avoids the situation when firstPath - // is too deep in the tree and lastPath is one level deep and vice versa - if (firstStart < lastStart) { - resultPath = firstParent; - } else { - resultPath = lastParent; - } - // Traverse bottom up till it finds the common ancestor - while (!(firstPath.isDescendant(resultPath) && - lastPath.isDescendant(resultPath))) { - resultPath = resultPath.getFunctionParent(); +function addToMap(map, key, value) { + if (!map.has(key)) { + map.set(key, []); } + map.get(key).push(value); +} - if (resultPath.isProgram()) { - return resultPath; - } - // return the block statment if its not program - return resultPath.get("body"); +// Creates a segmented map that contains the earliest common Ancestor +// as the key and array of subpaths that are descendats of the LCA as value +function getSegmentedSubPaths(expName, paths) { + let segments = new Map(); + + // Get earliest Path in tree where paths intersect + paths[ + 0 + ].getDeepestCommonAncestorFrom(paths, (lastCommon, index, ancestries) => { + // we found the LCA + if (!lastCommon.isProgram()) { + lastCommon = !lastCommon.isFunction() + ? lastCommon.getFunctionParent() + : lastCommon; + segments.set(lastCommon, paths); + return; + } + // Deopt and construct segments otherwise + for (const ancestor of ancestries) { + const parentPath = ancestor[index + 1]; + const validDescendants = paths.filter(p => { + return p.isDescendant(parentPath); + }); + segments.set(parentPath, validDescendants); + } + }); + + return segments; } function hasPureArgs(path) { diff --git a/packages/babel-plugin-minify-mangle-names/src/index.js b/packages/babel-plugin-minify-mangle-names/src/index.js index 399eb2b80..59cb22b5c 100644 --- a/packages/babel-plugin-minify-mangle-names/src/index.js +++ b/packages/babel-plugin-minify-mangle-names/src/index.js @@ -260,8 +260,8 @@ module.exports = ({ types: t, traverse }) => { const mangler = new Mangler(charset, path, this.opts); mangler.run(); } - }, - }, + } + } }; }; diff --git a/packages/babel-preset-babili/__tests__/preset-tests.js b/packages/babel-preset-babili/__tests__/preset-tests.js index 1c5e9cd1b..cb90a9eab 100644 --- a/packages/babel-preset-babili/__tests__/preset-tests.js +++ b/packages/babel-preset-babili/__tests__/preset-tests.js @@ -113,7 +113,8 @@ describe("preset", () => { }); it("should fix issue#425 - mangles the alaises from builtins transform", () => { - const source = unpad(` + const source = unpad( + ` function a (){ const d = Math.max(foo, bar); function b() { @@ -123,15 +124,17 @@ describe("preset", () => { Math.max(foo, bar) * Math.floor(baz); } } - `); - const expected = unpad(` + ` + ); + const expected = unpad( + ` function a() { var b = Math.floor, c = Math.max; c(foo, bar); } - `); + ` + ); expect(transform(source)).toBe(expected); }); - }); From f8f5609279c28889e7c14db8d52abda727e8616e Mon Sep 17 00:00:00 2001 From: Vignesh Shanmugam Date: Wed, 22 Mar 2017 16:37:33 +0100 Subject: [PATCH 6/6] moving the valid check in collect phase --- .../babel-plugin-minify-builtins/src/index.js | 24 +++++++------------ 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/packages/babel-plugin-minify-builtins/src/index.js b/packages/babel-plugin-minify-builtins/src/index.js index dd42fab5f..bde0996a8 100644 --- a/packages/babel-plugin-minify-builtins/src/index.js +++ b/packages/babel-plugin-minify-builtins/src/index.js @@ -10,6 +10,7 @@ module.exports = function({ types: t }) { class BuiltInReplacer { constructor(program) { this.program = program; + // map; this.pathsToUpdate = new Map(); } @@ -27,7 +28,11 @@ module.exports = function({ types: t }) { return; } - if (!isComputed(path) && isBuiltin(path)) { + if ( + !isComputed(path) && + isBuiltin(path) && + !path.getFunctionParent().isProgram() + ) { const expName = memberToString(path.node); addToMap(context.pathsToUpdate, expName, path); } @@ -49,7 +54,7 @@ module.exports = function({ types: t }) { // Math.floor(1) --> 1 if (result.confident && hasPureArgs(path)) { path.replaceWith(t.valueToNode(result.value)); - } else { + } else if (!callee.getFunctionParent().isProgram()) { const expName = memberToString(callee.node); addToMap(context.pathsToUpdate, expName, callee); } @@ -68,18 +73,7 @@ module.exports = function({ types: t }) { continue; } - // occurences that has program scope are not minified - // to avoid leaking identifiers - const validPaths = paths.filter(p => { - return !p.getFunctionParent().isProgram(); - }); - - // Early exit here as well - if (validPaths.length <= 1) { - continue; - } - - const segmentsMap = getSegmentedSubPaths(expName, validPaths); + const segmentsMap = getSegmentedSubPaths(paths); for (const [parent, subpaths] of segmentsMap) { if (subpaths.length <= 1) { continue; @@ -146,7 +140,7 @@ function addToMap(map, key, value) { // Creates a segmented map that contains the earliest common Ancestor // as the key and array of subpaths that are descendats of the LCA as value -function getSegmentedSubPaths(expName, paths) { +function getSegmentedSubPaths(paths) { let segments = new Map(); // Get earliest Path in tree where paths intersect