Bug JavaScript bugs

philmasterplus

Active member
JS is a very dynamic language with a large amount of cruft. There are many quirks that make it hard to answer the question, "How many arguments does this function take?". To answer this with certainty, you'll have to do symbolic execution--no static analysis is going to cut it 100%.

(Microsoft had to devise a new language (TypeScript) that adds numerous constraints in order to make static analysis feasible. And they're putting lots of money behind it.)

This would be much easily solved by giving users a function that launches a popup dialog asking for input.

Edit: Just re-read gausie's comment and he already added user_prompt(). Way to go gausie!
 

heeheehee

Developer
Staff member
To be clear: there's a difference between "how many parameters are explicitly configured for this function?" and "how many arguments can this function take / process?"

The latter is unbounded (with arbitrary access to arguments) and arguably not a meaningful question to ask.

But the former is encoded in the parse tree for the function.
 

heeheehee

Developer
Staff member
And specifically in the context of JS in Mafia:


I don't see figuring out how many args to request as fundamentally difficult. Figuring out what type they should be, sure (especially without something like TypeScript).

(edit: to be clear: I'm aware that gausie already implemented the more robust user_confirm, so this is nominally moot.)
 

xKiv

Active member
Can you also tell the names and types of those arguments, so kolmafia knows what to ask for?
 

heeheehee

Developer
Staff member
As mentioned, the hard part is the type information, as JS is dynamically-typed, so that's not even a thing. Variable names aren't particularly meaningful, unless for some reason you want to add type inference based on naming, which is incredibly error-prone and fragile and just all-around a terrible idea.

You could shunt strings into each of the detected variables and let the script writer call toItem() or whatever on them. There's really not much better that you can do.

edit: I suppose the parameter names are meaningful in the context of prompting. But my point was that the hard part was never figuring out how many arguments JS wants for a given function, so the snark addressed at frono was unwarranted.
 

gausie

D̰͕̝͚̤̥̙̐̇̑͗̒e͍͔͎͈͔ͥ̉̔̅́̈l̠̪̜͓̲ͧ̍̈́͛v̻̾ͤe͗̃ͥ̐̊ͬp̔͒ͪ
Staff member
Code:
function func2(a, b) {
    console.log("I have " + arguments.length + "arguments!");
}

console.log(func2.length);
// expected output: 2

func2(1,2,3);
 

philmasterplus

Active member
I don't want to end up manipulating Function.prototype.length just to suppress a popup box, or creating fake parameters to control how many popup boxes are launched. I'm also not too happy about showing parameter names directly in popups...so I'm okay with the status quo.
 

heeheehee

Developer
Staff member
Code:
function func2(a, b) {
    console.log("I have " + arguments.length + "arguments!");
}

console.log(func2.length);
// expected output: 2

func2(1,2,3);
This is precisely the situation that (I assert) is not meaningful to worry about.

If a function only requests two arguments, then why should I care that some rando decides to stuff another 20 in there?

Further: `arguments` manipulation is terrible for many reasons, not least of which being that in modern JS (i.e. in a situation like this where you don't have to worry about supporting IE6), you should use rest parameters instead.

(availability of Array.prototype methods and performance also come to mind)
 

philmasterplus

Active member
Rhino doesn't support default and rest parameters yet. Some transpilers use arguments extensively to transpile these features, so we can't abolish it yet. (Speaking of which, should we launch a popup for parameters with default values, too?)

I'd argue that relying on Function.prototype.length is about as hacky as using arguments. But the former is barely used in practice, while the other is still seen fairly often.
 

heeheehee

Developer
Staff member
(Parameters with default values don't need to be specified, so no.)

That's surprising that Rhino doesn't support a feature from 5 years ago, but I guess there would be far more SpiderMonkey devs than Rhino devs.

I'm not advocating using on Function.prototype.length specifically, but rather the similar function available to Java, FunctionObject.getArity().
 

xKiv

Active member
If a function only requests two arguments, then why should I care that some rando decides to stuff another 20 in there?
The context I am interested about is not "what does the function know about how it was called". It's "how does mafia know how many parameters it should ask for when the script is called, and how does it know how to describe those parameters to the user". You can't know how many arguments the function was called with yet, because you haven't called it yet, because you don't know how many arguments you should call it with.
 

heeheehee

Developer
Staff member
The context I am interested about is not "what does the function know about how it was called". It's "how does mafia know how many parameters it should ask for when the script is called, and how does it know how to describe those parameters to the user". You can't know how many arguments the function was called with yet, because you haven't called it yet, because you don't know how many arguments you should call it with.
I believe we're on the same page.

The number of parameters that the function expects is a known and accessible quantity. arguments is a distraction in that context.

The parameter types are not definable, barring type annotations (e.g. TypeScript). The parameter names are not exposed as part of the API and would require special parsing logic.
 

xKiv

Active member
So, how does the *user* know what is the meaning of which parameter?
For ash scripts, mafia pops up a input box that contains the type and name of each parameter.
For js scritps ... what should happen if neither of those can be known?
 

heeheehee

Developer
Staff member
I'm not saying that's a reasonable problem to solve.

I was responding to the very specific claim of "There are many quirks that make it hard to answer the question, 'How many arguments does this function take?'."
 
itemDropsArray() appears to not function in js--the most relevant part of the debug log appears to be

Code:
class net.sourceforge.kolmafia.textui.ScriptException: Failed to insert value into map.
net.sourceforge.kolmafia.textui.ScriptException: Failed to insert value into map.
 

heeheehee

Developer
Staff member
itemDropsArray() appears to not function in js
Try r20827.

appearanceRates() will likely continue to be unusable; I'm not familiar enough with the implementation to know whether I can remove the key coercion as well.

edit: it seems that a basic test for appearanceRates works just fine. Maybe the problem was just in records. Either way -- let me know if I ended up breaking some other behavior.
 
Update: it's weirder

> js getPlayerName(parseInt(getPlayerId("WoRtHaWhOlEbEaN")))

worthawholebean (#1972588), the Level 52 Pastamancer
This player is currently online in channel games and listening to hardcore and trade.

Returned: 1972588.0

> js getPlayerName(1483803)

Returned: Manendra

> js getPlayerName(1972588)

Returned: worthawholebean
 

heeheehee

Developer
Staff member
hehe

> js getPlayerName(toInt(getPlayerId("WoRtHaWhOlEbEaN")))

works for me though

From printing intermediate values, I think JS numbers are always treated as ASH floats. Note that get_player_name's implementation in RuntimeLibrary unconditionally calls playerIdValue.toString() without type-checking it.

Seems like we're just not coercing values properly when calling ASH functions from JS.
 
Top