A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://github.com/fabiosantoscode/terser/commit/0f4f01b66cb2aa4356309c70a7d6a95618603630 below:

clean up `collapse_vars` (#1826) · terser/terser@0f4f01b · GitHub

@@ -642,151 +642,134 @@ merge(Compressor.prototype, {

642 642

// and if it has exactly one reference then attempt to replace its reference

643 643

// in the statement with the var value and then erase the var definition.

644 644 645 -

var self = compressor.self();

646 -

var var_defs_removed = false;

645 +

var scope = compressor.find_parent(AST_Scope);

647 646

var toplevel = compressor.option("toplevel");

648 647

for (var stat_index = statements.length; --stat_index >= 0;) {

649 648

var stat = statements[stat_index];

650 -

if (stat instanceof AST_Definitions) continue;

651 - 652 -

// Process child blocks of statement if present.

653 -

[stat, stat.body, stat.alternative, stat.bcatch, stat.bfinally].forEach(function(node) {

654 -

node && node.body && collapse_single_use_vars(node.body, compressor);

655 -

});

656 649 657 -

// The variable definition must precede a statement.

658 -

if (stat_index <= 0) break;

659 -

var prev_stat_index = stat_index - 1;

660 -

var prev_stat = statements[prev_stat_index];

661 -

if (!(prev_stat instanceof AST_Definitions)) continue;

662 -

var var_defs = prev_stat.definitions;

663 -

if (var_defs == null) continue;

664 - 665 -

var var_names_seen = {};

650 +

var var_names_seen = Object.create(null);

666 651

var side_effects_encountered = false;

667 652

var lvalues_encountered = false;

668 -

var lvalues = {};

653 +

var lvalues = Object.create(null);

654 +

var prev_stat_index, var_defs, var_defs_index;

669 655 670 656

// Scan variable definitions from right to left.

671 -

for (var var_defs_index = var_defs.length; --var_defs_index >= 0;) {

672 - 673 -

// Obtain var declaration and var name with basic sanity check.

674 -

var var_decl = var_defs[var_defs_index];

675 -

if (var_decl.value == null) break;

676 -

var var_name = var_decl.name.name;

677 -

if (!var_name || !var_name.length) break;

678 - 679 -

// Bail if we've seen a var definition of same name before.

680 -

if (var_name in var_names_seen) break;

681 -

var_names_seen[var_name] = true;

682 - 683 -

// Only interested in cases with just one reference to the variable.

684 -

var def = self.find_variable && self.find_variable(var_name);

685 -

if (!def || !def.references || def.references.length !== 1

686 -

|| var_name == "arguments" || (!toplevel && def.global)) {

687 -

side_effects_encountered = true;

688 -

continue;

657 +

if (stat instanceof AST_Definitions) {

658 +

prev_stat_index = stat_index;

659 +

var_defs = stat.definitions;

660 +

for (var_defs_index = var_defs.length - 1; --var_defs_index >= 0;) {

661 +

if (collapse(var_defs[var_defs_index + 1])) break;

689 662

}

690 -

var ref = def.references[0];

691 - 692 -

// Don't replace ref if eval() or with statement in scope.

693 -

if (ref.scope.uses_eval || ref.scope.uses_with) break;

694 - 695 -

// Constant single use vars can be replaced in any scope.

696 -

if (var_decl.value.is_constant()) {

697 -

var ctt = new TreeTransformer(function(node) {

698 -

var parent = ctt.parent();

699 -

if (parent instanceof AST_IterationStatement

700 -

&& (parent.condition === node || parent.init === node)) {

701 -

return node;

702 -

}

703 -

if (node === ref)

704 -

return replace_var(node, parent, true);

705 -

});

706 -

stat.transform(ctt);

707 -

continue;

663 +

} else if (stat_index > 0) {

664 +

// The variable definition must precede a statement.

665 +

prev_stat_index = stat_index - 1;

666 +

var prev_stat = statements[prev_stat_index];

667 +

if (!(prev_stat instanceof AST_Definitions)) continue;

668 +

var_defs = prev_stat.definitions;

669 +

for (var_defs_index = var_defs.length; --var_defs_index >= 0;) {

670 +

if (collapse(stat)) break;

708 671

}

672 +

}

673 +

}

709 674 710 -

// Restrict var replacement to constants if side effects encountered.

711 -

if (side_effects_encountered |= lvalues_encountered) continue;

675 +

return statements;

712 676 713 -

var value_has_side_effects = var_decl.value.has_side_effects(compressor);

714 -

// Non-constant single use vars can only be replaced in same scope.

715 -

if (ref.scope !== self) {

716 -

side_effects_encountered |= value_has_side_effects;

717 -

continue;

718 -

}

677 +

function collapse(stat) {

678 +

var var_decl = var_defs[var_defs_index];

679 +

// `drop_unused()` shuffles variables without values to the top,

680 +

// so we can terminate upon first sighting as an optimization.

681 +

if (var_decl.value == null) return true;

682 +

var var_name = var_decl.name.name;

683 + 684 +

// Bail if we've seen a var definition of same name before.

685 +

if (var_name in var_names_seen) return true;

686 +

var_names_seen[var_name] = true;

687 + 688 +

// Only interested in non-constant values.

689 +

if (var_decl.value.is_constant()) return;

690 + 691 +

// Only interested in cases with just one reference to the variable.

692 +

var def = var_decl.name.definition();

693 +

if (def.references.length !== 1

694 +

|| var_name == "arguments" || (!toplevel && def.global)) {

695 +

side_effects_encountered = true;

696 +

return;

697 +

}

698 +

var ref = def.references[0];

699 + 700 +

// Don't replace ref if eval() or with statement in scope.

701 +

if (ref.scope.uses_eval || ref.scope.uses_with) return true;

702 + 703 +

// Restrict var replacement to constants if side effects encountered.

704 +

if (side_effects_encountered |= lvalues_encountered) return;

719 705 720 -

// Detect lvalues in var value.

721 -

var tw = new TreeWalker(function(node){

722 -

if (node instanceof AST_SymbolRef && is_lvalue(node, tw.parent())) {

723 -

lvalues[node.name] = lvalues_encountered = true;

706 +

var value_has_side_effects = var_decl.value.has_side_effects(compressor);

707 +

// Non-constant single use vars can only be replaced in same scope.

708 +

if (ref.scope !== scope) {

709 +

side_effects_encountered |= value_has_side_effects;

710 +

return;

711 +

}

712 + 713 +

// Detect lvalues in var value.

714 +

var tw = new TreeWalker(function(node){

715 +

if (node instanceof AST_SymbolRef && is_lvalue(node, tw.parent())) {

716 +

lvalues[node.name] = lvalues_encountered = true;

717 +

}

718 +

});

719 +

var_decl.value.walk(tw);

720 + 721 +

// Replace the non-constant single use var in statement if side effect free.

722 +

var unwind = false;

723 +

var tt = new TreeTransformer(

724 +

function preorder(node) {

725 +

if (unwind || node instanceof AST_Scope && node !== scope) return node;

726 +

var parent = tt.parent();

727 +

if (node instanceof AST_Try

728 +

|| node instanceof AST_With

729 +

|| node instanceof AST_Case

730 +

|| node instanceof AST_IterationStatement

731 +

|| (parent instanceof AST_If && node !== parent.condition)

732 +

|| (parent instanceof AST_Conditional && node !== parent.condition)

733 +

|| (node instanceof AST_SymbolRef

734 +

&& value_has_side_effects

735 +

&& !are_references_in_scope(node.definition(), scope))

736 +

|| (parent instanceof AST_Binary

737 +

&& (parent.operator == "&&" || parent.operator == "||")

738 +

&& node === parent.right)

739 +

|| (parent instanceof AST_Switch && node !== parent.expression)) {

740 +

return side_effects_encountered = unwind = true, node;

724 741

}

725 -

});

726 -

var_decl.value.walk(tw);

727 - 728 -

// Replace the non-constant single use var in statement if side effect free.

729 -

var unwind = false;

730 -

var tt = new TreeTransformer(

731 -

function preorder(node) {

732 -

if (unwind) return node;

733 -

var parent = tt.parent();

734 -

if (node instanceof AST_Lambda

735 -

|| node instanceof AST_Try

736 -

|| node instanceof AST_With

737 -

|| node instanceof AST_Case

738 -

|| node instanceof AST_IterationStatement

739 -

|| (parent instanceof AST_If && node !== parent.condition)

740 -

|| (parent instanceof AST_Conditional && node !== parent.condition)

741 -

|| (node instanceof AST_SymbolRef

742 -

&& value_has_side_effects

743 -

&& !are_references_in_scope(node.definition(), self))

744 -

|| (parent instanceof AST_Binary

745 -

&& (parent.operator == "&&" || parent.operator == "||")

746 -

&& node === parent.right)

747 -

|| (parent instanceof AST_Switch && node !== parent.expression)) {

748 -

return side_effects_encountered = unwind = true, node;

749 -

}

750 -

function are_references_in_scope(def, scope) {

751 -

if (def.orig.length === 1

752 -

&& def.orig[0] instanceof AST_SymbolDefun) return true;

753 -

if (def.scope !== scope) return false;

754 -

var refs = def.references;

755 -

for (var i = 0, len = refs.length; i < len; i++) {

756 -

if (refs[i].scope !== scope) return false;

757 -

}

758 -

return true;

759 -

}

760 -

},

761 -

function postorder(node) {

762 -

if (unwind) return node;

763 -

if (node === ref)

764 -

return unwind = true, replace_var(node, tt.parent(), false);

765 -

if (side_effects_encountered |= node.has_side_effects(compressor))

766 -

return unwind = true, node;

767 -

if (lvalues_encountered && node instanceof AST_SymbolRef && node.name in lvalues) {

768 -

side_effects_encountered = true;

769 -

return unwind = true, node;

742 +

function are_references_in_scope(def, scope) {

743 +

if (def.orig.length === 1

744 +

&& def.orig[0] instanceof AST_SymbolDefun) return true;

745 +

if (def.scope !== scope) return false;

746 +

var refs = def.references;

747 +

for (var i = 0, len = refs.length; i < len; i++) {

748 +

if (refs[i].scope !== scope) return false;

770 749

}

750 +

return true;

771 751

}

772 -

);

773 -

stat.transform(tt);

774 -

}

775 -

}

776 - 777 -

// Remove extraneous empty statments in block after removing var definitions.

778 -

// Leave at least one statement in `statements`.

779 -

if (var_defs_removed) for (var i = statements.length; --i >= 0;) {

780 -

if (statements.length > 1 && statements[i] instanceof AST_EmptyStatement)

781 -

statements.splice(i, 1);

752 +

},

753 +

function postorder(node) {

754 +

if (unwind) return node;

755 +

if (node === ref)

756 +

return unwind = true, replace_var(var_decl, node, tt.parent(), false);

757 +

if (side_effects_encountered |= node.has_side_effects(compressor))

758 +

return unwind = true, node;

759 +

if (lvalues_encountered && node instanceof AST_SymbolRef && node.name in lvalues) {

760 +

side_effects_encountered = true;

761 +

return unwind = true, node;

762 +

}

763 +

}

764 +

);

765 +

stat.transform(tt);

782 766

}

783 767 784 -

return statements;

785 - 786 768

function is_lvalue(node, parent) {

787 769

return node instanceof AST_SymbolRef && is_lhs(node, parent);

788 770

}

789 -

function replace_var(node, parent, is_constant) {

771 + 772 +

function replace_var(var_decl, node, parent, is_constant) {

790 773

if (is_lvalue(node, parent)) return node;

791 774 792 775

// Remove var definition and return its value to the TreeTransformer to replace.

@@ -795,14 +778,19 @@ merge(Compressor.prototype, {

795 778 796 779

var_defs.splice(var_defs_index, 1);

797 780

if (var_defs.length === 0) {

798 -

statements[prev_stat_index] = make_node(AST_EmptyStatement, self);

799 -

var_defs_removed = true;

781 +

statements.splice(prev_stat_index, 1);

782 +

stat_index--;

800 783

}

801 784

// Further optimize statement after substitution.

802 785

stat.reset_opt_flags(compressor);

803 786 804 -

compressor.info("Collapsing " + (is_constant ? "constant" : "variable") +

805 -

" " + var_name + " [{file}:{line},{col}]", node.start);

787 +

compressor.info("Collapsing {type} {name} [{file}:{line},{col}]", {

788 +

type: is_constant ? "constant" : "variable",

789 +

name: var_decl.name.name,

790 +

file: node.start.file,

791 +

line: node.start.line,

792 +

col: node.start.col

793 +

});

806 794

CHANGED = true;

807 795

return value;

808 796

}

@@ -1746,6 +1734,7 @@ merge(Compressor.prototype, {

1746 1734

def(AST_SymbolRef, function(compressor){

1747 1735

return this.undeclared();

1748 1736

});

1737 +

def(AST_SymbolDeclaration, return_false);

1749 1738

def(AST_Object, function(compressor){

1750 1739

return any(this.properties, compressor);

1751 1740

});


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4