Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Fixed array.flat[Map] on [[]] (fixes #719).#737

Merged
Perryvw merged 5 commits into
TypeScriptToLua:masterTypeScriptToLua/TypeScriptToLua:masterfrom
radekmie:fixed-array-flat-emptyCopy head branch name to clipboard
Oct 22, 2019
Merged

Fixed array.flat[Map] on [[]] (fixes #719).#737
Perryvw merged 5 commits into
TypeScriptToLua:masterTypeScriptToLua/TypeScriptToLua:masterfrom
radekmie:fixed-array-flat-emptyCopy head branch name to clipboard

Conversation

@radekmie

Copy link
Copy Markdown
Contributor

This change fixes a bug reported in #719: empty array elements (e.g. [[]]) were incorrectly handled by array.flat and array.flatMap.

@Perryvw Perryvw left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a feeling simply removing this check is not the answer here, I suggested 2 testcases that will either break your solution or help prove it is sound.

Comment thread test/unit/builtins/array.spec.ts
Comment thread test/unit/builtins/array.spec.ts
@radekmie

Copy link
Copy Markdown
Contributor Author

I've added these tests. Of course, they are failing. I'm just thinking, what is better to do here:

  • Add a special case for an empty table (not very efficient).
  • Add a isArray-like test (same as in __TS__ArrayConcat).

@Perryvw

Perryvw commented Oct 21, 2019

Copy link
Copy Markdown
Member

The problem is there is not really a way to distinguish an empty table from an empty object in lua (they are both translated to {}). I am thinking we could assume for this case objects won't be empty and extend the existing check to something like ... && (1 in value || (next(value, undefined) == undefined)) To efficiently check the object has no keys. I would like to discuss your and my suggestions with some other contributors in the discord before making a final decision. I will come back to this after.

@Perryvw

Perryvw commented Oct 22, 2019

Copy link
Copy Markdown
Member

Alright, we discussed it and came to the following conclusion: For now we would be fine if the way you solve this is by assuming that if an object has no keys, it is an array. This is not entirely correct, but there is no straightforward (or even a complex one) way to deal with this perfectly, so we would rather go for the very simple non-perfect fix than to go for a very complex non-perfect fix. So then the check could indeed be modified as I suggested above by adding a special case to the if statement. Please add a comment to the LuaLib explaining what the reasoning behind (1 in value || (next(value, undefined) == undefined)) is and in which case it will fail (objects without keys in list).

@radekmie

radekmie commented Oct 22, 2019

Copy link
Copy Markdown
Contributor Author

It didn't help as next(value, undefined) == undefined (using === works the same) translates to

({ next(value, nil) }) == nil

and not, as expected, to

next(value, nil) == nil

Any idea why?

EDIT: It's a more general problem, as next(x, undefined) translates to ({ next(x, nil) }).

@Perryvw

Perryvw commented Oct 22, 2019

Copy link
Copy Markdown
Member

That sounds very strange, can you just push your changes so I can have a look?

@radekmie

radekmie commented Oct 22, 2019

Copy link
Copy Markdown
Contributor Author

It seems to be caused by @tupleReturn directive on next definition - removing it fixes the problem (but it's there for a reason).

EDIT: All tests pass even without this directive.

@Perryvw

Perryvw commented Oct 22, 2019

Copy link
Copy Markdown
Member

That does explain the behavior. This turned out a bit more complicated than I expected. To get rid of the wrapping we need a bit of typing. I feel like there must be a better way but for now you can put this in declarations/global.d.ts:

// Override next declaration so we can omit extra return values
type NextEmptyCheck = (this: void, table: any, index: undefined) => unknown | undefined;

Then you change the check to

if (type(value) === "table" && (1 in value || (next as NextEmptyCheck)(value, undefined) === undefined)) {

Edit: oops, accidentally added some incorrect stuff to the NextEmptyCheck type, removed it now.

Comment thread src/lualib/ArrayFlat.ts Outdated
@lolleko

lolleko commented Oct 22, 2019

Copy link
Copy Markdown
Member

I used if (pcall(() => (arg as any[]).length) && type(arg) !== "string") in ArrayConcat to determine if a value is an array.
Maybe it could be used here as well.
Im not so sure tho since this new workaround might be better, because it doesn't rely on pcall.

In any case we should keep it consistent and use one of the methods for an isArray workaround across lualib.

@radekmie

radekmie commented Oct 22, 2019

Copy link
Copy Markdown
Contributor Author

I also thought about that at first, but {a: 1} also pass that pcall test. In general this may be a bigger problem, as [].concat({a: 1}) === [].

👍 for a general isArray.

EDIT: Maybe use Array.isArray for that?

@lolleko

lolleko commented Oct 22, 2019

Copy link
Copy Markdown
Member

You are right! The array concat test do not include a case with an object... yikes.
So good thing we found that issue #738 here.

Anyway I think we should merge this and address isArray and array.concat in a different issue/pr.

Also related: #262

@Perryvw

Perryvw commented Oct 22, 2019

Copy link
Copy Markdown
Member

I agree @lolleko, maybe we implement Array.isArray in the lualib and add some lualib dependencies? We can discuss it a bit more. That's a PR for another day.

@Perryvw Perryvw merged commit 5d2d64b into TypeScriptToLua:master Oct 22, 2019
@Perryvw Perryvw mentioned this pull request Jan 25, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

Morty Proxy This is a proxified and sanitized view of the page, visit original site.