mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 04:08:41 +00:00
feat(transformer): support all /regex/ to new RegExp transforms (#5387)
related: #4754
The implementation port from [esbuild](332727499e/internal/js_parser/js_parser.go (L12820-L12840)). And cover all babel's regexp plugins
---
## The following description was generated by `Graphite` 😋
### TL;DR
Added support for transforming various RegExp features to ensure compatibility with older JavaScript environments.
### What changed?
- Implemented a new `RegExp` transformer to handle unsupported RegExp literal features
- Added options to control different RegExp transformations (e.g., sticky flag, unicode flag, dot-all flag, etc.)
- Updated the transformer to convert unsupported RegExp literals into `new RegExp()` constructor calls
- Added test cases for different RegExp transformations
- Integrated the new RegExp transformer into the existing transformation pipeline
### How to test?
1. Run the existing test suite to ensure no regressions
2. Execute the new RegExp-specific tests in the `tasks/transform_conformance/tests/esbuild-tests/test/fixtures/regexp/` directory
3. Try transforming code with various RegExp features using different target environments to verify correct transformations
This commit is contained in:
parent
d9d29f8705
commit
c59d8b3c9b
35 changed files with 477 additions and 44 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
|
@ -1955,6 +1955,7 @@ dependencies = [
|
|||
"oxc_codegen",
|
||||
"oxc_diagnostics",
|
||||
"oxc_parser",
|
||||
"oxc_regular_expression",
|
||||
"oxc_semantic",
|
||||
"oxc_span",
|
||||
"oxc_syntax",
|
||||
|
|
|
|||
|
|
@ -21,13 +21,14 @@ test = false
|
|||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
oxc_ast = { workspace = true }
|
||||
oxc_span = { workspace = true }
|
||||
oxc_allocator = { workspace = true }
|
||||
oxc_diagnostics = { workspace = true }
|
||||
oxc_syntax = { workspace = true, features = ["to_js_string"] }
|
||||
oxc_traverse = { workspace = true }
|
||||
oxc_semantic = { workspace = true }
|
||||
oxc_ast = { workspace = true }
|
||||
oxc_span = { workspace = true }
|
||||
oxc_allocator = { workspace = true }
|
||||
oxc_diagnostics = { workspace = true }
|
||||
oxc_syntax = { workspace = true, features = ["to_js_string"] }
|
||||
oxc_traverse = { workspace = true }
|
||||
oxc_semantic = { workspace = true }
|
||||
oxc_regular_expression = { workspace = true }
|
||||
|
||||
dashmap = { workspace = true }
|
||||
indexmap = { workspace = true }
|
||||
|
|
|
|||
9
crates/oxc_transformer/src/env/data/babel.rs
vendored
9
crates/oxc_transformer/src/env/data/babel.rs
vendored
|
|
@ -8,10 +8,17 @@ use crate::env::{targets::version::Version, Versions};
|
|||
fn features() -> &'static FxHashMap<String, Versions> {
|
||||
static FEATURES: OnceLock<FxHashMap<String, Versions>> = OnceLock::new();
|
||||
FEATURES.get_or_init(|| {
|
||||
let map: FxHashMap<String, FxHashMap<String, String>> =
|
||||
let mut map: FxHashMap<String, FxHashMap<String, String>> =
|
||||
serde_json::from_str(include_str!("./@babel/compat_data/data/plugins.json"))
|
||||
.expect("failed to parse json");
|
||||
|
||||
map.extend(
|
||||
serde_json::from_str::<FxHashMap<String, FxHashMap<String, String>>>(include_str!(
|
||||
"./esbuild/features.json"
|
||||
))
|
||||
.expect("failed to parse json"),
|
||||
);
|
||||
|
||||
map.into_iter()
|
||||
.map(|(feature, mut versions)| {
|
||||
(feature, {
|
||||
|
|
|
|||
23
crates/oxc_transformer/src/env/data/esbuild/features.json
vendored
Normal file
23
crates/oxc_transformer/src/env/data/esbuild/features.json
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"esbuild-regexp-lookbehind-assertions": {
|
||||
"chrome": "62",
|
||||
"deno": "1.0",
|
||||
"edge": "79",
|
||||
"firefox": "78",
|
||||
"hermes": "0.7",
|
||||
"ios": "16.4",
|
||||
"node": "8.10",
|
||||
"opera": "49",
|
||||
"safari": "16.4"
|
||||
},
|
||||
"esbuild-regexp-match-indices": {
|
||||
"chrome": "90",
|
||||
"deno": "1.8",
|
||||
"edge": "90",
|
||||
"firefox": "88",
|
||||
"ios": "15.0",
|
||||
"node": "16.0",
|
||||
"opera": "76",
|
||||
"safari": "15.0"
|
||||
}
|
||||
}
|
||||
|
|
@ -21,6 +21,7 @@ mod es2019;
|
|||
mod es2020;
|
||||
mod es2021;
|
||||
mod react;
|
||||
mod regexp;
|
||||
mod typescript;
|
||||
|
||||
mod helpers {
|
||||
|
|
@ -41,6 +42,7 @@ use oxc_diagnostics::OxcDiagnostic;
|
|||
use oxc_semantic::{ScopeTree, SymbolTable};
|
||||
use oxc_span::{SourceType, SPAN};
|
||||
use oxc_traverse::{traverse_mut, Traverse, TraverseCtx};
|
||||
use regexp::RegExp;
|
||||
|
||||
pub use crate::{
|
||||
compiler_assumptions::CompilerAssumptions,
|
||||
|
|
@ -74,6 +76,7 @@ pub struct Transformer<'a> {
|
|||
x2_es2018: ES2018<'a>,
|
||||
x2_es2016: ES2016<'a>,
|
||||
x3_es2015: ES2015<'a>,
|
||||
x4_regexp: RegExp<'a>,
|
||||
}
|
||||
|
||||
impl<'a> Transformer<'a> {
|
||||
|
|
@ -102,7 +105,8 @@ impl<'a> Transformer<'a> {
|
|||
x2_es2019: ES2019::new(options.es2019, Rc::clone(&ctx)),
|
||||
x2_es2018: ES2018::new(options.es2018, Rc::clone(&ctx)),
|
||||
x2_es2016: ES2016::new(options.es2016, Rc::clone(&ctx)),
|
||||
x3_es2015: ES2015::new(options.es2015, ctx),
|
||||
x3_es2015: ES2015::new(options.es2015, Rc::clone(&ctx)),
|
||||
x4_regexp: RegExp::new(options.regexp, ctx),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -177,6 +181,7 @@ impl<'a> Traverse<'a> for Transformer<'a> {
|
|||
self.x2_es2018.enter_expression(expr, ctx);
|
||||
self.x2_es2016.enter_expression(expr, ctx);
|
||||
self.x3_es2015.enter_expression(expr, ctx);
|
||||
self.x4_regexp.enter_expression(expr, ctx);
|
||||
}
|
||||
|
||||
fn exit_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ use crate::{
|
|||
es2021::ES2021Options,
|
||||
options::babel::BabelOptions,
|
||||
react::ReactOptions,
|
||||
regexp::RegExpOptions,
|
||||
typescript::TypeScriptOptions,
|
||||
};
|
||||
|
||||
|
|
@ -38,6 +39,8 @@ pub struct TransformOptions {
|
|||
/// [preset-react](https://babeljs.io/docs/babel-preset-react)
|
||||
pub react: ReactOptions,
|
||||
|
||||
pub regexp: RegExpOptions,
|
||||
|
||||
pub es2015: ES2015Options,
|
||||
|
||||
pub es2016: ES2016Options,
|
||||
|
|
@ -60,6 +63,7 @@ impl TransformOptions {
|
|||
es2019: ES2019Options::from_targets_and_bugfixes(targets, bugfixes),
|
||||
es2020: ES2020Options::from_targets_and_bugfixes(targets, bugfixes),
|
||||
es2021: ES2021Options::from_targets_and_bugfixes(targets, bugfixes),
|
||||
regexp: RegExpOptions::from_targets_and_bugfixes(targets, bugfixes),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
|
@ -215,6 +219,29 @@ impl TransformOptions {
|
|||
}
|
||||
};
|
||||
|
||||
let regexp = transformer_options.regexp;
|
||||
if !regexp.sticky_flag {
|
||||
transformer_options.regexp.sticky_flag = options.has_plugin("transform-sticky-regex");
|
||||
}
|
||||
if !regexp.unicode_flag {
|
||||
transformer_options.regexp.unicode_flag = options.has_plugin("transform-unicode-regex");
|
||||
}
|
||||
if !regexp.dot_all_flag {
|
||||
transformer_options.regexp.dot_all_flag = options.has_plugin("transform-dotall-regex");
|
||||
}
|
||||
if !regexp.named_capture_groups {
|
||||
transformer_options.regexp.named_capture_groups =
|
||||
options.has_plugin("transform-named-capturing-groups-regex");
|
||||
}
|
||||
if !regexp.unicode_property_escapes {
|
||||
transformer_options.regexp.unicode_property_escapes =
|
||||
options.has_plugin("transform-unicode-property-regex");
|
||||
}
|
||||
if !regexp.set_notation {
|
||||
transformer_options.regexp.set_notation =
|
||||
options.has_plugin("transform-unicode-sets-regex");
|
||||
}
|
||||
|
||||
transformer_options.assumptions = if options.assumptions.is_null() {
|
||||
CompilerAssumptions::default()
|
||||
} else {
|
||||
|
|
|
|||
218
crates/oxc_transformer/src/regexp/mod.rs
Normal file
218
crates/oxc_transformer/src/regexp/mod.rs
Normal file
|
|
@ -0,0 +1,218 @@
|
|||
//! RegExp Transformer
|
||||
//!
|
||||
//! This module supports various RegExp plugins to handle unsupported RegExp literal features.
|
||||
//! When an unsupported feature is detected, these plugins convert the RegExp literal into
|
||||
//! a `new RegExp()` constructor call to avoid syntax errors.
|
||||
//!
|
||||
//! Note: You will need to include a polyfill for the `RegExp` constructor in your code to have the correct runtime behavior.
|
||||
//!
|
||||
//! ### ES2015
|
||||
//!
|
||||
//! #### Sticky flag (`y`)
|
||||
//! - @babel/plugin-transform-sticky-regex: <https://babeljs.io/docs/en/babel-plugin-transform-sticky-regex>
|
||||
//!
|
||||
//! #### Unicode flag (`u`)
|
||||
//! - @babel/plugin-transform-unicode-regex: <https://babeljs.io/docs/en/babel-plugin-transform-unicode-regex>
|
||||
//!
|
||||
//! ### ES2018
|
||||
//!
|
||||
//! #### DotAll flag (`s`)
|
||||
//! - @babel/plugin-transform-dotall-regex: <https://babeljs.io/docs/en/babel-plugin-transform-dotall-regex>
|
||||
//! - Spec: ECMAScript 2018: <https://262.ecma-international.org/9.0/#sec-get-regexp.prototype.dotAll>
|
||||
//!
|
||||
//! #### Lookbehind assertions (`/(?<=x)/` and `/(?<!x)/`)
|
||||
//! - Implementation: Same as esbuild's handling
|
||||
//!
|
||||
//! #### Named capture groups (`(?<name>x)`)
|
||||
//! - @babel/plugin-transform-named-capturing-groups-regex: <https://babeljs.io/docs/en/babel-plugin-transform-named-capturing-groups-regex>
|
||||
//!
|
||||
//! #### Unicode property escapes (`\p{...}` and `\P{...}`)
|
||||
//! - @babel/plugin-transform-unicode-property-regex: <https://babeljs.io/docs/en/babel-plugin-proposal-unicode-property-regex>
|
||||
//!
|
||||
//! ### ES2022
|
||||
//!
|
||||
//! #### Match indices flag (`d`)
|
||||
//! - Implementation: Same as esbuild's handling
|
||||
//!
|
||||
//! ### ES2024
|
||||
//!
|
||||
//! #### Set notation + properties of strings (`v`)
|
||||
//! - @babel/plugin-transform-unicode-sets-regex: <https://babeljs.io/docs/en/babel-plugin-proposal-unicode-sets-regex>
|
||||
//! - TC39 Proposal: <https://github.com/tc39/proposal-regexp-set-notation>
|
||||
|
||||
mod options;
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::mem;
|
||||
|
||||
pub use options::RegExpOptions;
|
||||
use oxc_allocator::Box;
|
||||
use oxc_allocator::Vec;
|
||||
use oxc_ast::ast::*;
|
||||
use oxc_regular_expression::ast::{
|
||||
CharacterClass, CharacterClassContents, LookAroundAssertionKind, Pattern, Term,
|
||||
};
|
||||
use oxc_semantic::ReferenceFlags;
|
||||
use oxc_span::Atom;
|
||||
use oxc_traverse::{Traverse, TraverseCtx};
|
||||
|
||||
use crate::context::Ctx;
|
||||
|
||||
pub struct RegExp<'a> {
|
||||
_ctx: Ctx<'a>,
|
||||
options: RegExpOptions,
|
||||
}
|
||||
|
||||
impl<'a> RegExp<'a> {
|
||||
pub fn new(options: RegExpOptions, ctx: Ctx<'a>) -> Self {
|
||||
Self { _ctx: ctx, options }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Traverse<'a> for RegExp<'a> {
|
||||
fn enter_expression(
|
||||
&mut self,
|
||||
expr: &mut Expression<'a>,
|
||||
ctx: &mut oxc_traverse::TraverseCtx<'a>,
|
||||
) {
|
||||
let Expression::RegExpLiteral(ref mut regexp) = expr else {
|
||||
return;
|
||||
};
|
||||
|
||||
if !self.has_unsupported_regular_expression_flags(regexp.regex.flags)
|
||||
&& self.requires_pattern_analysis()
|
||||
{
|
||||
match try_parse_pattern(regexp, ctx) {
|
||||
Ok(pattern) => {
|
||||
let is_unsupported = self.has_unsupported_regular_expression_pattern(&pattern);
|
||||
regexp.regex.pattern = RegExpPattern::Pattern(pattern);
|
||||
if !is_unsupported {
|
||||
return;
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
regexp.regex.pattern = RegExpPattern::Invalid(err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let pattern_source: Cow<'_, str> = match ®exp.regex.pattern {
|
||||
RegExpPattern::Raw(raw) | RegExpPattern::Invalid(raw) => Cow::Borrowed(raw),
|
||||
RegExpPattern::Pattern(p) => Cow::Owned(p.to_string()),
|
||||
};
|
||||
|
||||
let callee = {
|
||||
let symbol_id = ctx.scopes().find_binding(ctx.current_scope_id(), "RegExp");
|
||||
let ident = ctx.create_reference_id(
|
||||
regexp.span,
|
||||
Atom::from("RegExp"),
|
||||
symbol_id,
|
||||
ReferenceFlags::read(),
|
||||
);
|
||||
ctx.ast.expression_from_identifier_reference(ident)
|
||||
};
|
||||
|
||||
let mut arguments = ctx.ast.vec_with_capacity(2);
|
||||
arguments.push(
|
||||
ctx.ast.argument_expression(
|
||||
ctx.ast.expression_string_literal(regexp.span, pattern_source),
|
||||
),
|
||||
);
|
||||
|
||||
let flags = regexp.regex.flags.to_string();
|
||||
let flags =
|
||||
ctx.ast.argument_expression(ctx.ast.expression_string_literal(regexp.span, flags));
|
||||
arguments.push(flags);
|
||||
|
||||
*expr = ctx.ast.expression_new(
|
||||
regexp.span,
|
||||
callee,
|
||||
arguments,
|
||||
None::<TSTypeParameterInstantiation>,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> RegExp<'a> {
|
||||
fn requires_pattern_analysis(&self) -> bool {
|
||||
self.options.named_capture_groups
|
||||
|| self.options.unicode_property_escapes
|
||||
|| self.options.look_behind_assertions
|
||||
}
|
||||
|
||||
/// Check if the regular expression contains any unsupported flags.
|
||||
fn has_unsupported_regular_expression_flags(&self, flags: RegExpFlags) -> bool {
|
||||
flags.iter().any(|f| match f {
|
||||
RegExpFlags::S if self.options.dot_all_flag => true,
|
||||
RegExpFlags::Y if self.options.sticky_flag => true,
|
||||
RegExpFlags::U if self.options.unicode_flag => true,
|
||||
RegExpFlags::D if self.options.match_indices => true,
|
||||
RegExpFlags::V if self.options.set_notation => true,
|
||||
_ => false,
|
||||
})
|
||||
}
|
||||
|
||||
/// Check if the regular expression contains any unsupported syntax.
|
||||
///
|
||||
/// Based on parsed regular expression pattern.
|
||||
fn has_unsupported_regular_expression_pattern(&self, pattern: &Pattern<'a>) -> bool {
|
||||
let check_terms = |terms: &Vec<'a, Term>| {
|
||||
terms.iter().any(|element| match element {
|
||||
Term::CapturingGroup(_) if self.options.named_capture_groups => true,
|
||||
Term::UnicodePropertyEscape(_) if self.options.unicode_property_escapes => true,
|
||||
Term::CharacterClass(character_class) if self.options.unicode_property_escapes => {
|
||||
has_unicode_property_escape_character_class(character_class)
|
||||
}
|
||||
Term::LookAroundAssertion(assertion)
|
||||
if self.options.look_behind_assertions
|
||||
&& matches!(
|
||||
assertion.kind,
|
||||
LookAroundAssertionKind::Lookbehind
|
||||
| LookAroundAssertionKind::NegativeLookbehind
|
||||
) =>
|
||||
{
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
})
|
||||
};
|
||||
|
||||
pattern.body.body.iter().any(|alternative| check_terms(&alternative.body))
|
||||
}
|
||||
}
|
||||
|
||||
fn has_unicode_property_escape_character_class(character_class: &CharacterClass) -> bool {
|
||||
character_class.body.iter().any(|element| match element {
|
||||
CharacterClassContents::UnicodePropertyEscape(_) => true,
|
||||
CharacterClassContents::NestedCharacterClass(character_class) => {
|
||||
has_unicode_property_escape_character_class(character_class)
|
||||
}
|
||||
_ => false,
|
||||
})
|
||||
}
|
||||
|
||||
fn try_parse_pattern<'a>(
|
||||
literal: &mut RegExpLiteral<'a>,
|
||||
ctx: &mut TraverseCtx<'a>,
|
||||
) -> Result<Box<'a, Pattern<'a>>, &'a str> {
|
||||
// Take the ownership of the pattern
|
||||
let regexp_pattern = mem::replace(&mut literal.regex.pattern, RegExpPattern::Raw(""));
|
||||
|
||||
match regexp_pattern {
|
||||
RegExpPattern::Raw(raw) => {
|
||||
use oxc_regular_expression::{ParserOptions, PatternParser};
|
||||
let options = ParserOptions {
|
||||
span_offset: literal.span.start + 1, // exclude `/`
|
||||
unicode_mode: literal.regex.flags.contains(RegExpFlags::U)
|
||||
|| literal.regex.flags.contains(RegExpFlags::V),
|
||||
unicode_sets_mode: literal.regex.flags.contains(RegExpFlags::V),
|
||||
};
|
||||
PatternParser::new(ctx.ast.allocator, raw, options)
|
||||
.parse()
|
||||
.map_or_else(|_| Err(raw), |p| Ok(ctx.alloc(p)))
|
||||
}
|
||||
RegExpPattern::Pattern(pattern) => Ok(pattern),
|
||||
RegExpPattern::Invalid(raw) => Err(raw),
|
||||
}
|
||||
}
|
||||
49
crates/oxc_transformer/src/regexp/options.rs
Normal file
49
crates/oxc_transformer/src/regexp/options.rs
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
use crate::env::{can_enable_plugin, Versions};
|
||||
|
||||
#[derive(Default, Debug, Clone, Copy)]
|
||||
pub struct RegExpOptions {
|
||||
/// Enables plugin to transform the RegExp literal has `y` flag
|
||||
pub sticky_flag: bool,
|
||||
/// Enables plugin to transform the RegExp literal has `u` flag
|
||||
pub unicode_flag: bool,
|
||||
/// Enables plugin to transform the RegExp literal has `s` flag
|
||||
pub dot_all_flag: bool,
|
||||
/// Enables plugin to transform the RegExp literal has `(?<=)` or `(?<!)` lookbehind assertions
|
||||
pub look_behind_assertions: bool,
|
||||
/// Enables plugin to transform the RegExp literal has `(?<name>x)` named capture groups
|
||||
pub named_capture_groups: bool,
|
||||
/// Enables plugin to transform the RegExp literal has `\p{}` and `\P{}` unicode property escapes
|
||||
pub unicode_property_escapes: bool,
|
||||
/// Enables plugin to transform `d` flag
|
||||
pub match_indices: bool,
|
||||
/// Enables plugin to transform the RegExp literal has `v` flag
|
||||
pub set_notation: bool,
|
||||
}
|
||||
|
||||
impl RegExpOptions {
|
||||
#[must_use]
|
||||
pub fn from_targets_and_bugfixes(targets: Option<&Versions>, bugfixes: bool) -> Self {
|
||||
Self {
|
||||
sticky_flag: can_enable_plugin("transform-sticky-regex", targets, bugfixes),
|
||||
unicode_flag: can_enable_plugin("transform-unicode-regex", targets, bugfixes),
|
||||
dot_all_flag: can_enable_plugin("transform-dotall-regex", targets, bugfixes),
|
||||
look_behind_assertions: can_enable_plugin(
|
||||
"esbuild-regexp-lookbehind-assertions",
|
||||
targets,
|
||||
bugfixes,
|
||||
),
|
||||
named_capture_groups: can_enable_plugin(
|
||||
"transform-named-capturing-groups-regex",
|
||||
targets,
|
||||
bugfixes,
|
||||
),
|
||||
unicode_property_escapes: can_enable_plugin(
|
||||
"transform-unicode-property-regex",
|
||||
targets,
|
||||
bugfixes,
|
||||
),
|
||||
match_indices: can_enable_plugin("esbuild-regexp-match-indices", targets, bugfixes),
|
||||
set_notation: can_enable_plugin("transform-unicode-sets-regex", targets, bugfixes),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -46,10 +46,10 @@ after transform: ScopeId(0): [ScopeId(1), ScopeId(8), ScopeId(9), ScopeId(14), S
|
|||
rebuilt : ScopeId(0): [ScopeId(1), ScopeId(8), ScopeId(13), ScopeId(19), ScopeId(22), ScopeId(23)]
|
||||
Symbol reference IDs mismatch:
|
||||
after transform: SymbolId(1): [ReferenceId(0), ReferenceId(20), ReferenceId(22), ReferenceId(26), ReferenceId(34), ReferenceId(46), ReferenceId(48), ReferenceId(49), ReferenceId(51), ReferenceId(53), ReferenceId(55), ReferenceId(56), ReferenceId(58), ReferenceId(60), ReferenceId(65), ReferenceId(67), ReferenceId(68), ReferenceId(70), ReferenceId(74), ReferenceId(76), ReferenceId(77), ReferenceId(78), ReferenceId(80), ReferenceId(81), ReferenceId(83), ReferenceId(86), ReferenceId(89), ReferenceId(91), ReferenceId(97)]
|
||||
rebuilt : SymbolId(0): [ReferenceId(38), ReferenceId(39), ReferenceId(42), ReferenceId(44), ReferenceId(47), ReferenceId(53), ReferenceId(54), ReferenceId(56), ReferenceId(60), ReferenceId(62), ReferenceId(65), ReferenceId(68), ReferenceId(71), ReferenceId(73), ReferenceId(79)]
|
||||
rebuilt : SymbolId(0): [ReferenceId(39), ReferenceId(40), ReferenceId(43), ReferenceId(45), ReferenceId(48), ReferenceId(54), ReferenceId(55), ReferenceId(57), ReferenceId(61), ReferenceId(63), ReferenceId(66), ReferenceId(69), ReferenceId(72), ReferenceId(74), ReferenceId(80)]
|
||||
Unresolved references mismatch:
|
||||
after transform: ["Object", "true", "undefined"]
|
||||
rebuilt : ["Object", "undefined"]
|
||||
after transform: ["Object", "RegExp", "true", "undefined"]
|
||||
rebuilt : ["Object", "RegExp", "undefined"]
|
||||
|
||||
tasks/coverage/typescript/tests/cases/compiler/APISample_linter.ts
|
||||
semantic error: Bindings mismatch:
|
||||
|
|
@ -1496,43 +1496,43 @@ after transform: ScopeId(1): ["Tany"]
|
|||
rebuilt : ScopeId(1): []
|
||||
Reference symbol mismatch:
|
||||
after transform: ReferenceId(0): Some("a")
|
||||
rebuilt : ReferenceId(0): None
|
||||
Reference symbol mismatch:
|
||||
after transform: ReferenceId(1): Some("a")
|
||||
rebuilt : ReferenceId(1): None
|
||||
Reference symbol mismatch:
|
||||
after transform: ReferenceId(2): Some("a")
|
||||
after transform: ReferenceId(1): Some("a")
|
||||
rebuilt : ReferenceId(2): None
|
||||
Reference symbol mismatch:
|
||||
after transform: ReferenceId(3): Some("a")
|
||||
after transform: ReferenceId(2): Some("a")
|
||||
rebuilt : ReferenceId(3): None
|
||||
Reference symbol mismatch:
|
||||
after transform: ReferenceId(4): Some("a")
|
||||
after transform: ReferenceId(3): Some("a")
|
||||
rebuilt : ReferenceId(4): None
|
||||
Reference symbol mismatch:
|
||||
after transform: ReferenceId(5): Some("A")
|
||||
after transform: ReferenceId(4): Some("a")
|
||||
rebuilt : ReferenceId(5): None
|
||||
Reference symbol mismatch:
|
||||
after transform: ReferenceId(6): Some("A")
|
||||
after transform: ReferenceId(5): Some("A")
|
||||
rebuilt : ReferenceId(6): None
|
||||
Reference symbol mismatch:
|
||||
after transform: ReferenceId(7): Some("A")
|
||||
after transform: ReferenceId(6): Some("A")
|
||||
rebuilt : ReferenceId(7): None
|
||||
Reference symbol mismatch:
|
||||
after transform: ReferenceId(8): Some("A")
|
||||
after transform: ReferenceId(7): Some("A")
|
||||
rebuilt : ReferenceId(8): None
|
||||
Reference symbol mismatch:
|
||||
after transform: ReferenceId(9): Some("A")
|
||||
after transform: ReferenceId(8): Some("A")
|
||||
rebuilt : ReferenceId(9): None
|
||||
Reference symbol mismatch:
|
||||
after transform: ReferenceId(10): Some("A")
|
||||
after transform: ReferenceId(9): Some("A")
|
||||
rebuilt : ReferenceId(10): None
|
||||
Reference symbol mismatch:
|
||||
after transform: ReferenceId(11): Some("A")
|
||||
after transform: ReferenceId(10): Some("A")
|
||||
rebuilt : ReferenceId(11): None
|
||||
Reference symbol mismatch:
|
||||
after transform: ReferenceId(11): Some("A")
|
||||
rebuilt : ReferenceId(12): None
|
||||
Unresolved references mismatch:
|
||||
after transform: []
|
||||
rebuilt : ["A", "a"]
|
||||
after transform: ["RegExp"]
|
||||
rebuilt : ["A", "RegExp", "a"]
|
||||
|
||||
tasks/coverage/typescript/tests/cases/compiler/castNewObjectBug.ts
|
||||
semantic error: Bindings mismatch:
|
||||
|
|
@ -5108,8 +5108,8 @@ Reference symbol mismatch:
|
|||
after transform: ReferenceId(0): Some("require")
|
||||
rebuilt : ReferenceId(0): None
|
||||
Unresolved references mismatch:
|
||||
after transform: ["Error", "JSON"]
|
||||
rebuilt : ["Error", "JSON", "require"]
|
||||
after transform: ["Error", "JSON", "RegExp"]
|
||||
rebuilt : ["Error", "JSON", "RegExp", "require"]
|
||||
|
||||
tasks/coverage/typescript/tests/cases/compiler/controlFlowUnionContainingTypeParameter1.ts
|
||||
semantic error: Bindings mismatch:
|
||||
|
|
@ -31707,7 +31707,10 @@ rebuilt : ["undefined"]
|
|||
tasks/coverage/typescript/tests/cases/conformance/controlFlow/controlFlowDoWhileStatement.ts
|
||||
semantic error: Unresolved references mismatch:
|
||||
after transform: ["Function", "RegExp", "undefined"]
|
||||
rebuilt : ["undefined"]
|
||||
rebuilt : ["RegExp", "undefined"]
|
||||
Unresolved reference IDs mismatch for "RegExp":
|
||||
after transform: [ReferenceId(23), ReferenceId(33), ReferenceId(42), ReferenceId(43)]
|
||||
rebuilt : [ReferenceId(29), ReferenceId(38)]
|
||||
|
||||
tasks/coverage/typescript/tests/cases/conformance/controlFlow/controlFlowElementAccess2.ts
|
||||
semantic error: Bindings mismatch:
|
||||
|
|
@ -31746,7 +31749,10 @@ rebuilt : ScopeId(0): [ScopeId(1), ScopeId(2)]
|
|||
tasks/coverage/typescript/tests/cases/conformance/controlFlow/controlFlowForInStatement.ts
|
||||
semantic error: Unresolved references mismatch:
|
||||
after transform: ["Function", "RegExp"]
|
||||
rebuilt : []
|
||||
rebuilt : ["RegExp"]
|
||||
Unresolved reference IDs mismatch for "RegExp":
|
||||
after transform: [ReferenceId(0), ReferenceId(11)]
|
||||
rebuilt : [ReferenceId(1)]
|
||||
|
||||
tasks/coverage/typescript/tests/cases/conformance/controlFlow/controlFlowForInStatement2.ts
|
||||
semantic error: Bindings mismatch:
|
||||
|
|
@ -31809,10 +31815,10 @@ after transform: ScopeId(12): ["T", "data"]
|
|||
rebuilt : ScopeId(12): ["data"]
|
||||
Symbol reference IDs mismatch:
|
||||
after transform: SymbolId(15): [ReferenceId(29), ReferenceId(30)]
|
||||
rebuilt : SymbolId(11): [ReferenceId(23)]
|
||||
Unresolved references mismatch:
|
||||
after transform: ["Error", "JSON", "RegExp"]
|
||||
rebuilt : ["Error", "JSON"]
|
||||
rebuilt : SymbolId(11): [ReferenceId(24)]
|
||||
Unresolved reference IDs mismatch for "RegExp":
|
||||
after transform: [ReferenceId(0), ReferenceId(31)]
|
||||
rebuilt : [ReferenceId(1)]
|
||||
|
||||
tasks/coverage/typescript/tests/cases/conformance/controlFlow/controlFlowInOperator.ts
|
||||
semantic error: Bindings mismatch:
|
||||
|
|
@ -31971,8 +31977,8 @@ Symbol reference IDs mismatch:
|
|||
after transform: SymbolId(0): [ReferenceId(0), ReferenceId(1), ReferenceId(5), ReferenceId(6), ReferenceId(16)]
|
||||
rebuilt : SymbolId(0): [ReferenceId(11)]
|
||||
Unresolved references mismatch:
|
||||
after transform: ["Object", "RegExpExecArray", "getFooOrNull", "getStringOrNumberOrNull"]
|
||||
rebuilt : ["getFooOrNull", "getStringOrNumberOrNull"]
|
||||
after transform: ["Object", "RegExp", "RegExpExecArray", "getFooOrNull", "getStringOrNumberOrNull"]
|
||||
rebuilt : ["RegExp", "getFooOrNull", "getStringOrNumberOrNull"]
|
||||
|
||||
tasks/coverage/typescript/tests/cases/conformance/controlFlow/typeGuardsTypeParameters.ts
|
||||
semantic error: Bindings mismatch:
|
||||
|
|
@ -35668,9 +35674,9 @@ rebuilt : ScopeId(0): ["a", "arr", "x"]
|
|||
Scope children mismatch:
|
||||
after transform: ScopeId(0): [ScopeId(1), ScopeId(3)]
|
||||
rebuilt : ScopeId(0): [ScopeId(1)]
|
||||
Unresolved references mismatch:
|
||||
after transform: ["RegExp"]
|
||||
rebuilt : []
|
||||
Unresolved reference IDs mismatch for "RegExp":
|
||||
after transform: [ReferenceId(0), ReferenceId(22)]
|
||||
rebuilt : [ReferenceId(13)]
|
||||
|
||||
tasks/coverage/typescript/tests/cases/conformance/expressions/binaryOperators/additionOperator/additionOperatorWithAnyAndEveryType.ts
|
||||
semantic error: Namespaces exporting non-const are not supported by Babel. Change to const or see: https://babeljs.io/docs/en/babel-plugin-transform-typescript
|
||||
|
|
@ -42468,8 +42474,8 @@ Reference symbol mismatch:
|
|||
after transform: ReferenceId(1): Some("a")
|
||||
rebuilt : ReferenceId(1): None
|
||||
Unresolved references mismatch:
|
||||
after transform: []
|
||||
rebuilt : ["a"]
|
||||
after transform: ["RegExp"]
|
||||
rebuilt : ["RegExp", "a"]
|
||||
|
||||
tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript5/Symbols/parserES5SymbolIndexer1.ts
|
||||
semantic error: Bindings mismatch:
|
||||
|
|
@ -43194,7 +43200,7 @@ after transform: ScopeId(10): ["T", "x"]
|
|||
rebuilt : ScopeId(9): ["x"]
|
||||
Symbol reference IDs mismatch:
|
||||
after transform: SymbolId(2): [ReferenceId(2), ReferenceId(4), ReferenceId(5), ReferenceId(21), ReferenceId(42)]
|
||||
rebuilt : SymbolId(1): [ReferenceId(20), ReferenceId(40)]
|
||||
rebuilt : SymbolId(1): [ReferenceId(20), ReferenceId(41)]
|
||||
Symbol flags mismatch:
|
||||
after transform: SymbolId(7): SymbolFlags(Export | Class)
|
||||
rebuilt : SymbolId(6): SymbolFlags(Class)
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
commit: 3bcfee23
|
||||
|
||||
Passed: 13/41
|
||||
Passed: 21/49
|
||||
|
||||
# All Passed:
|
||||
* babel-plugin-transform-nullish-coalescing-operator
|
||||
* babel-plugin-transform-optional-catch-binding
|
||||
* babel-preset-typescript
|
||||
* esbuild-tests
|
||||
|
||||
|
||||
# babel-plugin-transform-arrow-functions (1/2)
|
||||
|
|
|
|||
|
|
@ -56,6 +56,9 @@ pub(crate) const PLUGINS: &[&str] = &[
|
|||
"babel-plugin-transform-react-jsx-development",
|
||||
// // Proposal
|
||||
// "babel-plugin-proposal-decorators",
|
||||
|
||||
// Tests port from esbuild
|
||||
"esbuild-tests",
|
||||
];
|
||||
|
||||
pub(crate) const PLUGINS_NOT_SUPPORTED_YET: &[&str] = &[
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
// ES2015
|
||||
// RegExpSticky
|
||||
x1 = /./y
|
||||
// RegExpUnicode
|
||||
x2 = /./u
|
||||
// ES2018
|
||||
// RegExpDotAllFlag
|
||||
a1 = /a.b/s
|
||||
// RegExpLookbehindAssertions
|
||||
b1 = /(?<!x)/
|
||||
b2 = /(?<=x)/
|
||||
// RegExpNamedCaptureGroups
|
||||
c1 = /(?<a>b)/
|
||||
// RegExpUnicodePropertyEscapes
|
||||
d1 = /\p{Emoji}/u
|
||||
// ES2022
|
||||
// RegExpMatchIndices
|
||||
f1 = /y/d
|
||||
// ES2024
|
||||
// RegExpSetNotation
|
||||
g1 = /[\p{White_Space}&&\p{ASCII}]/v
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"presets": [
|
||||
["env", {
|
||||
"targets": {
|
||||
"chrome": "40"
|
||||
}
|
||||
}]
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
x1 = new RegExp(".", "y");
|
||||
x2 = new RegExp(".", "u");
|
||||
a1 = new RegExp("a.b", "s");
|
||||
b1 = new RegExp("(?<!x)", "");
|
||||
b2 = new RegExp("(?<=x)", "");
|
||||
c1 = new RegExp("(?<a>b)", "");
|
||||
d1 = new RegExp("\\p{Emoji}", "u");
|
||||
f1 = new RegExp("y", "d");
|
||||
g1 = new RegExp("[\\p{White_Space}&&\\p{ASCII}]", "v");
|
||||
1
tasks/transform_conformance/tests/esbuild-tests/test/fixtures/regexp/igm/input.js
vendored
Normal file
1
tasks/transform_conformance/tests/esbuild-tests/test/fixtures/regexp/igm/input.js
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
a1 = /a.b/igm;
|
||||
9
tasks/transform_conformance/tests/esbuild-tests/test/fixtures/regexp/igm/options.json
vendored
Normal file
9
tasks/transform_conformance/tests/esbuild-tests/test/fixtures/regexp/igm/options.json
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"presets": [
|
||||
["env", {
|
||||
"targets": {
|
||||
"chrome": "40"
|
||||
}
|
||||
}]
|
||||
]
|
||||
}
|
||||
1
tasks/transform_conformance/tests/esbuild-tests/test/fixtures/regexp/igm/output.js
vendored
Normal file
1
tasks/transform_conformance/tests/esbuild-tests/test/fixtures/regexp/igm/output.js
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
a1 = /a.b/igm;
|
||||
|
|
@ -0,0 +1 @@
|
|||
a1 = /a.b/s
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"plugins": [
|
||||
"transform-dotall-regex"
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
a1 = new RegExp("a.b", "s");
|
||||
|
|
@ -0,0 +1 @@
|
|||
c1 = /(?<a>b)/
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"plugins": [
|
||||
"transform-named-capturing-groups-regex"
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
c1 = new RegExp("(?<a>b)", "");
|
||||
|
|
@ -0,0 +1 @@
|
|||
x1 = /./y
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"plugins": [
|
||||
"transform-sticky-regex"
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
x1 = new RegExp(".", "y");
|
||||
|
|
@ -0,0 +1 @@
|
|||
d1 = /\p{Emoji}/u
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"plugins": [
|
||||
"transform-unicode-property-regex"
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
d1 = new RegExp("\\p{Emoji}", "u");
|
||||
|
|
@ -0,0 +1 @@
|
|||
x2 = /./u
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"plugins": [
|
||||
"transform-unicode-regex"
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
x2 = new RegExp(".", "u");
|
||||
|
|
@ -0,0 +1 @@
|
|||
g1 = /[\p{White_Space}&&\p{ASCII}]/v
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"plugins": [
|
||||
"transform-unicode-sets-regex"
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
g1 = new RegExp("[\\p{White_Space}&&\\p{ASCII}]", "v");
|
||||
Loading…
Reference in a new issue