Skip to content

Commit bddb2d4

Browse files
gavinmorrowlpil
authored andcommitted
Fix invalid JS for ints with 0s as prefix (#5459)
1 parent e7ec1ea commit bddb2d4

12 files changed

Lines changed: 188 additions & 10 deletions

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,3 +421,6 @@
421421
updates if the constructor definition has a positional field defined after
422422
labelled fields.
423423
([Hari Mohan](https://gituhub.com/seafoamteal))
424+
425+
- Fixed invalid JavaScript code generation when ints or floats had prefixed `0`s
426+
before and after an `_` (e.g. `000_001`).

compiler-core/src/javascript/expression.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2464,16 +2464,11 @@ pub fn eco_string_int<'a>(value: EcoString) -> Document<'a> {
24642464
value
24652465
};
24662466

2467-
let value = value.trim_start_matches('0');
2467+
let value = value.trim_start_matches(['0', '_']);
24682468
if value.is_empty() {
24692469
out.push('0');
24702470
}
24712471

2472-
// If the number starts with a `0` then an underscore, the `0` will be stripped,
2473-
// leaving the number to look something like `_1_2_3`, which is not valid syntax.
2474-
// Therefore, we strip the `_` to avoid this case.
2475-
let value = value.trim_start_matches('_');
2476-
24772472
out.push_str(value);
24782473

24792474
out.to_doc()
@@ -2489,7 +2484,7 @@ pub fn float(value: &str) -> Document<'_> {
24892484
};
24902485
let value = value.trim_start_matches(['+', '-'].as_ref());
24912486

2492-
let value = value.trim_start_matches('0');
2487+
let value = value.trim_start_matches(['0', '_']);
24932488
if value.starts_with(['.', 'e', 'E']) {
24942489
out.push('0');
24952490
}

compiler-core/src/javascript/tests/numbers.rs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,18 @@ pub fn main() {
256256
);
257257
}
258258

259+
// https://github.com/gleam-lang/gleam/issues/5459
260+
#[test]
261+
fn many_preceeding_zeros_int() {
262+
assert_js!(
263+
r#"
264+
pub fn main() {
265+
0000_000_00_9_179
266+
}
267+
"#
268+
);
269+
}
270+
259271
// https://github.com/gleam-lang/gleam/issues/2412
260272
#[test]
261273
fn preceeding_zeros_float() {
@@ -268,6 +280,18 @@ pub fn main() {
268280
);
269281
}
270282

283+
// https://github.com/gleam-lang/gleam/issues/5459
284+
#[test]
285+
fn many_preceeding_zeros_float() {
286+
assert_js!(
287+
r#"
288+
pub fn main() {
289+
0000_000_00_9_179.1
290+
}
291+
"#
292+
);
293+
}
294+
271295
// https://github.com/gleam-lang/gleam/issues/2412
272296
#[test]
273297
fn preceeding_zeros_int_const() {
@@ -278,6 +302,16 @@ pub const x = 09_179
278302
);
279303
}
280304

305+
// https://github.com/gleam-lang/gleam/issues/5459
306+
#[test]
307+
fn many_preceeding_zeros_int_const() {
308+
assert_js!(
309+
r#"
310+
pub const x = 0000_000_00_9_179
311+
"#
312+
);
313+
}
314+
281315
// https://github.com/gleam-lang/gleam/issues/2412
282316
#[test]
283317
fn preceeding_zeros_float_const() {
@@ -288,6 +322,16 @@ pub const x = 09_179.1
288322
);
289323
}
290324

325+
// https://github.com/gleam-lang/gleam/issues/5459
326+
#[test]
327+
fn many_preceeding_zeros_float_const() {
328+
assert_js!(
329+
r#"
330+
pub const x = 0000_000_00_9_179.1
331+
"#
332+
);
333+
}
334+
291335
// https://github.com/gleam-lang/gleam/issues/2412
292336
#[test]
293337
fn preceeding_zeros_int_pattern() {
@@ -300,6 +344,18 @@ pub fn main(x) {
300344
);
301345
}
302346

347+
// https://github.com/gleam-lang/gleam/issues/5459
348+
#[test]
349+
fn many_preceeding_zeros_int_pattern() {
350+
assert_js!(
351+
r#"
352+
pub fn main(x) {
353+
let assert 0000_000_00_9_179 = x
354+
}
355+
"#
356+
);
357+
}
358+
303359
// https://github.com/gleam-lang/gleam/issues/2412
304360
#[test]
305361
fn preceeding_zeros_float_pattern() {
@@ -312,6 +368,18 @@ pub fn main(x) {
312368
);
313369
}
314370

