diff --git a/crates/oxc_ast/src/source_type.rs b/crates/oxc_ast/src/source_type.rs index 423a073e7..3fee23d13 100644 --- a/crates/oxc_ast/src/source_type.rs +++ b/crates/oxc_ast/src/source_type.rs @@ -14,6 +14,10 @@ pub struct SourceType { /// support JSX for JavaScript and TypeScript? default without JSX variant: LanguageVariant, + + /// Mark strict mode as always strict + /// See + always_strict: bool, } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -46,6 +50,7 @@ impl Default for SourceType { language: Language::JavaScript, module_kind: ModuleKind::Script, variant: LanguageVariant::Standard, + always_strict: false, } } } @@ -88,6 +93,10 @@ impl SourceType { self.variant = LanguageVariant::Jsx; } + pub fn set_always_strict(&mut self, yes: bool) { + self.always_strict = yes; + } + #[must_use] pub fn is_script(self) -> bool { self.module_kind == ModuleKind::Script @@ -123,6 +132,11 @@ impl SourceType { self.variant == LanguageVariant::Jsx } + #[must_use] + pub fn always_strict(self) -> bool { + self.always_strict + } + /// Converts file path to `SourceType` /// returns `SourceTypeError::UnkownExtension` if: /// * there is no file name @@ -161,7 +175,7 @@ impl SourceType { _ => LanguageVariant::Standard, }; - Ok(Self { language, module_kind: ModuleKind::Module, variant }) + Ok(Self { language, module_kind: ModuleKind::Module, variant, always_strict: false }) } } @@ -210,4 +224,10 @@ impl SourceTypeBuilder { self.source_type.language = Language::TypeScript { is_definition_file: true }; self } + + #[must_use] + pub fn always_strict(mut self, yes: bool) -> Self { + self.source_type.always_strict = yes; + self + } } diff --git a/crates/oxc_semantic/src/builder.rs b/crates/oxc_semantic/src/builder.rs index b2ff4d9e2..41e3390ef 100644 --- a/crates/oxc_semantic/src/builder.rs +++ b/crates/oxc_semantic/src/builder.rs @@ -83,9 +83,9 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> { } fn leave_node(&mut self, kind: AstKind<'a>) { + self.leave_kind(kind); self.pop_ast_node(); self.try_leave_scope(kind); - self.leave_kind(kind); } } diff --git a/crates/oxc_semantic/src/scope/builder.rs b/crates/oxc_semantic/src/scope/builder.rs index 6ce4c801f..49a3cd287 100644 --- a/crates/oxc_semantic/src/scope/builder.rs +++ b/crates/oxc_semantic/src/scope/builder.rs @@ -13,7 +13,7 @@ impl ScopeBuilder { #[must_use] pub fn new(source_type: SourceType) -> Self { // Module code is always strict mode code. - let strict_mode = source_type.is_module(); + let strict_mode = source_type.is_module() || source_type.always_strict(); let scopes = ScopeTree::new(strict_mode); let current_scope_id = scopes.root_scope_id(); Self { scopes, current_scope_id } diff --git a/tasks/coverage/src/test262.rs b/tasks/coverage/src/test262.rs index bf3a13012..95dfea53d 100644 --- a/tasks/coverage/src/test262.rs +++ b/tasks/coverage/src/test262.rs @@ -170,7 +170,6 @@ impl Case for Test262Case { // To run in strict mode, the test contents must be modified prior to execution-- // a "use strict" directive must be inserted as the initial character sequence of the file // https://github.com/tc39/test262/blob/main/INTERPRETING.md#strict-mode - #[allow(clippy::if_same_then_else)] fn run(&mut self) { let flags = &self.meta.flags; @@ -178,7 +177,7 @@ impl Case for Test262Case { source_type.set_script(); self.result = if flags.contains(&TestFlag::OnlyStrict) { - // always_strict = true; + source_type.set_always_strict(true); self.execute(source_type) } else if flags.contains(&TestFlag::Module) { source_type.set_module(); @@ -186,10 +185,10 @@ impl Case for Test262Case { } else if flags.contains(&TestFlag::NoStrict) || flags.contains(&TestFlag::Raw) { self.execute(source_type) } else { - // always_strict = true; + source_type.set_always_strict(true); let res = self.execute(source_type); if matches!(res, TestResult::Passed) { - // always_strict = false; + source_type.set_always_strict(false); self.execute(source_type) } else { res diff --git a/tasks/coverage/test262.snap b/tasks/coverage/test262.snap index ffa48380b..deda22b10 100644 --- a/tasks/coverage/test262.snap +++ b/tasks/coverage/test262.snap @@ -1,7 +1,7 @@ Test262 Summary: AST Parsed : 44000/44009 (99.98%) Positive Passed: 44000/44009 (99.98%) -Negative Passed: 1935/3917 (49.40%) +Negative Passed: 1945/3917 (49.66%) Expect Syntax Error: "annexB/language/expressions/template-literal/legacy-octal-escape-sequence-strict.js" Expect Syntax Error: "annexB/language/statements/for-in/const-initializer.js" Expect Syntax Error: "annexB/language/statements/for-in/let-initializer.js" @@ -946,16 +946,6 @@ Expect Syntax Error: "language/identifiers/val-yield-strict.js" Expect Syntax Error: "language/import/dup-bound-names.js" Expect Syntax Error: "language/import/json-invalid.js" Expect Syntax Error: "language/import/json-named-bindings.js" -Expect Syntax Error: "language/literals/numeric/7.8.3-1gs.js" -Expect Syntax Error: "language/literals/numeric/7.8.3-2gs.js" -Expect Syntax Error: "language/literals/numeric/legacy-octal-integer-strict.js" -Expect Syntax Error: "language/literals/numeric/legacy-octal-integery-000-strict.js" -Expect Syntax Error: "language/literals/numeric/legacy-octal-integery-005-strict.js" -Expect Syntax Error: "language/literals/numeric/legacy-octal-integery-01-strict.js" -Expect Syntax Error: "language/literals/numeric/legacy-octal-integery-010-strict.js" -Expect Syntax Error: "language/literals/numeric/legacy-octal-integery-06-strict.js" -Expect Syntax Error: "language/literals/numeric/legacy-octal-integery-07-strict.js" -Expect Syntax Error: "language/literals/numeric/non-octal-decimal-integer-strict.js" Expect Syntax Error: "language/literals/string/S7.8.4_A4.3_T1.js" Expect Syntax Error: "language/literals/string/S7.8.4_A4.3_T2.js" Expect Syntax Error: "language/literals/string/legacy-non-octal-escape-sequence-1-strict-explicit-pragma.js" @@ -12724,6 +12714,22 @@ Expect to Parse: "language/statements/class/decorator/syntax/class-valid/decorat · ╰── Invalid Character `9` ╰──── + × '0'-prefixed octal literals and octal escape sequences are deprecated + ╭─[language/literals/numeric/7.8.3-1gs.js:14:1] + 14 │ + 15 │ var y = 010; + · ─── + ╰──── + help: for octal literals use the '0o' prefix instead + + × '0'-prefixed octal literals and octal escape sequences are deprecated + ╭─[language/literals/numeric/7.8.3-2gs.js:18:1] + 18 │ a = 0x1; + 19 │ a = 01; + · ── + ╰──── + help: for octal literals use the '0o' prefix instead + × Invalid Character `'\n'` ╭─[language/literals/numeric/S7.8.3_A6.1_T1.js:15:1] 15 │ //CHECK#1 @@ -12791,6 +12797,70 @@ Expect to Parse: "language/statements/class/decorator/syntax/class-valid/decorat ╰──── help: Try insert a semicolon here + × '0'-prefixed octal literals and octal escape sequences are deprecated + ╭─[language/literals/numeric/legacy-octal-integer-strict.js:32:1] + 32 │ + 33 │ 00; + · ── + ╰──── + help: for octal literals use the '0o' prefix instead + + × '0'-prefixed octal literals and octal escape sequences are deprecated + ╭─[language/literals/numeric/legacy-octal-integery-000-strict.js:14:1] + 14 │ + 15 │ 000; + · ─── + ╰──── + help: for octal literals use the '0o' prefix instead + + × '0'-prefixed octal literals and octal escape sequences are deprecated + ╭─[language/literals/numeric/legacy-octal-integery-005-strict.js:14:1] + 14 │ + 15 │ 005; + · ─── + ╰──── + help: for octal literals use the '0o' prefix instead + + × '0'-prefixed octal literals and octal escape sequences are deprecated + ╭─[language/literals/numeric/legacy-octal-integery-01-strict.js:14:1] + 14 │ + 15 │ 01; + · ── + ╰──── + help: for octal literals use the '0o' prefix instead + + × '0'-prefixed octal literals and octal escape sequences are deprecated + ╭─[language/literals/numeric/legacy-octal-integery-010-strict.js:14:1] + 14 │ + 15 │ 010; + · ─── + ╰──── + help: for octal literals use the '0o' prefix instead + + × '0'-prefixed octal literals and octal escape sequences are deprecated + ╭─[language/literals/numeric/legacy-octal-integery-06-strict.js:14:1] + 14 │ + 15 │ 06; + · ── + ╰──── + help: for octal literals use the '0o' prefix instead + + × '0'-prefixed octal literals and octal escape sequences are deprecated + ╭─[language/literals/numeric/legacy-octal-integery-07-strict.js:14:1] + 14 │ + 15 │ 07; + · ── + ╰──── + help: for octal literals use the '0o' prefix instead + + × Decimals with leading zeros are not allowed in strict mode + ╭─[language/literals/numeric/non-octal-decimal-integer-strict.js:38:1] + 38 │ + 39 │ 08; + · ── + ╰──── + help: remove the leading zero + × Invalid characters after number ╭─[language/literals/numeric/numeric-followed-by-ident.js:17:1] 17 │