mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 12:19:15 +00:00
fix(mangler): no shorthand BindingProperty; handle var hoisting and export variables (#4319)
Trying to pass tests in https://github.com/oxc-project/monitor-oxc
This commit is contained in:
parent
a197e01b5c
commit
3df9e697cc
4 changed files with 41 additions and 27 deletions
|
|
@ -949,7 +949,7 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for ModuleExportName<'a> {
|
|||
fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) {
|
||||
match self {
|
||||
Self::IdentifierName(identifier) => p.print_str(identifier.name.as_str()),
|
||||
Self::IdentifierReference(identifier) => p.print_str(identifier.name.as_str()),
|
||||
Self::IdentifierReference(identifier) => identifier.gen(p, ctx),
|
||||
Self::StringLiteral(literal) => literal.gen(p, ctx),
|
||||
};
|
||||
}
|
||||
|
|
@ -2538,22 +2538,19 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for ObjectPattern<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
// NOTE: `shorthand` is not printed
|
||||
impl<'a, const MINIFY: bool> Gen<MINIFY> for BindingProperty<'a> {
|
||||
fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) {
|
||||
p.add_source_mapping(self.span.start);
|
||||
if self.computed {
|
||||
p.print_char(b'[');
|
||||
}
|
||||
if !self.shorthand {
|
||||
self.key.gen(p, ctx);
|
||||
}
|
||||
self.key.gen(p, ctx);
|
||||
if self.computed {
|
||||
p.print_char(b']');
|
||||
}
|
||||
if !self.shorthand {
|
||||
p.print_colon();
|
||||
p.print_soft_space();
|
||||
}
|
||||
p.print_colon();
|
||||
p.print_soft_space();
|
||||
self.value.gen(p, ctx);
|
||||
}
|
||||
}
|
||||
|
|
@ -2959,8 +2956,8 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for TSTypeLiteral<'a> {
|
|||
impl<'a, const MINIFY: bool> Gen<MINIFY> for TSTypeName<'a> {
|
||||
fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) {
|
||||
match self {
|
||||
Self::IdentifierReference(decl) => {
|
||||
p.print_str(decl.name.as_str());
|
||||
Self::IdentifierReference(ident) => {
|
||||
ident.gen(p, ctx);
|
||||
}
|
||||
Self::QualifiedName(decl) => {
|
||||
decl.left.gen(p, ctx);
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ input_file: crates/oxc_isolated_declarations/tests/fixtures/function-parameters.
|
|||
export declare function fnDeclGood(p?: T, rParam?: string): void;
|
||||
export declare function fnDeclGood2(p?: T, rParam?: number): void;
|
||||
export declare function fooGood([a, b]?: any[]): number;
|
||||
export declare const fooGood2: ({ a, b }?: object) => number;
|
||||
export declare function fooGood3({ a, b: [{ c }] }: object): void;
|
||||
export declare const fooGood2: ({ a: a, b: b }?: object) => number;
|
||||
export declare function fooGood3({ a: a, b: [{ c: c }] }: object): void;
|
||||
export declare function fnDeclBad<T>(p: T, rParam: T, r2: T): void;
|
||||
export declare function fnDeclBad2<T>(p: T, r2: T): void;
|
||||
export declare function fnDeclBad3<T>(p: T, rParam?: T, r2: T): void;
|
||||
|
|
|
|||
|
|
@ -27,8 +27,9 @@ fn main() -> std::io::Result<()> {
|
|||
println!("{printed}");
|
||||
|
||||
if twice {
|
||||
let printed = mangler(&printed, source_type, debug);
|
||||
println!("{printed}");
|
||||
let printed2 = mangler(&printed, source_type, debug);
|
||||
println!("{printed2}");
|
||||
println!("same = {}", printed == printed2);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -77,8 +77,7 @@ impl ManglerBuilder {
|
|||
|
||||
#[must_use]
|
||||
pub fn build<'a>(self, program: &'a Program<'a>) -> Mangler {
|
||||
let semantic_ret = SemanticBuilder::new("", program.source_type).build(program);
|
||||
let semantic = semantic_ret.semantic;
|
||||
let semantic = SemanticBuilder::new("", program.source_type).build(program).semantic;
|
||||
|
||||
// Mangle the symbol table by computing slots from the scope tree.
|
||||
// A slot is the occurrence index of a binding identifier inside a scope.
|
||||
|
|
@ -96,6 +95,7 @@ impl ManglerBuilder {
|
|||
// Walk the scope tree and compute the slot number for each scope
|
||||
for scope_id in scope_tree.descendants_from_root() {
|
||||
let bindings = scope_tree.get_bindings(scope_id);
|
||||
|
||||
// The current slot number is continued by the maximum slot from the parent scope
|
||||
let parent_max_slot = scope_tree
|
||||
.get_parent_id(scope_id)
|
||||
|
|
@ -103,10 +103,28 @@ impl ManglerBuilder {
|
|||
|
||||
let mut slot = parent_max_slot;
|
||||
|
||||
// `bindings` are stored in order, traverse and increment slot
|
||||
for symbol_id in bindings.values() {
|
||||
slots[*symbol_id] = slot;
|
||||
slot += 1;
|
||||
if !bindings.is_empty() {
|
||||
let mut parent_bindings = None;
|
||||
|
||||
// `bindings` are stored in order, traverse and increment slot
|
||||
for symbol_id in bindings.values() {
|
||||
// omit var hoisting because var symbols are added to every parent scope
|
||||
if symbol_table.get_flag(*symbol_id).is_function_scoped_declaration()
|
||||
&& parent_bindings.is_none()
|
||||
{
|
||||
parent_bindings = scope_tree
|
||||
.get_parent_id(scope_id)
|
||||
.map(|parent_scope_id| scope_tree.get_bindings(parent_scope_id));
|
||||
}
|
||||
if let Some(parent_bindings) = &parent_bindings {
|
||||
if parent_bindings.values().contains(symbol_id) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
slots[*symbol_id] = slot;
|
||||
slot += 1;
|
||||
}
|
||||
}
|
||||
|
||||
max_slot_for_scope[scope_id.index()] = slot;
|
||||
|
|
@ -119,12 +137,8 @@ impl ManglerBuilder {
|
|||
let frequencies =
|
||||
Self::tally_slot_frequencies(&symbol_table, total_number_of_slots, &slots);
|
||||
|
||||
let unresolved_references = scope_tree
|
||||
.root_unresolved_references()
|
||||
.keys()
|
||||
// It is unlike to get a 5 letter mangled identifier, which is a lot of slots.
|
||||
// .filter(|name| name.len() < 5)
|
||||
.collect::<Vec<_>>();
|
||||
let unresolved_references =
|
||||
scope_tree.root_unresolved_references().keys().collect::<Vec<_>>();
|
||||
|
||||
let mut names = Vec::with_capacity(total_number_of_slots);
|
||||
|
||||
|
|
@ -195,7 +209,9 @@ impl ManglerBuilder {
|
|||
) -> Vec<SlotFrequency> {
|
||||
let mut frequencies = vec![SlotFrequency::default(); total_number_of_slots];
|
||||
for (symbol_id, slot) in slots.iter_enumerated() {
|
||||
if !symbol_table.get_flag(symbol_id).is_variable() {
|
||||
let symbol_flag = symbol_table.get_flag(symbol_id);
|
||||
// omit renaming `export { x }`
|
||||
if !symbol_flag.is_variable() || symbol_flag.is_export() {
|
||||
continue;
|
||||
}
|
||||
let index = *slot;
|
||||
|
|
|
|||
Loading…
Reference in a new issue