371+
// https://github.com/gleam-lang/gleam/issues/5459
372+
#[test]
373+
fn many_preceeding_zeros_float_pattern() {
374+
assert_js!(
375+
r#"
376+
pub fn main(x) {
377+
let assert 0000_000_00_9_179.1 = x
378+
}
379+
"#
380+
);
381+
}
382+
315383
// https://github.com/gleam-lang/gleam/issues/4459
316384
#[test]
317385
fn underscore_after_hexadecimal_prefix() {
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
source: compiler-core/src/javascript/tests/numbers.rs
3+
expression: "\npub fn main() {\n 0000_000_00_9_179.1\n}\n"
4+
---
5+
----- SOURCE CODE
6+
7+
pub fn main() {
8+
0000_000_00_9_179.1
9+
}
10+
11+
12+
----- COMPILED JAVASCRIPT
13+
export function main() {
14+
return 9179.1;
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
source: compiler-core/src/javascript/tests/numbers.rs
3+
expression: "\npub const x = 0000_000_00_9_179.1\n"
4+
---
5+
----- SOURCE CODE
6+
7+
pub const x = 0000_000_00_9_179.1
8+
9+
10+
----- COMPILED JAVASCRIPT
11+
export const x = 9_179.1;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
---
2+
source: compiler-core/src/javascript/tests/numbers.rs
3+
expression: "\npub fn main(x) {\n let assert 0000_000_00_9_179.1 = x\n}\n"
4+
---
5+
----- SOURCE CODE
6+
7+
pub fn main(x) {
8+
let assert 0000_000_00_9_179.1 = x
9+
}
10+
11+
12+
----- COMPILED JAVASCRIPT
13+
import { makeError } from "../gleam.mjs";
14+
15+
const FILEPATH = "src/module.gleam";
16+
17+
export function main(x) {
18+
if (!(x === 9179.1)) {
19+
throw makeError(
20+
"let_assert",
21+
FILEPATH,
22+
"my/mod",
23+
3,
24+
"main",
25+
"Pattern match failed, no pattern matched the value.",
26+
{ value: x, start: 20, end: 54, pattern_start: 31, pattern_end: 50 }
27+
)
28+
}
29+
return x;
30+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
source: compiler-core/src/javascript/tests/numbers.rs
3+
expression: "\npub fn main() {\n 0000_000_00_9_179\n}\n"
4+
---
5+
----- SOURCE CODE
6+
7+
pub fn main() {
8+
0000_000_00_9_179
9+
}
10+
11+
12+
----- COMPILED JAVASCRIPT
13+
export function main() {
14+
return 9_179;
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
source: compiler-core/src/javascript/tests/numbers.rs
3+
expression: "\npub const x = 0000_000_00_9_179\n"
4+
---
5+
----- SOURCE CODE
6+
7+
pub const x = 0000_000_00_9_179
8+
9+
10+
----- COMPILED JAVASCRIPT
11+
export const x = 9_179;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
---
2+
source: compiler-core/src/javascript/tests/numbers.rs
3+
expression: "\npub fn main(x) {\n let assert 0000_000_00_9_179 = x\n}\n"
4+
---
5+
----- SOURCE CODE
6+
7+
pub fn main(x) {
8+
let assert 0000_000_00_9_179 = x
9+
}
10+
11+
12+
----- COMPILED JAVASCRIPT
13+
import { makeError } from "../gleam.mjs";
14+
15+
const FILEPATH = "src/module.gleam";
16+
17+
export function main(x) {
18+
if (!(x === 9179)) {
19+
throw makeError(
20+
"let_assert",
21+
FILEPATH,
22+
"my/mod",
23+
3,
24+
"main",
25+
"Pattern match failed, no pattern matched the value.",
26+
{ value: x, start: 20, end: 52, pattern_start: 31, pattern_end: 48 }
27+
)
28+
}
29+
return x;
30+
}

compiler-core/src/javascript/tests/snapshots/gleam_core__javascript__tests__numbers__zero_after_underscore_after_binary_prefix.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,5 @@ pub fn main() {
1111

1212
----- COMPILED JAVASCRIPT
1313
export function main() {
14-
return 0b0_1_0_1;
14+
return 0b1_0_1;
1515
}

0 commit comments

Comments
 (0)