fix(coverage): apply always_strict to test262 and typescript per the specifcation (#5555)

This also removes the confusing `SourceType::always_strict` field.

I hacked it with `SourceType::always_strict`, but what we actually want is add `'use strict'`.

This is technically a breaking change but I don't expect anyone using this outside of oxc.

The snapshot has a large diff due to every single line shifting by 1 row :-/
This commit is contained in:
Boshen 2024-09-06 17:14:01 +00:00
parent b06052501a
commit 28b934ca74
9 changed files with 21204 additions and 21169 deletions

View file

@ -1400,7 +1400,7 @@ const _: () = {
assert!(offset_of!(Span, start) == 0usize);
assert!(offset_of!(Span, end) == 4usize);
assert!(size_of::<SourceType>() == 4usize);
assert!(size_of::<SourceType>() == 3usize);
assert!(align_of::<SourceType>() == 1usize);
assert!(size_of::<Language>() == 1usize);
@ -2954,7 +2954,7 @@ const _: () = {
assert!(offset_of!(Span, start) == 0usize);
assert!(offset_of!(Span, end) == 4usize);
assert!(size_of::<SourceType>() == 4usize);
assert!(size_of::<SourceType>() == 3usize);
assert!(align_of::<SourceType>() == 1usize);
assert!(size_of::<Language>() == 1usize);

View file

@ -66,7 +66,6 @@ impl SourceType {
language: Language::JavaScript,
module_kind: ModuleKind::Script,
variant: LanguageVariant::Standard,
always_strict: false,
}
}
@ -110,7 +109,6 @@ impl SourceType {
language: Language::TypeScript,
module_kind: ModuleKind::Module,
variant: LanguageVariant::Standard,
always_strict: false,
}
}
@ -150,7 +148,6 @@ impl SourceType {
language: Language::TypeScriptDefinition,
module_kind: ModuleKind::Module,
variant: LanguageVariant::Standard,
always_strict: false,
}
}
@ -185,12 +182,8 @@ impl SourceType {
self.variant == LanguageVariant::Jsx
}
pub fn always_strict(self) -> bool {
self.always_strict
}
pub fn is_strict(self) -> bool {
self.is_module() || self.always_strict
self.is_module()
}
#[must_use]
@ -235,12 +228,6 @@ impl SourceType {
self
}
#[must_use]
pub const fn with_always_strict(mut self, yes: bool) -> Self {
self.always_strict = yes;
self
}
/// Converts a file [`Path`] to [`SourceType`].
///
/// ## Examples
@ -329,7 +316,7 @@ impl SourceType {
_ => LanguageVariant::Standard,
};
Ok(Self { language, module_kind, variant, always_strict: false })
Ok(Self { language, module_kind, variant })
}
}

View file

@ -3,7 +3,7 @@
use oxc_ast_macros::ast;
#[cfg(feature = "serialize")]
use ::{serde::Serialize, tsify::Tsify};
use {serde::Serialize, tsify::Tsify};
/// Source Type for JavaScript vs TypeScript / Script vs Module / JSX
#[ast]
@ -19,11 +19,6 @@ pub struct SourceType {
/// Support JSX for JavaScript and TypeScript? default without JSX
pub(super) variant: LanguageVariant,
/// Mark strict mode as always strict
///
/// See <https://github.com/tc39/test262/blob/main/INTERPRETING.md#strict-mode>
pub(super) always_strict: bool,
}
/// JavaScript or TypeScript

File diff suppressed because it is too large Load diff

View file

@ -3,7 +3,7 @@ commit: a709f989
parser_typescript Summary:
AST Parsed : 6470/6479 (99.86%)
Positive Passed: 6445/6479 (99.48%)
Negative Passed: 1208/5715 (21.14%)
Negative Passed: 1212/5715 (21.21%)
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/ClassDeclaration10.ts
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/ClassDeclaration11.ts
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/ClassDeclaration13.ts
@ -50,10 +50,6 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/allowSynthet
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/allowSyntheticDefaultImports3.ts
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/allowSyntheticDefaultImports6.ts
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/allowSyntheticDefaultImports8.ts
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/alwaysStrict.ts
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/alwaysStrictES6.ts
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/alwaysStrictModule.ts
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/alwaysStrictNoImplicitUseStrict.ts
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/ambientEnum1.ts
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/ambientExportDefaultErrors.ts
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/ambientExternalModuleInAnotherExternalModule.ts
@ -5091,11 +5087,43 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/salsa/typeFro
╰────
× Cannot assign to 'arguments' in strict mode
╭─[typescript/tests/cases/compiler/alwaysStrictModule2.ts:3:13]
2 │ export function f() {
3 │ var arguments = [];
╭─[typescript/tests/cases/compiler/alwaysStrict.ts:3:9]
2 │ function f() {
3 │ var arguments = [];
· ─────────
4 │ }
╰────
× Cannot assign to 'arguments' in strict mode
╭─[typescript/tests/cases/compiler/alwaysStrictES6.ts:3:9]
2 │ function f() {
3 │ var arguments = [];
· ─────────
4 │ }
╰────
× Cannot assign to 'arguments' in strict mode
╭─[typescript/tests/cases/compiler/alwaysStrictModule.ts:4:13]
3 │ export function f() {
4 │ var arguments = [];
· ─────────
4 │ }
5 │ }
╰────
× Cannot assign to 'arguments' in strict mode
╭─[typescript/tests/cases/compiler/alwaysStrictModule2.ts:4:13]
3 │ export function f() {
4 │ var arguments = [];
· ─────────
5 │ }
╰────
× Cannot assign to 'arguments' in strict mode
╭─[typescript/tests/cases/compiler/alwaysStrictNoImplicitUseStrict.ts:4:13]
3 │ export function f() {
4 │ var arguments = [];
· ─────────
5 │ }
╰────
× TS(1039): Initializers are not allowed in ambient contexts.

