Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions crates/oxc_parser/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ pub fn overlong_source() -> OxcDiagnostic {
OxcDiagnostic::error("Source length exceeds 4 GiB limit")
}

#[cold]
pub fn file_appears_to_be_binary() -> OxcDiagnostic {
ts_error("1490", "File appears to be binary.")
}

#[cold]
pub fn flow(span: Span) -> OxcDiagnostic {
OxcDiagnostic::error("Flow is not supported").with_label(span)
Expand Down
11 changes: 11 additions & 0 deletions crates/oxc_parser/src/lexer/unicode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ impl<'a> Lexer<'a> {
pub(super) fn unicode_char_handler(&mut self) -> Kind {
let c = self.peek_char().unwrap();
match c {
// U+FFFD (replacement character) appears when a binary file is decoded as UTF-8.
// This is likely a binary file that cannot be parsed.
// <https://github.com/microsoft/TypeScript/blob/main/src/compiler/scanner.ts>
'\u{FFFD}' => self.handle_binary_file(),
c if is_identifier_start_unicode(c) => {
let start_pos = self.source.position();
self.consume_char();
Expand All @@ -45,6 +49,13 @@ impl<'a> Lexer<'a> {
}
}

#[cold]
fn handle_binary_file(&mut self) -> Kind {
self.error(diagnostics::file_appears_to_be_binary());
self.source.advance_to_end();
Kind::Eof
}

#[cold]
fn handle_irregular_whitespace(&mut self, _c: char) -> Kind {
self.consume_char();
Expand Down
17 changes: 17 additions & 0 deletions crates/oxc_parser/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -808,6 +808,23 @@ mod test {
}
}

#[test]
fn binary_file() {
let allocator = Allocator::default();
let source_type = SourceType::default();

// U+FFFD as a standalone token — file appears to be binary
let ret = Parser::new(&allocator, "\u{FFFD}", source_type).parse();
assert!(ret.program.is_empty());
assert_eq!(ret.errors.len(), 1);
assert_eq!(ret.errors[0].to_string(), "File appears to be binary.");

// U+FFFD inside string literals — should parse fine
let ret = Parser::new(&allocator, "\"oops \u{FFFD} oops\";", source_type).parse();
assert!(!ret.program.is_empty());
assert!(ret.errors.is_empty());
}

#[test]
fn memory_leak() {
let allocator = Allocator::default();
Expand Down
15 changes: 9 additions & 6 deletions tasks/coverage/snapshots/parser_typescript.snap
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ commit: 95e3aaa9
parser_typescript Summary:
AST Parsed : 9841/9841 (100.00%)
Positive Passed: 9841/9841 (100.00%)
Negative Passed: 1529/2557 (59.80%)
Negative Passed: 1530/2558 (59.81%)
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/FunctionDeclaration3.ts

Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/FunctionDeclaration4.ts
Expand Down Expand Up @@ -2312,6 +2312,13 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/types/wit
5 │ }
╰────

× Expected a semicolon or an implicit semicolon after a statement, but found none
╭─[typescript/tests/cases/compiler/TransportStream.ts:1:2]
1 │ G@�G@�G@�
· ▲
╰────
help: Try inserting a semicolon here

× Getters and setters must have an implementation.
╭─[typescript/tests/cases/compiler/abstractPropertyNegative.ts:16:9]
15 │ abstract notAllowed: string;
Expand Down Expand Up @@ -4586,11 +4593,7 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/types/wit
293 │ class interface { }
╰────

× Invalid Character `�`
╭─[typescript/tests/cases/compiler/corrupted.ts:1:1]
1 │ ���
· ─
╰────
× TS(1490): File appears to be binary.

× TS(2391): Function implementation is missing or not immediately following the declaration.
╭─[typescript/tests/cases/compiler/crashOnMethodSignatures.ts:2:5]
Expand Down
3 changes: 0 additions & 3 deletions tasks/coverage/src/typescript/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,6 @@ pub static NOT_SUPPORTED_TEST_PATHS: phf::Set<&'static str> = phf::phf_set![
// TSC: Parse without error, they support BOM
// OXC: We do not ignore or exclude BOM, will be invalid character error
"bom-utf16be.ts",
// TSC: This is just a binary file, but their test project skips reading
// OXC: Try to parse, and fail
"TransportStream.ts",
// TSC: Allows `catch({x}) { var x; }` (destructured catch param + var redeclaration)
// OXC: Reports redeclaration error per Annex B §B.3.4 (only simple identifiers are exempt)
"asyncWithVarShadowing_es6.ts",
Expand Down
Loading