mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 04:08:41 +00:00
fix(ast): visit Programs hashbang field first (#4368)
Visit `hashbang` before `directives` for `Program`.
This commit is contained in:
parent
6ffce865d1
commit
aece1df561
8 changed files with 88 additions and 88 deletions
|
|
@ -39,8 +39,8 @@ pub struct Program<'a> {
|
|||
#[cfg_attr(feature = "serialize", serde(flatten))]
|
||||
pub span: Span,
|
||||
pub source_type: SourceType,
|
||||
pub directives: Vec<'a, Directive<'a>>,
|
||||
pub hashbang: Option<Hashbang<'a>>,
|
||||
pub directives: Vec<'a, Directive<'a>>,
|
||||
pub body: Vec<'a, Statement<'a>>,
|
||||
pub scope_id: Cell<Option<ScopeId>>,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -136,11 +136,11 @@ impl<'a> AstBuilder<'a> {
|
|||
self,
|
||||
span: Span,
|
||||
source_type: SourceType,
|
||||
directives: Vec<'a, Directive<'a>>,
|
||||
hashbang: Option<Hashbang<'a>>,
|
||||
directives: Vec<'a, Directive<'a>>,
|
||||
body: Vec<'a, Statement<'a>>,
|
||||
) -> Program<'a> {
|
||||
Program { span, source_type, directives, hashbang, body, scope_id: Default::default() }
|
||||
Program { span, source_type, hashbang, directives, body, scope_id: Default::default() }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
@ -148,11 +148,11 @@ impl<'a> AstBuilder<'a> {
|
|||
self,
|
||||
span: Span,
|
||||
source_type: SourceType,
|
||||
directives: Vec<'a, Directive<'a>>,
|
||||
hashbang: Option<Hashbang<'a>>,
|
||||
directives: Vec<'a, Directive<'a>>,
|
||||
body: Vec<'a, Statement<'a>>,
|
||||
) -> Box<'a, Program<'a>> {
|
||||
self.program(span, source_type, directives, hashbang, body).into_in(self.allocator)
|
||||
self.program(span, source_type, hashbang, directives, body).into_in(self.allocator)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
|
|||
|
|
@ -50,6 +50,11 @@ pub trait Visit<'a>: Sized {
|
|||
walk_program(self, it);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_hashbang(&mut self, it: &Hashbang<'a>) {
|
||||
walk_hashbang(self, it);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_directives(&mut self, it: &Vec<'a, Directive<'a>>) {
|
||||
walk_directives(self, it);
|
||||
|
|
@ -65,11 +70,6 @@ pub trait Visit<'a>: Sized {
|
|||
walk_string_literal(self, it);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_hashbang(&mut self, it: &Hashbang<'a>) {
|
||||
walk_hashbang(self, it);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_statements(&mut self, it: &Vec<'a, Statement<'a>>) {
|
||||
walk_statements(self, it);
|
||||
|
|
@ -1366,15 +1366,22 @@ pub mod walk {
|
|||
},
|
||||
&it.scope_id,
|
||||
);
|
||||
visitor.visit_directives(&it.directives);
|
||||
if let Some(hashbang) = &it.hashbang {
|
||||
visitor.visit_hashbang(hashbang);
|
||||
}
|
||||
visitor.visit_directives(&it.directives);
|
||||
visitor.visit_statements(&it.body);
|
||||
visitor.leave_scope();
|
||||
visitor.leave_node(kind);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn walk_hashbang<'a, V: Visit<'a>>(visitor: &mut V, it: &Hashbang<'a>) {
|
||||
let kind = AstKind::Hashbang(visitor.alloc(it));
|
||||
visitor.enter_node(kind);
|
||||
visitor.leave_node(kind);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn walk_directives<'a, V: Visit<'a>>(visitor: &mut V, it: &Vec<'a, Directive<'a>>) {
|
||||
for el in it.iter() {
|
||||
|
|
@ -1397,13 +1404,6 @@ pub mod walk {
|
|||
visitor.leave_node(kind);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn walk_hashbang<'a, V: Visit<'a>>(visitor: &mut V, it: &Hashbang<'a>) {
|
||||
let kind = AstKind::Hashbang(visitor.alloc(it));
|
||||
visitor.enter_node(kind);
|
||||
visitor.leave_node(kind);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn walk_statements<'a, V: Visit<'a>>(visitor: &mut V, it: &Vec<'a, Statement<'a>>) {
|
||||
for el in it.iter() {
|
||||
|
|
|
|||
|
|
@ -42,6 +42,11 @@ pub trait VisitMut<'a>: Sized {
|
|||
walk_program(self, it);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_hashbang(&mut self, it: &mut Hashbang<'a>) {
|
||||
walk_hashbang(self, it);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_directives(&mut self, it: &mut Vec<'a, Directive<'a>>) {
|
||||
walk_directives(self, it);
|
||||
|
|
@ -57,11 +62,6 @@ pub trait VisitMut<'a>: Sized {
|
|||
walk_string_literal(self, it);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_hashbang(&mut self, it: &mut Hashbang<'a>) {
|
||||
walk_hashbang(self, it);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_statements(&mut self, it: &mut Vec<'a, Statement<'a>>) {
|
||||
walk_statements(self, it);
|
||||
|
|
@ -1361,15 +1361,22 @@ pub mod walk_mut {
|
|||
},
|
||||
&it.scope_id,
|
||||
);
|
||||
visitor.visit_directives(&mut it.directives);
|
||||
if let Some(hashbang) = &mut it.hashbang {
|
||||
visitor.visit_hashbang(hashbang);
|
||||
}
|
||||
visitor.visit_directives(&mut it.directives);
|
||||
visitor.visit_statements(&mut it.body);
|
||||
visitor.leave_scope();
|
||||
visitor.leave_node(kind);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn walk_hashbang<'a, V: VisitMut<'a>>(visitor: &mut V, it: &mut Hashbang<'a>) {
|
||||
let kind = AstType::Hashbang;
|
||||
visitor.enter_node(kind);
|
||||
visitor.leave_node(kind);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn walk_directives<'a, V: VisitMut<'a>>(visitor: &mut V, it: &mut Vec<'a, Directive<'a>>) {
|
||||
for el in it.iter_mut() {
|
||||
|
|
@ -1392,13 +1399,6 @@ pub mod walk_mut {
|
|||
visitor.leave_node(kind);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn walk_hashbang<'a, V: VisitMut<'a>>(visitor: &mut V, it: &mut Hashbang<'a>) {
|
||||
let kind = AstType::Hashbang;
|
||||
visitor.enter_node(kind);
|
||||
visitor.leave_node(kind);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn walk_statements<'a, V: VisitMut<'a>>(visitor: &mut V, it: &mut Vec<'a, Statement<'a>>) {
|
||||
for el in it.iter_mut() {
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
let source_type = SourceType::default().with_module(true).with_typescript_definition(true);
|
||||
let directives = self.ast.vec();
|
||||
let stmts = self.transform_program(program);
|
||||
let program = self.ast.program(SPAN, source_type, directives, None, stmts);
|
||||
let program = self.ast.program(SPAN, source_type, None, directives, stmts);
|
||||
IsolatedDeclarationsReturn { program, errors: self.take_errors() }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -328,9 +328,9 @@ impl<'a> ParserImpl<'a> {
|
|||
let program = self.ast.program(
|
||||
Span::default(),
|
||||
self.source_type,
|
||||
self.ast.vec(),
|
||||
None,
|
||||
self.ast.vec(),
|
||||
self.ast.vec(),
|
||||
);
|
||||
(program, true)
|
||||
}
|
||||
|
|
@ -361,7 +361,7 @@ impl<'a> ParserImpl<'a> {
|
|||
self.parse_directives_and_statements(/* is_top_level */ true)?;
|
||||
|
||||
let span = Span::new(0, self.source_text.len() as u32);
|
||||
Ok(self.ast.program(span, self.source_type, directives, hashbang, statements))
|
||||
Ok(self.ast.program(span, self.source_type, hashbang, directives, statements))
|
||||
}
|
||||
|
||||
fn default_context(source_type: SourceType, options: ParserOptions) -> Context {
|
||||
|
|
|
|||
|
|
@ -30,8 +30,8 @@ use oxc_syntax::{
|
|||
#[allow(dead_code)]
|
||||
pub(crate) enum AncestorType {
|
||||
None = 0,
|
||||
ProgramDirectives = 1,
|
||||
ProgramHashbang = 2,
|
||||
ProgramHashbang = 1,
|
||||
ProgramDirectives = 2,
|
||||
ProgramBody = 3,
|
||||
ArrayExpressionElements = 4,
|
||||
ObjectExpressionProperties = 5,
|
||||
|
|
@ -343,8 +343,8 @@ pub(crate) enum AncestorType {
|
|||
#[derive(Debug)]
|
||||
pub enum Ancestor<'a> {
|
||||
None = AncestorType::None as u16,
|
||||
ProgramDirectives(ProgramWithoutDirectives<'a>) = AncestorType::ProgramDirectives as u16,
|
||||
ProgramHashbang(ProgramWithoutHashbang<'a>) = AncestorType::ProgramHashbang as u16,
|
||||
ProgramDirectives(ProgramWithoutDirectives<'a>) = AncestorType::ProgramDirectives as u16,
|
||||
ProgramBody(ProgramWithoutBody<'a>) = AncestorType::ProgramBody as u16,
|
||||
ArrayExpressionElements(ArrayExpressionWithoutElements<'a>) =
|
||||
AncestorType::ArrayExpressionElements as u16,
|
||||
|
|
@ -872,7 +872,7 @@ pub enum Ancestor<'a> {
|
|||
impl<'a> Ancestor<'a> {
|
||||
#[inline]
|
||||
pub fn is_program(&self) -> bool {
|
||||
matches!(self, Self::ProgramDirectives(_) | Self::ProgramHashbang(_) | Self::ProgramBody(_))
|
||||
matches!(self, Self::ProgramHashbang(_) | Self::ProgramDirectives(_) | Self::ProgramBody(_))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
@ -2178,48 +2178,11 @@ impl<'a> Ancestor<'a> {
|
|||
|
||||
pub(crate) const OFFSET_PROGRAM_SPAN: usize = offset_of!(Program, span);
|
||||
pub(crate) const OFFSET_PROGRAM_SOURCE_TYPE: usize = offset_of!(Program, source_type);
|
||||
pub(crate) const OFFSET_PROGRAM_DIRECTIVES: usize = offset_of!(Program, directives);
|
||||
pub(crate) const OFFSET_PROGRAM_HASHBANG: usize = offset_of!(Program, hashbang);
|
||||
pub(crate) const OFFSET_PROGRAM_DIRECTIVES: usize = offset_of!(Program, directives);
|
||||
pub(crate) const OFFSET_PROGRAM_BODY: usize = offset_of!(Program, body);
|
||||
pub(crate) const OFFSET_PROGRAM_SCOPE_ID: usize = offset_of!(Program, scope_id);
|
||||
|
||||
#[repr(transparent)]
|
||||
#[derive(Debug)]
|
||||
pub struct ProgramWithoutDirectives<'a>(pub(crate) *const Program<'a>);
|
||||
|
||||
impl<'a> ProgramWithoutDirectives<'a> {
|
||||
#[inline]
|
||||
pub fn span(&self) -> &Span {
|
||||
unsafe { &*((self.0 as *const u8).add(OFFSET_PROGRAM_SPAN) as *const Span) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn source_type(&self) -> &SourceType {
|
||||
unsafe { &*((self.0 as *const u8).add(OFFSET_PROGRAM_SOURCE_TYPE) as *const SourceType) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn hashbang(&self) -> &Option<Hashbang<'a>> {
|
||||
unsafe {
|
||||
&*((self.0 as *const u8).add(OFFSET_PROGRAM_HASHBANG) as *const Option<Hashbang<'a>>)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn body(&self) -> &Vec<'a, Statement<'a>> {
|
||||
unsafe {
|
||||
&*((self.0 as *const u8).add(OFFSET_PROGRAM_BODY) as *const Vec<'a, Statement<'a>>)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn scope_id(&self) -> &Cell<Option<ScopeId>> {
|
||||
unsafe {
|
||||
&*((self.0 as *const u8).add(OFFSET_PROGRAM_SCOPE_ID) as *const Cell<Option<ScopeId>>)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(transparent)]
|
||||
#[derive(Debug)]
|
||||
pub struct ProgramWithoutHashbang<'a>(pub(crate) *const Program<'a>);
|
||||
|
|
@ -2258,6 +2221,43 @@ impl<'a> ProgramWithoutHashbang<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
#[repr(transparent)]
|
||||
#[derive(Debug)]
|
||||
pub struct ProgramWithoutDirectives<'a>(pub(crate) *const Program<'a>);
|
||||
|
||||
impl<'a> ProgramWithoutDirectives<'a> {
|
||||
#[inline]
|
||||
pub fn span(&self) -> &Span {
|
||||
unsafe { &*((self.0 as *const u8).add(OFFSET_PROGRAM_SPAN) as *const Span) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn source_type(&self) -> &SourceType {
|
||||
unsafe { &*((self.0 as *const u8).add(OFFSET_PROGRAM_SOURCE_TYPE) as *const SourceType) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn hashbang(&self) -> &Option<Hashbang<'a>> {
|
||||
unsafe {
|
||||
&*((self.0 as *const u8).add(OFFSET_PROGRAM_HASHBANG) as *const Option<Hashbang<'a>>)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn body(&self) -> &Vec<'a, Statement<'a>> {
|
||||
unsafe {
|
||||
&*((self.0 as *const u8).add(OFFSET_PROGRAM_BODY) as *const Vec<'a, Statement<'a>>)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn scope_id(&self) -> &Cell<Option<ScopeId>> {
|
||||
unsafe {
|
||||
&*((self.0 as *const u8).add(OFFSET_PROGRAM_SCOPE_ID) as *const Cell<Option<ScopeId>>)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(transparent)]
|
||||
#[derive(Debug)]
|
||||
pub struct ProgramWithoutBody<'a>(pub(crate) *const Program<'a>);
|
||||
|
|
@ -2274,17 +2274,17 @@ impl<'a> ProgramWithoutBody<'a> {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn directives(&self) -> &Vec<'a, Directive<'a>> {
|
||||
pub fn hashbang(&self) -> &Option<Hashbang<'a>> {
|
||||
unsafe {
|
||||
&*((self.0 as *const u8).add(OFFSET_PROGRAM_DIRECTIVES)
|
||||
as *const Vec<'a, Directive<'a>>)
|
||||
&*((self.0 as *const u8).add(OFFSET_PROGRAM_HASHBANG) as *const Option<Hashbang<'a>>)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn hashbang(&self) -> &Option<Hashbang<'a>> {
|
||||
pub fn directives(&self) -> &Vec<'a, Directive<'a>> {
|
||||
unsafe {
|
||||
&*((self.0 as *const u8).add(OFFSET_PROGRAM_HASHBANG) as *const Option<Hashbang<'a>>)
|
||||
&*((self.0 as *const u8).add(OFFSET_PROGRAM_DIRECTIVES)
|
||||
as *const Vec<'a, Directive<'a>>)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -37,19 +37,19 @@ pub(crate) unsafe fn walk_program<'a, Tr: Traverse<'a>>(
|
|||
ctx.set_current_scope_id(scope_id);
|
||||
}
|
||||
traverser.enter_program(&mut *node, ctx);
|
||||
ctx.push_stack(Ancestor::ProgramDirectives(ancestor::ProgramWithoutDirectives(node)));
|
||||
ctx.push_stack(Ancestor::ProgramHashbang(ancestor::ProgramWithoutHashbang(node)));
|
||||
if let Some(field) =
|
||||
&mut *((node as *mut u8).add(ancestor::OFFSET_PROGRAM_HASHBANG) as *mut Option<Hashbang>)
|
||||
{
|
||||
walk_hashbang(traverser, field as *mut _, ctx);
|
||||
}
|
||||
ctx.retag_stack(AncestorType::ProgramDirectives);
|
||||
for item in (*((node as *mut u8).add(ancestor::OFFSET_PROGRAM_DIRECTIVES)
|
||||
as *mut Vec<Directive>))
|
||||
.iter_mut()
|
||||
{
|
||||
walk_directive(traverser, item as *mut _, ctx);
|
||||
}
|
||||
if let Some(field) =
|
||||
&mut *((node as *mut u8).add(ancestor::OFFSET_PROGRAM_HASHBANG) as *mut Option<Hashbang>)
|
||||
{
|
||||
ctx.retag_stack(AncestorType::ProgramHashbang);
|
||||
walk_hashbang(traverser, field as *mut _, ctx);
|
||||
}
|
||||
ctx.retag_stack(AncestorType::ProgramBody);
|
||||
walk_statements(
|
||||
traverser,
|
||||
|
|
|
|||
Loading…
Reference in a new issue