Skip to content

Commit

Permalink
Merge branch 'master' into feature/codeql
Browse files Browse the repository at this point in the history
  • Loading branch information
aleks-ivanov committed May 9, 2023
2 parents 390d917 + 26b70f3 commit 7ce6996
Show file tree
Hide file tree
Showing 10 changed files with 173 additions and 28 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Changelog

## v5.17.2
- Be less conservative when detecting use-before-definition of `var` in hoisted functions.
- Support unusual (but perfectly valid) initializers of for-in and for-of loops.
- Fix issue where hoisted function would be dropped if it was after a `continue` statement

## v5.17.1
- Fix evaluating `.length` when the source array might've been mutated

Expand Down
9 changes: 9 additions & 0 deletions lib/compress/drop-side-effect-free.js
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,15 @@ def_drop_side_effect_free(AST_Class, function (compressor) {
}
}

if (
prop instanceof AST_ClassProperty
&& prop.static
&& prop.value.has_side_effects(compressor)
&& prop.contains_this()
) {
return this;
}

const trimmed_prop = prop.drop_side_effect_free(compressor);
if (trimmed_prop)
with_effects.push(trimmed_prop);
Expand Down
13 changes: 0 additions & 13 deletions lib/compress/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3358,19 +3358,6 @@ def_optimize(AST_Chain, function (self, compressor) {
return self;
});

AST_Lambda.DEFMETHOD("contains_this", function() {
return walk(this, node => {
if (node instanceof AST_This) return walk_abort;
if (
node !== this
&& node instanceof AST_Scope
&& !(node instanceof AST_Arrow)
) {
return true;
}
});
});

