Skip to content

Commit 2c5e729

Browse files
committed
Move sourcemap content generation to the sourcemap module, document the sourcemap module
1 parent 9ed2600 commit 2c5e729

File tree

2 files changed

+51
-22
lines changed

2 files changed

+51
-22
lines changed

compiler-core/src/codegen.rs

+8-22
Original file line numberDiff line numberDiff line change
@@ -263,31 +263,17 @@ impl<'a> JavaScript<'a> {
263263
self.typescript,
264264
&mut source_map_emitter,
265265
);
266+
266267
tracing::debug!(name = ?js_name, "Generated js module");
267268
writer.write(&path, &output?)?;
268269

269-
match source_map_emitter {
270-
SourceMapEmitter::Null => Ok(()),
271-
SourceMapEmitter::Emit(builder) => {
272-
let sourcemap_name = format!("{js_name}.mjs.map");
273-
let sourcemap_path = self.output_directory.join(sourcemap_name);
274-
tracing::debug!(path = ?sourcemap_path, name = ?js_name, "Emitting sourcemap for module");
275-
276-
// NOTE: This is a bit inefficient
277-
// * we first write to a buffer
278-
// * then construct a String based on the output
279-
// * then write to the output
280-
let sourcemap = builder.into_sourcemap();
281-
282-
let mut output = Vec::new();
283-
sourcemap
284-
.to_writer(&mut output)
285-
.expect("Failed to write sourcemap to memory.");
286-
let output =
287-
String::from_utf8(output).expect("Sourcemap did not generate valid UTF-8.");
288-
289-
writer.write(&sourcemap_path, &output)
290-
}
270+
if let Some(sourcemap_content) = source_map_emitter.maybe_emit_sourcemap_content() {
271+
let sourcemap_name = format!("{js_name}.mjs.map");
272+
let sourcemap_path = self.output_directory.join(sourcemap_name);
273+
tracing::debug!(path = ?sourcemap_path, name = ?js_name, "Emitting sourcemap for module");
274+
writer.write(&sourcemap_path, &sourcemap_content)?;
291275
}
276+
277+
Ok(())
292278
}
293279
}

compiler-core/src/sourcemap.rs

+43
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,28 @@
1+
//! Sourcemap generation utils
2+
//!
3+
//! # What are sourcemaps ?
4+
//!
5+
//! Sourcemaps are a tool of web development that helps debugging when working
6+
//! with code that is generated from other code.
7+
//!
8+
//! A sourcemap is essentially a list of positions in a target file (the
9+
//! code generated by the tool - in our case JavaScript) linked to a location
10+
//! in the source code (Gleam) that is responsible for its presence.
11+
112
use sourcemap::SourceMapBuilder;
213

314
use crate::line_numbers::LineColumn;
415

16+
/// Tells whether or not the codegen should emit sourcemaps for all Gleam
17+
/// modules
518
#[derive(Debug, Clone, Copy)]
619
pub enum SourceMapSupport {
720
Emit,
821
None,
922
}
1023

24+
/// An utility that handles the emission of an associated sourcemap
25+
/// for a given Gleam module.
1126
pub enum SourceMapEmitter {
1227
Null,
1328
Emit(Box<SourceMapBuilder>),
@@ -24,6 +39,8 @@ impl std::fmt::Debug for SourceMapEmitter {
2439
}
2540

2641
impl SourceMapEmitter {
42+
/// Adds one mapping on the generated (javascript) file
43+
/// referring to the given Gleam source location
2744
pub fn add_mapping(
2845
&mut self,
2946
generated_code_line: u32,
@@ -47,6 +64,32 @@ impl SourceMapEmitter {
4764
}
4865
}
4966

67+
/// Consumes the SourceMapEmitter to get the content of the sourcemap as a
68+
/// String
69+
pub fn maybe_emit_sourcemap_content(self) -> Option<String> {
70+
match self {
71+
SourceMapEmitter::Null => None,
72+
SourceMapEmitter::Emit(builder) => {
73+
let sourcemap = builder.into_sourcemap();
74+
let mut output = Vec::new();
75+
// We first write to a vector then build a string, hoping that
76+
// the `sourcemap` crate generated a valid sourcemap. If it
77+
// did not, it is a bug that should be reported.
78+
//
79+
// SourceMap currently does not support being written directly
80+
// to a string.
81+
sourcemap
82+
.to_writer(&mut output)
83+
.expect("Failed to write sourcemap to memory.");
84+
let content =
85+
String::from_utf8(output).expect("Sourcemap did not generate valid UTF-8.");
86+
Some(content)
87+
}
88+
}
89+
}
90+
91+
/// Creates a null SourceMapEmitter.
92+
/// Any operation on this SourceMapEmitter will be no-ops
5093
pub fn null() -> Self {
5194
SourceMapEmitter::Null
5295
}

0 commit comments

Comments
 (0)