feat(minifier): scaffold peephole replace known methods. (#6245)

This commit is contained in:
7086cmd 2024-10-02 14:06:05 +00:00
parent c32af57e13
commit ee6c85003d
3 changed files with 101 additions and 4 deletions

View file

@ -3,6 +3,7 @@ mod exploit_assigns;
mod peephole_fold_constants;
mod peephole_minimize_conditions;
mod peephole_remove_dead_code;
mod peephole_replace_known_methods;
mod peephole_substitute_alternate_syntax;
mod remove_syntax;
mod statement_fusion;
@ -12,6 +13,7 @@ pub use exploit_assigns::ExploitAssigns;
pub use peephole_fold_constants::PeepholeFoldConstants;
pub use peephole_minimize_conditions::PeepholeMinimizeConditions;
pub use peephole_remove_dead_code::PeepholeRemoveDeadCode;
pub use peephole_replace_known_methods::PeepholeReplaceKnownMethods;
pub use peephole_substitute_alternate_syntax::PeepholeSubstituteAlternateSyntax;
pub use remove_syntax::RemoveSyntax;
pub use statement_fusion::StatementFusion;

View file

@ -0,0 +1,95 @@
use oxc_ast::ast::*;
use oxc_traverse::{Traverse, TraverseCtx};
use crate::CompressorPass;
/// Minimize With Known Methods
/// <https://github.com/google/closure-compiler/blob/master/src/com/google/javascript/jscomp/PeepholeMinimizeReplacements.java>
pub struct PeepholeReplaceKnownMethods {
changed: bool,
}
impl<'a> CompressorPass<'a> for PeepholeReplaceKnownMethods {
fn changed(&self) -> bool {
self.changed
}
fn build(&mut self, _program: &mut Program<'a>, _ctx: &mut TraverseCtx<'a>) {
self.changed = false;
// oxc_traverse::walk_program(self, program, ctx);
}
}
impl<'a> Traverse<'a> for PeepholeReplaceKnownMethods {}
impl PeepholeReplaceKnownMethods {
pub fn new() -> Self {
Self { changed: false }
}
}
/// <https://github.com/google/closure-compiler/blob/master/test/com/google/javascript/jscomp/PeepholeReplaceKnownMethodsTest.java>
#[cfg(test)]
mod test {
use oxc_allocator::Allocator;
use crate::tester;
fn test(source_text: &str, positive: &str) {
let allocator = Allocator::default();
let mut pass = super::PeepholeReplaceKnownMethods::new();
tester::test(&allocator, source_text, positive, &mut pass);
}
fn test_same(source_text: &str) {
test(source_text, source_text);
}
fn fold_same(js: &str) {
test_same(js);
}
fn fold(js: &str, expected: &str) {
test(js, expected);
}
#[test]
#[ignore]
fn test_string_index_of() {
fold("x = 'abcdef'.indexOf('g')", "x = -1");
fold("x = 'abcdef'.indexOf('b')", "x = 1");
fold("x = 'abcdefbe'.indexOf('b', 2)", "x = 6");
fold("x = 'abcdef'.indexOf('bcd')", "x = 1");
fold("x = 'abcdefsdfasdfbcdassd'.indexOf('bcd', 4)", "x = 13");
fold("x = 'abcdef'.lastIndexOf('b')", "x = 1");
fold("x = 'abcdefbe'.lastIndexOf('b')", "x = 6");
fold("x = 'abcdefbe'.lastIndexOf('b', 5)", "x = 1");
// Both elements must be strings. Don't do anything if either one is not
// string.
fold("x = 'abc1def'.indexOf(1)", "x = 3");
fold("x = 'abcNaNdef'.indexOf(NaN)", "x = 3");
fold("x = 'abcundefineddef'.indexOf(undefined)", "x = 3");
fold("x = 'abcnulldef'.indexOf(null)", "x = 3");
fold("x = 'abctruedef'.indexOf(true)", "x = 3");
// The following test case fails with JSC_PARSE_ERROR. Hence omitted.
// fold_same("x = 1.indexOf('bcd');");
fold_same("x = NaN.indexOf('bcd')");
fold_same("x = undefined.indexOf('bcd')");
fold_same("x = null.indexOf('bcd')");
fold_same("x = true.indexOf('bcd')");
fold_same("x = false.indexOf('bcd')");
// Avoid dealing with regex or other types.
fold_same("x = 'abcdef'.indexOf(/b./)");
fold_same("x = 'abcdef'.indexOf({a:2})");
fold_same("x = 'abcdef'.indexOf([1,2])");
// Template Strings
fold_same("x = `abcdef`.indexOf('b')");
fold_same("x = `Hello ${name}`.indexOf('a')");
fold_same("x = tag `Hello ${name}`.indexOf('a')");
}
}

View file

@ -6,8 +6,8 @@ use oxc_traverse::TraverseCtx;
use crate::{
ast_passes::{
CollapseVariableDeclarations, ExploitAssigns, PeepholeFoldConstants,
PeepholeMinimizeConditions, PeepholeRemoveDeadCode, PeepholeSubstituteAlternateSyntax,
RemoveSyntax, StatementFusion,
PeepholeMinimizeConditions, PeepholeRemoveDeadCode, PeepholeReplaceKnownMethods,
PeepholeSubstituteAlternateSyntax, RemoveSyntax, StatementFusion,
},
CompressOptions, CompressorPass,
};
@ -46,13 +46,13 @@ impl<'a> Compressor<'a> {
CollapseVariableDeclarations::new(self.options).build(program, &mut ctx);
// See `latePeepholeOptimizations`
let mut passes: [&mut dyn CompressorPass; 5] = [
let mut passes: [&mut dyn CompressorPass; 6] = [
&mut StatementFusion::new(),
&mut PeepholeRemoveDeadCode::new(),
// TODO: MinimizeExitPoints
&mut PeepholeMinimizeConditions::new(),
&mut PeepholeSubstituteAlternateSyntax::new(self.options),
// TODO: PeepholeReplaceKnownMethods
&mut PeepholeReplaceKnownMethods::new(),
&mut PeepholeFoldConstants::new(),
];