mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 12:21:58 +00:00
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:
parent
b06052501a
commit
28b934ca74
9 changed files with 21204 additions and 21169 deletions
|
|
@ -1400,7 +1400,7 @@ const _: () = {
|
||||||
assert!(offset_of!(Span, start) == 0usize);
|
assert!(offset_of!(Span, start) == 0usize);
|
||||||
assert!(offset_of!(Span, end) == 4usize);
|
assert!(offset_of!(Span, end) == 4usize);
|
||||||
|
|
||||||
assert!(size_of::<SourceType>() == 4usize);
|
assert!(size_of::<SourceType>() == 3usize);
|
||||||
assert!(align_of::<SourceType>() == 1usize);
|
assert!(align_of::<SourceType>() == 1usize);
|
||||||
|
|
||||||
assert!(size_of::<Language>() == 1usize);
|
assert!(size_of::<Language>() == 1usize);
|
||||||
|
|
@ -2954,7 +2954,7 @@ const _: () = {
|
||||||
assert!(offset_of!(Span, start) == 0usize);
|
assert!(offset_of!(Span, start) == 0usize);
|
||||||
assert!(offset_of!(Span, end) == 4usize);
|
assert!(offset_of!(Span, end) == 4usize);
|
||||||
|
|
||||||
assert!(size_of::<SourceType>() == 4usize);
|
assert!(size_of::<SourceType>() == 3usize);
|
||||||
assert!(align_of::<SourceType>() == 1usize);
|
assert!(align_of::<SourceType>() == 1usize);
|
||||||
|
|
||||||
assert!(size_of::<Language>() == 1usize);
|
assert!(size_of::<Language>() == 1usize);
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,6 @@ impl SourceType {
|
||||||
language: Language::JavaScript,
|
language: Language::JavaScript,
|
||||||
module_kind: ModuleKind::Script,
|
module_kind: ModuleKind::Script,
|
||||||
variant: LanguageVariant::Standard,
|
variant: LanguageVariant::Standard,
|
||||||
always_strict: false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -110,7 +109,6 @@ impl SourceType {
|
||||||
language: Language::TypeScript,
|
language: Language::TypeScript,
|
||||||
module_kind: ModuleKind::Module,
|
module_kind: ModuleKind::Module,
|
||||||
variant: LanguageVariant::Standard,
|
variant: LanguageVariant::Standard,
|
||||||
always_strict: false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -150,7 +148,6 @@ impl SourceType {
|
||||||
language: Language::TypeScriptDefinition,
|
language: Language::TypeScriptDefinition,
|
||||||
module_kind: ModuleKind::Module,
|
module_kind: ModuleKind::Module,
|
||||||
variant: LanguageVariant::Standard,
|
variant: LanguageVariant::Standard,
|
||||||
always_strict: false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -185,12 +182,8 @@ impl SourceType {
|
||||||
self.variant == LanguageVariant::Jsx
|
self.variant == LanguageVariant::Jsx
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn always_strict(self) -> bool {
|
|
||||||
self.always_strict
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_strict(self) -> bool {
|
pub fn is_strict(self) -> bool {
|
||||||
self.is_module() || self.always_strict
|
self.is_module()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
|
|
@ -235,12 +228,6 @@ impl SourceType {
|
||||||
self
|
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`].
|
/// Converts a file [`Path`] to [`SourceType`].
|
||||||
///
|
///
|
||||||
/// ## Examples
|
/// ## Examples
|
||||||
|
|
@ -329,7 +316,7 @@ impl SourceType {
|
||||||
_ => LanguageVariant::Standard,
|
_ => LanguageVariant::Standard,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Self { language, module_kind, variant, always_strict: false })
|
Ok(Self { language, module_kind, variant })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
use oxc_ast_macros::ast;
|
use oxc_ast_macros::ast;
|
||||||
#[cfg(feature = "serialize")]
|
#[cfg(feature = "serialize")]
|
||||||
use ::{serde::Serialize, tsify::Tsify};
|
use {serde::Serialize, tsify::Tsify};
|
||||||
|
|
||||||
/// Source Type for JavaScript vs TypeScript / Script vs Module / JSX
|
/// Source Type for JavaScript vs TypeScript / Script vs Module / JSX
|
||||||
#[ast]
|
#[ast]
|
||||||
|
|
@ -19,11 +19,6 @@ pub struct SourceType {
|
||||||
|
|
||||||
/// Support JSX for JavaScript and TypeScript? default without JSX
|
/// Support JSX for JavaScript and TypeScript? default without JSX
|
||||||
pub(super) variant: LanguageVariant,
|
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
|
/// JavaScript or TypeScript
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -3,7 +3,7 @@ commit: a709f989
|
||||||
parser_typescript Summary:
|
parser_typescript Summary:
|
||||||
AST Parsed : 6470/6479 (99.86%)
|
AST Parsed : 6470/6479 (99.86%)
|
||||||
Positive Passed: 6445/6479 (99.48%)
|
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/ClassDeclaration10.ts
|
||||||
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/ClassDeclaration11.ts
|
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/ClassDeclaration11.ts
|
||||||
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/ClassDeclaration13.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/allowSyntheticDefaultImports3.ts
|
||||||
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/allowSyntheticDefaultImports6.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/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/ambientEnum1.ts
|
||||||
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/ambientExportDefaultErrors.ts
|
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/ambientExportDefaultErrors.ts
|
||||||
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/ambientExternalModuleInAnotherExternalModule.ts
|
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/ambientExternalModuleInAnotherExternalModule.ts
|
||||||
|
|
@ -5091,13 +5087,45 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/salsa/typeFro
|
||||||
╰────
|
╰────
|
||||||
|
|
||||||
× Cannot assign to 'arguments' in strict mode
|
× Cannot assign to 'arguments' in strict mode
|
||||||
╭─[typescript/tests/cases/compiler/alwaysStrictModule2.ts:3:13]
|
╭─[typescript/tests/cases/compiler/alwaysStrict.ts:3:9]
|
||||||
2 │ export function f() {
|
2 │ function f() {
|
||||||
3 │ var arguments = [];
|
3 │ var arguments = [];
|
||||||
· ─────────
|
· ─────────
|
||||||
4 │ }
|
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 = [];
|
||||||
|
· ─────────
|
||||||
|
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.
|
× TS(1039): Initializers are not allowed in ambient contexts.
|
||||||
╭─[typescript/tests/cases/compiler/ambientErrors1.ts:1:17]
|
╭─[typescript/tests/cases/compiler/ambientErrors1.ts:1:17]
|
||||||
1 │ declare var x = 4;
|
1 │ declare var x = 4;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
use std::{
|
use std::{
|
||||||
|
borrow::Cow,
|
||||||
fs,
|
fs,
|
||||||
io::{stdout, Read, Write},
|
io::{stdout, Read, Write},
|
||||||
panic::UnwindSafe,
|
panic::UnwindSafe,
|
||||||
|
|
@ -291,6 +292,13 @@ pub trait Case: Sized + Sync + Send + UnwindSafe {
|
||||||
false
|
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 {
|
fn test_passed(&self) -> bool {
|
||||||
let result = self.test_result();
|
let result = self.test_result();
|
||||||
assert!(!matches!(result, TestResult::ToBeRun), "test should be run");
|
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
|
/// Execute the parser once and get the test result
|
||||||
fn execute(&mut self, source_type: SourceType) -> TestResult {
|
fn execute(&mut self, source_type: SourceType) -> TestResult {
|
||||||
let source_text = self.code();
|
|
||||||
let path = self.path();
|
let path = self.path();
|
||||||
|
|
||||||
let mut driver = Driver {
|
let mut driver = Driver {
|
||||||
|
|
@ -325,7 +332,17 @@ pub trait Case: Sized + Sync + Send + UnwindSafe {
|
||||||
allow_return_outside_function: self.allow_return_outside_function(),
|
allow_return_outside_function: self.allow_return_outside_function(),
|
||||||
..Driver::default()
|
..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 errors = driver.errors();
|
||||||
|
|
||||||
let result = if errors.is_empty() {
|
let result = if errors.is_empty() {
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,7 @@ pub struct Test262Case {
|
||||||
code: String,
|
code: String,
|
||||||
meta: MetaData,
|
meta: MetaData,
|
||||||
should_fail: bool,
|
should_fail: bool,
|
||||||
|
always_strict: bool,
|
||||||
result: TestResult,
|
result: TestResult,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -79,7 +80,7 @@ impl Case for Test262Case {
|
||||||
fn new(path: PathBuf, code: String) -> Self {
|
fn new(path: PathBuf, code: String) -> Self {
|
||||||
let meta = Self::read_metadata(&code);
|
let meta = Self::read_metadata(&code);
|
||||||
let should_fail = Self::compute_should_fail(&meta);
|
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 {
|
fn code(&self) -> &str {
|
||||||
|
|
@ -98,6 +99,10 @@ impl Case for Test262Case {
|
||||||
self.should_fail
|
self.should_fail
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn always_strict(&self) -> bool {
|
||||||
|
self.always_strict
|
||||||
|
}
|
||||||
|
|
||||||
fn skip_test_case(&self) -> bool {
|
fn skip_test_case(&self) -> bool {
|
||||||
[
|
[
|
||||||
// ES2025 https://github.com/tc39/proposal-duplicate-named-capturing-groups
|
// 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);
|
let source_type = SourceType::default().with_script(true);
|
||||||
|
|
||||||
self.result = if flags.contains(&TestFlag::OnlyStrict) {
|
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) {
|
} else if flags.contains(&TestFlag::Module) {
|
||||||
self.execute(source_type.with_module(true))
|
self.execute(source_type.with_module(true))
|
||||||
} else if flags.contains(&TestFlag::NoStrict) || flags.contains(&TestFlag::Raw) {
|
} else if flags.contains(&TestFlag::NoStrict) || flags.contains(&TestFlag::Raw) {
|
||||||
self.execute(source_type)
|
self.execute(source_type)
|
||||||
} else {
|
} 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) {
|
if matches!(res, TestResult::Passed) {
|
||||||
self.execute(source_type.with_always_strict(false))
|
self.always_strict = false;
|
||||||
|
self.execute(source_type)
|
||||||
} else {
|
} else {
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -102,6 +102,10 @@ impl Case for TypeScriptCase {
|
||||||
!self.error_files.is_empty()
|
!self.error_files.is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn always_strict(&self) -> bool {
|
||||||
|
self.settings.always_strict
|
||||||
|
}
|
||||||
|
|
||||||
fn run(&mut self) {
|
fn run(&mut self) {
|
||||||
let units = self.units.clone();
|
let units = self.units.clone();
|
||||||
for unit in units {
|
for unit in units {
|
||||||
|
|
|
||||||
|
|
@ -106,13 +106,9 @@ fn source_type_from_code_element(code: ElementRef) -> Option<SourceType> {
|
||||||
};
|
};
|
||||||
|
|
||||||
match *lang {
|
match *lang {
|
||||||
"javascript" | "js" => Some(SourceType::default().with_always_strict(true)),
|
"javascript" | "js" => Some(SourceType::default()),
|
||||||
"typescript" | "ts" => {
|
"typescript" | "ts" => Some(SourceType::default().with_typescript(true)),
|
||||||
Some(SourceType::default().with_typescript(true).with_always_strict(true))
|
"tsx" => Some(SourceType::default().with_typescript(true).with_jsx(true)),
|
||||||
}
|
|
||||||
"tsx" => Some(
|
|
||||||
SourceType::default().with_typescript(true).with_jsx(true).with_always_strict(true),
|
|
||||||
),
|
|
||||||
// FIXME: lots of jsx examples are usefully succinct but not valid JSX.
|
// FIXME: lots of jsx examples are usefully succinct but not valid JSX.
|
||||||
// "jsx" => Some(SourceType::default().with_jsx(true).with_always_strict(true)),
|
// "jsx" => Some(SourceType::default().with_jsx(true).with_always_strict(true)),
|
||||||
_ => None,
|
_ => None,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue