-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
perf(es/compat): Merge regexp pass into Transformer
#11307
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
b6abb58
ef5f638
57e349e
f24d4aa
b67ab31
480d61b
46eb206
8061b5f
e7b992e
6882d23
68be702
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,4 +1,7 @@ | ||||||||||||||
| use swc_common::util::take::Take; | ||||||||||||||
| use swc_ecma_ast::*; | ||||||||||||||
| use swc_ecma_hooks::VisitMutHook; | ||||||||||||||
| use swc_ecma_utils::{quote_ident, ExprFactory}; | ||||||||||||||
|
|
||||||||||||||
| use crate::TraverseCtx; | ||||||||||||||
|
|
||||||||||||||
|
|
@@ -44,4 +47,38 @@ struct RegexpPass { | |||||||||||||
| options: RegExpOptions, | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| impl VisitMutHook<TraverseCtx> for RegexpPass {} | ||||||||||||||
| impl VisitMutHook<TraverseCtx> for RegexpPass { | ||||||||||||||
| fn exit_expr(&mut self, expr: &mut Expr, _: &mut TraverseCtx) { | ||||||||||||||
| if let Expr::Lit(Lit::Regex(regex)) = expr { | ||||||||||||||
| if (self.options.dot_all_regex && regex.flags.contains('s')) | ||||||||||||||
| || (self.options.sticky_regex && regex.flags.contains('y')) | ||||||||||||||
| || (self.options.unicode_regex && regex.flags.contains('u')) | ||||||||||||||
| || (self.options.unicode_sets_regex && regex.flags.contains('v')) | ||||||||||||||
| || (self.options.has_indices && regex.flags.contains('d')) | ||||||||||||||
| || (self.options.named_capturing_groups_regex && regex.exp.contains("(?<")) | ||||||||||||||
| || (self.options.lookbehind_assertion && regex.exp.contains("(?<=") | ||||||||||||||
| || regex.exp.contains("(?<!")) | ||||||||||||||
|
Comment on lines
+59
to
+60
|
||||||||||||||
| || (self.options.lookbehind_assertion && regex.exp.contains("(?<=") | |
| || regex.exp.contains("(?<!")) | |
| || (self.options.lookbehind_assertion && (regex.exp.contains("(?<=") || regex.exp.contains("(?<!"))) |
Copilot
AI
Nov 19, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Operator precedence issue: the condition for lookbehind_assertion is incorrectly grouped. Line 60's || regex.exp.contains(\"(?<!\") is not checked against self.options.lookbehind_assertion, so negative lookbehind patterns (?<!) will always be transformed regardless of the option setting. Add parentheses around the entire lookbehind check: || (self.options.lookbehind_assertion && (regex.exp.contains(\"(?<=\") || regex.exp.contains(\"(?<!\")))
| || (self.options.lookbehind_assertion && regex.exp.contains("(?<=") | |
| || regex.exp.contains("(?<!")) | |
| || (self.options.lookbehind_assertion && (regex.exp.contains("(?<=") || regex.exp.contains("(?<!"))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The output shows inconsistent behavior where variable
cis transformed tonew RegExp(...)while variablesaandbon lines 4-5 are transformed toRegExp(...)without thenewkeyword. Since the transformation code creates aCallExprwithoutnew, this suggests an unintended change in behavior. Please verify that this test output is correct or investigate why thenewkeyword is being added for this specific case.