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
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion crates/oxc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,16 @@ required-features = ["full"]
[dependencies]
oxc_allocator = { workspace = true }
oxc_ast = { workspace = true }
oxc_parser = { workspace = true }
oxc_regular_expression = { workspace = true }

oxc_cfg = { workspace = true, optional = true }
oxc_codegen = { workspace = true, optional = true }
oxc_diagnostics = { workspace = true }
oxc_index = { workspace = true }
oxc_isolated_declarations = { workspace = true, optional = true }
oxc_mangler = { workspace = true, optional = true }
oxc_minifier = { workspace = true, optional = true }
oxc_parser = { workspace = true }
oxc_semantic = { workspace = true, optional = true }
oxc_sourcemap = { workspace = true, optional = true }
oxc_span = { workspace = true }
Expand Down
5 changes: 5 additions & 0 deletions crates/oxc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ pub mod parser {
pub use oxc_parser::*;
}

pub mod regular_expression {
#[doc(inline)]
pub use oxc_regular_expression::*;
}

pub mod span {
#[doc(inline)]
pub use oxc_span::*;
Expand Down
5 changes: 4 additions & 1 deletion tasks/coverage/parser_test262.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ commit: d62fa93c

parser_test262 Summary:
AST Parsed : 43765/43765 (100.00%)
Positive Passed: 43765/43765 (100.00%)
Positive Passed: 43764/43765 (100.00%)
Negative Passed: 4237/4237 (100.00%)
Expect to Parse: tasks/coverage/test262/test/annexB/language/literals/regexp/legacy-octal-escape.js

× Regular Expression mismatch: \03 \3

× '0'-prefixed octal literals and octal escape sequences are deprecated
╭─[test262/test/annexB/language/expressions/template-literal/legacy-octal-escape-sequence-strict.js:19:4]
Expand Down
5 changes: 4 additions & 1 deletion tasks/coverage/semantic_test262.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ commit: d62fa93c

semantic_test262 Summary:
AST Parsed : 43765/43765 (100.00%)
Positive Passed: 43565/43765 (99.54%)
Positive Passed: 43564/43765 (99.54%)
tasks/coverage/test262/test/annexB/language/function-code/if-decl-else-decl-a-func-block-scoping.js
semantic error: Symbol scope ID mismatch:
after transform: SymbolId(3): ScopeId(4294967294)
Expand Down Expand Up @@ -1119,6 +1119,9 @@ semantic error: Symbol scope ID mismatch:
after transform: SymbolId(0): ScopeId(4294967294)
rebuilt : SymbolId(0): ScopeId(4294967294)

tasks/coverage/test262/test/annexB/language/literals/regexp/legacy-octal-escape.js
semantic error: Regular Expression mismatch: \03 \3

tasks/coverage/test262/test/language/module-code/eval-rqstd-once.js
semantic error: Bindings mismatch:
after transform: ScopeId(0): ["dflt1", "dflt2", "dflt3", "global", "ns1", "ns3"]
Expand Down
49 changes: 46 additions & 3 deletions tasks/coverage/src/driver.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
use std::{collections::HashSet, ops::ControlFlow, path::PathBuf};

use oxc::{
ast::{ast::Program, Trivias},
allocator::Allocator,
ast::{
ast::{Program, RegExpFlags},
Trivias,
},
codegen::CodegenOptions,
diagnostics::OxcDiagnostic,
minifier::CompressOptions,
parser::{ParseOptions, ParserReturn},
regular_expression::{ParserOptions, PatternParser},
semantic::{
post_transform_checker::{check_semantic_after_transform, check_semantic_ids},
SemanticBuilderReturn,
Semantic, SemanticBuilderReturn,
},
span::{SourceType, Span},
transformer::{TransformOptions, TransformerReturn},
Expand Down Expand Up @@ -78,14 +83,15 @@ impl CompilerInterface for Driver {
fn after_semantic(
&mut self,
program: &mut Program<'_>,
_semantic_return: &mut SemanticBuilderReturn,
ret: &mut SemanticBuilderReturn,
) -> ControlFlow<()> {
if self.check_semantic {
if let Some(errors) = check_semantic_ids(program) {
self.errors.extend(errors);
return ControlFlow::Break(());
}
};
self.check_regular_expressions(&ret.semantic);
ControlFlow::Continue(())
}

Expand Down Expand Up @@ -150,4 +156,41 @@ impl Driver {
}
false
}

/// Idempotency test for printing regular expressions.
fn check_regular_expressions(&mut self, semantic: &Semantic<'_>) {
let allocator = Allocator::default();
for literal in semantic.nodes().iter().filter_map(|node| node.kind().as_reg_exp_literal()) {
let Some(pattern) = literal.regex.pattern.as_pattern() else {
continue;
};
let printed1 = pattern.to_string();
let flags = literal.regex.flags;
let printed2 = match PatternParser::new(
&allocator,
&printed1,
ParserOptions {
span_offset: 0,
unicode_mode: flags.contains(RegExpFlags::U) || flags.contains(RegExpFlags::V),
unicode_sets_mode: flags.contains(RegExpFlags::V),
},
)
.parse()
{
Ok(pattern) => pattern.to_string(),
Err(error) => {
self.errors.push(OxcDiagnostic::error(format!(
"Failed to re-parse `{}`, printed as `/{printed1}/{flags}`, {error}",
literal.span.source_text(semantic.source_text()),
)));
continue;
}
};
if printed1 != printed2 {
self.errors.push(OxcDiagnostic::error(format!(
"Regular Expression mismatch: {printed1} {printed2}"
)));
}
}
}
}