mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 04:08:41 +00:00
fix(transformer): remove span of define value (#7811)
- Closes https://github.com/oxc-project/oxc/issues/7797 Removing span seems to work, but I'm not sure traversing all the time is okay. --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
parent
1bb097d459
commit
5b7e1adc9b
5 changed files with 97 additions and 3 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
|
@ -2057,6 +2057,7 @@ dependencies = [
|
|||
"oxc_parser",
|
||||
"oxc_regular_expression",
|
||||
"oxc_semantic",
|
||||
"oxc_sourcemap",
|
||||
"oxc_span",
|
||||
"oxc_syntax",
|
||||
"oxc_traverse",
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ sha1 = { workspace = true }
|
|||
insta = { workspace = true }
|
||||
oxc_codegen = { workspace = true }
|
||||
oxc_parser = { workspace = true }
|
||||
oxc_sourcemap = { workspace = true }
|
||||
pico-args = { workspace = true }
|
||||
|
||||
[features]
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@ use std::{cmp::Ordering, sync::Arc};
|
|||
|
||||
use lazy_static::lazy_static;
|
||||
use oxc_allocator::{Address, Allocator, GetAddress};
|
||||
use oxc_ast::ast::*;
|
||||
use oxc_ast::{ast::*, VisitMut};
|
||||
use oxc_diagnostics::OxcDiagnostic;
|
||||
use oxc_parser::Parser;
|
||||
use oxc_semantic::{IsGlobalReference, ScopeFlags, ScopeTree, SymbolTable};
|
||||
use oxc_span::{CompactStr, SourceType};
|
||||
use oxc_span::{CompactStr, SourceType, SPAN};
|
||||
use oxc_syntax::identifier::is_identifier_name;
|
||||
use oxc_traverse::{traverse_mut, Ancestor, Traverse, TraverseCtx};
|
||||
use rustc_hash::FxHashSet;
|
||||
|
|
@ -293,7 +293,13 @@ impl<'a> ReplaceGlobalDefines<'a> {
|
|||
// Allocate the string lazily because replacement happens rarely.
|
||||
let source_text = self.allocator.alloc_str(source_text);
|
||||
// Unwrapping here, it should already be checked by [ReplaceGlobalDefinesConfig::new].
|
||||
Parser::new(self.allocator, source_text, SourceType::default()).parse_expression().unwrap()
|
||||
let mut expr = Parser::new(self.allocator, source_text, SourceType::default())
|
||||
.parse_expression()
|
||||
.unwrap();
|
||||
|
||||
RemoveSpans.visit_expression(&mut expr);
|
||||
|
||||
expr
|
||||
}
|
||||
|
||||
fn replace_identifier_defines(
|
||||
|
|
@ -706,3 +712,11 @@ fn assignment_target_from_expr(expr: Expression) -> Option<AssignmentTarget> {
|
|||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
struct RemoveSpans;
|
||||
|
||||
impl<'ast> VisitMut<'ast> for RemoveSpans {
|
||||
fn visit_span(&mut self, span: &mut Span) {
|
||||
*span = SPAN;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ use oxc_allocator::Allocator;
|
|||
use oxc_codegen::{CodeGenerator, CodegenOptions};
|
||||
use oxc_parser::Parser;
|
||||
use oxc_semantic::SemanticBuilder;
|
||||
use oxc_sourcemap::SourcemapVisualizer;
|
||||
use oxc_span::SourceType;
|
||||
use oxc_transformer::{ReplaceGlobalDefines, ReplaceGlobalDefinesConfig};
|
||||
|
||||
|
|
@ -235,3 +236,57 @@ console.log(
|
|||
config.clone(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sourcemap() {
|
||||
let config = ReplaceGlobalDefinesConfig::new(&[
|
||||
("__OBJECT__", r#"{"hello": "test"}"#),
|
||||
("__STRING__", r#""development""#),
|
||||
("__MEMBER__", r"xx.yy.zz"),
|
||||
])
|
||||
.unwrap();
|
||||
let source_text = r"
|
||||
1;
|
||||
__OBJECT__;
|
||||
2;
|
||||
__STRING__;
|
||||
3;
|
||||
log(__OBJECT__);
|
||||
4;
|
||||
log(__STRING__);
|
||||
5;
|
||||
__OBJECT__.hello;
|
||||
6;
|
||||
log(__MEMBER__);
|
||||
7;
|
||||
"
|
||||
.trim_start();
|
||||
|
||||
let source_type = SourceType::default();
|
||||
let allocator = Allocator::default();
|
||||
let ret = Parser::new(&allocator, source_text, source_type).parse();
|
||||
let mut program = ret.program;
|
||||
let (symbols, scopes) =
|
||||
SemanticBuilder::new().build(&program).semantic.into_symbol_table_and_scope_tree();
|
||||
let _ = ReplaceGlobalDefines::new(&allocator, config).build(symbols, scopes, &mut program);
|
||||
let result = CodeGenerator::new()
|
||||
.with_options(CodegenOptions {
|
||||
single_quote: true,
|
||||
source_map_path: Some(std::path::Path::new(&"test.js.map").to_path_buf()),
|
||||
..CodegenOptions::default()
|
||||
})
|
||||
.build(&program);
|
||||
|
||||
let output = result.code;
|
||||
let output_map = result.map.unwrap();
|
||||
let visualizer = SourcemapVisualizer::new(&output, &output_map);
|
||||
let snapshot = visualizer.into_visualizer_text();
|
||||
insta::assert_snapshot!("test_sourcemap", snapshot);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "")]
|
||||
fn test_complex() {
|
||||
let config = ReplaceGlobalDefinesConfig::new(&[("__DEF__", "((() => {})())")]).unwrap();
|
||||
test("__DEF__", "1", config.clone());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
---
|
||||
source: crates/oxc_transformer/tests/integrations/plugins/replace_global_defines.rs
|
||||
expression: snapshot
|
||||
snapshot_kind: text
|
||||
---
|
||||
- test.js.map
|
||||
(0:0) "1;\n" --> (0:0) "1;\n"
|
||||
(1:0) "__OBJECT__;\n" --> (1:0) "({ 'hello': 'test' });\n"
|
||||
(2:0) "2;\n" --> (2:0) "2;\n"
|
||||
(3:0) "__STRING__;\n" --> (3:0) "'development';\n"
|
||||
(4:0) "3;\n" --> (4:0) "3;\n"
|
||||
(5:0) "log(__OBJECT__)" --> (5:0) "log({ 'hello': 'test' })"
|
||||
(5:15) ";\n" --> (5:24) ";\n"
|
||||
(6:0) "4;\n" --> (6:0) "4;\n"
|
||||
(7:0) "log(__STRING__)" --> (7:0) "log('development')"
|
||||
(7:15) ";\n" --> (7:18) ";\n"
|
||||
(8:0) "5;\n" --> (8:0) "5;\n"
|
||||
(9:0) "__OBJECT__." --> (9:0) "({ 'hello': 'test' })."
|
||||
(9:11) "hello;\n" --> (9:22) "hello;\n"
|
||||
(10:0) "6;\n" --> (10:0) "6;\n"
|
||||
(11:0) "log(__MEMBER__)" --> (11:0) "log(xx.yy.zz)"
|
||||
(11:15) ";\n" --> (11:13) ";\n"
|
||||
(12:0) "7;\n" --> (12:0) "7;\n"
|
||||
Loading…
Reference in a new issue