Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(Util): fix sorting for GuildChannels #7002

Merged
merged 4 commits into from Dec 1, 2021
Merged

fix(Util): fix sorting for GuildChannels #7002

merged 4 commits into from Dec 1, 2021

Conversation

That-Guy977
Copy link
Contributor

@That-Guy977 That-Guy977 commented Nov 18, 2021

Please describe the changes this PR makes and why it should be merged:

Util#discordSort sorts Ids descending when the rawPosition is the same, which is consistent with Role sorting, but is not for GuildChannel sorting, which sorts Ids ascending

Status and versioning classification:

  • Typings don't need updating

Note: I've been unable to test the changes nor some similar versions, due to issues as I mentioned here; I'm not sure what I'm doing wrong, as I've only modified the required files and this method, but it seems to break the entire Util exports
I've just decided to create this PR in the hopes that someone else with more experience can fix these mistakes

Issues resolved, changes tested

@iCrawl iCrawl added this to the Version 13.4 milestone Nov 18, 2021
src/util/Util.js Outdated Show resolved Hide resolved
@kyranet
Copy link
Member

kyranet commented Nov 24, 2021

Come think of it, can't we read the first value in the collection and determine whether or not it's a collection of GuildChannels? That way we do 1 instanceof check rather than N * log(N) times (being N the collection's size), which can be quite expensive as instanceof is an O(N) operation (being N the amount of prototypes it takes to get to null), resulting on an O(N^2) cost?

I'm thinking more along the lines of:

// Nothing to sort if it has 0 or 1 entry:
if (collection.size < 2) return collection.clone();

// Check whether or not the first value is a GuildChannel, if it is, assume the rest
// of entries also are:
const isGuildChannel = collection.first() instanceof GuildChannel;
return collection.sorted(isGuildChannel ?
	(a, b) => a.rawPosition - b.rawPosition || Number(BigInt(a.id) - BigInt(b.id)) :
	(a, b) => a.rawPosition - b.rawPosition || Number(BigInt(b.id) - BigInt(a.id)));

This way it keeps being O(N * log N) while also fixes the bug.

@That-Guy977
Copy link
Contributor Author

Would it really be necessary to add a case specifically for 0 or 1 elements in the collection? Wouldn't the internal use of Array#sort just not do much at all?

@kyranet
Copy link
Member

kyranet commented Nov 25, 2021

That's because with this trick, we're reading the first element, so we need to make sure the collection is not empty (if (collection.size === 0) return collection.clone();), however, since we cannot sort a collection with one entry (it's always sorted), then we change the condition from === 0 to < 2, that's why the suggested code is like that.

@That-Guy977
Copy link
Contributor Author

But if there aren't elements, the sort function isn't run anyways, so I don't understand why we would need to make sure that it isn't empty
It'd just be undefined instanceof GuildChannel, no? and that would be false but it wouldn't really matter

@kyranet
Copy link
Member

kyranet commented Nov 25, 2021

Fair enough, feel free to remove that size check.

@That-Guy977
Copy link
Contributor Author

This is what i got to after a few style iterations

static discordSort(collection) {
  const isGuildChannel = collection.first() instanceof GuildChannel;
  return collection.sorted(
    (a, b) =>
      a.rawPosition - b.rawPosition ||
      Number(isGuildChannel ? BigInt(a.id) - BigInt(b.id) : BigInt(b.id) - BigInt(a.id)),
  );
}

Does this look good to you?

@kyranet
Copy link
Member

kyranet commented Nov 25, 2021

You're back to making an easily avoidable ternary check N * log(N) times.

@That-Guy977
Copy link
Contributor Author

Ah, i missed the purpose of the seperate functions, I'll just go with your method minus the size check then

Copy link
Member

@kyranet kyranet left a comment

Choose a reason for hiding this comment

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

As long as this is tested, looks good to me.

@That-Guy977
Copy link
Contributor Author

That-Guy977 commented Nov 25, 2021

The issues i mentioned in the initial comment seem to have fixed themselves, so I was able to test it, and the position is consistent with the UI for both channels and roles with this version
However, I'm now getting these warnings/errors from sending the message output, not sure if this is related/significant? I tested this in the node repl

(node:24339) Warning: Accessing non-existent property 'idToBinary' of module exports inside circular dependency
Uncaught TypeError: Util.idToBinary is not a function
    at Function.deconstruct (/Users/that_guy977/Desktop/Stuff/Github/test/node_modules/discord.js/src/util/SnowflakeUtil.js:63:25)
    at Message._patch (/Users/that_guy977/Desktop/Stuff/Github/test/node_modules/discord.js/src/structures/Message.js:62:43)
    at new Message (/Users/that_guy977/Desktop/Stuff/Github/test/node_modules/discord.js/src/structures/Message.js:48:10)
    at MessageManager._add (/Users/that_guy977/Desktop/Stuff/Github/test/node_modules/discord.js/src/managers/CachedManager.js:58:32)
    at MessageManager._add (/Users/that_guy977/Desktop/Stuff/Github/test/node_modules/discord.js/src/managers/MessageManager.js:31:18)
    at TextChannel.send (/Users/that_guy977/Desktop/Stuff/Github/test/node_modules/discord.js/src/structures/interfaces/TextBasedChannel.js:177:59)

Seems to occur with the other Util methods as well

Solved with 5dddd92

@iCrawl iCrawl merged commit c07207f into discordjs:main Dec 1, 2021
Koyamie added a commit to Koyamie/discord.js that referenced this pull request Dec 2, 2021
commit 01f8d1b
Author: Jiralite <33201955+Jiralite@users.noreply.github.com>
Date:   Thu Dec 2 13:29:54 2021 +0000

    types(Interaction): Narrow `memberPermissions` (discordjs#7054)

commit 5fcda73
Author: That_Guy977 <72870724+That-Guy977@users.noreply.github.com>
Date:   Thu Dec 2 20:29:21 2021 +0700

    fix(GuildChannel): default to `this.rawPosition` in `clone()` (discordjs#7057)

commit 552d89f
Author: Rodry <38259440+ImRodry@users.noreply.github.com>
Date:   Wed Dec 1 11:40:49 2021 +0000

    feat(Guild): add premiumProgressbarEnabled (discordjs#6887)

    Co-authored-by: Vlad Frangu <kingdgrizzle@gmail.com>

commit b183a8e
Author: Rodry <38259440+ImRodry@users.noreply.github.com>
Date:   Wed Dec 1 11:33:28 2021 +0000

    docs(Invite): add info blocks for missing props (discordjs#7014)

commit da86bd4
Author: Suneet Tipirneni <77477100+suneettipirneni@users.noreply.github.com>
Date:   Wed Dec 1 06:33:11 2021 -0500

    fix: Interaction channel type should be `GuildTextBasedChannels` when in guild (discordjs#6998)

commit c07207f
Author: That_Guy977 <72870724+That-Guy977@users.noreply.github.com>
Date:   Wed Dec 1 18:32:13 2021 +0700

    fix(Util): fix sorting for GuildChannels (discordjs#7002)

commit 4fe063f
Author: GrapeColor <40069549+GrapeColor@users.noreply.github.com>
Date:   Wed Dec 1 20:31:37 2021 +0900

    feat: add `UserContextMenuInteraction` and `MessageContextMenuInteraction` (discordjs#7003)

    Co-authored-by: Rodry <38259440+ImRodry@users.noreply.github.com>
    Co-authored-by: Suneet Tipirneni <77477100+suneettipirneni@users.noreply.github.com>
    Co-authored-by: Vlad Frangu <kingdgrizzle@gmail.com>
    Co-authored-by: GrapeColor <grapecolor@users.noreply.github.com>

commit a39d8c4
Author: Suneet Tipirneni <77477100+suneettipirneni@users.noreply.github.com>
Date:   Wed Dec 1 06:28:22 2021 -0500

    Revert "types(ApplicationCommandManager): Deprecate old `*Data` type …usages and allow camel cased dapi types to be used (discordjs#7052)

commit 85e6812
Author: Jiralite <33201955+Jiralite@users.noreply.github.com>
Date:   Wed Dec 1 11:27:24 2021 +0000

    docs(MessageReference): Fix static link (discordjs#7041)

commit e305156
Author: Suneet Tipirneni <77477100+suneettipirneni@users.noreply.github.com>
Date:   Mon Nov 29 13:32:26 2021 -0500

    chore: bump deps (discordjs#7048)

commit 374f970
Author: Antonio Román <kyradiscord@gmail.com>
Date:   Mon Nov 29 11:20:52 2021 +0100

    chore: add myself as contributor in package.json (discordjs#7037)

commit e59fac3
Author: Antonio Román <kyradiscord@gmail.com>
Date:   Mon Nov 29 11:20:18 2021 +0100

    refactor(SnowflakeUtil): clean up utils and improve perf (discordjs#7036)

commit fd63139
Author: Antonio Román <kyradiscord@gmail.com>
Date:   Mon Nov 29 11:19:32 2021 +0100

    fix(MessageManager): do not use `client.emojis` (discordjs#7039)

commit 0193efa
Author: Antonio Román <kyradiscord@gmail.com>
Date:   Mon Nov 29 11:19:21 2021 +0100

    fix(ActionsManager): revert to manual requires (discordjs#7034)

commit fabd343
Author: Antonio Román <kyradiscord@gmail.com>
Date:   Mon Nov 29 11:18:41 2021 +0100

    fix(MessagePayload): prevent spread of `undefined` (discordjs#7029)

commit 2c91c48
Author: Suneet Tipirneni <77477100+suneettipirneni@users.noreply.github.com>
Date:   Mon Nov 29 05:17:57 2021 -0500

    types(ApplicationCommandManager): Deprecate old `*Data` type usages and allow camel cased dapi types to be used (discordjs#6959)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

None yet

4 participants