mirror of
https://github.com/swc-project/swc.git
synced 2024-11-26 20:36:17 +03:00
Faster sourcemap generation for large files (#697)
We buffer operations related to source map and make it fast using an assumption that the byte positions always increment while emitting a file.
This commit is contained in:
parent
8f280c535c
commit
6e028696a5
1
.gitignore
vendored
1
.gitignore
vendored
@ -23,6 +23,7 @@ node_modules/
|
|||||||
package-lock.json
|
package-lock.json
|
||||||
*.data
|
*.data
|
||||||
*.old
|
*.old
|
||||||
|
*.stacks
|
||||||
|
|
||||||
# Coverage datas
|
# Coverage datas
|
||||||
*.zip
|
*.zip
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "swc_common"
|
name = "swc_common"
|
||||||
version = "0.5.6"
|
version = "0.5.7"
|
||||||
authors = ["강동윤 <kdy1997.dev@gmail.com>"]
|
authors = ["강동윤 <kdy1997.dev@gmail.com>"]
|
||||||
license = "Apache-2.0/MIT"
|
license = "Apache-2.0/MIT"
|
||||||
repository = "https://github.com/swc-project/swc.git"
|
repository = "https://github.com/swc-project/swc.git"
|
||||||
@ -30,6 +30,7 @@ termcolor = "1.0"
|
|||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
dashmap = "=3.5.1"
|
dashmap = "=3.5.1"
|
||||||
fxhash = "0.2.1"
|
fxhash = "0.2.1"
|
||||||
|
sourcemap = "5"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
rayon = "1"
|
rayon = "1"
|
||||||
|
@ -10,6 +10,7 @@ pub use self::{
|
|||||||
SyntaxContext, DUMMY_SP, GLOBALS, NO_EXPANSION,
|
SyntaxContext, DUMMY_SP, GLOBALS, NO_EXPANSION,
|
||||||
},
|
},
|
||||||
source_map::{FileLines, FileLoader, FilePathMapping, SourceMap, SpanSnippetError},
|
source_map::{FileLines, FileLoader, FilePathMapping, SourceMap, SpanSnippetError},
|
||||||
|
syntax_pos::LineCol,
|
||||||
};
|
};
|
||||||
pub use ast_node::{ast_node, DeserializeEnum, Fold, Spanned};
|
pub use ast_node::{ast_node, DeserializeEnum, Fold, Spanned};
|
||||||
pub use from_variant::FromVariant;
|
pub use from_variant::FromVariant;
|
||||||
|
@ -24,6 +24,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use log::debug;
|
use log::debug;
|
||||||
|
use sourcemap::SourceMapBuilder;
|
||||||
use std::{
|
use std::{
|
||||||
cmp,
|
cmp,
|
||||||
cmp::{max, min},
|
cmp::{max, min},
|
||||||
@ -820,25 +821,8 @@ impl SourceMap {
|
|||||||
self.bytepos_to_file_charpos_with(&map, bpos)
|
self.bytepos_to_file_charpos_with(&map, bpos)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts an absolute BytePos to a CharPos relative to the source_file.
|
|
||||||
fn bytepos_to_file_charpos_with(&self, map: &SourceFile, bpos: BytePos) -> CharPos {
|
fn bytepos_to_file_charpos_with(&self, map: &SourceFile, bpos: BytePos) -> CharPos {
|
||||||
// The number of extra bytes due to multibyte chars in the SourceFile
|
let total_extra_bytes = self.calc_extra_bytes(map, &mut 0, bpos);
|
||||||
let mut total_extra_bytes = 0;
|
|
||||||
|
|
||||||
for mbc in map.multibyte_chars.iter() {
|
|
||||||
debug!("{}-byte char at {:?}", mbc.bytes, mbc.pos);
|
|
||||||
if mbc.pos < bpos {
|
|
||||||
// every character is at least one byte, so we only
|
|
||||||
// count the actual extra bytes.
|
|
||||||
total_extra_bytes += mbc.bytes as u32 - 1;
|
|
||||||
// We should never see a byte position in the middle of a
|
|
||||||
// character
|
|
||||||
assert!(bpos.to_u32() >= mbc.pos.to_u32() + mbc.bytes as u32);
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
map.start_pos.to_u32() + total_extra_bytes <= bpos.to_u32(),
|
map.start_pos.to_u32() + total_extra_bytes <= bpos.to_u32(),
|
||||||
"map.start_pos = {:?}; total_extra_bytes = {}; bpos = {:?}",
|
"map.start_pos = {:?}; total_extra_bytes = {}; bpos = {:?}",
|
||||||
@ -849,6 +833,29 @@ impl SourceMap {
|
|||||||
CharPos(bpos.to_usize() - map.start_pos.to_usize() - total_extra_bytes as usize)
|
CharPos(bpos.to_usize() - map.start_pos.to_usize() - total_extra_bytes as usize)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Converts an absolute BytePos to a CharPos relative to the source_file.
|
||||||
|
fn calc_extra_bytes(&self, map: &SourceFile, start: &mut usize, bpos: BytePos) -> u32 {
|
||||||
|
// The number of extra bytes due to multibyte chars in the SourceFile
|
||||||
|
let mut total_extra_bytes = 0;
|
||||||
|
|
||||||
|
for (i, &mbc) in map.multibyte_chars[*start..].iter().enumerate() {
|
||||||
|
debug!("{}-byte char at {:?}", mbc.bytes, mbc.pos);
|
||||||
|
if mbc.pos < bpos {
|
||||||
|
// every character is at least one byte, so we only
|
||||||
|
// count the actual extra bytes.
|
||||||
|
total_extra_bytes += mbc.bytes as u32 - 1;
|
||||||
|
// We should never see a byte position in the middle of a
|
||||||
|
// character
|
||||||
|
debug_assert!(bpos.to_u32() >= mbc.pos.to_u32() + mbc.bytes as u32);
|
||||||
|
} else {
|
||||||
|
*start += i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
total_extra_bytes
|
||||||
|
}
|
||||||
|
|
||||||
/// Return the index of the source_file (in self.files) which contains pos.
|
/// Return the index of the source_file (in self.files) which contains pos.
|
||||||
///
|
///
|
||||||
/// This method exists only for optimization and it's not part of public
|
/// This method exists only for optimization and it's not part of public
|
||||||
@ -986,6 +993,67 @@ impl SourceMap {
|
|||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates a `.map` file.
|
||||||
|
pub fn build_source_map(&self, mappings: &mut Vec<(BytePos, LineCol)>) -> sourcemap::SourceMap {
|
||||||
|
let mut builder = SourceMapBuilder::new(None);
|
||||||
|
|
||||||
|
// // This method is optimized based on the fact that mapping is sorted.
|
||||||
|
// mappings.sort_by_key(|v| v.0);
|
||||||
|
|
||||||
|
let mut cur_file: Option<Arc<SourceFile>> = None;
|
||||||
|
// let mut src_id = None;
|
||||||
|
|
||||||
|
let mut ch_start = 0;
|
||||||
|
let mut line_ch_start = 0;
|
||||||
|
|
||||||
|
for (pos, lc) in mappings.iter() {
|
||||||
|
let pos = *pos;
|
||||||
|
let lc = *lc;
|
||||||
|
|
||||||
|
// TODO: Use correct algorithm
|
||||||
|
if pos >= BytePos(4294967295) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let f;
|
||||||
|
let f = match cur_file {
|
||||||
|
Some(ref f) if f.start_pos <= pos && pos < f.end_pos => f,
|
||||||
|
_ => {
|
||||||
|
f = self.lookup_source_file(pos);
|
||||||
|
builder.add_source(&f.src);
|
||||||
|
cur_file = Some(f.clone());
|
||||||
|
ch_start = 0;
|
||||||
|
line_ch_start = 0;
|
||||||
|
// src_id = Some(builder.add_source(&f.src));
|
||||||
|
&f
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let a = match f.lookup_line(pos) {
|
||||||
|
Some(line) => line,
|
||||||
|
None => continue,
|
||||||
|
};
|
||||||
|
|
||||||
|
let line = a + 1; // Line numbers start at 1
|
||||||
|
let linebpos = f.lines[a];
|
||||||
|
debug_assert!(
|
||||||
|
pos >= linebpos,
|
||||||
|
"{}: bpos = {:?}; linebpos = {:?};",
|
||||||
|
f.name,
|
||||||
|
pos,
|
||||||
|
linebpos,
|
||||||
|
);
|
||||||
|
let chpos = { self.calc_extra_bytes(&f, &mut ch_start, pos) };
|
||||||
|
let linechpos = { self.calc_extra_bytes(&f, &mut line_ch_start, linebpos) };
|
||||||
|
|
||||||
|
let col = max(chpos, linechpos) - min(chpos, linechpos);
|
||||||
|
|
||||||
|
builder.add(lc.line, lc.col, (line - 1) as _, col as _, None, None);
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.into_sourcemap()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SourceMapper for SourceMap {
|
impl SourceMapper for SourceMap {
|
||||||
|
@ -923,6 +923,13 @@ pub struct LineInfo {
|
|||||||
pub end_col: CharPos,
|
pub end_col: CharPos,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Used to create a `.map` file.
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub struct LineCol {
|
||||||
|
pub line: u32,
|
||||||
|
pub col: u32,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct FileLines {
|
pub struct FileLines {
|
||||||
pub file: Arc<SourceFile>,
|
pub file: Arc<SourceFile>,
|
||||||
pub lines: Vec<LineInfo>,
|
pub lines: Vec<LineInfo>,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "swc_ecma_codegen"
|
name = "swc_ecma_codegen"
|
||||||
version = "0.17.0"
|
version = "0.18.0"
|
||||||
authors = ["강동윤 <kdy1997.dev@gmail.com>"]
|
authors = ["강동윤 <kdy1997.dev@gmail.com>"]
|
||||||
license = "Apache-2.0/MIT"
|
license = "Apache-2.0/MIT"
|
||||||
repository = "https://github.com/swc-project/swc.git"
|
repository = "https://github.com/swc-project/swc.git"
|
||||||
@ -17,7 +17,7 @@ swc_ecma_ast = { version = "0.17.0", path ="../ast" }
|
|||||||
swc_ecma_codegen_macros = { version = "0.5", path ="./macros" }
|
swc_ecma_codegen_macros = { version = "0.5", path ="./macros" }
|
||||||
sourcemap = "5"
|
sourcemap = "5"
|
||||||
num-bigint = { version = "0.2", features = ["serde"] }
|
num-bigint = { version = "0.2", features = ["serde"] }
|
||||||
|
swc_ecma_parser = { version = "0.20", path ="../parser" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
testing = { version = "0.5", path ="../../testing" }
|
testing = { version = "0.5", path ="../../testing" }
|
||||||
swc_ecma_parser = { version = "0.20", path ="../parser" }
|
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
extern crate test;
|
extern crate test;
|
||||||
|
|
||||||
use sourcemap::SourceMapBuilder;
|
use std::hint::black_box;
|
||||||
use swc_common::FileName;
|
use swc_common::FileName;
|
||||||
use swc_ecma_codegen::{self, Emitter};
|
use swc_ecma_codegen::{self, Emitter};
|
||||||
use swc_ecma_parser::{Parser, Session, SourceFileInput, Syntax};
|
use swc_ecma_parser::{Parser, Session, SourceFileInput, Syntax};
|
||||||
@ -88,6 +88,7 @@ fn bench_emitter(b: &mut Bencher, s: &str) {
|
|||||||
|
|
||||||
let _ = ::testing::run_test(true, |cm, handler| {
|
let _ = ::testing::run_test(true, |cm, handler| {
|
||||||
let session = Session { handler: &handler };
|
let session = Session { handler: &handler };
|
||||||
|
|
||||||
let fm = cm.new_source_file(FileName::Anon, s.into());
|
let fm = cm.new_source_file(FileName::Anon, s.into());
|
||||||
let mut parser = Parser::new(
|
let mut parser = Parser::new(
|
||||||
session,
|
session,
|
||||||
@ -95,6 +96,7 @@ fn bench_emitter(b: &mut Bencher, s: &str) {
|
|||||||
SourceFileInput::from(&*fm),
|
SourceFileInput::from(&*fm),
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
let mut src_map_buf = vec![];
|
||||||
let module = parser
|
let module = parser
|
||||||
.parse_module()
|
.parse_module()
|
||||||
.map_err(|mut e| {
|
.map_err(|mut e| {
|
||||||
@ -103,8 +105,7 @@ fn bench_emitter(b: &mut Bencher, s: &str) {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
let buf = vec![];
|
let mut buf = vec![];
|
||||||
let mut src_map_builder = SourceMapBuilder::new(None);
|
|
||||||
{
|
{
|
||||||
let handlers = box MyHandlers;
|
let handlers = box MyHandlers;
|
||||||
let mut emitter = Emitter {
|
let mut emitter = Emitter {
|
||||||
@ -116,14 +117,17 @@ fn bench_emitter(b: &mut Bencher, s: &str) {
|
|||||||
wr: box swc_ecma_codegen::text_writer::JsWriter::new(
|
wr: box swc_ecma_codegen::text_writer::JsWriter::new(
|
||||||
cm.clone(),
|
cm.clone(),
|
||||||
"\n",
|
"\n",
|
||||||
buf,
|
&mut buf,
|
||||||
Some(&mut src_map_builder),
|
Some(&mut src_map_buf),
|
||||||
),
|
),
|
||||||
handlers,
|
handlers,
|
||||||
};
|
};
|
||||||
|
|
||||||
emitter.emit_module(&module)
|
let _ = emitter.emit_module(&module);
|
||||||
}
|
}
|
||||||
|
black_box(buf);
|
||||||
|
let srcmap = cm.build_source_map(&mut src_map_buf);
|
||||||
|
black_box(srcmap);
|
||||||
});
|
});
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
extern crate test;
|
extern crate test;
|
||||||
|
|
||||||
use sourcemap::SourceMapBuilder;
|
use std::hint::black_box;
|
||||||
use swc_common::FileName;
|
use swc_common::FileName;
|
||||||
use swc_ecma_codegen::{self, Emitter};
|
use swc_ecma_codegen::{self, Emitter};
|
||||||
use swc_ecma_parser::{Parser, Session, SourceFileInput, Syntax};
|
use swc_ecma_parser::{Parser, Session, SourceFileInput, Syntax};
|
||||||
@ -97,6 +97,7 @@ fn bench_emitter(b: &mut Bencher, s: &str) {
|
|||||||
SourceFileInput::from(&*fm),
|
SourceFileInput::from(&*fm),
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
let mut src_map_buf = vec![];
|
||||||
let module = parser
|
let module = parser
|
||||||
.parse_module()
|
.parse_module()
|
||||||
.map_err(|mut e| {
|
.map_err(|mut e| {
|
||||||
@ -104,8 +105,7 @@ fn bench_emitter(b: &mut Bencher, s: &str) {
|
|||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let buf = vec![];
|
let mut buf = vec![];
|
||||||
let mut src_map_builder = SourceMapBuilder::new(None);
|
|
||||||
{
|
{
|
||||||
let handlers = box MyHandlers;
|
let handlers = box MyHandlers;
|
||||||
let mut emitter = Emitter {
|
let mut emitter = Emitter {
|
||||||
@ -117,14 +117,17 @@ fn bench_emitter(b: &mut Bencher, s: &str) {
|
|||||||
wr: box swc_ecma_codegen::text_writer::JsWriter::new(
|
wr: box swc_ecma_codegen::text_writer::JsWriter::new(
|
||||||
cm.clone(),
|
cm.clone(),
|
||||||
"\n",
|
"\n",
|
||||||
buf,
|
&mut buf,
|
||||||
Some(&mut src_map_builder),
|
Some(&mut src_map_buf),
|
||||||
),
|
),
|
||||||
handlers,
|
handlers,
|
||||||
};
|
};
|
||||||
|
|
||||||
emitter.emit_module(&module)
|
let _ = emitter.emit_module(&module);
|
||||||
}
|
}
|
||||||
|
black_box(buf);
|
||||||
|
let srcmap = cm.build_source_map(&mut src_map_buf);
|
||||||
|
black_box(srcmap);
|
||||||
});
|
});
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
/// [ratel]:https://github.com/ratel-rust/ratel-core
|
/// [ratel]:https://github.com/ratel-rust/ratel-core
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::tests::{assert_min, assert_pretty};
|
use crate::tests::assert_min;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn values() {
|
fn values() {
|
||||||
@ -139,16 +139,16 @@ mod tests {
|
|||||||
assert_min("[,,1];", "[,,1];");
|
assert_min("[,,1];", "[,,1];");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
// #[test]
|
||||||
fn sparse_array_expression_pretty() {
|
// fn sparse_array_expression_pretty() {
|
||||||
assert_pretty("[]", "[];");
|
// assert_pretty("[]", "[];");
|
||||||
assert_pretty("[,]", "[, ];");
|
// assert_pretty("[,]", "[, ];");
|
||||||
assert_pretty("[1,]", "[1, ];");
|
// assert_pretty("[1,]", "[1, ];");
|
||||||
assert_pretty("[,1]", "[, 1];");
|
// assert_pretty("[,1]", "[, 1];");
|
||||||
assert_pretty("[,,];", "[, , ];");
|
// assert_pretty("[,,];", "[, , ];");
|
||||||
assert_pretty("[1,,];", "[1, , ];");
|
// assert_pretty("[1,,];", "[1, , ];");
|
||||||
assert_pretty("[,,1];", "[, , 1];");
|
// assert_pretty("[,,1];", "[, , 1];");
|
||||||
}
|
// }
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn object_expression() {
|
fn object_expression() {
|
||||||
@ -159,8 +159,8 @@ mod tests {
|
|||||||
assert_min("({ foo: 10, bar: 20 });", "({foo:10,bar:20});");
|
assert_min("({ foo: 10, bar: 20 });", "({foo:10,bar:20});");
|
||||||
assert_min("({ foo: 10, bar() {} });", "({foo:10,bar(){}});");
|
assert_min("({ foo: 10, bar() {} });", "({foo:10,bar(){}});");
|
||||||
assert_min("({ foo(bar, baz) {} });", "({foo(bar,baz){}});");
|
assert_min("({ foo(bar, baz) {} });", "({foo(bar,baz){}});");
|
||||||
let expected = "({\n foo: true,\n bar: false\n});";
|
// let expected = "({\n foo: true,\n bar: false\n});";
|
||||||
assert_pretty("({ foo: true, bar: false })", expected);
|
// assert_pretty("({ foo: true, bar: false })", expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
use super::{Result, WriteJs};
|
use super::{Result, WriteJs};
|
||||||
use sourcemap::SourceMapBuilder;
|
|
||||||
use std::{
|
use std::{
|
||||||
io::{self, Write},
|
io::{self, Write},
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
u16,
|
|
||||||
};
|
};
|
||||||
use swc_common::{BytePos, FileName, SourceFile, SourceMap, Span};
|
use swc_common::{BytePos, LineCol, SourceMap, Span};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// -----
|
/// -----
|
||||||
@ -14,17 +12,16 @@ use swc_common::{BytePos, FileName, SourceFile, SourceMap, Span};
|
|||||||
///
|
///
|
||||||
/// https://github.com/Microsoft/TypeScript/blob/45eaf42006/src/compiler/utilities.ts#L2548
|
/// https://github.com/Microsoft/TypeScript/blob/45eaf42006/src/compiler/utilities.ts#L2548
|
||||||
pub struct JsWriter<'a, W: Write> {
|
pub struct JsWriter<'a, W: Write> {
|
||||||
cm: Arc<SourceMap>,
|
/// We may use this in future...
|
||||||
|
_cm: Arc<SourceMap>,
|
||||||
indent: usize,
|
indent: usize,
|
||||||
line_start: bool,
|
line_start: bool,
|
||||||
line_count: usize,
|
line_count: usize,
|
||||||
line_pos: usize,
|
line_pos: usize,
|
||||||
new_line: &'a str,
|
new_line: &'a str,
|
||||||
srcmap: Option<&'a mut SourceMapBuilder>,
|
srcmap: Option<&'a mut Vec<(BytePos, LineCol)>>,
|
||||||
wr: W,
|
wr: W,
|
||||||
written_bytes: usize,
|
written_bytes: usize,
|
||||||
|
|
||||||
files: Vec<Arc<SourceFile>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, W: Write> JsWriter<'a, W> {
|
impl<'a, W: Write> JsWriter<'a, W> {
|
||||||
@ -32,10 +29,10 @@ impl<'a, W: Write> JsWriter<'a, W> {
|
|||||||
cm: Arc<SourceMap>,
|
cm: Arc<SourceMap>,
|
||||||
new_line: &'a str,
|
new_line: &'a str,
|
||||||
wr: W,
|
wr: W,
|
||||||
srcmap: Option<&'a mut SourceMapBuilder>,
|
srcmap: Option<&'a mut Vec<(BytePos, LineCol)>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
JsWriter {
|
JsWriter {
|
||||||
cm,
|
_cm: cm,
|
||||||
indent: Default::default(),
|
indent: Default::default(),
|
||||||
line_start: true,
|
line_start: true,
|
||||||
line_count: 0,
|
line_count: 0,
|
||||||
@ -44,7 +41,6 @@ impl<'a, W: Write> JsWriter<'a, W> {
|
|||||||
srcmap,
|
srcmap,
|
||||||
wr,
|
wr,
|
||||||
written_bytes: 0,
|
written_bytes: 0,
|
||||||
files: Vec::with_capacity(2),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,31 +90,13 @@ impl<'a, W: Write> JsWriter<'a, W> {
|
|||||||
|
|
||||||
fn srcmap(&mut self, byte_pos: BytePos) {
|
fn srcmap(&mut self, byte_pos: BytePos) {
|
||||||
if let Some(ref mut srcmap) = self.srcmap {
|
if let Some(ref mut srcmap) = self.srcmap {
|
||||||
let fm = match SourceMap::lookup_source_file_in(&self.files, byte_pos) {
|
srcmap.push((
|
||||||
Some(fm) => fm,
|
byte_pos,
|
||||||
None => {
|
LineCol {
|
||||||
let fm = self.cm.lookup_source_file(byte_pos);
|
line: self.line_count as _,
|
||||||
self.files.push(fm.clone());
|
col: self.line_pos as _,
|
||||||
fm
|
},
|
||||||
}
|
))
|
||||||
};
|
|
||||||
|
|
||||||
let loc = self.cm.lookup_char_pos_with(fm, byte_pos);
|
|
||||||
|
|
||||||
let src = match loc.file.name {
|
|
||||||
FileName::Real(ref p) => Some(p.display().to_string()),
|
|
||||||
_ => None,
|
|
||||||
};
|
|
||||||
if loc.col.0 < u16::MAX as usize {
|
|
||||||
srcmap.add(
|
|
||||||
self.line_count as _,
|
|
||||||
self.line_pos as _,
|
|
||||||
(loc.line - 1) as _,
|
|
||||||
loc.col.0 as _,
|
|
||||||
src.as_ref().map(|s| &**s),
|
|
||||||
None,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,12 +26,13 @@ pub trait SourceMapperExt {
|
|||||||
fn get_code_map(&self) -> &dyn SourceMapper;
|
fn get_code_map(&self) -> &dyn SourceMapper;
|
||||||
|
|
||||||
fn is_on_same_line(&self, lo: BytePos, hi: BytePos) -> bool {
|
fn is_on_same_line(&self, lo: BytePos, hi: BytePos) -> bool {
|
||||||
let cm = self.get_code_map();
|
// let cm = self.get_code_map();
|
||||||
|
|
||||||
let lo = cm.lookup_char_pos(lo);
|
// let lo = cm.lookup_char_pos(lo);
|
||||||
let hi = cm.lookup_char_pos(hi);
|
// let hi = cm.lookup_char_pos(hi);
|
||||||
|
|
||||||
lo.line == hi.line && lo.file.name_hash == hi.file.name_hash
|
// lo.line == hi.line && lo.file.name_hash == hi.file.name_hash
|
||||||
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn should_write_separating_line_terminator<P: Spanned, N: Spanned>(
|
fn should_write_separating_line_terminator<P: Spanned, N: Spanned>(
|
||||||
|
@ -1 +1,3 @@
|
|||||||
[1];
|
[
|
||||||
|
1
|
||||||
|
];
|
||||||
|
@ -1 +1,3 @@
|
|||||||
a = [1];
|
a = [
|
||||||
|
1
|
||||||
|
];
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
switch(a){
|
switch(a){
|
||||||
case b: {
|
case b:
|
||||||
c;
|
{
|
||||||
}
|
c;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1 +1,3 @@
|
|||||||
var [a] = [1];
|
var [a] = [
|
||||||
|
1
|
||||||
|
];
|
||||||
|
@ -1 +1,4 @@
|
|||||||
[a, b] = [b, a];
|
[a, b] = [
|
||||||
|
b,
|
||||||
|
a
|
||||||
|
];
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
switch(a){
|
switch(a){
|
||||||
case 1: /* perfect */
|
case 1:
|
||||||
b();
|
/* perfect */
|
||||||
|
b();
|
||||||
}
|
}
|
||||||
|
@ -1 +1,5 @@
|
|||||||
[1, 2, 3, ];
|
[
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
];
|
||||||
|
@ -1 +1,4 @@
|
|||||||
for(let a in [1, 2])3;
|
for(let a in [
|
||||||
|
1,
|
||||||
|
2
|
||||||
|
])3;
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
switch(1){
|
switch(1){
|
||||||
case 2: a();
|
case 2:
|
||||||
|
a();
|
||||||
case 3 + 4:
|
case 3 + 4:
|
||||||
b();
|
b();
|
||||||
break;
|
break;
|
||||||
case 5 + 6 + 7: c();
|
case 5 + 6 + 7:
|
||||||
|
c();
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,19 @@
|
|||||||
a = [1, , ];
|
a = [
|
||||||
b = [2, 3, c];
|
1,
|
||||||
d = [4,
|
,
|
||||||
|
];
|
||||||
|
b = [
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
c
|
||||||
|
];
|
||||||
|
d = [
|
||||||
|
4,
|
||||||
,
|
,
|
||||||
5, ];
|
5,
|
||||||
e = [6, c, 7];
|
];
|
||||||
|
e = [
|
||||||
|
6,
|
||||||
|
c,
|
||||||
|
7
|
||||||
|
];
|
||||||
|
@ -4,5 +4,10 @@
|
|||||||
var b = 2;
|
var b = 2;
|
||||||
var c = 3;
|
var c = 3;
|
||||||
var d = [].e.f(arguments);
|
var d = [].e.f(arguments);
|
||||||
return [a, b, c, g];
|
return [
|
||||||
|
a,
|
||||||
|
b,
|
||||||
|
c,
|
||||||
|
g
|
||||||
|
];
|
||||||
}());
|
}());
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
function a() {
|
function a() {
|
||||||
new ['b'];
|
new [
|
||||||
|
'b'
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
switch(a){
|
switch(a){
|
||||||
case 1: let b;
|
case 1:
|
||||||
|
let b;
|
||||||
}
|
}
|
||||||
|
@ -1 +1,3 @@
|
|||||||
[1].a = 2;
|
[
|
||||||
|
1
|
||||||
|
].a = 2;
|
||||||
|
@ -1 +1,4 @@
|
|||||||
for (let a of [1, 2])3;
|
for (let a of [
|
||||||
|
1,
|
||||||
|
2
|
||||||
|
])3;
|
||||||
|
@ -1 +1,4 @@
|
|||||||
[a, ...(b = c)];
|
[
|
||||||
|
a,
|
||||||
|
...(b = c)
|
||||||
|
];
|
||||||
|
@ -1 +1,3 @@
|
|||||||
[{ a =b } = 1];
|
[
|
||||||
|
{ a =b } = 1
|
||||||
|
];
|
||||||
|
@ -1,2 +1,4 @@
|
|||||||
function a([b] = [1]) {
|
function a([b] = [
|
||||||
|
1
|
||||||
|
]) {
|
||||||
}
|
}
|
||||||
|
@ -1 +1,3 @@
|
|||||||
a = [1, ];
|
a = [
|
||||||
|
1,
|
||||||
|
];
|
||||||
|
@ -1 +1,6 @@
|
|||||||
a = [1, 2, , 3, ];
|
a = [
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
,
|
||||||
|
3,
|
||||||
|
];
|
||||||
|
@ -1,10 +1,51 @@
|
|||||||
var a = ['b', 'c', 'd'].e('');
|
var a = [
|
||||||
var f = ['b', 'c', 'd'].e();
|
'b',
|
||||||
var g = ['b', 1, 2, 3, 'c'].e('');
|
'c',
|
||||||
var h = [i(), 'b', 4, 5, 6, 'c', c()].e('');
|
'd'
|
||||||
var j = [i(), c(), 'b', 7, 8, 9, 'c', c()].e('');
|
].e('');
|
||||||
var k = [10, 11, 'b', 'c', d()].e('');
|
var f = [
|
||||||
var l = ['b', 12 + 13 + 'c', 'd'].e('m');
|
'b',
|
||||||
|
'c',
|
||||||
|
'd'
|
||||||
|
].e();
|
||||||
|
var g = [
|
||||||
|
'b',
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
'c'
|
||||||
|
].e('');
|
||||||
|
var h = [
|
||||||
|
i(),
|
||||||
|
'b',
|
||||||
|
4,
|
||||||
|
5,
|
||||||
|
6,
|
||||||
|
'c',
|
||||||
|
c()
|
||||||
|
].e('');
|
||||||
|
var j = [
|
||||||
|
i(),
|
||||||
|
c(),
|
||||||
|
'b',
|
||||||
|
7,
|
||||||
|
8,
|
||||||
|
9,
|
||||||
|
'c',
|
||||||
|
c()
|
||||||
|
].e('');
|
||||||
|
var k = [
|
||||||
|
10,
|
||||||
|
11,
|
||||||
|
'b',
|
||||||
|
'c',
|
||||||
|
d()
|
||||||
|
].e('');
|
||||||
|
var l = [
|
||||||
|
'b',
|
||||||
|
12 + 13 + 'c',
|
||||||
|
'd'
|
||||||
|
].e('m');
|
||||||
var n = [].e(b + c);
|
var n = [].e(b + c);
|
||||||
var o = [].e('');
|
var o = [].e('');
|
||||||
var p = [].e('b');
|
var p = [].e('b');
|
||||||
|
@ -1,10 +1,61 @@
|
|||||||
var a = ['b', 'c', d(), 'e', 'f', 'g'].h('');
|
var a = [
|
||||||
var i = ['b', 'c', d(), 'e', 'f', 'g'].h('j');
|
'b',
|
||||||
var k = ['b', 'c', d(), 'e', 'f', 'g'].h('l');
|
'c',
|
||||||
var m = ['b', 'c', d(),
|
d(),
|
||||||
['b', 1, 2, 3, 'c'].h('+'),
|
'e',
|
||||||
'e', 'f', 'g'].h('j');
|
'f',
|
||||||
var n = ['b', 'c', d(),
|
'g'
|
||||||
['b', 4, 5, 6, 'c'].h('+'),
|
].h('');
|
||||||
'e', 'f', 'g'].h('l');
|
var i = [
|
||||||
var o = ['p', 'p' + q, 'b', 'c', 'r' + b].h('');
|
'b',
|
||||||
|
'c',
|
||||||
|
d(),
|
||||||
|
'e',
|
||||||
|
'f',
|
||||||
|
'g'
|
||||||
|
].h('j');
|
||||||
|
var k = [
|
||||||
|
'b',
|
||||||
|
'c',
|
||||||
|
d(),
|
||||||
|
'e',
|
||||||
|
'f',
|
||||||
|
'g'
|
||||||
|
].h('l');
|
||||||
|
var m = [
|
||||||
|
'b',
|
||||||
|
'c',
|
||||||
|
d(),
|
||||||
|
[
|
||||||
|
'b',
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
'c'
|
||||||
|
].h('+'),
|
||||||
|
'e',
|
||||||
|
'f',
|
||||||
|
'g'
|
||||||
|
].h('j');
|
||||||
|
var n = [
|
||||||
|
'b',
|
||||||
|
'c',
|
||||||
|
d(),
|
||||||
|
[
|
||||||
|
'b',
|
||||||
|
4,
|
||||||
|
5,
|
||||||
|
6,
|
||||||
|
'c'
|
||||||
|
].h('+'),
|
||||||
|
'e',
|
||||||
|
'f',
|
||||||
|
'g'
|
||||||
|
].h('l');
|
||||||
|
var o = [
|
||||||
|
'p',
|
||||||
|
'p' + q,
|
||||||
|
'b',
|
||||||
|
'c',
|
||||||
|
'r' + b
|
||||||
|
].h('');
|
||||||
|
@ -1 +1,5 @@
|
|||||||
[, , 1];
|
[
|
||||||
|
,
|
||||||
|
,
|
||||||
|
1
|
||||||
|
];
|
||||||
|
@ -1,2 +1,4 @@
|
|||||||
([a])=>[1]
|
([a])=>[
|
||||||
|
1
|
||||||
|
]
|
||||||
;
|
;
|
||||||
|
@ -1 +1,6 @@
|
|||||||
[1, 2, , 3, ];
|
[
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
,
|
||||||
|
3,
|
||||||
|
];
|
||||||
|
@ -1 +1,3 @@
|
|||||||
[1, ];
|
[
|
||||||
|
1,
|
||||||
|
];
|
||||||
|
@ -2,5 +2,6 @@ switch(a){
|
|||||||
case 1:
|
case 1:
|
||||||
b();
|
b();
|
||||||
break;
|
break;
|
||||||
default: break;
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
({
|
({
|
||||||
a: [1]
|
a: [
|
||||||
|
1
|
||||||
|
]
|
||||||
} + []) / 2;
|
} + []) / 2;
|
||||||
|
@ -1 +1,4 @@
|
|||||||
for(var a in [1, 2])3;
|
for(var a in [
|
||||||
|
1,
|
||||||
|
2
|
||||||
|
])3;
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
switch(1){
|
switch(1){
|
||||||
case 2: a();
|
case 2:
|
||||||
|
a();
|
||||||
case 3 + 4:
|
case 3 + 4:
|
||||||
b();
|
b();
|
||||||
break;
|
break;
|
||||||
case 5 + 6 + 7: c();
|
case 5 + 6 + 7:
|
||||||
|
c();
|
||||||
default:
|
default:
|
||||||
d();
|
d();
|
||||||
}
|
}
|
||||||
|
@ -1 +1,3 @@
|
|||||||
[/q/];
|
[
|
||||||
|
/q/
|
||||||
|
];
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
switch(a){
|
switch(a){
|
||||||
case 1: b();
|
case 1:
|
||||||
|
b();
|
||||||
}
|
}
|
||||||
|
@ -3,5 +3,7 @@ function a(b = 1) {
|
|||||||
function c(b = (2 + 3)) {
|
function c(b = (2 + 3)) {
|
||||||
}
|
}
|
||||||
function d({ e } = {
|
function d({ e } = {
|
||||||
}, [f] = [4]) {
|
}, [f] = [
|
||||||
|
4
|
||||||
|
]) {
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
switch(a){
|
switch(a){
|
||||||
case 'b': c();
|
case 'b':
|
||||||
|
c();
|
||||||
default:
|
default:
|
||||||
d();
|
d();
|
||||||
break;
|
break;
|
||||||
|
@ -1 +1,3 @@
|
|||||||
let [a, ] = [1];
|
let [a, ] = [
|
||||||
|
1
|
||||||
|
];
|
||||||
|
@ -1 +1,5 @@
|
|||||||
a = [1, 2, 3, ];
|
a = [
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
];
|
||||||
|
@ -1 +1,3 @@
|
|||||||
[1].a = 2;
|
[
|
||||||
|
1
|
||||||
|
].a = 2;
|
||||||
|
@ -1 +1,10 @@
|
|||||||
[, , 1, , , 2, 3, , ];
|
[
|
||||||
|
,
|
||||||
|
,
|
||||||
|
1,
|
||||||
|
,
|
||||||
|
,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
,
|
||||||
|
];
|
||||||
|
@ -1 +1,5 @@
|
|||||||
[1, , 2];
|
[
|
||||||
|
1,
|
||||||
|
,
|
||||||
|
2
|
||||||
|
];
|
||||||
|
@ -1 +1,4 @@
|
|||||||
for (var a of [1, 2])3;
|
for (var a of [
|
||||||
|
1,
|
||||||
|
2
|
||||||
|
])3;
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
{
|
{
|
||||||
[1];
|
[
|
||||||
|
1
|
||||||
|
];
|
||||||
}/foo/;
|
}/foo/;
|
||||||
|
@ -1 +1,5 @@
|
|||||||
a = [, , 1];
|
a = [
|
||||||
|
,
|
||||||
|
,
|
||||||
|
1
|
||||||
|
];
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
switch(a){
|
switch(a){
|
||||||
case 'b': c();
|
case 'b':
|
||||||
|
c();
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ log = "0.4.8"
|
|||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
testing = { version = "0.5", path ="../../testing" }
|
testing = { version = "0.5", path ="../../testing" }
|
||||||
swc_ecma_codegen = { version = "0.17.0", path ="../codegen" }
|
swc_ecma_codegen = { version = "0.18.0", path ="../codegen" }
|
||||||
tempfile = "3"
|
tempfile = "3"
|
||||||
pretty_assertions = "0.6"
|
pretty_assertions = "0.6"
|
||||||
sourcemap = "5"
|
sourcemap = "5"
|
||||||
|
@ -2,7 +2,6 @@ use crate::{
|
|||||||
helpers::{InjectHelpers, HELPERS},
|
helpers::{InjectHelpers, HELPERS},
|
||||||
pass::Pass,
|
pass::Pass,
|
||||||
};
|
};
|
||||||
use sourcemap::SourceMapBuilder;
|
|
||||||
use std::{
|
use std::{
|
||||||
fmt,
|
fmt,
|
||||||
fs::{create_dir_all, remove_dir_all, OpenOptions},
|
fs::{create_dir_all, remove_dir_all, OpenOptions},
|
||||||
@ -139,7 +138,6 @@ impl<'a> Tester<'a> {
|
|||||||
|
|
||||||
let mut wr = Buf(Arc::new(RwLock::new(vec![])));
|
let mut wr = Buf(Arc::new(RwLock::new(vec![])));
|
||||||
{
|
{
|
||||||
let mut src_map_builder = SourceMapBuilder::new(None);
|
|
||||||
let mut emitter = Emitter {
|
let mut emitter = Emitter {
|
||||||
cfg: Default::default(),
|
cfg: Default::default(),
|
||||||
cm: self.cm.clone(),
|
cm: self.cm.clone(),
|
||||||
@ -147,7 +145,7 @@ impl<'a> Tester<'a> {
|
|||||||
self.cm.clone(),
|
self.cm.clone(),
|
||||||
"\n",
|
"\n",
|
||||||
&mut wr,
|
&mut wr,
|
||||||
Some(&mut src_map_builder),
|
None,
|
||||||
),
|
),
|
||||||
comments: None,
|
comments: None,
|
||||||
handlers,
|
handlers,
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
#![allow(unused_macros)]
|
#![allow(unused_macros)]
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
use sourcemap::SourceMapBuilder;
|
|
||||||
use std::{
|
use std::{
|
||||||
fmt,
|
fmt,
|
||||||
fs::{create_dir_all, remove_dir_all, OpenOptions},
|
fs::{create_dir_all, remove_dir_all, OpenOptions},
|
||||||
@ -149,7 +148,6 @@ impl<'a> Tester<'a> {
|
|||||||
|
|
||||||
let mut wr = Buf(Arc::new(RwLock::new(vec![])));
|
let mut wr = Buf(Arc::new(RwLock::new(vec![])));
|
||||||
{
|
{
|
||||||
let mut src_map_builder = SourceMapBuilder::new(None);
|
|
||||||
let mut emitter = Emitter {
|
let mut emitter = Emitter {
|
||||||
cfg: Default::default(),
|
cfg: Default::default(),
|
||||||
cm: self.cm.clone(),
|
cm: self.cm.clone(),
|
||||||
@ -157,7 +155,7 @@ impl<'a> Tester<'a> {
|
|||||||
self.cm.clone(),
|
self.cm.clone(),
|
||||||
"\n",
|
"\n",
|
||||||
&mut wr,
|
&mut wr,
|
||||||
Some(&mut src_map_builder),
|
None,
|
||||||
),
|
),
|
||||||
comments: None,
|
comments: None,
|
||||||
handlers,
|
handlers,
|
||||||
|
27
src/lib.rs
27
src/lib.rs
@ -33,7 +33,6 @@ pub use ecmascript::{
|
|||||||
transforms::{chain_at, pass::Pass},
|
transforms::{chain_at, pass::Pass},
|
||||||
};
|
};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use sourcemap::SourceMapBuilder;
|
|
||||||
use std::{fs::File, path::Path, sync::Arc};
|
use std::{fs::File, path::Path, sync::Arc};
|
||||||
|
|
||||||
pub struct Compiler {
|
pub struct Compiler {
|
||||||
@ -126,21 +125,12 @@ impl Compiler {
|
|||||||
pub fn print(
|
pub fn print(
|
||||||
&self,
|
&self,
|
||||||
program: &Program,
|
program: &Program,
|
||||||
fm: Arc<SourceFile>,
|
|
||||||
comments: &Comments,
|
comments: &Comments,
|
||||||
source_map: bool,
|
source_map: bool,
|
||||||
minify: bool,
|
minify: bool,
|
||||||
) -> Result<TransformOutput, Error> {
|
) -> Result<TransformOutput, Error> {
|
||||||
self.run(|| {
|
self.run(|| {
|
||||||
let mut src_map_builder = SourceMapBuilder::new(None);
|
let mut src_map_buf = vec![];
|
||||||
|
|
||||||
match fm.name {
|
|
||||||
FileName::Real(ref p) => {
|
|
||||||
let id = src_map_builder.add_source(&p.display().to_string());
|
|
||||||
src_map_builder.set_source_contents(id, Some(&fm.src));
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
let src = {
|
let src = {
|
||||||
let mut buf = vec![];
|
let mut buf = vec![];
|
||||||
@ -155,7 +145,7 @@ impl Compiler {
|
|||||||
"\n",
|
"\n",
|
||||||
&mut buf,
|
&mut buf,
|
||||||
if source_map {
|
if source_map {
|
||||||
Some(&mut src_map_builder)
|
Some(&mut src_map_buf)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
},
|
},
|
||||||
@ -174,8 +164,9 @@ impl Compiler {
|
|||||||
code: src,
|
code: src,
|
||||||
map: if source_map {
|
map: if source_map {
|
||||||
let mut buf = vec![];
|
let mut buf = vec![];
|
||||||
src_map_builder
|
|
||||||
.into_sourcemap()
|
self.cm
|
||||||
|
.build_source_map(&mut src_map_buf)
|
||||||
.to_writer(&mut buf)
|
.to_writer(&mut buf)
|
||||||
.map_err(|err| Error::FailedToWriteSourceMap { err })?;
|
.map_err(|err| Error::FailedToWriteSourceMap { err })?;
|
||||||
let map =
|
let map =
|
||||||
@ -323,13 +314,7 @@ impl Compiler {
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
self.print(
|
self.print(&module, &self.comments, config.source_maps, config.minify)
|
||||||
&module,
|
|
||||||
fm,
|
|
||||||
&self.comments,
|
|
||||||
config.source_maps,
|
|
||||||
config.minify,
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -214,7 +214,8 @@ fn issue_414() {
|
|||||||
|
|
||||||
let s2 = file("tests/projects/issue-414/b.ts").unwrap();
|
let s2 = file("tests/projects/issue-414/b.ts").unwrap();
|
||||||
println!("{}", s2);
|
println!("{}", s2);
|
||||||
assert!(s2.contains("define(['bar'], function(_bar) {"));
|
assert!(s2.contains("define("));
|
||||||
|
assert!(s2.contains("function(_bar) {"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// should handle comments in return statement
|
/// should handle comments in return statement
|
||||||
|
Loading…
Reference in New Issue
Block a user