fix(semantic): apply strict mode scope flag for strict mode TS Modules (#3861)

#3830 added a `directives` field to `TSModuleBlock`. Make semantic apply strict mode scope flag if directives include `'use strict'`.
This commit is contained in:
overlookmotel 2024-06-24 02:38:59 +00:00
parent acf69fa1b6
commit 8c9fc6347d
5 changed files with 36 additions and 4 deletions

View file

@ -782,7 +782,11 @@ pub enum TSTypePredicateName<'a> {
This(TSThisType),
}
#[visited_node(scope(ScopeFlags::TsModuleBlock), enter_scope_before(body))]
#[visited_node(
scope(ScopeFlags::TsModuleBlock),
enter_scope_before(body),
strict_if(self.body.as_ref().is_some_and(|body| body.is_strict()))
)]
#[derive(Debug)]
#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))]
#[cfg_attr(feature = "serialize", serde(tag = "type", rename_all = "camelCase"))]

View file

@ -153,6 +153,10 @@ impl<'a> TSModuleDeclaration<'a> {
) -> Self {
Self { span, id, body, kind, declare, scope_id: Cell::default() }
}
pub fn is_strict(&self) -> bool {
self.body.as_ref().is_some_and(TSModuleDeclarationBody::is_strict)
}
}
impl<'a> Hash for TSModuleDeclaration<'a> {
@ -177,6 +181,18 @@ impl<'a> TSModuleDeclarationName<'a> {
}
}
impl<'a> TSModuleDeclarationBody<'a> {
pub fn is_strict(&self) -> bool {
matches!(self, Self::TSModuleBlock(block) if block.is_strict())
}
}
impl<'a> TSModuleBlock<'a> {
pub fn is_strict(&self) -> bool {
self.directives.iter().any(Directive::is_use_strict)
}
}
impl<'a> Decorator<'a> {
/// Get the name of the decorator
/// ```ts

View file

@ -2647,7 +2647,13 @@ pub mod walk {
TSModuleDeclarationName::Identifier(ident) => visitor.visit_identifier_name(ident),
TSModuleDeclarationName::StringLiteral(lit) => visitor.visit_string_literal(lit),
}
visitor.enter_scope(ScopeFlags::TsModuleBlock);
visitor.enter_scope({
let mut flags = ScopeFlags::TsModuleBlock;
if decl.is_strict() {
flags |= ScopeFlags::StrictMode;
}
flags
});
match &decl.body {
Some(TSModuleDeclarationBody::TSModuleDeclaration(decl)) => {
visitor.visit_ts_module_declaration(decl);

View file

@ -2727,7 +2727,13 @@ pub mod walk_mut {
TSModuleDeclarationName::Identifier(ident) => visitor.visit_identifier_name(ident),
TSModuleDeclarationName::StringLiteral(lit) => visitor.visit_string_literal(lit),
}
visitor.enter_scope(ScopeFlags::TsModuleBlock);
visitor.enter_scope({
let mut flags = ScopeFlags::TsModuleBlock;
if decl.is_strict() {
flags |= ScopeFlags::StrictMode;
}
flags
});
match &mut decl.body {
Some(TSModuleDeclarationBody::TSModuleDeclaration(decl)) => {
visitor.visit_ts_module_declaration(decl);

View file

@ -424,7 +424,7 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> {
let parent_scope_flags = self.scope.get_flags(parent_scope_id);
if !strict_mode
&& parent_scope_flags.is_function()
&& (parent_scope_flags.is_function() || parent_scope_flags.is_ts_module_block())
&& parent_scope_flags.is_strict_mode()
{
strict_mode = true;