Skip to content

Commit 9676a5d

Browse files
committed
Implement Number.toFixed
1 parent 1af3db3 commit 9676a5d

File tree

4 files changed

+55
-0
lines changed

4 files changed

+55
-0
lines changed

src/LuaLib.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ export enum LuaLibFeature {
5858
NumberIsFinite = "NumberIsFinite",
5959
NumberIsNaN = "NumberIsNaN",
6060
NumberToString = "NumberToString",
61+
NumberToFixed = "NumberToFixed",
6162
ObjectAssign = "ObjectAssign",
6263
ObjectDefineProperty = "ObjectDefineProperty",
6364
ObjectEntries = "ObjectEntries",

src/lualib/NumberToFixed.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/// https://www.ecma-international.org/ecma-262/10.0/index.html#sec-number.prototype.tofixed
2+
export function __TS__NumberToFixed(this: number, fractionDigits?: number): string {
3+
if (Math.abs(this) >= 1e21 || this !== this) {
4+
return this.toString();
5+
}
6+
const f = Math.floor(fractionDigits ?? 0);
7+
if (f < 0 || f > 100) {
8+
throw "toFixed() digits argument must be between 0 and 100";
9+
}
10+
// throws "invalid format (width or precision too long)" if strlen > 99
11+
// if (f < 80) return fmt; else try {return fmt} catch(_) { throw "toFixed() digits argument..." }
12+
return string.format(`%.${f}f`, this);
13+
}

src/transformation/builtins/number.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ export function transformNumberPrototypeCall(
2020
return params.length === 0
2121
? lua.createCallExpression(lua.createIdentifier("tostring"), [caller], node)
2222
: transformLuaLibFunction(context, LuaLibFeature.NumberToString, node, caller, ...params);
23+
case "toFixed":
24+
return transformLuaLibFunction(context, LuaLibFeature.NumberToFixed, node, caller, ...params);
2325
default:
2426
context.diagnostics.push(unsupportedProperty(calledMethod.name, "number", expressionName));
2527
}

test/unit/builtins/numbers.spec.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,45 @@ test.each([
6969
util.testExpressionTemplate`(${value}).toString(2)`.expectToEqual(luaNativeSpecialNumString);
7070
});
7171

72+
// frac=100 fails as result can't fit
73+
const toFixedFractions = [undefined, 0, 1, 1.23456, 2, Math.PI, 5, 10, 80];
74+
// val=x.5 fails as rounding differ
75+
const toFixedValues = [
76+
-1,
77+
0,
78+
1,
79+
1.2345678,
80+
-20391,
81+
3.1415,
82+
Math.PI,
83+
2.7182,
84+
-34910.3,
85+
1.45,
86+
1.55,
87+
1.444555,
88+
1024,
89+
1.2,
90+
1e19,
91+
1e22,
92+
];
93+
const toFixedPairs = toFixedValues.flatMap(value => toFixedFractions.map(frac => [value, frac] as const));
94+
test.each(toFixedPairs)("(%p).toFixed(%p)", (value, frac) => {
95+
util.testExpressionTemplate`(${value}).toFixed(${frac})`.expectToMatchJsResult();
96+
});
97+
98+
test.each([
99+
[NaN, "(0/0)"],
100+
[Infinity, "(1/0)"],
101+
[-Infinity, "(-(1/0))"],
102+
])("%p.toFixed(2)", (value, luaNativeSpecialNum) => {
103+
// Need to get the actual lua tostring version of inf/nan
104+
// this is platform dependent so we can/should not hardcode it
105+
const luaNativeSpecialNumString = util.testExpression`${luaNativeSpecialNum}.toString()`.getLuaExecutionResult();
106+
// Cannot use expectToMatchJsResult because this actually wont be the same in JS in Lua
107+
// TODO fix this in lualib/NumberToString.ts
108+
util.testExpressionTemplate`(${value}).toFixed(2)`.expectToEqual(luaNativeSpecialNumString);
109+
});
110+
72111
test.each(cases)("isNaN(%p)", value => {
73112
util.testExpressionTemplate`isNaN(${value} as any)`.expectToMatchJsResult();
74113
});

0 commit comments

Comments
 (0)