View file

@ -1,4 +1,5 @@
use std::{
borrow::Cow,
fs,
io::{stdout, Read, Write},
panic::UnwindSafe,
@ -291,6 +292,13 @@ pub trait Case: Sized + Sync + Send + UnwindSafe {
false
}
/// Mark strict mode as always strict
///
/// See <https://github.com/tc39/test262/blob/main/INTERPRETING.md#strict-mode>
fn always_strict(&self) -> bool {
false
}
fn test_passed(&self) -> bool {
let result = self.test_result();
assert!(!matches!(result, TestResult::ToBeRun), "test should be run");
@ -317,7 +325,6 @@ pub trait Case: Sized + Sync + Send + UnwindSafe {
/// Execute the parser once and get the test result
fn execute(&mut self, source_type: SourceType) -> TestResult {
let source_text = self.code();
let path = self.path();
let mut driver = Driver {
@ -325,7 +332,17 @@ pub trait Case: Sized + Sync + Send + UnwindSafe {
allow_return_outside_function: self.allow_return_outside_function(),
..Driver::default()
};
driver.run(source_text, source_type);
let source_text = if self.always_strict() {
// 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,
// followed by a semicolon (;) and newline character (\n): "use strict";
Cow::Owned(format!("'use strict';\n{}", self.code()))
} else {
Cow::Borrowed(self.code())
};
driver.run(&source_text, source_type);
let errors = driver.errors();
let result = if errors.is_empty() {

View file

@ -51,6 +51,7 @@ pub struct Test262Case {
code: String,
meta: MetaData,
should_fail: bool,
always_strict: bool,
result: TestResult,
}
@ -79,7 +80,7 @@ impl Case for Test262Case {
fn new(path: PathBuf, code: String) -> Self {
let meta = Self::read_metadata(&code);
let should_fail = Self::compute_should_fail(&meta);
Self { path, code, meta, should_fail, result: TestResult::ToBeRun }
Self { path, code, meta, should_fail, always_strict: false, result: TestResult::ToBeRun }
}
fn code(&self) -> &str {
@ -98,6 +99,10 @@ impl Case for Test262Case {
self.should_fail
}
fn always_strict(&self) -> bool {
self.always_strict
}
fn skip_test_case(&self) -> bool {
[
// ES2025 https://github.com/tc39/proposal-duplicate-named-capturing-groups
@ -124,15 +129,18 @@ impl Case for Test262Case {
let source_type = SourceType::default().with_script(true);
self.result = if flags.contains(&TestFlag::OnlyStrict) {
self.execute(source_type.with_always_strict(true))
self.always_strict = true;
self.execute(source_type)
} else if flags.contains(&TestFlag::Module) {
self.execute(source_type.with_module(true))
} else if flags.contains(&TestFlag::NoStrict) || flags.contains(&TestFlag::Raw) {
self.execute(source_type)
} else {
let res = self.execute(source_type.with_always_strict(true));
self.always_strict = true;
let res = self.execute(source_type);
if matches!(res, TestResult::Passed) {
self.execute(source_type.with_always_strict(false))
self.always_strict = false;
self.execute(source_type)
} else {
res
}

View file

@ -102,6 +102,10 @@ impl Case for TypeScriptCase {
!self.error_files.is_empty()
}
fn always_strict(&self) -> bool {
self.settings.always_strict
}
fn run(&mut self) {
let units = self.units.clone();
for unit in units {

View file

@ -106,13 +106,9 @@ fn source_type_from_code_element(code: ElementRef) -> Option<SourceType> {
};
match *lang {
"javascript" | "js" => Some(SourceType::default().with_always_strict(true)),
"typescript" | "ts" => {
Some(SourceType::default().with_typescript(true).with_always_strict(true))
}
"tsx" => Some(
SourceType::default().with_typescript(true).with_jsx(true).with_always_strict(true),
),
"javascript" | "js" => Some(SourceType::default()),
"typescript" | "ts" => Some(SourceType::default().with_typescript(true)),
"tsx" => Some(SourceType::default().with_typescript(true).with_jsx(true)),
// FIXME: lots of jsx examples are usefully succinct but not valid JSX.
// "jsx" => Some(SourceType::default().with_jsx(true).with_always_strict(true)),
_ => None,