Skip to content

Commit d060ee2

Browse files
nkxxlllpil
authored andcommitted
feat(compiler-core): add mts, jsx, tsx, cts to native extensions
1 parent 248864f commit d060ee2

3 files changed

Lines changed: 271 additions & 8 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
in the body of a `use` expression
1313
([Giovanni Maria Zanchetta](https://github.com/GioMaz))
1414

15+
- Added `mts`, `cts`, `jsx`, `tsx` to native file extensions so you can use
16+
external JavaScript code from files with these file extensions.
17+
([Niklas Kirschall](https://github.com/nkxxll))
1518

1619
## v1.16.0-rc1 - 2026-04-24
1720

@@ -125,7 +128,7 @@
125128

126129
([Surya Rose](https://github.com/GearsDatapacks))
127130

128-
- Compiler can now emit source maps when targeting javascript. This can be enabled
131+
- Compiler can now emit source maps when targeting JavaScript. This can be enabled
129132
in the gleam.toml with the `source_maps` setting under the `javascript` section.
130133
([Ameen Radwan](https://github.com/Acepie))
131134

compiler-core/src/build/native_file_copier/tests.rs

Lines changed: 266 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,63 @@ fn cjavascript_files_are_copied_from_dev() {
192192
);
193193
}
194194

195+
#[test]
196+
fn javascriptx_files_are_copied_from_src() {
197+
let fs = InMemoryFileSystem::new();
198+
fs.write(&Utf8Path::new("/src/wibble.jsx"), "1").unwrap();
199+
200+
let copier = NativeFileCopier::new(fs.clone(), root(), root_out(), CheckModuleConflicts::Check);
201+
let copied = copier.run().unwrap();
202+
203+
assert!(!copied.any_elixir);
204+
assert!(copied.to_compile.is_empty());
205+
assert_eq!(
206+
HashMap::from([
207+
(Utf8PathBuf::from("/src/wibble.jsx"), "1".into()),
208+
(Utf8PathBuf::from("/out/wibble.jsx"), "1".into())
209+
]),
210+
fs.into_contents(),
211+
);
212+
}
213+
214+
#[test]
215+
fn javascriptx_files_are_copied_from_test() {
216+
let fs = InMemoryFileSystem::new();
217+
fs.write(&Utf8Path::new("/test/wibble.jsx"), "1").unwrap();
218+
219+
let copier = NativeFileCopier::new(fs.clone(), root(), root_out(), CheckModuleConflicts::Check);
220+
let copied = copier.run().unwrap();
221+
222+
assert!(!copied.any_elixir);
223+
assert!(copied.to_compile.is_empty());
224+
assert_eq!(
225+
HashMap::from([
226+
(Utf8PathBuf::from("/test/wibble.jsx"), "1".into()),
227+
(Utf8PathBuf::from("/out/wibble.jsx"), "1".into())
228+
]),
229+
fs.into_contents(),
230+
);
231+
}
232+
233+
#[test]
234+
fn javascriptx_files_are_copied_from_dev() {
235+
let fs = InMemoryFileSystem::new();
236+
fs.write(&Utf8Path::new("/dev/wibble.jsx"), "1").unwrap();
237+
238+
let copier = NativeFileCopier::new(fs.clone(), root(), root_out(), CheckModuleConflicts::Check);
239+
let copied = copier.run().unwrap();
240+
241+
assert!(!copied.any_elixir);
242+
assert!(copied.to_compile.is_empty());
243+
assert_eq!(
244+
HashMap::from([
245+
(Utf8PathBuf::from("/dev/wibble.jsx"), "1".into()),
246+
(Utf8PathBuf::from("/out/wibble.jsx"), "1".into())
247+
]),
248+
fs.into_contents(),
249+
);
250+
}
251+
195252
#[test]
196253
fn typescript_files_are_copied_from_src() {
197254
let fs = InMemoryFileSystem::new();
@@ -249,6 +306,177 @@ fn typescript_files_are_copied_from_dev() {
249306
);
250307
}
251308

309+
#[test]
310+
fn mtypescript_files_are_copied_from_src() {
311+
let fs = InMemoryFileSystem::new();
312+
fs.write(&Utf8Path::new("/src/wibble.mts"), "1").unwrap();
313+
314+
let copier = NativeFileCopier::new(fs.clone(), root(), root_out(), CheckModuleConflicts::Check);
315+
let copied = copier.run().unwrap();
316+
317+
assert!(!copied.any_elixir);
318+
assert!(copied.to_compile.is_empty());
319+
assert_eq!(
320+
HashMap::from([
321+
(Utf8PathBuf::from("/src/wibble.mts"), "1".into()),
322+
(Utf8PathBuf::from("/out/wibble.mts"), "1".into())
323+
]),
324+
fs.into_contents(),
325+
);
326+
}
327+
328+
#[test]
329+
fn mtypescript_files_are_copied_from_test() {
330+
let fs = InMemoryFileSystem::new();
331+
fs.write(&Utf8Path::new("/test/wibble.mts"), "1").unwrap();
332+
333+
let copier = NativeFileCopier::new(fs.clone(), root(), root_out(), CheckModuleConflicts::Check);
334+
let copied = copier.run().unwrap();
335+
336+
assert!(!copied.any_elixir);
337+
assert!(copied.to_compile.is_empty());
338+
assert_eq!(
339+
HashMap::from([
340+
(Utf8PathBuf::from("/test/wibble.mts"), "1".into()),
341+
(Utf8PathBuf::from("/out/wibble.mts"), "1".into())
342+
]),
343+
fs.into_contents(),
344+
);
345+
}
346+
347+
#[test]
348+
fn mtypescript_files_are_copied_from_dev() {
349+
let fs = InMemoryFileSystem::new();
350+
fs.write(&Utf8Path::new("/dev/wibble.mts"), "1").unwrap();
351+
352+
let copier = NativeFileCopier::new(fs.clone(), root(), root_out(), CheckModuleConflicts::Check);
353+
let copied = copier.run().unwrap();
354+
355+
assert!(!copied.any_elixir);
356+
assert!(copied.to_compile.is_empty());
357+
assert_eq!(
358+
HashMap::from([
359+
(Utf8PathBuf::from("/dev/wibble.mts"), "1".into()),
360+
(Utf8PathBuf::from("/out/wibble.mts"), "1".into())
361+
]),
362+
fs.into_contents(),
363+
);
364+
}
365+
366+
#[test]
367+
fn ctypescript_files_are_copied_from_src() {
368+
let fs = InMemoryFileSystem::new();
369+
fs.write(&Utf8Path::new("/src/wibble.cts"), "1").unwrap();
370+
371+
let copier = NativeFileCopier::new(fs.clone(), root(), root_out(), CheckModuleConflicts::Check);
372+
let copied = copier.run().unwrap();
373+
374+
assert!(!copied.any_elixir);
375+
assert!(copied.to_compile.is_empty());
376+
assert_eq!(
377+
HashMap::from([
378+
(Utf8PathBuf::from("/src/wibble.cts"), "1".into()),
379+
(Utf8PathBuf::from("/out/wibble.cts"), "1".into())
380+
]),
381+
fs.into_contents(),
382+
);
383+
}
384+
385+
#[test]
386+
fn ctypescript_files_are_copied_from_test() {
387+
let fs = InMemoryFileSystem::new();
388+
fs.write(&Utf8Path::new("/test/wibble.cts"), "1").unwrap();
389+
390+
let copier = NativeFileCopier::new(fs.clone(), root(), root_out(), CheckModuleConflicts::Check);
391+
let copied = copier.run().unwrap();
392+
393+
assert!(!copied.any_elixir);
394+
assert!(copied.to_compile.is_empty());
395+
assert_eq!(
396+
HashMap::from([
397+
(Utf8PathBuf::from("/test/wibble.cts"), "1".into()),
398+
(Utf8PathBuf::from("/out/wibble.cts"), "1".into())
399+
]),
400+
fs.into_contents(),
401+
);
402+
}
403+
404+
#[test]
405+
fn ctypescript_files_are_copied_from_dev() {
406+
let fs = InMemoryFileSystem::new();
407+
fs.write(&Utf8Path::new("/dev/wibble.cts"), "1").unwrap();
408+
409+
let copier = NativeFileCopier::new(fs.clone(), root(), root_out(), CheckModuleConflicts::Check);
410+
let copied = copier.run().unwrap();
411+
412+
assert!(!copied.any_elixir);
413+
assert!(copied.to_compile.is_empty());
414+
assert_eq!(
415+
HashMap::from([
416+
(Utf8PathBuf::from("/dev/wibble.cts"), "1".into()),
417+
(Utf8PathBuf::from("/out/wibble.cts"), "1".into())
418+
]),
419+
fs.into_contents(),
420+
);
421+
}
422+
423+
#[test]
424+
fn typescriptx_files_are_copied_from_src() {
425+
let fs = InMemoryFileSystem::new();
426+
fs.write(&Utf8Path::new("/src/wibble.tsx"), "1").unwrap();
427+
428+
let copier = NativeFileCopier::new(fs.clone(), root(), root_out(), CheckModuleConflicts::Check);
429+
let copied = copier.run().unwrap();
430+
431+
assert!(!copied.any_elixir);
432+
assert!(copied.to_compile.is_empty());
433+
assert_eq!(
434+
HashMap::from([
435+
(Utf8PathBuf::from("/src/wibble.tsx"), "1".into()),
436+
(Utf8PathBuf::from("/out/wibble.tsx"), "1".into())
437+
]),
438+
fs.into_contents(),
439+
);
440+
}
441+
442+
#[test]
443+
fn typescriptx_files_are_copied_from_test() {
444+
let fs = InMemoryFileSystem::new();
445+
fs.write(&Utf8Path::new("/test/wibble.tsx"), "1").unwrap();
446+
447+
let copier = NativeFileCopier::new(fs.clone(), root(), root_out(), CheckModuleConflicts::Check);
448+
let copied = copier.run().unwrap();
449+
450+
assert!(!copied.any_elixir);
451+
assert!(copied.to_compile.is_empty());
452+
assert_eq!(
453+
HashMap::from([
454+
(Utf8PathBuf::from("/test/wibble.tsx"), "1".into()),
455+
(Utf8PathBuf::from("/out/wibble.tsx"), "1".into())
456+
]),
457+
fs.into_contents(),
458+
);
459+
}
460+
461+
#[test]
462+
fn typescriptx_files_are_copied_from_dev() {
463+
let fs = InMemoryFileSystem::new();
464+
fs.write(&Utf8Path::new("/dev/wibble.tsx"), "1").unwrap();
465+
466+
let copier = NativeFileCopier::new(fs.clone(), root(), root_out(), CheckModuleConflicts::Check);
467+
let copied = copier.run().unwrap();
468+
469+
assert!(!copied.any_elixir);
470+
assert!(copied.to_compile.is_empty());
471+
assert_eq!(
472+
HashMap::from([
473+
(Utf8PathBuf::from("/dev/wibble.tsx"), "1".into()),
474+
(Utf8PathBuf::from("/out/wibble.tsx"), "1".into())
475+
]),
476+
fs.into_contents(),
477+
);
478+
}
479+
252480
#[test]
253481
fn all_javascript_files_are_copied_from_src_subfolders() {
254482
let fs = InMemoryFileSystem::new();
@@ -258,7 +486,15 @@ fn all_javascript_files_are_copied_from_src_subfolders() {
258486
.unwrap();
259487
fs.write(&Utf8Path::new("/src/abc/jkl/wibble.cjs"), "3")
260488
.unwrap();
261-
fs.write(&Utf8Path::new("/src/def/wobble.ts"), "4").unwrap();
489+
fs.write(&Utf8Path::new("/src/abc/jkl/wibble.jsx"), "4")
490+
.unwrap();
491+
fs.write(&Utf8Path::new("/src/def/wobble.ts"), "5").unwrap();
492+
fs.write(&Utf8Path::new("/src/def/wobble.mts"), "6")
493+
.unwrap();
494+
fs.write(&Utf8Path::new("/src/def/wobble.cts"), "7")
495+
.unwrap();
496+
fs.write(&Utf8Path::new("/src/def/wobble.tsx"), "8")
497+
.unwrap();
262498

263499
let copier = NativeFileCopier::new(fs.clone(), root(), root_out(), CheckModuleConflicts::Check);
264500
let copied = copier.run().unwrap();
@@ -273,8 +509,16 @@ fn all_javascript_files_are_copied_from_src_subfolders() {
273509
(Utf8PathBuf::from("/out/abc/ghi/wibble.js"), "2".into()),
274510
(Utf8PathBuf::from("/src/abc/jkl/wibble.cjs"), "3".into()),
275511
(Utf8PathBuf::from("/out/abc/jkl/wibble.cjs"), "3".into()),
276-
(Utf8PathBuf::from("/src/def/wobble.ts"), "4".into()),
277-
(Utf8PathBuf::from("/out/def/wobble.ts"), "4".into())
512+
(Utf8PathBuf::from("/src/abc/jkl/wibble.jsx"), "4".into()),
513+
(Utf8PathBuf::from("/out/abc/jkl/wibble.jsx"), "4".into()),
514+
(Utf8PathBuf::from("/src/def/wobble.ts"), "5".into()),
515+
(Utf8PathBuf::from("/out/def/wobble.ts"), "5".into()),
516+
(Utf8PathBuf::from("/src/def/wobble.mts"), "6".into()),
517+
(Utf8PathBuf::from("/out/def/wobble.mts"), "6".into()),
518+
(Utf8PathBuf::from("/src/def/wobble.cts"), "7".into()),
519+
(Utf8PathBuf::from("/out/def/wobble.cts"), "7".into()),
520+
(Utf8PathBuf::from("/src/def/wobble.tsx"), "8".into()),
521+
(Utf8PathBuf::from("/out/def/wobble.tsx"), "8".into()),
278522
]),
279523
fs.into_contents(),
280524
);
@@ -289,7 +533,15 @@ fn all_javascript_files_are_copied_from_test_subfolders() {
289533
.unwrap();
290534
fs.write(&Utf8Path::new("/test/abc/jkl/wibble.cjs"), "3")
291535
.unwrap();
292-
fs.write(&Utf8Path::new("/test/def/wobble.ts"), "4")
536+
fs.write(&Utf8Path::new("/test/abc/jkl/wibble.jsx"), "4")
537+
.unwrap();
538+
fs.write(&Utf8Path::new("/test/def/wobble.ts"), "5")
539+
.unwrap();
540+
fs.write(&Utf8Path::new("/test/def/wobble.mts"), "6")
541+
.unwrap();
542+
fs.write(&Utf8Path::new("/test/def/wobble.cts"), "7")
543+
.unwrap();
544+
fs.write(&Utf8Path::new("/test/def/wobble.tsx"), "8")
293545
.unwrap();
294546

295547
let copier = NativeFileCopier::new(fs.clone(), root(), root_out(), CheckModuleConflicts::Check);
@@ -305,8 +557,16 @@ fn all_javascript_files_are_copied_from_test_subfolders() {
305557
(Utf8PathBuf::from("/out/abc/ghi/wibble.js"), "2".into()),
306558
(Utf8PathBuf::from("/test/abc/jkl/wibble.cjs"), "3".into()),
307559
(Utf8PathBuf::from("/out/abc/jkl/wibble.cjs"), "3".into()),
308-
(Utf8PathBuf::from("/test/def/wobble.ts"), "4".into()),
309-
(Utf8PathBuf::from("/out/def/wobble.ts"), "4".into())
560+
(Utf8PathBuf::from("/test/abc/jkl/wibble.jsx"), "4".into()),
561+
(Utf8PathBuf::from("/out/abc/jkl/wibble.jsx"), "4".into()),
562+
(Utf8PathBuf::from("/test/def/wobble.ts"), "5".into()),
563+
(Utf8PathBuf::from("/out/def/wobble.ts"), "5".into()),
564+
(Utf8PathBuf::from("/test/def/wobble.mts"), "6".into()),
565+
(Utf8PathBuf::from("/out/def/wobble.mts"), "6".into()),
566+
(Utf8PathBuf::from("/test/def/wobble.cts"), "7".into()),
567+
(Utf8PathBuf::from("/out/def/wobble.cts"), "7".into()),
568+
(Utf8PathBuf::from("/test/def/wobble.tsx"), "8".into()),
569+
(Utf8PathBuf::from("/out/def/wobble.tsx"), "8".into()),
310570
]),
311571
fs.into_contents(),
312572
);

compiler-core/src/io.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,7 @@ pub trait TarUnpacker {
432432
pub fn is_native_file_extension(extension: &str) -> bool {
433433
matches!(
434434
extension,
435-
"erl" | "hrl" | "ex" | "js" | "mjs" | "cjs" | "ts"
435+
"erl" | "hrl" | "ex" | "js" | "mjs" | "cjs" | "jsx" | "ts" | "mts" | "cts" | "tsx"
436436
)
437437
}
438438

0 commit comments

Comments
 (0)