-
-
Notifications
You must be signed in to change notification settings - Fork 932
Description
There appear to be some discrepancies in when ScopeFlags::StrictMode is applied by semantic.
enter_scope looks like its logic is that StrictMode should be set on any scope which is strict mode (including from a 'use strict' directive somewhere above it). But this doesn't appear to be what it actually does, because it only sets StrictMode flag if the direct parent is a function with a 'use strict' directive, or if the entire program is strict mode:
oxc/crates/oxc_semantic/src/builder.rs
Lines 414 to 440 in 9e148e9
| impl<'a> Visit<'a> for SemanticBuilder<'a> { | |
| fn enter_scope(&mut self, flags: ScopeFlags) { | |
| let parent_scope_id = | |
| if flags.contains(ScopeFlags::Top) { None } else { Some(self.current_scope_id) }; | |
| let mut flags = flags; | |
| // Inherit strict mode for functions | |
| // https://tc39.es/ecma262/#sec-strict-mode-code | |
| if let Some(parent_scope_id) = parent_scope_id { | |
| let mut strict_mode = self.scope.root_flags().is_strict_mode(); | |
| let parent_scope_flags = self.scope.get_flags(parent_scope_id); | |
| if !strict_mode | |
| && parent_scope_flags.is_function() | |
| && parent_scope_flags.is_strict_mode() | |
| { | |
| strict_mode = true; | |
| } | |
| // inherit flags for non-function scopes | |
| if !flags.contains(ScopeFlags::Function) { | |
| flags |= parent_scope_flags & ScopeFlags::Modifiers; | |
| }; | |
| if strict_mode { | |
| flags |= ScopeFlags::StrictMode; | |
| } |
A couple of examples of weirdness:
// Script - sloppy mode
function foo() {
'use strict';
{
// Scope flags for this block include `StrictMode`
{
// Scope flags for this block do NOT include `StrictMode`
}
}
}// Script - sloppy mode
class X {
foo() {
// Scope flags for this method do NOT include `StrictMode`
}
}When is StrictMode flag meant to be set?
If intended behavior is that StrictMode flag should be set for any scope which runs in strict context, we can simplify the above logic to:
if let Some(parent_scope_id) = parent_scope_id {
let parent_scope_flags = self.scope.get_flags(parent_scope_id);
flags |= parent_scope_flags & ScopeFlags::StrictMode;
// inherit flags for non-function scopes
if !flags.contains(ScopeFlags::Function) {
flags |= parent_scope_flags & ScopeFlags::Modifiers;
}
}Metadata
Metadata
Assignees
Labels
Type
Fields
Give feedbackPriority