def_optimize(AST_Dot, function(self, compressor) {
const parent = compressor.parent();
if (is_lhs(self, parent)) return self;
Expand Down
14 changes: 14 additions & 0 deletions lib/compress/inference.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ import {
AST_PropAccess,
AST_RegExp,
AST_Return,
AST_Scope,
AST_Sequence,
AST_SimpleStatement,
AST_Statement,
Expand Down Expand Up @@ -950,6 +951,19 @@ export const aborts = (thing) => thing && thing.aborts();
node.DEFMETHOD("aborts", func);
});

AST_Node.DEFMETHOD("contains_this", function() {
return walk(this, node => {
if (node instanceof AST_This) return walk_abort;
if (
node !== this
&& node instanceof AST_Scope
&& !(node instanceof AST_Arrow)
) {
return true;
}
});
});

export function is_modified(compressor, tw, node, value, level, immutable) {
var parent = tw.parent(level);
var lhs = is_lhs(node, parent);
Expand Down
37 changes: 25 additions & 12 deletions lib/compress/reduce-vars.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ import {
AST_Symbol,
AST_SymbolCatch,
AST_SymbolConst,
AST_SymbolDeclaration,
AST_SymbolDefun,
AST_SymbolFunarg,
AST_SymbolLambda,
Expand All @@ -92,6 +93,7 @@ import {
AST_Yield,

walk,
walk_parent,
walk_abort,
walk_body,

Expand All @@ -101,7 +103,7 @@ import {
} from "../ast.js";
import { HOP, make_node, noop } from "../utils/index.js";

import { lazy_op, is_modified } from "./inference.js";
import { lazy_op, is_modified, is_lhs } from "./inference.js";
import { INLINED, clear_flag } from "./compressor-flags.js";
import { read_property, has_break_or_continue, is_recursive_ref } from "./common.js";

Expand Down Expand Up @@ -540,20 +542,31 @@ function handle_defined_after_hoist(parent) {
continue;
}

// Detect `call_defun(); var used_in_defun = ...`
// Because `used_in_defun` can no longer be fixed
let found_defun = false;
// Detect `call_defun(); var used_in_defun = X`
// Because `used_in_defun` is not certainly X when it's defined after.
let found_defun_ref = false;
let found_def_after_defun = false;
walk(parent, node => {
walk_parent(parent, (node, info) => {
if (node === defun) return true;

if (node instanceof AST_Symbol) {
if (!found_defun && node.thedef === fname_def) {
found_defun = true;
} else if (found_defun && node.thedef === def) {
found_def_after_defun = true;
return walk_abort;
}
// Step 1: find `call_defun()` or other refs to the defun
if (
!found_defun_ref
&& node.thedef === fname_def
&& node instanceof AST_Symbol
) {
found_defun_ref = true;
}

// Step 2: if Step 1 occurred, find a var the defun uses
if (
found_defun_ref
&& node.thedef === def
&& (node instanceof AST_SymbolDeclaration
|| is_lhs(node, info))
) {
found_def_after_defun = true;
return walk_abort;
}
});

Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"homepage": "https://terser.org",
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
"license": "BSD-2-Clause",
"version": "5.17.1",
"version": "5.17.2",
"engines": {
"node": ">=10"
},
Expand Down
56 changes: 56 additions & 0 deletions test/compress/drop-unused.js
Original file line number Diff line number Diff line change
Expand Up @@ -2774,6 +2774,62 @@ unused_class_with_static_props_side_effects: {
expect_stdout: "PASS"
}

unused_class_with_static_props_this: {
node_version = ">=12"
options = {
toplevel: true,
unused: true
}
input: {
let _classThis;
var Foo = class {
static _ = Foo = _classThis = this;
};
const x = Foo = _classThis;
leak(x);
}
expect: {
let _classThis;
(class {
static _ = _classThis = this;
});
const x = _classThis;
leak(x);
}
}

unused_class_with_static_props_this_2: {
node_version = ">=12"
options = {
toplevel: true,
unused: true,
}
input: {
let Foo = (()=>{
let _classThis;
var Foo = class {
static _ = (()=>{
Foo = _classThis = this;
})();
foo(){
return "PASS";
}
};
return Foo = _classThis;
})();
console.log(new Foo().foo());
}
expect: {
let Foo = (()=>{
let _classThis;
(class{static _=(()=>{_classThis=this})();foo(){return "PASS"}});
return _classThis
})();
console.log((new Foo).foo());
}
expect_stdout: "PASS"
}

unused_class_with_static_props_side_effects_2: {
node_version = ">=12"
options = {
Expand Down
25 changes: 25 additions & 0 deletions test/compress/if_return.js
Original file line number Diff line number Diff line change
Expand Up @@ -528,3 +528,28 @@ if_return_same_value: {
function h() { return (foo || bar) ? x() : y() }
}
}

issue_t833: {
options = {
if_return: true,
}
input: {
var a = id(1), object = {PASS: 1};
for (var p in object) {
if (a) {
test(); continue;
function test() {console.log(p)}
}
}
}
expect: {
var a = id(1), object = {PASS: 1};
for (var p in object)
if (a) {
test();
continue;
function test(){console.log(p)}
}
}
expect_stdout: "PASS"
}
38 changes: 37 additions & 1 deletion test/compress/reduce_vars.js
Original file line number Diff line number Diff line change
Expand Up @@ -1393,13 +1393,49 @@ defun_reference_fixed: {
expect_stdout: "true"
}

issue_t1382: {
options = {
module: true,
reduce_vars: true,
unused: true,
evaluate: true,
}
input: {
const qDev = false;

function assertEqual() {
if (qDev) {
throw new Error('SHOULD BE REMOVED')
}
}

export {assertEqual}

export class ReadWriteProxyHandler {
set() {
if (qDev) if (invokeCtx) {}
}
}
}
expect: {
function assertEqual(){
if(false) throw new Error("SHOULD BE REMOVED")
}

export{assertEqual};

export class ReadWriteProxyHandler{
set(){if(false)if(invokeCtx);}
}
}
}

defun_reference_fixed_let: {
options = {
toplevel: true,
reduce_vars: true,
unused: true,
evaluate: true,
passes: 3
}
input: {
let on = true;
Expand Down

0 comments on commit 7ce6996

Please sign in to comment.