Skip to content

Commit faec8c1

Browse files
authored
refactor(es/utils): Unify prepend_stmts (#9493)
1 parent 5258763 commit faec8c1

File tree

4 files changed

+53
-69
lines changed

4 files changed

+53
-69
lines changed

.changeset/rare-queens-change.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
swc_ecma_transforms_typescript: patch
3+
swc_ecma_utils: patch
4+
swc_core: patch
5+
---
6+
7+
refactor(es/utils): Unify `prepend_stmts`

crates/swc_ecma_transforms_typescript/src/transform.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use swc_ecma_ast::*;
1313
use swc_ecma_utils::{
1414
alias_ident_for, constructor::inject_after_super, find_pat_ids, is_literal, member_expr,
1515
private_ident, quote_ident, quote_str, stack_size::maybe_grow_default, ExprFactory, QueryRef,
16-
RefRewriter,
16+
RefRewriter, StmtLikeInjector,
1717
};
1818
use swc_ecma_visit::{as_folder, noop_visit_mut_type, Fold, VisitMut, VisitMutWith};
1919

@@ -22,7 +22,7 @@ use crate::{
2222
ts_enum::{EnumValueComputer, InlineEnum, TsEnumRecord, TsEnumRecordKey, TsEnumRecordValue},
2323
utils::{
2424
assign_value_to_this_private_prop, assign_value_to_this_prop, AsCollapsibleDecl,
25-
AsEnumOrModule, Factory, VecStmtLike,
25+
AsEnumOrModule, Factory,
2626
},
2727
};
2828

@@ -1162,7 +1162,7 @@ impl Transform {
11621162
}
11631163

11641164
if should_inject {
1165-
n.inject_after_directive([
1165+
n.prepend_stmts([
11661166
// import { createRequire } from "module";
11671167
ImportDecl {
11681168
span: DUMMY_SP,

crates/swc_ecma_transforms_typescript/src/utils.rs

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -139,32 +139,3 @@ impl Factory {
139139
}
140140
}
141141
}
142-
143-
pub(crate) trait VecStmtLike {
144-
type StmtLike;
145-
fn inject_after_directive<T>(&mut self, replace_with: T)
146-
where
147-
T: IntoIterator<Item = Self::StmtLike>;
148-
}
149-
150-
impl VecStmtLike for Vec<ModuleItem> {
151-
type StmtLike = ModuleItem;
152-
153-
fn inject_after_directive<T>(&mut self, replace_with: T)
154-
where
155-
T: IntoIterator<Item = Self::StmtLike>,
156-
{
157-
let directive_pos = self
158-
.iter()
159-
.position(|stmt| match stmt {
160-
// search first none directive
161-
ModuleItem::Stmt(Stmt::Expr(ExprStmt { expr, .. })) => {
162-
!matches!(**expr, Expr::Lit(Lit::Str(..)))
163-
}
164-
_ => true,
165-
})
166-
.unwrap_or_default();
167-
168-
self.splice(directive_pos..directive_pos, replace_with);
169-
}
170-
}

crates/swc_ecma_utils/src/lib.rs

Lines changed: 43 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,45 @@ impl StmtLike for ModuleItem {
336336
}
337337
}
338338

339+
/// Prepends statements after directive statements.
340+
pub trait StmtLikeInjector<S>
341+
where
342+
S: StmtLike,
343+
{
344+
fn prepend_stmt(&mut self, insert_with: S);
345+
fn prepend_stmts<I>(&mut self, insert_with: I)
346+
where
347+
I: IntoIterator<Item = S>;
348+
}
349+
350+
impl<S> StmtLikeInjector<S> for Vec<S>
351+
where
352+
S: StmtLike,
353+
{
354+
/// Note: If there is no directive, use `insert` instead.
355+
fn prepend_stmt(&mut self, insert_with: S) {
356+
let directive_pos = self
357+
.iter()
358+
.position(|stmt| !stmt.as_stmt().map_or(false, is_maybe_branch_directive))
359+
.unwrap_or(self.len());
360+
361+
self.insert(directive_pos, insert_with);
362+
}
363+
364+
/// Note: If there is no directive, use `splice` instead.
365+
fn prepend_stmts<I>(&mut self, insert_with: I)
366+
where
367+
I: IntoIterator<Item = S>,
368+
{
369+
let directive_pos = self
370+
.iter()
371+
.position(|stmt| !stmt.as_stmt().map_or(false, is_maybe_branch_directive))
372+
.unwrap_or(self.len());
373+
374+
self.splice(directive_pos..directive_pos, insert_with);
375+
}
376+
}
377+
339378
pub type BoolValue = Value<bool>;
340379

341380
pub trait IsEmpty {
@@ -2218,17 +2257,9 @@ pub fn opt_chain_test(
22182257
}
22192258

22202259
/// inject `branch` after directives
2260+
#[inline]
22212261
pub fn prepend_stmt<T: StmtLike>(stmts: &mut Vec<T>, stmt: T) {
2222-
let idx = stmts
2223-
.iter()
2224-
.position(|item| {
2225-
item.as_stmt()
2226-
.map(|s| !is_maybe_branch_directive(s))
2227-
.unwrap_or(true)
2228-
})
2229-
.unwrap_or(stmts.len());
2230-
2231-
stmts.insert(idx, stmt);
2262+
stmts.prepend_stmt(stmt);
22322263
}
22332264

22342265
/// If the stmt is maybe a directive like `"use strict";`
@@ -2240,34 +2271,9 @@ pub fn is_maybe_branch_directive(stmt: &Stmt) -> bool {
22402271
}
22412272

22422273
/// inject `stmts` after directives
2274+
#[inline]
22432275
pub fn prepend_stmts<T: StmtLike>(to: &mut Vec<T>, stmts: impl ExactSizeIterator<Item = T>) {
2244-
let idx = to
2245-
.iter()
2246-
.position(|item| {
2247-
if let Some(&Stmt::Expr(ExprStmt { ref expr, .. })) = item.as_stmt() {
2248-
match &**expr {
2249-
Expr::Lit(Lit::Str(..)) => return false,
2250-
Expr::Call(expr) => match expr.callee {
2251-
Callee::Super(_) | Callee::Import(_) => return false,
2252-
Callee::Expr(_) => {}
2253-
},
2254-
_ => {}
2255-
}
2256-
}
2257-
2258-
true
2259-
})
2260-
.unwrap_or(to.len());
2261-
2262-
let mut buf = Vec::with_capacity(to.len() + stmts.len());
2263-
// TODO: Optimize (maybe unsafe)
2264-
2265-
buf.extend(to.drain(..idx));
2266-
buf.extend(stmts);
2267-
buf.append(to);
2268-
debug_assert!(to.is_empty());
2269-
2270-
*to = buf
2276+
to.prepend_stmts(stmts);
22712277
}
22722278

22732279
pub trait IsDirective {

0 commit comments

Comments
 (0)