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!
---
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]