Skip to content

Commit

Permalink
fix(transformer): remove span of define value (#7811)
Browse files Browse the repository at this point in the history
- Closes #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>
  • Loading branch information
hi-ogawa and autofix-ci[bot] authored Dec 13, 2024
1 parent 1bb097d commit 5b7e1ad
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 3 deletions.
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.

1 change: 1 addition & 0 deletions crates/oxc_transformer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
20 changes: 17 additions & 3 deletions crates/oxc_transformer/src/plugins/replace_global_defines.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand Down Expand Up @@ -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());
}
Original file line number Diff line number Diff line change
@@ -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"

0 comments on commit 5b7e1ad

Please sign in to comment.