From 45cad43966fead9e6a23c617ac2e0aaba2fcc99b Mon Sep 17 00:00:00 2001 From: liufengkai Date: Thu, 17 Sep 2026 13:34:54 -0700 Subject: [PATCH 1/3] fix(lexer): align malformed escape wording and unterminated-string column with pinned QuickJS Pinned QuickJS funnels every malformed \x/\u string escape to one message, "malformed escape sequence in string literal", emitted at the backslash (quickjs.c:22439), and reports unterminated strings through the token pointer, i.e. at the opening quote (quickjs.c:22473). - unify fixed-hex (\x2, \u4), braced (\u{}, unclosed, > U+10FFFF) and strict/template \8 \9 failures on the pinned wording instead of count/braced/range-specific text - anchor raw CR/LF-terminated string errors at the opening quote instead of the line terminator (:1:9 instead of :1:13 on the scout case) - bare trailing backslash takes the pinned "unexpected end of string" label (upstream case '\0' -> invalid_char), re-anchored at the quote for ordinary strings; template EOF behavior unchanged Adds 2 lexer unit tests, 12 compiler diagnostic-table rows, and a 19-case pinned-oracle byte-exact diagnostic test. Differential matrix 17 -> 0 mismatches over 37 probes; test262 string/template subset shows no pass flips (207 pass both), only the exempt phase/type rows' observed text now matches pinned. Co-Authored-By: Claude Code (cherry picked from commit 01428509dccb3903d986ae7a5137617a47510454) --- apps/cli/tests/oracle/lexical/mod.rs | 6 + .../oracle_string_escape_diagnostics.rs | 169 ++++++++++++++++++ apps/cli/tests/oracle/main.rs | 1 + src/engine/compiler/lexer.rs | 119 ++++++++++-- src/engine/compiler/tests/syntax.rs | 73 ++++++++ 5 files changed, 357 insertions(+), 11 deletions(-) create mode 100644 apps/cli/tests/oracle/lexical/mod.rs create mode 100644 apps/cli/tests/oracle/lexical/oracle_string_escape_diagnostics.rs diff --git a/apps/cli/tests/oracle/lexical/mod.rs b/apps/cli/tests/oracle/lexical/mod.rs new file mode 100644 index 00000000..a3a74675 --- /dev/null +++ b/apps/cli/tests/oracle/lexical/mod.rs @@ -0,0 +1,6 @@ +// Keep the lexical oracle implementations in isolated modules while Cargo +// builds one integration target. + +use crate::quickjs_syntax_diagnostic_oracle; + +mod oracle_string_escape_diagnostics; diff --git a/apps/cli/tests/oracle/lexical/oracle_string_escape_diagnostics.rs b/apps/cli/tests/oracle/lexical/oracle_string_escape_diagnostics.rs new file mode 100644 index 00000000..cfec7ac3 --- /dev/null +++ b/apps/cli/tests/oracle/lexical/oracle_string_escape_diagnostics.rs @@ -0,0 +1,169 @@ +//! B12 (S2 C5/C6): malformed string-escape wording and unterminated-string +//! columns must match the pinned QuickJS byte-for-byte at the command line, +//! including the message text and the line:column location. + +use super::quickjs_syntax_diagnostic_oracle::observe_cmdline_syntax_error as oracle_observation; +use quickjs_oxide::engine::api::{Context, Runtime, RuntimeError, Value}; + +/// (description, source, `SyntaxError||:`) +/// +/// Locations are asserted against pinned QuickJS `qjs -e` output, so each +/// expectation is a copy of the pinned engine's emitted frame. +const CASES: &[(&str, &str, &str)] = &[ + // --- C6: unterminated strings point at the opening quote --- + ( + "newline-terminated single-quoted string", + "var s = 'abc\n", + "SyntaxError|unexpected end of string|1:9", + ), + ( + "crlf-terminated single-quoted string", + "var s = 'abc\r\n", + "SyntaxError|unexpected end of string|1:9", + ), + ( + "newline-terminated string on the second line", + "var t = 1;\nvar s = 'abc\n", + "SyntaxError|unexpected end of string|2:9", + ), + ( + "eof-terminated string already matched and keeps the quote", + "var s = 'abc", + "SyntaxError|unexpected end of string|1:9", + ), + ( + "bare backslash before a newline", + "var s = '\\\n", + "SyntaxError|unexpected end of string|1:9", + ), + ( + "bare backslash at end of file", + "var s = '\\", + "SyntaxError|unexpected end of string|1:9", + ), + // --- C5: every malformed \x / \u escape shares one pinned message --- + ( + "short fixed unicode escape", + "var s = '\\u00'", + "SyntaxError|malformed escape sequence in string literal|1:10", + ), + ( + "non-hex fixed unicode escape", + "var s = '\\uz'", + "SyntaxError|malformed escape sequence in string literal|1:10", + ), + ( + "unicode escape exhausted at end of file", + "var s = '\\u'", + "SyntaxError|malformed escape sequence in string literal|1:10", + ), + ( + "non-hex hex escape", + "var s = '\\xZZ'", + "SyntaxError|malformed escape sequence in string literal|1:10", + ), + ( + "hex escape exhausted at end of file", + "var s = '\\x'", + "SyntaxError|malformed escape sequence in string literal|1:10", + ), + ( + "empty braced unicode escape", + "var s = '\\u{}'", + "SyntaxError|malformed escape sequence in string literal|1:10", + ), + ( + "non-hex braced unicode escape", + "var s = '\\u{zz}'", + "SyntaxError|malformed escape sequence in string literal|1:10", + ), + ( + "unterminated braced unicode escape", + "var s = '\\u{41'", + "SyntaxError|malformed escape sequence in string literal|1:10", + ), + ( + "braced unicode escape beyond U+10FFFF", + "var s = '\\u{110000}'", + "SyntaxError|malformed escape sequence in string literal|1:10", + ), + ( + "double-quoted malformed escape behaves identically", + "var s = \"\\u00\"", + "SyntaxError|malformed escape sequence in string literal|1:10", + ), + ( + "strict mode \\8 uses the generic message", + "\"use strict\"; var s = \"a\\8b\"", + "SyntaxError|malformed escape sequence in string literal|1:25", + ), + ( + "strict mode \\9 uses the generic message", + "\"use strict\"; var s = \"a\\9b\"", + "SyntaxError|malformed escape sequence in string literal|1:25", + ), + // --- unaffected surfaces that must not regress --- + ( + "strict legacy octal keeps its dedicated message", + "\"use strict\"; var s = \"a\\07b\"", + "SyntaxError|octal escape sequences are not allowed in strict mode|1:25", + ), +]; + +#[test] +fn string_escape_diagnostics_match_pinned_quickjs() { + for &(description, source, expected) in CASES { + assert_eq!(rust_observation(source), expected, "Rust: {description}"); + } + + let Some(oracle) = std::env::var_os("QJS_ORACLE") else { + eprintln!("SKIP string escape diagnostic differential: set QJS_ORACLE to upstream qjs"); + return; + }; + for &(description, source, expected) in CASES { + assert_eq!( + oracle_observation(&oracle, source), + expected, + "QuickJS: {description}" + ); + } +} + +fn rust_observation(source: &str) -> String { + let runtime = + Runtime::new_with_host_services(quickjs_oxide_host::SystemHostServices::default()); + let mut context = runtime.new_context(); + assert_eq!( + context.eval(source), + Err(RuntimeError::Exception), + "Rust accepted {source:?}" + ); + let Value::Object(error) = context + .take_exception() + .unwrap() + .unwrap_or_else(|| panic!("Rust produced no exception for {source:?}")) + else { + panic!("Rust exception was not an Error object for {source:?}"); + }; + let read = |context: &mut Context, name: &str| { + let key = runtime.intern_property_key(name).unwrap(); + context.get_property(&error, &key).unwrap() + }; + let Value::String(name) = read(&mut context, "name") else { + panic!("Rust Error.name was not a string for {source:?}"); + }; + let Value::String(message) = read(&mut context, "message") else { + panic!("Rust Error.message was not a string for {source:?}"); + }; + let Value::Int(line) = read(&mut context, "lineNumber") else { + panic!("Rust Error.lineNumber was not an integer for {source:?}"); + }; + let Value::Int(column) = read(&mut context, "columnNumber") else { + panic!("Rust Error.columnNumber was not an integer for {source:?}"); + }; + format!( + "{}|{}|{line}:{column}", + name.to_utf8_lossy(), + message.to_utf8_lossy() + ) +} diff --git a/apps/cli/tests/oracle/main.rs b/apps/cli/tests/oracle/main.rs index 251dacfe..af1deaa9 100644 --- a/apps/cli/tests/oracle/main.rs +++ b/apps/cli/tests/oracle/main.rs @@ -40,6 +40,7 @@ mod generator_yield_star_depth; mod global; mod iterator; mod json; +mod lexical; mod math_intrinsic; mod member_access; mod module_reentry; diff --git a/src/engine/compiler/lexer.rs b/src/engine/compiler/lexer.rs index 6685c0b6..d18a6db8 100644 --- a/src/engine/compiler/lexer.rs +++ b/src/engine/compiler/lexer.rs @@ -1373,9 +1373,15 @@ impl<'a> Lexer<'a> { })); } if matches!(ch, '\r' | '\n') { - return Err( - self.error_here(LexErrorKind::UnterminatedString, "unexpected end of string") - ); + // Pinned QuickJS reaches its `invalid_char` label and reports + // the error through the token pointer, which is still the + // opening quote (a bare CR is not a line continuation either: + // only an escaped CR/LF is consumed by scan_escape_sequence). + return Err(self.error_from( + start, + LexErrorKind::UnterminatedString, + "unexpected end of string", + )); } if ch == '\\' { has_escape = true; @@ -1390,6 +1396,19 @@ impl<'a> Lexer<'a> { error.message, )); } + // A trailing bare backslash is reported at the opening + // quote, exactly like any other unterminated string: the + // pinned parser raises it from the token pointer. + Err(error) + if error.kind == LexErrorKind::UnterminatedString + && error.message == "unexpected end of string" => + { + return Err(self.error_from( + start, + LexErrorKind::UnterminatedString, + error.message, + )); + } result => result?, }; has_legacy_octal_escape |= escape.legacy_octal; @@ -1423,10 +1442,14 @@ impl<'a> Lexer<'a> { return Err(self.invalid_utf8_error_here("invalid UTF-8 sequence")); } let Some(ch) = self.peek_char() else { + // Pinned QuickJS's `case '\0': goto invalid_char` turns a bare + // trailing backslash into "unexpected end of string" rather than + // an escape error. scan_string re-anchors the span at the + // opening quote; the template scanner's own EOF branch wins. return Err(self.error_from( start, - LexErrorKind::InvalidEscape, - "escape sequence reaches end of source", + LexErrorKind::UnterminatedString, + "unexpected end of string", )); }; @@ -1495,10 +1518,13 @@ impl<'a> Lexer<'a> { '8' | '9' => { if template || self.options.context.strict { self.bump_char(); + // Pinned QuickJS routes the strict/template `\8` and `\9` + // rejection through lre_parse_escape's failure label, + // which uses the generic malformed-escape wording. return Err(self.error_from( start, LexErrorKind::InvalidEscape, - "escape 8 or 9 is not allowed in strict strings or templates", + "malformed escape sequence in string literal", )); } self.bump_char(); @@ -1574,7 +1600,7 @@ impl<'a> Lexer<'a> { return Err(self.error_from( start, LexErrorKind::InvalidEscape, - "malformed braced Unicode escape", + "malformed escape sequence in string literal", )); } self.bump_char(); @@ -1582,7 +1608,7 @@ impl<'a> Lexer<'a> { return Err(self.error_from( start, LexErrorKind::InvalidEscape, - "Unicode escape exceeds U+10FFFF", + "malformed escape sequence in string literal", )); } Ok(value) @@ -1597,11 +1623,14 @@ impl<'a> Lexer<'a> { if self.invalid_source_byte_at(self.offset) { return Err(self.invalid_utf8_error_here("invalid UTF-8 sequence")); } + // Both exhaustion and a non-hex byte take pinned QuickJS's + // lre_parse_escape failure path, whose only wording is the + // generic malformed-escape message. let Some(ch) = self.peek_char() else { return Err(self.error_from( start, LexErrorKind::InvalidEscape, - format!("escape requires exactly {count} hexadecimal digits"), + "malformed escape sequence in string literal", )); }; let Some(digit) = ch.to_digit(16) else { @@ -1609,7 +1638,7 @@ impl<'a> Lexer<'a> { return Err(self.error_from( start, LexErrorKind::InvalidEscape, - format!("escape requires exactly {count} hexadecimal digits"), + "malformed escape sequence in string literal", )); }; self.bump_char(); @@ -2878,6 +2907,71 @@ mod tests { } } + #[test] + fn newline_terminated_strings_anchor_diagnostic_at_opening_quote() { + for source in ["'abc\n", "'abc\r\n", "'abc\r", "\"abc\n", "'\\\n", "'"] { + let error = Lexer::new(source).next_token().unwrap_err(); + assert_eq!(error.kind, LexErrorKind::UnterminatedString, "{source:?}"); + assert_eq!(error.message, "unexpected end of string", "{source:?}"); + // Pinned QuickJS raises through the token pointer, which still + // addresses the opening quote at column 1. + assert_eq!( + (error.span.start.line, error.span.start.column), + (1, 1), + "{source:?}" + ); + } + + let second_line = Lexer::new("var t = 1;\n'abc\n").tokenize().unwrap_err(); + assert_eq!(second_line.kind, LexErrorKind::UnterminatedString); + assert_eq!( + (second_line.span.start.line, second_line.span.start.column), + (2, 1) + ); + } + + #[test] + fn malformed_string_escapes_share_pinned_quickjs_wording_and_span() { + for source in [ + r"'\u00'", + r"'\uz'", + r"'\xZZ'", + r"'\x'", + r"'\u'", + r"'\u{}'", + r"'\u{zz}'", + r"'\u{41'", + r"'\u{110000}'", + ] { + let error = Lexer::new(source).next_token().unwrap_err(); + assert_eq!(error.kind, LexErrorKind::InvalidEscape, "{source}"); + assert_eq!( + error.message, "malformed escape sequence in string literal", + "{source}" + ); + assert_eq!(error.span.start.byte_offset, 1, "{source}"); + assert_eq!(error.span.start.column, 2, "{source}"); + } + + let strict = LexerOptions { + context: LexContext { + strict: true, + ..LexContext::default() + }, + ..LexerOptions::default() + }; + for source in [r"'\8'", r"'\9'"] { + let error = Lexer::with_options(source, strict) + .next_token() + .unwrap_err(); + assert_eq!(error.kind, LexErrorKind::InvalidEscape, "{source}"); + assert_eq!( + error.message, "malformed escape sequence in string literal", + "{source}" + ); + } + } + #[test] fn raw_source_template_and_regexp_diagnostics_point_at_malformed_byte() { for (raw, expected_offset) in [ @@ -2998,7 +3092,10 @@ mod tests { assert_eq!(part.kind, TemplatePartKind::NoSubstitution); assert!(part.cooked.is_none()); let invalid = part.invalid_escape.expect("invalid escape metadata"); - assert!(invalid.message.contains("not allowed")); + assert_eq!( + invalid.message, + "malformed escape sequence in string literal" + ); } #[test] diff --git a/src/engine/compiler/tests/syntax.rs b/src/engine/compiler/tests/syntax.rs index cd6ac0c6..472b7946 100644 --- a/src/engine/compiler/tests/syntax.rs +++ b/src/engine/compiler/tests/syntax.rs @@ -284,6 +284,79 @@ fn parser_driven_lexing_preserves_quickjs_error_priority_and_locations() { 1, 50, ), + // A string terminated by a raw line terminator is reported at the + // opening quote, matching pinned QuickJS's token-pointer location + // rather than at the newline character (B12/C6). + ( + "(function(){ \"unterminated\n})()", + "unexpected end of string", + 1, + 14, + ), + ( + "(function(){ 'unterminated\n})()", + "unexpected end of string", + 1, + 14, + ), + ( + "(function(){ \"unterminated\r\n})()", + "unexpected end of string", + 1, + 14, + ), + ( + "var t = 1;\n(function(){ \"unterminated\n})()", + "unexpected end of string", + 2, + 14, + ), + // A trailing backslash before the line terminator takes the same + // label and is also anchored at the opening quote. + ( + "(function(){ \"unterminated\\\n})()", + "unexpected end of string", + 1, + 14, + ), + // Malformed fixed-width and braced escapes share the pinned wording + // and point at the backslash (B12/C5). + ( + "(function(){ \"\\u00\"; })()", + "malformed escape sequence in string literal", + 1, + 15, + ), + ( + "(function(){ \"\\xZZ\"; })()", + "malformed escape sequence in string literal", + 1, + 15, + ), + ( + "(function(){ \"\\u{}\"; })()", + "malformed escape sequence in string literal", + 1, + 15, + ), + ( + "(function(){ \"\\u{110000}\"; })()", + "malformed escape sequence in string literal", + 1, + 15, + ), + ( + "(function(){ \"\\u\"; })()", + "malformed escape sequence in string literal", + 1, + 15, + ), + ( + "(function(){ \"\\x\"; })()", + "malformed escape sequence in string literal", + 1, + 15, + ), ]; for (source, message, line, column) in cases { From 890fa44588c998ef8b13a0fc8ca5f754300e2b99 Mon Sep 17 00:00:00 2001 From: liufengkai Date: Thu, 17 Sep 2026 13:36:31 -0700 Subject: [PATCH 2/3] fix(lexer): collapse malformed-number diagnostics to match QuickJS The three oxide-specific messages for malformed numeric literals ("base-{2,8,16} literal requires at least one digit", "BigInt suffix cannot follow a fraction or exponent", "decimal BigInt cannot contain a leading zero") diverged from pinned QuickJS 2026-06-04, which reports a single "invalid number literal" for all of them at js_parse_get_number (quickjs.c:22928). Collapse all three to "invalid number literal" without changing accept/reject decisions or spans, and add a unit test asserting the exact QuickJS wording across the three failure families. Co-Authored-By: Claude Code (cherry picked from commit 08b426f4758bd1e5bd5fdb398292aab4f13a81d9) --- src/engine/compiler/lexer.rs | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/src/engine/compiler/lexer.rs b/src/engine/compiler/lexer.rs index d18a6db8..228dd2ff 100644 --- a/src/engine/compiler/lexer.rs +++ b/src/engine/compiler/lexer.rs @@ -1141,7 +1141,7 @@ impl<'a> Lexer<'a> { return Err(self.error_from( start, LexErrorKind::InvalidNumber, - format!("base-{base} literal requires at least one digit"), + "invalid number literal", )); } @@ -1248,7 +1248,7 @@ impl<'a> Lexer<'a> { return Err(self.error_from( start, LexErrorKind::InvalidNumber, - "BigInt suffix cannot follow a fraction or exponent", + "invalid number literal", )); } if legacy_leading_zero { @@ -1256,7 +1256,7 @@ impl<'a> Lexer<'a> { return Err(self.error_from( start, LexErrorKind::InvalidNumber, - "decimal BigInt cannot contain a leading zero", + "invalid number literal", )); } self.bump_char(); @@ -2607,6 +2607,26 @@ mod tests { ); } + #[test] + fn malformed_number_diagnostic_matches_quickjs_wording() { + // Pinned QuickJS 2026-06-04 reports a single `invalid number literal` + // message for every malformed numeric literal (quickjs.c:22928, + // js_parse_get_number), regardless of the specific grammar failure. + // Three failure families, all sharing the same upstream message: + // prefixed literals without digits / out-of-radix digits; a BigInt + // suffix on a fraction or exponent; a decimal BigInt with a legacy + // leading zero. + for source in [ + "0x", "0X", "0b", "0B", "0o", "0O", "0b2n", "0xgn", "0o8", "1.0n", ".5n", "0e0n", + "1E2n", "01n", "00n", "012348n", "0008n", + ] { + let error = Lexer::new(source).next_token().unwrap_err(); + assert_eq!(error.kind, LexErrorKind::InvalidNumber, "{source}"); + assert_eq!(error.message, "invalid number literal", "{source}"); + assert_eq!(error.span.start, Position::new(0, 1, 1), "{source}"); + } + } + #[test] fn rejects_malformed_numbers() { for source in [ From 73ffedd3c2c84c156930925f729641f18d900837 Mon Sep 17 00:00:00 2001 From: liufengkai Date: Thu, 17 Sep 2026 14:09:50 -0700 Subject: [PATCH 3/3] test(test262): admit M3 numeric-literal diagnostic contracts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add rule numeric-literal.invalid (anchor js_parse_get_number) and 28 exact negative-diagnostic contracts for malformed numeric/BigInt literals whose sloppy and strict variants both belong to the M3 cluster; admit the corresponding 14 paths in the Oxide profile audited-negative section. Rows were produced with scripts/audit-negative-diagnostics.mjs --generate (both engines must agree byte-for-byte) and validated by the full registry replay: 2972 exact contracts / 78 rules. The remaining 7 M3 sloppy variants share paths with the parallel M1 strict-octal cluster and are admitted together with M1; their candidate rows are staged in the verify report's handoff section. Co-Authored-By: Claude Code (cherry picked from commit 0018504c9699030bbd0910bd40075a1f6079166e) Rebase note (onto main@49d1a299 workspace): contracts regenerated byte-identical (28 rows, e4cf946b…) with scripts/test262/audit-negative-diagnostics.mjs --generate; the new gate authenticates line counts/SHAs via dev-support/test262/current.conf and compat/upstream.toml, so profile/contract/rule counts and hashes were script-updated (profile 3194->3208 lines sha 5b7327f5…; contracts 2945->2973; rules 78->79). The frozen focused receipt still carries the old profile/contract header hashes and can only be re-issued by a maintainer `--full` promote (no receipt touched here, per policy); --check consequently reports only "focused report diagnostic contract drifted", with zero line-count/checksum drift. --- compat/test262-oxide.conf | 14 ++++++++++ compat/upstream.toml | 2 +- dev-support/test262/current.conf | 14 +++++----- .../test262/negative-diagnostic-rules.tsv | 1 + dev-support/test262/negative-diagnostics.tsv | 28 +++++++++++++++++++ 5 files changed, 51 insertions(+), 8 deletions(-) diff --git a/compat/test262-oxide.conf b/compat/test262-oxide.conf index adfa83e2..1c1e2af0 100644 --- a/compat/test262-oxide.conf +++ b/compat/test262-oxide.conf @@ -1812,6 +1812,11 @@ test/language/import/escaped-as-namespace-import.js test/language/import/escaped-from.js test/language/import/import-attributes/json-invalid.js test/language/import/import-attributes/json-named-bindings.js +test/language/literals/bigint/binary-invalid-digit.js +test/language/literals/bigint/exponent-part.js +test/language/literals/bigint/hexadecimal-invalid-digit.js +test/language/literals/bigint/mv-is-not-integer-dil-dot-dds.js +test/language/literals/bigint/mv-is-not-integer-dot-dds.js test/language/literals/bigint/numeric-separators/numeric-separator-literal-bil-bd-nsl-bd-err.js test/language/literals/bigint/numeric-separators/numeric-separator-literal-bil-nsl-bd-dunder-err.js test/language/literals/bigint/numeric-separators/numeric-separator-literal-bil-nsl-bd-err.js @@ -1838,6 +1843,13 @@ test/language/literals/bigint/numeric-separators/numeric-separator-literal-oil-n test/language/literals/bigint/numeric-separators/numeric-separator-literal-oil-nsl-od-err.js test/language/literals/bigint/numeric-separators/numeric-separator-literal-oil-od-nsl-od-err.js test/language/literals/bigint/numeric-separators/numeric-separator-literal-unicode-err.js +test/language/literals/bigint/octal-invalid-digit.js +test/language/literals/numeric/S7.8.3_A6.1_T1.js +test/language/literals/numeric/S7.8.3_A6.1_T2.js +test/language/literals/numeric/S7.8.3_A6.2_T1.js +test/language/literals/numeric/S7.8.3_A6.2_T2.js +test/language/literals/numeric/binary-invalid-digit.js +test/language/literals/numeric/binary-invalid-truncated.js test/language/literals/numeric/numeric-separators/numeric-separator-literal-bil-bd-nsl-bd-err.js test/language/literals/numeric/numeric-separators/numeric-separator-literal-bil-nsl-bd-dunder-err.js test/language/literals/numeric/numeric-separators/numeric-separator-literal-bil-nsl-bd-err.js @@ -1871,6 +1883,8 @@ test/language/literals/numeric/numeric-separators/numeric-separator-literal-oil- test/language/literals/numeric/numeric-separators/numeric-separator-literal-oil-nsl-od-err.js test/language/literals/numeric/numeric-separators/numeric-separator-literal-oil-od-nsl-od-err.js test/language/literals/numeric/numeric-separators/numeric-separator-literal-unicode-err.js +test/language/literals/numeric/octal-invalid-digit.js +test/language/literals/numeric/octal-invalid-truncated.js test/language/literals/regexp/early-err-arithmetic-modifiers-add-remove-i.js test/language/literals/regexp/early-err-arithmetic-modifiers-add-remove-m.js test/language/literals/regexp/early-err-arithmetic-modifiers-add-remove-multi-duplicate.js diff --git a/compat/upstream.toml b/compat/upstream.toml index 9052efeb..4bc57ca2 100644 --- a/compat/upstream.toml +++ b/compat/upstream.toml @@ -19,7 +19,7 @@ config_sha256 = "79c64748ff1182baf5433d0a8378e3666738a785d02faf71f0d459ed42ae897 test_count = 53125 metadata_records_sha256 = "a37219960819e56a5c5c1723d31d6a33095c778bf5347385187fde96f927a06a" oxide_profile = "compat/test262-oxide.conf" -oxide_profile_sha256 = "aa9fa3581c86cf1f1ef786a54c2023107f3a99002129b726024ddd8ea0838d67" +oxide_profile_sha256 = "5b7327f5f3606ed732a799241efec90f4ce01d6e08e2477745fc1a9e4dce4cfe" expected_errors = "test262_errors.txt" [test262_es5] diff --git a/dev-support/test262/current.conf b/dev-support/test262/current.conf index 5b2f2174..da20b8c7 100644 --- a/dev-support/test262/current.conf +++ b/dev-support/test262/current.conf @@ -16,19 +16,19 @@ engine_semantics_trees=src engine_semantics_sha256=f61afc7314c09e4b507468ca9bffdeb920d3e9c896068b3a9f39b4587caa0333 upstream=compat/upstream.toml upstream_lines=28 -upstream_sha256=ec5d1af6ad36f69946588dc959f1a2fc7a183999a9cf914812f114453e1cc9c3 +upstream_sha256=fa83c501ada9e5a687f0015a371075dbd870e3d98bb92a408b8ee3d77286a0cf admissions=dev-support/test262/admissions.tsv admissions_lines=1310 admissions_sha256=64bb20004f7b85ff5327aa241400547fa66e15cc4b673fd01602873ca9464ec5 profile=compat/test262-oxide.conf -profile_lines=3194 -profile_sha256=aa9fa3581c86cf1f1ef786a54c2023107f3a99002129b726024ddd8ea0838d67 +profile_lines=3208 +profile_sha256=5b7327f5f3606ed732a799241efec90f4ce01d6e08e2477745fc1a9e4dce4cfe negative_diagnostics=dev-support/test262/negative-diagnostics.tsv -negative_diagnostics_lines=2945 -negative_diagnostics_sha256=0f20554444b18fe2a714732b392a72785d88e8b315620bd619b473c93b7f01bf +negative_diagnostics_lines=2973 +negative_diagnostics_sha256=e4cf946bd0e83f8ad1271a29a1486506f33f116e415cdb21ea2709ab183025ac negative_diagnostic_rules=dev-support/test262/negative-diagnostic-rules.tsv -negative_diagnostic_rules_lines=78 -negative_diagnostic_rules_sha256=e238443877c19f6f1086a97d34adc755a62970e7e31dc800619291c68dcc0fcc +negative_diagnostic_rules_lines=79 +negative_diagnostic_rules_sha256=c3cafa5a9d697fc6247171aa189a86cce53664338007df5148ba8b4b62cafc89 negative_diagnostic_audit_tool=scripts/test262/audit-negative-diagnostics.mjs negative_diagnostic_audit_tool_lines=942 negative_diagnostic_audit_tool_sha256=8f84d6d3a95297862c47e04e37372aec18f73f7fb09f830971725fd3b7c0228e diff --git a/dev-support/test262/negative-diagnostic-rules.tsv b/dev-support/test262/negative-diagnostic-rules.tsv index 3006483c..5be38878 100644 --- a/dev-support/test262/negative-diagnostic-rules.tsv +++ b/dev-support/test262/negative-diagnostic-rules.tsv @@ -68,6 +68,7 @@ module.missing-export js_resolve_export_throw_error module resolution reports a module.tla-dependency-rejection js_async_module_execution_rejected async module evaluation propagates the dependency rejection unchanged module.top-level-await.escaped-keyword js_parse_error_reserved_identifier the await terminal cannot contain Unicode escapes module.top-level-await.function-context js_parse_unary the Await grammar parameter does not propagate into nested function syntax +numeric-literal.invalid js_parse_get_number malformed numeric and BigInt literals share the single QuickJS invalid number literal diagnostic object-literal.private-name js_parse_object_literal private names are invalid object literal properties optional-chaining.invalid-assignment-target get_lvalue optional chains are not assignment targets regexp.flags.unicode-mode-conflict lre_compile the u and v Unicode modes are mutually exclusive diff --git a/dev-support/test262/negative-diagnostics.tsv b/dev-support/test262/negative-diagnostics.tsv index aa9d0204..f133aad6 100644 --- a/dev-support/test262/negative-diagnostics.tsv +++ b/dev-support/test262/negative-diagnostics.tsv @@ -1828,6 +1828,34 @@ test/language/identifier-resolution/static-init-invalid-await.js sloppy 255d713c test/language/identifier-resolution/static-init-invalid-await.js strict 255d713c335cc9ffcaad5cec3e350d7ee20f8dce60e882f66a71388bd6a74ffb parse SyntaxError class-static-block.await-context unexpected 'await' keyword 24 5 exact test/language/import/import-attributes/json-invalid.js sloppy 721e75c25d4839b55206c70b09d12fbd7e6f37d36081f1c982a11e4aebfa3e76 resolution SyntaxError module.json-parse expecting property name 2 3 exact test/language/import/import-attributes/json-named-bindings.js sloppy f6725a7d6e92ff06fd725a05fb8402bc9952f29357a344660378b37fa556a1dd resolution SyntaxError module.missing-export Could not find export 'name' in module 'test/language/import/import-attributes/json-named-bindings_FIXTURE.json' absent +test/language/literals/bigint/binary-invalid-digit.js sloppy e7e79e572d5ad384bccacd1791828292eee524854c7614fda3007bebb4a73491 parse SyntaxError numeric-literal.invalid invalid number literal 26 1 exact +test/language/literals/bigint/binary-invalid-digit.js strict e7e79e572d5ad384bccacd1791828292eee524854c7614fda3007bebb4a73491 parse SyntaxError numeric-literal.invalid invalid number literal 27 1 exact +test/language/literals/bigint/exponent-part.js sloppy aa28ffdf429c4cf0ce43fc705fc98594ab1607a2d19f4762cf02f55404ba6cdc parse SyntaxError numeric-literal.invalid invalid number literal 16 1 exact +test/language/literals/bigint/exponent-part.js strict aa28ffdf429c4cf0ce43fc705fc98594ab1607a2d19f4762cf02f55404ba6cdc parse SyntaxError numeric-literal.invalid invalid number literal 17 1 exact +test/language/literals/bigint/hexadecimal-invalid-digit.js sloppy b1cbede6feac553e3bf1a3ede63ebcfcd9f4d17bee81a610bbbb8614212315c7 parse SyntaxError numeric-literal.invalid invalid number literal 26 1 exact +test/language/literals/bigint/hexadecimal-invalid-digit.js strict b1cbede6feac553e3bf1a3ede63ebcfcd9f4d17bee81a610bbbb8614212315c7 parse SyntaxError numeric-literal.invalid invalid number literal 27 1 exact +test/language/literals/bigint/mv-is-not-integer-dil-dot-dds.js sloppy b311e04e37639ee42799be9a7c3560bc9561264fed953992b474eeef75b5e846 parse SyntaxError numeric-literal.invalid invalid number literal 27 1 exact +test/language/literals/bigint/mv-is-not-integer-dil-dot-dds.js strict b311e04e37639ee42799be9a7c3560bc9561264fed953992b474eeef75b5e846 parse SyntaxError numeric-literal.invalid invalid number literal 28 1 exact +test/language/literals/bigint/mv-is-not-integer-dot-dds.js sloppy 1b12408b8c3347301244e76e7fa77d7cfcd0d8aa4369e2c18db2a8cc498b6496 parse SyntaxError numeric-literal.invalid invalid number literal 27 1 exact +test/language/literals/bigint/mv-is-not-integer-dot-dds.js strict 1b12408b8c3347301244e76e7fa77d7cfcd0d8aa4369e2c18db2a8cc498b6496 parse SyntaxError numeric-literal.invalid invalid number literal 28 1 exact +test/language/literals/bigint/octal-invalid-digit.js sloppy e5a5e3dd821b995f2f541c96998c3763faeaefc419e26a139afc20d3b140f884 parse SyntaxError numeric-literal.invalid invalid number literal 26 1 exact +test/language/literals/bigint/octal-invalid-digit.js strict e5a5e3dd821b995f2f541c96998c3763faeaefc419e26a139afc20d3b140f884 parse SyntaxError numeric-literal.invalid invalid number literal 27 1 exact +test/language/literals/numeric/S7.8.3_A6.1_T1.js sloppy 01d2089310638f3ca289b808ef5c6d1dc9f08c6b6bdc6e8bfbf5389d6f9aafc8 parse SyntaxError numeric-literal.invalid invalid number literal 16 1 exact +test/language/literals/numeric/S7.8.3_A6.1_T1.js strict 01d2089310638f3ca289b808ef5c6d1dc9f08c6b6bdc6e8bfbf5389d6f9aafc8 parse SyntaxError numeric-literal.invalid invalid number literal 17 1 exact +test/language/literals/numeric/S7.8.3_A6.1_T2.js sloppy 01f2d2e116ac0b6fd3bb4c5415ca130a0d1b58987f52ef99b667c9309b32df87 parse SyntaxError numeric-literal.invalid invalid number literal 16 1 exact +test/language/literals/numeric/S7.8.3_A6.1_T2.js strict 01f2d2e116ac0b6fd3bb4c5415ca130a0d1b58987f52ef99b667c9309b32df87 parse SyntaxError numeric-literal.invalid invalid number literal 17 1 exact +test/language/literals/numeric/S7.8.3_A6.2_T1.js sloppy b86e909498e91bc5ff23fd6d7ba67500d0114f0f00781ebe9a9a4f1059ac8997 parse SyntaxError numeric-literal.invalid invalid number literal 16 1 exact +test/language/literals/numeric/S7.8.3_A6.2_T1.js strict b86e909498e91bc5ff23fd6d7ba67500d0114f0f00781ebe9a9a4f1059ac8997 parse SyntaxError numeric-literal.invalid invalid number literal 17 1 exact +test/language/literals/numeric/S7.8.3_A6.2_T2.js sloppy 7546b6bce1526552b9b602ee8e81cbb73055c51a353598af2f2b05d67fb8b44e parse SyntaxError numeric-literal.invalid invalid number literal 16 1 exact +test/language/literals/numeric/S7.8.3_A6.2_T2.js strict 7546b6bce1526552b9b602ee8e81cbb73055c51a353598af2f2b05d67fb8b44e parse SyntaxError numeric-literal.invalid invalid number literal 17 1 exact +test/language/literals/numeric/binary-invalid-digit.js sloppy 497cf540a29de8280c08931c0142b34aab8d5aae0f78108393e7c02fd9c2b943 parse SyntaxError numeric-literal.invalid invalid number literal 23 1 exact +test/language/literals/numeric/binary-invalid-digit.js strict 497cf540a29de8280c08931c0142b34aab8d5aae0f78108393e7c02fd9c2b943 parse SyntaxError numeric-literal.invalid invalid number literal 24 1 exact +test/language/literals/numeric/binary-invalid-truncated.js sloppy 831cd030540a182e06e59dac3e12f74d9b7dafbe3a2842de3af648f37b662a7e parse SyntaxError numeric-literal.invalid invalid number literal 23 1 exact +test/language/literals/numeric/binary-invalid-truncated.js strict 831cd030540a182e06e59dac3e12f74d9b7dafbe3a2842de3af648f37b662a7e parse SyntaxError numeric-literal.invalid invalid number literal 24 1 exact +test/language/literals/numeric/octal-invalid-digit.js sloppy eabf1f14e9cb59d585e6c703993883f81fee710fd53702731af862dd974747be parse SyntaxError numeric-literal.invalid invalid number literal 23 1 exact +test/language/literals/numeric/octal-invalid-digit.js strict eabf1f14e9cb59d585e6c703993883f81fee710fd53702731af862dd974747be parse SyntaxError numeric-literal.invalid invalid number literal 24 1 exact +test/language/literals/numeric/octal-invalid-truncated.js sloppy a995268a8f2f49c1a137c2eb08b7d7c86716b7134113408c3898a28d4a7437cc parse SyntaxError numeric-literal.invalid invalid number literal 23 1 exact +test/language/literals/numeric/octal-invalid-truncated.js strict a995268a8f2f49c1a137c2eb08b7d7c86716b7134113408c3898a28d4a7437cc parse SyntaxError numeric-literal.invalid invalid number literal 24 1 exact test/language/module-code/early-import-arguments.js sloppy f7bd4a8d7f839d89ed84922588b5242f5bdd9d9e01114ebe2b1dbe827cc8fd50 parse SyntaxError module.invalid-import-binding invalid import binding 35 20 exact test/language/module-code/early-import-as-arguments.js sloppy d2761605cdd1657cb54fdbca1b45d9d46a6a6063523e884783c2c80909cae753 parse SyntaxError module.invalid-import-binding invalid import binding 35 25 exact test/language/module-code/early-import-as-eval.js sloppy 742fbd6917df4cb1fe5e0058504c83afe15ac2588ef370977962672d61ccf230 parse SyntaxError module.invalid-import-binding invalid import binding 35 20 exact