compiler-cli
compiler-core
src
build
javascript
snapshots
compiler-wasm
test
test-package-compiler
···
107
107
108
108
([Surya Rose](https://github.com/GearsDatapacks))
109
109
110
110
+
- Compiler can now emit source maps when targeting javascript. This can be enabled
111
111
+
in the gleam.toml with the `source_maps` setting under the `javascript` section.
112
112
+
([Ameen Radwan](https://github.com/Acepie))
113
113
+
110
114
### Build tool
111
115
112
116
- The `gleam hex owner add` command has been added, which allows adding
···
263
263
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
264
264
265
265
[[package]]
266
266
+
name = "base64-simd"
267
267
+
version = "0.7.0"
268
268
+
source = "registry+https://github.com/rust-lang/crates.io-index"
269
269
+
checksum = "781dd20c3aff0bd194fe7d2a977dd92f21c173891f3a03b677359e5fa457e5d5"
270
270
+
dependencies = [
271
271
+
"simd-abstraction",
272
272
+
]
273
273
+
274
274
+
[[package]]
266
275
name = "basic-toml"
267
276
version = "0.1.9"
268
277
source = "registry+https://github.com/rust-lang/crates.io-index"
···
648
657
"cpufeatures 0.2.12",
649
658
"curve25519-dalek-derive",
650
659
"fiat-crypto",
651
651
-
"rustc_version",
660
660
+
"rustc_version 0.4.1",
652
661
"subtle",
653
662
"zeroize",
654
663
]
···
691
700
checksum = "ffe7ed1d93f4553003e20b629abe9085e1e81b1429520f897f8f8860bc6dfc21"
692
701
693
702
[[package]]
703
703
+
name = "debugid"
704
704
+
version = "0.8.0"
705
705
+
source = "registry+https://github.com/rust-lang/crates.io-index"
706
706
+
checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d"
707
707
+
dependencies = [
708
708
+
"serde",
709
709
+
"uuid",
710
710
+
]
711
711
+
712
712
+
[[package]]
694
713
name = "der-parser"
695
714
version = "10.0.0"
696
715
source = "registry+https://github.com/rust-lang/crates.io-index"
···
1188
1207
"serde",
1189
1208
"serde_derive",
1190
1209
"serde_json",
1210
1210
+
"sourcemap",
1191
1211
"spdx",
1192
1212
"stacker",
1193
1213
"strum",
···
1659
1679
]
1660
1680
1661
1681
[[package]]
1682
1682
+
name = "if_chain"
1683
1683
+
version = "1.0.3"
1684
1684
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1685
1685
+
checksum = "cd62e6b5e86ea8eeeb8db1de02880a6abc01a397b2ebb64b5d74ac255318f5cb"
1686
1686
+
1687
1687
+
[[package]]
1662
1688
name = "ignore"
1663
1689
version = "0.4.25"
1664
1690
source = "registry+https://github.com/rust-lang/crates.io-index"
···
2089
2115
"normpath",
2090
2116
"windows-sys 0.60.2",
2091
2117
]
2118
2118
+
2119
2119
+
[[package]]
2120
2120
+
name = "outref"
2121
2121
+
version = "0.1.0"
2122
2122
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2123
2123
+
checksum = "7f222829ae9293e33a9f5e9f440c6760a3d450a64affe1846486b140db81c1f4"
2092
2124
2093
2125
[[package]]
2094
2126
name = "parking_lot"
···
2710
2742
2711
2743
[[package]]
2712
2744
name = "rustc_version"
2745
2745
+
version = "0.2.3"
2746
2746
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2747
2747
+
checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
2748
2748
+
dependencies = [
2749
2749
+
"semver 0.9.0",
2750
2750
+
]
2751
2751
+
2752
2752
+
[[package]]
2753
2753
+
name = "rustc_version"
2713
2754
version = "0.4.1"
2714
2755
source = "registry+https://github.com/rust-lang/crates.io-index"
2715
2756
checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
2716
2757
dependencies = [
2717
2717
-
"semver",
2758
2758
+
"semver 1.0.23",
2718
2759
]
2719
2760
2720
2761
[[package]]
···
2853
2894
2854
2895
[[package]]
2855
2896
name = "semver"
2897
2897
+
version = "0.9.0"
2898
2898
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2899
2899
+
checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
2900
2900
+
dependencies = [
2901
2901
+
"semver-parser",
2902
2902
+
]
2903
2903
+
2904
2904
+
[[package]]
2905
2905
+
name = "semver"
2856
2906
version = "1.0.23"
2857
2907
source = "registry+https://github.com/rust-lang/crates.io-index"
2858
2908
checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
2909
2909
+
2910
2910
+
[[package]]
2911
2911
+
name = "semver-parser"
2912
2912
+
version = "0.7.0"
2913
2913
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2914
2914
+
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
2859
2915
2860
2916
[[package]]
2861
2917
name = "serde"
···
2990
3046
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
2991
3047
2992
3048
[[package]]
3049
3049
+
name = "simd-abstraction"
3050
3050
+
version = "0.7.1"
3051
3051
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3052
3052
+
checksum = "9cadb29c57caadc51ff8346233b5cec1d240b68ce55cf1afc764818791876987"
3053
3053
+
dependencies = [
3054
3054
+
"outref",
3055
3055
+
]
3056
3056
+
3057
3057
+
[[package]]
2993
3058
name = "similar"
2994
3059
version = "2.5.0"
2995
3060
source = "registry+https://github.com/rust-lang/crates.io-index"
···
3038
3103
dependencies = [
3039
3104
"libc",
3040
3105
"windows-sys 0.59.0",
3106
3106
+
]
3107
3107
+
3108
3108
+
[[package]]
3109
3109
+
name = "sourcemap"
3110
3110
+
version = "9.1.2"
3111
3111
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3112
3112
+
checksum = "27c4ea7042fd1a155ad95335b5d505ab00d5124ea0332a06c8390d200bb1a76a"
3113
3113
+
dependencies = [
3114
3114
+
"base64-simd",
3115
3115
+
"bitvec",
3116
3116
+
"data-encoding",
3117
3117
+
"debugid",
3118
3118
+
"if_chain",
3119
3119
+
"rustc-hash 1.1.0",
3120
3120
+
"rustc_version 0.2.3",
3121
3121
+
"serde",
3122
3122
+
"serde_json",
3123
3123
+
"unicode-id-start",
3124
3124
+
"url",
3041
3125
]
3042
3126
3043
3127
[[package]]
···
3625
3709
]
3626
3710
3627
3711
[[package]]
3712
3712
+
name = "unicode-id-start"
3713
3713
+
version = "1.4.0"
3714
3714
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3715
3715
+
checksum = "81b79ad29b5e19de4260020f8919b443b2ef0277d242ce532ec7b7a2cc8b6007"
3716
3716
+
3717
3717
+
[[package]]
3628
3718
name = "unicode-ident"
3629
3719
version = "1.0.22"
3630
3720
source = "registry+https://github.com/rust-lang/crates.io-index"
···
3688
3778
version = "0.2.2"
3689
3779
source = "registry+https://github.com/rust-lang/crates.io-index"
3690
3780
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
3781
3781
+
3782
3782
+
[[package]]
3783
3783
+
name = "uuid"
3784
3784
+
version = "1.19.0"
3785
3785
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3786
3786
+
checksum = "e2e054861b4bd027cd373e18e8d8d8e6548085000e41290d95ce0c373a654b4a"
3787
3787
+
dependencies = [
3788
3788
+
"js-sys",
3789
3789
+
"wasm-bindgen",
3790
3790
+
]
3691
3791
3692
3792
[[package]]
3693
3793
name = "valuable"
···
30
30
Target::Erlang => TargetCodegenConfiguration::Erlang { app_file: None },
31
31
Target::JavaScript => TargetCodegenConfiguration::JavaScript {
32
32
emit_typescript_definitions: false,
33
33
+
emit_source_maps: false,
33
34
prelude_location: options
34
35
.javascript_prelude
35
36
.ok_or_else(|| Error::JavaScriptPreludeRequired)?,
···
46
46
stacker = "0.1.21"
47
47
# Manipulating bit arrays
48
48
bitvec = { version = "1", features = ["serde"] }
49
49
+
# Sourcemap generation
50
50
+
sourcemap = "9"
51
51
+
49
52
async-trait.workspace = true
50
53
base16.workspace = true
51
54
camino = { workspace = true, features = ["serde1"] }
···
174
174
pub enum TargetCodegenConfiguration {
175
175
JavaScript {
176
176
emit_typescript_definitions: bool,
177
177
+
emit_source_maps: bool,
177
178
prelude_location: Utf8PathBuf,
178
179
},
179
180
Erlang {
···
356
356
match self.target {
357
357
TargetCodegenConfiguration::JavaScript {
358
358
emit_typescript_definitions,
359
359
+
emit_source_maps,
359
360
prelude_location,
360
361
} => self.perform_javascript_codegen(
361
362
modules,
362
363
*emit_typescript_definitions,
364
364
+
*emit_source_maps,
363
365
prelude_location,
364
366
),
365
367
TargetCodegenConfiguration::Erlang { app_file } => {
···
421
423
&mut self,
422
424
modules: &[Module],
423
425
typescript: bool,
426
426
+
sourcemap: bool,
424
427
prelude_location: &Utf8Path,
425
428
) -> Result<(), Error> {
426
429
let mut written = HashSet::new();
···
429
432
} else {
430
433
TypeScriptDeclarations::None
431
434
};
432
432
-
433
433
-
JavaScript::new(&self.out, typescript, prelude_location, &self.root).render(
434
434
-
&self.io,
435
435
-
modules,
436
436
-
self.stdlib_package(),
437
437
-
)?;
435
435
+
JavaScript::new(
436
436
+
&self.out,
437
437
+
typescript,
438
438
+
sourcemap,
439
439
+
prelude_location,
440
440
+
&self.root,
441
441
+
)
442
442
+
.render(&self.io, modules, self.stdlib_package())?;
438
443
439
444
if self.copy_native_files {
440
445
self.copy_project_native_files(&self.out, &mut written)?;
···
599
599
600
600
Target::JavaScript => super::TargetCodegenConfiguration::JavaScript {
601
601
emit_typescript_definitions: self.config.javascript.typescript_declarations,
602
602
+
emit_source_maps: self.config.javascript.source_maps,
602
603
// This path is relative to each package output directory
603
604
prelude_location: Utf8PathBuf::from("../prelude.mjs"),
604
605
},
···
175
175
prelude_location: &'a Utf8Path,
176
176
project_root: &'a Utf8Path,
177
177
typescript: TypeScriptDeclarations,
178
178
+
source_map: bool,
178
179
}
179
180
180
181
impl<'a> JavaScript<'a> {
181
182
pub fn new(
182
183
output_directory: &'a Utf8Path,
183
184
typescript: TypeScriptDeclarations,
185
185
+
source_map: bool,
184
186
prelude_location: &'a Utf8Path,
185
187
project_root: &'a Utf8Path,
186
188
) -> Self {
···
189
191
output_directory,
190
192
project_root,
191
193
typescript,
194
194
+
source_map,
192
195
}
193
196
}
194
197
···
259
262
let name = format!("{js_name}.mjs");
260
263
let path = self.output_directory.join(name);
261
264
let line_numbers = LineNumbers::new(&module.code);
262
262
-
let output = javascript::module(ModuleConfig {
265
265
+
let (output, source_map) = javascript::module(ModuleConfig {
263
266
module: &module.ast,
264
267
line_numbers: &line_numbers,
265
268
path: &module.input_path,
266
269
project_root: self.project_root,
267
270
src: &module.code,
268
271
typescript: self.typescript,
272
272
+
source_map: self.source_map,
269
273
stdlib_package,
270
274
});
271
275
tracing::debug!(name = ?js_name, "Generated js module");
272
272
-
writer.write(&path, &output)
276
276
+
writer.write(&path, &output)?;
277
277
+
278
278
+
if let Some(source_map) = source_map {
279
279
+
let mut output = Vec::new();
280
280
+
// We first write to a vector then build a string, hoping that
281
281
+
// the `sourcemap` crate generated a valid sourcemap. If it
282
282
+
// did not, it is a bug that should be reported.
283
283
+
//
284
284
+
// SourceMap currently does not support being written directly
285
285
+
// to a string.
286
286
+
source_map
287
287
+
.to_writer(&mut output)
288
288
+
.expect("Failed to write sourcemap to memory.");
289
289
+
let content =
290
290
+
String::from_utf8(output).expect("Sourcemap did not generate valid UTF-8.");
291
291
+
let source_map_path = self.output_directory.join(format!("{js_name}.mjs.map"));
292
292
+
tracing::debug!(path = ?source_map_path, name = ?js_name, "Emitting sourcemap for module");
293
293
+
writer.write(&source_map_path, &content)?;
294
294
+
}
295
295
+
Ok(())
273
296
}
274
297
}
···
726
726
pub struct JavaScriptConfig {
727
727
#[serde(default)]
728
728
pub typescript_declarations: bool,
729
729
+
#[serde(default)]
730
730
+
pub source_maps: bool,
729
731
#[serde(default = "default_javascript_runtime")]
730
732
pub runtime: Runtime,
731
733
#[serde(default, rename = "deno")]
···
1161
1163
1162
1164
[javascript]
1163
1165
typescript_declarations = true
1166
1166
+
source_maps = true
1164
1167
runtime = "node"
1165
1168
1166
1169
[javascript.deno]
···
319
319
}
320
320
}
321
321
322
322
-
fn register_custom_type_exports(
322
322
+
fn register_custom_type_exports<'a>(
323
323
custom_type: &TypedCustomType,
324
324
-
type_exports: &mut Vec<Document<'_>>,
325
325
-
type_defs: &mut Vec<Document<'_>>,
326
326
-
module_name: &str,
324
324
+
type_exports: &mut Vec<Document<'a>>,
325
325
+
type_defs: &mut Vec<Document<'a>>,
326
326
+
module_name: &'a str,
327
327
) {
328
328
let TypedCustomType {
329
329
name,
···
5
5
mod tests;
6
6
mod typescript;
7
7
8
8
+
use std::cell::RefCell;
8
9
use std::collections::HashMap;
10
10
+
use std::rc::Rc;
9
11
12
12
+
use debug_ignore::DebugIgnore;
10
13
use num_bigint::BigInt;
11
14
use num_traits::ToPrimitive;
15
15
+
use sourcemap::SourceMap;
12
16
13
17
use crate::build::Target;
14
18
use crate::build::package_compiler::StdlibPackage;
15
19
use crate::codegen::TypeScriptDeclarations;
20
20
+
use crate::line_numbers::LineColumn;
21
21
+
use crate::pretty::CursorPositionObserver;
16
22
use crate::type_::{PRELUDE_MODULE_NAME, RecordAccessor};
17
23
use crate::{
18
24
ast::{Import, *},
···
38
44
TypeScriptDeclarations,
39
45
}
40
46
47
47
+
/// A cursor position observer that does nothing.
48
48
+
/// Mainly used to allow us to create a cursor position observer that does
49
49
+
/// nothing without having to check if the source map builder is present.
50
50
+
#[derive(Debug, Clone, Copy)]
51
51
+
pub struct NullCursorPositionObserver;
52
52
+
53
53
+
impl CursorPositionObserver for NullCursorPositionObserver {
54
54
+
fn observe_cursor_position(&mut self, _line: isize, _width: isize) {
55
55
+
// Do nothing
56
56
+
}
57
57
+
}
58
58
+
59
59
+
/// A cursor position observer that observes the cursor position and adds it
60
60
+
/// to the source map builder. When notified it will take the destination
61
61
+
/// location and map it to the initial source location given when
62
62
+
/// creating the observer.
63
63
+
#[derive(Debug)]
64
64
+
pub struct SourceMapCursorPositionObserver {
65
65
+
source_start_location: LineColumn,
66
66
+
source_map_builder: Rc<RefCell<DebugIgnore<sourcemap::SourceMapBuilder>>>,
67
67
+
}
68
68
+
69
69
+
impl SourceMapCursorPositionObserver {
70
70
+
pub fn new(
71
71
+
source_start_location: LineColumn,
72
72
+
source_map_builder: Rc<RefCell<DebugIgnore<sourcemap::SourceMapBuilder>>>,
73
73
+
) -> Self {
74
74
+
Self {
75
75
+
source_start_location,
76
76
+
source_map_builder,
77
77
+
}
78
78
+
}
79
79
+
}
80
80
+
81
81
+
impl CursorPositionObserver for SourceMapCursorPositionObserver {
82
82
+
fn observe_cursor_position(&mut self, line: isize, column: isize) {
83
83
+
let _ = self.source_map_builder.borrow_mut().add_raw(
84
84
+
line as u32,
85
85
+
column as u32,
86
86
+
// SourceMapBuilder expects 0-based line and column numbers and we use 1-based ones
87
87
+
self.source_start_location.line - 1,
88
88
+
self.source_start_location.column - 1,
89
89
+
// Since we have a 1-1 mapping between source and destination locations
90
90
+
// We always use 0 for the source index.
91
91
+
Some(0),
92
92
+
None,
93
93
+
false,
94
94
+
);
95
95
+
}
96
96
+
}
97
97
+
41
98
#[derive(Debug)]
42
99
pub struct Generator<'a> {
43
100
line_numbers: &'a LineNumbers,
···
46
103
module_scope: im::HashMap<EcoString, usize>,
47
104
current_module_name_segments_count: usize,
48
105
typescript: TypeScriptDeclarations,
106
106
+
// Debug ignored since SourceMapBuilder doesn't implement debug
107
107
+
source_map_builder: Option<Rc<RefCell<DebugIgnore<sourcemap::SourceMapBuilder>>>>,
49
108
stdlib_package: StdlibPackage,
50
109
/// Relative path to the module, surrounded in `"`s to make it a string, and with `\`s escaped
51
110
/// to `\\`.
···
56
115
pub fn new(config: ModuleConfig<'a>) -> Self {
57
116
let ModuleConfig {
58
117
typescript,
118
118
+
source_map,
59
119
stdlib_package,
60
120
module,
61
121
line_numbers,
62
122
src: _,
63
63
-
path: _,
123
123
+
path,
64
124
project_root,
65
125
} = config;
66
126
let current_module_name_segments_count = module.name.split('/').count();
···
71
131
.unwrap_or(src_path)
72
132
.as_str();
73
133
let src_path = eco_format!("\"{src_path}\"").replace("\\", "\\\\");
74
74
-
75
134
Self {
76
135
current_module_name_segments_count,
77
136
line_numbers,
···
80
139
tracker: UsageTracker::default(),
81
140
module_scope: Default::default(),
82
141
typescript,
142
142
+
source_map_builder: if source_map {
143
143
+
let module_name = module.name.clone();
144
144
+
// Need the absolute path to the module to be able to map the
145
145
+
// destination location back to the source location.
146
146
+
let src_path_str = path.as_str();
147
147
+
let output_path = format!("{module_name}.mjs");
148
148
+
let mut source_map_builder =
149
149
+
sourcemap::SourceMapBuilder::new(Some(&output_path.clone()));
150
150
+
let _ = source_map_builder.add_source(src_path_str);
151
151
+
Some(Rc::new(RefCell::new(DebugIgnore(source_map_builder))))
152
152
+
} else {
153
153
+
None
154
154
+
},
83
155
stdlib_package,
84
156
}
85
157
}
···
101
173
docvec!["/// <reference types=\"./", module, ".d.mts\" />", line()]
102
174
}
103
175
176
176
+
fn sourcemap_reference(&self) -> Document<'a> {
177
177
+
match self.source_map_builder {
178
178
+
None => "".to_doc(),
179
179
+
Some(_) => {
180
180
+
// Get the name of the module relative the directory (similar to basename)
181
181
+
let module = self
182
182
+
.module
183
183
+
.name
184
184
+
.as_str()
185
185
+
.split('/')
186
186
+
.next_back()
187
187
+
.expect("JavaScript generator could not identify imported module name.");
188
188
+
189
189
+
docvec!["//# sourceMappingURL=", module, ".mjs.map", line()]
190
190
+
}
191
191
+
}
192
192
+
}
193
193
+
104
194
pub fn compile(&mut self) -> Document<'a> {
105
195
// Determine what JavaScript imports we need to generate
106
196
let mut imports = self.collect_imports();
···
215
305
}
216
306
217
307
let echo_definition = self.echo_definition(&mut imports);
308
308
+
let sourcemap_reference = self.sourcemap_reference();
218
309
let type_reference = self.type_reference();
219
310
let filepath_definition = self.filepath_definition();
220
311
···
222
313
223
314
if imports.is_empty() && statements.is_empty() {
224
315
docvec![
316
316
+
sourcemap_reference,
225
317
type_reference,
226
318
filepath_definition,
227
319
"export {}",
···
231
323
} else if imports.is_empty() {
232
324
statements.push(line());
233
325
docvec![
326
326
+
sourcemap_reference,
234
327
type_reference,
235
328
filepath_definition,
236
329
statements,
···
238
331
]
239
332
} else if statements.is_empty() {
240
333
docvec![
334
334
+
sourcemap_reference,
241
335
type_reference,
242
336
imports.into_doc(JavaScriptCodegenTarget::JavaScript),
243
337
filepath_definition,
···
245
339
]
246
340
} else {
247
341
docvec![
342
342
+
sourcemap_reference,
248
343
type_reference,
249
344
imports.into_doc(JavaScriptCodegenTarget::JavaScript),
250
345
line(),
···
396
491
.group();
397
492
398
493
docvec![
494
494
+
self.source_map_tracker(constructor.location.start),
399
495
"export const ",
400
496
type_name,
401
497
"$",
···
421
517
.group();
422
518
423
519
docvec![
520
520
+
self.source_map_tracker(constructor.location.start),
424
521
"export const ",
425
522
type_name,
426
523
"$is",
···
464
561
465
562
functions.push(docvec![
466
563
line(),
564
564
+
self.source_map_tracker(constructor.location.start),
467
565
"export const ",
468
566
function_name,
469
567
" = (value) =>",
···
475
573
476
574
functions.push(docvec![
477
575
line(),
576
576
+
self.source_map_tracker(constructor.location.start),
478
577
"export const ",
479
578
function_name,
480
579
" = (value) =>",
···
530
629
} else {
531
630
"class "
532
631
};
533
533
-
let head = docvec![head, &constructor.name, " extends $CustomType {"];
632
632
+
633
633
+
let sourcemap_cursor_position_observer =
634
634
+
self.source_map_tracker(constructor.location.start);
635
635
+
636
636
+
let head = docvec![
637
637
+
sourcemap_cursor_position_observer,
638
638
+
head,
639
639
+
&constructor.name,
640
640
+
" extends $CustomType {"
641
641
+
];
534
642
535
643
if constructor.arguments.is_empty() {
536
644
return head.append("}");
···
736
844
vec![],
737
845
&mut self.tracker,
738
846
self.module_scope.clone(),
847
847
+
self.source_map_builder.clone(),
739
848
);
740
849
741
850
let document = generator.constant_expression(Context::Constant, value);
···
748
857
749
858
Some(docvec![
750
859
jsdoc,
860
860
+
self.source_map_tracker(location.start),
751
861
head,
752
862
maybe_escape_identifier(name),
753
863
" = ",
···
781
891
if !function.implementations.supports(Target::JavaScript) {
782
892
return None;
783
893
}
894
894
+
let function_source_mapping = self.source_map_tracker(function.location.start);
784
895
785
896
let (_, name) = function
786
897
.name
···
799
910
argument_names,
800
911
&mut self.tracker,
801
912
self.module_scope.clone(),
913
913
+
self.source_map_builder.clone(),
802
914
);
803
915
804
916
let function_doc = match &function.documentation {
···
818
930
819
931
Some(docvec![
820
932
function_doc,
933
933
+
function_source_mapping,
821
934
head,
822
935
maybe_escape_identifier(name.as_str()),
823
936
fun_arguments(function.arguments.as_slice(), generator.tail_recursion_used),
···
853
966
854
967
docvec!["const FILEPATH = ", self.src_path.clone(), ';', lines(2)]
855
968
}
969
969
+
970
970
+
fn source_map_tracker(&self, start_index: u32) -> Document<'a> {
971
971
+
create_cursor_position_observer(&self.source_map_builder, self.line_numbers, start_index)
972
972
+
}
856
973
}
857
974
858
975
fn jsdoc_comment(documentation: &EcoString, publicity: Publicity) -> Document<'_> {
···
880
997
pub line_numbers: &'a LineNumbers,
881
998
pub src: &'a EcoString,
882
999
pub typescript: TypeScriptDeclarations,
1000
1000
+
pub source_map: bool,
883
1001
pub stdlib_package: StdlibPackage,
884
1002
pub path: &'a Utf8Path,
885
1003
pub project_root: &'a Utf8Path,
886
1004
}
887
1005
888
888
-
pub fn module(config: ModuleConfig<'_>) -> String {
889
889
-
let document = Generator::new(config).compile();
890
890
-
document.to_pretty_string(80)
1006
1006
+
pub fn module(config: ModuleConfig<'_>) -> (String, Option<SourceMap>) {
1007
1007
+
let (output, sourcemap_builder) = {
1008
1008
+
let mut generator = Generator::new(config);
1009
1009
+
let document = generator.compile();
1010
1010
+
let builder = generator.source_map_builder;
1011
1011
+
(document.to_pretty_string(80), builder)
1012
1012
+
};
1013
1013
+
let source_map = sourcemap_builder.map(|builder| {
1014
1014
+
// We have completed the generation of the module, so we can now take ownership of the builder.
1015
1015
+
Rc::try_unwrap(builder)
1016
1016
+
.unwrap_or_else(|_| panic!("Failed to take ownership of sourcemap builder"))
1017
1017
+
.into_inner()
1018
1018
+
.0
1019
1019
+
.into_sourcemap()
1020
1020
+
});
1021
1021
+
(output, source_map)
891
1022
}
892
1023
893
1024
pub fn ts_declaration(module: &TypedModule) -> String {
894
1025
let document = typescript::TypeScriptGenerator::new(module).compile();
895
1026
document.to_pretty_string(80)
1027
1027
+
}
1028
1028
+
1029
1029
+
fn create_cursor_position_observer<'a>(
1030
1030
+
builder: &Option<Rc<RefCell<DebugIgnore<sourcemap::SourceMapBuilder>>>>,
1031
1031
+
line_numbers: &LineNumbers,
1032
1032
+
start_index: u32,
1033
1033
+
) -> Document<'a> {
1034
1034
+
let start_location = line_numbers.line_and_column_number(start_index);
1035
1035
+
Document::CursorPositionObserver {
1036
1036
+
observer: match builder {
1037
1037
+
None => Rc::new(RefCell::new(NullCursorPositionObserver)),
1038
1038
+
Some(builder) => Rc::new(RefCell::new(SourceMapCursorPositionObserver::new(
1039
1039
+
start_location,
1040
1040
+
builder.clone(),
1041
1041
+
))),
1042
1042
+
},
1043
1043
+
}
896
1044
}
897
1045
898
1046
fn fun_arguments(arguments: &'_ [TypedArg], tail_recursion_used: bool) -> Document<'_> {
···
1089
1237
pub echo_used: bool,
1090
1238
}
1091
1239
1092
1092
-
fn bool(bool: bool) -> Document<'static> {
1240
1240
+
fn bool<'a>(bool: bool) -> Document<'a> {
1093
1241
match bool {
1094
1242
true => "true".to_doc(),
1095
1243
false => "false".to_doc(),
···
80
80
| Decision::Switch { .. }
81
81
| Decision::Fail) => printer.decision(tree).into_doc(),
82
82
};
83
83
-
docvec![assignments_to_doc(assignments), decision].force_break()
83
83
+
docvec![
84
84
+
subjects
85
85
+
.first()
86
86
+
.map(|subject| expression_generator.source_map_tracker(subject.location().start))
87
87
+
.unwrap_or_else(nil),
88
88
+
assignments_to_doc(&mut *expression_generator, assignments),
89
89
+
decision
90
90
+
]
91
91
+
.force_break()
84
92
}
85
93
86
94
/// The generated code for a decision tree.
···
321
329
}
322
330
}
323
331
Decision::Run { body } => {
324
324
-
let bindings = self.variables.bindings_doc(&body.bindings);
332
332
+
let location = match self.kind {
333
333
+
DecisionKind::Case { clauses } => clauses
334
334
+
.get(body.clause_index)
335
335
+
.expect("invalid clause index")
336
336
+
.location(),
337
337
+
DecisionKind::LetAssert {
338
338
+
subject_location, ..
339
339
+
} => subject_location,
340
340
+
};
341
341
+
let source_map_tracker = self
342
342
+
.variables
343
343
+
.expression_generator
344
344
+
.source_map_tracker(location.start);
345
345
+
let bindings = docvec![
346
346
+
source_map_tracker,
347
347
+
self.variables.bindings_doc(&body.bindings)
348
348
+
];
325
349
let body = self.body_expression(body.clause_index);
326
350
let body = match body {
327
351
BodyExpression::Variable(variable) => variable,
···
836
860
let assignment = variables.assign_let_subject(compiled_case, subject);
837
861
let assignment_name = assignment.name();
838
862
let assignments = vec![assignment];
839
839
-
863
863
+
let pattern_location = pattern.location();
840
864
let decision = CasePrinter {
841
865
variables,
842
866
assignments: &assignments,
843
867
kind: DecisionKind::LetAssert {
844
868
kind,
845
869
subject_location: subject.location(),
846
846
-
pattern_location: pattern.location(),
870
870
+
pattern_location,
847
871
subject: assignment_name.clone(),
848
872
},
849
873
}
850
874
.decision(&compiled_case.tree);
875
875
+
876
876
+
let assignments_doc = assignments_to_doc(expression_generator, assignments);
851
877
852
878
// When we generate `let assert` statements, we want to produce code like
853
879
// this:
···
875
901
});
876
902
877
903
let doc = docvec![
878
878
-
assignments_to_doc(assignments),
904
904
+
assignments_doc,
879
905
concat(beginning_assignments),
880
906
decision.into_doc()
881
907
];
···
1876
1902
BindToVariable {
1877
1903
name: EcoString,
1878
1904
value: Document<'a>,
1905
1905
+
location: SrcSpan,
1879
1906
},
1880
1907
/// The subject is already a simple variable with the given name, we will
1881
1908
/// keep using that name to reference it.
···
1885
1912
impl SubjectAssignment<'_> {
1886
1913
fn name(&self) -> EcoString {
1887
1914
match self {
1888
1888
-
SubjectAssignment::BindToVariable { name, value: _ }
1915
1915
+
SubjectAssignment::BindToVariable {
1916
1916
+
name,
1917
1917
+
value: _,
1918
1918
+
location: _,
1919
1919
+
}
1889
1920
| SubjectAssignment::AlreadyAVariable { name } => name.clone(),
1890
1921
}
1891
1922
}
···
1917
1948
let value = expression_generator
1918
1949
.not_in_tail_position(Some(ordering), |this| this.wrap_expression(subject));
1919
1950
1920
1920
-
SubjectAssignment::BindToVariable { value, name }
1951
1951
+
SubjectAssignment::BindToVariable {
1952
1952
+
value,
1953
1953
+
name,
1954
1954
+
location: subject.location(),
1955
1955
+
}
1921
1956
}
1922
1957
}
1923
1958
1924
1924
-
fn assignments_to_doc(assignments: Vec<SubjectAssignment<'_>>) -> Document<'_> {
1959
1959
+
fn assignments_to_doc<'a>(
1960
1960
+
expression_generator: &mut Generator<'_, 'a>,
1961
1961
+
assignments: Vec<SubjectAssignment<'a>>,
1962
1962
+
) -> Document<'a> {
1925
1963
let mut assignments_docs = vec![];
1926
1964
for assignment in assignments.into_iter() {
1927
1927
-
let SubjectAssignment::BindToVariable { name, value } = assignment else {
1965
1965
+
let SubjectAssignment::BindToVariable {
1966
1966
+
name,
1967
1967
+
value,
1968
1968
+
location,
1969
1969
+
} = assignment
1970
1970
+
else {
1928
1971
continue;
1929
1972
};
1930
1930
-
assignments_docs.push(docvec![let_doc(name, value), line()])
1973
1973
+
assignments_docs.push(docvec![
1974
1974
+
expression_generator.source_map_tracker(location.start),
1975
1975
+
let_doc(name, value),
1976
1976
+
line()
1977
1977
+
])
1931
1978
}
1932
1979
assignments_docs.to_doc()
1933
1980
}
···
176
176
/// This means we can stop code generation for all the following statements
177
177
/// in the same block!
178
178
pub let_assert_always_panics: bool,
179
179
+
180
180
+
pub source_map_builder: Option<Rc<RefCell<DebugIgnore<sourcemap::SourceMapBuilder>>>>,
179
181
}
180
182
181
183
impl<'module, 'a> Generator<'module, 'a> {
···
188
190
function_arguments: Vec<Option<&'module EcoString>>,
189
191
tracker: &'module mut UsageTracker,
190
192
mut current_scope_vars: im::HashMap<EcoString, usize>,
193
193
+
source_map_builder: Option<Rc<RefCell<DebugIgnore<sourcemap::SourceMapBuilder>>>>,
191
194
) -> Self {
192
195
let mut current_function = CurrentFunction::Module;
193
196
for &name in function_arguments.iter().flatten() {
···
214
217
scope_position: Position::Tail,
215
218
statement_level: Vec::new(),
216
219
let_assert_always_panics: false,
220
220
+
source_map_builder,
217
221
}
218
222
}
219
223
···
249
253
}
250
254
251
255
fn tail_call_loop(&mut self, body: Document<'a>, arguments: &'a [TypedArg]) -> Document<'a> {
252
252
-
let loop_assignments = concat(arguments.iter().flat_map(Arg::get_variable_name).map(
253
253
-
|name| {
256
256
+
let loop_assignments = concat(arguments.iter().flat_map(|arg| {
257
257
+
arg.get_variable_name().map(|name| {
254
258
let var = maybe_escape_identifier(name);
255
255
-
docvec!["let ", var, " = loop$", name, ";", line()]
256
256
-
},
257
257
-
));
259
259
+
docvec![
260
260
+
self.source_map_tracker(arg.location.start),
261
261
+
"let ",
262
262
+
var,
263
263
+
" = loop$",
264
264
+
name,
265
265
+
";",
266
266
+
line()
267
267
+
]
268
268
+
})
269
269
+
}));
258
270
docvec![
259
271
"while (true) {",
260
272
docvec![line(), loop_assignments, body].nest(INDENT),
···
392
404
}
393
405
};
394
406
if expression.handles_own_return() {
395
395
-
document
407
407
+
docvec![
408
408
+
self.source_map_tracker(expression.location().start),
409
409
+
document
410
410
+
]
396
411
} else {
397
397
-
self.wrap_return(document)
412
412
+
docvec![
413
413
+
self.source_map_tracker(expression.location().start),
414
414
+
self.wrap_return(document)
415
415
+
]
398
416
}
399
417
}
400
418
···
742
760
documents.push(";".to_doc());
743
761
} else {
744
762
// Otherwise we assign the intermediate pipe value to a variable.
745
745
-
let assignment_document = self
746
746
-
.not_in_tail_position(Some(Ordering::Strict), |this| {
747
747
-
this.simple_variable_assignment(&assignment.name, &assignment.value)
763
763
+
let assignment_document =
764
764
+
self.not_in_tail_position(Some(Ordering::Strict), |this| {
765
765
+
this.simple_variable_assignment(
766
766
+
&assignment.name,
767
767
+
&assignment.value,
768
768
+
&assignment.location,
769
769
+
)
748
770
});
749
771
documents.push(self.add_statement_level(assignment_document));
750
772
latest_local_var = Some(self.local_var(&assignment.name));
···
890
912
&mut self,
891
913
name: &'a EcoString,
892
914
value: &'a TypedExpr,
915
915
+
location: &'a SrcSpan,
893
916
) -> Document<'a> {
894
917
// Subject must be rendered before the variable for variable numbering
895
918
let subject =
896
919
self.not_in_tail_position(Some(Ordering::Loose), |this| this.wrap_expression(value));
897
920
let js_name = self.next_local_var(name);
898
898
-
let assignment = docvec!["let ", js_name.clone(), " = ", subject, ";"];
921
921
+
let assignment = docvec![
922
922
+
self.source_map_tracker(location.start),
923
923
+
"let ",
924
924
+
js_name.clone(),
925
925
+
" = ",
926
926
+
subject,
927
927
+
";"
928
928
+
];
899
929
let assignment = match &self.scope_position {
900
930
Position::Expression(_) | Position::Statement => assignment,
901
931
Position::Tail => docvec![assignment, line(), "return ", js_name, ";"],
···
918
948
kind,
919
949
value,
920
950
compiled_case,
951
951
+
location,
921
952
annotation: _,
922
922
-
location: _,
923
953
} = assignment;
924
954
925
955
// In case the pattern is just a variable, we special case it to
926
956
// generate just a simple assignment instead of using the decision tree
927
957
// for the code generation step.
928
958
if let TypedPattern::Variable { name, .. } = pattern {
929
929
-
return self.simple_variable_assignment(name, value);
959
959
+
return self.simple_variable_assignment(name, value, location);
930
960
}
931
961
932
932
-
decision::let_(compiled_case, value, kind, self, pattern)
962
962
+
docvec![
963
963
+
self.source_map_tracker(location.start),
964
964
+
decision::let_(compiled_case, value, kind, self, pattern)
965
965
+
]
933
966
}
934
967
935
968
fn assert(&mut self, assert: &'a TypedAssert) -> Document<'a> {
···
1102
1135
fields.push(("expression_start", subject.location().start.to_doc()));
1103
1136
1104
1137
docvec![
1138
1138
+
self.source_map_tracker(location.start),
1105
1139
"if (",
1106
1140
docvec!["!", subject_document].nest(INDENT),
1107
1141
break_("", ""),
···
1257
1291
];
1258
1292
1259
1293
docvec![
1294
1294
+
self.source_map_tracker(location.start),
1260
1295
"if (",
1261
1296
left_value.nest(INDENT),
1262
1297
") {",
···
1320
1355
1321
1356
docvec![
1322
1357
line(),
1358
1358
+
self.source_map_tracker(location.start),
1323
1359
"if (",
1324
1360
docvec!["!(", left_value, " || ", right_value, ")"].nest(INDENT),
1325
1361
") {",
···
1918
1954
let fields = wrap_object(fields.into_iter().map(|(k, v)| (k.to_doc(), Some(v))));
1919
1955
1920
1956
docvec![
1957
1957
+
self.source_map_tracker(location.start),
1921
1958
"throw makeError",
1922
1959
wrap_arguments([
1923
1960
string(error_name),
···
2442
2479
| Constant::Invalid { .. } => self.constant_expression(Context::Guard, expression),
2443
2480
}
2444
2481
}
2482
2482
+
2483
2483
+
pub fn source_map_tracker(&mut self, start_index: u32) -> Document<'a> {
2484
2484
+
create_cursor_position_observer(&self.source_map_builder, self.line_numbers, start_index)
2485
2485
+
}
2445
2486
}
2446
2487
2447
2488
#[derive(Clone, Copy)]
···
2517
2558
out.to_doc()
2518
2559
}
2519
2560
2520
2520
-
pub fn float_from_value(value: f64) -> Document<'static> {
2561
2561
+
pub fn float_from_value<'a>(value: f64) -> Document<'a> {
2521
2562
if value.is_infinite() {
2522
2563
if value.is_sign_positive() {
2523
2564
"Infinity".to_doc()
···
2599
2640
}
2600
2641
}
2601
2642
2602
2602
-
pub fn string(value: &str) -> Document<'_> {
2643
2643
+
pub fn string<'a>(value: &'a str) -> Document<'a> {
2603
2644
if value.contains('\n') {
2604
2645
EcoString::from(value.replace('\n', r"\n"))
2605
2646
.to_doc()
···
8
8
warning::{TypeWarningEmitter, WarningEmitter},
9
9
};
10
10
use camino::{Utf8Path, Utf8PathBuf};
11
11
+
use lsp_types::Position;
11
12
12
13
mod assert;
13
14
mod assignments;
···
31
32
mod records;
32
33
mod recursion;
33
34
mod results;
35
35
+
mod sourcemaps;
34
36
mod strings;
35
37
mod todo;
36
38
mod tuples;
···
86
88
}
87
89
88
90
#[macro_export]
91
91
+
macro_rules! assert_source_map {
92
92
+
($src:expr $(,)?) => {{
93
93
+
let (compiled, source_map) =
94
94
+
$crate::javascript::tests::compile_js_with_source_map($src, vec![]);
95
95
+
96
96
+
let output = format!(
97
97
+
"----- SOURCE CODE\n{}\n\n----- COMPILED JAVASCRIPT\n{}\n\n----- SOURCE MAP\n{}",
98
98
+
$crate::javascript::tests::append_line_numbers($src),
99
99
+
$crate::javascript::tests::append_line_numbers(&compiled),
100
100
+
$crate::javascript::tests::source_map_to_string($src, &compiled, source_map)
101
101
+
);
102
102
+
insta::assert_snapshot!(insta::internals::AutoName, output, $src);
103
103
+
}};
104
104
+
}
105
105
+
106
106
+
#[macro_export]
89
107
macro_rules! assert_ts_def {
90
108
(($dep_1_package:expr, $dep_1_name:expr, $dep_1_src:expr), ($dep_2_package:expr, $dep_2_name:expr, $dep_2_src:expr), $src:expr $(,)?) => {{
91
109
let compiled = $crate::javascript::tests::compile_ts(
···
195
213
let ast = compile(src, deps);
196
214
let line_numbers = LineNumbers::new(src);
197
215
let stdlib_package = StdlibPackage::Present;
198
198
-
let output = module(ModuleConfig {
216
216
+
let (output, _) = module(ModuleConfig {
199
217
module: &ast,
200
218
line_numbers: &line_numbers,
201
219
src: &"".into(),
202
220
typescript: TypeScriptDeclarations::None,
221
221
+
source_map: false,
203
222
stdlib_package,
204
223
path: Utf8Path::new("src/module.gleam"),
205
224
project_root: "project/root".into(),
···
211
230
)
212
231
}
213
232
233
233
+
pub fn compile_js_with_source_map(src: &str, deps: Vec<(&str, &str, &str)>) -> (String, SourceMap) {
234
234
+
let ast = compile(src, deps);
235
235
+
let line_numbers = LineNumbers::new(src);
236
236
+
let stdlib_package = StdlibPackage::Present;
237
237
+
let (output, source_map) = module(ModuleConfig {
238
238
+
module: &ast,
239
239
+
line_numbers: &line_numbers,
240
240
+
src: &"".into(),
241
241
+
typescript: TypeScriptDeclarations::None,
242
242
+
source_map: true,
243
243
+
stdlib_package,
244
244
+
path: Utf8Path::new("src/module.gleam"),
245
245
+
project_root: "project/root".into(),
246
246
+
});
247
247
+
let source_map = source_map.expect("source map should always be present");
248
248
+
249
249
+
let output = output.replace(
250
250
+
std::include_str!("../../templates/echo.mjs"),
251
251
+
"// ...omitted code from `templates/echo.mjs`...",
252
252
+
);
253
253
+
(output, source_map)
254
254
+
}
255
255
+
214
256
pub fn compile_ts(src: &str, deps: Vec<(&str, &str, &str)>) -> String {
215
257
let ast = compile(src, deps);
216
258
ts_declaration(&ast)
217
259
}
260
260
+
261
261
+
// Append zero indexed line numbers to the code for easier reading of source maps.
262
262
+
pub fn append_line_numbers(src: &str) -> String {
263
263
+
src.lines()
264
264
+
.enumerate()
265
265
+
.map(|(line, content)| format!("{} |{}", line, content))
266
266
+
.collect::<Vec<String>>()
267
267
+
.join("\n")
268
268
+
}
269
269
+
270
270
+
// Pretty-print a sourcemap to a string that might be readable by humans.
271
271
+
pub fn source_map_to_string(src: &str, compiled: &str, source_map: SourceMap) -> String {
272
272
+
let mut output = String::new();
273
273
+
output.push_str("Mappings:\n");
274
274
+
output.push_str("----- \n");
275
275
+
let mut prev_src_index = 0;
276
276
+
let mut prev_compiled_index = 0;
277
277
+
let src_line_numbers = LineNumbers::new(&src);
278
278
+
let compiled_line_numbers = LineNumbers::new(&compiled);
279
279
+
280
280
+
// Since source maps can have multiple tokens for the same source index, we skip over the intermediate tokens and only keep tokens with a new source index.
281
281
+
let mut tokens = source_map.tokens().collect::<Vec<_>>();
282
282
+
tokens.sort_by_key(|token| token.get_src());
283
283
+
// construct a vector of tuples of (src_line, src_col, dst_line, dst_col)
284
284
+
let mut merged_tokens: Vec<((u32, u32), (u32, u32))> = Vec::new();
285
285
+
let mut prev_token_src = (0, 0);
286
286
+
for token in tokens {
287
287
+
if prev_token_src == token.get_src() {
288
288
+
// Same source index, so extend the current token
289
289
+
continue;
290
290
+
} else {
291
291
+
// Different source index, so add the previous token to the merged tokens
292
292
+
merged_tokens.push((token.get_src(), token.get_dst()));
293
293
+
prev_token_src = token.get_src();
294
294
+
};
295
295
+
}
296
296
+
297
297
+
for ((src_line, src_col), (dst_line, dst_col)) in merged_tokens {
298
298
+
// get the index of this mapping in the source and compiled code
299
299
+
let src_index = src_line_numbers.byte_index(Position::new(src_line, src_col)) as usize;
300
300
+
let compiled_index =
301
301
+
compiled_line_numbers.byte_index(Position::new(dst_line, dst_col)) as usize;
302
302
+
303
303
+
// print the source and compiled code for this mapping by getting the substring of the source and compiled code
304
304
+
// from the previous mapping to the current mapping
305
305
+
output.push_str(&format!("{}\n", &src[prev_src_index..src_index]));
306
306
+
output.push_str("⏷\n");
307
307
+
output.push_str(&format!(
308
308
+
"{}\n",
309
309
+
&compiled[prev_compiled_index..compiled_index]
310
310
+
));
311
311
+
output.push_str("----- \n");
312
312
+
prev_src_index = src_index;
313
313
+
prev_compiled_index = compiled_index;
314
314
+
}
315
315
+
// print the last mapping
316
316
+
output.push_str(&format!("{}\n", &src[prev_src_index..]));
317
317
+
output.push_str("⏷\n");
318
318
+
output.push_str(&format!("{}\n", &compiled[prev_compiled_index..]));
319
319
+
output.push_str("----- \n");
320
320
+
output
321
321
+
}
···
1
1
+
---
2
2
+
source: compiler-core/src/javascript/tests/sourcemaps.rs
3
3
+
expression: "\npub fn main() {\n let x = True\n assert x\n}\n"
4
4
+
---
5
5
+
----- SOURCE CODE
6
6
+
0 |
7
7
+
1 |pub fn main() {
8
8
+
2 | let x = True
9
9
+
3 | assert x
10
10
+
4 |}
11
11
+
12
12
+
----- COMPILED JAVASCRIPT
13
13
+
0 |//# sourceMappingURL=mod.mjs.map
14
14
+
1 |import { makeError } from "../gleam.mjs";
15
15
+
2 |
16
16
+
3 |const FILEPATH = "src/module.gleam";
17
17
+
4 |
18
18
+
5 |export function main() {
19
19
+
6 | let x = true;
20
20
+
7 | if (!x) {
21
21
+
8 | throw makeError(
22
22
+
9 | "assert",
23
23
+
10 | FILEPATH,
24
24
+
11 | "my/mod",
25
25
+
12 | 4,
26
26
+
13 | "main",
27
27
+
14 | "Assertion failed.",
28
28
+
15 | {
29
29
+
16 | kind: "expression",
30
30
+
17 | expression: { kind: "expression", value: false, start: 41, end: 42 },
31
31
+
18 | start: 34,
32
32
+
19 | end: 42,
33
33
+
20 | expression_start: 41
34
34
+
21 | }
35
35
+
22 | )
36
36
+
23 | }
37
37
+
24 | return undefined;
38
38
+
25 |}
39
39
+
40
40
+
----- SOURCE MAP
41
41
+
Mappings:
42
42
+
-----
43
43
+
44
44
+
45
45
+
⏷
46
46
+
//# sourceMappingURL=mod.mjs.map
47
47
+
import { makeError } from "../gleam.mjs";
48
48
+
49
49
+
const FILEPATH = "src/module.gleam";
50
50
+
51
51
+
52
52
+
-----
53
53
+
pub fn main() {
54
54
+
55
55
+
⏷
56
56
+
export function main() {
57
57
+
58
58
+
-----
59
59
+
let x =
60
60
+
⏷
61
61
+
let x =
62
62
+
-----
63
63
+
True
64
64
+
65
65
+
⏷
66
66
+
true;
67
67
+
68
68
+
-----
69
69
+
assert
70
70
+
⏷
71
71
+
if (!
72
72
+
-----
73
73
+
x
74
74
+
}
75
75
+
76
76
+
⏷
77
77
+
x) {
78
78
+
throw makeError(
79
79
+
"assert",
80
80
+
FILEPATH,
81
81
+
"my/mod",
82
82
+
4,
83
83
+
"main",
84
84
+
"Assertion failed.",
85
85
+
{
86
86
+
kind: "expression",
87
87
+
expression: { kind: "expression", value: false, start: 41, end: 42 },
88
88
+
start: 34,
89
89
+
end: 42,
90
90
+
expression_start: 41
91
91
+
}
92
92
+
)
93
93
+
}
94
94
+
return undefined;
95
95
+
}
96
96
+
97
97
+
-----
···
1
1
+
---
2
2
+
source: compiler-core/src/javascript/tests/sourcemaps.rs
3
3
+
expression: "\npub type Wibble {\n Wibble(Int, Int)\n}\n\npub fn go(x) {\n case Wibble(1, 2) {\n Wibble(wibble, wobble) -> wibble + wobble\n }\n}\n"
4
4
+
---
5
5
+
----- SOURCE CODE
6
6
+
0 |
7
7
+
1 |pub type Wibble {
8
8
+
2 | Wibble(Int, Int)
9
9
+
3 |}
10
10
+
4 |
11
11
+
5 |pub fn go(x) {
12
12
+
6 | case Wibble(1, 2) {
13
13
+
7 | Wibble(wibble, wobble) -> wibble + wobble
14
14
+
8 | }
15
15
+
9 |}
16
16
+
17
17
+
----- COMPILED JAVASCRIPT
18
18
+
0 |//# sourceMappingURL=mod.mjs.map
19
19
+
1 |import { CustomType as $CustomType } from "../gleam.mjs";
20
20
+
2 |
21
21
+
3 |export class Wibble extends $CustomType {
22
22
+
4 | constructor($0, $1) {
23
23
+
5 | super();
24
24
+
6 | this[0] = $0;
25
25
+
7 | this[1] = $1;
26
26
+
8 | }
27
27
+
9 |}
28
28
+
10 |export const Wibble$Wibble = ($0, $1) => new Wibble($0, $1);
29
29
+
11 |export const Wibble$isWibble = (value) => value instanceof Wibble;
30
30
+
12 |export const Wibble$Wibble$0 = (value) => value[0];
31
31
+
13 |export const Wibble$Wibble$1 = (value) => value[1];
32
32
+
14 |
33
33
+
15 |export function go(x) {
34
34
+
16 | let $ = new Wibble(1, 2);
35
35
+
17 | let wibble = $[0];
36
36
+
18 | let wobble = $[1];
37
37
+
19 | return wibble + wobble;
38
38
+
20 |}
39
39
+
40
40
+
----- SOURCE MAP
41
41
+
Mappings:
42
42
+
-----
43
43
+
44
44
+
pub type Wibble {
45
45
+
46
46
+
⏷
47
47
+
//# sourceMappingURL=mod.mjs.map
48
48
+
import { CustomType as $CustomType } from "../gleam.mjs";
49
49
+
50
50
+
51
51
+
-----
52
52
+
Wibble(Int, Int)
53
53
+
}
54
54
+
55
55
+
56
56
+
⏷
57
57
+
export class Wibble extends $CustomType {
58
58
+
constructor($0, $1) {
59
59
+
super();
60
60
+
this[0] = $0;
61
61
+
this[1] = $1;
62
62
+
}
63
63
+
}
64
64
+
export const Wibble$Wibble = ($0, $1) => new Wibble($0, $1);
65
65
+
export const Wibble$isWibble = (value) => value instanceof Wibble;
66
66
+
export const Wibble$Wibble$0 = (value) => value[0];
67
67
+
export const Wibble$Wibble$1 = (value) => value[1];
68
68
+
69
69
+
70
70
+
-----
71
71
+
pub fn go(x) {
72
72
+
73
73
+
⏷
74
74
+
export function go(x) {
75
75
+
76
76
+
-----
77
77
+
case
78
78
+
⏷
79
79
+
80
80
+
-----
81
81
+
Wibble(
82
82
+
⏷
83
83
+
let $ = new Wibble(
84
84
+
-----
85
85
+
1,
86
86
+
⏷
87
87
+
1,
88
88
+
-----
89
89
+
2) {
90
90
+
91
91
+
⏷
92
92
+
2);
93
93
+
94
94
+
-----
95
95
+
Wibble(wibble, wobble) ->
96
96
+
⏷
97
97
+
let wibble = $[0];
98
98
+
let wobble = $[1];
99
99
+
100
100
+
-----
101
101
+
wibble +
102
102
+
⏷
103
103
+
return wibble +
104
104
+
-----
105
105
+
wobble
106
106
+
}
107
107
+
}
108
108
+
109
109
+
⏷
110
110
+
wobble;
111
111
+
}
112
112
+
113
113
+
-----
···
1
1
+
---
2
2
+
source: compiler-core/src/javascript/tests/sourcemaps.rs
3
3
+
expression: "\n/// my custom type\npub type Wibble {\n /// Wibble\n Wibble\n /// Wobble\n Wobble(field: Int)\n /// Wabble\n Wabble(Wibble)\n}"
4
4
+
---
5
5
+
----- SOURCE CODE
6
6
+
0 |
7
7
+
1 |/// my custom type
8
8
+
2 |pub type Wibble {
9
9
+
3 | /// Wibble
10
10
+
4 | Wibble
11
11
+
5 | /// Wobble
12
12
+
6 | Wobble(field: Int)
13
13
+
7 | /// Wabble
14
14
+
8 | Wabble(Wibble)
15
15
+
9 |}
16
16
+
17
17
+
----- COMPILED JAVASCRIPT
18
18
+
0 |//# sourceMappingURL=mod.mjs.map
19
19
+
1 |import { CustomType as $CustomType } from "../gleam.mjs";
20
20
+
2 |
21
21
+
3 |export class Wibble extends $CustomType {}
22
22
+
4 |export const Wibble$Wibble = () => new Wibble();
23
23
+
5 |export const Wibble$isWibble = (value) => value instanceof Wibble;
24
24
+
6 |
25
25
+
7 |/**
26
26
+
8 | * Wobble
27
27
+
9 | */
28
28
+
10 |export class Wobble extends $CustomType {
29
29
+
11 | constructor(field) {
30
30
+
12 | super();
31
31
+
13 | this.field = field;
32
32
+
14 | }
33
33
+
15 |}
34
34
+
16 |export const Wibble$Wobble = (field) => new Wobble(field);
35
35
+
17 |export const Wibble$isWobble = (value) => value instanceof Wobble;
36
36
+
18 |export const Wibble$Wobble$field = (value) => value.field;
37
37
+
19 |export const Wibble$Wobble$0 = (value) => value.field;
38
38
+
20 |
39
39
+
21 |/**
40
40
+
22 | * Wabble
41
41
+
23 | */
42
42
+
24 |export class Wabble extends $CustomType {
43
43
+
25 | constructor($0) {
44
44
+
26 | super();
45
45
+
27 | this[0] = $0;
46
46
+
28 | }
47
47
+
29 |}
48
48
+
30 |export const Wibble$Wabble = ($0) => new Wabble($0);
49
49
+
31 |export const Wibble$isWabble = (value) => value instanceof Wabble;
50
50
+
32 |export const Wibble$Wabble$0 = (value) => value[0];
51
51
+
52
52
+
----- SOURCE MAP
53
53
+
Mappings:
54
54
+
-----
55
55
+
56
56
+
/// my custom type
57
57
+
pub type Wibble {
58
58
+
/// Wibble
59
59
+
60
60
+
⏷
61
61
+
//# sourceMappingURL=mod.mjs.map
62
62
+
import { CustomType as $CustomType } from "../gleam.mjs";
63
63
+
64
64
+
65
65
+
-----
66
66
+
Wibble
67
67
+
/// Wobble
68
68
+
69
69
+
⏷
70
70
+
export class Wibble extends $CustomType {}
71
71
+
export const Wibble$Wibble = () => new Wibble();
72
72
+
export const Wibble$isWibble = (value) => value instanceof Wibble;
73
73
+
74
74
+
/**
75
75
+
* Wobble
76
76
+
*/
77
77
+
78
78
+
-----
79
79
+
Wobble(field: Int)
80
80
+
/// Wabble
81
81
+
82
82
+
⏷
83
83
+
export class Wobble extends $CustomType {
84
84
+
constructor(field) {
85
85
+
super();
86
86
+
this.field = field;
87
87
+
}
88
88
+
}
89
89
+
export const Wibble$Wobble = (field) => new Wobble(field);
90
90
+
export const Wibble$isWobble = (value) => value instanceof Wobble;
91
91
+
export const Wibble$Wobble$field = (value) => value.field;
92
92
+
export const Wibble$Wobble$0 = (value) => value.field;
93
93
+
94
94
+
/**
95
95
+
* Wabble
96
96
+
*/
97
97
+
98
98
+
-----
99
99
+
Wabble(Wibble)
100
100
+
}
101
101
+
⏷
102
102
+
export class Wabble extends $CustomType {
103
103
+
constructor($0) {
104
104
+
super();
105
105
+
this[0] = $0;
106
106
+
}
107
107
+
}
108
108
+
export const Wibble$Wabble = ($0) => new Wabble($0);
109
109
+
export const Wibble$isWabble = (value) => value instanceof Wabble;
110
110
+
export const Wibble$Wabble$0 = (value) => value[0];
111
111
+
112
112
+
-----
···
1
1
+
---
2
2
+
source: compiler-core/src/javascript/tests/sourcemaps.rs
3
3
+
expression: "\n/// my add function\npub fn add_2(x) {\n x + 2\n}"
4
4
+
---
5
5
+
----- SOURCE CODE
6
6
+
0 |
7
7
+
1 |/// my add function
8
8
+
2 |pub fn add_2(x) {
9
9
+
3 | x + 2
10
10
+
4 |}
11
11
+
12
12
+
----- COMPILED JAVASCRIPT
13
13
+
0 |//# sourceMappingURL=mod.mjs.map
14
14
+
1 |/**
15
15
+
2 | * my add function
16
16
+
3 | */
17
17
+
4 |export function add_2(x) {
18
18
+
5 | return x + 2;
19
19
+
6 |}
20
20
+
21
21
+
----- SOURCE MAP
22
22
+
Mappings:
23
23
+
-----
24
24
+
25
25
+
/// my add function
26
26
+
27
27
+
⏷
28
28
+
//# sourceMappingURL=mod.mjs.map
29
29
+
/**
30
30
+
* my add function
31
31
+
*/
32
32
+
33
33
+
-----
34
34
+
pub fn add_2(x) {
35
35
+
36
36
+
⏷
37
37
+
export function add_2(x) {
38
38
+
39
39
+
-----
40
40
+
x +
41
41
+
⏷
42
42
+
return x +
43
43
+
-----
44
44
+
2
45
45
+
}
46
46
+
⏷
47
47
+
2;
48
48
+
}
49
49
+
50
50
+
-----
···
1
1
+
---
2
2
+
source: compiler-core/src/javascript/tests/sourcemaps.rs
3
3
+
expression: "\n/// my function\npub fn wibble() {\n let wibble = \"hello\nworld\"\n wibble <> \"!\"\n}"
4
4
+
---
5
5
+
----- SOURCE CODE
6
6
+
0 |
7
7
+
1 |/// my function
8
8
+
2 |pub fn wibble() {
9
9
+
3 | let wibble = "hello
10
10
+
4 |world"
11
11
+
5 | wibble <> "!"
12
12
+
6 |}
13
13
+
14
14
+
----- COMPILED JAVASCRIPT
15
15
+
0 |//# sourceMappingURL=mod.mjs.map
16
16
+
1 |/**
17
17
+
2 | * my function
18
18
+
3 | */
19
19
+
4 |export function wibble() {
20
20
+
5 | let wibble$1 = "hello\nworld";
21
21
+
6 | return wibble$1 + "!";
22
22
+
7 |}
23
23
+
24
24
+
----- SOURCE MAP
25
25
+
Mappings:
26
26
+
-----
27
27
+
28
28
+
/// my function
29
29
+
30
30
+
⏷
31
31
+
//# sourceMappingURL=mod.mjs.map
32
32
+
/**
33
33
+
* my function
34
34
+
*/
35
35
+
36
36
+
-----
37
37
+
pub fn wibble() {
38
38
+
39
39
+
⏷
40
40
+
export function wibble() {
41
41
+
42
42
+
-----
43
43
+
let wibble =
44
44
+
⏷
45
45
+
let wibble$1 =
46
46
+
-----
47
47
+
"hello
48
48
+
world"
49
49
+
50
50
+
⏷
51
51
+
"hello\nworld";
52
52
+
53
53
+
-----
54
54
+
wibble <>
55
55
+
⏷
56
56
+
return wibble$1 +
57
57
+
-----
58
58
+
"!"
59
59
+
}
60
60
+
⏷
61
61
+
"!";
62
62
+
}
63
63
+
64
64
+
-----
···
1
1
+
---
2
2
+
source: compiler-core/src/javascript/tests/sourcemaps.rs
3
3
+
expression: "\n/// my function\npub fn wibble() {\n let wibble = \"hello\\nworld\"\n wibble <> \"!\"\n}"
4
4
+
---
5
5
+
----- SOURCE CODE
6
6
+
0 |
7
7
+
1 |/// my function
8
8
+
2 |pub fn wibble() {
9
9
+
3 | let wibble = "hello\nworld"
10
10
+
4 | wibble <> "!"
11
11
+
5 |}
12
12
+
13
13
+
----- COMPILED JAVASCRIPT
14
14
+
0 |//# sourceMappingURL=mod.mjs.map
15
15
+
1 |/**
16
16
+
2 | * my function
17
17
+
3 | */
18
18
+
4 |export function wibble() {
19
19
+
5 | let wibble$1 = "hello\nworld";
20
20
+
6 | return wibble$1 + "!";
21
21
+
7 |}
22
22
+
23
23
+
----- SOURCE MAP
24
24
+
Mappings:
25
25
+
-----
26
26
+
27
27
+
/// my function
28
28
+
29
29
+
⏷
30
30
+
//# sourceMappingURL=mod.mjs.map
31
31
+
/**
32
32
+
* my function
33
33
+
*/
34
34
+
35
35
+
-----
36
36
+
pub fn wibble() {
37
37
+
38
38
+
⏷
39
39
+
export function wibble() {
40
40
+
41
41
+
-----
42
42
+
let wibble =
43
43
+
⏷
44
44
+
let wibble$1 =
45
45
+
-----
46
46
+
"hello\nworld"
47
47
+
48
48
+
⏷
49
49
+
"hello\nworld";
50
50
+
51
51
+
-----
52
52
+
wibble <>
53
53
+
⏷
54
54
+
return wibble$1 +
55
55
+
-----
56
56
+
"!"
57
57
+
}
58
58
+
⏷
59
59
+
"!";
60
60
+
}
61
61
+
62
62
+
-----
···
1
1
+
---
2
2
+
source: compiler-core/src/javascript/tests/sourcemaps.rs
3
3
+
expression: "\n/// my function\npub fn wibble() {\n let wibble = 1\n wibble + 2\n}"
4
4
+
---
5
5
+
----- SOURCE CODE
6
6
+
0 |
7
7
+
1 |/// my function
8
8
+
2 |pub fn wibble() {
9
9
+
3 | let wibble = 1
10
10
+
4 | wibble + 2
11
11
+
5 |}
12
12
+
13
13
+
----- COMPILED JAVASCRIPT
14
14
+
0 |//# sourceMappingURL=mod.mjs.map
15
15
+
1 |/**
16
16
+
2 | * my function
17
17
+
3 | */
18
18
+
4 |export function wibble() {
19
19
+
5 | let wibble$1 = 1;
20
20
+
6 | return wibble$1 + 2;
21
21
+
7 |}
22
22
+
23
23
+
----- SOURCE MAP
24
24
+
Mappings:
25
25
+
-----
26
26
+
27
27
+
/// my function
28
28
+
29
29
+
⏷
30
30
+
//# sourceMappingURL=mod.mjs.map
31
31
+
/**
32
32
+
* my function
33
33
+
*/
34
34
+
35
35
+
-----
36
36
+
pub fn wibble() {
37
37
+
38
38
+
⏷
39
39
+
export function wibble() {
40
40
+
41
41
+
-----
42
42
+
let wibble =
43
43
+
⏷
44
44
+
let wibble$1 =
45
45
+
-----
46
46
+
1
47
47
+
48
48
+
⏷
49
49
+
1;
50
50
+
51
51
+
-----
52
52
+
wibble +
53
53
+
⏷
54
54
+
return wibble$1 +
55
55
+
-----
56
56
+
2
57
57
+
}
58
58
+
⏷
59
59
+
2;
60
60
+
}
61
61
+
62
62
+
-----
···
1
1
+
---
2
2
+
source: compiler-core/src/javascript/tests/sourcemaps.rs
3
3
+
expression: "\npub fn go(x) {\n let assert #(wibble, wobble) = x\n}\n"
4
4
+
---
5
5
+
----- SOURCE CODE
6
6
+
0 |
7
7
+
1 |pub fn go(x) {
8
8
+
2 | let assert #(wibble, wobble) = x
9
9
+
3 |}
10
10
+
11
11
+
----- COMPILED JAVASCRIPT
12
12
+
0 |//# sourceMappingURL=mod.mjs.map
13
13
+
1 |export function go(x) {
14
14
+
2 | let wibble;
15
15
+
3 | let wobble;
16
16
+
4 | wibble = x[0];
17
17
+
5 | wobble = x[1];
18
18
+
6 | return x;
19
19
+
7 |}
20
20
+
21
21
+
----- SOURCE MAP
22
22
+
Mappings:
23
23
+
-----
24
24
+
25
25
+
26
26
+
⏷
27
27
+
//# sourceMappingURL=mod.mjs.map
28
28
+
29
29
+
-----
30
30
+
pub fn go(x) {
31
31
+
32
32
+
⏷
33
33
+
export function go(x) {
34
34
+
35
35
+
-----
36
36
+
let assert #(wibble, wobble) =
37
37
+
⏷
38
38
+
let wibble;
39
39
+
let wobble;
40
40
+
41
41
+
-----
42
42
+
x
43
43
+
}
44
44
+
45
45
+
⏷
46
46
+
wibble = x[0];
47
47
+
wobble = x[1];
48
48
+
return x;
49
49
+
}
50
50
+
51
51
+
-----
···
1
1
+
---
2
2
+
source: compiler-core/src/javascript/tests/sourcemaps.rs
3
3
+
expression: "\n/// my constant\npub const wibble = 1\n/// wobble\nconst wobble = 2\n/// wabble\npub const wabble = 3"
4
4
+
---
5
5
+
----- SOURCE CODE
6
6
+
0 |
7
7
+
1 |/// my constant
8
8
+
2 |pub const wibble = 1
9
9
+
3 |/// wobble
10
10
+
4 |const wobble = 2
11
11
+
5 |/// wabble
12
12
+
6 |pub const wabble = 3
13
13
+
14
14
+
----- COMPILED JAVASCRIPT
15
15
+
0 |//# sourceMappingURL=mod.mjs.map
16
16
+
1 |/**
17
17
+
2 | * my constant
18
18
+
3 | */
19
19
+
4 |export const wibble = 1;
20
20
+
5 |
21
21
+
6 |/**
22
22
+
7 | * wabble
23
23
+
8 | */
24
24
+
9 |export const wabble = 3;
25
25
+
26
26
+
----- SOURCE MAP
27
27
+
Mappings:
28
28
+
-----
29
29
+
30
30
+
/// my constant
31
31
+
32
32
+
⏷
33
33
+
//# sourceMappingURL=mod.mjs.map
34
34
+
/**
35
35
+
* my constant
36
36
+
*/
37
37
+
38
38
+
-----
39
39
+
pub const wibble = 1
40
40
+
/// wobble
41
41
+
const wobble = 2
42
42
+
/// wabble
43
43
+
44
44
+
⏷
45
45
+
export const wibble = 1;
46
46
+
47
47
+
/**
48
48
+
* wabble
49
49
+
*/
50
50
+
51
51
+
-----
52
52
+
pub const wabble = 3
53
53
+
⏷
54
54
+
export const wabble = 3;
55
55
+
56
56
+
-----
···
1
1
+
---
2
2
+
source: compiler-core/src/javascript/tests/sourcemaps.rs
3
3
+
expression: "\nfn add_2(x) {\n x + 2\n}\n\npub fn go(x) {\n x |> add_2\n}\n"
4
4
+
---
5
5
+
----- SOURCE CODE
6
6
+
0 |
7
7
+
1 |fn add_2(x) {
8
8
+
2 | x + 2
9
9
+
3 |}
10
10
+
4 |
11
11
+
5 |pub fn go(x) {
12
12
+
6 | x |> add_2
13
13
+
7 |}
14
14
+
15
15
+
----- COMPILED JAVASCRIPT
16
16
+
0 |//# sourceMappingURL=mod.mjs.map
17
17
+
1 |function add_2(x) {
18
18
+
2 | return x + 2;
19
19
+
3 |}
20
20
+
4 |
21
21
+
5 |export function go(x) {
22
22
+
6 | let _pipe = x;
23
23
+
7 | return add_2(_pipe);
24
24
+
8 |}
25
25
+
26
26
+
----- SOURCE MAP
27
27
+
Mappings:
28
28
+
-----
29
29
+
30
30
+
31
31
+
⏷
32
32
+
//# sourceMappingURL=mod.mjs.map
33
33
+
34
34
+
-----
35
35
+
fn add_2(x) {
36
36
+
37
37
+
⏷
38
38
+
function add_2(x) {
39
39
+
40
40
+
-----
41
41
+
x +
42
42
+
⏷
43
43
+
return x +
44
44
+
-----
45
45
+
2
46
46
+
}
47
47
+
48
48
+
49
49
+
⏷
50
50
+
2;
51
51
+
}
52
52
+
53
53
+
54
54
+
-----
55
55
+
pub fn go(x) {
56
56
+
57
57
+
⏷
58
58
+
export function go(x) {
59
59
+
60
60
+
-----
61
61
+
x |>
62
62
+
⏷
63
63
+
let _pipe = x;
64
64
+
65
65
+
-----
66
66
+
add_2
67
67
+
}
68
68
+
69
69
+
⏷
70
70
+
return add_2(_pipe);
71
71
+
}
72
72
+
73
73
+
-----
···
1
1
+
---
2
2
+
source: compiler-core/src/javascript/tests/sourcemaps.rs
3
3
+
expression: "\nfn add_3_to_result(i, f) {\n f(i) + 3\n}\n\npub fn go(x) {\n use a <- add_3_to_result(1)\n a + 2\n}\n"
4
4
+
---
5
5
+
----- SOURCE CODE
6
6
+
0 |
7
7
+
1 |fn add_3_to_result(i, f) {
8
8
+
2 | f(i) + 3
9
9
+
3 |}
10
10
+
4 |
11
11
+
5 |pub fn go(x) {
12
12
+
6 | use a <- add_3_to_result(1)
13
13
+
7 | a + 2
14
14
+
8 |}
15
15
+
16
16
+
----- COMPILED JAVASCRIPT
17
17
+
0 |//# sourceMappingURL=mod.mjs.map
18
18
+
1 |function add_3_to_result(i, f) {
19
19
+
2 | return f(i) + 3;
20
20
+
3 |}
21
21
+
4 |
22
22
+
5 |export function go(x) {
23
23
+
6 | return add_3_to_result(1, (a) => { return a + 2; });
24
24
+
7 |}
25
25
+
26
26
+
----- SOURCE MAP
27
27
+
Mappings:
28
28
+
-----
29
29
+
30
30
+
31
31
+
⏷
32
32
+
//# sourceMappingURL=mod.mjs.map
33
33
+
34
34
+
-----
35
35
+
fn add_3_to_result(i, f) {
36
36
+
37
37
+
⏷
38
38
+
function add_3_to_result(i, f) {
39
39
+
40
40
+
-----
41
41
+
f(
42
42
+
⏷
43
43
+
return f(
44
44
+
-----
45
45
+
i) +
46
46
+
⏷
47
47
+
i) +
48
48
+
-----
49
49
+
3
50
50
+
}
51
51
+
52
52
+
53
53
+
⏷
54
54
+
3;
55
55
+
}
56
56
+
57
57
+
58
58
+
-----
59
59
+
pub fn go(x) {
60
60
+
61
61
+
⏷
62
62
+
export function go(x) {
63
63
+
64
64
+
-----
65
65
+
use a <-
66
66
+
⏷
67
67
+
return
68
68
+
-----
69
69
+
add_3_to_result(
70
70
+
⏷
71
71
+
add_3_to_result(
72
72
+
-----
73
73
+
1)
74
74
+
75
75
+
⏷
76
76
+
1,
77
77
+
-----
78
78
+
a +
79
79
+
⏷
80
80
+
(a) => { return a +
81
81
+
-----
82
82
+
2
83
83
+
}
84
84
+
85
85
+
⏷
86
86
+
2; });
87
87
+
}
88
88
+
89
89
+
-----
···
1
1
+
---
2
2
+
source: compiler-core/src/javascript/tests/sourcemaps.rs
3
3
+
expression: "\npub fn go(x) {\n <<256:int>>\n}\n"
4
4
+
---
5
5
+
----- SOURCE CODE
6
6
+
0 |
7
7
+
1 |pub fn go(x) {
8
8
+
2 | <<256:int>>
9
9
+
3 |}
10
10
+
11
11
+
----- COMPILED JAVASCRIPT
12
12
+
0 |//# sourceMappingURL=mod.mjs.map
13
13
+
1 |import { toBitArray } from "../gleam.mjs";
14
14
+
2 |
15
15
+
3 |export function go(x) {
16
16
+
4 | return toBitArray([0]);
17
17
+
5 |}
18
18
+
19
19
+
----- SOURCE MAP
20
20
+
Mappings:
21
21
+
-----
22
22
+
23
23
+
24
24
+
⏷
25
25
+
//# sourceMappingURL=mod.mjs.map
26
26
+
import { toBitArray } from "../gleam.mjs";
27
27
+
28
28
+
29
29
+
-----
30
30
+
pub fn go(x) {
31
31
+
32
32
+
⏷
33
33
+
export function go(x) {
34
34
+
35
35
+
-----
36
36
+
<<256:int>>
37
37
+
}
38
38
+
39
39
+
⏷
40
40
+
return toBitArray([0]);
41
41
+
}
42
42
+
43
43
+
-----
···
1
1
+
---
2
2
+
source: compiler-core/src/javascript/tests/sourcemaps.rs
3
3
+
expression: "\npub fn go(one, other) {\n case one, other {\n Ok(1), Error(_) -> 1\n Ok(_), _ -> 2\n Error(_), Ok(2) -> 3\n _, _ -> 4\n }\n}\n"
4
4
+
---
5
5
+
----- SOURCE CODE
6
6
+
0 |
7
7
+
1 |pub fn go(one, other) {
8
8
+
2 | case one, other {
9
9
+
3 | Ok(1), Error(_) -> 1
10
10
+
4 | Ok(_), _ -> 2
11
11
+
5 | Error(_), Ok(2) -> 3
12
12
+
6 | _, _ -> 4
13
13
+
7 | }
14
14
+
8 |}
15
15
+
16
16
+
----- COMPILED JAVASCRIPT
17
17
+
0 |//# sourceMappingURL=mod.mjs.map
18
18
+
1 |import { Ok, Error } from "../gleam.mjs";
19
19
+
2 |
20
20
+
3 |export function go(one, other) {
21
21
+
4 | if (one instanceof Ok) {
22
22
+
5 | if (other instanceof Error) {
23
23
+
6 | let $ = one[0];
24
24
+
7 | if ($ === 1) {
25
25
+
8 | return 1;
26
26
+
9 | } else {
27
27
+
10 | return 2;
28
28
+
11 | }
29
29
+
12 | } else {
30
30
+
13 | return 2;
31
31
+
14 | }
32
32
+
15 | } else if (other instanceof Ok) {
33
33
+
16 | let $ = other[0];
34
34
+
17 | if ($ === 2) {
35
35
+
18 | return 3;
36
36
+
19 | } else {
37
37
+
20 | return 4;
38
38
+
21 | }
39
39
+
22 | } else {
40
40
+
23 | return 4;
41
41
+
24 | }
42
42
+
25 |}
43
43
+
44
44
+
----- SOURCE MAP
45
45
+
Mappings:
46
46
+
-----
47
47
+
48
48
+
49
49
+
⏷
50
50
+
//# sourceMappingURL=mod.mjs.map
51
51
+
import { Ok, Error } from "../gleam.mjs";
52
52
+
53
53
+
54
54
+
-----
55
55
+
pub fn go(one, other) {
56
56
+
57
57
+
⏷
58
58
+
export function go(one, other) {
59
59
+
60
60
+
-----
61
61
+
case
62
62
+
⏷
63
63
+
64
64
+
-----
65
65
+
one, other {
66
66
+
Ok(1), Error(_) ->
67
67
+
⏷
68
68
+
if (one instanceof Ok) {
69
69
+
if (other instanceof Error) {
70
70
+
let $ = one[0];
71
71
+
if ($ === 1) {
72
72
+
73
73
+
-----
74
74
+
1
75
75
+
Ok(_), _ ->
76
76
+
⏷
77
77
+
return 1;
78
78
+
} else {
79
79
+
80
80
+
-----
81
81
+
2
82
82
+
Error(_), Ok(2) ->
83
83
+
⏷
84
84
+
return 2;
85
85
+
}
86
86
+
} else {
87
87
+
return 2;
88
88
+
}
89
89
+
} else if (other instanceof Ok) {
90
90
+
let $ = other[0];
91
91
+
if ($ === 2) {
92
92
+
93
93
+
-----
94
94
+
3
95
95
+
_, _ ->
96
96
+
⏷
97
97
+
return 3;
98
98
+
} else {
99
99
+
100
100
+
-----
101
101
+
4
102
102
+
}
103
103
+
}
104
104
+
105
105
+
⏷
106
106
+
return 4;
107
107
+
}
108
108
+
} else {
109
109
+
return 4;
110
110
+
}
111
111
+
}
112
112
+
113
113
+
-----
···
1
1
+
---
2
2
+
source: compiler-core/src/javascript/tests/sourcemaps.rs
3
3
+
expression: "\npub fn go(x) {\n [1, 2, 3]\n}\n"
4
4
+
---
5
5
+
----- SOURCE CODE
6
6
+
0 |
7
7
+
1 |pub fn go(x) {
8
8
+
2 | [1, 2, 3]
9
9
+
3 |}
10
10
+
11
11
+
----- COMPILED JAVASCRIPT
12
12
+
0 |//# sourceMappingURL=mod.mjs.map
13
13
+
1 |import { toList } from "../gleam.mjs";
14
14
+
2 |
15
15
+
3 |export function go(x) {
16
16
+
4 | return toList([1, 2, 3]);
17
17
+
5 |}
18
18
+
19
19
+
----- SOURCE MAP
20
20
+
Mappings:
21
21
+
-----
22
22
+
23
23
+
24
24
+
⏷
25
25
+
//# sourceMappingURL=mod.mjs.map
26
26
+
import { toList } from "../gleam.mjs";
27
27
+
28
28
+
29
29
+
-----
30
30
+
pub fn go(x) {
31
31
+
32
32
+
⏷
33
33
+
export function go(x) {
34
34
+
35
35
+
-----
36
36
+
[
37
37
+
⏷
38
38
+
return toList([
39
39
+
-----
40
40
+
1,
41
41
+
⏷
42
42
+
1,
43
43
+
-----
44
44
+
2,
45
45
+
⏷
46
46
+
2,
47
47
+
-----
48
48
+
3]
49
49
+
}
50
50
+
51
51
+
⏷
52
52
+
3]);
53
53
+
}
54
54
+
55
55
+
-----
···
1
1
+
---
2
2
+
source: compiler-core/src/javascript/tests/sourcemaps.rs
3
3
+
expression: "\npub fn wibble(lon, acc) {\n case lon {\n [] -> 0\n [n, ..rest] -> wibble(rest, acc + n)\n }\n}\n"
4
4
+
---
5
5
+
----- SOURCE CODE
6
6
+
0 |
7
7
+
1 |pub fn wibble(lon, acc) {
8
8
+
2 | case lon {
9
9
+
3 | [] -> 0
10
10
+
4 | [n, ..rest] -> wibble(rest, acc + n)
11
11
+
5 | }
12
12
+
6 |}
13
13
+
14
14
+
----- COMPILED JAVASCRIPT
15
15
+
0 |//# sourceMappingURL=mod.mjs.map
16
16
+
1 |import { Empty as $Empty } from "../gleam.mjs";
17
17
+
2 |
18
18
+
3 |export function wibble(loop$lon, loop$acc) {
19
19
+
4 | while (true) {
20
20
+
5 | let lon = loop$lon;
21
21
+
6 | let acc = loop$acc;
22
22
+
7 | if (lon instanceof $Empty) {
23
23
+
8 | return 0;
24
24
+
9 | } else {
25
25
+
10 | let n = lon.head;
26
26
+
11 | let rest = lon.tail;
27
27
+
12 | loop$lon = rest;
28
28
+
13 | loop$acc = acc + n;
29
29
+
14 | }
30
30
+
15 | }
31
31
+
16 |}
32
32
+
33
33
+
----- SOURCE MAP
34
34
+
Mappings:
35
35
+
-----
36
36
+
37
37
+
38
38
+
⏷
39
39
+
//# sourceMappingURL=mod.mjs.map
40
40
+
import { Empty as $Empty } from "../gleam.mjs";
41
41
+
42
42
+
43
43
+
-----
44
44
+
pub fn wibble(
45
45
+
⏷
46
46
+
export function wibble(loop$lon, loop$acc) {
47
47
+
while (true) {
48
48
+
49
49
+
-----
50
50
+
lon,
51
51
+
⏷
52
52
+
let lon = loop$lon;
53
53
+
54
54
+
-----
55
55
+
acc) {
56
56
+
57
57
+
⏷
58
58
+
let acc = loop$acc;
59
59
+
60
60
+
-----
61
61
+
case
62
62
+
⏷
63
63
+
64
64
+
-----
65
65
+
lon {
66
66
+
[] ->
67
67
+
⏷
68
68
+
if (lon instanceof $Empty) {
69
69
+
70
70
+
-----
71
71
+
0
72
72
+
73
73
+
⏷
74
74
+
return 0;
75
75
+
} else {
76
76
+
77
77
+
-----
78
78
+
[n, ..rest] ->
79
79
+
⏷
80
80
+
let n = lon.head;
81
81
+
let rest = lon.tail;
82
82
+
83
83
+
-----
84
84
+
wibble(
85
85
+
⏷
86
86
+
loop$lon =
87
87
+
-----
88
88
+
rest,
89
89
+
⏷
90
90
+
rest;
91
91
+
loop$acc =
92
92
+
-----
93
93
+
acc +
94
94
+
⏷
95
95
+
acc +
96
96
+
-----
97
97
+
n)
98
98
+
}
99
99
+
}
100
100
+
101
101
+
⏷
102
102
+
n;
103
103
+
}
104
104
+
}
105
105
+
}
106
106
+
107
107
+
-----
···
1
1
+
---
2
2
+
source: compiler-core/src/javascript/tests/sourcemaps.rs
3
3
+
expression: "\npub fn go(x) {\n #(1, 2, 3)\n}\n"
4
4
+
---
5
5
+
----- SOURCE CODE
6
6
+
0 |
7
7
+
1 |pub fn go(x) {
8
8
+
2 | #(1, 2, 3)
9
9
+
3 |}
10
10
+
11
11
+
----- COMPILED JAVASCRIPT
12
12
+
0 |//# sourceMappingURL=mod.mjs.map
13
13
+
1 |export function go(x) {
14
14
+
2 | return [1, 2, 3];
15
15
+
3 |}
16
16
+
17
17
+
----- SOURCE MAP
18
18
+
Mappings:
19
19
+
-----
20
20
+
21
21
+
22
22
+
⏷
23
23
+
//# sourceMappingURL=mod.mjs.map
24
24
+
25
25
+
-----
26
26
+
pub fn go(x) {
27
27
+
28
28
+
⏷
29
29
+
export function go(x) {
30
30
+
31
31
+
-----
32
32
+
#(
33
33
+
⏷
34
34
+
return [
35
35
+
-----
36
36
+
1,
37
37
+
⏷
38
38
+
1,
39
39
+
-----
40
40
+
2,
41
41
+
⏷
42
42
+
2,
43
43
+
-----
44
44
+
3)
45
45
+
}
46
46
+
47
47
+
⏷
48
48
+
3];
49
49
+
}
50
50
+
51
51
+
-----
···
1
1
+
use crate::assert_source_map;
2
2
+
3
3
+
#[test]
4
4
+
fn sourcemap_function_definition() {
5
5
+
assert_source_map!(
6
6
+
"
7
7
+
/// my add function
8
8
+
pub fn add_2(x) {
9
9
+
x + 2
10
10
+
}"
11
11
+
)
12
12
+
}
13
13
+
14
14
+
#[test]
15
15
+
fn sourcemap_function_definition_with_variable_assignment() {
16
16
+
assert_source_map!(
17
17
+
"
18
18
+
/// my function
19
19
+
pub fn wibble() {
20
20
+
let wibble = 1
21
21
+
wibble + 2
22
22
+
}"
23
23
+
)
24
24
+
}
25
25
+
26
26
+
#[test]
27
27
+
fn sourcemap_function_definition_with_string_with_newline_escaped() {
28
28
+
assert_source_map!(
29
29
+
"
30
30
+
/// my function
31
31
+
pub fn wibble() {
32
32
+
let wibble = \"hello\\nworld\"
33
33
+
wibble <> \"!\"
34
34
+
}"
35
35
+
)
36
36
+
}
37
37
+
38
38
+
#[test]
39
39
+
fn sourcemap_function_definition_with_string_with_newline() {
40
40
+
assert_source_map!(
41
41
+
"
42
42
+
/// my function
43
43
+
pub fn wibble() {
44
44
+
let wibble = \"hello
45
45
+
world\"
46
46
+
wibble <> \"!\"
47
47
+
}"
48
48
+
)
49
49
+
}
50
50
+
51
51
+
#[test]
52
52
+
fn sourcemap_custom_type_definition() {
53
53
+
assert_source_map!(
54
54
+
"
55
55
+
/// my custom type
56
56
+
pub type Wibble {
57
57
+
/// Wibble
58
58
+
Wibble
59
59
+
/// Wobble
60
60
+
Wobble(field: Int)
61
61
+
/// Wabble
62
62
+
Wabble(Wibble)
63
63
+
}"
64
64
+
)
65
65
+
}
66
66
+
67
67
+
#[test]
68
68
+
fn sourcemap_module_constant() {
69
69
+
assert_source_map!(
70
70
+
"
71
71
+
/// my constant
72
72
+
pub const wibble = 1
73
73
+
/// wobble
74
74
+
const wobble = 2
75
75
+
/// wabble
76
76
+
pub const wabble = 3"
77
77
+
)
78
78
+
}
79
79
+
80
80
+
#[test]
81
81
+
fn sourcemap_assert() {
82
82
+
assert_source_map!(
83
83
+
"
84
84
+
pub fn main() {
85
85
+
let x = True
86
86
+
assert x
87
87
+
}
88
88
+
"
89
89
+
)
90
90
+
}
91
91
+
92
92
+
#[test]
93
93
+
fn sourcemap_let_assert() {
94
94
+
assert_source_map!(
95
95
+
r#"
96
96
+
pub fn go(x) {
97
97
+
let assert #(wibble, wobble) = x
98
98
+
}
99
99
+
"#
100
100
+
)
101
101
+
}
102
102
+
103
103
+
#[test]
104
104
+
fn sourcemap_case_destructure_assignment_statement() {
105
105
+
assert_source_map!(
106
106
+
"
107
107
+
pub type Wibble {
108
108
+
Wibble(Int, Int)
109
109
+
}
110
110
+
111
111
+
pub fn go(x) {
112
112
+
case Wibble(1, 2) {
113
113
+
Wibble(wibble, wobble) -> wibble + wobble
114
114
+
}
115
115
+
}
116
116
+
"
117
117
+
)
118
118
+
}
119
119
+
120
120
+
#[test]
121
121
+
fn sourcemap_with_complex_case_expression() {
122
122
+
assert_source_map!(
123
123
+
"
124
124
+
pub fn go(one, other) {
125
125
+
case one, other {
126
126
+
Ok(1), Error(_) -> 1
127
127
+
Ok(_), _ -> 2
128
128
+
Error(_), Ok(2) -> 3
129
129
+
_, _ -> 4
130
130
+
}
131
131
+
}
132
132
+
"
133
133
+
)
134
134
+
}
135
135
+
136
136
+
#[test]
137
137
+
fn sourcemap_pipe() {
138
138
+
assert_source_map!(
139
139
+
"
140
140
+
fn add_2(x) {
141
141
+
x + 2
142
142
+
}
143
143
+
144
144
+
pub fn go(x) {
145
145
+
x |> add_2
146
146
+
}
147
147
+
"
148
148
+
)
149
149
+
}
150
150
+
151
151
+
#[test]
152
152
+
fn sourcemap_use() {
153
153
+
assert_source_map!(
154
154
+
"
155
155
+
fn add_3_to_result(i, f) {
156
156
+
f(i) + 3
157
157
+
}
158
158
+
159
159
+
pub fn go(x) {
160
160
+
use a <- add_3_to_result(1)
161
161
+
a + 2
162
162
+
}
163
163
+
"
164
164
+
)
165
165
+
}
166
166
+
167
167
+
#[test]
168
168
+
fn sourcemap_with_list() {
169
169
+
assert_source_map!(
170
170
+
"
171
171
+
pub fn go(x) {
172
172
+
[1, 2, 3]
173
173
+
}
174
174
+
"
175
175
+
)
176
176
+
}
177
177
+
178
178
+
#[test]
179
179
+
fn sourcemap_with_tuple() {
180
180
+
assert_source_map!(
181
181
+
"
182
182
+
pub fn go(x) {
183
183
+
#(1, 2, 3)
184
184
+
}
185
185
+
"
186
186
+
)
187
187
+
}
188
188
+
189
189
+
#[test]
190
190
+
fn sourcemap_with_bitarray() {
191
191
+
assert_source_map!(
192
192
+
"
193
193
+
pub fn go(x) {
194
194
+
<<256:int>>
195
195
+
}
196
196
+
"
197
197
+
)
198
198
+
}
199
199
+
200
200
+
#[test]
201
201
+
fn sourcemap_with_tail_recursive_functions() {
202
202
+
assert_source_map!(
203
203
+
"
204
204
+
pub fn wibble(lon, acc) {
205
205
+
case lon {
206
206
+
[] -> 0
207
207
+
[n, ..rest] -> wibble(rest, acc + n)
208
208
+
}
209
209
+
}
210
210
+
"
211
211
+
)
212
212
+
}
···
30
30
#[cfg(test)]
31
31
mod tests;
32
32
33
33
+
use std::{cell::RefCell, rc::Rc};
34
34
+
33
35
use ecow::{EcoString, eco_format};
34
36
use itertools::Itertools;
35
37
use num_bigint::BigInt;
···
197
199
concat(Itertools::intersperse(docs.into_iter(), separator))
198
200
}
199
201
202
202
+
/// A trait that allows for objects to observe the cursor position as it is being formatted.
203
203
+
/// This is useful for any operations that need to track the exact position a document is
204
204
+
/// being written to in a buffer such as for source mapping.
205
205
+
pub trait CursorPositionObserver: std::fmt::Debug {
206
206
+
fn observe_cursor_position(&mut self, line: isize, width: isize);
207
207
+
}
208
208
+
200
209
/// A pretty printable document. A tree structure, made up of text and other
201
210
/// elements which determine how it can be formatted.
202
211
///
···
204
213
/// rather use the helper functions of the same names to construct them.
205
214
/// For example, use `line()` instead of `Document::Line(1)`.
206
215
///
207
207
-
#[derive(Debug, Clone, PartialEq, Eq)]
216
216
+
#[derive(Debug, Clone)]
208
217
pub enum Document<'a> {
209
218
/// A mandatory linebreak. This is always printed as a string of newlines,
210
219
/// equal in length to the number specified.
···
280
289
/// This is useful for additional formatting text which won't be rendered
281
290
/// in the final output, such as ANSI codes or HTML elements.
282
291
ZeroWidthString { string: EcoString },
292
292
+
293
293
+
/// A node that gets notified of the cursor position as it is being formatted.
294
294
+
/// This allows for processes outside of the final output to be notified of
295
295
+
/// the cursor position and perform actions based on it, such as recording
296
296
+
/// the span of the node in the generated source code for a source mapping.
297
297
+
CursorPositionObserver {
298
298
+
observer: Rc<RefCell<dyn CursorPositionObserver>>,
299
299
+
},
283
300
}
284
301
285
302
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
···
426
443
}
427
444
428
445
// Zero width strings do nothing: they do not contribute to line length
429
429
-
Document::ZeroWidthString { .. } => {}
446
446
+
Document::ZeroWidthString { .. } | Document::CursorPositionObserver { .. } => {}
430
447
431
448
// If we get to a break we need to first see if it has to be
432
449
// rendered as its unbroken or broken string, depending on the mode.
···
495
512
fn format(
496
513
writer: &mut impl Utf8Writer,
497
514
limit: isize,
498
498
-
mut width: isize,
499
515
mut docs: im::Vector<(isize, Mode, &Document<'_>)>,
500
516
) -> Result<()> {
517
517
+
let mut line: isize = 0;
518
518
+
let mut width: isize = 0;
501
519
// As long as there are documents to print we'll take each one by one and
502
520
// output the corresponding string to the given writer.
503
521
//
···
518
536
for _ in 0..*i {
519
537
writer.str_write("\n")?;
520
538
}
539
539
+
// i will always be positive, so we can safely cast it to isize
540
540
+
line += *i as isize;
521
541
for _ in 0..indent {
522
542
writer.str_write(" ")?;
523
543
}
···
544
564
} else {
545
565
writer.str_write(broken)?;
546
566
writer.str_write("\n")?;
567
567
+
line += 1;
547
568
for _ in 0..indent {
548
569
writer.str_write(" ")?;
549
570
}
···
569
590
Mode::Broken | Mode::ForcedBroken => {
570
591
writer.str_write(broken)?;
571
592
writer.str_write("\n")?;
593
593
+
line += 1;
572
594
for _ in 0..indent {
573
595
writer.str_write(" ")?;
574
596
}
···
658
680
Document::ForceBroken(document) | Document::NextBreakFits(document, _) => {
659
681
docs.push_front((indent, mode, document));
660
682
}
683
683
+
684
684
+
Document::CursorPositionObserver { observer } => {
685
685
+
// Notify the observer of the current cursor position
686
686
+
observer.borrow_mut().observe_cursor_position(line, width);
687
687
+
}
661
688
}
662
689
}
663
690
Ok(())
···
842
869
| Self::Group(..)
843
870
| Self::Str { .. }
844
871
| Self::EcoString { .. }
845
845
-
| Self::ZeroWidthString { .. } => Self::Vec(vec![self, second.to_doc()]),
872
872
+
| Self::ZeroWidthString { .. }
873
873
+
| Self::CursorPositionObserver { .. } => Self::Vec(vec![self, second.to_doc()]),
846
874
}
847
875
}
848
876
···
865
893
/// characters in length.
866
894
pub fn pretty_print(&self, limit: isize, writer: &mut impl Utf8Writer) -> Result<()> {
867
895
let docs = im::vector![(0, Mode::Unbroken, self)];
868
868
-
format(writer, limit, 0, docs)?;
896
896
+
format(writer, limit, docs)?;
869
897
Ok(())
870
898
}
871
899
···
885
913
// still printed and so are not empty. (Unless their string contents
886
914
// is also empty)
887
915
ZeroWidthString { string } => string.is_empty(),
916
916
+
CursorPositionObserver { .. } => true,
888
917
}
889
918
}
890
919
}
···
2
2
source: compiler-core/src/config.rs
3
3
assertion_line: 1193
4
4
expression: output
5
5
-
snapshot_kind: text
6
5
---
7
6
--- GLEAM.TOML
8
7
···
32
31
},
33
32
"javascript": {
34
33
"typescript_declarations": false,
34
34
+
"source_maps": false,
35
35
"runtime": "nodejs",
36
36
"deno": {
37
37
"allow_env": [],
···
2
2
source: compiler-core/src/config.rs
3
3
assertion_line: 1177
4
4
expression: output
5
5
-
snapshot_kind: text
6
5
---
7
6
--- GLEAM.TOML
8
7
···
32
31
33
32
[javascript]
34
33
typescript_declarations = true
34
34
+
source_maps = true
35
35
runtime = "node"
36
36
37
37
[javascript.deno]
···
98
98
},
99
99
"javascript": {
100
100
"typescript_declarations": true,
101
101
+
"source_maps": true,
101
102
"runtime": "nodejs",
102
103
"deno": {
103
104
"allow_env": [
···
2
2
source: compiler-core/src/docs.rs
3
3
assertion_line: 786
4
4
expression: output
5
5
-
snapshot_kind: text
6
5
---
7
6
--- GLEAM.TOML
8
7
···
33
32
},
34
33
"javascript": {
35
34
"typescript_declarations": false,
35
35
+
"source_maps": false,
36
36
"runtime": "nodejs",
37
37
"deno": {
38
38
"allow_env": [],
···
2
2
source: compiler-core/src/docs.rs
3
3
assertion_line: 770
4
4
expression: output
5
5
-
snapshot_kind: text
6
5
---
7
6
--- GLEAM.TOML
8
7
···
32
31
33
32
[javascript]
34
33
typescript_declarations = true
34
34
+
source_maps = true
35
35
runtime = "node"
36
36
37
37
[javascript.deno]
···
99
99
},
100
100
"javascript": {
101
101
"typescript_declarations": true,
102
102
+
"source_maps": true,
102
103
"runtime": "nodejs",
103
104
"deno": {
104
105
"allow_env": [
···
181
181
Target::Erlang => TargetCodegenConfiguration::Erlang { app_file: None },
182
182
Target::JavaScript => TargetCodegenConfiguration::JavaScript {
183
183
emit_typescript_definitions: false,
184
184
+
emit_source_maps: false,
184
185
prelude_location: Utf8PathBuf::from("./gleam_prelude.mjs"),
185
186
},
186
187
};
···
31
31
},
32
32
Target::JavaScript => TargetCodegenConfiguration::JavaScript {
33
33
emit_typescript_definitions: config.javascript.typescript_declarations,
34
34
+
emit_source_maps: config.javascript.source_maps,
34
35
prelude_location: Utf8PathBuf::from("../prelude.mjs"),
35
36
},
36
37
};
···
4
4
5
5
[javascript]
6
6
typescript_declarations = true
7
7
+
source_maps = true
7
8
runtime = "node"
8
9
9
10
[dependencies]