Skip to content

Commit

Permalink
factor out the inline code
Browse files Browse the repository at this point in the history
  • Loading branch information
fabiosantoscode committed Apr 28, 2022
1 parent 9a548dd commit 56a05f0
Show file tree
Hide file tree
Showing 5 changed files with 730 additions and 554 deletions.
24 changes: 24 additions & 0 deletions lib/ast.js
Expand Up @@ -2869,6 +2869,21 @@ function walk(node, cb, to_visit = [node]) {
return false;
}

/**
* Walks an AST node and its children.
*
* {cb} can return `walk_abort` to interrupt the walk.
*
* @param node
* @param cb {(node, info: { parent: (nth) => any }) => (boolean | undefined)}
*
* @returns {boolean} whether the walk was aborted
*
* @example
* const found_some_cond = walk_parent(my_ast_node, (node, { parent }) => {
* if (some_cond(node, parent())) return walk_abort
* });
*/
function walk_parent(node, cb, initial_stack) {
const to_visit = [node];
const push = to_visit.push.bind(to_visit);
Expand Down Expand Up @@ -2987,6 +3002,15 @@ class TreeWalker {
}
}

find_scope() {
for (let i = 0;;i++) {
const p = this.parent(i);
if (p instanceof AST_Toplevel) return p;
if (p instanceof AST_Lambda) return p;
if (p.block_scope) return p.block_scope;
}
}

has_directive(type) {
var dir = this.directives[type];
if (dir) return dir;
Expand Down
48 changes: 48 additions & 0 deletions lib/compress/common.js
Expand Up @@ -80,9 +80,13 @@ import {
AST_Undefined,

TreeWalker,
walk,
walk_abort,
walk_parent,
} from "../ast.js";
import { make_node, regexp_source_fix, string_template, makePredicate } from "../utils/index.js";
import { first_in_statement } from "../utils/first_in_statement.js";
import { has_flag, TOP } from "./compressor-flags.js";

export function merge_sequence(array, node) {
if (node instanceof AST_Sequence) {
Expand Down Expand Up @@ -244,6 +248,13 @@ export function is_iife_call(node) {
return node.expression instanceof AST_Function || is_iife_call(node.expression);
}

export function is_empty(thing) {
if (thing === null) return true;
if (thing instanceof AST_EmptyStatement) return true;
if (thing instanceof AST_BlockStatement) return thing.body.length == 0;
return false;
}

export const identifier_atom = makePredicate("Infinity NaN undefined");
export function is_identifier_atom(node) {
return node instanceof AST_Infinity
Expand Down Expand Up @@ -281,6 +292,34 @@ export function as_statement_array(thing) {
throw new Error("Can't convert thing to statement array");
}

export function is_reachable(scope_node, defs) {
const find_ref = node => {
if (node instanceof AST_SymbolRef && defs.includes(node.definition())) {
return walk_abort;
}
};

return walk_parent(scope_node, (node, info) => {
if (node instanceof AST_Scope && node !== scope_node) {
var parent = info.parent();

if (
parent instanceof AST_Call
&& parent.expression === node
// Async/Generators aren't guaranteed to sync evaluate all of
// their body steps, so it's possible they close over the variable.
&& !(node.async || node.is_generator)
) {
return;
}

if (walk(node, find_ref)) return walk_abort;

return true;
}
});
}

/** Check if a ref refers to the name of a function/class it's defined within */
export function is_recursive_ref(compressor, def) {
var node;
Expand All @@ -294,3 +333,12 @@ export function is_recursive_ref(compressor, def) {
}
return false;
}

// TODO this only works with AST_Defun, shouldn't it work for other ways of defining functions?
export function retain_top_func(fn, compressor) {
return compressor.top_retain
&& fn instanceof AST_Defun
&& has_flag(fn, TOP)
&& fn.name
&& compressor.top_retain(fn.name);
}

0 comments on commit 56a05f0

Please sign in to comment.