mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 12:21:58 +00:00
feat(sourcemap): add sourceRoot (#2926)
This commit is contained in:
parent
3e5530805d
commit
5cb3991b67
5 changed files with 30 additions and 2 deletions
|
|
@ -78,6 +78,7 @@ impl ConcatSourceMapBuilder {
|
|||
SourceMap::new(
|
||||
None,
|
||||
self.names,
|
||||
None,
|
||||
self.sources,
|
||||
Some(self.source_contents),
|
||||
self.tokens,
|
||||
|
|
@ -91,6 +92,7 @@ fn test_concat_sourcemap_builder() {
|
|||
let sm1 = SourceMap::new(
|
||||
None,
|
||||
vec!["foo".into(), "foo2".into()],
|
||||
None,
|
||||
vec!["foo.js".into()],
|
||||
None,
|
||||
vec![Token::new(1, 1, 1, 1, Some(0), Some(0))],
|
||||
|
|
@ -99,6 +101,7 @@ fn test_concat_sourcemap_builder() {
|
|||
let sm2 = SourceMap::new(
|
||||
None,
|
||||
vec!["bar".into()],
|
||||
None,
|
||||
vec!["bar.js".into()],
|
||||
None,
|
||||
vec![Token::new(1, 1, 1, 1, Some(0), Some(0))],
|
||||
|
|
@ -112,6 +115,7 @@ fn test_concat_sourcemap_builder() {
|
|||
let sm = SourceMap::new(
|
||||
None,
|
||||
vec!["foo".into(), "foo2".into(), "bar".into()],
|
||||
None,
|
||||
vec!["foo.js".into(), "bar.js".into()],
|
||||
None,
|
||||
vec![Token::new(1, 1, 1, 1, Some(0), Some(0)), Token::new(3, 1, 1, 1, Some(1), Some(2))],
|
||||
|
|
|
|||
|
|
@ -6,10 +6,17 @@ use crate::{SourceMap, Token};
|
|||
#[derive(serde::Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct JSONSourceMap {
|
||||
// An optional name of the generated code that this source map is associated with.
|
||||
file: Option<String>,
|
||||
// A string with the encoded mapping data.
|
||||
mappings: Option<String>,
|
||||
// An optional source root, useful for relocating source files on a server or removing repeated values in the “sources” entry. This value is prepended to the individual entries in the “source” field.
|
||||
source_root: Option<String>,
|
||||
// A list of original sources used by the “mappings” entry.
|
||||
sources: Option<Vec<Option<String>>>,
|
||||
// An optional list of source content, useful when the “source” can’t be hosted. The contents are listed in the same order as the sources in line 5. “null” may be used if some original sources should be retrieved by name.
|
||||
sources_content: Option<Vec<Option<String>>>,
|
||||
// A list of symbol names used by the “mappings” entry.
|
||||
names: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
|
|
@ -18,6 +25,7 @@ pub fn decode(value: &str) -> Result<SourceMap> {
|
|||
let file = json.file.map(Into::into);
|
||||
let names =
|
||||
json.names.map(|v| v.into_iter().map(Into::into).collect::<Vec<_>>()).unwrap_or_default();
|
||||
let source_root = json.source_root.map(Into::into);
|
||||
let sources = json
|
||||
.sources
|
||||
.map(|v| v.into_iter().map(Option::unwrap_or_default).map(Into::into).collect::<Vec<_>>())
|
||||
|
|
@ -26,7 +34,7 @@ pub fn decode(value: &str) -> Result<SourceMap> {
|
|||
.sources_content
|
||||
.map(|v| v.into_iter().map(Option::unwrap_or_default).map(Into::into).collect::<Vec<_>>());
|
||||
let tokens = decode_mapping(&json.mappings.unwrap_or_default(), names.len(), sources.len())?;
|
||||
Ok(SourceMap::new(file, names, sources, source_contents, tokens, None))
|
||||
Ok(SourceMap::new(file, names, source_root, sources, source_contents, tokens, None))
|
||||
}
|
||||
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
|
|
@ -140,6 +148,7 @@ fn test_decode_sourcemap() {
|
|||
"mappings": "AAAA,GAAIA,GAAI,EACR,IAAIA,GAAK,EAAG,CACVC,MAAM"
|
||||
}"#;
|
||||
let sm = SourceMap::from_json_string(input).unwrap();
|
||||
assert_eq!(sm.get_source_root(), Some("x"));
|
||||
let mut iter = sm.get_source_view_tokens().filter(|token| token.get_name_id().is_some());
|
||||
assert_eq!(iter.next().unwrap().to_tuple(), (Some("coolstuff.js"), 0, 4, Some("x")));
|
||||
assert_eq!(iter.next().unwrap().to_tuple(), (Some("coolstuff.js"), 1, 4, Some("x")));
|
||||
|
|
|
|||
|
|
@ -16,6 +16,11 @@ pub fn encode(sourcemap: &SourceMap) -> Result<String> {
|
|||
buf.push_str(file);
|
||||
buf.push_str("\",");
|
||||
}
|
||||
if let Some(source_root) = sourcemap.get_source_root() {
|
||||
buf.push_str("\"sourceRoot\":\"");
|
||||
buf.push_str(source_root);
|
||||
buf.push_str("\",");
|
||||
}
|
||||
buf.push_str("\"names\":[");
|
||||
let names = sourcemap
|
||||
.names
|
||||
|
|
@ -144,6 +149,7 @@ fn test_encode() {
|
|||
let input = r#"{
|
||||
"version": 3,
|
||||
"sources": ["coolstuff.js"],
|
||||
"sourceRoot": "x",
|
||||
"names": ["x","alert"],
|
||||
"mappings": "AAAA,GAAIA,GAAI,EACR,IAAIA,GAAK,EAAG,CACVC,MAAM"
|
||||
}"#;
|
||||
|
|
@ -161,6 +167,7 @@ fn test_encode_escape_string() {
|
|||
let sm = SourceMap::new(
|
||||
None,
|
||||
vec!["\0".into()],
|
||||
None,
|
||||
vec!["\0".into()],
|
||||
Some(vec!["\0".into()]),
|
||||
vec![],
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ use std::sync::Arc;
|
|||
pub struct SourceMap {
|
||||
pub(crate) file: Option<Arc<str>>,
|
||||
pub(crate) names: Vec<Arc<str>>,
|
||||
pub(crate) source_root: Option<String>,
|
||||
pub(crate) sources: Vec<Arc<str>>,
|
||||
pub(crate) source_contents: Option<Vec<Arc<str>>>,
|
||||
pub(crate) tokens: Vec<Token>,
|
||||
|
|
@ -22,12 +23,13 @@ impl SourceMap {
|
|||
pub fn new(
|
||||
file: Option<Arc<str>>,
|
||||
names: Vec<Arc<str>>,
|
||||
source_root: Option<String>,
|
||||
sources: Vec<Arc<str>>,
|
||||
source_contents: Option<Vec<Arc<str>>>,
|
||||
tokens: Vec<Token>,
|
||||
token_chunks: Option<Vec<TokenChunk>>,
|
||||
) -> Self {
|
||||
Self { file, names, sources, source_contents, tokens, token_chunks }
|
||||
Self { file, names, source_root, sources, source_contents, tokens, token_chunks }
|
||||
}
|
||||
|
||||
/// Convert `SourceMap` to vlq sourcemap string.
|
||||
|
|
@ -63,6 +65,10 @@ impl SourceMap {
|
|||
self.file = Some(file.into());
|
||||
}
|
||||
|
||||
pub fn get_source_root(&self) -> Option<&str> {
|
||||
self.source_root.as_deref()
|
||||
}
|
||||
|
||||
pub fn get_names(&self) -> impl Iterator<Item = &str> {
|
||||
self.names.iter().map(AsRef::as_ref)
|
||||
}
|
||||
|
|
@ -224,6 +230,7 @@ fn test_sourcemap_source_view_token() {
|
|||
let sm = SourceMap::new(
|
||||
None,
|
||||
vec!["foo".into()],
|
||||
None,
|
||||
vec!["foo.js".into()],
|
||||
None,
|
||||
vec![Token::new(1, 1, 1, 1, Some(0), Some(0))],
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ impl SourceMapBuilder {
|
|||
SourceMap::new(
|
||||
self.file,
|
||||
self.names,
|
||||
None,
|
||||
self.sources,
|
||||
Some(self.source_contents),
|
||||
self.tokens,
|
||||
|
|
|
|||
Loading…
Reference in a new issue