JavaScript float natives arguments bug

Hey, I’ve found a pretty annoying bug in the JS client natives wrapper and the source of the bug.

Every float argument of natives is parsed with _fv function which add 0.0000001 to the value.

In most cases, it isn’t an issue, but if you want for example disable vehicle traffic with SetVehicleDensityMultiplierThisFrame(0.0) it will flash ghost vehicles because the multiplier argument value will be 0.0000001.

JS natives wrapper source code

function _fv(flt) {
	return flt + 0.0000001;
}

...

global.SetVehicleDensityMultiplierThisFrame = function (multiplier) {
	return _in(0x245a6883, 0xd966d537, _fv(multiplier));
};

Video bug reproduction

ok, how would you suggest this be fixed, since there’s no other way to annotate a value as being an integer in JS:

i’m curious if the addition to _fv is to confirm it’s decimalized…
but i can’t fathom why parseInt() or parseFloat() weren’t used instead.
I look forward to finding out, i’ve begun devving in the JS engine as well and i’d hate all that work to go to bunk.

Sorry, I can’t answer that question, I’m not a C++ dev, just a web developer having a good time customizing GTA V!

So the temp fix in the video bug repro above generates side effects (int/float detection) in the V8ScriptRuntime ?

I thought the _fv function was just a convenience of the JS wrapper to handle both int/float params in the natives.

I really hope we can find a fix, it’s the last thing preventing me developing full JS resources!

I thought the same thing (see my deterministic_bubble answer above and my video bug repro temp fix).
I hope it’ll be as simple as that!

JS only has floats, unlike Lua you can’t tell if a number is a float or not from external API.

i just use this on any number if i want to do that…

function(n){return Number(n) === n && n % 1 !== 0};

but that’s just a band-aid.
if this extra amount affects our floats in the JS engine…that’s kinda big for JS nerds.
Is there some code standard that exists that we’d be breaching if we just passed it as it is and let us assume it’s an int unless it has decimal remainders?

Thanks for answering. if i can help fix this in any way, would be totally up for assisting. i’m no codemonkey, but i can throw some Visual studio around when i have to.

1 Like

I checked the code you mentioned and understand the issue : if we set for example 1.0 as a float native parameter in JavaScript it’ll be dynamically converted to an integer value and the native will fail because it expect a float.

Can’t we use the _fv function to return a string if the value is an integer (example: if the value is 1 or 1.0 return ‘1.0’ string), then in the V8ScriptRuntime we add a test to treat text float values as float parameter ?

It adds more tests when calling natives, but we could keep float information from JS to C++

Example of modified _fv function

function _fv(flt) {
	return  Number.isInteger(flt) ? parseFloat(flt).toFixed(1) : flt
}

I tried to get a working C++ POC but I’m not good enough… The best answer I found is to test with a regex digit, minus and dot characters.

P.S : Correct me if I’m wrong, I just try to help :wink:

EDIT @nta

A temp fix I found is the below _fv(flt) function : it only add 0.0000001 to integers above 0.

function _fv(flt) {
	return flt && Number.isInteger(flt) ? flt + 0.0000001 : flt;
}

With this function, all bellow JS native calls work as expected :slight_smile:

SetVehicleDensityMultiplierThisFrame(0)
SetVehicleDensityMultiplierThisFrame(1)
SetVehicleDensityMultiplierThisFrame(0.0)
SetVehicleDensityMultiplierThisFrame(0.5)
SetVehicleDensityMultiplierThisFrame(1.0)
2 Likes

Good job guys. When I found this problem with the spawning parameters I created a simple lua package to handle the traffic. It’s good to know there is a workaround now for that problem. Anybody plan to create a pull request into the Fivem repository if this solution is tested properly?

This has been fixed today in https://github.com/citizenfx/fivem/commit/a077d2f87dff856cc9a97567c4b1fce2df2ddb81