fengari-lua / fengari-interop

Fengari <=> JS Interop
MIT License
98 stars 13 forks source link

Integers retrieved from JS objects become floats #31

Closed timkurvers closed 6 years ago

timkurvers commented 6 years ago

It seems fengari-interop retrieves any number on a JS object as a float, internally using lua_pushnumber, rather than lua_pushinteger for integers.

Example using https://fengari.io:

→ js.global.document.documentElement.clientWidth
1628.0

Is this intentional?

timkurvers commented 6 years ago

Just to clarify why this can be problematic when combined with how recent versions of Lua interpolate floats into strings:

local index = js.global.nextIndex -- set to 1 in JS code
_G["MyComponent"..index] = ...

This would result in MyComponent1.0 rather than MyComponent1 being globalized, which leads to a variety of issues down the road.

daurnimator commented 6 years ago

Javascript numbers are floating point, and have floating point semantics when used. It would be very odd IMO to convert them into integers (which would introduce e.g. overflow at 32bits)

The .0 shouldn't cause suprises in lua: the conversion of a number to a string has no defined representation (either with tostring or when concatenating). You should be using string.format to convert numbers to strings in any case. (I was very tempted to turn off coercion by default in fengari)

From https://www.lua.org/manual/5.3/manual.html#8.1:

The conversion of a float to a string now adds a .0 suffix to the result if it looks like an integer. (For instance, the float 2.0 will be printed as 2.0, not as 2.) You should always use an explicit format when you need a specific format for numbers.

(Formally this is not an incompatibility, because Lua does not specify how numbers are formatted as strings, but some programs assumed a specific format.)

daurnimator commented 6 years ago

Hrm, maybe we could support LUA_COMPAT_FLOATSTRING?

From lua 5.3's luaconf.h:

/*
@@ LUA_COMPAT_FLOATSTRING makes Lua format integral floats without a
@@ a float mark ('.0').
** This macro is not on by default even in compatibility mode,
** because this is not really an incompatibility.
*/
/* #define LUA_COMPAT_FLOATSTRING */

https://github.com/fengari-lua/fengari/blob/79a9c5e4c123da9e58979a61d17557398b0c1be7/src/lobject.js#L595

If that is something that you require, please create an issue for it in the fengari repository (rather than here)

fallenoak commented 6 years ago

Thanks for the replies, @daurnimator! I'm working on the same project as @timkurvers. To add a bit of context:

We're reimplementing a game client in Javascript using the client's original data files (including its Lua scripts). The original game client used Lua 5.1.x. It appears that in older versions of Lua, integral floats in string casts always retained their integral form.

Example (Lua 5.1): https://repl.it/repls/TameOverjoyedAdmins

local foo = 1.0
local baz = "bar"..foo
print(baz)
-- "bar1"

While we could modify the client's original scripts, we're hoping to use them as is. As a result, figuring out a way to enable that legacy behavior within Fengari would be fantastic. Support for something like LUA_COMPAT_FLOATSTRING would likely fit the bill.

timkurvers commented 6 years ago

Thanks @daurnimator! Opened an issue: https://github.com/fengari-lua/fengari/issues/113.