Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions crates/oxc_transformer/src/es2015/arrow_functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ impl<'a> Traverse<'a> for ArrowFunctions<'a> {

/// Insert `var _this = this;` for the global scope.
fn exit_program(&mut self, program: &mut Program<'a>, ctx: &mut TraverseCtx<'a>) {
if let Some(this_var) = self.this_var_stack.take() {
if let Some(this_var) = self.this_var_stack.take_last() {
self.insert_this_var_statement_at_the_top_of_statements(
&mut program.body,
&this_var,
Expand Down Expand Up @@ -270,7 +270,7 @@ impl<'a> ArrowFunctions<'a> {
// `this` can be in scope at a time. We could create a single `_this` UID and reuse it in each
// scope. But this does not match output for some of Babel's test cases.
// <https://github.com/oxc-project/oxc/pull/5840>
let this_var = self.this_var_stack.get_or_init(|| {
let this_var = self.this_var_stack.last_or_init(|| {
let target_scope_id = ctx
.scopes()
.ancestors(arrow_scope_id)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ impl<'a> ExponentiationOperator<'a> {
let id = ctx.ast.binding_pattern_kind_from_binding_identifier(binding_identifier);
let id = ctx.ast.binding_pattern(id, NONE, false);
self.var_declarations
.get_mut_or_init(|| ctx.ast.vec())
.last_mut_or_init(|| ctx.ast.vec())
.push(ctx.ast.variable_declarator(SPAN, kind, id, None, false));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ impl<'a> Traverse<'a> for NullishCoalescingOperator<'a> {
} else {
let kind = VariableDeclarationKind::Var;
self.var_declarations
.get_mut_or_init(|| ctx.ast.vec())
.last_mut_or_init(|| ctx.ast.vec())
.push(ctx.ast.variable_declarator(SPAN, kind, id, None, false));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ impl<'a> LogicalAssignmentOperators<'a> {
let id = ctx.ast.binding_pattern_kind_from_binding_identifier(binding_identifier);
let id = ctx.ast.binding_pattern(id, NONE, false);
self.var_declarations
.get_mut_or_init(|| ctx.ast.vec())
.last_mut_or_init(|| ctx.ast.vec())
.push(ctx.ast.variable_declarator(SPAN, kind, id, None, false));

// _name = name
Expand Down
30 changes: 15 additions & 15 deletions crates/oxc_transformer/src/helpers/stack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
///
/// Stack is initialized with a single entry which can never be popped off.
/// If `Program` has a entry on the stack, can use this initial entry for it. Get value for `Program`
/// in `exit_program` visitor with `SparseStack::take` instead of `SparseStack::pop`.
/// in `exit_program` visitor with `SparseStack::take_last` instead of `SparseStack::pop`.
///
/// The stack is stored as 2 arrays:
/// 1. `has_values` - Records whether an entry on the stack has a value or not (`Some` or `None`).
Expand All @@ -30,7 +30,7 @@ impl<T> SparseStack<T> {
/// Create new `SparseStack`.
pub fn new() -> Self {
// `has_values` starts with a single empty entry, which will never be popped off.
// This means `take`, `get_or_init`, and `get_mut_or_init` can all be infallible,
// This means `take_last`, `last_or_init`, and `last_mut_or_init` can all be infallible,
// as there's always an entry on the stack to read.
Self { has_values: vec![false], values: vec![] }
}
Expand Down Expand Up @@ -75,7 +75,7 @@ impl<T> SparseStack<T> {
if has_value {
debug_assert!(!self.values.is_empty());
// SAFETY: Last `self.has_values` is only `true` if there's a corresponding value in `self.values`.
// This invariant is maintained in `push`, `take`, `get_or_init`, and `get_mut_or_init`.
// This invariant is maintained in `push`, `take_last`, `last_or_init`, and `last_mut_or_init`.
// We maintain it here too because we just popped from `self.has_values`, so that `true`
// has been consumed at the same time we consume its corresponding value from `self.values`.
let value = unsafe { self.values.pop().unwrap_unchecked() };
Expand All @@ -85,19 +85,19 @@ impl<T> SparseStack<T> {
}
}

/// Take value from last entry on the stack.
/// Take value from last entry on the stack, leaving last entry empty.
#[inline]
pub fn take(&mut self) -> Option<T> {
pub fn take_last(&mut self) -> Option<T> {
debug_assert!(!self.has_values.is_empty());
// SAFETY: `self.has_values` starts with 1 entry. Only `pop` removes entries from it,
// and it ensures `self.has_values` always has at least one entry.
// and it ensures `self.has_values` always has at least 1 entry.
let has_value = unsafe { self.has_values.last_mut().unwrap_unchecked() };
if *has_value {
*has_value = false;

debug_assert!(!self.values.is_empty());
// SAFETY: Last `self.has_values` is only `true` if there's a corresponding value in `self.values`.
// This invariant is maintained in `push`, `pop`, `get_or_init`, and `get_mut_or_init`.
// This invariant is maintained in `push`, `pop`, `last_or_init`, and `last_mut_or_init`.
// We maintain it here too because we just set last `self.has_values` to `false`
// at the same time as we consume the corresponding value from `self.values`.
let value = unsafe { self.values.pop().unwrap_unchecked() };
Expand All @@ -107,13 +107,13 @@ impl<T> SparseStack<T> {
}
}

/// Initialize the value for top entry on the stack, if it has no value already.
/// Initialize the value for last entry on the stack, if it has no value already.
/// Return reference to value.
#[inline]
pub fn get_or_init<I: FnOnce() -> T>(&mut self, init: I) -> &T {
pub fn last_or_init<I: FnOnce() -> T>(&mut self, init: I) -> &T {
debug_assert!(!self.has_values.is_empty());
// SAFETY: `self.has_values` starts with 1 entry. Only `pop` removes entries from it,
// and it ensures `self.has_values` always has at least one entry.
// and it ensures `self.has_values` always has at least 1 entry.
let has_value = unsafe { self.has_values.last_mut().unwrap_unchecked() };
if !*has_value {
*has_value = true;
Expand All @@ -122,27 +122,27 @@ impl<T> SparseStack<T> {

debug_assert!(!self.values.is_empty());
// SAFETY: Last `self.has_values` is only `true` if there's a corresponding value in `self.values`.
// This invariant is maintained in `push`, `pop`, `take`, and `get_mut_or_init`.
// This invariant is maintained in `push`, `pop`, `take_last`, and `last_mut_or_init`.
// Here either last `self.has_values` was already `true`, or it's just been set to `true`
// and a value pushed to `self.values` above.
unsafe { self.values.last().unwrap_unchecked() }
}

/// Initialize the value for top entry on the stack, if it has no value already.
/// Initialize the value for last entry on the stack, if it has no value already.
/// Return mutable reference to value.
#[inline]
pub fn get_mut_or_init<I: FnOnce() -> T>(&mut self, init: I) -> &mut T {
pub fn last_mut_or_init<I: FnOnce() -> T>(&mut self, init: I) -> &mut T {
debug_assert!(!self.has_values.is_empty());
// SAFETY: `self.has_values` starts with 1 entry. Only `pop` removes entries from it,
// and it ensures `self.has_values` always has at least one entry.
// and it ensures `self.has_values` always has at least 1 entry.
let has_value = unsafe { self.has_values.last_mut().unwrap_unchecked() };
if !*has_value {
*has_value = true;
self.values.push(init());
}

// SAFETY: Last `self.has_values` is only `true` if there's a corresponding value in `self.values`.
// This invariant is maintained in `push`, `pop`, `take`, and `get_or_init`.
// This invariant is maintained in `push`, `pop`, `take_last`, and `last_or_init`.
// Here either last `self.has_values` was already `true`, or it's just been set to `true`
// and a value pushed to `self.values` above.
unsafe { self.values.last_mut().unwrap_unchecked() }
Expand Down