From 5e14fe95100c3086fc74905dfb38292e7563c766 Mon Sep 17 00:00:00 2001 From: shulaoda <165626830+shulaoda@users.noreply.github.com> Date: Thu, 27 Mar 2025 14:30:10 +0000 Subject: [PATCH 01/15] perf(linter): inline `PRE_DEFINE_VAR` and use `array` format (#10079) Related to #10076 --- crates/oxc_linter/src/globals.rs | 10 +--------- .../src/rules/eslint/no_shadow_restricted_names.rs | 6 ++++-- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/crates/oxc_linter/src/globals.rs b/crates/oxc_linter/src/globals.rs index e24589f6042fb..4045af29410ac 100644 --- a/crates/oxc_linter/src/globals.rs +++ b/crates/oxc_linter/src/globals.rs @@ -1,12 +1,4 @@ -use phf::{Map, phf_map, phf_set}; - -pub const PRE_DEFINE_VAR: Map<&'static str, bool> = phf_map! { - "undefined" => false, - "Infinity" => false, - "NaN" => false, - "eval" => false, - "arguments" => false, -}; +use phf::phf_set; pub const GLOBAL_OBJECT_NAMES: phf::Set<&'static str> = phf_set! { "global", diff --git a/crates/oxc_linter/src/rules/eslint/no_shadow_restricted_names.rs b/crates/oxc_linter/src/rules/eslint/no_shadow_restricted_names.rs index d942fa6829ce5..04791fb77f8d1 100644 --- a/crates/oxc_linter/src/rules/eslint/no_shadow_restricted_names.rs +++ b/crates/oxc_linter/src/rules/eslint/no_shadow_restricted_names.rs @@ -4,7 +4,9 @@ use oxc_macros::declare_oxc_lint; use oxc_span::Span; use oxc_syntax::symbol::SymbolId; -use crate::{context::LintContext, globals::PRE_DEFINE_VAR, rule::Rule}; +use crate::{context::LintContext, rule::Rule}; + +const PRE_DEFINE_VAR: [&str; 5] = ["undefined", "Infinity", "NaN", "eval", "arguments"]; fn no_shadow_restricted_names_diagnostic(shadowed_name: &str, span: Span) -> OxcDiagnostic { OxcDiagnostic::warn("Shadowing of global properties such as 'undefined' is not allowed.") @@ -79,7 +81,7 @@ impl Rule for NoShadowRestrictedNames { fn run_on_symbol(&self, symbol_id: SymbolId, ctx: &LintContext<'_>) { let name = ctx.scoping().symbol_name(symbol_id); - if !PRE_DEFINE_VAR.contains_key(name) { + if !PRE_DEFINE_VAR.contains(&name) { return; } From 8e55395efb03505c2e3bf6ff496248a21290d07a Mon Sep 17 00:00:00 2001 From: Sysix <3897725+Sysix@users.noreply.github.com> Date: Thu, 27 Mar 2025 21:20:42 +0000 Subject: [PATCH 02/15] chore(editor): git ignore test_workspace (#10082) --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 461af1d485b23..f5c456436da18 100644 --- a/.gitignore +++ b/.gitignore @@ -22,6 +22,7 @@ target/ /editors/vscode/icon.png /editors/vscode/out/ /editors/vscode/*.vsix +/editors/vscode/test_workspace/ # Cloned conformance repos tasks/coverage/babel/ From 84e167ee9f7f145e9b211d07f53f7462bffa7db5 Mon Sep 17 00:00:00 2001 From: Dunqing <29533304+Dunqing@users.noreply.github.com> Date: Fri, 28 Mar 2025 04:12:20 +0000 Subject: [PATCH 03/15] perf(semantic): use `FxHashMap` to replace `IndexVec` for `symbol_redeclarations` (#10058) Further improve on https://github.com/oxc-project/oxc/pull/4463. As #4463 said: > Most symbols don't have redeclarations. Yes, so inserting a `None` for every `SymbolId` is also unnecessary, changes to `FxHashMap` so that we can insert where redeclaration appears. There is a 1% performance improvement in semantic! image --- crates/oxc_semantic/src/scoping.rs | 66 ++++++++++++++---------------- 1 file changed, 31 insertions(+), 35 deletions(-) diff --git a/crates/oxc_semantic/src/scoping.rs b/crates/oxc_semantic/src/scoping.rs index 9b31c010a1ac8..2537744c8a6a8 100644 --- a/crates/oxc_semantic/src/scoping.rs +++ b/crates/oxc_semantic/src/scoping.rs @@ -1,6 +1,6 @@ -use std::{fmt, mem}; +use std::{collections::hash_map::Entry, fmt, mem}; -use rustc_hash::FxHashSet; +use rustc_hash::{FxHashMap, FxHashSet}; use oxc_allocator::{Allocator, CloneIn, FromIn, HashMap as ArenaHashMap, Vec as ArenaVec}; use oxc_index::{Idx, IndexVec}; @@ -9,7 +9,7 @@ use oxc_syntax::{ node::NodeId, reference::{Reference, ReferenceId}, scope::{ScopeFlags, ScopeId}, - symbol::{RedeclarationId, SymbolFlags, SymbolId}, + symbol::{SymbolFlags, SymbolId}, }; pub type Bindings<'a> = ArenaHashMap<'a, &'a str, SymbolId>; @@ -40,7 +40,6 @@ pub struct Scoping { pub(crate) symbol_scope_ids: IndexVec, /// Pointer to the AST Node where this symbol is declared pub(crate) symbol_declarations: IndexVec, - symbol_redeclarations: IndexVec>, pub(crate) references: IndexVec, @@ -75,7 +74,6 @@ impl Default for Scoping { symbol_flags: IndexVec::new(), symbol_scope_ids: IndexVec::new(), symbol_declarations: IndexVec::new(), - symbol_redeclarations: IndexVec::new(), references: IndexVec::new(), no_side_effects: FxHashSet::default(), scope_parent_ids: IndexVec::new(), @@ -85,7 +83,7 @@ impl Default for Scoping { cell: ScopingCell::new(Allocator::default(), |allocator| ScopingInner { symbol_names: ArenaVec::new_in(allocator), resolved_references: ArenaVec::new_in(allocator), - redeclaration_spans: ArenaVec::new_in(allocator), + symbol_redeclarations: FxHashMap::default(), bindings: IndexVec::new(), scope_child_ids: ArenaVec::new_in(allocator), root_unresolved_references: UnresolvedReferences::new_in(allocator), @@ -106,7 +104,7 @@ pub struct ScopingInner<'cell> { /* Symbol Table Fields */ symbol_names: ArenaVec<'cell, Atom<'cell>>, resolved_references: ArenaVec<'cell, ArenaVec<'cell, ReferenceId>>, - redeclaration_spans: ArenaVec<'cell, ArenaVec<'cell, Span>>, + symbol_redeclarations: FxHashMap>, /* Scope Tree Fields */ /// Symbol bindings in a scope. /// @@ -196,12 +194,13 @@ impl Scoping { #[inline] pub fn symbol_redeclarations(&self, symbol_id: SymbolId) -> &[Span] { - if let Some(redeclaration_id) = self.symbol_redeclarations[symbol_id] { - &self.cell.borrow_dependent().redeclaration_spans[redeclaration_id.index()] - } else { - static EMPTY: &[Span] = &[]; - EMPTY - } + self.cell.borrow_dependent().symbol_redeclarations.get(&symbol_id).map_or_else( + || { + static EMPTY: &[Span] = &[]; + EMPTY + }, + |spans| spans.as_slice(), + ) } #[inline] @@ -242,31 +241,27 @@ impl Scoping { scope_id: ScopeId, node_id: NodeId, ) -> SymbolId { - self.symbol_spans.push(span); - self.symbol_flags.push(flags); - self.symbol_scope_ids.push(scope_id); - self.symbol_declarations.push(node_id); self.cell.with_dependent_mut(|allocator, cell| { cell.symbol_names.push(Atom::from_in(name, allocator)); cell.resolved_references.push(ArenaVec::new_in(allocator)); }); - self.symbol_redeclarations.push(None) + self.symbol_spans.push(span); + self.symbol_flags.push(flags); + self.symbol_scope_ids.push(scope_id); + self.symbol_declarations.push(node_id) } pub fn add_symbol_redeclaration(&mut self, symbol_id: SymbolId, span: Span) { - if let Some(redeclaration_id) = self.symbol_redeclarations[symbol_id] { - self.cell.with_dependent_mut(|_, cell| { - cell.redeclaration_spans[redeclaration_id.index()].push(span); - }); - } else { - self.cell.with_dependent_mut(|allocator, cell| { - let v = ArenaVec::from_array_in([span], allocator); - let redeclaration_id = cell.redeclaration_spans.len(); - cell.redeclaration_spans.push(v); - self.symbol_redeclarations[symbol_id] = - Some(RedeclarationId::from_usize(redeclaration_id)); - }); - }; + self.cell.with_dependent_mut(|allocator, cell| { + match cell.symbol_redeclarations.entry(symbol_id) { + Entry::Occupied(mut entry) => { + entry.get_mut().push(span); + } + Entry::Vacant(entry) => { + entry.insert(ArenaVec::from_array_in([span], allocator)); + } + } + }); } pub fn create_reference(&mut self, reference: Reference) -> ReferenceId { @@ -779,7 +774,6 @@ impl Scoping { symbol_flags: self.symbol_flags.clone(), symbol_scope_ids: self.symbol_scope_ids.clone(), symbol_declarations: self.symbol_declarations.clone(), - symbol_redeclarations: self.symbol_redeclarations.clone(), references: self.references.clone(), no_side_effects: self.no_side_effects.clone(), scope_parent_ids: self.scope_parent_ids.clone(), @@ -793,9 +787,11 @@ impl Scoping { resolved_references: cell .resolved_references .clone_in_with_semantic_ids(allocator), - redeclaration_spans: cell - .redeclaration_spans - .clone_in_with_semantic_ids(allocator), + symbol_redeclarations: cell + .symbol_redeclarations + .iter() + .map(|(k, v)| (*k, v.clone_in_with_semantic_ids(allocator))) + .collect(), bindings: cell .bindings .iter() From b804f7c23bba52905257bbbafb70863d0b60e1ce Mon Sep 17 00:00:00 2001 From: Dunqing <29533304+Dunqing@users.noreply.github.com> Date: Fri, 28 Mar 2025 04:12:21 +0000 Subject: [PATCH 04/15] feat(semantic): introduce `Redeclaraion` for `Scoping::symbol_declarations` (#10059) Introduce the `Redeclaration` struct so that we can add more information to it later. --- .../src/rules/eslint/no_redeclare.rs | 6 ++-- .../eslint/no_shadow_restricted_names.rs | 4 +-- crates/oxc_semantic/src/scoping.rs | 30 ++++++++++++------- .../src/typescript/namespace.rs | 2 +- tasks/transform_checker/src/lib.rs | 6 +++- 5 files changed, 31 insertions(+), 17 deletions(-) diff --git a/crates/oxc_linter/src/rules/eslint/no_redeclare.rs b/crates/oxc_linter/src/rules/eslint/no_redeclare.rs index d18bd58a8a462..0f733511efbbf 100644 --- a/crates/oxc_linter/src/rules/eslint/no_redeclare.rs +++ b/crates/oxc_linter/src/rules/eslint/no_redeclare.rs @@ -82,11 +82,11 @@ impl Rule for NoRedeclare { ctx.diagnostic(no_redeclare_as_builtin_in_diagnostic(name, decl_span)); } - for span in ctx.scoping().symbol_redeclarations(symbol_id) { + for rd in ctx.scoping().symbol_redeclarations(symbol_id) { if is_builtin { - ctx.diagnostic(no_redeclare_as_builtin_in_diagnostic(name, *span)); + ctx.diagnostic(no_redeclare_as_builtin_in_diagnostic(name, rd.span)); } else { - ctx.diagnostic(no_redeclare_diagnostic(name, decl_span, *span)); + ctx.diagnostic(no_redeclare_diagnostic(name, decl_span, rd.span)); } } } diff --git a/crates/oxc_linter/src/rules/eslint/no_shadow_restricted_names.rs b/crates/oxc_linter/src/rules/eslint/no_shadow_restricted_names.rs index 04791fb77f8d1..c99216c86b8ab 100644 --- a/crates/oxc_linter/src/rules/eslint/no_shadow_restricted_names.rs +++ b/crates/oxc_linter/src/rules/eslint/no_shadow_restricted_names.rs @@ -103,8 +103,8 @@ impl Rule for NoShadowRestrictedNames { let span = ctx.scoping().symbol_span(symbol_id); ctx.diagnostic(no_shadow_restricted_names_diagnostic(name, span)); - for &span in ctx.scoping().symbol_redeclarations(symbol_id) { - ctx.diagnostic(no_shadow_restricted_names_diagnostic(name, span)); + for rd in ctx.scoping().symbol_redeclarations(symbol_id) { + ctx.diagnostic(no_shadow_restricted_names_diagnostic(name, rd.span)); } } } diff --git a/crates/oxc_semantic/src/scoping.rs b/crates/oxc_semantic/src/scoping.rs index 2537744c8a6a8..08978bbd8edb3 100644 --- a/crates/oxc_semantic/src/scoping.rs +++ b/crates/oxc_semantic/src/scoping.rs @@ -15,6 +15,11 @@ use oxc_syntax::{ pub type Bindings<'a> = ArenaHashMap<'a, &'a str, SymbolId>; pub type UnresolvedReferences<'a> = ArenaHashMap<'a, &'a str, ArenaVec<'a, ReferenceId>>; +#[derive(Debug)] +pub struct Redeclaration { + pub span: Span, +} + /// # Symbol Table and Scope Tree /// /// ## Symbol Table @@ -104,7 +109,7 @@ pub struct ScopingInner<'cell> { /* Symbol Table Fields */ symbol_names: ArenaVec<'cell, Atom<'cell>>, resolved_references: ArenaVec<'cell, ArenaVec<'cell, ReferenceId>>, - symbol_redeclarations: FxHashMap>, + symbol_redeclarations: FxHashMap>, /* Scope Tree Fields */ /// Symbol bindings in a scope. /// @@ -193,13 +198,13 @@ impl Scoping { } #[inline] - pub fn symbol_redeclarations(&self, symbol_id: SymbolId) -> &[Span] { + pub fn symbol_redeclarations(&self, symbol_id: SymbolId) -> &[Redeclaration] { self.cell.borrow_dependent().symbol_redeclarations.get(&symbol_id).map_or_else( || { - static EMPTY: &[Span] = &[]; + static EMPTY: &[Redeclaration] = &[]; EMPTY }, - |spans| spans.as_slice(), + |v| v.as_slice(), ) } @@ -253,12 +258,14 @@ impl Scoping { pub fn add_symbol_redeclaration(&mut self, symbol_id: SymbolId, span: Span) { self.cell.with_dependent_mut(|allocator, cell| { + let redeclaration = Redeclaration { span }; match cell.symbol_redeclarations.entry(symbol_id) { - Entry::Occupied(mut entry) => { - entry.get_mut().push(span); + Entry::Occupied(occupied) => { + occupied.into_mut().push(redeclaration); } - Entry::Vacant(entry) => { - entry.insert(ArenaVec::from_array_in([span], allocator)); + Entry::Vacant(vacant) => { + let v = ArenaVec::from_array_in([redeclaration], allocator); + vacant.insert(v); } } }); @@ -790,8 +797,11 @@ impl Scoping { symbol_redeclarations: cell .symbol_redeclarations .iter() - .map(|(k, v)| (*k, v.clone_in_with_semantic_ids(allocator))) - .collect(), + .map(|(k, v)| { + let v = v.iter().map(|r| Redeclaration { span: r.span }); + (*k, ArenaVec::from_iter_in(v, allocator)) + }) + .collect::>(), bindings: cell .bindings .iter() diff --git a/crates/oxc_transformer/src/typescript/namespace.rs b/crates/oxc_transformer/src/typescript/namespace.rs index c475234807078..f24beb7b0f6bc 100644 --- a/crates/oxc_transformer/src/typescript/namespace.rs +++ b/crates/oxc_transformer/src/typescript/namespace.rs @@ -468,7 +468,7 @@ impl<'a> TypeScriptNamespace<'a, '_> { // namespace Foo {} // is redeclaration // ``` let redeclarations = ctx.scoping().symbol_redeclarations(symbol_id); - !redeclarations.is_empty() && redeclarations.contains(&id.span) + !redeclarations.is_empty() && redeclarations.iter().any(|rd| rd.span == id.span) } } } diff --git a/tasks/transform_checker/src/lib.rs b/tasks/transform_checker/src/lib.rs index 0ab84e9d60cce..05b85e804149d 100644 --- a/tasks/transform_checker/src/lib.rs +++ b/tasks/transform_checker/src/lib.rs @@ -427,7 +427,11 @@ impl PostTransformChecker<'_, '_> { // Check redeclarations match let redeclaration_spans = self.get_pair(symbol_ids, |scoping, symbol_id| { - let mut spans = scoping.symbol_redeclarations(symbol_id).to_vec(); + let mut spans = scoping + .symbol_redeclarations(symbol_id) + .iter() + .map(|rd| rd.span) + .collect::>(); spans.sort_unstable(); spans }); From 528469e2d803b3b830f8931fcff41eefabde6411 Mon Sep 17 00:00:00 2001 From: Dunqing <29533304+Dunqing@users.noreply.github.com> Date: Fri, 28 Mar 2025 04:12:21 +0000 Subject: [PATCH 05/15] feat(semantic/scoping): add `declaration` and `flags` fields for Redeclaraion (#10060) `declaration` and `flags` are also fields of the symbol. Before, we only had a span info in `symbol_redeclarations`, which means we have no way to know what the redeclaration AST node is and what the symbol flags is --- crates/oxc_semantic/src/binder.rs | 2 +- crates/oxc_semantic/src/builder.rs | 11 ++++++++--- crates/oxc_semantic/src/scoping.rs | 18 +++++++++++++++--- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/crates/oxc_semantic/src/binder.rs b/crates/oxc_semantic/src/binder.rs index 91da0536b55c6..8ad73a467c8b1 100644 --- a/crates/oxc_semantic/src/binder.rs +++ b/crates/oxc_semantic/src/binder.rs @@ -63,7 +63,7 @@ impl<'a> Binder<'a> for VariableDeclarator<'a> { if let Some(symbol_id) = builder.check_redeclaration(scope_id, span, &name, excludes, true) { - builder.add_redeclare_variable(symbol_id, span); + builder.add_redeclare_variable(symbol_id, includes, span); declared_symbol_id = Some(symbol_id); // remove current scope binding and add to target scope diff --git a/crates/oxc_semantic/src/builder.rs b/crates/oxc_semantic/src/builder.rs index bd8f180d3701b..a181f82ca687d 100644 --- a/crates/oxc_semantic/src/builder.rs +++ b/crates/oxc_semantic/src/builder.rs @@ -388,7 +388,7 @@ impl<'a> SemanticBuilder<'a> { ) -> SymbolId { if let Some(symbol_id) = self.check_redeclaration(scope_id, span, name, excludes, true) { self.scoping.union_symbol_flag(symbol_id, includes); - self.add_redeclare_variable(symbol_id, span); + self.add_redeclare_variable(symbol_id, includes, span); return symbol_id; } @@ -561,8 +561,13 @@ impl<'a> SemanticBuilder<'a> { } } - pub(crate) fn add_redeclare_variable(&mut self, symbol_id: SymbolId, span: Span) { - self.scoping.add_symbol_redeclaration(symbol_id, span); + pub(crate) fn add_redeclare_variable( + &mut self, + symbol_id: SymbolId, + flags: SymbolFlags, + span: Span, + ) { + self.scoping.add_symbol_redeclaration(symbol_id, flags, self.current_node_id, span); } } diff --git a/crates/oxc_semantic/src/scoping.rs b/crates/oxc_semantic/src/scoping.rs index 08978bbd8edb3..efe6110b62b8a 100644 --- a/crates/oxc_semantic/src/scoping.rs +++ b/crates/oxc_semantic/src/scoping.rs @@ -18,6 +18,8 @@ pub type UnresolvedReferences<'a> = ArenaHashMap<'a, &'a str, ArenaVec<'a, Refer #[derive(Debug)] pub struct Redeclaration { pub span: Span, + pub declaration: NodeId, + pub flags: SymbolFlags, } /// # Symbol Table and Scope Tree @@ -256,9 +258,15 @@ impl Scoping { self.symbol_declarations.push(node_id) } - pub fn add_symbol_redeclaration(&mut self, symbol_id: SymbolId, span: Span) { + pub fn add_symbol_redeclaration( + &mut self, + symbol_id: SymbolId, + flags: SymbolFlags, + declaration: NodeId, + span: Span, + ) { self.cell.with_dependent_mut(|allocator, cell| { - let redeclaration = Redeclaration { span }; + let redeclaration = Redeclaration { span, declaration, flags }; match cell.symbol_redeclarations.entry(symbol_id) { Entry::Occupied(occupied) => { occupied.into_mut().push(redeclaration); @@ -798,7 +806,11 @@ impl Scoping { .symbol_redeclarations .iter() .map(|(k, v)| { - let v = v.iter().map(|r| Redeclaration { span: r.span }); + let v = v.iter().map(|r| Redeclaration { + span: r.span, + declaration: r.declaration, + flags: r.flags, + }); (*k, ArenaVec::from_iter_in(v, allocator)) }) .collect::>(), From cd1f0359a36023ec80b95054296d314c02f6e188 Mon Sep 17 00:00:00 2001 From: Dunqing <29533304+Dunqing@users.noreply.github.com> Date: Fri, 28 Mar 2025 04:12:21 +0000 Subject: [PATCH 06/15] refactor(semantic)!: store symbol information as the first entry in `symbol_declarations` when it is redeclared (#10062) This PR aims to solve a problem where the flags of a symbol would merge its redeclaration symbol flags, which means we can't know what the flags of the first definition is. This PR changes to when a symbol is redeclared, store the symbol itself as the first entry of `symbol_redeclarations`, from which we can know the `flags` of every definition. --- .../src/rules/eslint/no_redeclare.rs | 8 +- .../eslint/no_shadow_restricted_names.rs | 13 +- .../src/snapshots/eslint_no_redeclare.snap | 8 +- crates/oxc_semantic/src/builder.rs | 2 +- crates/oxc_semantic/src/scoping.rs | 23 +- .../src/typescript/namespace.rs | 14 +- tasks/coverage/snapshots/semantic_babel.snap | 90 ++--- .../snapshots/semantic_typescript.snap | 342 +++++++++--------- .../snapshots/babel.snap.md | 36 +- .../snapshots/oxc.snap.md | 10 +- 10 files changed, 281 insertions(+), 265 deletions(-) diff --git a/crates/oxc_linter/src/rules/eslint/no_redeclare.rs b/crates/oxc_linter/src/rules/eslint/no_redeclare.rs index 0f733511efbbf..15ea27fb720fb 100644 --- a/crates/oxc_linter/src/rules/eslint/no_redeclare.rs +++ b/crates/oxc_linter/src/rules/eslint/no_redeclare.rs @@ -82,11 +82,13 @@ impl Rule for NoRedeclare { ctx.diagnostic(no_redeclare_as_builtin_in_diagnostic(name, decl_span)); } - for rd in ctx.scoping().symbol_redeclarations(symbol_id) { + for window in ctx.scoping().symbol_redeclarations(symbol_id).windows(2) { + let first = &window[0]; + let second = &window[1]; if is_builtin { - ctx.diagnostic(no_redeclare_as_builtin_in_diagnostic(name, rd.span)); + ctx.diagnostic(no_redeclare_as_builtin_in_diagnostic(name, second.span)); } else { - ctx.diagnostic(no_redeclare_diagnostic(name, decl_span, rd.span)); + ctx.diagnostic(no_redeclare_diagnostic(name, first.span, second.span)); } } } diff --git a/crates/oxc_linter/src/rules/eslint/no_shadow_restricted_names.rs b/crates/oxc_linter/src/rules/eslint/no_shadow_restricted_names.rs index c99216c86b8ab..407a820cb75c3 100644 --- a/crates/oxc_linter/src/rules/eslint/no_shadow_restricted_names.rs +++ b/crates/oxc_linter/src/rules/eslint/no_shadow_restricted_names.rs @@ -100,11 +100,14 @@ impl Rule for NoShadowRestrictedNames { } } - let span = ctx.scoping().symbol_span(symbol_id); - ctx.diagnostic(no_shadow_restricted_names_diagnostic(name, span)); - - for rd in ctx.scoping().symbol_redeclarations(symbol_id) { - ctx.diagnostic(no_shadow_restricted_names_diagnostic(name, rd.span)); + let redeclarations = ctx.scoping().symbol_redeclarations(symbol_id); + if redeclarations.is_empty() { + let span = ctx.scoping().symbol_span(symbol_id); + ctx.diagnostic(no_shadow_restricted_names_diagnostic(name, span)); + } else { + for rd in redeclarations { + ctx.diagnostic(no_shadow_restricted_names_diagnostic(name, rd.span)); + } } } } diff --git a/crates/oxc_linter/src/snapshots/eslint_no_redeclare.snap b/crates/oxc_linter/src/snapshots/eslint_no_redeclare.snap index ce33ba2ffabd3..34ee3b55bb12c 100644 --- a/crates/oxc_linter/src/snapshots/eslint_no_redeclare.snap +++ b/crates/oxc_linter/src/snapshots/eslint_no_redeclare.snap @@ -68,11 +68,11 @@ source: crates/oxc_linter/src/tester.rs ╰──── ⚠ eslint(no-redeclare): 'a' is already defined. - ╭─[no_redeclare.tsx:1:5] + ╭─[no_redeclare.tsx:1:16] 1 │ var a = 3; var a = 10; var a = 15; - · ┬ ┬ - · │ ╰── It can not be redeclare here. - · ╰── 'a' is already defined. + · ┬ ┬ + · │ ╰── It can not be redeclare here. + · ╰── 'a' is already defined. ╰──── ⚠ eslint(no-redeclare): 'a' is already defined. diff --git a/crates/oxc_semantic/src/builder.rs b/crates/oxc_semantic/src/builder.rs index a181f82ca687d..a0174ff1f7e42 100644 --- a/crates/oxc_semantic/src/builder.rs +++ b/crates/oxc_semantic/src/builder.rs @@ -387,8 +387,8 @@ impl<'a> SemanticBuilder<'a> { excludes: SymbolFlags, ) -> SymbolId { if let Some(symbol_id) = self.check_redeclaration(scope_id, span, name, excludes, true) { - self.scoping.union_symbol_flag(symbol_id, includes); self.add_redeclare_variable(symbol_id, includes, span); + self.scoping.union_symbol_flag(symbol_id, includes); return symbol_id; } diff --git a/crates/oxc_semantic/src/scoping.rs b/crates/oxc_semantic/src/scoping.rs index efe6110b62b8a..c3a2519387776 100644 --- a/crates/oxc_semantic/src/scoping.rs +++ b/crates/oxc_semantic/src/scoping.rs @@ -111,6 +111,12 @@ pub struct ScopingInner<'cell> { /* Symbol Table Fields */ symbol_names: ArenaVec<'cell, Atom<'cell>>, resolved_references: ArenaVec<'cell, ArenaVec<'cell, ReferenceId>>, + /// Redeclarations of a symbol. + /// + /// NOTE: + /// Once a symbol is redeclared, there are at least two entries here. The first + /// entry is the original symbol information, and the rest are redeclarations. + /// i.e. `symbol_redeclarations[symbol_id].len() >= 2` always. symbol_redeclarations: FxHashMap>, /* Scope Tree Fields */ /// Symbol bindings in a scope. @@ -265,6 +271,16 @@ impl Scoping { declaration: NodeId, span: Span, ) { + let is_first_redeclared = + !self.cell.borrow_dependent().symbol_redeclarations.contains_key(&symbol_id); + // Borrow checker doesn't allow us to call `self.symbol_span` in `with_dependent_mut`, + // so we need construct `Redeclaration` here. + let first_declaration = is_first_redeclared.then(|| Redeclaration { + span: self.symbol_span(symbol_id), + declaration: self.symbol_declaration(symbol_id), + flags: self.symbol_flags(symbol_id), + }); + self.cell.with_dependent_mut(|allocator, cell| { let redeclaration = Redeclaration { span, declaration, flags }; match cell.symbol_redeclarations.entry(symbol_id) { @@ -272,7 +288,12 @@ impl Scoping { occupied.into_mut().push(redeclaration); } Entry::Vacant(vacant) => { - let v = ArenaVec::from_array_in([redeclaration], allocator); + let first_declaration = first_declaration.unwrap_or_else(|| { + unreachable!( + "The above step has already been checked, and it was first declared." + ) + }); + let v = ArenaVec::from_array_in([first_declaration, redeclaration], allocator); vacant.insert(v); } } diff --git a/crates/oxc_transformer/src/typescript/namespace.rs b/crates/oxc_transformer/src/typescript/namespace.rs index f24beb7b0f6bc..5e88eefa72e9c 100644 --- a/crates/oxc_transformer/src/typescript/namespace.rs +++ b/crates/oxc_transformer/src/typescript/namespace.rs @@ -458,18 +458,8 @@ impl<'a> TypeScriptNamespace<'a, '_> { /// Check the namespace binding identifier if it is a redeclaration fn is_redeclaration_namespace(id: &BindingIdentifier<'a>, ctx: &TraverseCtx<'a>) -> bool { let symbol_id = id.symbol_id(); - // Only `enum`, `class`, `function` and `namespace` can be re-declared in same scope - ctx.scoping() - .symbol_flags(symbol_id) - .intersects(SymbolFlags::RegularEnum | SymbolFlags::Class | SymbolFlags::Function) - || { - // ``` - // namespace Foo {} - // namespace Foo {} // is redeclaration - // ``` - let redeclarations = ctx.scoping().symbol_redeclarations(symbol_id); - !redeclarations.is_empty() && redeclarations.iter().any(|rd| rd.span == id.span) - } + let redeclarations = ctx.scoping().symbol_redeclarations(symbol_id); + redeclarations.first().map_or_else(|| false, |rd| rd.span != id.span) } } diff --git a/tasks/coverage/snapshots/semantic_babel.snap b/tasks/coverage/snapshots/semantic_babel.snap index dd2fb8982f185..664db2483aeb8 100644 --- a/tasks/coverage/snapshots/semantic_babel.snap +++ b/tasks/coverage/snapshots/semantic_babel.snap @@ -1556,7 +1556,7 @@ Symbol flags mismatch for "A": after transform: SymbolId(0): SymbolFlags(Class | Interface) rebuilt : SymbolId(0): SymbolFlags(Class) Symbol redeclarations mismatch for "A": -after transform: SymbolId(0): [Span { start: 21, end: 22 }] +after transform: SymbolId(0): [Span { start: 6, end: 7 }, Span { start: 21, end: 22 }] rebuilt : SymbolId(0): [] tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/scope/redeclaration-const-type/input.ts @@ -1570,7 +1570,7 @@ Symbol flags mismatch for "X": after transform: SymbolId(0): SymbolFlags(BlockScopedVariable | ConstVariable | TypeAlias) rebuilt : SymbolId(0): SymbolFlags(BlockScopedVariable | ConstVariable) Symbol redeclarations mismatch for "X": -after transform: SymbolId(0): [Span { start: 19, end: 20 }] +after transform: SymbolId(0): [Span { start: 6, end: 7 }, Span { start: 19, end: 20 }] rebuilt : SymbolId(0): [] tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/scope/redeclaration-constenum-constenum/input.ts @@ -1584,7 +1584,7 @@ Symbol flags mismatch for "Foo": after transform: SymbolId(0): SymbolFlags(ConstEnum) rebuilt : SymbolId(0): SymbolFlags(FunctionScopedVariable) Symbol redeclarations mismatch for "Foo": -after transform: SymbolId(0): [Span { start: 29, end: 32 }] +after transform: SymbolId(0): [Span { start: 11, end: 14 }, Span { start: 29, end: 32 }] rebuilt : SymbolId(0): [] tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/scope/redeclaration-constenum-constenum-babel-7/input.ts @@ -1598,7 +1598,7 @@ Symbol flags mismatch for "Foo": after transform: SymbolId(0): SymbolFlags(ConstEnum) rebuilt : SymbolId(0): SymbolFlags(FunctionScopedVariable) Symbol redeclarations mismatch for "Foo": -after transform: SymbolId(0): [Span { start: 29, end: 32 }] +after transform: SymbolId(0): [Span { start: 11, end: 14 }, Span { start: 29, end: 32 }] rebuilt : SymbolId(0): [] tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/scope/redeclaration-enum-enum/input.ts @@ -1612,7 +1612,7 @@ Symbol flags mismatch for "Foo": after transform: SymbolId(0): SymbolFlags(RegularEnum) rebuilt : SymbolId(0): SymbolFlags(FunctionScopedVariable) Symbol redeclarations mismatch for "Foo": -after transform: SymbolId(0): [Span { start: 17, end: 20 }] +after transform: SymbolId(0): [Span { start: 5, end: 8 }, Span { start: 17, end: 20 }] rebuilt : SymbolId(0): [] tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/scope/redeclaration-enum-enum-babel-7/input.ts @@ -1626,7 +1626,7 @@ Symbol flags mismatch for "Foo": after transform: SymbolId(0): SymbolFlags(RegularEnum) rebuilt : SymbolId(0): SymbolFlags(FunctionScopedVariable) Symbol redeclarations mismatch for "Foo": -after transform: SymbolId(0): [Span { start: 17, end: 20 }] +after transform: SymbolId(0): [Span { start: 5, end: 8 }, Span { start: 17, end: 20 }] rebuilt : SymbolId(0): [] tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/scope/redeclaration-function-interface/input.ts @@ -1640,7 +1640,7 @@ Symbol flags mismatch for "A": after transform: SymbolId(0): SymbolFlags(Function | Interface) rebuilt : SymbolId(0): SymbolFlags(Function) Symbol redeclarations mismatch for "A": -after transform: SymbolId(0): [Span { start: 26, end: 27 }] +after transform: SymbolId(0): [Span { start: 9, end: 10 }, Span { start: 26, end: 27 }] rebuilt : SymbolId(0): [] tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/scope/redeclaration-function-type/input.ts @@ -1654,7 +1654,7 @@ Symbol flags mismatch for "A": after transform: SymbolId(0): SymbolFlags(Function | TypeAlias) rebuilt : SymbolId(0): SymbolFlags(Function) Symbol redeclarations mismatch for "A": -after transform: SymbolId(0): [Span { start: 21, end: 22 }] +after transform: SymbolId(0): [Span { start: 9, end: 10 }, Span { start: 21, end: 22 }] rebuilt : SymbolId(0): [] tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/scope/redeclaration-import-ambient-class/input.ts @@ -1679,7 +1679,7 @@ Symbol span mismatch for "a": after transform: SymbolId(1): Span { start: 20, end: 21 } rebuilt : SymbolId(0): Span { start: 31, end: 32 } Symbol redeclarations mismatch for "a": -after transform: SymbolId(1): [Span { start: 31, end: 32 }] +after transform: SymbolId(1): [Span { start: 20, end: 21 }, Span { start: 31, end: 32 }] rebuilt : SymbolId(0): [] Unresolved references mismatch: after transform: ["M"] @@ -1699,7 +1699,7 @@ Symbol span mismatch for "a": after transform: SymbolId(1): Span { start: 20, end: 21 } rebuilt : SymbolId(0): Span { start: 31, end: 32 } Symbol redeclarations mismatch for "a": -after transform: SymbolId(1): [Span { start: 31, end: 32 }] +after transform: SymbolId(1): [Span { start: 20, end: 21 }, Span { start: 31, end: 32 }] rebuilt : SymbolId(0): [] Unresolved references mismatch: after transform: ["M"] @@ -1716,7 +1716,7 @@ Symbol reference IDs mismatch for "Context": after transform: SymbolId(1): [ReferenceId(0)] rebuilt : SymbolId(1): [] Symbol redeclarations mismatch for "Context": -after transform: SymbolId(1): [Span { start: 104, end: 124 }] +after transform: SymbolId(1): [Span { start: 16, end: 23 }, Span { start: 104, end: 124 }] rebuilt : SymbolId(1): [] Symbol flags mismatch for "a": after transform: SymbolId(2): SymbolFlags(BlockScopedVariable | Import) @@ -1728,7 +1728,7 @@ Symbol reference IDs mismatch for "a": after transform: SymbolId(2): [ReferenceId(2)] rebuilt : SymbolId(2): [] Symbol redeclarations mismatch for "a": -after transform: SymbolId(2): [Span { start: 156, end: 160 }] +after transform: SymbolId(2): [Span { start: 49, end: 50 }, Span { start: 156, end: 160 }] rebuilt : SymbolId(2): [] Symbol flags mismatch for "b": after transform: SymbolId(3): SymbolFlags(BlockScopedVariable | Import) @@ -1740,7 +1740,7 @@ Symbol reference IDs mismatch for "b": after transform: SymbolId(3): [ReferenceId(3)] rebuilt : SymbolId(3): [] Symbol redeclarations mismatch for "b": -after transform: SymbolId(3): [Span { start: 170, end: 174 }] +after transform: SymbolId(3): [Span { start: 81, end: 82 }, Span { start: 170, end: 174 }] rebuilt : SymbolId(3): [] tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/scope/redeclaration-import-let-babel-7/input.ts @@ -1754,7 +1754,7 @@ Symbol reference IDs mismatch for "Context": after transform: SymbolId(1): [ReferenceId(0)] rebuilt : SymbolId(1): [] Symbol redeclarations mismatch for "Context": -after transform: SymbolId(1): [Span { start: 104, end: 124 }] +after transform: SymbolId(1): [Span { start: 16, end: 23 }, Span { start: 104, end: 124 }] rebuilt : SymbolId(1): [] Symbol flags mismatch for "a": after transform: SymbolId(2): SymbolFlags(BlockScopedVariable | Import) @@ -1766,7 +1766,7 @@ Symbol reference IDs mismatch for "a": after transform: SymbolId(2): [ReferenceId(2)] rebuilt : SymbolId(2): [] Symbol redeclarations mismatch for "a": -after transform: SymbolId(2): [Span { start: 156, end: 160 }] +after transform: SymbolId(2): [Span { start: 49, end: 50 }, Span { start: 156, end: 160 }] rebuilt : SymbolId(2): [] Symbol flags mismatch for "b": after transform: SymbolId(3): SymbolFlags(BlockScopedVariable | Import) @@ -1778,7 +1778,7 @@ Symbol reference IDs mismatch for "b": after transform: SymbolId(3): [ReferenceId(3)] rebuilt : SymbolId(3): [] Symbol redeclarations mismatch for "b": -after transform: SymbolId(3): [Span { start: 170, end: 174 }] +after transform: SymbolId(3): [Span { start: 81, end: 82 }, Span { start: 170, end: 174 }] rebuilt : SymbolId(3): [] tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/scope/redeclaration-import-type-let/input.ts @@ -1792,7 +1792,7 @@ Symbol reference IDs mismatch for "Context": after transform: SymbolId(1): [ReferenceId(0)] rebuilt : SymbolId(1): [] Symbol redeclarations mismatch for "Context": -after transform: SymbolId(1): [Span { start: 119, end: 139 }] +after transform: SymbolId(1): [Span { start: 21, end: 28 }, Span { start: 119, end: 139 }] rebuilt : SymbolId(1): [] Symbol flags mismatch for "a": after transform: SymbolId(2): SymbolFlags(BlockScopedVariable | TypeImport) @@ -1804,7 +1804,7 @@ Symbol reference IDs mismatch for "a": after transform: SymbolId(2): [ReferenceId(2)] rebuilt : SymbolId(2): [] Symbol redeclarations mismatch for "a": -after transform: SymbolId(2): [Span { start: 171, end: 175 }] +after transform: SymbolId(2): [Span { start: 59, end: 60 }, Span { start: 171, end: 175 }] rebuilt : SymbolId(2): [] Symbol flags mismatch for "b": after transform: SymbolId(3): SymbolFlags(BlockScopedVariable | TypeImport) @@ -1816,7 +1816,7 @@ Symbol reference IDs mismatch for "b": after transform: SymbolId(3): [ReferenceId(3)] rebuilt : SymbolId(3): [] Symbol redeclarations mismatch for "b": -after transform: SymbolId(3): [Span { start: 185, end: 189 }] +after transform: SymbolId(3): [Span { start: 96, end: 97 }, Span { start: 185, end: 189 }] rebuilt : SymbolId(3): [] tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/scope/redeclaration-import-type-let-babel-7/input.ts @@ -1830,7 +1830,7 @@ Symbol reference IDs mismatch for "Context": after transform: SymbolId(1): [ReferenceId(0)] rebuilt : SymbolId(1): [] Symbol redeclarations mismatch for "Context": -after transform: SymbolId(1): [Span { start: 119, end: 139 }] +after transform: SymbolId(1): [Span { start: 21, end: 28 }, Span { start: 119, end: 139 }] rebuilt : SymbolId(1): [] Symbol flags mismatch for "a": after transform: SymbolId(2): SymbolFlags(BlockScopedVariable | TypeImport) @@ -1842,7 +1842,7 @@ Symbol reference IDs mismatch for "a": after transform: SymbolId(2): [ReferenceId(2)] rebuilt : SymbolId(2): [] Symbol redeclarations mismatch for "a": -after transform: SymbolId(2): [Span { start: 171, end: 175 }] +after transform: SymbolId(2): [Span { start: 59, end: 60 }, Span { start: 171, end: 175 }] rebuilt : SymbolId(2): [] Symbol flags mismatch for "b": after transform: SymbolId(3): SymbolFlags(BlockScopedVariable | TypeImport) @@ -1854,7 +1854,7 @@ Symbol reference IDs mismatch for "b": after transform: SymbolId(3): [ReferenceId(3)] rebuilt : SymbolId(3): [] Symbol redeclarations mismatch for "b": -after transform: SymbolId(3): [Span { start: 185, end: 189 }] +after transform: SymbolId(3): [Span { start: 96, end: 97 }, Span { start: 185, end: 189 }] rebuilt : SymbolId(3): [] tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/scope/redeclaration-import-type-type/input.ts @@ -1873,7 +1873,7 @@ Symbol reference IDs mismatch for "Context": after transform: SymbolId(1): [ReferenceId(0)] rebuilt : SymbolId(1): [] Symbol redeclarations mismatch for "Context": -after transform: SymbolId(1): [Span { start: 119, end: 139 }] +after transform: SymbolId(1): [Span { start: 21, end: 28 }, Span { start: 119, end: 139 }] rebuilt : SymbolId(1): [] Symbol flags mismatch for "a": after transform: SymbolId(2): SymbolFlags(FunctionScopedVariable | TypeImport) @@ -1885,7 +1885,7 @@ Symbol reference IDs mismatch for "a": after transform: SymbolId(2): [ReferenceId(2)] rebuilt : SymbolId(2): [] Symbol redeclarations mismatch for "a": -after transform: SymbolId(2): [Span { start: 171, end: 175 }] +after transform: SymbolId(2): [Span { start: 59, end: 60 }, Span { start: 171, end: 175 }] rebuilt : SymbolId(2): [] Symbol flags mismatch for "b": after transform: SymbolId(3): SymbolFlags(FunctionScopedVariable | TypeImport) @@ -1897,7 +1897,7 @@ Symbol reference IDs mismatch for "b": after transform: SymbolId(3): [ReferenceId(3)] rebuilt : SymbolId(3): [] Symbol redeclarations mismatch for "b": -after transform: SymbolId(3): [Span { start: 185, end: 189 }] +after transform: SymbolId(3): [Span { start: 96, end: 97 }, Span { start: 185, end: 189 }] rebuilt : SymbolId(3): [] tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/scope/redeclaration-import-type-var-babel-7/input.ts @@ -1911,7 +1911,7 @@ Symbol reference IDs mismatch for "Context": after transform: SymbolId(1): [ReferenceId(0)] rebuilt : SymbolId(1): [] Symbol redeclarations mismatch for "Context": -after transform: SymbolId(1): [Span { start: 119, end: 139 }] +after transform: SymbolId(1): [Span { start: 21, end: 28 }, Span { start: 119, end: 139 }] rebuilt : SymbolId(1): [] Symbol flags mismatch for "a": after transform: SymbolId(2): SymbolFlags(FunctionScopedVariable | TypeImport) @@ -1923,7 +1923,7 @@ Symbol reference IDs mismatch for "a": after transform: SymbolId(2): [ReferenceId(2)] rebuilt : SymbolId(2): [] Symbol redeclarations mismatch for "a": -after transform: SymbolId(2): [Span { start: 171, end: 175 }] +after transform: SymbolId(2): [Span { start: 59, end: 60 }, Span { start: 171, end: 175 }] rebuilt : SymbolId(2): [] Symbol flags mismatch for "b": after transform: SymbolId(3): SymbolFlags(FunctionScopedVariable | TypeImport) @@ -1935,7 +1935,7 @@ Symbol reference IDs mismatch for "b": after transform: SymbolId(3): [ReferenceId(3)] rebuilt : SymbolId(3): [] Symbol redeclarations mismatch for "b": -after transform: SymbolId(3): [Span { start: 185, end: 189 }] +after transform: SymbolId(3): [Span { start: 96, end: 97 }, Span { start: 185, end: 189 }] rebuilt : SymbolId(3): [] tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/scope/redeclaration-import-var/input.ts @@ -1949,7 +1949,7 @@ Symbol reference IDs mismatch for "Context": after transform: SymbolId(1): [ReferenceId(0)] rebuilt : SymbolId(1): [] Symbol redeclarations mismatch for "Context": -after transform: SymbolId(1): [Span { start: 104, end: 124 }] +after transform: SymbolId(1): [Span { start: 16, end: 23 }, Span { start: 104, end: 124 }] rebuilt : SymbolId(1): [] Symbol flags mismatch for "a": after transform: SymbolId(2): SymbolFlags(FunctionScopedVariable | Import) @@ -1961,7 +1961,7 @@ Symbol reference IDs mismatch for "a": after transform: SymbolId(2): [ReferenceId(2)] rebuilt : SymbolId(2): [] Symbol redeclarations mismatch for "a": -after transform: SymbolId(2): [Span { start: 156, end: 160 }] +after transform: SymbolId(2): [Span { start: 49, end: 50 }, Span { start: 156, end: 160 }] rebuilt : SymbolId(2): [] Symbol flags mismatch for "b": after transform: SymbolId(3): SymbolFlags(FunctionScopedVariable | Import) @@ -1973,7 +1973,7 @@ Symbol reference IDs mismatch for "b": after transform: SymbolId(3): [ReferenceId(3)] rebuilt : SymbolId(3): [] Symbol redeclarations mismatch for "b": -after transform: SymbolId(3): [Span { start: 170, end: 174 }] +after transform: SymbolId(3): [Span { start: 81, end: 82 }, Span { start: 170, end: 174 }] rebuilt : SymbolId(3): [] tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/scope/redeclaration-import-var-babel-7/input.ts @@ -1987,7 +1987,7 @@ Symbol reference IDs mismatch for "Context": after transform: SymbolId(1): [ReferenceId(0)] rebuilt : SymbolId(1): [] Symbol redeclarations mismatch for "Context": -after transform: SymbolId(1): [Span { start: 104, end: 124 }] +after transform: SymbolId(1): [Span { start: 16, end: 23 }, Span { start: 104, end: 124 }] rebuilt : SymbolId(1): [] Symbol flags mismatch for "a": after transform: SymbolId(2): SymbolFlags(FunctionScopedVariable | Import) @@ -1999,7 +1999,7 @@ Symbol reference IDs mismatch for "a": after transform: SymbolId(2): [ReferenceId(2)] rebuilt : SymbolId(2): [] Symbol redeclarations mismatch for "a": -after transform: SymbolId(2): [Span { start: 156, end: 160 }] +after transform: SymbolId(2): [Span { start: 49, end: 50 }, Span { start: 156, end: 160 }] rebuilt : SymbolId(2): [] Symbol flags mismatch for "b": after transform: SymbolId(3): SymbolFlags(FunctionScopedVariable | Import) @@ -2011,7 +2011,7 @@ Symbol reference IDs mismatch for "b": after transform: SymbolId(3): [ReferenceId(3)] rebuilt : SymbolId(3): [] Symbol redeclarations mismatch for "b": -after transform: SymbolId(3): [Span { start: 170, end: 174 }] +after transform: SymbolId(3): [Span { start: 81, end: 82 }, Span { start: 170, end: 174 }] rebuilt : SymbolId(3): [] tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/scope/redeclaration-in-different-module/input.ts @@ -2055,7 +2055,7 @@ Symbol span mismatch for "A": after transform: SymbolId(0): Span { start: 10, end: 11 } rebuilt : SymbolId(0): Span { start: 21, end: 22 } Symbol redeclarations mismatch for "A": -after transform: SymbolId(0): [Span { start: 21, end: 22 }] +after transform: SymbolId(0): [Span { start: 10, end: 11 }, Span { start: 21, end: 22 }] rebuilt : SymbolId(0): [] tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/scope/redeclaration-interface-function/input.ts @@ -2072,7 +2072,7 @@ Symbol span mismatch for "A": after transform: SymbolId(0): Span { start: 10, end: 11 } rebuilt : SymbolId(0): Span { start: 24, end: 25 } Symbol redeclarations mismatch for "A": -after transform: SymbolId(0): [Span { start: 24, end: 25 }] +after transform: SymbolId(0): [Span { start: 10, end: 11 }, Span { start: 24, end: 25 }] rebuilt : SymbolId(0): [] tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/scope/redeclaration-interface-interface/input.ts @@ -2094,7 +2094,7 @@ Symbol span mismatch for "A": after transform: SymbolId(0): Span { start: 10, end: 11 } rebuilt : SymbolId(0): Span { start: 19, end: 20 } Symbol redeclarations mismatch for "A": -after transform: SymbolId(0): [Span { start: 19, end: 20 }] +after transform: SymbolId(0): [Span { start: 10, end: 11 }, Span { start: 19, end: 20 }] rebuilt : SymbolId(0): [] tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/scope/redeclaration-interface-var/input.ts @@ -2111,7 +2111,7 @@ Symbol span mismatch for "A": after transform: SymbolId(0): Span { start: 10, end: 11 } rebuilt : SymbolId(0): Span { start: 19, end: 20 } Symbol redeclarations mismatch for "A": -after transform: SymbolId(0): [Span { start: 19, end: 20 }] +after transform: SymbolId(0): [Span { start: 10, end: 11 }, Span { start: 19, end: 20 }] rebuilt : SymbolId(0): [] tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/scope/redeclaration-let-interface/input.ts @@ -2125,7 +2125,7 @@ Symbol flags mismatch for "A": after transform: SymbolId(0): SymbolFlags(BlockScopedVariable | Interface) rebuilt : SymbolId(0): SymbolFlags(BlockScopedVariable) Symbol redeclarations mismatch for "A": -after transform: SymbolId(0): [Span { start: 17, end: 18 }] +after transform: SymbolId(0): [Span { start: 4, end: 5 }, Span { start: 17, end: 18 }] rebuilt : SymbolId(0): [] tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/scope/redeclaration-let-type/input.ts @@ -2139,7 +2139,7 @@ Symbol flags mismatch for "X": after transform: SymbolId(0): SymbolFlags(BlockScopedVariable | TypeAlias) rebuilt : SymbolId(0): SymbolFlags(BlockScopedVariable) Symbol redeclarations mismatch for "X": -after transform: SymbolId(0): [Span { start: 17, end: 18 }] +after transform: SymbolId(0): [Span { start: 4, end: 5 }, Span { start: 17, end: 18 }] rebuilt : SymbolId(0): [] tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/scope/redeclaration-type-function/input.ts @@ -2156,7 +2156,7 @@ Symbol span mismatch for "A": after transform: SymbolId(0): Span { start: 5, end: 6 } rebuilt : SymbolId(0): Span { start: 26, end: 27 } Symbol redeclarations mismatch for "A": -after transform: SymbolId(0): [Span { start: 26, end: 27 }] +after transform: SymbolId(0): [Span { start: 5, end: 6 }, Span { start: 26, end: 27 }] rebuilt : SymbolId(0): [] tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/scope/redeclaration-type-let/input.ts @@ -2173,7 +2173,7 @@ Symbol span mismatch for "A": after transform: SymbolId(0): Span { start: 5, end: 6 } rebuilt : SymbolId(0): Span { start: 21, end: 22 } Symbol redeclarations mismatch for "A": -after transform: SymbolId(0): [Span { start: 21, end: 22 }] +after transform: SymbolId(0): [Span { start: 5, end: 6 }, Span { start: 21, end: 22 }] rebuilt : SymbolId(0): [] tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/scope/redeclaration-type-var/input.ts @@ -2190,7 +2190,7 @@ Symbol span mismatch for "A": after transform: SymbolId(0): Span { start: 5, end: 6 } rebuilt : SymbolId(0): Span { start: 21, end: 22 } Symbol redeclarations mismatch for "A": -after transform: SymbolId(0): [Span { start: 21, end: 22 }] +after transform: SymbolId(0): [Span { start: 5, end: 6 }, Span { start: 21, end: 22 }] rebuilt : SymbolId(0): [] tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/scope/redeclaration-var-interface/input.ts @@ -2204,7 +2204,7 @@ Symbol flags mismatch for "A": after transform: SymbolId(0): SymbolFlags(FunctionScopedVariable | Interface) rebuilt : SymbolId(0): SymbolFlags(FunctionScopedVariable) Symbol redeclarations mismatch for "A": -after transform: SymbolId(0): [Span { start: 17, end: 18 }] +after transform: SymbolId(0): [Span { start: 4, end: 5 }, Span { start: 17, end: 18 }] rebuilt : SymbolId(0): [] tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/scope/redeclaration-var-type/input.ts @@ -2218,7 +2218,7 @@ Symbol flags mismatch for "X": after transform: SymbolId(0): SymbolFlags(FunctionScopedVariable | TypeAlias) rebuilt : SymbolId(0): SymbolFlags(FunctionScopedVariable) Symbol redeclarations mismatch for "X": -after transform: SymbolId(0): [Span { start: 17, end: 18 }] +after transform: SymbolId(0): [Span { start: 4, end: 5 }, Span { start: 17, end: 18 }] rebuilt : SymbolId(0): [] tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/tsx/anonymous-function-generator/input.ts diff --git a/tasks/coverage/snapshots/semantic_typescript.snap b/tasks/coverage/snapshots/semantic_typescript.snap index 962cb0195ce53..61ad0a6abfa9b 100644 --- a/tasks/coverage/snapshots/semantic_typescript.snap +++ b/tasks/coverage/snapshots/semantic_typescript.snap @@ -1056,7 +1056,7 @@ Symbol flags mismatch for "c5": after transform: SymbolId(1): SymbolFlags(Class | NameSpaceModule) rebuilt : SymbolId(1): SymbolFlags(Class) Symbol redeclarations mismatch for "c5": -after transform: SymbolId(1): [Span { start: 55, end: 57 }] +after transform: SymbolId(1): [Span { start: 24, end: 26 }, Span { start: 55, end: 57 }] rebuilt : SymbolId(1): [] tasks/coverage/typescript/tests/cases/compiler/augmentedTypesModules3b.ts @@ -1085,7 +1085,7 @@ Symbol flags mismatch for "Foo": after transform: SymbolId(0): SymbolFlags(RegularEnum) rebuilt : SymbolId(0): SymbolFlags(FunctionScopedVariable) Symbol redeclarations mismatch for "Foo": -after transform: SymbolId(0): [Span { start: 29, end: 32 }] +after transform: SymbolId(0): [Span { start: 5, end: 8 }, Span { start: 29, end: 32 }] rebuilt : SymbolId(0): [] tasks/coverage/typescript/tests/cases/compiler/avoidCycleWithVoidExpressionReturnedFromArrow.ts @@ -1559,7 +1559,7 @@ Symbol reference IDs mismatch for "maker": after transform: SymbolId(1): [ReferenceId(0), ReferenceId(1), ReferenceId(5), ReferenceId(6)] rebuilt : SymbolId(1): [ReferenceId(0), ReferenceId(4), ReferenceId(5)] Symbol redeclarations mismatch for "maker": -after transform: SymbolId(1): [Span { start: 121, end: 126 }] +after transform: SymbolId(1): [Span { start: 44, end: 49 }, Span { start: 121, end: 126 }] rebuilt : SymbolId(1): [] tasks/coverage/typescript/tests/cases/compiler/circularlySimplifyingConditionalTypesNoCrash.ts @@ -1879,7 +1879,7 @@ Symbol flags mismatch for "C": after transform: SymbolId(1): SymbolFlags(Class | Interface) rebuilt : SymbolId(3): SymbolFlags(Class) Symbol redeclarations mismatch for "C": -after transform: SymbolId(1): [Span { start: 41, end: 42 }] +after transform: SymbolId(1): [Span { start: 21, end: 22 }, Span { start: 41, end: 42 }] rebuilt : SymbolId(3): [] Symbol flags mismatch for "D": after transform: SymbolId(2): SymbolFlags(Class | Interface) @@ -1888,7 +1888,7 @@ Symbol span mismatch for "D": after transform: SymbolId(2): Span { start: 61, end: 62 } rebuilt : SymbolId(4): Span { start: 77, end: 78 } Symbol redeclarations mismatch for "D": -after transform: SymbolId(2): [Span { start: 77, end: 78 }] +after transform: SymbolId(2): [Span { start: 61, end: 62 }, Span { start: 77, end: 78 }] rebuilt : SymbolId(4): [] Symbol flags mismatch for "Foo": after transform: SymbolId(3): SymbolFlags(Class | Interface) @@ -1897,13 +1897,13 @@ Symbol span mismatch for "Foo": after transform: SymbolId(3): Span { start: 96, end: 99 } rebuilt : SymbolId(5): Span { start: 129, end: 132 } Symbol redeclarations mismatch for "Foo": -after transform: SymbolId(3): [Span { start: 129, end: 132 }] +after transform: SymbolId(3): [Span { start: 96, end: 99 }, Span { start: 129, end: 132 }] rebuilt : SymbolId(5): [] Symbol flags mismatch for "Bar": after transform: SymbolId(6): SymbolFlags(Class | Interface) rebuilt : SymbolId(6): SymbolFlags(Class) Symbol redeclarations mismatch for "Bar": -after transform: SymbolId(6): [Span { start: 197, end: 200 }] +after transform: SymbolId(6): [Span { start: 161, end: 164 }, Span { start: 197, end: 200 }] rebuilt : SymbolId(6): [] tasks/coverage/typescript/tests/cases/compiler/cloduleAcrossModuleDefinitions.ts @@ -1923,7 +1923,7 @@ Symbol reference IDs mismatch for "Foo": after transform: SymbolId(0): [ReferenceId(0), ReferenceId(3), ReferenceId(4)] rebuilt : SymbolId(0): [ReferenceId(2), ReferenceId(3)] Symbol redeclarations mismatch for "Foo": -after transform: SymbolId(0): [Span { start: 63, end: 66 }] +after transform: SymbolId(0): [Span { start: 6, end: 9 }, Span { start: 63, end: 66 }] rebuilt : SymbolId(0): [] tasks/coverage/typescript/tests/cases/compiler/cloduleGenericOnSelfMember.ts @@ -1937,7 +1937,7 @@ Symbol reference IDs mismatch for "Service": after transform: SymbolId(2): [ReferenceId(2), ReferenceId(4), ReferenceId(5)] rebuilt : SymbolId(2): [ReferenceId(4), ReferenceId(5)] Symbol redeclarations mismatch for "Service": -after transform: SymbolId(2): [Span { start: 108, end: 115 }] +after transform: SymbolId(2): [Span { start: 45, end: 52 }, Span { start: 108, end: 115 }] rebuilt : SymbolId(2): [] tasks/coverage/typescript/tests/cases/compiler/cloduleTest1.ts @@ -1977,7 +1977,7 @@ Symbol span mismatch for "Moclodule": after transform: SymbolId(0): Span { start: 47, end: 56 } rebuilt : SymbolId(0): Span { start: 132, end: 141 } Symbol redeclarations mismatch for "Moclodule": -after transform: SymbolId(0): [Span { start: 132, end: 141 }, Span { start: 178, end: 187 }] +after transform: SymbolId(0): [Span { start: 47, end: 56 }, Span { start: 132, end: 141 }, Span { start: 178, end: 187 }] rebuilt : SymbolId(0): [] tasks/coverage/typescript/tests/cases/compiler/cloduleWithRecursiveReference.ts @@ -2834,7 +2834,7 @@ Symbol span mismatch for "multiM": after transform: SymbolId(0): Span { start: 49, end: 55 } rebuilt : SymbolId(0): Span { start: 0, end: 0 } Symbol redeclarations mismatch for "multiM": -after transform: SymbolId(0): [Span { start: 153, end: 159 }] +after transform: SymbolId(0): [Span { start: 49, end: 55 }, Span { start: 153, end: 159 }] rebuilt : SymbolId(0): [] tasks/coverage/typescript/tests/cases/compiler/commentsMultiModuleSingleFile.ts @@ -2851,7 +2851,7 @@ Symbol span mismatch for "multiM": after transform: SymbolId(0): Span { start: 42, end: 48 } rebuilt : SymbolId(0): Span { start: 0, end: 0 } Symbol redeclarations mismatch for "multiM": -after transform: SymbolId(0): [Span { start: 176, end: 182 }] +after transform: SymbolId(0): [Span { start: 42, end: 48 }, Span { start: 176, end: 182 }] rebuilt : SymbolId(0): [] tasks/coverage/typescript/tests/cases/compiler/commentsOnJSXExpressionsArePreserved.tsx @@ -3342,7 +3342,7 @@ Symbol flags mismatch for "foo": after transform: SymbolId(0): SymbolFlags(Function | NameSpaceModule | ValueModule) rebuilt : SymbolId(0): SymbolFlags(Function) Symbol redeclarations mismatch for "foo": -after transform: SymbolId(0): [Span { start: 25, end: 28 }] +after transform: SymbolId(0): [Span { start: 9, end: 12 }, Span { start: 25, end: 28 }] rebuilt : SymbolId(0): [] Symbol flags mismatch for "E": after transform: SymbolId(1): SymbolFlags(ConstEnum) @@ -3359,7 +3359,7 @@ Symbol flags mismatch for "foo": after transform: SymbolId(0): SymbolFlags(Class | NameSpaceModule | ValueModule) rebuilt : SymbolId(0): SymbolFlags(Class) Symbol redeclarations mismatch for "foo": -after transform: SymbolId(0): [Span { start: 20, end: 23 }] +after transform: SymbolId(0): [Span { start: 6, end: 9 }, Span { start: 20, end: 23 }] rebuilt : SymbolId(0): [] Symbol flags mismatch for "E": after transform: SymbolId(1): SymbolFlags(ConstEnum) @@ -3382,7 +3382,7 @@ Symbol flags mismatch for "foo": after transform: SymbolId(0): SymbolFlags(RegularEnum | NameSpaceModule | ValueModule) rebuilt : SymbolId(0): SymbolFlags(FunctionScopedVariable) Symbol redeclarations mismatch for "foo": -after transform: SymbolId(0): [Span { start: 22, end: 25 }] +after transform: SymbolId(0): [Span { start: 5, end: 8 }, Span { start: 22, end: 25 }] rebuilt : SymbolId(0): [] Symbol flags mismatch for "E": after transform: SymbolId(2): SymbolFlags(ConstEnum) @@ -3402,7 +3402,7 @@ Symbol span mismatch for "foo": after transform: SymbolId(0): Span { start: 7, end: 10 } rebuilt : SymbolId(0): Span { start: 0, end: 0 } Symbol redeclarations mismatch for "foo": -after transform: SymbolId(0): [Span { start: 46, end: 49 }] +after transform: SymbolId(0): [Span { start: 7, end: 10 }, Span { start: 46, end: 49 }] rebuilt : SymbolId(0): [] Symbol flags mismatch for "E": after transform: SymbolId(1): SymbolFlags(ConstEnum) @@ -3634,7 +3634,7 @@ Symbol reference IDs mismatch for "Enum1": after transform: SymbolId(0): [ReferenceId(23), ReferenceId(25), ReferenceId(26), ReferenceId(27), ReferenceId(28), ReferenceId(50), ReferenceId(52), ReferenceId(53), ReferenceId(54), ReferenceId(55), ReferenceId(56), ReferenceId(57), ReferenceId(58), ReferenceId(59), ReferenceId(60), ReferenceId(61), ReferenceId(62), ReferenceId(63), ReferenceId(64), ReferenceId(65), ReferenceId(66), ReferenceId(67), ReferenceId(68), ReferenceId(69), ReferenceId(70), ReferenceId(71), ReferenceId(72), ReferenceId(73), ReferenceId(74), ReferenceId(75), ReferenceId(76), ReferenceId(77), ReferenceId(78), ReferenceId(79), ReferenceId(149), ReferenceId(209), ReferenceId(210)] rebuilt : SymbolId(0): [ReferenceId(3), ReferenceId(4), ReferenceId(67), ReferenceId(181), ReferenceId(182), ReferenceId(183), ReferenceId(184), ReferenceId(185), ReferenceId(186), ReferenceId(187), ReferenceId(188), ReferenceId(189), ReferenceId(190), ReferenceId(191), ReferenceId(192), ReferenceId(193), ReferenceId(194), ReferenceId(195), ReferenceId(196), ReferenceId(197), ReferenceId(198), ReferenceId(199), ReferenceId(200), ReferenceId(201), ReferenceId(202), ReferenceId(203), ReferenceId(204), ReferenceId(205), ReferenceId(206), ReferenceId(207), ReferenceId(208)] Symbol redeclarations mismatch for "Enum1": -after transform: SymbolId(0): [Span { start: 46, end: 51 }] +after transform: SymbolId(0): [Span { start: 11, end: 16 }, Span { start: 46, end: 51 }] rebuilt : SymbolId(0): [] Symbol reference IDs mismatch for "Enum1": after transform: SymbolId(92): [ReferenceId(150), ReferenceId(151), ReferenceId(152), ReferenceId(153), ReferenceId(154), ReferenceId(155), ReferenceId(156), ReferenceId(157), ReferenceId(158), ReferenceId(159), ReferenceId(160), ReferenceId(161), ReferenceId(162), ReferenceId(163), ReferenceId(164), ReferenceId(165), ReferenceId(166), ReferenceId(167), ReferenceId(168), ReferenceId(169), ReferenceId(170), ReferenceId(171), ReferenceId(172), ReferenceId(173), ReferenceId(174), ReferenceId(175), ReferenceId(176), ReferenceId(177), ReferenceId(178), ReferenceId(179), ReferenceId(180), ReferenceId(181), ReferenceId(182), ReferenceId(183), ReferenceId(184), ReferenceId(185), ReferenceId(186), ReferenceId(187), ReferenceId(188), ReferenceId(189), ReferenceId(190), ReferenceId(191), ReferenceId(192), ReferenceId(193), ReferenceId(194), ReferenceId(195), ReferenceId(196), ReferenceId(197), ReferenceId(198), ReferenceId(199), ReferenceId(200), ReferenceId(201), ReferenceId(202), ReferenceId(203), ReferenceId(204), ReferenceId(205), ReferenceId(206), ReferenceId(207), ReferenceId(208)] @@ -3652,7 +3652,7 @@ Symbol span mismatch for "A": after transform: SymbolId(39): Span { start: 717, end: 718 } rebuilt : SymbolId(5): Span { start: 0, end: 0 } Symbol redeclarations mismatch for "A": -after transform: SymbolId(39): [Span { start: 905, end: 906 }] +after transform: SymbolId(39): [Span { start: 717, end: 718 }, Span { start: 905, end: 906 }] rebuilt : SymbolId(5): [] Symbol flags mismatch for "B": after transform: SymbolId(40): SymbolFlags(NameSpaceModule | ValueModule) @@ -3718,7 +3718,7 @@ Symbol span mismatch for "C": after transform: SymbolId(58): Span { start: 1341, end: 1342 } rebuilt : SymbolId(30): Span { start: 0, end: 0 } Symbol redeclarations mismatch for "C": -after transform: SymbolId(58): [Span { start: 1524, end: 1525 }] +after transform: SymbolId(58): [Span { start: 1341, end: 1342 }, Span { start: 1524, end: 1525 }] rebuilt : SymbolId(30): [] Symbol reference IDs mismatch for "I": after transform: SymbolId(63): [ReferenceId(35), ReferenceId(37), ReferenceId(39)] @@ -3939,7 +3939,7 @@ Symbol reference IDs mismatch for "propName": after transform: SymbolId(11): [ReferenceId(13), ReferenceId(14), ReferenceId(15)] rebuilt : SymbolId(2): [ReferenceId(4)] Symbol redeclarations mismatch for "propName": -after transform: SymbolId(11): [Span { start: 551, end: 569 }] +after transform: SymbolId(11): [Span { start: 526, end: 534 }, Span { start: 551, end: 569 }] rebuilt : SymbolId(2): [] tasks/coverage/typescript/tests/cases/compiler/contextualExpressionTypecheckingDoesntBlowStack.ts @@ -5131,7 +5131,7 @@ Symbol span mismatch for "m2": after transform: SymbolId(0): Span { start: 7, end: 9 } rebuilt : SymbolId(0): Span { start: 229, end: 322 } Symbol redeclarations mismatch for "m2": -after transform: SymbolId(0): [Span { start: 229, end: 322 }] +after transform: SymbolId(0): [Span { start: 7, end: 9 }, Span { start: 229, end: 322 }] rebuilt : SymbolId(0): [] Unresolved references mismatch: after transform: ["m2", "module"] @@ -5591,7 +5591,7 @@ Symbol span mismatch for "X": after transform: SymbolId(4): Span { start: 82, end: 83 } rebuilt : SymbolId(1): Span { start: 0, end: 0 } Symbol redeclarations mismatch for "X": -after transform: SymbolId(4): [Span { start: 172, end: 173 }] +after transform: SymbolId(4): [Span { start: 82, end: 83 }, Span { start: 172, end: 173 }] rebuilt : SymbolId(1): [] Symbol flags mismatch for "Y": after transform: SymbolId(5): SymbolFlags(NameSpaceModule | ValueModule) @@ -5864,7 +5864,7 @@ Symbol reference IDs mismatch for "bar": after transform: SymbolId(0): [ReferenceId(0)] rebuilt : SymbolId(0): [] Symbol redeclarations mismatch for "bar": -after transform: SymbolId(0): [Span { start: 26, end: 29 }] +after transform: SymbolId(0): [Span { start: 10, end: 13 }, Span { start: 26, end: 29 }] rebuilt : SymbolId(0): [] tasks/coverage/typescript/tests/cases/compiler/declInput3.ts @@ -6154,7 +6154,7 @@ Symbol reference IDs mismatch for "TranslationKeyEnum": after transform: SymbolId(1): [ReferenceId(1), ReferenceId(2)] rebuilt : SymbolId(1): [] Symbol redeclarations mismatch for "TranslationKeyEnum": -after transform: SymbolId(1): [Span { start: 198, end: 216 }] +after transform: SymbolId(1): [Span { start: 129, end: 147 }, Span { start: 198, end: 216 }] rebuilt : SymbolId(1): [] Reference symbol mismatch for "Translation": after transform: SymbolId(0) "Translation" @@ -6188,7 +6188,7 @@ Symbol reference IDs mismatch for "Point": after transform: SymbolId(0): [ReferenceId(0), ReferenceId(3), ReferenceId(6), ReferenceId(13), ReferenceId(14), ReferenceId(15)] rebuilt : SymbolId(0): [ReferenceId(4), ReferenceId(5)] Symbol redeclarations mismatch for "Point": -after transform: SymbolId(0): [Span { start: 171, end: 176 }] +after transform: SymbolId(0): [Span { start: 17, end: 22 }, Span { start: 171, end: 176 }] rebuilt : SymbolId(0): [] Symbol flags mismatch for "Rect": after transform: SymbolId(1): SymbolFlags(BlockScopedVariable | ConstVariable | Interface) @@ -6200,7 +6200,7 @@ Symbol reference IDs mismatch for "Rect": after transform: SymbolId(1): [ReferenceId(9)] rebuilt : SymbolId(3): [] Symbol redeclarations mismatch for "Rect": -after transform: SymbolId(1): [Span { start: 237, end: 241 }] +after transform: SymbolId(1): [Span { start: 93, end: 97 }, Span { start: 237, end: 241 }] rebuilt : SymbolId(3): [] tasks/coverage/typescript/tests/cases/compiler/declarationEmitExportAliasVisibiilityMarking.ts @@ -6372,7 +6372,7 @@ Symbol reference IDs mismatch for "F": after transform: SymbolId(62): [ReferenceId(159), ReferenceId(161), ReferenceId(170), ReferenceId(176), ReferenceId(185), ReferenceId(191), ReferenceId(200), ReferenceId(210), ReferenceId(216), ReferenceId(225), ReferenceId(233), ReferenceId(234)] rebuilt : SymbolId(4): [ReferenceId(2), ReferenceId(3)] Symbol redeclarations mismatch for "F": -after transform: SymbolId(62): [Span { start: 2610, end: 2631 }] +after transform: SymbolId(62): [Span { start: 2588, end: 2589 }, Span { start: 2610, end: 2631 }] rebuilt : SymbolId(4): [] Symbol flags mismatch for "F": after transform: SymbolId(90): SymbolFlags(FunctionScopedVariable | TypeParameter) @@ -6384,7 +6384,7 @@ Symbol reference IDs mismatch for "F": after transform: SymbolId(90): [ReferenceId(242), ReferenceId(244), ReferenceId(250), ReferenceId(256), ReferenceId(265), ReferenceId(271), ReferenceId(277), ReferenceId(287), ReferenceId(293), ReferenceId(299), ReferenceId(308)] rebuilt : SymbolId(11): [ReferenceId(11)] Symbol redeclarations mismatch for "F": -after transform: SymbolId(90): [Span { start: 3354, end: 3375 }] +after transform: SymbolId(90): [Span { start: 3332, end: 3333 }, Span { start: 3354, end: 3375 }] rebuilt : SymbolId(11): [] Reference symbol mismatch for "dual": after transform: SymbolId(58) "dual" @@ -6443,7 +6443,7 @@ Symbol span mismatch for "A": after transform: SymbolId(0): Span { start: 25, end: 26 } rebuilt : SymbolId(2): Span { start: 78, end: 79 } Symbol redeclarations mismatch for "A": -after transform: SymbolId(0): [Span { start: 78, end: 79 }] +after transform: SymbolId(0): [Span { start: 25, end: 26 }, Span { start: 78, end: 79 }] rebuilt : SymbolId(2): [] Symbol flags mismatch for "Y": after transform: SymbolId(3): SymbolFlags(Class | NameSpaceModule | Ambient) @@ -6452,7 +6452,7 @@ Symbol span mismatch for "Y": after transform: SymbolId(3): Span { start: 128, end: 129 } rebuilt : SymbolId(3): Span { start: 149, end: 150 } Symbol redeclarations mismatch for "Y": -after transform: SymbolId(3): [Span { start: 149, end: 150 }] +after transform: SymbolId(3): [Span { start: 128, end: 129 }, Span { start: 149, end: 150 }] rebuilt : SymbolId(3): [] tasks/coverage/typescript/tests/cases/compiler/declarationEmitMappedTypeDistributivityPreservesConstraints.ts @@ -6482,7 +6482,7 @@ Symbol reference IDs mismatch for "Color": after transform: SymbolId(0): [ReferenceId(1), ReferenceId(2), ReferenceId(3)] rebuilt : SymbolId(0): [] Symbol redeclarations mismatch for "Color": -after transform: SymbolId(0): [Span { start: 100, end: 105 }] +after transform: SymbolId(0): [Span { start: 13, end: 18 }, Span { start: 100, end: 105 }] rebuilt : SymbolId(0): [] Unresolved references mismatch: after transform: ["const"] @@ -6622,7 +6622,7 @@ Symbol flags mismatch for "ExpandoMerge": after transform: SymbolId(0): SymbolFlags(Function | NameSpaceModule) rebuilt : SymbolId(0): SymbolFlags(Function) Symbol redeclarations mismatch for "ExpandoMerge": -after transform: SymbolId(0): [Span { start: 71, end: 83 }] +after transform: SymbolId(0): [Span { start: 19, end: 31 }, Span { start: 71, end: 83 }] rebuilt : SymbolId(0): [] tasks/coverage/typescript/tests/cases/compiler/declarationEmitOptionalMappedTypePropertyNoStrictNullChecks1.ts @@ -7085,7 +7085,7 @@ Symbol span mismatch for "m2": after transform: SymbolId(0): Span { start: 7, end: 9 } rebuilt : SymbolId(0): Span { start: 230, end: 323 } Symbol redeclarations mismatch for "m2": -after transform: SymbolId(0): [Span { start: 230, end: 323 }] +after transform: SymbolId(0): [Span { start: 7, end: 9 }, Span { start: 230, end: 323 }] rebuilt : SymbolId(0): [] Unresolved references mismatch: after transform: ["m2", "module"] @@ -7188,7 +7188,7 @@ Symbol span mismatch for "m2": after transform: SymbolId(0): Span { start: 7, end: 9 } rebuilt : SymbolId(0): Span { start: 230, end: 323 } Symbol redeclarations mismatch for "m2": -after transform: SymbolId(0): [Span { start: 230, end: 323 }] +after transform: SymbolId(0): [Span { start: 7, end: 9 }, Span { start: 230, end: 323 }] rebuilt : SymbolId(0): [] Unresolved references mismatch: after transform: ["m2", "module"] @@ -7205,7 +7205,7 @@ Symbol span mismatch for "m2": after transform: SymbolId(0): Span { start: 7, end: 9 } rebuilt : SymbolId(1): Span { start: 238, end: 331 } Symbol redeclarations mismatch for "m2": -after transform: SymbolId(0): [Span { start: 238, end: 331 }] +after transform: SymbolId(0): [Span { start: 7, end: 9 }, Span { start: 238, end: 331 }] rebuilt : SymbolId(1): [] Unresolved references mismatch: after transform: ["m2", "module"] @@ -7453,7 +7453,7 @@ Symbol span mismatch for "Foo": after transform: SymbolId(0): Span { start: 5, end: 8 } rebuilt : SymbolId(0): Span { start: 32, end: 35 } Symbol redeclarations mismatch for "Foo": -after transform: SymbolId(0): [Span { start: 32, end: 35 }] +after transform: SymbolId(0): [Span { start: 5, end: 8 }, Span { start: 32, end: 35 }] rebuilt : SymbolId(0): [] tasks/coverage/typescript/tests/cases/compiler/defaultNamedExportWithType2.ts @@ -7470,7 +7470,7 @@ Symbol span mismatch for "Foo": after transform: SymbolId(0): Span { start: 5, end: 8 } rebuilt : SymbolId(0): Span { start: 25, end: 28 } Symbol redeclarations mismatch for "Foo": -after transform: SymbolId(0): [Span { start: 25, end: 28 }] +after transform: SymbolId(0): [Span { start: 5, end: 8 }, Span { start: 25, end: 28 }] rebuilt : SymbolId(0): [] tasks/coverage/typescript/tests/cases/compiler/defaultNamedExportWithType3.ts @@ -7487,7 +7487,7 @@ Symbol span mismatch for "Foo": after transform: SymbolId(0): Span { start: 10, end: 13 } rebuilt : SymbolId(0): Span { start: 30, end: 33 } Symbol redeclarations mismatch for "Foo": -after transform: SymbolId(0): [Span { start: 30, end: 33 }] +after transform: SymbolId(0): [Span { start: 10, end: 13 }, Span { start: 30, end: 33 }] rebuilt : SymbolId(0): [] tasks/coverage/typescript/tests/cases/compiler/defaultNamedExportWithType4.ts @@ -7504,7 +7504,7 @@ Symbol span mismatch for "Foo": after transform: SymbolId(0): Span { start: 10, end: 13 } rebuilt : SymbolId(0): Span { start: 23, end: 26 } Symbol redeclarations mismatch for "Foo": -after transform: SymbolId(0): [Span { start: 23, end: 26 }] +after transform: SymbolId(0): [Span { start: 10, end: 13 }, Span { start: 23, end: 26 }] rebuilt : SymbolId(0): [] tasks/coverage/typescript/tests/cases/compiler/defaultParameterAddsUndefinedWithStrictNullChecks.ts @@ -8161,13 +8161,13 @@ Symbol flags mismatch for "Foo": after transform: SymbolId(0): SymbolFlags(RegularEnum | NameSpaceModule | ValueModule) rebuilt : SymbolId(0): SymbolFlags(FunctionScopedVariable) Symbol redeclarations mismatch for "Foo": -after transform: SymbolId(0): [Span { start: 117, end: 120 }] +after transform: SymbolId(0): [Span { start: 5, end: 8 }, Span { start: 117, end: 120 }] rebuilt : SymbolId(0): [] Symbol flags mismatch for "Bar": after transform: SymbolId(6): SymbolFlags(Function | NameSpaceModule | ValueModule) rebuilt : SymbolId(4): SymbolFlags(Function) Symbol redeclarations mismatch for "Bar": -after transform: SymbolId(6): [Span { start: 235, end: 238 }] +after transform: SymbolId(6): [Span { start: 198, end: 201 }, Span { start: 235, end: 238 }] rebuilt : SymbolId(4): [] tasks/coverage/typescript/tests/cases/compiler/doubleUnderscoreMappedTypes.ts @@ -8249,7 +8249,7 @@ Symbol span mismatch for "F": after transform: SymbolId(0): Span { start: 7, end: 8 } rebuilt : SymbolId(0): Span { start: 0, end: 0 } Symbol redeclarations mismatch for "F": -after transform: SymbolId(0): [Span { start: 50, end: 51 }] +after transform: SymbolId(0): [Span { start: 7, end: 8 }, Span { start: 50, end: 51 }] rebuilt : SymbolId(0): [] Symbol flags mismatch for "Foo": after transform: SymbolId(3): SymbolFlags(NameSpaceModule | ValueModule) @@ -8258,7 +8258,7 @@ Symbol span mismatch for "Foo": after transform: SymbolId(3): Span { start: 126, end: 129 } rebuilt : SymbolId(5): Span { start: 0, end: 0 } Symbol redeclarations mismatch for "Foo": -after transform: SymbolId(3): [Span { start: 171, end: 174 }] +after transform: SymbolId(3): [Span { start: 126, end: 129 }, Span { start: 171, end: 174 }] rebuilt : SymbolId(5): [] Symbol flags mismatch for "Gar": after transform: SymbolId(6): SymbolFlags(NameSpaceModule | ValueModule) @@ -8273,7 +8273,7 @@ Symbol span mismatch for "Foo": after transform: SymbolId(7): Span { start: 266, end: 269 } rebuilt : SymbolId(12): Span { start: 0, end: 0 } Symbol redeclarations mismatch for "Foo": -after transform: SymbolId(7): [Span { start: 327, end: 330 }] +after transform: SymbolId(7): [Span { start: 266, end: 269 }, Span { start: 327, end: 330 }] rebuilt : SymbolId(12): [] tasks/coverage/typescript/tests/cases/compiler/duplicateConstructSignature.ts @@ -8338,7 +8338,7 @@ Symbol flags mismatch for "a": after transform: SymbolId(0): SymbolFlags(FunctionScopedVariable | Import) rebuilt : SymbolId(0): SymbolFlags(FunctionScopedVariable) Symbol redeclarations mismatch for "a": -after transform: SymbolId(0): [Span { start: 73, end: 74 }] +after transform: SymbolId(0): [Span { start: 50, end: 51 }, Span { start: 73, end: 74 }] rebuilt : SymbolId(0): [] Unresolved references mismatch: after transform: ["M"] @@ -8892,7 +8892,7 @@ Symbol span mismatch for "E": after transform: SymbolId(0): Span { start: 7, end: 8 } rebuilt : SymbolId(0): Span { start: 19, end: 20 } Symbol redeclarations mismatch for "E": -after transform: SymbolId(0): [Span { start: 19, end: 20 }] +after transform: SymbolId(0): [Span { start: 7, end: 8 }, Span { start: 19, end: 20 }] rebuilt : SymbolId(0): [] tasks/coverage/typescript/tests/cases/compiler/errorConstructorSubtypes.ts @@ -10725,7 +10725,7 @@ Symbol reference IDs mismatch for "A": after transform: SymbolId(0): [ReferenceId(0), ReferenceId(2)] rebuilt : SymbolId(0): [ReferenceId(2)] Symbol redeclarations mismatch for "A": -after transform: SymbolId(0): [Span { start: 82, end: 83 }] +after transform: SymbolId(0): [Span { start: 6, end: 7 }, Span { start: 82, end: 83 }] rebuilt : SymbolId(0): [] tasks/coverage/typescript/tests/cases/compiler/es6ClassTest2.ts @@ -11268,7 +11268,7 @@ Symbol flags mismatch for "Foo": after transform: SymbolId(0): SymbolFlags(Function | NameSpaceModule | Ambient) rebuilt : SymbolId(0): SymbolFlags(Function) Symbol redeclarations mismatch for "Foo": -after transform: SymbolId(0): [Span { start: 44, end: 47 }] +after transform: SymbolId(0): [Span { start: 9, end: 12 }, Span { start: 44, end: 47 }] rebuilt : SymbolId(0): [] tasks/coverage/typescript/tests/cases/compiler/expandoFunctionNullishProperty.ts @@ -11303,7 +11303,7 @@ Symbol reference IDs mismatch for "Foo": after transform: SymbolId(0): [ReferenceId(0), ReferenceId(1)] rebuilt : SymbolId(1): [ReferenceId(2)] Symbol redeclarations mismatch for "Foo": -after transform: SymbolId(0): [Span { start: 37, end: 40 }] +after transform: SymbolId(0): [Span { start: 6, end: 9 }, Span { start: 37, end: 40 }] rebuilt : SymbolId(1): [] tasks/coverage/typescript/tests/cases/compiler/exportAssignValueAndType.ts @@ -11320,7 +11320,7 @@ Symbol span mismatch for "server": after transform: SymbolId(2): Span { start: 82, end: 88 } rebuilt : SymbolId(1): Span { start: 152, end: 158 } Symbol redeclarations mismatch for "server": -after transform: SymbolId(2): [Span { start: 152, end: 158 }] +after transform: SymbolId(2): [Span { start: 82, end: 88 }, Span { start: 152, end: 158 }] rebuilt : SymbolId(1): [] Unresolved references mismatch: after transform: ["Date", "http", "module"] @@ -11475,7 +11475,7 @@ Symbol flags mismatch for "B": after transform: SymbolId(1): SymbolFlags(Class | NameSpaceModule | ValueModule) rebuilt : SymbolId(2): SymbolFlags(Class) Symbol redeclarations mismatch for "B": -after transform: SymbolId(1): [Span { start: 84, end: 85 }] +after transform: SymbolId(1): [Span { start: 31, end: 32 }, Span { start: 84, end: 85 }] rebuilt : SymbolId(2): [] tasks/coverage/typescript/tests/cases/compiler/exportDefaultProperty2.ts @@ -11486,7 +11486,7 @@ Symbol flags mismatch for "C": after transform: SymbolId(0): SymbolFlags(Class | NameSpaceModule) rebuilt : SymbolId(1): SymbolFlags(Class) Symbol redeclarations mismatch for "C": -after transform: SymbolId(0): [Span { start: 121, end: 122 }] +after transform: SymbolId(0): [Span { start: 83, end: 84 }, Span { start: 121, end: 122 }] rebuilt : SymbolId(1): [] tasks/coverage/typescript/tests/cases/compiler/exportDefaultVariable.ts @@ -11514,7 +11514,7 @@ Symbol reference IDs mismatch for "server": after transform: SymbolId(0): [ReferenceId(1), ReferenceId(4)] rebuilt : SymbolId(1): [ReferenceId(2)] Symbol redeclarations mismatch for "server": -after transform: SymbolId(0): [Span { start: 77, end: 83 }, Span { start: 149, end: 155 }] +after transform: SymbolId(0): [Span { start: 15, end: 21 }, Span { start: 77, end: 83 }, Span { start: 149, end: 155 }] rebuilt : SymbolId(1): [] Unresolved references mismatch: after transform: ["Date", "Object", "module"] @@ -11545,7 +11545,7 @@ Symbol flags mismatch for "B": after transform: SymbolId(1): SymbolFlags(Class | NameSpaceModule | ValueModule) rebuilt : SymbolId(2): SymbolFlags(Class) Symbol redeclarations mismatch for "B": -after transform: SymbolId(1): [Span { start: 84, end: 85 }] +after transform: SymbolId(1): [Span { start: 31, end: 32 }, Span { start: 84, end: 85 }] rebuilt : SymbolId(2): [] tasks/coverage/typescript/tests/cases/compiler/exportEqualsProperty2.ts @@ -11556,7 +11556,7 @@ Symbol flags mismatch for "C": after transform: SymbolId(0): SymbolFlags(Class | NameSpaceModule) rebuilt : SymbolId(1): SymbolFlags(Class) Symbol redeclarations mismatch for "C": -after transform: SymbolId(0): [Span { start: 116, end: 117 }] +after transform: SymbolId(0): [Span { start: 78, end: 79 }, Span { start: 116, end: 117 }] rebuilt : SymbolId(1): [] tasks/coverage/typescript/tests/cases/compiler/exportImport.ts @@ -11605,7 +11605,7 @@ Symbol span mismatch for "MsPortalFx": after transform: SymbolId(0): Span { start: 7, end: 17 } rebuilt : SymbolId(0): Span { start: 0, end: 0 } Symbol redeclarations mismatch for "MsPortalFx": -after transform: SymbolId(0): [Span { start: 526, end: 536 }] +after transform: SymbolId(0): [Span { start: 7, end: 17 }, Span { start: 526, end: 536 }] rebuilt : SymbolId(0): [] Symbol flags mismatch for "ViewModels": after transform: SymbolId(1): SymbolFlags(NameSpaceModule | ValueModule) @@ -11700,7 +11700,7 @@ Symbol span mismatch for "Foo": after transform: SymbolId(0): Span { start: 12, end: 15 } rebuilt : SymbolId(0): Span { start: 73, end: 76 } Symbol redeclarations mismatch for "Foo": -after transform: SymbolId(0): [Span { start: 73, end: 76 }] +after transform: SymbolId(0): [Span { start: 12, end: 15 }, Span { start: 73, end: 76 }] rebuilt : SymbolId(0): [] tasks/coverage/typescript/tests/cases/compiler/exportSpecifierAndExportedMemberDeclaration.ts @@ -11825,7 +11825,7 @@ Symbol span mismatch for "M": after transform: SymbolId(0): Span { start: 7, end: 8 } rebuilt : SymbolId(1): Span { start: 0, end: 0 } Symbol redeclarations mismatch for "M": -after transform: SymbolId(0): [Span { start: 104, end: 105 }] +after transform: SymbolId(0): [Span { start: 7, end: 8 }, Span { start: 104, end: 105 }] rebuilt : SymbolId(1): [] Symbol flags mismatch for "N": after transform: SymbolId(4): SymbolFlags(NameSpaceModule | ValueModule) @@ -12257,7 +12257,7 @@ Symbol reference IDs mismatch for "f": after transform: SymbolId(0): [ReferenceId(0), ReferenceId(1)] rebuilt : SymbolId(0): [ReferenceId(0)] Symbol redeclarations mismatch for "f": -after transform: SymbolId(0): [Span { start: 26, end: 27 }] +after transform: SymbolId(0): [Span { start: 10, end: 11 }, Span { start: 26, end: 27 }] rebuilt : SymbolId(0): [] tasks/coverage/typescript/tests/cases/compiler/functionExpressionAndLambdaMatchesFunction.ts @@ -12308,7 +12308,7 @@ Symbol flags mismatch for "foo": after transform: SymbolId(0): SymbolFlags(Function | NameSpaceModule | ValueModule) rebuilt : SymbolId(0): SymbolFlags(Function) Symbol redeclarations mismatch for "foo": -after transform: SymbolId(0): [Span { start: 56, end: 59 }, Span { start: 108, end: 111 }] +after transform: SymbolId(0): [Span { start: 9, end: 12 }, Span { start: 56, end: 59 }, Span { start: 108, end: 111 }] rebuilt : SymbolId(0): [] Symbol flags mismatch for "Bar": after transform: SymbolId(3): SymbolFlags(NameSpaceModule | ValueModule) @@ -13172,7 +13172,7 @@ Symbol reference IDs mismatch for "C": after transform: SymbolId(4): [ReferenceId(3), ReferenceId(8), ReferenceId(11), ReferenceId(13)] rebuilt : SymbolId(4): [ReferenceId(2), ReferenceId(5), ReferenceId(6)] Symbol redeclarations mismatch for "C": -after transform: SymbolId(4): [Span { start: 100, end: 101 }] +after transform: SymbolId(4): [Span { start: 66, end: 67 }, Span { start: 100, end: 101 }] rebuilt : SymbolId(4): [] Unresolved references mismatch: after transform: ["M"] @@ -13201,7 +13201,7 @@ Symbol reference IDs mismatch for "C": after transform: SymbolId(4): [ReferenceId(3), ReferenceId(8), ReferenceId(11), ReferenceId(13)] rebuilt : SymbolId(4): [ReferenceId(2), ReferenceId(5), ReferenceId(6)] Symbol redeclarations mismatch for "C": -after transform: SymbolId(4): [Span { start: 100, end: 101 }] +after transform: SymbolId(4): [Span { start: 66, end: 67 }, Span { start: 100, end: 101 }] rebuilt : SymbolId(4): [] Symbol flags mismatch for "N": after transform: SymbolId(7): SymbolFlags(NameSpaceModule | ValueModule) @@ -13449,7 +13449,7 @@ Symbol reference IDs mismatch for "a1": after transform: SymbolId(1): [ReferenceId(0), ReferenceId(111)] rebuilt : SymbolId(4): [ReferenceId(3)] Symbol redeclarations mismatch for "a1": -after transform: SymbolId(1): [Span { start: 724, end: 731 }] +after transform: SymbolId(1): [Span { start: 18, end: 20 }, Span { start: 724, end: 731 }] rebuilt : SymbolId(4): [] tasks/coverage/typescript/tests/cases/compiler/getAccessorWithImpliedReturnTypeAndFunctionClassMerge.ts @@ -13769,7 +13769,7 @@ Symbol reference IDs mismatch for "MyFunction": after transform: SymbolId(0): [ReferenceId(0), ReferenceId(3)] rebuilt : SymbolId(0): [ReferenceId(2)] Symbol redeclarations mismatch for "MyFunction": -after transform: SymbolId(0): [Span { start: 52, end: 62 }] +after transform: SymbolId(0): [Span { start: 10, end: 20 }, Span { start: 52, end: 62 }] rebuilt : SymbolId(0): [] tasks/coverage/typescript/tests/cases/compiler/importHelpers.ts @@ -13959,7 +13959,7 @@ Symbol span mismatch for "foo": after transform: SymbolId(0): Span { start: 7, end: 10 } rebuilt : SymbolId(0): Span { start: 48, end: 51 } Symbol redeclarations mismatch for "foo": -after transform: SymbolId(0): [Span { start: 48, end: 51 }] +after transform: SymbolId(0): [Span { start: 7, end: 10 }, Span { start: 48, end: 51 }] rebuilt : SymbolId(0): [] Unresolved references mismatch: after transform: ["m1"] @@ -15092,7 +15092,7 @@ Symbol reference IDs mismatch for "B": after transform: SymbolId(1): [ReferenceId(0), ReferenceId(5), ReferenceId(7)] rebuilt : SymbolId(2): [ReferenceId(2), ReferenceId(3)] Symbol redeclarations mismatch for "B": -after transform: SymbolId(1): [Span { start: 136, end: 137 }] +after transform: SymbolId(1): [Span { start: 30, end: 31 }, Span { start: 136, end: 137 }] rebuilt : SymbolId(2): [] Unresolved references mismatch: after transform: ["A"] @@ -15179,7 +15179,7 @@ Symbol reference IDs mismatch for "B": after transform: SymbolId(1): [ReferenceId(0), ReferenceId(4), ReferenceId(5)] rebuilt : SymbolId(2): [ReferenceId(2), ReferenceId(3)] Symbol redeclarations mismatch for "B": -after transform: SymbolId(1): [Span { start: 129, end: 130 }] +after transform: SymbolId(1): [Span { start: 23, end: 24 }, Span { start: 129, end: 130 }] rebuilt : SymbolId(2): [] Unresolved references mismatch: after transform: ["A"] @@ -15211,7 +15211,7 @@ Symbol span mismatch for "B": after transform: SymbolId(1): Span { start: 30, end: 31 } rebuilt : SymbolId(2): Span { start: 0, end: 0 } Symbol redeclarations mismatch for "B": -after transform: SymbolId(1): [Span { start: 134, end: 135 }] +after transform: SymbolId(1): [Span { start: 30, end: 31 }, Span { start: 134, end: 135 }] rebuilt : SymbolId(2): [] tasks/coverage/typescript/tests/cases/compiler/interMixingModulesInterfaces5.ts @@ -15259,7 +15259,7 @@ Symbol span mismatch for "Foo": after transform: SymbolId(0): Span { start: 10, end: 13 } rebuilt : SymbolId(1): Span { start: 149, end: 152 } Symbol redeclarations mismatch for "Foo": -after transform: SymbolId(0): [Span { start: 149, end: 152 }] +after transform: SymbolId(0): [Span { start: 10, end: 13 }, Span { start: 149, end: 152 }] rebuilt : SymbolId(1): [] tasks/coverage/typescript/tests/cases/compiler/interfaceClassMerging2.ts @@ -15276,7 +15276,7 @@ Symbol span mismatch for "Foo": after transform: SymbolId(0): Span { start: 10, end: 13 } rebuilt : SymbolId(1): Span { start: 89, end: 92 } Symbol redeclarations mismatch for "Foo": -after transform: SymbolId(0): [Span { start: 89, end: 92 }] +after transform: SymbolId(0): [Span { start: 10, end: 13 }, Span { start: 89, end: 92 }] rebuilt : SymbolId(1): [] Symbol flags mismatch for "Bar": after transform: SymbolId(1): SymbolFlags(Class | Interface) @@ -15285,7 +15285,7 @@ Symbol span mismatch for "Bar": after transform: SymbolId(1): Span { start: 194, end: 197 } rebuilt : SymbolId(2): Span { start: 273, end: 276 } Symbol redeclarations mismatch for "Bar": -after transform: SymbolId(1): [Span { start: 273, end: 276 }] +after transform: SymbolId(1): [Span { start: 194, end: 197 }, Span { start: 273, end: 276 }] rebuilt : SymbolId(2): [] tasks/coverage/typescript/tests/cases/compiler/interfaceContextualType.ts @@ -15307,7 +15307,7 @@ Symbol span mismatch for "I2": after transform: SymbolId(1): Span { start: 42, end: 44 } rebuilt : SymbolId(0): Span { start: 55, end: 57 } Symbol redeclarations mismatch for "I2": -after transform: SymbolId(1): [Span { start: 55, end: 57 }] +after transform: SymbolId(1): [Span { start: 42, end: 44 }, Span { start: 55, end: 57 }] rebuilt : SymbolId(0): [] Symbol flags mismatch for "I3": after transform: SymbolId(2): SymbolFlags(Function | Interface) @@ -15316,7 +15316,7 @@ Symbol span mismatch for "I3": after transform: SymbolId(2): Span { start: 73, end: 75 } rebuilt : SymbolId(1): Span { start: 89, end: 91 } Symbol redeclarations mismatch for "I3": -after transform: SymbolId(2): [Span { start: 89, end: 91 }] +after transform: SymbolId(2): [Span { start: 73, end: 75 }, Span { start: 89, end: 91 }] rebuilt : SymbolId(1): [] Symbol flags mismatch for "I4": after transform: SymbolId(3): SymbolFlags(FunctionScopedVariable | Interface) @@ -15325,7 +15325,7 @@ Symbol span mismatch for "I4": after transform: SymbolId(3): Span { start: 109, end: 111 } rebuilt : SymbolId(2): Span { start: 120, end: 129 } Symbol redeclarations mismatch for "I4": -after transform: SymbolId(3): [Span { start: 120, end: 129 }] +after transform: SymbolId(3): [Span { start: 109, end: 111 }, Span { start: 120, end: 129 }] rebuilt : SymbolId(2): [] tasks/coverage/typescript/tests/cases/compiler/interfaceDeclaration5.ts @@ -15659,7 +15659,7 @@ Symbol reference IDs mismatch for "A": after transform: SymbolId(0): [ReferenceId(0)] rebuilt : SymbolId(1): [] Symbol redeclarations mismatch for "A": -after transform: SymbolId(0): [Span { start: 38, end: 39 }] +after transform: SymbolId(0): [Span { start: 6, end: 7 }, Span { start: 38, end: 39 }] rebuilt : SymbolId(1): [] tasks/coverage/typescript/tests/cases/compiler/internalImportUnInstantiatedModuleNotReferencingInstanceNoConflict.ts @@ -15967,7 +15967,7 @@ Symbol span mismatch for "schema": after transform: SymbolId(0): Span { start: 25, end: 31 } rebuilt : SymbolId(0): Span { start: 0, end: 0 } Symbol redeclarations mismatch for "schema": -after transform: SymbolId(0): [Span { start: 168, end: 174 }, Span { start: 309, end: 315 }, Span { start: 464, end: 470 }, Span { start: 613, end: 619 }, Span { start: 756, end: 762 }, Span { start: 908, end: 914 }, Span { start: 1055, end: 1061 }, Span { start: 1187, end: 1193 }] +after transform: SymbolId(0): [Span { start: 25, end: 31 }, Span { start: 168, end: 174 }, Span { start: 309, end: 315 }, Span { start: 464, end: 470 }, Span { start: 613, end: 619 }, Span { start: 756, end: 762 }, Span { start: 908, end: 914 }, Span { start: 1055, end: 1061 }, Span { start: 1187, end: 1193 }] rebuilt : SymbolId(0): [] Unresolved references mismatch: after transform: ["Array", "undefined"] @@ -16388,7 +16388,7 @@ Symbol flags mismatch for "X": after transform: SymbolId(0): SymbolFlags(Class | NameSpaceModule) rebuilt : SymbolId(1): SymbolFlags(Class) Symbol redeclarations mismatch for "X": -after transform: SymbolId(0): [Span { start: 106, end: 107 }] +after transform: SymbolId(0): [Span { start: 13, end: 14 }, Span { start: 106, end: 107 }] rebuilt : SymbolId(1): [] tasks/coverage/typescript/tests/cases/compiler/jsxMultilineAttributeValuesReact.tsx @@ -16963,7 +16963,7 @@ Symbol flags mismatch for "E": after transform: SymbolId(0): SymbolFlags(RegularEnum) rebuilt : SymbolId(0): SymbolFlags(FunctionScopedVariable) Symbol redeclarations mismatch for "E": -after transform: SymbolId(0): [Span { start: 33, end: 34 }] +after transform: SymbolId(0): [Span { start: 5, end: 6 }, Span { start: 33, end: 34 }] rebuilt : SymbolId(0): [] Unresolved references mismatch: after transform: ["a"] @@ -16993,7 +16993,7 @@ Symbol span mismatch for "X": after transform: SymbolId(0): Span { start: 14, end: 15 } rebuilt : SymbolId(0): Span { start: 0, end: 0 } Symbol redeclarations mismatch for "X": -after transform: SymbolId(0): [Span { start: 163, end: 164 }] +after transform: SymbolId(0): [Span { start: 14, end: 15 }, Span { start: 163, end: 164 }] rebuilt : SymbolId(0): [] Symbol flags mismatch for "Y": after transform: SymbolId(1): SymbolFlags(NameSpaceModule | ValueModule) @@ -17031,7 +17031,7 @@ Symbol span mismatch for "my": after transform: SymbolId(0): Span { start: 7, end: 9 } rebuilt : SymbolId(0): Span { start: 0, end: 0 } Symbol redeclarations mismatch for "my": -after transform: SymbolId(0): [Span { start: 60, end: 62 }] +after transform: SymbolId(0): [Span { start: 7, end: 9 }, Span { start: 60, end: 62 }] rebuilt : SymbolId(0): [] Symbol flags mismatch for "data": after transform: SymbolId(1): SymbolFlags(NameSpaceModule | ValueModule) @@ -17075,7 +17075,7 @@ Symbol span mismatch for "my": after transform: SymbolId(0): Span { start: 7, end: 9 } rebuilt : SymbolId(0): Span { start: 0, end: 0 } Symbol redeclarations mismatch for "my": -after transform: SymbolId(0): [Span { start: 56, end: 58 }] +after transform: SymbolId(0): [Span { start: 7, end: 9 }, Span { start: 56, end: 58 }] rebuilt : SymbolId(0): [] Symbol flags mismatch for "data": after transform: SymbolId(1): SymbolFlags(NameSpaceModule | ValueModule) @@ -17140,7 +17140,7 @@ Symbol span mismatch for "my": after transform: SymbolId(2): Span { start: 72, end: 74 } rebuilt : SymbolId(4): Span { start: 0, end: 0 } Symbol redeclarations mismatch for "my": -after transform: SymbolId(2): [Span { start: 202, end: 204 }] +after transform: SymbolId(2): [Span { start: 72, end: 74 }, Span { start: 202, end: 204 }] rebuilt : SymbolId(4): [] Symbol flags mismatch for "buz": after transform: SymbolId(3): SymbolFlags(NameSpaceModule | ValueModule) @@ -17457,7 +17457,7 @@ Symbol span mismatch for "My": after transform: SymbolId(1): Span { start: 30, end: 32 } rebuilt : SymbolId(2): Span { start: 84, end: 86 } Symbol redeclarations mismatch for "My": -after transform: SymbolId(1): [Span { start: 84, end: 86 }] +after transform: SymbolId(1): [Span { start: 30, end: 32 }, Span { start: 84, end: 86 }] rebuilt : SymbolId(2): [] Symbol flags mismatch for "B": after transform: SymbolId(4): SymbolFlags(NameSpaceModule | ValueModule) @@ -17472,7 +17472,7 @@ Symbol span mismatch for "My": after transform: SymbolId(5): Span { start: 135, end: 137 } rebuilt : SymbolId(6): Span { start: 218, end: 220 } Symbol redeclarations mismatch for "My": -after transform: SymbolId(5): [Span { start: 218, end: 220 }] +after transform: SymbolId(5): [Span { start: 135, end: 137 }, Span { start: 218, end: 220 }] rebuilt : SymbolId(6): [] Symbol flags mismatch for "C": after transform: SymbolId(9): SymbolFlags(NameSpaceModule | ValueModule) @@ -17948,7 +17948,7 @@ Symbol span mismatch for "TypeScript": after transform: SymbolId(0): Span { start: 7, end: 17 } rebuilt : SymbolId(0): Span { start: 0, end: 0 } Symbol redeclarations mismatch for "TypeScript": -after transform: SymbolId(0): [Span { start: 146, end: 156 }, Span { start: 535, end: 545 }, Span { start: 879, end: 889 }] +after transform: SymbolId(0): [Span { start: 7, end: 17 }, Span { start: 146, end: 156 }, Span { start: 535, end: 545 }, Span { start: 879, end: 889 }] rebuilt : SymbolId(0): [] Symbol flags mismatch for "Parser": after transform: SymbolId(1): SymbolFlags(NameSpaceModule | ValueModule) @@ -17989,7 +17989,7 @@ Symbol span mismatch for "A": after transform: SymbolId(0): Span { start: 101, end: 102 } rebuilt : SymbolId(0): Span { start: 0, end: 0 } Symbol redeclarations mismatch for "A": -after transform: SymbolId(0): [Span { start: 227, end: 228 }] +after transform: SymbolId(0): [Span { start: 101, end: 102 }, Span { start: 227, end: 228 }] rebuilt : SymbolId(0): [] tasks/coverage/typescript/tests/cases/compiler/moduleMergeConstructor.ts @@ -18048,7 +18048,7 @@ Symbol flags mismatch for "A": after transform: SymbolId(0): SymbolFlags(Class | NameSpaceModule) rebuilt : SymbolId(0): SymbolFlags(Class) Symbol redeclarations mismatch for "A": -after transform: SymbolId(0): [Span { start: 19, end: 20 }] +after transform: SymbolId(0): [Span { start: 6, end: 7 }, Span { start: 19, end: 20 }] rebuilt : SymbolId(0): [] tasks/coverage/typescript/tests/cases/compiler/moduleReopenedTypeOtherBlock.ts @@ -18068,7 +18068,7 @@ Symbol span mismatch for "M": after transform: SymbolId(0): Span { start: 7, end: 8 } rebuilt : SymbolId(0): Span { start: 0, end: 0 } Symbol redeclarations mismatch for "M": -after transform: SymbolId(0): [Span { start: 82, end: 83 }] +after transform: SymbolId(0): [Span { start: 7, end: 8 }, Span { start: 82, end: 83 }] rebuilt : SymbolId(0): [] Unresolved references mismatch: after transform: ["I"] @@ -18091,7 +18091,7 @@ Symbol span mismatch for "M": after transform: SymbolId(0): Span { start: 7, end: 8 } rebuilt : SymbolId(0): Span { start: 0, end: 0 } Symbol redeclarations mismatch for "M": -after transform: SymbolId(0): [Span { start: 40, end: 41 }] +after transform: SymbolId(0): [Span { start: 7, end: 8 }, Span { start: 40, end: 41 }] rebuilt : SymbolId(0): [] tasks/coverage/typescript/tests/cases/compiler/moduleResolutionAsTypeReferenceDirective.ts @@ -18433,7 +18433,7 @@ Symbol span mismatch for "M": after transform: SymbolId(5): Span { start: 95, end: 96 } rebuilt : SymbolId(9): Span { start: 112, end: 113 } Symbol redeclarations mismatch for "M": -after transform: SymbolId(5): [Span { start: 112, end: 113 }] +after transform: SymbolId(5): [Span { start: 95, end: 96 }, Span { start: 112, end: 113 }] rebuilt : SymbolId(9): [] tasks/coverage/typescript/tests/cases/compiler/moduleSharesNameWithImportDeclarationInsideIt6.ts @@ -18628,7 +18628,7 @@ Symbol span mismatch for "M": after transform: SymbolId(0): Span { start: 7, end: 8 } rebuilt : SymbolId(0): Span { start: 0, end: 0 } Symbol redeclarations mismatch for "M": -after transform: SymbolId(0): [Span { start: 43, end: 44 }] +after transform: SymbolId(0): [Span { start: 7, end: 8 }, Span { start: 43, end: 44 }] rebuilt : SymbolId(0): [] tasks/coverage/typescript/tests/cases/compiler/namedFunctionExpressionInModule.ts @@ -19287,7 +19287,7 @@ Symbol flags mismatch for "Foo": after transform: SymbolId(1): SymbolFlags(Class | NameSpaceModule | Ambient) rebuilt : SymbolId(1): SymbolFlags(Class) Symbol redeclarations mismatch for "Foo": -after transform: SymbolId(1): [Span { start: 61, end: 64 }] +after transform: SymbolId(1): [Span { start: 22, end: 25 }, Span { start: 61, end: 64 }] rebuilt : SymbolId(1): [] tasks/coverage/typescript/tests/cases/compiler/noCollisionThisExpressionAndLocalVarInFunction.ts @@ -20298,7 +20298,7 @@ Symbol span mismatch for "foo": after transform: SymbolId(0): Span { start: 15, end: 18 } rebuilt : SymbolId(0): Span { start: 59, end: 62 } Symbol redeclarations mismatch for "foo": -after transform: SymbolId(0): [Span { start: 59, end: 62 }] +after transform: SymbolId(0): [Span { start: 15, end: 18 }, Span { start: 59, end: 62 }] rebuilt : SymbolId(0): [] tasks/coverage/typescript/tests/cases/compiler/partiallyAmbientFundule.ts @@ -20312,7 +20312,7 @@ Symbol span mismatch for "foo": after transform: SymbolId(0): Span { start: 15, end: 18 } rebuilt : SymbolId(0): Span { start: 62, end: 65 } Symbol redeclarations mismatch for "foo": -after transform: SymbolId(0): [Span { start: 62, end: 65 }] +after transform: SymbolId(0): [Span { start: 15, end: 18 }, Span { start: 62, end: 65 }] rebuilt : SymbolId(0): [] tasks/coverage/typescript/tests/cases/compiler/partiallyDiscriminantedUnions.ts @@ -20585,7 +20585,7 @@ Symbol span mismatch for "Q": after transform: SymbolId(3): Span { start: 92, end: 93 } rebuilt : SymbolId(1): Span { start: 0, end: 0 } Symbol redeclarations mismatch for "Q": -after transform: SymbolId(3): [Span { start: 190, end: 191 }] +after transform: SymbolId(3): [Span { start: 92, end: 93 }, Span { start: 190, end: 191 }] rebuilt : SymbolId(1): [] tasks/coverage/typescript/tests/cases/compiler/privacyCheckCallbackOfInterfaceMethodWithTypeParameter.ts @@ -20610,7 +20610,7 @@ Symbol reference IDs mismatch for "Foo": after transform: SymbolId(0): [ReferenceId(0), ReferenceId(1), ReferenceId(2)] rebuilt : SymbolId(0): [ReferenceId(1)] Symbol redeclarations mismatch for "Foo": -after transform: SymbolId(0): [Span { start: 59, end: 62 }, Span { start: 74, end: 107 }] +after transform: SymbolId(0): [Span { start: 7, end: 10 }, Span { start: 59, end: 62 }, Span { start: 74, end: 107 }] rebuilt : SymbolId(0): [] tasks/coverage/typescript/tests/cases/compiler/privacyCheckExportAssignmentOnExportedGenericInterface2.ts @@ -22842,7 +22842,7 @@ Symbol span mismatch for "Foo": after transform: SymbolId(0): Span { start: 14, end: 17 } rebuilt : SymbolId(0): Span { start: 0, end: 0 } Symbol redeclarations mismatch for "Foo": -after transform: SymbolId(0): [Span { start: 56, end: 59 }] +after transform: SymbolId(0): [Span { start: 14, end: 17 }, Span { start: 56, end: 59 }] rebuilt : SymbolId(0): [] Unresolved reference IDs mismatch for "C": after transform: [ReferenceId(0), ReferenceId(2), ReferenceId(3), ReferenceId(6)] @@ -23038,7 +23038,7 @@ Symbol span mismatch for "Sizing": after transform: SymbolId(0): Span { start: 12, end: 18 } rebuilt : SymbolId(0): Span { start: 39, end: 45 } Symbol redeclarations mismatch for "Sizing": -after transform: SymbolId(0): [Span { start: 39, end: 45 }] +after transform: SymbolId(0): [Span { start: 12, end: 18 }, Span { start: 39, end: 45 }] rebuilt : SymbolId(0): [] tasks/coverage/typescript/tests/cases/compiler/reexportWrittenCorrectlyInDeclaration.ts @@ -23173,7 +23173,7 @@ Symbol reference IDs mismatch for "bar": after transform: SymbolId(0): [ReferenceId(0)] rebuilt : SymbolId(0): [] Symbol redeclarations mismatch for "bar": -after transform: SymbolId(0): [Span { start: 22, end: 30 }] +after transform: SymbolId(0): [Span { start: 10, end: 13 }, Span { start: 22, end: 30 }] rebuilt : SymbolId(0): [] tasks/coverage/typescript/tests/cases/compiler/resolveInterfaceNameWithSameLetDeclarationName2.ts @@ -23193,7 +23193,7 @@ Symbol reference IDs mismatch for "bar": after transform: SymbolId(1): [ReferenceId(0), ReferenceId(2)] rebuilt : SymbolId(0): [] Symbol redeclarations mismatch for "bar": -after transform: SymbolId(1): [Span { start: 40, end: 54 }] +after transform: SymbolId(1): [Span { start: 28, end: 31 }, Span { start: 40, end: 54 }] rebuilt : SymbolId(0): [] Symbol flags mismatch for "foo": after transform: SymbolId(0): SymbolFlags(BlockScopedVariable | Interface) @@ -23205,7 +23205,7 @@ Symbol reference IDs mismatch for "foo": after transform: SymbolId(0): [ReferenceId(1), ReferenceId(3)] rebuilt : SymbolId(1): [] Symbol redeclarations mismatch for "foo": -after transform: SymbolId(0): [Span { start: 60, end: 74 }] +after transform: SymbolId(0): [Span { start: 10, end: 13 }, Span { start: 60, end: 74 }] rebuilt : SymbolId(1): [] tasks/coverage/typescript/tests/cases/compiler/resolveModuleNameWithSameLetDeclarationName1.ts @@ -23219,7 +23219,7 @@ Symbol span mismatch for "foo": after transform: SymbolId(0): Span { start: 15, end: 18 } rebuilt : SymbolId(0): Span { start: 56, end: 68 } Symbol redeclarations mismatch for "foo": -after transform: SymbolId(0): [Span { start: 56, end: 68 }] +after transform: SymbolId(0): [Span { start: 15, end: 18 }, Span { start: 56, end: 68 }] rebuilt : SymbolId(0): [] Unresolved references mismatch: after transform: ["foo"] @@ -23244,7 +23244,7 @@ Symbol span mismatch for "myAssert": after transform: SymbolId(0): Span { start: 44, end: 52 } rebuilt : SymbolId(0): Span { start: 91, end: 99 } Symbol redeclarations mismatch for "myAssert": -after transform: SymbolId(0): [Span { start: 91, end: 99 }] +after transform: SymbolId(0): [Span { start: 44, end: 52 }, Span { start: 91, end: 99 }] rebuilt : SymbolId(0): [] tasks/coverage/typescript/tests/cases/compiler/resolveTypeAliasWithSameLetDeclarationName1.ts @@ -23267,7 +23267,7 @@ Symbol reference IDs mismatch for "baz": after transform: SymbolId(1): [ReferenceId(1)] rebuilt : SymbolId(1): [] Symbol redeclarations mismatch for "baz": -after transform: SymbolId(1): [Span { start: 30, end: 38 }] +after transform: SymbolId(1): [Span { start: 17, end: 20 }, Span { start: 30, end: 38 }] rebuilt : SymbolId(1): [] tasks/coverage/typescript/tests/cases/compiler/restParamUsingMappedTypeOverUnionConstraint.ts @@ -25184,7 +25184,7 @@ Symbol span mismatch for "m1": after transform: SymbolId(0): Span { start: 7, end: 9 } rebuilt : SymbolId(0): Span { start: 0, end: 0 } Symbol redeclarations mismatch for "m1": -after transform: SymbolId(0): [Span { start: 64, end: 66 }] +after transform: SymbolId(0): [Span { start: 7, end: 9 }, Span { start: 64, end: 66 }] rebuilt : SymbolId(0): [] tasks/coverage/typescript/tests/cases/compiler/specedNoStackBlown.ts @@ -25834,7 +25834,7 @@ Symbol flags mismatch for "C": after transform: SymbolId(0): SymbolFlags(Class | Interface) rebuilt : SymbolId(0): SymbolFlags(Class) Symbol redeclarations mismatch for "C": -after transform: SymbolId(0): [Span { start: 31, end: 32 }] +after transform: SymbolId(0): [Span { start: 6, end: 7 }, Span { start: 31, end: 32 }] rebuilt : SymbolId(0): [] tasks/coverage/typescript/tests/cases/compiler/superWithGenericSpecialization.ts @@ -25879,7 +25879,7 @@ Symbol span mismatch for "X": after transform: SymbolId(0): Span { start: 9, end: 10 } rebuilt : SymbolId(0): Span { start: 35, end: 36 } Symbol redeclarations mismatch for "X": -after transform: SymbolId(0): [Span { start: 35, end: 36 }] +after transform: SymbolId(0): [Span { start: 9, end: 10 }, Span { start: 35, end: 36 }] rebuilt : SymbolId(0): [] tasks/coverage/typescript/tests/cases/compiler/symbolObserverMismatchingPolyfillsWorkTogether.ts @@ -25918,7 +25918,7 @@ Symbol span mismatch for "M": after transform: SymbolId(0): Span { start: 49, end: 50 } rebuilt : SymbolId(0): Span { start: 0, end: 0 } Symbol redeclarations mismatch for "M": -after transform: SymbolId(0): [Span { start: 123, end: 124 }] +after transform: SymbolId(0): [Span { start: 49, end: 50 }, Span { start: 123, end: 124 }] rebuilt : SymbolId(0): [] tasks/coverage/typescript/tests/cases/compiler/systemModuleAmbientDeclarations.ts @@ -26001,19 +26001,19 @@ Symbol flags mismatch for "F": after transform: SymbolId(0): SymbolFlags(Function | NameSpaceModule | ValueModule) rebuilt : SymbolId(0): SymbolFlags(Function) Symbol redeclarations mismatch for "F": -after transform: SymbolId(0): [Span { start: 37, end: 38 }] +after transform: SymbolId(0): [Span { start: 16, end: 17 }, Span { start: 37, end: 38 }] rebuilt : SymbolId(0): [] Symbol flags mismatch for "C": after transform: SymbolId(2): SymbolFlags(Class | NameSpaceModule | ValueModule) rebuilt : SymbolId(3): SymbolFlags(Class) Symbol redeclarations mismatch for "C": -after transform: SymbolId(2): [Span { start: 83, end: 84 }] +after transform: SymbolId(2): [Span { start: 64, end: 65 }, Span { start: 83, end: 84 }] rebuilt : SymbolId(3): [] Symbol flags mismatch for "E": after transform: SymbolId(4): SymbolFlags(RegularEnum | NameSpaceModule | ValueModule) rebuilt : SymbolId(6): SymbolFlags(BlockScopedVariable) Symbol redeclarations mismatch for "E": -after transform: SymbolId(4): [Span { start: 128, end: 129 }] +after transform: SymbolId(4): [Span { start: 109, end: 110 }, Span { start: 128, end: 129 }] rebuilt : SymbolId(6): [] tasks/coverage/typescript/tests/cases/compiler/systemModuleNonTopLevelModuleMembers.ts @@ -26374,7 +26374,7 @@ Symbol flags mismatch for "createElement": after transform: SymbolId(2): SymbolFlags(Function | NameSpaceModule) rebuilt : SymbolId(1): SymbolFlags(Function) Symbol redeclarations mismatch for "createElement": -after transform: SymbolId(2): [Span { start: 243, end: 256 }] +after transform: SymbolId(2): [Span { start: 125, end: 138 }, Span { start: 243, end: 256 }] rebuilt : SymbolId(1): [] Unresolved references mismatch: after transform: ["Date", "React"] @@ -26559,7 +26559,7 @@ Symbol reference IDs mismatch for "Mixin": after transform: SymbolId(0): [ReferenceId(3), ReferenceId(6)] rebuilt : SymbolId(0): [] Symbol redeclarations mismatch for "Mixin": -after transform: SymbolId(0): [Span { start: 152, end: 157 }] +after transform: SymbolId(0): [Span { start: 42, end: 47 }, Span { start: 152, end: 157 }] rebuilt : SymbolId(0): [] tasks/coverage/typescript/tests/cases/compiler/typeAnnotationBestCommonTypeInArrayLiteral.ts @@ -26879,7 +26879,7 @@ Symbol reference IDs mismatch for "A": after transform: SymbolId(1): [ReferenceId(1), ReferenceId(2), ReferenceId(3)] rebuilt : SymbolId(1): [ReferenceId(0)] Symbol redeclarations mismatch for "A": -after transform: SymbolId(1): [Span { start: 29, end: 33 }] +after transform: SymbolId(1): [Span { start: 11, end: 12 }, Span { start: 29, end: 33 }] rebuilt : SymbolId(1): [] Unresolved references mismatch: after transform: ["Number"] @@ -27275,7 +27275,7 @@ Symbol reference IDs mismatch for "I": after transform: SymbolId(0): [ReferenceId(0), ReferenceId(1)] rebuilt : SymbolId(0): [ReferenceId(0)] Symbol redeclarations mismatch for "I": -after transform: SymbolId(0): [Span { start: 35, end: 38 }] +after transform: SymbolId(0): [Span { start: 10, end: 11 }, Span { start: 35, end: 38 }] rebuilt : SymbolId(0): [] tasks/coverage/typescript/tests/cases/compiler/typeVariableConstraintIntersections.ts @@ -27352,7 +27352,7 @@ Symbol reference IDs mismatch for "I": after transform: SymbolId(0): [ReferenceId(0), ReferenceId(1)] rebuilt : SymbolId(0): [] Symbol redeclarations mismatch for "I": -after transform: SymbolId(0): [Span { start: 32, end: 33 }] +after transform: SymbolId(0): [Span { start: 4, end: 19 }, Span { start: 32, end: 33 }] rebuilt : SymbolId(0): [] Symbol reference IDs mismatch for "k": after transform: SymbolId(1): [ReferenceId(2)] @@ -27632,7 +27632,7 @@ Symbol span mismatch for "M": after transform: SymbolId(0): Span { start: 7, end: 8 } rebuilt : SymbolId(0): Span { start: 0, end: 0 } Symbol redeclarations mismatch for "M": -after transform: SymbolId(0): [Span { start: 61, end: 62 }] +after transform: SymbolId(0): [Span { start: 7, end: 8 }, Span { start: 61, end: 62 }] rebuilt : SymbolId(0): [] tasks/coverage/typescript/tests/cases/compiler/unionCallMixedTypeParameterPresence.ts @@ -27970,13 +27970,13 @@ Symbol flags mismatch for "C1": after transform: SymbolId(0): SymbolFlags(Class | Interface) rebuilt : SymbolId(1): SymbolFlags(Class) Symbol redeclarations mismatch for "C1": -after transform: SymbolId(0): [Span { start: 46, end: 48 }] +after transform: SymbolId(0): [Span { start: 26, end: 28 }, Span { start: 46, end: 48 }] rebuilt : SymbolId(1): [] Symbol flags mismatch for "C2": after transform: SymbolId(3): SymbolFlags(Class | Interface) rebuilt : SymbolId(2): SymbolFlags(Class) Symbol redeclarations mismatch for "C2": -after transform: SymbolId(3): [Span { start: 116, end: 118 }] +after transform: SymbolId(3): [Span { start: 90, end: 92 }, Span { start: 116, end: 118 }] rebuilt : SymbolId(2): [] tasks/coverage/typescript/tests/cases/compiler/unusedTypeParametersNotCheckedByNoUnusedLocals.ts @@ -29777,7 +29777,7 @@ Symbol flags mismatch for "C": after transform: SymbolId(0): SymbolFlags(Class | Interface) rebuilt : SymbolId(1): SymbolFlags(Class) Symbol redeclarations mismatch for "C": -after transform: SymbolId(0): [Span { start: 35, end: 36 }] +after transform: SymbolId(0): [Span { start: 6, end: 7 }, Span { start: 35, end: 36 }] rebuilt : SymbolId(1): [] Symbol flags mismatch for "M": after transform: SymbolId(1): SymbolFlags(NameSpaceModule | ValueModule) @@ -29789,7 +29789,7 @@ Symbol flags mismatch for "D": after transform: SymbolId(2): SymbolFlags(Class | Interface) rebuilt : SymbolId(4): SymbolFlags(Class) Symbol redeclarations mismatch for "D": -after transform: SymbolId(2): [Span { start: 122, end: 123 }] +after transform: SymbolId(2): [Span { start: 76, end: 77 }, Span { start: 122, end: 123 }] rebuilt : SymbolId(4): [] tasks/coverage/typescript/tests/cases/conformance/classes/classDeclarations/classBody/classWithEmptyBody.ts @@ -29853,7 +29853,7 @@ Symbol flags mismatch for "C3": after transform: SymbolId(2): SymbolFlags(Class | Interface) rebuilt : SymbolId(0): SymbolFlags(Class) Symbol redeclarations mismatch for "C3": -after transform: SymbolId(2): [Span { start: 104, end: 106 }] +after transform: SymbolId(2): [Span { start: 86, end: 88 }, Span { start: 104, end: 106 }] rebuilt : SymbolId(0): [] Symbol flags mismatch for "C4": after transform: SymbolId(3): SymbolFlags(Class | Interface) @@ -29862,7 +29862,7 @@ Symbol span mismatch for "C4": after transform: SymbolId(3): Span { start: 122, end: 124 } rebuilt : SymbolId(1): Span { start: 136, end: 138 } Symbol redeclarations mismatch for "C4": -after transform: SymbolId(3): [Span { start: 136, end: 138 }] +after transform: SymbolId(3): [Span { start: 122, end: 124 }, Span { start: 136, end: 138 }] rebuilt : SymbolId(1): [] tasks/coverage/typescript/tests/cases/conformance/classes/classDeclarations/mergedInheritedClassInterface.ts @@ -29882,7 +29882,7 @@ Symbol reference IDs mismatch for "Child": after transform: SymbolId(2): [ReferenceId(4)] rebuilt : SymbolId(2): [] Symbol redeclarations mismatch for "Child": -after transform: SymbolId(2): [Span { start: 213, end: 218 }] +after transform: SymbolId(2): [Span { start: 150, end: 155 }, Span { start: 213, end: 218 }] rebuilt : SymbolId(2): [] Symbol flags mismatch for "ChildNoBaseClass": after transform: SymbolId(3): SymbolFlags(Class | Interface) @@ -29891,7 +29891,7 @@ Symbol span mismatch for "ChildNoBaseClass": after transform: SymbolId(3): Span { start: 294, end: 310 } rebuilt : SymbolId(4): Span { start: 368, end: 384 } Symbol redeclarations mismatch for "ChildNoBaseClass": -after transform: SymbolId(3): [Span { start: 368, end: 384 }] +after transform: SymbolId(3): [Span { start: 294, end: 310 }, Span { start: 368, end: 384 }] rebuilt : SymbolId(4): [] Symbol reference IDs mismatch for "Grandchild": after transform: SymbolId(4): [ReferenceId(12)] @@ -30239,7 +30239,7 @@ Symbol flags mismatch for "C": after transform: SymbolId(1): SymbolFlags(Class | Interface) rebuilt : SymbolId(3): SymbolFlags(Class) Symbol redeclarations mismatch for "C": -after transform: SymbolId(1): [Span { start: 185, end: 186 }] +after transform: SymbolId(1): [Span { start: 37, end: 38 }, Span { start: 185, end: 186 }] rebuilt : SymbolId(3): [] tasks/coverage/typescript/tests/cases/conformance/classes/members/privateNames/privateNameFieldDestructuredBinding.ts @@ -30335,7 +30335,7 @@ Symbol reference IDs mismatch for "Mixin": after transform: SymbolId(0): [ReferenceId(2), ReferenceId(4), ReferenceId(6), ReferenceId(11)] rebuilt : SymbolId(0): [ReferenceId(2), ReferenceId(7)] Symbol redeclarations mismatch for "Mixin": -after transform: SymbolId(0): [Span { start: 55, end: 60 }] +after transform: SymbolId(0): [Span { start: 10, end: 15 }, Span { start: 55, end: 60 }] rebuilt : SymbolId(0): [] tasks/coverage/typescript/tests/cases/conformance/classes/mixinAbstractClassesReturnTypeInference.ts @@ -30366,7 +30366,7 @@ Symbol reference IDs mismatch for "Printable": after transform: SymbolId(9): [ReferenceId(8), ReferenceId(22)] rebuilt : SymbolId(8): [ReferenceId(19)] Symbol redeclarations mismatch for "Printable": -after transform: SymbolId(9): [Span { start: 287, end: 296 }] +after transform: SymbolId(9): [Span { start: 247, end: 256 }, Span { start: 287, end: 296 }] rebuilt : SymbolId(8): [] Symbol flags mismatch for "Tagged": after transform: SymbolId(13): SymbolFlags(Function | Interface) @@ -30378,7 +30378,7 @@ Symbol reference IDs mismatch for "Tagged": after transform: SymbolId(13): [ReferenceId(14), ReferenceId(19), ReferenceId(21)] rebuilt : SymbolId(12): [ReferenceId(16), ReferenceId(18)] Symbol redeclarations mismatch for "Tagged": -after transform: SymbolId(13): [Span { start: 596, end: 602 }] +after transform: SymbolId(13): [Span { start: 557, end: 563 }, Span { start: 596, end: 602 }] rebuilt : SymbolId(12): [] tasks/coverage/typescript/tests/cases/conformance/classes/mixinClassesAnonymous.ts @@ -30486,7 +30486,7 @@ Symbol span mismatch for "B": after transform: SymbolId(1): Span { start: 40, end: 41 } rebuilt : SymbolId(0): Span { start: 62, end: 63 } Symbol redeclarations mismatch for "B": -after transform: SymbolId(1): [Span { start: 62, end: 63 }] +after transform: SymbolId(1): [Span { start: 40, end: 41 }, Span { start: 62, end: 63 }] rebuilt : SymbolId(0): [] tasks/coverage/typescript/tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty8.ts @@ -30520,7 +30520,7 @@ Symbol reference IDs mismatch for "ApiItemContainerMixin": after transform: SymbolId(8): [ReferenceId(17), ReferenceId(19), ReferenceId(24)] rebuilt : SymbolId(2): [ReferenceId(4)] Symbol redeclarations mismatch for "ApiItemContainerMixin": -after transform: SymbolId(8): [Span { start: 558, end: 579 }] +after transform: SymbolId(8): [Span { start: 462, end: 483 }, Span { start: 558, end: 579 }] rebuilt : SymbolId(2): [] Unresolved references mismatch: after transform: ["ReadonlyArray"] @@ -32050,7 +32050,7 @@ Symbol flags mismatch for "Animals": after transform: SymbolId(0): SymbolFlags(RegularEnum) rebuilt : SymbolId(0): SymbolFlags(BlockScopedVariable) Symbol redeclarations mismatch for "Animals": -after transform: SymbolId(0): [Span { start: 45, end: 52 }, Span { start: 78, end: 85 }] +after transform: SymbolId(0): [Span { start: 12, end: 19 }, Span { start: 45, end: 52 }, Span { start: 78, end: 85 }] rebuilt : SymbolId(0): [] Unresolved references mismatch: after transform: ["Cat", "Dog"] @@ -32175,13 +32175,13 @@ Symbol flags mismatch for "EImpl1": after transform: SymbolId(1): SymbolFlags(RegularEnum) rebuilt : SymbolId(2): SymbolFlags(BlockScopedVariable) Symbol redeclarations mismatch for "EImpl1": -after transform: SymbolId(1): [Span { start: 238, end: 244 }] +after transform: SymbolId(1): [Span { start: 197, end: 203 }, Span { start: 238, end: 244 }] rebuilt : SymbolId(2): [] Symbol flags mismatch for "EConst1": after transform: SymbolId(8): SymbolFlags(RegularEnum) rebuilt : SymbolId(5): SymbolFlags(BlockScopedVariable) Symbol redeclarations mismatch for "EConst1": -after transform: SymbolId(8): [Span { start: 351, end: 358 }] +after transform: SymbolId(8): [Span { start: 290, end: 297 }, Span { start: 351, end: 358 }] rebuilt : SymbolId(5): [] Symbol flags mismatch for "M2": after transform: SymbolId(16): SymbolFlags(NameSpaceModule | ValueModule) @@ -32193,7 +32193,7 @@ Symbol flags mismatch for "EComp2": after transform: SymbolId(17): SymbolFlags(RegularEnum) rebuilt : SymbolId(11): SymbolFlags(BlockScopedVariable) Symbol redeclarations mismatch for "EComp2": -after transform: SymbolId(17): [Span { start: 684, end: 690 }] +after transform: SymbolId(17): [Span { start: 591, end: 597 }, Span { start: 684, end: 690 }] rebuilt : SymbolId(11): [] Symbol flags mismatch for "M3": after transform: SymbolId(25): SymbolFlags(NameSpaceModule | ValueModule) @@ -32205,7 +32205,7 @@ Symbol flags mismatch for "EInit": after transform: SymbolId(26): SymbolFlags(RegularEnum) rebuilt : SymbolId(17): SymbolFlags(BlockScopedVariable) Symbol redeclarations mismatch for "EInit": -after transform: SymbolId(26): [Span { start: 1009, end: 1014 }] +after transform: SymbolId(26): [Span { start: 964, end: 969 }, Span { start: 1009, end: 1014 }] rebuilt : SymbolId(17): [] Symbol flags mismatch for "M4": after transform: SymbolId(32): SymbolFlags(NameSpaceModule | ValueModule) @@ -32229,7 +32229,7 @@ Symbol span mismatch for "M6": after transform: SymbolId(42): Span { start: 1218, end: 1220 } rebuilt : SymbolId(27): Span { start: 0, end: 0 } Symbol redeclarations mismatch for "M6": -after transform: SymbolId(42): [Span { start: 1277, end: 1279 }] +after transform: SymbolId(42): [Span { start: 1218, end: 1220 }, Span { start: 1277, end: 1279 }] rebuilt : SymbolId(27): [] Symbol flags mismatch for "A": after transform: SymbolId(43): SymbolFlags(NameSpaceModule | ValueModule) @@ -33866,7 +33866,7 @@ Symbol flags mismatch for "Example": after transform: SymbolId(1): SymbolFlags(Class | NameSpaceModule | ValueModule) rebuilt : SymbolId(0): SymbolFlags(Class) Symbol redeclarations mismatch for "Example": -after transform: SymbolId(1): [Span { start: 93, end: 100 }] +after transform: SymbolId(1): [Span { start: 43, end: 50 }, Span { start: 93, end: 100 }] rebuilt : SymbolId(0): [] Reference symbol mismatch for "deco": after transform: SymbolId(0) "deco" @@ -35872,7 +35872,7 @@ Symbol reference IDs mismatch for "nestedCtor": after transform: SymbolId(9): [ReferenceId(1), ReferenceId(2), ReferenceId(15)] rebuilt : SymbolId(8): [ReferenceId(8)] Symbol redeclarations mismatch for "nestedCtor": -after transform: SymbolId(9): [Span { start: 240, end: 262 }] +after transform: SymbolId(9): [Span { start: 197, end: 207 }, Span { start: 240, end: 262 }] rebuilt : SymbolId(8): [] tasks/coverage/typescript/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator10.ts @@ -37733,19 +37733,19 @@ Symbol flags mismatch for "C": after transform: SymbolId(0): SymbolFlags(Class | NameSpaceModule | ValueModule) rebuilt : SymbolId(0): SymbolFlags(Class) Symbol redeclarations mismatch for "C": -after transform: SymbolId(0): [Span { start: 37, end: 38 }] +after transform: SymbolId(0): [Span { start: 13, end: 14 }, Span { start: 37, end: 38 }] rebuilt : SymbolId(0): [] Symbol flags mismatch for "E": after transform: SymbolId(2): SymbolFlags(RegularEnum | NameSpaceModule | ValueModule) rebuilt : SymbolId(3): SymbolFlags(BlockScopedVariable) Symbol redeclarations mismatch for "E": -after transform: SymbolId(2): [Span { start: 109, end: 110 }, Span { start: 143, end: 144 }, Span { start: 191, end: 192 }] +after transform: SymbolId(2): [Span { start: 80, end: 81 }, Span { start: 109, end: 110 }, Span { start: 143, end: 144 }, Span { start: 191, end: 192 }] rebuilt : SymbolId(3): [] Symbol flags mismatch for "F": after transform: SymbolId(9): SymbolFlags(Function | NameSpaceModule | ValueModule) rebuilt : SymbolId(12): SymbolFlags(Function) Symbol redeclarations mismatch for "F": -after transform: SymbolId(9): [Span { start: 336, end: 337 }] +after transform: SymbolId(9): [Span { start: 310, end: 311 }, Span { start: 336, end: 337 }] rebuilt : SymbolId(12): [] Reference symbol mismatch for "N": after transform: SymbolId(7) "N" @@ -37829,19 +37829,19 @@ Symbol flags mismatch for "C": after transform: SymbolId(0): SymbolFlags(Class | NameSpaceModule | ValueModule) rebuilt : SymbolId(0): SymbolFlags(Class) Symbol redeclarations mismatch for "C": -after transform: SymbolId(0): [Span { start: 37, end: 38 }] +after transform: SymbolId(0): [Span { start: 13, end: 14 }, Span { start: 37, end: 38 }] rebuilt : SymbolId(0): [] Symbol flags mismatch for "E": after transform: SymbolId(2): SymbolFlags(RegularEnum | NameSpaceModule | ValueModule) rebuilt : SymbolId(3): SymbolFlags(BlockScopedVariable) Symbol redeclarations mismatch for "E": -after transform: SymbolId(2): [Span { start: 109, end: 110 }, Span { start: 143, end: 144 }, Span { start: 191, end: 192 }] +after transform: SymbolId(2): [Span { start: 80, end: 81 }, Span { start: 109, end: 110 }, Span { start: 143, end: 144 }, Span { start: 191, end: 192 }] rebuilt : SymbolId(3): [] Symbol flags mismatch for "F": after transform: SymbolId(9): SymbolFlags(Function | NameSpaceModule | ValueModule) rebuilt : SymbolId(12): SymbolFlags(Function) Symbol redeclarations mismatch for "F": -after transform: SymbolId(9): [Span { start: 336, end: 337 }] +after transform: SymbolId(9): [Span { start: 310, end: 311 }, Span { start: 336, end: 337 }] rebuilt : SymbolId(12): [] Reference symbol mismatch for "N": after transform: SymbolId(7) "N" @@ -38118,7 +38118,7 @@ Symbol span mismatch for "A": after transform: SymbolId(0): Span { start: 12, end: 13 } rebuilt : SymbolId(0): Span { start: 33, end: 34 } Symbol redeclarations mismatch for "A": -after transform: SymbolId(0): [Span { start: 33, end: 34 }] +after transform: SymbolId(0): [Span { start: 12, end: 13 }, Span { start: 33, end: 34 }] rebuilt : SymbolId(0): [] Symbol flags mismatch for "B": after transform: SymbolId(1): SymbolFlags(FunctionScopedVariable | TypeAlias) @@ -38127,7 +38127,7 @@ Symbol span mismatch for "B": after transform: SymbolId(1): Span { start: 67, end: 68 } rebuilt : SymbolId(1): Span { start: 83, end: 84 } Symbol redeclarations mismatch for "B": -after transform: SymbolId(1): [Span { start: 83, end: 84 }] +after transform: SymbolId(1): [Span { start: 67, end: 68 }, Span { start: 83, end: 84 }] rebuilt : SymbolId(1): [] tasks/coverage/typescript/tests/cases/conformance/externalModules/umd-augmentation-1.ts @@ -38263,7 +38263,7 @@ Symbol reference IDs mismatch for "Directive": after transform: SymbolId(10): [ReferenceId(14), ReferenceId(16), ReferenceId(18), ReferenceId(51), ReferenceId(54), ReferenceId(64), ReferenceId(93), ReferenceId(94), ReferenceId(108)] rebuilt : SymbolId(3): [ReferenceId(13), ReferenceId(15), ReferenceId(19), ReferenceId(20)] Symbol redeclarations mismatch for "Directive": -after transform: SymbolId(10): [Span { start: 381, end: 390 }] +after transform: SymbolId(10): [Span { start: 318, end: 327 }, Span { start: 381, end: 390 }] rebuilt : SymbolId(3): [] Symbol flags mismatch for "StepResult": after transform: SymbolId(26): SymbolFlags(TypeAlias | NameSpaceModule | ValueModule) @@ -38275,7 +38275,7 @@ Symbol reference IDs mismatch for "StepResult": after transform: SymbolId(26): [ReferenceId(25), ReferenceId(29), ReferenceId(36), ReferenceId(41), ReferenceId(46), ReferenceId(90), ReferenceId(96), ReferenceId(97)] rebuilt : SymbolId(8): [ReferenceId(23), ReferenceId(24), ReferenceId(33)] Symbol redeclarations mismatch for "StepResult": -after transform: SymbolId(26): [Span { start: 1321, end: 1331 }] +after transform: SymbolId(26): [Span { start: 1257, end: 1267 }, Span { start: 1321, end: 1331 }] rebuilt : SymbolId(8): [] Symbol reference IDs mismatch for "step": after transform: SymbolId(51): [ReferenceId(83), ReferenceId(84), ReferenceId(86)] @@ -38412,7 +38412,7 @@ Symbol span mismatch for "M2": after transform: SymbolId(0): Span { start: 113, end: 115 } rebuilt : SymbolId(0): Span { start: 0, end: 0 } Symbol redeclarations mismatch for "M2": -after transform: SymbolId(0): [Span { start: 235, end: 237 }, Span { start: 518, end: 520 }, Span { start: 693, end: 695 }, Span { start: 892, end: 894 }] +after transform: SymbolId(0): [Span { start: 113, end: 115 }, Span { start: 235, end: 237 }, Span { start: 518, end: 520 }, Span { start: 693, end: 695 }, Span { start: 892, end: 894 }] rebuilt : SymbolId(0): [] Symbol flags mismatch for "M3": after transform: SymbolId(10): SymbolFlags(NameSpaceModule | ValueModule) @@ -38488,7 +38488,7 @@ Symbol span mismatch for "M2": after transform: SymbolId(0): Span { start: 113, end: 115 } rebuilt : SymbolId(0): Span { start: 0, end: 0 } Symbol redeclarations mismatch for "M2": -after transform: SymbolId(0): [Span { start: 234, end: 236 }, Span { start: 412, end: 414 }, Span { start: 586, end: 588 }] +after transform: SymbolId(0): [Span { start: 113, end: 115 }, Span { start: 234, end: 236 }, Span { start: 412, end: 414 }, Span { start: 586, end: 588 }] rebuilt : SymbolId(0): [] Symbol flags mismatch for "M3": after transform: SymbolId(9): SymbolFlags(NameSpaceModule | ValueModule) @@ -38740,7 +38740,7 @@ Symbol reference IDs mismatch for "Point": after transform: SymbolId(0): [ReferenceId(0), ReferenceId(2), ReferenceId(3)] rebuilt : SymbolId(0): [ReferenceId(2), ReferenceId(3)] Symbol redeclarations mismatch for "Point": -after transform: SymbolId(0): [Span { start: 135, end: 140 }] +after transform: SymbolId(0): [Span { start: 6, end: 11 }, Span { start: 135, end: 140 }] rebuilt : SymbolId(0): [] Symbol flags mismatch for "A": after transform: SymbolId(4): SymbolFlags(NameSpaceModule | ValueModule) @@ -38755,7 +38755,7 @@ Symbol reference IDs mismatch for "Point": after transform: SymbolId(5): [ReferenceId(1), ReferenceId(5), ReferenceId(6), ReferenceId(8)] rebuilt : SymbolId(7): [ReferenceId(7), ReferenceId(8), ReferenceId(9)] Symbol redeclarations mismatch for "Point": -after transform: SymbolId(5): [Span { start: 399, end: 404 }] +after transform: SymbolId(5): [Span { start: 247, end: 252 }, Span { start: 399, end: 404 }] rebuilt : SymbolId(7): [] tasks/coverage/typescript/tests/cases/conformance/internalModules/DeclarationMerging/ClassAndModuleThatMergeWithStaticVariableAndNonExportedVarThatShareAName.ts @@ -38775,7 +38775,7 @@ Symbol reference IDs mismatch for "Point": after transform: SymbolId(0): [ReferenceId(0), ReferenceId(2), ReferenceId(3), ReferenceId(14)] rebuilt : SymbolId(1): [ReferenceId(4), ReferenceId(5), ReferenceId(6)] Symbol redeclarations mismatch for "Point": -after transform: SymbolId(0): [Span { start: 124, end: 129 }] +after transform: SymbolId(0): [Span { start: 6, end: 11 }, Span { start: 124, end: 129 }] rebuilt : SymbolId(1): [] Symbol flags mismatch for "A": after transform: SymbolId(4): SymbolFlags(NameSpaceModule | ValueModule) @@ -38790,7 +38790,7 @@ Symbol reference IDs mismatch for "Point": after transform: SymbolId(5): [ReferenceId(1), ReferenceId(5), ReferenceId(6), ReferenceId(8), ReferenceId(18)] rebuilt : SymbolId(8): [ReferenceId(10), ReferenceId(12), ReferenceId(13), ReferenceId(14)] Symbol redeclarations mismatch for "Point": -after transform: SymbolId(5): [Span { start: 362, end: 367 }] +after transform: SymbolId(5): [Span { start: 221, end: 226 }, Span { start: 362, end: 367 }] rebuilt : SymbolId(8): [] tasks/coverage/typescript/tests/cases/conformance/internalModules/DeclarationMerging/EnumAndModuleWithSameNameAndCommonRoot.ts @@ -38810,7 +38810,7 @@ Symbol reference IDs mismatch for "enumdule": after transform: SymbolId(0): [ReferenceId(0), ReferenceId(1), ReferenceId(2), ReferenceId(5), ReferenceId(6), ReferenceId(12)] rebuilt : SymbolId(0): [ReferenceId(5), ReferenceId(10), ReferenceId(11), ReferenceId(12), ReferenceId(13)] Symbol redeclarations mismatch for "enumdule": -after transform: SymbolId(0): [Span { start: 40, end: 48 }] +after transform: SymbolId(0): [Span { start: 5, end: 13 }, Span { start: 40, end: 48 }] rebuilt : SymbolId(0): [] tasks/coverage/typescript/tests/cases/conformance/internalModules/DeclarationMerging/FunctionAndModuleWithSameNameAndDifferentCommonRoot.ts @@ -38833,16 +38833,16 @@ after transform: ScopeId(4): ScopeFlags(0x0) rebuilt : ScopeId(4): ScopeFlags(Function) Symbol flags mismatch for "enumdule": after transform: SymbolId(0): SymbolFlags(RegularEnum | NameSpaceModule | ValueModule) -rebuilt : SymbolId(4): SymbolFlags(FunctionScopedVariable) +rebuilt : SymbolId(0): SymbolFlags(FunctionScopedVariable | BlockScopedVariable) Symbol span mismatch for "enumdule": after transform: SymbolId(0): Span { start: 7, end: 15 } -rebuilt : SymbolId(4): Span { start: 118, end: 126 } +rebuilt : SymbolId(0): Span { start: 0, end: 0 } Symbol reference IDs mismatch for "enumdule": after transform: SymbolId(0): [ReferenceId(0), ReferenceId(1), ReferenceId(2), ReferenceId(5), ReferenceId(6), ReferenceId(14)] -rebuilt : SymbolId(4): [ReferenceId(4), ReferenceId(5), ReferenceId(11), ReferenceId(12), ReferenceId(13)] +rebuilt : SymbolId(0): [ReferenceId(4), ReferenceId(5), ReferenceId(11), ReferenceId(12), ReferenceId(13)] Symbol redeclarations mismatch for "enumdule": -after transform: SymbolId(0): [Span { start: 118, end: 126 }] -rebuilt : SymbolId(4): [] +after transform: SymbolId(0): [Span { start: 7, end: 15 }, Span { start: 118, end: 126 }] +rebuilt : SymbolId(0): [Span { start: 0, end: 0 }, Span { start: 118, end: 126 }] tasks/coverage/typescript/tests/cases/conformance/internalModules/DeclarationMerging/TwoInternalModulesThatMergeEachWithExportedAndNonExportedClassesOfTheSameName.ts semantic error: Scope flags mismatch: @@ -38876,7 +38876,7 @@ Symbol span mismatch for "A": after transform: SymbolId(0): Span { start: 7, end: 8 } rebuilt : SymbolId(1): Span { start: 0, end: 0 } Symbol redeclarations mismatch for "A": -after transform: SymbolId(0): [Span { start: 90, end: 91 }] +after transform: SymbolId(0): [Span { start: 7, end: 8 }, Span { start: 90, end: 91 }] rebuilt : SymbolId(1): [] Symbol flags mismatch for "X": after transform: SymbolId(5): SymbolFlags(NameSpaceModule | ValueModule) @@ -38885,7 +38885,7 @@ Symbol span mismatch for "X": after transform: SymbolId(5): Span { start: 294, end: 295 } rebuilt : SymbolId(8): Span { start: 0, end: 0 } Symbol redeclarations mismatch for "X": -after transform: SymbolId(5): [Span { start: 366, end: 367 }] +after transform: SymbolId(5): [Span { start: 294, end: 295 }, Span { start: 366, end: 367 }] rebuilt : SymbolId(8): [] Symbol flags mismatch for "Y": after transform: SymbolId(6): SymbolFlags(NameSpaceModule | ValueModule) @@ -39160,7 +39160,7 @@ Symbol reference IDs mismatch for "clodule": after transform: SymbolId(6): [ReferenceId(4), ReferenceId(6), ReferenceId(15), ReferenceId(16)] rebuilt : SymbolId(7): [ReferenceId(8), ReferenceId(9)] Symbol redeclarations mismatch for "clodule": -after transform: SymbolId(6): [Span { start: 257, end: 264 }] +after transform: SymbolId(6): [Span { start: 219, end: 226 }, Span { start: 257, end: 264 }] rebuilt : SymbolId(7): [] Symbol flags mismatch for "Point": after transform: SymbolId(7): SymbolFlags(FunctionScopedVariable | Interface) @@ -39172,7 +39172,7 @@ Symbol reference IDs mismatch for "Point": after transform: SymbolId(7): [ReferenceId(3)] rebuilt : SymbolId(9): [] Symbol redeclarations mismatch for "Point": -after transform: SymbolId(7): [Span { start: 340, end: 352 }] +after transform: SymbolId(7): [Span { start: 288, end: 293 }, Span { start: 340, end: 352 }] rebuilt : SymbolId(9): [] Symbol flags mismatch for "fundule": after transform: SymbolId(9): SymbolFlags(Function | NameSpaceModule | ValueModule) @@ -39181,7 +39181,7 @@ Symbol reference IDs mismatch for "fundule": after transform: SymbolId(9): [ReferenceId(8), ReferenceId(17), ReferenceId(18)] rebuilt : SymbolId(10): [ReferenceId(10), ReferenceId(11)] Symbol redeclarations mismatch for "fundule": -after transform: SymbolId(9): [Span { start: 539, end: 546 }] +after transform: SymbolId(9): [Span { start: 490, end: 497 }, Span { start: 539, end: 546 }] rebuilt : SymbolId(10): [] Symbol flags mismatch for "Point": after transform: SymbolId(10): SymbolFlags(FunctionScopedVariable | Interface) @@ -39193,7 +39193,7 @@ Symbol reference IDs mismatch for "Point": after transform: SymbolId(10): [ReferenceId(7)] rebuilt : SymbolId(12): [] Symbol redeclarations mismatch for "Point": -after transform: SymbolId(10): [Span { start: 622, end: 634 }] +after transform: SymbolId(10): [Span { start: 570, end: 575 }, Span { start: 622, end: 634 }] rebuilt : SymbolId(12): [] Unresolved references mismatch: after transform: ["fundule", "moduleA", "require"] @@ -39496,7 +39496,7 @@ Symbol span mismatch for "x": after transform: SymbolId(9): Span { start: 231, end: 236 } rebuilt : SymbolId(3): Span { start: 537, end: 538 } Symbol redeclarations mismatch for "x": -after transform: SymbolId(9): [Span { start: 537, end: 538 }] +after transform: SymbolId(9): [Span { start: 231, end: 236 }, Span { start: 537, end: 538 }] rebuilt : SymbolId(3): [] Reference symbol mismatch for "Component": after transform: SymbolId(1) "Component" @@ -42038,7 +42038,7 @@ Symbol reference IDs mismatch for "FAILURE": after transform: SymbolId(63): [ReferenceId(55), ReferenceId(58), ReferenceId(66), ReferenceId(68)] rebuilt : SymbolId(62): [ReferenceId(50), ReferenceId(54)] Symbol redeclarations mismatch for "FAILURE": -after transform: SymbolId(63): [Span { start: 2256, end: 2263 }] +after transform: SymbolId(63): [Span { start: 2229, end: 2236 }, Span { start: 2256, end: 2263 }] rebuilt : SymbolId(62): [] Symbol reference IDs mismatch for "langCodeSet": after transform: SymbolId(90): [ReferenceId(95), ReferenceId(97)] @@ -44550,7 +44550,7 @@ Symbol reference IDs mismatch for "Derived": after transform: SymbolId(15): [ReferenceId(4), ReferenceId(30), ReferenceId(31), ReferenceId(48), ReferenceId(69), ReferenceId(70), ReferenceId(116), ReferenceId(117)] rebuilt : SymbolId(16): [ReferenceId(30), ReferenceId(31)] Symbol redeclarations mismatch for "Derived": -after transform: SymbolId(15): [Span { start: 842, end: 849 }] +after transform: SymbolId(15): [Span { start: 689, end: 696 }, Span { start: 842, end: 849 }] rebuilt : SymbolId(16): [] Symbol reference IDs mismatch for "Derived2": after transform: SymbolId(16): [ReferenceId(5)] @@ -46205,7 +46205,7 @@ Symbol reference IDs mismatch for "fn": after transform: SymbolId(81): [ReferenceId(118)] rebuilt : SymbolId(32): [] Symbol redeclarations mismatch for "fn": -after transform: SymbolId(81): [Span { start: 1621, end: 1627 }] +after transform: SymbolId(81): [Span { start: 1594, end: 1596 }, Span { start: 1621, end: 1627 }] rebuilt : SymbolId(32): [] tasks/coverage/typescript/tests/cases/conformance/types/typeRelationships/typeInference/genericContextualTypes2.ts diff --git a/tasks/transform_conformance/snapshots/babel.snap.md b/tasks/transform_conformance/snapshots/babel.snap.md index 3a9625a691378..bc22d6ef5dcbe 100644 --- a/tasks/transform_conformance/snapshots/babel.snap.md +++ b/tasks/transform_conformance/snapshots/babel.snap.md @@ -1016,8 +1016,8 @@ Symbol scope ID mismatch for "a": after transform: SymbolId(0): ScopeId(2) rebuilt : SymbolId(8): ScopeId(0) Symbol redeclarations mismatch for "a": -after transform: SymbolId(0): [Span { start: 86, end: 87 }, Span { start: 189, end: 190 }, Span { start: 274, end: 275 }] -rebuilt : SymbolId(8): [Span { start: 189, end: 190 }, Span { start: 274, end: 275 }] +after transform: SymbolId(0): [Span { start: 27, end: 28 }, Span { start: 86, end: 87 }, Span { start: 189, end: 190 }, Span { start: 274, end: 275 }] +rebuilt : SymbolId(8): [Span { start: 86, end: 87 }, Span { start: 189, end: 190 }, Span { start: 274, end: 275 }] Symbol reference IDs mismatch for "b": after transform: SymbolId(1): [ReferenceId(1), ReferenceId(3)] rebuilt : SymbolId(5): [] @@ -1486,7 +1486,7 @@ Symbol flags mismatch for "Animals": after transform: SymbolId(0): SymbolFlags(RegularEnum) rebuilt : SymbolId(0): SymbolFlags(FunctionScopedVariable) Symbol redeclarations mismatch for "Animals": -after transform: SymbolId(0): [Span { start: 41, end: 48 }] +after transform: SymbolId(0): [Span { start: 5, end: 12 }, Span { start: 41, end: 48 }] rebuilt : SymbolId(0): [] Unresolved references mismatch: after transform: ["Cat", "Dog"] @@ -1521,7 +1521,7 @@ Symbol flags mismatch for "Animals": after transform: SymbolId(2): SymbolFlags(RegularEnum) rebuilt : SymbolId(2): SymbolFlags(FunctionScopedVariable) Symbol redeclarations mismatch for "Animals": -after transform: SymbolId(2): [Span { start: 65, end: 72 }, Span { start: 92, end: 99 }] +after transform: SymbolId(2): [Span { start: 38, end: 45 }, Span { start: 65, end: 72 }, Span { start: 92, end: 99 }] rebuilt : SymbolId(2): [] * enum/export/input.ts @@ -1541,7 +1541,7 @@ Symbol flags mismatch for "E": after transform: SymbolId(0): SymbolFlags(RegularEnum) rebuilt : SymbolId(0): SymbolFlags(BlockScopedVariable) Symbol redeclarations mismatch for "E": -after transform: SymbolId(0): [Span { start: 40, end: 41 }] +after transform: SymbolId(0): [Span { start: 12, end: 13 }, Span { start: 40, end: 41 }] rebuilt : SymbolId(0): [] * enum/inferred/input.ts @@ -1613,7 +1613,7 @@ Symbol flags mismatch for "E": after transform: SymbolId(0): SymbolFlags(RegularEnum) rebuilt : SymbolId(0): SymbolFlags(FunctionScopedVariable) Symbol redeclarations mismatch for "E": -after transform: SymbolId(0): [Span { start: 40, end: 41 }] +after transform: SymbolId(0): [Span { start: 5, end: 6 }, Span { start: 40, end: 41 }] rebuilt : SymbolId(0): [] * enum/outer-references/input.ts @@ -1697,7 +1697,7 @@ Symbol reference IDs mismatch for "N": after transform: SymbolId(0): [ReferenceId(0), ReferenceId(2)] rebuilt : SymbolId(0): [ReferenceId(1)] Symbol redeclarations mismatch for "N": -after transform: SymbolId(0): [Span { start: 83, end: 84 }] +after transform: SymbolId(0): [Span { start: 13, end: 14 }, Span { start: 83, end: 84 }] rebuilt : SymbolId(0): [] * exports/declare-shadowed/input.ts @@ -1885,7 +1885,7 @@ Symbol span mismatch for "Foo": after transform: SymbolId(0): Span { start: 13, end: 16 } rebuilt : SymbolId(0): Span { start: 70, end: 73 } Symbol redeclarations mismatch for "Foo": -after transform: SymbolId(0): [Span { start: 70, end: 73 }] +after transform: SymbolId(0): [Span { start: 13, end: 16 }, Span { start: 70, end: 73 }] rebuilt : SymbolId(0): [] Symbol flags mismatch for "Foo2": after transform: SymbolId(1): SymbolFlags(Function | TypeImport) @@ -1894,7 +1894,7 @@ Symbol span mismatch for "Foo2": after transform: SymbolId(1): Span { start: 43, end: 47 } rebuilt : SymbolId(1): Span { start: 87, end: 91 } Symbol redeclarations mismatch for "Foo2": -after transform: SymbolId(1): [Span { start: 87, end: 91 }] +after transform: SymbolId(1): [Span { start: 43, end: 47 }, Span { start: 87, end: 91 }] rebuilt : SymbolId(1): [] * imports/import-type-not-removed/input.ts @@ -1959,7 +1959,7 @@ Symbol flags mismatch for "A": after transform: SymbolId(0): SymbolFlags(Class | NameSpaceModule | ValueModule) rebuilt : SymbolId(0): SymbolFlags(Class) Symbol redeclarations mismatch for "A": -after transform: SymbolId(0): [Span { start: 22, end: 23 }] +after transform: SymbolId(0): [Span { start: 6, end: 7 }, Span { start: 22, end: 23 }] rebuilt : SymbolId(0): [] * namespace/clobber-enum/input.ts @@ -1973,7 +1973,7 @@ Symbol flags mismatch for "A": after transform: SymbolId(0): SymbolFlags(RegularEnum | NameSpaceModule | ValueModule) rebuilt : SymbolId(0): SymbolFlags(FunctionScopedVariable) Symbol redeclarations mismatch for "A": -after transform: SymbolId(0): [Span { start: 30, end: 31 }] +after transform: SymbolId(0): [Span { start: 5, end: 6 }, Span { start: 30, end: 31 }] rebuilt : SymbolId(0): [] * namespace/clobber-export/input.ts @@ -1981,7 +1981,7 @@ Symbol flags mismatch for "N": after transform: SymbolId(0): SymbolFlags(Class | NameSpaceModule | ValueModule) rebuilt : SymbolId(0): SymbolFlags(Class) Symbol redeclarations mismatch for "N": -after transform: SymbolId(0): [Span { start: 35, end: 36 }] +after transform: SymbolId(0): [Span { start: 13, end: 14 }, Span { start: 35, end: 36 }] rebuilt : SymbolId(0): [] * namespace/contentious-names/input.ts @@ -2374,7 +2374,7 @@ Symbol span mismatch for "N": after transform: SymbolId(0): Span { start: 10, end: 11 } rebuilt : SymbolId(0): Span { start: 0, end: 0 } Symbol redeclarations mismatch for "N": -after transform: SymbolId(0): [Span { start: 33, end: 34 }] +after transform: SymbolId(0): [Span { start: 10, end: 11 }, Span { start: 33, end: 34 }] rebuilt : SymbolId(0): [] * namespace/mutable-fail/input.ts @@ -2417,7 +2417,7 @@ Symbol flags mismatch for "A": after transform: SymbolId(0): SymbolFlags(Class | NameSpaceModule | ValueModule) rebuilt : SymbolId(0): SymbolFlags(Class) Symbol redeclarations mismatch for "A": -after transform: SymbolId(0): [Span { start: 22, end: 23 }] +after transform: SymbolId(0): [Span { start: 6, end: 7 }, Span { start: 22, end: 23 }] rebuilt : SymbolId(0): [] Symbol flags mismatch for "C": after transform: SymbolId(1): SymbolFlags(NameSpaceModule | ValueModule) @@ -2429,13 +2429,13 @@ Symbol flags mismatch for "M": after transform: SymbolId(4): SymbolFlags(Function | NameSpaceModule | ValueModule) rebuilt : SymbolId(6): SymbolFlags(Function) Symbol redeclarations mismatch for "M": -after transform: SymbolId(4): [Span { start: 129, end: 130 }] +after transform: SymbolId(4): [Span { start: 110, end: 111 }, Span { start: 129, end: 130 }] rebuilt : SymbolId(6): [] Symbol flags mismatch for "D": after transform: SymbolId(6): SymbolFlags(Function | NameSpaceModule | ValueModule) rebuilt : SymbolId(9): SymbolFlags(Function) Symbol redeclarations mismatch for "D": -after transform: SymbolId(6): [Span { start: 207, end: 208 }] +after transform: SymbolId(6): [Span { start: 181, end: 182 }, Span { start: 207, end: 208 }] rebuilt : SymbolId(9): [] Symbol flags mismatch for "H": after transform: SymbolId(8): SymbolFlags(RegularEnum) @@ -2444,7 +2444,7 @@ Symbol flags mismatch for "F": after transform: SymbolId(12): SymbolFlags(Class | NameSpaceModule | ValueModule) rebuilt : SymbolId(14): SymbolFlags(Class) Symbol redeclarations mismatch for "F": -after transform: SymbolId(12): [Span { start: 325, end: 326 }] +after transform: SymbolId(12): [Span { start: 308, end: 309 }, Span { start: 325, end: 326 }] rebuilt : SymbolId(14): [] Symbol flags mismatch for "G": after transform: SymbolId(14): SymbolFlags(NameSpaceModule | ValueModule) @@ -2540,7 +2540,7 @@ Symbol span mismatch for "N": after transform: SymbolId(3): Span { start: 59, end: 60 } rebuilt : SymbolId(5): Span { start: 0, end: 0 } Symbol redeclarations mismatch for "N": -after transform: SymbolId(3): [Span { start: 115, end: 116 }, Span { start: 166, end: 167 }] +after transform: SymbolId(3): [Span { start: 59, end: 60 }, Span { start: 115, end: 116 }, Span { start: 166, end: 167 }] rebuilt : SymbolId(5): [] Symbol flags mismatch for "_N": after transform: SymbolId(6): SymbolFlags(RegularEnum) diff --git a/tasks/transform_conformance/snapshots/oxc.snap.md b/tasks/transform_conformance/snapshots/oxc.snap.md index c3e400a25e771..d6e22d6a59a65 100644 --- a/tasks/transform_conformance/snapshots/oxc.snap.md +++ b/tasks/transform_conformance/snapshots/oxc.snap.md @@ -148,7 +148,7 @@ Symbol flags mismatch for "Merge": after transform: SymbolId(5): SymbolFlags(RegularEnum) rebuilt : SymbolId(3): SymbolFlags(FunctionScopedVariable) Symbol redeclarations mismatch for "Merge": -after transform: SymbolId(5): [Span { start: 103, end: 108 }] +after transform: SymbolId(5): [Span { start: 70, end: 75 }, Span { start: 103, end: 108 }] rebuilt : SymbolId(3): [] Symbol reference IDs mismatch for "Merge": after transform: SymbolId(16): [ReferenceId(20), ReferenceId(21), ReferenceId(22)] @@ -189,7 +189,7 @@ Symbol reference IDs mismatch for "T": after transform: SymbolId(9): [ReferenceId(8), ReferenceId(9)] rebuilt : SymbolId(8): [ReferenceId(9)] Symbol redeclarations mismatch for "T": -after transform: SymbolId(9): [Span { start: 226, end: 227 }] +after transform: SymbolId(9): [Span { start: 205, end: 206 }, Span { start: 226, end: 227 }] rebuilt : SymbolId(8): [] * exports/type-and-non-type/input.ts @@ -279,13 +279,13 @@ Symbol reference IDs mismatch for "A": after transform: SymbolId(0): [ReferenceId(0), ReferenceId(1)] rebuilt : SymbolId(0): [ReferenceId(0)] Symbol redeclarations mismatch for "A": -after transform: SymbolId(0): [Span { start: 79, end: 83 }] +after transform: SymbolId(0): [Span { start: 57, end: 58 }, Span { start: 79, end: 83 }] rebuilt : SymbolId(0): [] Symbol flags mismatch for "T": after transform: SymbolId(1): SymbolFlags(Import | TypeAlias) rebuilt : SymbolId(1): SymbolFlags(Import) Symbol redeclarations mismatch for "T": -after transform: SymbolId(1): [Span { start: 170, end: 171 }] +after transform: SymbolId(1): [Span { start: 149, end: 150 }, Span { start: 170, end: 171 }] rebuilt : SymbolId(1): [] Symbol flags mismatch for "B": after transform: SymbolId(2): SymbolFlags(BlockScopedVariable | ConstVariable | Import | TypeAlias) @@ -297,7 +297,7 @@ Symbol reference IDs mismatch for "B": after transform: SymbolId(2): [ReferenceId(3), ReferenceId(4)] rebuilt : SymbolId(2): [ReferenceId(2)] Symbol redeclarations mismatch for "B": -after transform: SymbolId(2): [Span { start: 289, end: 293 }, Span { start: 304, end: 305 }] +after transform: SymbolId(2): [Span { start: 267, end: 268 }, Span { start: 289, end: 293 }, Span { start: 304, end: 305 }] rebuilt : SymbolId(2): [] * ts-declaration-empty-output/input.d.ts From 6687f5b5fa633648b6360a809acc0ffcfc0856ce Mon Sep 17 00:00:00 2001 From: Dunqing <29533304+Dunqing@users.noreply.github.com> Date: Fri, 28 Mar 2025 04:12:21 +0000 Subject: [PATCH 07/15] fix(semantic): define a variable in a function expression whose name is the same as the function name which is considered a redeclaration (#10077) ```js (function n(n) {})() ``` The function `n` symbol will insert into the function itself scope, which causes param `n` to be considered a redeclaration, but it is not. --- crates/oxc_semantic/src/builder.rs | 23 +++++++++++++++---- .../oxc_semantic/tests/integration/symbols.rs | 9 ++++++++ .../tests/integration/util/symbol_tester.rs | 23 +++++++++++++++++-- 3 files changed, 48 insertions(+), 7 deletions(-) diff --git a/crates/oxc_semantic/src/builder.rs b/crates/oxc_semantic/src/builder.rs index a0174ff1f7e42..e4f00a2c4d18f 100644 --- a/crates/oxc_semantic/src/builder.rs +++ b/crates/oxc_semantic/src/builder.rs @@ -425,6 +425,23 @@ impl<'a> SemanticBuilder<'a> { let symbol_id = self.scoping.get_binding(scope_id, name).or_else(|| { self.hoisting_variables.get(&scope_id).and_then(|symbols| symbols.get(name).copied()) })?; + + // `(function n(n) {})()` + // ^ is not a redeclaration + // Since we put the function expression binding 'n' Symbol into the function itself scope, + // then defining a variable with the same name as the function name will be considered + // a redeclaration, but it's actually not a redeclaration, so if the symbol declaration + // is a function expression, then return None to tell the caller that it's not a redeclaration. + if self.scoping.symbol_flags(symbol_id).is_function() + && self + .nodes + .kind(self.scoping.symbol_declaration(symbol_id)) + .as_function() + .is_some_and(Function::is_expression) + { + return None; + } + if report_error { self.check_and_report_redeclaration(name, span, symbol_id, excludes); } @@ -447,11 +464,7 @@ impl<'a> SemanticBuilder<'a> { None }; - if ( - flags.intersects(excludes) - // `function n() { let n; }` - // ^ is not a redeclaration - && !function_kind.is_some_and(Function::is_expression)) + if flags.intersects(excludes) // Needs to further check if the previous declaration is a function and the function // is not allowed to be redeclared. // For example: `async function goo(); var goo;` diff --git a/crates/oxc_semantic/tests/integration/symbols.rs b/crates/oxc_semantic/tests/integration/symbols.rs index 9a17c87b3cd3e..41c09cbeb5fbf 100644 --- a/crates/oxc_semantic/tests/integration/symbols.rs +++ b/crates/oxc_semantic/tests/integration/symbols.rs @@ -451,3 +451,12 @@ fn test_class_merging() { .contains_flags(SymbolFlags::Interface) .test(); } + +#[test] +fn test_redeclaration() { + SemanticTester::js("(function n(n) { console.log (n) }) ()") + .has_symbol("n") // the first `n` is the function expression + .equal_flags(SymbolFlags::Function) // param `n` is a SymbolFlags::FunctionScopedVariable + .has_number_of_references(0) // no references to the function + .test(); +} diff --git a/crates/oxc_semantic/tests/integration/util/symbol_tester.rs b/crates/oxc_semantic/tests/integration/util/symbol_tester.rs index efd88f92475ba..f3efe642b3748 100644 --- a/crates/oxc_semantic/tests/integration/util/symbol_tester.rs +++ b/crates/oxc_semantic/tests/integration/util/symbol_tester.rs @@ -100,8 +100,8 @@ impl<'a> SymbolTester<'a> { ) -> Self { let symbols_with_target_name: Option = semantic .scoping() - .iter_bindings() - .find_map(|(_, bindings)| bindings.get(target).copied()); + .symbol_ids() + .find(|&symbol_id| semantic.scoping().symbol_name(symbol_id) == target); let data = match symbols_with_target_name { Some(symbol_id) => Ok(symbol_id), @@ -153,6 +153,25 @@ impl<'a> SymbolTester<'a> { self } + /// Checks if the resolved symbol has exactly the flags in `flags`, using [`SymbolFlags::eq()`] + pub fn equal_flags(mut self, flags: SymbolFlags) -> Self { + self.test_result = match self.test_result { + Ok(symbol_id) => { + let found_flags = self.semantic.scoping().symbol_flags(symbol_id); + if found_flags == flags { + Ok(symbol_id) + } else { + Err(OxcDiagnostic::error(format!( + "Expected {} to equal flags {:?}, but it is {:?}", + self.target_symbol_name, flags, found_flags + ))) + } + } + err => err, + }; + self + } + /// Check that this symbol has a certain number of read [`Reference`]s /// /// References that are both read and write are counted. From 95e69f68ef5fe6c79bfe5871148511dc9e92062a Mon Sep 17 00:00:00 2001 From: overlookmotel <557937+overlookmotel@users.noreply.github.com> Date: Fri, 28 Mar 2025 04:30:19 +0000 Subject: [PATCH 08/15] fix(ast/estree): fix `StringLiteral`s containing lone surrogates (#10036) Improve output for `StringLiteral`s containing lone surrogates. Most of the remaining failing tests are just due to difference in case e.g.: ```diff - "value": "\ud83d", + "value": "\uD83D", ``` But there are still a few genuine test fails. We don't have it exactly right yet. But this is a step in the right direction. --- crates/oxc_ast/src/ast/literal.rs | 1 + crates/oxc_ast/src/generated/derive_estree.rs | 2 +- crates/oxc_ast/src/serialize.rs | 69 +++++++++++++++++++ napi/parser/deserialize-js.js | 6 +- napi/parser/deserialize-ts.js | 6 +- tasks/coverage/snapshots/estree_test262.snap | 14 +--- .../coverage/snapshots/estree_typescript.snap | 4 +- 7 files changed, 82 insertions(+), 20 deletions(-) diff --git a/crates/oxc_ast/src/ast/literal.rs b/crates/oxc_ast/src/ast/literal.rs index fc4a695e1a6eb..11f7aaa24d225 100644 --- a/crates/oxc_ast/src/ast/literal.rs +++ b/crates/oxc_ast/src/ast/literal.rs @@ -76,6 +76,7 @@ pub struct StringLiteral<'a> { /// The value of the string. /// /// Any escape sequences in the raw code are unescaped. + #[estree(via = StringLiteralValue)] pub value: Atom<'a>, /// The raw string as it appears in source code. diff --git a/crates/oxc_ast/src/generated/derive_estree.rs b/crates/oxc_ast/src/generated/derive_estree.rs index e32dbf5e2925d..ca05218b648aa 100644 --- a/crates/oxc_ast/src/generated/derive_estree.rs +++ b/crates/oxc_ast/src/generated/derive_estree.rs @@ -1925,7 +1925,7 @@ impl ESTree for StringLiteral<'_> { state.serialize_field("type", &JsonSafeString("Literal")); state.serialize_field("start", &self.span.start); state.serialize_field("end", &self.span.end); - state.serialize_field("value", &self.value); + state.serialize_field("value", &crate::serialize::StringLiteralValue(self)); state.serialize_field("raw", &self.raw); state.end(); } diff --git a/crates/oxc_ast/src/serialize.rs b/crates/oxc_ast/src/serialize.rs index 8d24d429e786a..aad56b4df31a5 100644 --- a/crates/oxc_ast/src/serialize.rs +++ b/crates/oxc_ast/src/serialize.rs @@ -1,3 +1,5 @@ +use std::borrow::Cow; + use cow_utils::CowUtils; use oxc_ast_macros::ast_meta; @@ -225,6 +227,73 @@ impl ESTree for NullLiteralRaw<'_> { } } +/// Serializer for `value` field of `StringLiteral`. +/// +/// Handle when `lossy` flag is set, indicating the string contains lone surrogates. +#[ast_meta] +#[estree( + ts_type = "string", + raw_deser = " + const lossy = DESER[bool](POS_OFFSET.lossy); + (THIS.lossy && THIS.raw !== null) ? (0, eval)(THIS.raw) : DESER[Atom](POS_OFFSET.value) + " +)] +pub struct StringLiteralValue<'a, 'b>(pub &'b StringLiteral<'a>); + +impl ESTree for StringLiteralValue<'_, '_> { + fn serialize(&self, serializer: S) { + let lit = self.0; + #[expect(clippy::if_not_else)] + if !lit.lossy { + lit.value.serialize(serializer); + } else { + self.serialize_lossy(serializer); + } + } +} + +impl StringLiteralValue<'_, '_> { + #[cold] + #[inline(never)] + fn serialize_lossy(&self, serializer: S) { + // String contains lone surrogates + let lit = self.0; + let raw = + lit.raw.expect("`StringLiteral` with `lossy` flag set must have `raw` field populated"); + let raw = raw.as_str(); + let quote = raw.as_bytes().first().copied().unwrap(); + let raw_unquoted = &raw[1..raw.len() - 1]; + let raw_with_quotes_escaped = if quote == b'"' { + // String was in double quotes in original source, so it's valid JSON + Cow::Borrowed(raw_unquoted) + } else { + // String was in single quotes in original source. + // We need to replace any `"` characters with `\"`, and then it's valid JSON. + // We *don't* escape `"` characters preceded by an odd number of `\`s, + // because they're already escaped. + // We could make this more performant, but it should be vanishingly rare to hit this path anyway. + let mut encoded = Vec::with_capacity(raw_unquoted.len()); + let mut has_slash = false; + for &b in raw_unquoted.as_bytes() { + if b == b'\\' { + has_slash = !has_slash; + } else if b == b'"' && !has_slash { + encoded.push(b'\\'); + } else { + has_slash = false; + } + encoded.push(b); + } + + // SAFETY: `raw_without_quotes` is a `&str`. `encoded` contains the exact same bytes, + // except we may have inserted `\` before `"`s. That cannot create invalid UTF-8. + let encoded = unsafe { String::from_utf8_unchecked(encoded) }; + Cow::Owned(encoded) + }; + JsonSafeString(&raw_with_quotes_escaped).serialize(serializer); + } +} + /// Serializer for `bigint` field of `BigIntLiteral`. #[ast_meta] #[estree(ts_type = "string", raw_deser = "THIS.raw.slice(0, -1).replace(/_/g, '')")] diff --git a/napi/parser/deserialize-js.js b/napi/parser/deserialize-js.js index 955a6016d8c4d..5d619163be434 100644 --- a/napi/parser/deserialize-js.js +++ b/napi/parser/deserialize-js.js @@ -1061,12 +1061,14 @@ function deserializeNumericLiteral(pos) { } function deserializeStringLiteral(pos) { + const raw = deserializeOptionStr(pos + 24); + const lossy = deserializeBool(pos + 40); return { type: 'Literal', start: deserializeU32(pos), end: deserializeU32(pos + 4), - value: deserializeStr(pos + 8), - raw: deserializeOptionStr(pos + 24), + value: (lossy && raw !== null) ? (0, eval)(raw) : deserializeStr(pos + 8), + raw, }; } diff --git a/napi/parser/deserialize-ts.js b/napi/parser/deserialize-ts.js index 7b6458b209010..9a4cb15d20b7e 100644 --- a/napi/parser/deserialize-ts.js +++ b/napi/parser/deserialize-ts.js @@ -1126,12 +1126,14 @@ function deserializeNumericLiteral(pos) { } function deserializeStringLiteral(pos) { + const raw = deserializeOptionStr(pos + 24); + const lossy = deserializeBool(pos + 40); return { type: 'Literal', start: deserializeU32(pos), end: deserializeU32(pos + 4), - value: deserializeStr(pos + 8), - raw: deserializeOptionStr(pos + 24), + value: (lossy && raw !== null) ? (0, eval)(raw) : deserializeStr(pos + 8), + raw, }; } diff --git a/tasks/coverage/snapshots/estree_test262.snap b/tasks/coverage/snapshots/estree_test262.snap index 06dac390d2d80..31d5fe6c077d9 100644 --- a/tasks/coverage/snapshots/estree_test262.snap +++ b/tasks/coverage/snapshots/estree_test262.snap @@ -2,9 +2,7 @@ commit: bc5c1417 estree_test262 Summary: AST Parsed : 44047/44047 (100.00%) -Positive Passed: 44002/44047 (99.90%) -Mismatch: tasks/coverage/test262/test/annexB/built-ins/RegExp/prototype/compile/pattern-string-u.js -Mismatch: tasks/coverage/test262/test/annexB/built-ins/String/prototype/substr/surrogate-pairs.js +Positive Passed: 44014/44047 (99.93%) Mismatch: tasks/coverage/test262/test/built-ins/Array/prototype/concat/Array.prototype.concat_spreadable-string-wrapper.js Mismatch: tasks/coverage/test262/test/built-ins/JSON/stringify/value-string-escape-unicode.js Mismatch: tasks/coverage/test262/test/built-ins/RegExp/dotall/with-dotall-unicode.js @@ -12,10 +10,6 @@ Mismatch: tasks/coverage/test262/test/built-ins/RegExp/dotall/with-dotall.js Mismatch: tasks/coverage/test262/test/built-ins/RegExp/dotall/without-dotall-unicode.js Mismatch: tasks/coverage/test262/test/built-ins/RegExp/dotall/without-dotall.js Mismatch: tasks/coverage/test262/test/built-ins/RegExp/escape/escaped-surrogates.js -Mismatch: tasks/coverage/test262/test/built-ins/RegExp/named-groups/non-unicode-property-names-invalid.js -Mismatch: tasks/coverage/test262/test/built-ins/RegExp/named-groups/unicode-property-names-invalid.js -Mismatch: tasks/coverage/test262/test/built-ins/RegExp/prototype/Symbol.replace/coerce-unicode.js -Mismatch: tasks/coverage/test262/test/built-ins/RegExp/prototype/exec/u-captured-value.js Mismatch: tasks/coverage/test262/test/built-ins/RegExp/regexp-modifiers/add-dotAll.js Mismatch: tasks/coverage/test262/test/built-ins/RegExp/regexp-modifiers/changing-dotAll-flag-does-not-affect-dotAll-modifier.js Mismatch: tasks/coverage/test262/test/built-ins/RegExp/regexp-modifiers/nesting-add-dotAll-within-remove-dotAll.js @@ -31,9 +25,6 @@ Mismatch: tasks/coverage/test262/test/built-ins/String/prototype/padStart/normal Mismatch: tasks/coverage/test262/test/built-ins/String/prototype/toWellFormed/returns-well-formed-string.js Mismatch: tasks/coverage/test262/test/built-ins/StringIteratorPrototype/next/next-iteration-surrogate-pairs.js Mismatch: tasks/coverage/test262/test/intl402/NumberFormat/prototype/format/format-non-finite-numbers.js -Mismatch: tasks/coverage/test262/test/intl402/Segmenter/prototype/segment/containing/breakable-input.js -Mismatch: tasks/coverage/test262/test/intl402/Segmenter/prototype/segment/containing/unbreakable-input.js -Mismatch: tasks/coverage/test262/test/intl402/Segmenter/prototype/segment/containing/zero-index.js Mismatch: tasks/coverage/test262/test/language/expressions/assignment/fn-name-lhs-cover.js Mismatch: tasks/coverage/test262/test/language/expressions/assignment/target-cover-id.js Mismatch: tasks/coverage/test262/test/language/expressions/postfix-decrement/target-cover-id.js @@ -41,10 +32,7 @@ Mismatch: tasks/coverage/test262/test/language/expressions/postfix-increment/tar Mismatch: tasks/coverage/test262/test/language/expressions/prefix-decrement/target-cover-id.js Mismatch: tasks/coverage/test262/test/language/expressions/prefix-increment/target-cover-id.js Mismatch: tasks/coverage/test262/test/language/literals/regexp/named-groups/invalid-lone-surrogate-groupname.js -Mismatch: tasks/coverage/test262/test/language/literals/regexp/u-astral.js -Mismatch: tasks/coverage/test262/test/language/literals/regexp/u-surrogate-pairs-atom-char-class.js Mismatch: tasks/coverage/test262/test/language/literals/regexp/u-surrogate-pairs-atom-escape-decimal.js Mismatch: tasks/coverage/test262/test/language/statements/for-in/head-lhs-cover.js Mismatch: tasks/coverage/test262/test/language/statements/for-of/head-lhs-async-parens.js Mismatch: tasks/coverage/test262/test/language/statements/for-of/head-lhs-cover.js -Mismatch: tasks/coverage/test262/test/language/statements/for-of/string-astral-truncated.js diff --git a/tasks/coverage/snapshots/estree_typescript.snap b/tasks/coverage/snapshots/estree_typescript.snap index 05fa7a8ba15a7..a16ef821a956a 100644 --- a/tasks/coverage/snapshots/estree_typescript.snap +++ b/tasks/coverage/snapshots/estree_typescript.snap @@ -4717,10 +4717,10 @@ Mismatch: tasks/coverage/typescript/tests/cases/conformance/es6/unicodeExtendedE Mismatch: tasks/coverage/typescript/tests/cases/conformance/es6/unicodeExtendedEscapes/unicodeExtendedEscapesInStrings08.ts Mismatch: tasks/coverage/typescript/tests/cases/conformance/es6/unicodeExtendedEscapes/unicodeExtendedEscapesInStrings09.ts tasks/coverage/typescript/tests/cases/conformance/es6/unicodeExtendedEscapes/unicodeExtendedEscapesInStrings10.ts -serde_json::from_str(estree_json) error: unexpected end of hex escape at line 30 column 29 +serde_json::from_str(oxc_json) error: invalid escape at line 30 column 28 tasks/coverage/typescript/tests/cases/conformance/es6/unicodeExtendedEscapes/unicodeExtendedEscapesInStrings11.ts -serde_json::from_str(estree_json) error: lone leading surrogate in hex escape at line 30 column 28 +serde_json::from_str(oxc_json) error: invalid escape at line 30 column 28 Mismatch: tasks/coverage/typescript/tests/cases/conformance/es6/unicodeExtendedEscapes/unicodeExtendedEscapesInStrings13.ts Mismatch: tasks/coverage/typescript/tests/cases/conformance/es6/unicodeExtendedEscapes/unicodeExtendedEscapesInStrings15.ts From 326b4df8d429cdda08ff4e5240777208709d0093 Mon Sep 17 00:00:00 2001 From: overlookmotel <557937+overlookmotel@users.noreply.github.com> Date: Fri, 28 Mar 2025 04:30:19 +0000 Subject: [PATCH 09/15] refactor(lexer): simplify macros for string parsing + correct comment (#10039) Small simplification of `handle_string_literal!` macro in lexer. Correct one comment which was wrong. --- crates/oxc_parser/src/lexer/string.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/oxc_parser/src/lexer/string.rs b/crates/oxc_parser/src/lexer/string.rs index b739277402d5e..533fb715d7a44 100644 --- a/crates/oxc_parser/src/lexer/string.rs +++ b/crates/oxc_parser/src/lexer/string.rs @@ -25,7 +25,7 @@ static SINGLE_QUOTE_STRING_END_TABLE: SafeByteMatchTable = /// `$table` must be a `SafeByteMatchTable`. /// `$table` must only match `$delimiter`, '\', '\r' or '\n'. macro_rules! handle_string_literal { - ($lexer:ident, $delimiter:expr_2021, $table:ident) => {{ + ($lexer:ident, $delimiter:literal, $table:ident) => {{ debug_assert!($delimiter.is_ascii()); if $lexer.context == LexerContext::JsxAttributeValue { @@ -37,7 +37,7 @@ macro_rules! handle_string_literal { // SAFETY: Caller guarantees next byte is ASCII, so safe to advance past it. let after_opening_quote = $lexer.source.position().add(1); - // Consume bytes which are part of identifier + // Consume bytes which are part of string let next_byte = byte_search! { lexer: $lexer, table: $table, @@ -74,7 +74,7 @@ macro_rules! handle_string_literal { } macro_rules! handle_string_literal_escape { - ($lexer:ident, $delimiter:expr_2021, $table:ident, $after_opening_quote:ident) => {{ + ($lexer:ident, $delimiter:literal, $table:ident, $after_opening_quote:ident) => {{ // Create arena string to hold unescaped string. // We don't know how long string will end up being. Take a guess that total length // will be double what we've seen so far, or `MIN_ESCAPED_STR_LEN` minimum. From c7079b5c59bc5396e716ea7ccb889c620676d25c Mon Sep 17 00:00:00 2001 From: overlookmotel <557937+overlookmotel@users.noreply.github.com> Date: Fri, 28 Mar 2025 04:30:19 +0000 Subject: [PATCH 10/15] refactor(lexer): clarify and reformat comments (#10040) Clarify and reformat comments in the code relating to lone surrogates. --- crates/oxc_parser/src/lexer/unicode.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/crates/oxc_parser/src/lexer/unicode.rs b/crates/oxc_parser/src/lexer/unicode.rs index e96269753da49..d33b6c203eca0 100644 --- a/crates/oxc_parser/src/lexer/unicode.rs +++ b/crates/oxc_parser/src/lexer/unicode.rs @@ -206,18 +206,21 @@ impl<'a> Lexer<'a> { /// * `https://mathiasbynens.be/notes/javascript-identifiers-es6` fn surrogate_pair(&mut self) -> Option { let high = self.hex_4_digits()?; - // The first code unit of a surrogate pair is always in the range from 0xD800 to 0xDBFF, and is called a high surrogate or a lead surrogate. + // The first code unit of a surrogate pair is always in the range from 0xD800 to 0xDBFF, + // and is called a high surrogate or a lead surrogate. let is_pair = (0xD800..=0xDBFF).contains(&high) && self.peek_2_bytes() == Some([b'\\', b'u']); if !is_pair { return Some(SurrogatePair::CodePoint(high)); } + // We checked above that next 2 chars are `\u` self.consume_2_chars(); let low = self.hex_4_digits()?; - // The second code unit of a surrogate pair is always in the range from 0xDC00 to 0xDFFF, and is called a low surrogate or a trail surrogate. + // The second code unit of a surrogate pair is always in the range from 0xDC00 to 0xDFFF, + // and is called a low surrogate or a trail surrogate. if !(0xDC00..=0xDFFF).contains(&low) { return Some(SurrogatePair::HighLow(high, low)); } From a24ccebe3543dee285ff20a026930d49873746e1 Mon Sep 17 00:00:00 2001 From: overlookmotel <557937+overlookmotel@users.noreply.github.com> Date: Fri, 28 Mar 2025 04:30:20 +0000 Subject: [PATCH 11/15] refactor(lexer): remove unnecessary line (#10042) Tiny refactor to lexer. Remove a pointless line from string parsing code. --- crates/oxc_parser/src/lexer/string.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/oxc_parser/src/lexer/string.rs b/crates/oxc_parser/src/lexer/string.rs index 533fb715d7a44..10f471fb02f87 100644 --- a/crates/oxc_parser/src/lexer/string.rs +++ b/crates/oxc_parser/src/lexer/string.rs @@ -109,7 +109,6 @@ macro_rules! handle_string_literal_escape { // mean `!table.matches(b)` on this branch prevents exiting this loop until // `source` is positioned on a UTF-8 character boundary again. $lexer.source.next_byte_unchecked(); - continue; } b if b == $delimiter => { // End of string found. Push last chunk to `str`. From 630e1894269928cd7af68b29be28e207e578e4f9 Mon Sep 17 00:00:00 2001 From: overlookmotel <557937+overlookmotel@users.noreply.github.com> Date: Fri, 28 Mar 2025 04:30:20 +0000 Subject: [PATCH 12/15] refactor(lexer): shorten code for parsing hex digit (#10072) Pure refactor. Shorten code by using `?`. --- crates/oxc_parser/src/lexer/unicode.rs | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/crates/oxc_parser/src/lexer/unicode.rs b/crates/oxc_parser/src/lexer/unicode.rs index d33b6c203eca0..34cae583718ff 100644 --- a/crates/oxc_parser/src/lexer/unicode.rs +++ b/crates/oxc_parser/src/lexer/unicode.rs @@ -163,29 +163,29 @@ impl<'a> Lexer<'a> { } fn hex_digit(&mut self) -> Option { + let b = self.peek_byte()?; + // Reduce instructions and remove 1 branch by comparing against `A-F` and `a-f` simultaneously // https://godbolt.org/z/9caMMzvP3 - let value = if let Some(b) = self.peek_byte() { - if b.is_ascii_digit() { - b - b'0' + let value = if b.is_ascii_digit() { + b - b'0' + } else { + // Match `A-F` or `a-f`. `b | 32` converts uppercase letters to lowercase, + // but leaves lowercase as they are + let lower_case = b | 32; + if matches!(lower_case, b'a'..=b'f') { + lower_case + 10 - b'a' } else { - // Match `A-F` or `a-f`. `b | 32` converts uppercase letters to lowercase, - // but leaves lowercase as they are - let lower_case = b | 32; - if matches!(lower_case, b'a'..=b'f') { - lower_case + 10 - b'a' - } else { - return None; - } + return None; } - } else { - return None; }; + // Because of `b | 32` above, compiler cannot deduce that next byte is definitely ASCII // so `next_byte_unchecked` is necessary to produce compact assembly, rather than `consume_char`. // SAFETY: This code is only reachable if there is a byte remaining, and it's ASCII. // Therefore it's safe to consume that byte, and will leave position on a UTF-8 char boundary. unsafe { self.source.next_byte_unchecked() }; + Some(u32::from(value)) } From 59b855f3f45fa44c5f125587a1d06bd14217bbef Mon Sep 17 00:00:00 2001 From: overlookmotel <557937+overlookmotel@users.noreply.github.com> Date: Fri, 28 Mar 2025 04:30:20 +0000 Subject: [PATCH 13/15] perf(lexer): faster decoding unicode escape sequences (#10073) Tiny optimization to lexer. Use `peek_byte` instead of `peek_char`, and move consuming `{` character in `\u{` to directly after the `peek_byte` call, so that compiler can see that it's infallible and that the next char is definitely ASCII. --- crates/oxc_parser/src/lexer/unicode.rs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/crates/oxc_parser/src/lexer/unicode.rs b/crates/oxc_parser/src/lexer/unicode.rs index 34cae583718ff..131d43151036b 100644 --- a/crates/oxc_parser/src/lexer/unicode.rs +++ b/crates/oxc_parser/src/lexer/unicode.rs @@ -65,7 +65,10 @@ impl<'a> Lexer<'a> { } let value = match self.peek_byte() { - Some(b'{') => self.unicode_code_point(), + Some(b'{') => { + self.consume_char(); + self.unicode_code_point() + } _ => self.surrogate_pair(), }; @@ -113,8 +116,11 @@ impl<'a> Lexer<'a> { text: &mut String<'a>, is_valid_escape_sequence: &mut bool, ) { - let value = match self.peek_char() { - Some('{') => self.unicode_code_point(), + let value = match self.peek_byte() { + Some(b'{') => { + self.consume_char(); + self.unicode_code_point() + } _ => self.surrogate_pair(), }; @@ -143,10 +149,10 @@ impl<'a> Lexer<'a> { } } + /// Decode unicode code point (`\u{ HexBytes }`). + /// + /// The opening `\u{` must already have been consumed before calling this method. fn unicode_code_point(&mut self) -> Option { - if !self.next_ascii_byte_eq(b'{') { - return None; - } let value = self.code_point()?; if !self.next_ascii_byte_eq(b'}') { return None; From 015a0a154a97cc2df12fa3ec554e83090dd9c8bf Mon Sep 17 00:00:00 2001 From: overlookmotel Date: Tue, 25 Mar 2025 22:29:55 +0530 Subject: [PATCH 14/15] fix(parser): store lone surrogates as escape sequence --- crates/oxc_ast/src/ast/literal.rs | 8 +- .../oxc_ast/src/generated/assert_layouts.rs | 4 +- crates/oxc_ast/src/generated/ast_builder.rs | 143 ++++++++++------ .../oxc_ast/src/generated/derive_clone_in.rs | 4 +- .../src/generated/derive_content_eq.rs | 2 +- crates/oxc_ast/src/generated/derive_dummy.rs | 2 +- crates/oxc_ast/src/serialize.rs | 60 ++----- crates/oxc_codegen/src/lib.rs | 2 +- crates/oxc_estree/src/serialize/mod.rs | 2 +- crates/oxc_estree/src/serialize/strings.rs | 131 +++++++++++++-- crates/oxc_parser/src/js/expression.rs | 4 +- crates/oxc_parser/src/js/module.rs | 2 +- crates/oxc_parser/src/lexer/string.rs | 72 +++++++- crates/oxc_parser/src/lexer/token.rs | 4 +- crates/oxc_parser/src/lexer/unicode.rs | 155 ++++++++++++------ napi/parser/deserialize-js.js | 10 +- napi/parser/deserialize-ts.js | 10 +- tasks/coverage/snapshots/estree_test262.snap | 26 +-- .../coverage/snapshots/estree_typescript.snap | 4 +- tasks/coverage/snapshots/parser_test262.snap | 2 +- tasks/coverage/src/tools/estree.rs | 41 +---- 21 files changed, 433 insertions(+), 255 deletions(-) diff --git a/crates/oxc_ast/src/ast/literal.rs b/crates/oxc_ast/src/ast/literal.rs index 11f7aaa24d225..a03d2d8e466c4 100644 --- a/crates/oxc_ast/src/ast/literal.rs +++ b/crates/oxc_ast/src/ast/literal.rs @@ -85,10 +85,14 @@ pub struct StringLiteral<'a> { #[content_eq(skip)] pub raw: Option>, - /// The string value contains replacement character (U+FFFD). + /// The string value contains lone surrogates. + /// + /// `value` is encoded using `\u{FFFD}` (the lossy replacement character) as an escape character. + /// Lone surrogates are encoded as `\u{FFFD}XXXX`, where `XXXX` is the code unit in hex. + /// The lossy escape character itself is encoded as `\u{FFFD}fffd`. #[builder(default)] #[estree(skip)] - pub lossy: bool, + pub lone_surrogates: bool, } /// BigInt literal diff --git a/crates/oxc_ast/src/generated/assert_layouts.rs b/crates/oxc_ast/src/generated/assert_layouts.rs index f45db57d750b2..192583465e212 100644 --- a/crates/oxc_ast/src/generated/assert_layouts.rs +++ b/crates/oxc_ast/src/generated/assert_layouts.rs @@ -776,7 +776,7 @@ const _: () = { assert!(offset_of!(StringLiteral, span) == 0); assert!(offset_of!(StringLiteral, value) == 8); assert!(offset_of!(StringLiteral, raw) == 24); - assert!(offset_of!(StringLiteral, lossy) == 40); + assert!(offset_of!(StringLiteral, lone_surrogates) == 40); assert!(size_of::() == 32); assert!(align_of::() == 8); @@ -2167,7 +2167,7 @@ const _: () = { assert!(offset_of!(StringLiteral, span) == 0); assert!(offset_of!(StringLiteral, value) == 8); assert!(offset_of!(StringLiteral, raw) == 16); - assert!(offset_of!(StringLiteral, lossy) == 24); + assert!(offset_of!(StringLiteral, lone_surrogates) == 24); assert!(size_of::() == 20); assert!(align_of::() == 4); diff --git a/crates/oxc_ast/src/generated/ast_builder.rs b/crates/oxc_ast/src/generated/ast_builder.rs index 3c1385074b2c9..61c88f90b02dc 100644 --- a/crates/oxc_ast/src/generated/ast_builder.rs +++ b/crates/oxc_ast/src/generated/ast_builder.rs @@ -276,7 +276,7 @@ impl<'a> AstBuilder<'a> { Expression::StringLiteral(self.alloc_string_literal(span, value, raw)) } - /// Build an [`Expression::StringLiteral`] with `lossy`. + /// Build an [`Expression::StringLiteral`] with `lone_surrogates`. /// /// This node contains a [`StringLiteral`] that will be stored in the memory arena. /// @@ -284,19 +284,24 @@ impl<'a> AstBuilder<'a> { /// * `span`: Node location in source code /// * `value`: The value of the string. /// * `raw`: The raw string as it appears in source code. - /// * `lossy`: The string value contains replacement character (U+FFFD). + /// * `lone_surrogates`: The string value contains lone surrogates. #[inline] - pub fn expression_string_literal_with_lossy( + pub fn expression_string_literal_with_lone_surrogates( self, span: Span, value: A, raw: Option>, - lossy: bool, + lone_surrogates: bool, ) -> Expression<'a> where A: IntoIn<'a, Atom<'a>>, { - Expression::StringLiteral(self.alloc_string_literal_with_lossy(span, value, raw, lossy)) + Expression::StringLiteral(self.alloc_string_literal_with_lone_surrogates( + span, + value, + raw, + lone_surrogates, + )) } /// Build an [`Expression::TemplateLiteral`]. @@ -7843,25 +7848,30 @@ impl<'a> AstBuilder<'a> { ImportAttributeKey::StringLiteral(self.string_literal(span, value, raw)) } - /// Build an [`ImportAttributeKey::StringLiteral`] with `lossy`. + /// Build an [`ImportAttributeKey::StringLiteral`] with `lone_surrogates`. /// /// ## Parameters /// * `span`: Node location in source code /// * `value`: The value of the string. /// * `raw`: The raw string as it appears in source code. - /// * `lossy`: The string value contains replacement character (U+FFFD). + /// * `lone_surrogates`: The string value contains lone surrogates. #[inline] - pub fn import_attribute_key_string_literal_with_lossy( + pub fn import_attribute_key_string_literal_with_lone_surrogates( self, span: Span, value: A, raw: Option>, - lossy: bool, + lone_surrogates: bool, ) -> ImportAttributeKey<'a> where A: IntoIn<'a, Atom<'a>>, { - ImportAttributeKey::StringLiteral(self.string_literal_with_lossy(span, value, raw, lossy)) + ImportAttributeKey::StringLiteral(self.string_literal_with_lone_surrogates( + span, + value, + raw, + lone_surrogates, + )) } /// Build an [`ExportNamedDeclaration`]. @@ -8442,25 +8452,30 @@ impl<'a> AstBuilder<'a> { ModuleExportName::StringLiteral(self.string_literal(span, value, raw)) } - /// Build a [`ModuleExportName::StringLiteral`] with `lossy`. + /// Build a [`ModuleExportName::StringLiteral`] with `lone_surrogates`. /// /// ## Parameters /// * `span`: Node location in source code /// * `value`: The value of the string. /// * `raw`: The raw string as it appears in source code. - /// * `lossy`: The string value contains replacement character (U+FFFD). + /// * `lone_surrogates`: The string value contains lone surrogates. #[inline] - pub fn module_export_name_string_literal_with_lossy( + pub fn module_export_name_string_literal_with_lone_surrogates( self, span: Span, value: A, raw: Option>, - lossy: bool, + lone_surrogates: bool, ) -> ModuleExportName<'a> where A: IntoIn<'a, Atom<'a>>, { - ModuleExportName::StringLiteral(self.string_literal_with_lossy(span, value, raw, lossy)) + ModuleExportName::StringLiteral(self.string_literal_with_lone_surrogates( + span, + value, + raw, + lone_surrogates, + )) } /// Build a [`V8IntrinsicExpression`]. @@ -8598,7 +8613,12 @@ impl<'a> AstBuilder<'a> { where A: IntoIn<'a, Atom<'a>>, { - StringLiteral { span, value: value.into_in(self.allocator), raw, lossy: Default::default() } + StringLiteral { + span, + value: value.into_in(self.allocator), + raw, + lone_surrogates: Default::default(), + } } /// Build a [`StringLiteral`], and store it in the memory arena. @@ -8622,50 +8642,53 @@ impl<'a> AstBuilder<'a> { Box::new_in(self.string_literal(span, value, raw), self.allocator) } - /// Build a [`StringLiteral`] with `lossy`. + /// Build a [`StringLiteral`] with `lone_surrogates`. /// - /// If you want the built node to be allocated in the memory arena, use [`AstBuilder::alloc_string_literal_with_lossy`] instead. + /// If you want the built node to be allocated in the memory arena, use [`AstBuilder::alloc_string_literal_with_lone_surrogates`] instead. /// /// ## Parameters /// * `span`: Node location in source code /// * `value`: The value of the string. /// * `raw`: The raw string as it appears in source code. - /// * `lossy`: The string value contains replacement character (U+FFFD). + /// * `lone_surrogates`: The string value contains lone surrogates. #[inline] - pub fn string_literal_with_lossy( + pub fn string_literal_with_lone_surrogates( self, span: Span, value: A, raw: Option>, - lossy: bool, + lone_surrogates: bool, ) -> StringLiteral<'a> where A: IntoIn<'a, Atom<'a>>, { - StringLiteral { span, value: value.into_in(self.allocator), raw, lossy } + StringLiteral { span, value: value.into_in(self.allocator), raw, lone_surrogates } } - /// Build a [`StringLiteral`] with `lossy`, and store it in the memory arena. + /// Build a [`StringLiteral`] with `lone_surrogates`, and store it in the memory arena. /// - /// Returns a [`Box`] containing the newly-allocated node. If you want a stack-allocated node, use [`AstBuilder::string_literal_with_lossy`] instead. + /// Returns a [`Box`] containing the newly-allocated node. If you want a stack-allocated node, use [`AstBuilder::string_literal_with_lone_surrogates`] instead. /// /// ## Parameters /// * `span`: Node location in source code /// * `value`: The value of the string. /// * `raw`: The raw string as it appears in source code. - /// * `lossy`: The string value contains replacement character (U+FFFD). + /// * `lone_surrogates`: The string value contains lone surrogates. #[inline] - pub fn alloc_string_literal_with_lossy( + pub fn alloc_string_literal_with_lone_surrogates( self, span: Span, value: A, raw: Option>, - lossy: bool, + lone_surrogates: bool, ) -> Box<'a, StringLiteral<'a>> where A: IntoIn<'a, Atom<'a>>, { - Box::new_in(self.string_literal_with_lossy(span, value, raw, lossy), self.allocator) + Box::new_in( + self.string_literal_with_lone_surrogates(span, value, raw, lone_surrogates), + self.allocator, + ) } /// Build a [`BigIntLiteral`]. @@ -9444,7 +9467,7 @@ impl<'a> AstBuilder<'a> { JSXAttributeValue::StringLiteral(self.alloc_string_literal(span, value, raw)) } - /// Build a [`JSXAttributeValue::StringLiteral`] with `lossy`. + /// Build a [`JSXAttributeValue::StringLiteral`] with `lone_surrogates`. /// /// This node contains a [`StringLiteral`] that will be stored in the memory arena. /// @@ -9452,21 +9475,24 @@ impl<'a> AstBuilder<'a> { /// * `span`: Node location in source code /// * `value`: The value of the string. /// * `raw`: The raw string as it appears in source code. - /// * `lossy`: The string value contains replacement character (U+FFFD). + /// * `lone_surrogates`: The string value contains lone surrogates. #[inline] - pub fn jsx_attribute_value_string_literal_with_lossy( + pub fn jsx_attribute_value_string_literal_with_lone_surrogates( self, span: Span, value: A, raw: Option>, - lossy: bool, + lone_surrogates: bool, ) -> JSXAttributeValue<'a> where A: IntoIn<'a, Atom<'a>>, { - JSXAttributeValue::StringLiteral( - self.alloc_string_literal_with_lossy(span, value, raw, lossy), - ) + JSXAttributeValue::StringLiteral(self.alloc_string_literal_with_lone_surrogates( + span, + value, + raw, + lone_surrogates, + )) } /// Build a [`JSXAttributeValue::ExpressionContainer`]. @@ -9949,7 +9975,7 @@ impl<'a> AstBuilder<'a> { TSEnumMemberName::String(self.alloc_string_literal(span, value, raw)) } - /// Build a [`TSEnumMemberName::String`] with `lossy`. + /// Build a [`TSEnumMemberName::String`] with `lone_surrogates`. /// /// This node contains a [`StringLiteral`] that will be stored in the memory arena. /// @@ -9957,19 +9983,24 @@ impl<'a> AstBuilder<'a> { /// * `span`: Node location in source code /// * `value`: The value of the string. /// * `raw`: The raw string as it appears in source code. - /// * `lossy`: The string value contains replacement character (U+FFFD). + /// * `lone_surrogates`: The string value contains lone surrogates. #[inline] - pub fn ts_enum_member_name_string_with_lossy( + pub fn ts_enum_member_name_string_with_lone_surrogates( self, span: Span, value: A, raw: Option>, - lossy: bool, + lone_surrogates: bool, ) -> TSEnumMemberName<'a> where A: IntoIn<'a, Atom<'a>>, { - TSEnumMemberName::String(self.alloc_string_literal_with_lossy(span, value, raw, lossy)) + TSEnumMemberName::String(self.alloc_string_literal_with_lone_surrogates( + span, + value, + raw, + lone_surrogates, + )) } /// Build a [`TSTypeAnnotation`]. @@ -10106,7 +10137,7 @@ impl<'a> AstBuilder<'a> { TSLiteral::StringLiteral(self.alloc_string_literal(span, value, raw)) } - /// Build a [`TSLiteral::StringLiteral`] with `lossy`. + /// Build a [`TSLiteral::StringLiteral`] with `lone_surrogates`. /// /// This node contains a [`StringLiteral`] that will be stored in the memory arena. /// @@ -10114,19 +10145,24 @@ impl<'a> AstBuilder<'a> { /// * `span`: Node location in source code /// * `value`: The value of the string. /// * `raw`: The raw string as it appears in source code. - /// * `lossy`: The string value contains replacement character (U+FFFD). + /// * `lone_surrogates`: The string value contains lone surrogates. #[inline] - pub fn ts_literal_string_literal_with_lossy( + pub fn ts_literal_string_literal_with_lone_surrogates( self, span: Span, value: A, raw: Option>, - lossy: bool, + lone_surrogates: bool, ) -> TSLiteral<'a> where A: IntoIn<'a, Atom<'a>>, { - TSLiteral::StringLiteral(self.alloc_string_literal_with_lossy(span, value, raw, lossy)) + TSLiteral::StringLiteral(self.alloc_string_literal_with_lone_surrogates( + span, + value, + raw, + lone_surrogates, + )) } /// Build a [`TSLiteral::TemplateLiteral`]. @@ -13387,27 +13423,30 @@ impl<'a> AstBuilder<'a> { TSModuleDeclarationName::StringLiteral(self.string_literal(span, value, raw)) } - /// Build a [`TSModuleDeclarationName::StringLiteral`] with `lossy`. + /// Build a [`TSModuleDeclarationName::StringLiteral`] with `lone_surrogates`. /// /// ## Parameters /// * `span`: Node location in source code /// * `value`: The value of the string. /// * `raw`: The raw string as it appears in source code. - /// * `lossy`: The string value contains replacement character (U+FFFD). + /// * `lone_surrogates`: The string value contains lone surrogates. #[inline] - pub fn ts_module_declaration_name_string_literal_with_lossy( + pub fn ts_module_declaration_name_string_literal_with_lone_surrogates( self, span: Span, value: A, raw: Option>, - lossy: bool, + lone_surrogates: bool, ) -> TSModuleDeclarationName<'a> where A: IntoIn<'a, Atom<'a>>, { - TSModuleDeclarationName::StringLiteral( - self.string_literal_with_lossy(span, value, raw, lossy), - ) + TSModuleDeclarationName::StringLiteral(self.string_literal_with_lone_surrogates( + span, + value, + raw, + lone_surrogates, + )) } /// Build a [`TSModuleDeclarationBody::TSModuleDeclaration`]. diff --git a/crates/oxc_ast/src/generated/derive_clone_in.rs b/crates/oxc_ast/src/generated/derive_clone_in.rs index 7783a17120e70..fe6b4d8a92d79 100644 --- a/crates/oxc_ast/src/generated/derive_clone_in.rs +++ b/crates/oxc_ast/src/generated/derive_clone_in.rs @@ -4843,7 +4843,7 @@ impl<'new_alloc> CloneIn<'new_alloc> for StringLiteral<'_> { span: CloneIn::clone_in(&self.span, allocator), value: CloneIn::clone_in(&self.value, allocator), raw: CloneIn::clone_in(&self.raw, allocator), - lossy: CloneIn::clone_in(&self.lossy, allocator), + lone_surrogates: CloneIn::clone_in(&self.lone_surrogates, allocator), } } @@ -4852,7 +4852,7 @@ impl<'new_alloc> CloneIn<'new_alloc> for StringLiteral<'_> { span: CloneIn::clone_in_with_semantic_ids(&self.span, allocator), value: CloneIn::clone_in_with_semantic_ids(&self.value, allocator), raw: CloneIn::clone_in_with_semantic_ids(&self.raw, allocator), - lossy: CloneIn::clone_in_with_semantic_ids(&self.lossy, allocator), + lone_surrogates: CloneIn::clone_in_with_semantic_ids(&self.lone_surrogates, allocator), } } } diff --git a/crates/oxc_ast/src/generated/derive_content_eq.rs b/crates/oxc_ast/src/generated/derive_content_eq.rs index f21c825d68a08..e9cb8d3c237f8 100644 --- a/crates/oxc_ast/src/generated/derive_content_eq.rs +++ b/crates/oxc_ast/src/generated/derive_content_eq.rs @@ -1471,7 +1471,7 @@ impl ContentEq for NumericLiteral<'_> { impl ContentEq for StringLiteral<'_> { fn content_eq(&self, other: &Self) -> bool { ContentEq::content_eq(&self.value, &other.value) - && ContentEq::content_eq(&self.lossy, &other.lossy) + && ContentEq::content_eq(&self.lone_surrogates, &other.lone_surrogates) } } diff --git a/crates/oxc_ast/src/generated/derive_dummy.rs b/crates/oxc_ast/src/generated/derive_dummy.rs index b113c775cb348..3c3e7960d3285 100644 --- a/crates/oxc_ast/src/generated/derive_dummy.rs +++ b/crates/oxc_ast/src/generated/derive_dummy.rs @@ -1597,7 +1597,7 @@ impl<'a> Dummy<'a> for StringLiteral<'a> { span: Dummy::dummy(allocator), value: Dummy::dummy(allocator), raw: Dummy::dummy(allocator), - lossy: Dummy::dummy(allocator), + lone_surrogates: Dummy::dummy(allocator), } } } diff --git a/crates/oxc_ast/src/serialize.rs b/crates/oxc_ast/src/serialize.rs index aad56b4df31a5..b7177a79a69b2 100644 --- a/crates/oxc_ast/src/serialize.rs +++ b/crates/oxc_ast/src/serialize.rs @@ -1,11 +1,9 @@ -use std::borrow::Cow; - use cow_utils::CowUtils; use oxc_ast_macros::ast_meta; use oxc_estree::{ - CompactJSSerializer, CompactTSSerializer, ESTree, JsonSafeString, PrettyJSSerializer, - PrettyTSSerializer, SequenceSerializer, Serializer, StructSerializer, + CompactJSSerializer, CompactTSSerializer, ESTree, JsonSafeString, LoneSurrogatesString, + PrettyJSSerializer, PrettyTSSerializer, SequenceSerializer, Serializer, StructSerializer, }; use crate::ast::*; @@ -233,10 +231,13 @@ impl ESTree for NullLiteralRaw<'_> { #[ast_meta] #[estree( ts_type = "string", - raw_deser = " - const lossy = DESER[bool](POS_OFFSET.lossy); - (THIS.lossy && THIS.raw !== null) ? (0, eval)(THIS.raw) : DESER[Atom](POS_OFFSET.value) - " + raw_deser = r#" + let value = DESER[Atom](POS_OFFSET.value); + if (DESER[bool](POS_OFFSET.lone_surrogates)) { + value = value.replace(/\uFFFD(.{4})/g, (_, hex) => String.fromCodePoint(parseInt(hex, 16))); + } + value + "# )] pub struct StringLiteralValue<'a, 'b>(pub &'b StringLiteral<'a>); @@ -244,10 +245,11 @@ impl ESTree for StringLiteralValue<'_, '_> { fn serialize(&self, serializer: S) { let lit = self.0; #[expect(clippy::if_not_else)] - if !lit.lossy { + if !lit.lone_surrogates { lit.value.serialize(serializer); } else { - self.serialize_lossy(serializer); + // String contains lone surrogates + self.serialize_lone_surrogates(serializer); } } } @@ -255,42 +257,8 @@ impl ESTree for StringLiteralValue<'_, '_> { impl StringLiteralValue<'_, '_> { #[cold] #[inline(never)] - fn serialize_lossy(&self, serializer: S) { - // String contains lone surrogates - let lit = self.0; - let raw = - lit.raw.expect("`StringLiteral` with `lossy` flag set must have `raw` field populated"); - let raw = raw.as_str(); - let quote = raw.as_bytes().first().copied().unwrap(); - let raw_unquoted = &raw[1..raw.len() - 1]; - let raw_with_quotes_escaped = if quote == b'"' { - // String was in double quotes in original source, so it's valid JSON - Cow::Borrowed(raw_unquoted) - } else { - // String was in single quotes in original source. - // We need to replace any `"` characters with `\"`, and then it's valid JSON. - // We *don't* escape `"` characters preceded by an odd number of `\`s, - // because they're already escaped. - // We could make this more performant, but it should be vanishingly rare to hit this path anyway. - let mut encoded = Vec::with_capacity(raw_unquoted.len()); - let mut has_slash = false; - for &b in raw_unquoted.as_bytes() { - if b == b'\\' { - has_slash = !has_slash; - } else if b == b'"' && !has_slash { - encoded.push(b'\\'); - } else { - has_slash = false; - } - encoded.push(b); - } - - // SAFETY: `raw_without_quotes` is a `&str`. `encoded` contains the exact same bytes, - // except we may have inserted `\` before `"`s. That cannot create invalid UTF-8. - let encoded = unsafe { String::from_utf8_unchecked(encoded) }; - Cow::Owned(encoded) - }; - JsonSafeString(&raw_with_quotes_escaped).serialize(serializer); + fn serialize_lone_surrogates(&self, serializer: S) { + LoneSurrogatesString(self.0.value.as_str()).serialize(serializer); } } diff --git a/crates/oxc_codegen/src/lib.rs b/crates/oxc_codegen/src/lib.rs index b74a3db51e4f0..acb413068bff7 100644 --- a/crates/oxc_codegen/src/lib.rs +++ b/crates/oxc_codegen/src/lib.rs @@ -578,7 +578,7 @@ impl<'a> Codegen<'a> { fn print_string_literal(&mut self, s: &StringLiteral<'_>, allow_backtick: bool) { self.add_source_mapping(s.span); - if s.lossy { + if s.lone_surrogates { self.print_str(s.raw.unwrap().as_str()); return; } diff --git a/crates/oxc_estree/src/serialize/mod.rs b/crates/oxc_estree/src/serialize/mod.rs index 9727f1855763c..c07475f76355f 100644 --- a/crates/oxc_estree/src/serialize/mod.rs +++ b/crates/oxc_estree/src/serialize/mod.rs @@ -16,7 +16,7 @@ use sequences::ESTreeSequenceSerializer; use structs::ESTreeStructSerializer; pub use sequences::SequenceSerializer; -pub use strings::JsonSafeString; +pub use strings::{JsonSafeString, LoneSurrogatesString}; pub use structs::{FlatStructSerializer, StructSerializer}; /// Trait for types which can be serialized to ESTree. diff --git a/crates/oxc_estree/src/serialize/strings.rs b/crates/oxc_estree/src/serialize/strings.rs index 336a502a47e33..1b83cfb69ba5c 100644 --- a/crates/oxc_estree/src/serialize/strings.rs +++ b/crates/oxc_estree/src/serialize/strings.rs @@ -2,6 +2,17 @@ use oxc_data_structures::code_buffer::CodeBuffer; use super::{ESTree, Serializer}; +/// Convert `char` to UTF-8 bytes array. +const fn to_bytes(ch: char) -> [u8; N] { + let mut bytes = [0u8; N]; + ch.encode_utf8(&mut bytes); + bytes +} + +/// Lossy replacement character (U+FFFD) as UTF-8 bytes. +const LOSSY_REPLACEMENT_CHAR_BYTES: [u8; 3] = to_bytes('\u{FFFD}'); +const LOSSY_REPLACEMENT_CHAR_FIRST_BYTE: u8 = LOSSY_REPLACEMENT_CHAR_BYTES[0]; // 0xEF + /// A string which does not need any escaping in JSON. /// /// This provides better performance when you know that the string definitely contains no characters @@ -20,17 +31,32 @@ impl ESTree for JsonSafeString<'_> { } } +/// A string which contains lone surrogates escaped with lossy replacement character (U+FFFD). +/// +/// Lone surrogates are encoded in the string as `\uFFFD1234` where `1234` is the code point in hex. +/// These are converted to `\u1234` in JSON. +/// An actual lossy replacement character is encoded in the string as `\uFFFDfffd`, and is converted +/// to the actual character. +pub struct LoneSurrogatesString<'s>(pub &'s str); + +impl ESTree for LoneSurrogatesString<'_> { + #[inline(always)] + fn serialize(&self, mut serializer: S) { + write_str(self.0, &ESCAPE_LONE_SURROGATES, serializer.buffer_mut()); + } +} + /// [`ESTree`] implementation for string slice. impl ESTree for str { fn serialize(&self, mut serializer: S) { - write_str(self, serializer.buffer_mut()); + write_str(self, &ESCAPE, serializer.buffer_mut()); } } /// [`ESTree`] implementation for `String`. impl ESTree for String { - fn serialize(&self, mut serializer: S) { - write_str(self.as_str(), serializer.buffer_mut()); + fn serialize(&self, serializer: S) { + self.as_str().serialize(serializer); } } @@ -46,7 +72,8 @@ enum Escape { RR = b'r', // \x0D QU = b'"', // \x22 BS = b'\\', // \x5C - UU = b'u', // \x00...\x1F except the ones above + LO = LOSSY_REPLACEMENT_CHAR_FIRST_BYTE, + UU = b'u', // \x00...\x1F except the ones above } /// Lookup table of escape sequences. A value of `b'x'` at index `i` means that byte `i` @@ -54,7 +81,12 @@ enum Escape { /// /// A value of `UU` means that byte is escaped as `\u00xx`, where `xx` is the hex code of the byte. /// e.g. `0x1F` is output as `\u001F`. -static ESCAPE: [Escape; 256] = { +static ESCAPE: [Escape; 256] = create_table(Escape::__); + +/// Same as `ESCAPE` but with `Escape::LO` for byte 0xEF. +static ESCAPE_LONE_SURROGATES: [Escape; 256] = create_table(Escape::LO); + +const fn create_table(lo: Escape) -> [Escape; 256] { #[allow(clippy::enum_glob_use, clippy::allow_attributes)] use Escape::*; @@ -74,29 +106,73 @@ static ESCAPE: [Escape; 256] = { __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // B __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // C __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // D - __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // E + __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, lo, // E __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // F ] -}; +} /// Write string to buffer. /// String is wrapped in `"`s, and with any characters which are not valid in JSON escaped. +// +// `#[inline(always)]` because this is a hot path, and to make compiler remove the code +// for handling lone surrogates when outputting a normal string (the common case). #[inline(always)] -fn write_str(s: &str, buffer: &mut CodeBuffer) { +fn write_str(s: &str, table: &[Escape; 256], buffer: &mut CodeBuffer) { buffer.print_ascii_byte(b'"'); let bytes = s.as_bytes(); let mut start = 0; - for (index, &byte) in bytes.iter().enumerate() { - let escape = ESCAPE[byte as usize]; + let mut iter = bytes.iter().enumerate(); + while let Some((index, &byte)) = iter.next() { + let escape = table[byte as usize]; if escape == Escape::__ { continue; } + // Handle lone surrogates + if table == &ESCAPE_LONE_SURROGATES && escape == Escape::LO { + let (_, &next1) = iter.next().unwrap(); + let (_, &next2) = iter.next().unwrap(); + if [next1, next2] == [LOSSY_REPLACEMENT_CHAR_BYTES[1], LOSSY_REPLACEMENT_CHAR_BYTES[2]] + { + // Lossy replacement character (U+FFFD) is used as an escape before lone surrogates, + // with the code point as 4 x hex characters after it. + let (_, &hex1) = iter.next().unwrap(); + let (_, &hex2) = iter.next().unwrap(); + let (_, &hex3) = iter.next().unwrap(); + let (_, &hex4) = iter.next().unwrap(); + + // Print the chunk upto before the lossy replacement character. + // SAFETY: 0xEF is always the start of a 3-byte unicode character. + // Therefore `index` must be on a UTF-8 character boundary. + unsafe { buffer.print_bytes_unchecked(&bytes[start..index]) }; + + if [hex1, hex2, hex3, hex4] == *b"fffd" { + // This is an actual lossy replacement character (not an escaped lone surrogate) + buffer.print_str("\u{FFFD}"); + } else { + // This is an escaped lone surrogate. + // Print `\uXXXX` where `XXXX` is hex characters. e.g. `\ud800`. + assert!((hex1 | hex2 | hex3 | hex3).is_ascii()); + buffer.print_str("\\u"); + // SAFETY: Just checked all 4 bytes are ASCII + unsafe { buffer.print_bytes_unchecked(&[hex1, hex2, hex3, hex4]) }; + } + + // Skip the 3 bytes of the lossy replacement character + 4 hex bytes. + // We checked that all 4 hex bytes are ASCII, so `start` is definitely left on + // a UTF-8 character boundary. + start = index + 7; + } else { + // Some other unicode character starting with 0xEF. Just continue the loop. + } + continue; + } + if start < index { // SAFETY: `bytes` is derived from a `&str`. - // `escape` is only non-zero for ASCII bytes. + // `escape` is only non-zero for ASCII bytes, except `Escape::LO` which is handled above. // Therefore current `index` must mark the end of a valid UTF8 character sequence. // `start` is either the start of string, or after an ASCII character, // therefore always the start of a valid UTF8 character sequence. @@ -181,7 +257,38 @@ mod tests { for (input, output) in cases { let mut serializer = CompactTSSerializer::new(); - input.serialize(&mut serializer); + input.to_string().serialize(&mut serializer); + let s = serializer.into_string(); + assert_eq!(&s, output); + } + } + + #[test] + fn serialize_json_safe_string() { + let cases = [("", r#""""#), ("a", r#""a""#), ("abc", r#""abc""#)]; + + for (input, output) in cases { + let mut serializer = CompactTSSerializer::new(); + JsonSafeString(input).serialize(&mut serializer); + let s = serializer.into_string(); + assert_eq!(&s, output); + } + } + + #[test] + fn serialize_lone_surrogates_string() { + let cases = [ + ("\u{FFFD}fffd", "\"\u{FFFD}\""), + ("_x_\u{FFFD}fffd_y_\u{FFFD}fffd_z_", "\"_x_\u{FFFD}_y_\u{FFFD}_z_\""), + ("\u{FFFD}d834\u{FFFD}d835", r#""\ud834\ud835""#), + ("_x_\u{FFFD}d834\u{FFFD}d835", r#""_x_\ud834\ud835""#), + ("\u{FFFD}d834\u{FFFD}d835_y_", r#""\ud834\ud835_y_""#), + ("_x_\u{FFFD}d834_y_\u{FFFD}d835_z_", r#""_x_\ud834_y_\ud835_z_""#), + ]; + + for (input, output) in cases { + let mut serializer = CompactTSSerializer::new(); + LoneSurrogatesString(input).serialize(&mut serializer); let s = serializer.into_string(); assert_eq!(&s, output); } diff --git a/crates/oxc_parser/src/js/expression.rs b/crates/oxc_parser/src/js/expression.rs index 7d8c04301de51..f5371284901ce 100644 --- a/crates/oxc_parser/src/js/expression.rs +++ b/crates/oxc_parser/src/js/expression.rs @@ -406,7 +406,7 @@ impl<'a> ParserImpl<'a> { } let value = self.cur_string(); let span = self.start_span(); - let lossy = self.cur_token().lossy; + let lone_surrogates = self.cur_token().lone_surrogates; self.bump_any(); let span = self.end_span(span); // SAFETY: @@ -415,7 +415,7 @@ impl<'a> ParserImpl<'a> { self.source_text.get_unchecked(span.start as usize..span.end as usize) }); let mut string_literal = self.ast.string_literal(span, value, Some(raw)); - string_literal.lossy = lossy; + string_literal.lone_surrogates = lone_surrogates; Ok(string_literal) } diff --git a/crates/oxc_parser/src/js/module.rs b/crates/oxc_parser/src/js/module.rs index 35526c1d74313..561ada51df3c5 100644 --- a/crates/oxc_parser/src/js/module.rs +++ b/crates/oxc_parser/src/js/module.rs @@ -503,7 +503,7 @@ impl<'a> ParserImpl<'a> { let literal = self.parse_literal_string()?; // ModuleExportName : StringLiteral // It is a Syntax Error if IsStringWellFormedUnicode(the SV of StringLiteral) is false. - if literal.lossy || !literal.is_string_well_formed_unicode() { + if literal.lone_surrogates || !literal.is_string_well_formed_unicode() { self.error(diagnostics::export_lone_surrogate(literal.span)); }; Ok(ModuleExportName::StringLiteral(literal)) diff --git a/crates/oxc_parser/src/lexer/string.rs b/crates/oxc_parser/src/lexer/string.rs index 10f471fb02f87..4078d603cb779 100644 --- a/crates/oxc_parser/src/lexer/string.rs +++ b/crates/oxc_parser/src/lexer/string.rs @@ -9,6 +9,17 @@ use super::{ search::{SafeByteMatchTable, byte_search, safe_byte_match_table}, }; +/// Convert `char` to UTF-8 bytes array. +const fn to_bytes(ch: char) -> [u8; N] { + let mut bytes = [0u8; N]; + ch.encode_utf8(&mut bytes); + bytes +} + +/// Lossy replacement character (U+FFFD) as UTF-8 bytes. +const LOSSY_REPLACEMENT_CHAR_BYTES: [u8; 3] = to_bytes('\u{FFFD}'); +const LOSSY_REPLACEMENT_CHAR_FIRST_BYTE: u8 = LOSSY_REPLACEMENT_CHAR_BYTES[0]; // 0xEF + const MIN_ESCAPED_STR_LEN: usize = 16; static DOUBLE_QUOTE_STRING_END_TABLE: SafeByteMatchTable = @@ -17,6 +28,17 @@ static DOUBLE_QUOTE_STRING_END_TABLE: SafeByteMatchTable = static SINGLE_QUOTE_STRING_END_TABLE: SafeByteMatchTable = safe_byte_match_table!(|b| matches!(b, b'\'' | b'\r' | b'\n' | b'\\')); +// Same as above, but with 1st byte of lossy replacement character added +static DOUBLE_QUOTE_ESCAPED_MATCH_TABLE: SafeByteMatchTable = safe_byte_match_table!(|b| matches!( + b, + b'"' | b'\r' | b'\n' | b'\\' | LOSSY_REPLACEMENT_CHAR_FIRST_BYTE +)); + +static SINGLE_QUOTE_ESCAPED_MATCH_TABLE: SafeByteMatchTable = safe_byte_match_table!(|b| matches!( + b, + b'\'' | b'\r' | b'\n' | b'\\' | LOSSY_REPLACEMENT_CHAR_FIRST_BYTE +)); + /// Macro to handle a string literal. /// /// # SAFETY @@ -25,7 +47,7 @@ static SINGLE_QUOTE_STRING_END_TABLE: SafeByteMatchTable = /// `$table` must be a `SafeByteMatchTable`. /// `$table` must only match `$delimiter`, '\', '\r' or '\n'. macro_rules! handle_string_literal { - ($lexer:ident, $delimiter:literal, $table:ident) => {{ + ($lexer:ident, $delimiter:literal, $table:ident, $escaped_table:ident) => {{ debug_assert!($delimiter.is_ascii()); if $lexer.context == LexerContext::JsxAttributeValue { @@ -58,7 +80,12 @@ macro_rules! handle_string_literal { Kind::Str } b'\\' => cold_branch(|| { - handle_string_literal_escape!($lexer, $delimiter, $table, after_opening_quote) + handle_string_literal_escape!( + $lexer, + $delimiter, + $escaped_table, + after_opening_quote + ) }), _ => { // Line break. This is impossible in valid JS, so cold path. @@ -99,7 +126,7 @@ macro_rules! handle_string_literal_escape { } // Consume bytes until reach end of string, line break, or another escape - let chunk_start = $lexer.source.position(); + let mut chunk_start = $lexer.source.position(); while let Some(b) = $lexer.peek_byte() { match b { b if !$table.matches(b) => { @@ -127,6 +154,27 @@ macro_rules! handle_string_literal_escape { str.push_str(chunk); continue 'outer; } + LOSSY_REPLACEMENT_CHAR_FIRST_BYTE => cold_branch(|| { + // If the string contains lone surrogates, the lossy replacement character (U+FFFD) + // is used as start of an escape sequence. + // So an actual lossy escape character has to be escaped too. + // Output it as `\u{FFFD}fffd`. + // Cold branch because this should be very rare in real-world code. + + // SAFETY: A byte is available, as we just peeked it, and it's 0xEF. + // 0xEF is always 1st byte of a 3-byte Unicode sequence, so safe to consume 3 bytes. + $lexer.source.next_byte_unchecked(); + let next1 = $lexer.source.next_byte_unchecked(); + let next2 = $lexer.source.next_byte_unchecked(); + if $lexer.token.lone_surrogates + && [next1, next2] == [LOSSY_REPLACEMENT_CHAR_BYTES[1], LOSSY_REPLACEMENT_CHAR_BYTES[2]] + { + let chunk = $lexer.source.str_from_pos_to_current(chunk_start); + str.push_str(chunk); + str.push_str("fffd"); + chunk_start = $lexer.source.position(); + } + }), _ => { // Line break. This is impossible in valid JS, so cold path. return cold_branch(|| { @@ -159,7 +207,14 @@ impl<'a> Lexer<'a> { pub(super) unsafe fn read_string_literal_double_quote(&mut self) -> Kind { // SAFETY: Caller guarantees next char is `"`, which is ASCII. // b'"' is an ASCII byte. `DOUBLE_QUOTE_STRING_END_TABLE` is a `SafeByteMatchTable`. - unsafe { handle_string_literal!(self, b'"', DOUBLE_QUOTE_STRING_END_TABLE) } + unsafe { + handle_string_literal!( + self, + b'"', + DOUBLE_QUOTE_STRING_END_TABLE, + DOUBLE_QUOTE_ESCAPED_MATCH_TABLE + ) + } } /// Read string literal delimited with `'`. @@ -168,7 +223,14 @@ impl<'a> Lexer<'a> { pub(super) unsafe fn read_string_literal_single_quote(&mut self) -> Kind { // SAFETY: Caller guarantees next char is `'`, which is ASCII. // b'\'' is an ASCII byte. `SINGLE_QUOTE_STRING_END_TABLE` is a `SafeByteMatchTable`. - unsafe { handle_string_literal!(self, b'\'', SINGLE_QUOTE_STRING_END_TABLE) } + unsafe { + handle_string_literal!( + self, + b'\'', + SINGLE_QUOTE_STRING_END_TABLE, + SINGLE_QUOTE_ESCAPED_MATCH_TABLE + ) + } } /// Save the string if it is escaped diff --git a/crates/oxc_parser/src/lexer/token.rs b/crates/oxc_parser/src/lexer/token.rs index 21a0bd6879e46..0ac7f60244047 100644 --- a/crates/oxc_parser/src/lexer/token.rs +++ b/crates/oxc_parser/src/lexer/token.rs @@ -26,8 +26,8 @@ pub struct Token { /// [Lexer::escaped_templates]: [super::Lexer::escaped_templates] pub escaped: bool, - /// True if a string contains lossy replacement character (U+FFFD). - pub lossy: bool, + /// True if a string contains lone surrogates. + pub lone_surrogates: bool, /// True if for numeric literal tokens that contain separator characters (`_`). /// diff --git a/crates/oxc_parser/src/lexer/unicode.rs b/crates/oxc_parser/src/lexer/unicode.rs index 131d43151036b..20667a9111044 100644 --- a/crates/oxc_parser/src/lexer/unicode.rs +++ b/crates/oxc_parser/src/lexer/unicode.rs @@ -1,3 +1,7 @@ +use std::{borrow::Cow, fmt::Write}; + +use cow_utils::CowUtils; + use oxc_allocator::String; use oxc_syntax::identifier::{ CR, FF, LF, LS, PS, TAB, VT, is_identifier_part, is_identifier_start, @@ -8,13 +12,19 @@ use crate::diagnostics; use super::{Kind, Lexer, Span}; -enum SurrogatePair { - // valid \u Hex4Digits \u Hex4Digits - Astral(u32), - // valid \u Hex4Digits - CodePoint(u32), - // invalid \u Hex4Digits \u Hex4Digits - HighLow(u32, u32), +/// A Unicode escape sequence. +/// +/// `\u Hex4Digits`, `\u Hex4Digits \u Hex4Digits`, or `\u{ HexDigits }`. +enum UnicodeEscape { + // `\u Hex4Digits` or `\u{ HexDigits }`, which forms a valid Unicode code point. + // Char cannot be in range 0xD800..=0xDFFF. + CodePoint(char), + // `\u Hex4Digits \u Hex4Digits`, which forms a valid Unicode astral code point. + // Char is in the range 0x10000..=0x10FFFF. + SurrogatePair(char), + // `\u Hex4Digits` or `\u{ HexDigits }`, which forms an invalid Unicode code point. + // Code unit is in the range 0xD800..=0xDFFF. + LoneSurrogate(u32), } impl<'a> Lexer<'a> { @@ -69,7 +79,7 @@ impl<'a> Lexer<'a> { self.consume_char(); self.unicode_code_point() } - _ => self.surrogate_pair(), + _ => self.unicode_code_unit(), }; let Some(value) = value else { @@ -80,20 +90,12 @@ impl<'a> Lexer<'a> { // For Identifiers, surrogate pair is an invalid grammar, e.g. `var \uD800\uDEA7`. let ch = match value { - SurrogatePair::Astral(..) | SurrogatePair::HighLow(..) => { + UnicodeEscape::CodePoint(ch) => ch, + UnicodeEscape::SurrogatePair(_) | UnicodeEscape::LoneSurrogate(_) => { let range = Span::new(start, self.offset()); self.error(diagnostics::unicode_escape_sequence(range)); return; } - SurrogatePair::CodePoint(code_point) => { - if let Ok(ch) = char::try_from(code_point) { - ch - } else { - let range = Span::new(start, self.offset()); - self.error(diagnostics::unicode_escape_sequence(range)); - return; - } - } }; let is_valid = @@ -121,7 +123,7 @@ impl<'a> Lexer<'a> { self.consume_char(); self.unicode_code_point() } - _ => self.surrogate_pair(), + _ => self.unicode_code_unit(), }; let Some(value) = value else { @@ -132,32 +134,47 @@ impl<'a> Lexer<'a> { // For strings and templates, surrogate pairs are valid grammar, e.g. `"\uD83D\uDE00" === 😀`. match value { - SurrogatePair::CodePoint(code_point) | SurrogatePair::Astral(code_point) => { - if let Ok(ch) = char::try_from(code_point) { - text.push(ch); - } else { - // Turns lone surrogate into lossy replacement character (U+FFFD). - // A lone surrogate '\u{df06}' is not a valid UTF8 string. - text.push_str("\u{FFFD}"); - self.token.lossy = true; - } + UnicodeEscape::CodePoint(ch) | UnicodeEscape::SurrogatePair(ch) => { + text.push(ch); } - SurrogatePair::HighLow(_high, _low) => { - text.push_str("\u{FFFD}\u{FFFD}"); - self.token.lossy = true; + UnicodeEscape::LoneSurrogate(code_point) => { + self.string_lone_surrogate(code_point, text); } } } + /// Lone surrogate found in string. + fn string_lone_surrogate(&mut self, code_point: u32, text: &mut String<'a>) { + debug_assert!(code_point <= 0xFFFF); + + if !self.token.lone_surrogates { + self.token.lone_surrogates = true; + + // We use `\u{FFFD}` (the lossy replacement character) as a marker indicating the start + // of a lone surrogate. e.g. `\u{FFFD}d800` (which will be output as `\ud800`). + // So we need to escape any actual lossy replacement characters in the string so far. + // + // This could be more efficient, avoiding allocating a temporary `String`. + // But strings containing both lone surrogates and lossy replacement characters + // should be vanishingly rare, so don't bother. + if let Cow::Owned(replaced) = text.cow_replace("\u{FFFD}", "\u{FFFD}fffd") { + *text = String::from_str_in(&replaced, self.allocator); + } + } + + // Encode lone surrogate as `\u{FFFD}XXXX` where XXXX is the code point as hex + write!(text, "\u{FFFD}{code_point:04x}").unwrap(); + } + /// Decode unicode code point (`\u{ HexBytes }`). /// /// The opening `\u{` must already have been consumed before calling this method. - fn unicode_code_point(&mut self) -> Option { + fn unicode_code_point(&mut self) -> Option { let value = self.code_point()?; if !self.next_ascii_byte_eq(b'}') { return None; } - Some(SurrogatePair::CodePoint(value)) + Some(value) } fn hex_4_digits(&mut self) -> Option { @@ -195,7 +212,7 @@ impl<'a> Lexer<'a> { Some(u32::from(value)) } - fn code_point(&mut self) -> Option { + fn code_point(&mut self) -> Option { let mut value = self.hex_digit()?; while let Some(next) = self.hex_digit() { value = (value << 4) | next; @@ -203,38 +220,78 @@ impl<'a> Lexer<'a> { return None; } } - Some(value) + + match char::from_u32(value) { + Some(ch) => Some(UnicodeEscape::CodePoint(ch)), + None => Some(UnicodeEscape::LoneSurrogate(value)), + } } - /// Surrogate pairs - /// See background info: + /// Unicode code unit (`\uXXXX`). + /// + /// The opening `\u` must already have been consumed before calling this method. + /// + /// See background info on surrogate pairs: /// * `https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae` /// * `https://mathiasbynens.be/notes/javascript-identifiers-es6` - fn surrogate_pair(&mut self) -> Option { + fn unicode_code_unit(&mut self) -> Option { + const MIN_HIGH: u32 = 0xD800; + const MAX_HIGH: u32 = 0xDBFF; + const MIN_LOW: u32 = 0xDC00; + const MAX_LOW: u32 = 0xDFFF; + + // `https://tc39.es/ecma262/#sec-utf16decodesurrogatepair` + #[inline] + const fn pair_to_code_point(high: u32, low: u32) -> u32 { + (high - 0xD800) * 0x400 + low - 0xDC00 + 0x10000 + } + + const _: () = { + assert!(char::from_u32(pair_to_code_point(MIN_HIGH, MIN_LOW)).is_some()); + assert!(char::from_u32(pair_to_code_point(MIN_HIGH, MAX_LOW)).is_some()); + assert!(char::from_u32(pair_to_code_point(MAX_HIGH, MIN_LOW)).is_some()); + assert!(char::from_u32(pair_to_code_point(MAX_HIGH, MAX_LOW)).is_some()); + }; + let high = self.hex_4_digits()?; + if let Some(ch) = char::from_u32(high) { + return Some(UnicodeEscape::CodePoint(ch)); + } + // The first code unit of a surrogate pair is always in the range from 0xD800 to 0xDBFF, // and is called a high surrogate or a lead surrogate. - let is_pair = - (0xD800..=0xDBFF).contains(&high) && self.peek_2_bytes() == Some([b'\\', b'u']); + // Note: `high` must be >= `MIN_HIGH`, otherwise `char::from_u32` would have returned `Some`, + // and already exited. + debug_assert!(high >= MIN_HIGH); + let is_pair = high <= MAX_HIGH && self.peek_2_bytes() == Some([b'\\', b'u']); if !is_pair { - return Some(SurrogatePair::CodePoint(high)); + return Some(UnicodeEscape::LoneSurrogate(high)); } - // We checked above that next 2 chars are `\u` - self.consume_2_chars(); + let before_second = self.source.position(); + + // SAFETY: We checked above that next 2 chars are `\u` + unsafe { + self.source.next_byte_unchecked(); + self.source.next_byte_unchecked(); + } let low = self.hex_4_digits()?; // The second code unit of a surrogate pair is always in the range from 0xDC00 to 0xDFFF, // and is called a low surrogate or a trail surrogate. - if !(0xDC00..=0xDFFF).contains(&low) { - return Some(SurrogatePair::HighLow(high, low)); + // If this isn't a valid pair, rewind to before the 2nd, and return the first only. + // The 2nd could be the first part of a valid pair. + if !(MIN_LOW..=MAX_LOW).contains(&low) { + self.source.set_position(before_second); + return Some(UnicodeEscape::LoneSurrogate(high)); } - // `https://tc39.es/ecma262/#sec-utf16decodesurrogatepair` - let astral_code_point = (high - 0xD800) * 0x400 + low - 0xDC00 + 0x10000; - - Some(SurrogatePair::Astral(astral_code_point)) + let code_point = pair_to_code_point(high, low); + // SAFETY: `high` and `low` have been checked to be in ranges which always yield a `code_point` + // which is a valid `char` + let ch = unsafe { char::from_u32_unchecked(code_point) }; + Some(UnicodeEscape::SurrogatePair(ch)) } // EscapeSequence :: diff --git a/napi/parser/deserialize-js.js b/napi/parser/deserialize-js.js index 5d619163be434..681690ec1a428 100644 --- a/napi/parser/deserialize-js.js +++ b/napi/parser/deserialize-js.js @@ -1061,14 +1061,16 @@ function deserializeNumericLiteral(pos) { } function deserializeStringLiteral(pos) { - const raw = deserializeOptionStr(pos + 24); - const lossy = deserializeBool(pos + 40); + let value = deserializeStr(pos + 8); + if (deserializeBool(pos + 40)) { + value = value.replace(/\uFFFD(.{4})/g, (_, hex) => String.fromCodePoint(parseInt(hex, 16))); + } return { type: 'Literal', start: deserializeU32(pos), end: deserializeU32(pos + 4), - value: (lossy && raw !== null) ? (0, eval)(raw) : deserializeStr(pos + 8), - raw, + value, + raw: deserializeOptionStr(pos + 24), }; } diff --git a/napi/parser/deserialize-ts.js b/napi/parser/deserialize-ts.js index 9a4cb15d20b7e..dca1bf8992122 100644 --- a/napi/parser/deserialize-ts.js +++ b/napi/parser/deserialize-ts.js @@ -1126,14 +1126,16 @@ function deserializeNumericLiteral(pos) { } function deserializeStringLiteral(pos) { - const raw = deserializeOptionStr(pos + 24); - const lossy = deserializeBool(pos + 40); + let value = deserializeStr(pos + 8); + if (deserializeBool(pos + 40)) { + value = value.replace(/\uFFFD(.{4})/g, (_, hex) => String.fromCodePoint(parseInt(hex, 16))); + } return { type: 'Literal', start: deserializeU32(pos), end: deserializeU32(pos + 4), - value: (lossy && raw !== null) ? (0, eval)(raw) : deserializeStr(pos + 8), - raw, + value, + raw: deserializeOptionStr(pos + 24), }; } diff --git a/tasks/coverage/snapshots/estree_test262.snap b/tasks/coverage/snapshots/estree_test262.snap index 31d5fe6c077d9..9551cc82385c3 100644 --- a/tasks/coverage/snapshots/estree_test262.snap +++ b/tasks/coverage/snapshots/estree_test262.snap @@ -2,37 +2,13 @@ commit: bc5c1417 estree_test262 Summary: AST Parsed : 44047/44047 (100.00%) -Positive Passed: 44014/44047 (99.93%) -Mismatch: tasks/coverage/test262/test/built-ins/Array/prototype/concat/Array.prototype.concat_spreadable-string-wrapper.js -Mismatch: tasks/coverage/test262/test/built-ins/JSON/stringify/value-string-escape-unicode.js -Mismatch: tasks/coverage/test262/test/built-ins/RegExp/dotall/with-dotall-unicode.js -Mismatch: tasks/coverage/test262/test/built-ins/RegExp/dotall/with-dotall.js -Mismatch: tasks/coverage/test262/test/built-ins/RegExp/dotall/without-dotall-unicode.js -Mismatch: tasks/coverage/test262/test/built-ins/RegExp/dotall/without-dotall.js -Mismatch: tasks/coverage/test262/test/built-ins/RegExp/escape/escaped-surrogates.js -Mismatch: tasks/coverage/test262/test/built-ins/RegExp/regexp-modifiers/add-dotAll.js -Mismatch: tasks/coverage/test262/test/built-ins/RegExp/regexp-modifiers/changing-dotAll-flag-does-not-affect-dotAll-modifier.js -Mismatch: tasks/coverage/test262/test/built-ins/RegExp/regexp-modifiers/nesting-add-dotAll-within-remove-dotAll.js -Mismatch: tasks/coverage/test262/test/built-ins/RegExp/regexp-modifiers/nesting-remove-dotAll-within-add-dotAll.js -Mismatch: tasks/coverage/test262/test/built-ins/RegExp/regexp-modifiers/remove-dotAll.js -Mismatch: tasks/coverage/test262/test/built-ins/String/prototype/at/returns-code-unit.js -Mismatch: tasks/coverage/test262/test/built-ins/String/prototype/codePointAt/return-first-code-unit.js -Mismatch: tasks/coverage/test262/test/built-ins/String/prototype/codePointAt/return-single-code-unit.js -Mismatch: tasks/coverage/test262/test/built-ins/String/prototype/isWellFormed/returns-boolean.js -Mismatch: tasks/coverage/test262/test/built-ins/String/prototype/match/regexp-prototype-match-v-u-flag.js -Mismatch: tasks/coverage/test262/test/built-ins/String/prototype/padEnd/normal-operation.js -Mismatch: tasks/coverage/test262/test/built-ins/String/prototype/padStart/normal-operation.js -Mismatch: tasks/coverage/test262/test/built-ins/String/prototype/toWellFormed/returns-well-formed-string.js -Mismatch: tasks/coverage/test262/test/built-ins/StringIteratorPrototype/next/next-iteration-surrogate-pairs.js -Mismatch: tasks/coverage/test262/test/intl402/NumberFormat/prototype/format/format-non-finite-numbers.js +Positive Passed: 44038/44047 (99.98%) Mismatch: tasks/coverage/test262/test/language/expressions/assignment/fn-name-lhs-cover.js Mismatch: tasks/coverage/test262/test/language/expressions/assignment/target-cover-id.js Mismatch: tasks/coverage/test262/test/language/expressions/postfix-decrement/target-cover-id.js Mismatch: tasks/coverage/test262/test/language/expressions/postfix-increment/target-cover-id.js Mismatch: tasks/coverage/test262/test/language/expressions/prefix-decrement/target-cover-id.js Mismatch: tasks/coverage/test262/test/language/expressions/prefix-increment/target-cover-id.js -Mismatch: tasks/coverage/test262/test/language/literals/regexp/named-groups/invalid-lone-surrogate-groupname.js -Mismatch: tasks/coverage/test262/test/language/literals/regexp/u-surrogate-pairs-atom-escape-decimal.js Mismatch: tasks/coverage/test262/test/language/statements/for-in/head-lhs-cover.js Mismatch: tasks/coverage/test262/test/language/statements/for-of/head-lhs-async-parens.js Mismatch: tasks/coverage/test262/test/language/statements/for-of/head-lhs-cover.js diff --git a/tasks/coverage/snapshots/estree_typescript.snap b/tasks/coverage/snapshots/estree_typescript.snap index a16ef821a956a..ce83f499cbda7 100644 --- a/tasks/coverage/snapshots/estree_typescript.snap +++ b/tasks/coverage/snapshots/estree_typescript.snap @@ -4717,10 +4717,10 @@ Mismatch: tasks/coverage/typescript/tests/cases/conformance/es6/unicodeExtendedE Mismatch: tasks/coverage/typescript/tests/cases/conformance/es6/unicodeExtendedEscapes/unicodeExtendedEscapesInStrings08.ts Mismatch: tasks/coverage/typescript/tests/cases/conformance/es6/unicodeExtendedEscapes/unicodeExtendedEscapesInStrings09.ts tasks/coverage/typescript/tests/cases/conformance/es6/unicodeExtendedEscapes/unicodeExtendedEscapesInStrings10.ts -serde_json::from_str(oxc_json) error: invalid escape at line 30 column 28 +serde_json::from_str(oxc_json) error: unexpected end of hex escape at line 30 column 29 tasks/coverage/typescript/tests/cases/conformance/es6/unicodeExtendedEscapes/unicodeExtendedEscapesInStrings11.ts -serde_json::from_str(oxc_json) error: invalid escape at line 30 column 28 +serde_json::from_str(oxc_json) error: lone leading surrogate in hex escape at line 30 column 28 Mismatch: tasks/coverage/typescript/tests/cases/conformance/es6/unicodeExtendedEscapes/unicodeExtendedEscapesInStrings13.ts Mismatch: tasks/coverage/typescript/tests/cases/conformance/es6/unicodeExtendedEscapes/unicodeExtendedEscapesInStrings15.ts diff --git a/tasks/coverage/snapshots/parser_test262.snap b/tasks/coverage/snapshots/parser_test262.snap index e7b1a8ec20e71..38e1a9ce85bad 100644 --- a/tasks/coverage/snapshots/parser_test262.snap +++ b/tasks/coverage/snapshots/parser_test262.snap @@ -23905,7 +23905,7 @@ Negative Passed: 4519/4519 (100.00%) 24 │ ╰──── - × Duplicated export '�' + × Duplicated export '�d83c' ╭─[test262/test/language/module-code/early-export-ill-formed-string.js:21:17] 20 │ // 🌙 is '\uD83C\uDF19' 21 │ export {Moon as "\uD83C",} from "./early-export-ill-formed-string.js"; diff --git a/tasks/coverage/src/tools/estree.rs b/tasks/coverage/src/tools/estree.rs index f99a130524e78..6adcb010adbe2 100644 --- a/tasks/coverage/src/tools/estree.rs +++ b/tasks/coverage/src/tools/estree.rs @@ -61,6 +61,7 @@ impl Case for EstreeTest262Case { // We don't filter them out because they are genuine test fails, but leaving this list here so // can uncomment this block when debugging any new test failures, to filter out "known bad". /* + #[expect(clippy::items_after_statements)] static IGNORE_PATHS: &[&str] = &[ // Missing `ParenthesizedExpression` on left side of assignment. // Oxc's parser does not support this, and we do not intend to fix. @@ -74,46 +75,6 @@ impl Case for EstreeTest262Case { "test262/test/language/statements/for-in/head-lhs-cover.js", "test262/test/language/statements/for-of/head-lhs-async-parens.js", "test262/test/language/statements/for-of/head-lhs-cover.js", - - // Lone surrogates in strings. - // We cannot pass these tests at present, as Oxc's parser does not handle them correctly. - // https://github.com/oxc-project/oxc/issues/3526#issuecomment-2650260735 - "test262/test/annexB/built-ins/RegExp/prototype/compile/pattern-string-u.js", - "test262/test/annexB/built-ins/String/prototype/substr/surrogate-pairs.js", - "test262/test/built-ins/Array/prototype/concat/Array.prototype.concat_spreadable-string-wrapper.js", - "test262/test/built-ins/JSON/stringify/value-string-escape-unicode.js", - "test262/test/built-ins/RegExp/dotall/with-dotall-unicode.js", - "test262/test/built-ins/RegExp/dotall/with-dotall.js", - "test262/test/built-ins/RegExp/dotall/without-dotall-unicode.js", - "test262/test/built-ins/RegExp/dotall/without-dotall.js", - "test262/test/built-ins/RegExp/escape/escaped-surrogates.js", - "test262/test/built-ins/RegExp/named-groups/non-unicode-property-names-invalid.js", - "test262/test/built-ins/RegExp/named-groups/unicode-property-names-invalid.js", - "test262/test/built-ins/RegExp/prototype/Symbol.replace/coerce-unicode.js", - "test262/test/built-ins/RegExp/prototype/exec/u-captured-value.js", - "test262/test/built-ins/RegExp/regexp-modifiers/add-dotAll.js", - "test262/test/built-ins/RegExp/regexp-modifiers/changing-dotAll-flag-does-not-affect-dotAll-modifier.js", - "test262/test/built-ins/RegExp/regexp-modifiers/nesting-add-dotAll-within-remove-dotAll.js", - "test262/test/built-ins/RegExp/regexp-modifiers/nesting-remove-dotAll-within-add-dotAll.js", - "test262/test/built-ins/RegExp/regexp-modifiers/remove-dotAll.js", - "test262/test/built-ins/String/prototype/at/returns-code-unit.js", - "test262/test/built-ins/String/prototype/codePointAt/return-first-code-unit.js", - "test262/test/built-ins/String/prototype/codePointAt/return-single-code-unit.js", - "test262/test/built-ins/String/prototype/isWellFormed/returns-boolean.js", - "test262/test/built-ins/String/prototype/match/regexp-prototype-match-v-u-flag.js", - "test262/test/built-ins/String/prototype/padEnd/normal-operation.js", - "test262/test/built-ins/String/prototype/padStart/normal-operation.js", - "test262/test/built-ins/String/prototype/toWellFormed/returns-well-formed-string.js", - "test262/test/built-ins/StringIteratorPrototype/next/next-iteration-surrogate-pairs.js", - "test262/test/intl402/NumberFormat/prototype/format/format-non-finite-numbers.js", - "test262/test/intl402/Segmenter/prototype/segment/containing/breakable-input.js", - "test262/test/intl402/Segmenter/prototype/segment/containing/unbreakable-input.js", - "test262/test/intl402/Segmenter/prototype/segment/containing/zero-index.js", - "test262/test/language/literals/regexp/named-groups/invalid-lone-surrogate-groupname.js", - "test262/test/language/literals/regexp/u-astral.js", - "test262/test/language/literals/regexp/u-surrogate-pairs-atom-char-class.js", - "test262/test/language/literals/regexp/u-surrogate-pairs-atom-escape-decimal.js", - "test262/test/language/statements/for-of/string-astral-truncated.js", ]; let path = &*self.path().to_string_lossy(); From e3a2d8a13d1cfcf8f858bd1f90be624ede4d85db Mon Sep 17 00:00:00 2001 From: overlookmotel Date: Wed, 26 Mar 2025 00:42:18 +0530 Subject: [PATCH 15/15] refactor(codegen): print string literals containing lone surrogates without reference to `raw` --- crates/oxc_codegen/src/lib.rs | 33 +++++++++++++++---- .../oxc_codegen/tests/integration/esbuild.rs | 10 +++--- crates/oxc_codegen/tests/integration/unit.rs | 2 +- 3 files changed, 32 insertions(+), 13 deletions(-) diff --git a/crates/oxc_codegen/src/lib.rs b/crates/oxc_codegen/src/lib.rs index acb413068bff7..e44f332956879 100644 --- a/crates/oxc_codegen/src/lib.rs +++ b/crates/oxc_codegen/src/lib.rs @@ -242,6 +242,12 @@ impl<'a> Codegen<'a> { self.code.print_str(s); } + /// Push `char` into the buffer. + #[inline] + pub fn print_char(&mut self, ch: char) { + self.code.print_char(ch); + } + /// Print a single [`Expression`], adding it to the code generator's /// internal buffer. Unlike [`Codegen::build`], this does not consume `self`. #[inline] @@ -578,14 +584,7 @@ impl<'a> Codegen<'a> { fn print_string_literal(&mut self, s: &StringLiteral<'_>, allow_backtick: bool) { self.add_source_mapping(s.span); - if s.lone_surrogates { - self.print_str(s.raw.unwrap().as_str()); - return; - } - self.print_quoted_utf16(s, allow_backtick); - } - fn print_quoted_utf16(&mut self, s: &StringLiteral<'_>, allow_backtick: bool) { let quote = if self.options.minify { let mut single_cost: i32 = 0; let mut double_cost: i32 = 0; @@ -680,6 +679,26 @@ impl<'a> Codegen<'a> { } self.print_ascii_byte(b'$'); } + '\u{FFFD}' if s.lone_surrogates => { + // If `lone_surrogates` is set, string contains lone surrogates which are escaped + // using the lossy replacement character (U+FFFD) as an escape marker. + // The lone surrogate is encoded as `\u{FFFD}XXXX` where `XXXX` is the code point as hex. + let hex1 = chars.next().unwrap(); + let hex2 = chars.next().unwrap(); + let hex3 = chars.next().unwrap(); + let hex4 = chars.next().unwrap(); + if [hex1, hex2, hex3, hex4] == ['f', 'f', 'f', 'd'] { + // Actual lossy replacement character + self.print_char('\u{FFFD}'); + } else { + // Lossy replacement character representing a lone surrogate + self.print_str("\\u"); + self.print_char(hex1); + self.print_char(hex2); + self.print_char(hex3); + self.print_char(hex4); + } + } _ => self.print_str(c.encode_utf8([0; 4].as_mut())), } } diff --git a/crates/oxc_codegen/tests/integration/esbuild.rs b/crates/oxc_codegen/tests/integration/esbuild.rs index 172f0290475be..6e75a376d4939 100644 --- a/crates/oxc_codegen/tests/integration/esbuild.rs +++ b/crates/oxc_codegen/tests/integration/esbuild.rs @@ -363,15 +363,15 @@ fn test_string() { test("let x = '\\U000123AB'", "let x = \"U000123AB\";\n"); test("let x = '\\u{123AB}'", "let x = \"\u{123ab}\";\n"); test("let x = '\\uD808\\uDFAB'", "let x = \"\u{123ab}\";\n"); - test("let x = '\\uD808'", "let x = '\\uD808';\n"); // lone surrogate - test("let x = '\\uD808X'", "let x = '\\uD808X';\n"); - test("let x = '\\uDFAB'", "let x = '\\uDFAB';\n"); - test("let x = '\\uDFABX'", "let x = '\\uDFABX';\n"); + test("let x = '\\uD808'", "let x = \"\\ud808\";\n"); // lone surrogate + test("let x = '\\uD808X'", "let x = \"\\ud808X\";\n"); + test("let x = '\\uDFAB'", "let x = \"\\udfab\";\n"); + test("let x = '\\uDFABX'", "let x = \"\\udfabX\";\n"); test("let x = '\\x80'", "let x = \"\u{80}\";\n"); test("let x = '\\xFF'", "let x = \"ÿ\";\n"); test("let x = '\\xF0\\x9F\\x8D\\x95'", "let x = \"ð\u{9f}\u{8d}\u{95}\";\n"); - test("let x = '\\uD801\\uDC02\\uDC03\\uD804'", "let x = '\\uD801\\uDC02\\uDC03\\uD804';\n"); // lossy + test("let x = '\\uD801\\uDC02\\uDC03\\uD804'", "let x = \"𐐂\\udc03\\ud804\";\n"); // surrogates } #[test] diff --git a/crates/oxc_codegen/tests/integration/unit.rs b/crates/oxc_codegen/tests/integration/unit.rs index 567949256d029..d66dfbf3bf81e 100644 --- a/crates/oxc_codegen/tests/integration/unit.rs +++ b/crates/oxc_codegen/tests/integration/unit.rs @@ -143,7 +143,7 @@ fn unicode_escape() { test("console.log('こんにちは');", "console.log(\"こんにちは\");\n"); test("console.log('안녕하세요');", "console.log(\"안녕하세요\");\n"); test("console.log('🧑‍🤝‍🧑');", "console.log(\"🧑‍🤝‍🧑\");\n"); - test("console.log(\"\\uD800\\uD801\")", "console.log(\"\\uD800\\uD801\");\n"); + test("console.log(\"\\uD800\\uD801\")", "console.log(\"\\ud800\\ud801\");\n"); } #[test]