Repository: discordjs/discord.js
File: packages/discord.js/src/structures/Message.js (JavaScript)

Code before:
    return (
      (this.inGuild() &&
        Date.now() - this.createdTimestamp < MaxBulkDeletableMessageAge &&
        this.deletable &&
        this.channel?.permissionsFor(this.client.user).has(PermissionFlagsBits.ManageMessages, false)) ??
      false
    );
  }

  /**
   * Whether the message is pinnable by the client user
   *
   * @type {boolean}
   * @readonly
   */
  get pinnable() {
    const { channel } = this;

    if (this.system) return false;
    if (!this.guild) return true;
    if (!channel?.viewable) return false;

    const permissions = channel?.permissionsFor(this.client.user);
    if (!permissions) return false;

    return permissions.has([PermissionFlagsBits.ReadMessageHistory, PermissionFlagsBits.PinMessages]);
  }

  /**
   * Fetches the Message this crosspost/reply/pin-add references, if available to the client
   *
   * @returns {Promise<Message>}
   */
  async fetchReference() {
    if (!this.reference) throw new DiscordjsError(ErrorCodes.MessageReferenceMissing);
    const { channelId, messageId } = this.reference;
    if (!messageId) throw new DiscordjsError(ErrorCodes.MessageReferenceMissing);
    const channel = this.client.channels.resolve(channelId);
    if (!channel) throw new DiscordjsError(ErrorCodes.GuildChannelResolve);
    return channel.messages.fetch(messageId);
  }

  /**
   * Whether the message is crosspostable by the client user
   *
   * @type {boolean}
   * @readonly
   */
  get crosspostable() {
    const bitfield =
      PermissionFlagsBits.SendMessages |

Review comment (security):
Code path terminates quicker if you do this:

```suggestion
    return permissions.has(PermissionFlagsBits.ReadMessageHistory | PermissionFlagsBits.PinMessages);
```

Array is passed to here:

https://github.com/discordjs/discord.js/blob/ee3be2c3c3b7b79e41b84cc416e25cf9a9a48d53/packages/discord.js/src/util/PermissionsBitField.js#L96-L105

https://github.com/discordjs/discord.js/blob/ee3be2c3c3b7b79e41b84cc416e25cf9a9a48d53/packages/discord.js/src/util/BitField.js#L59-L68

When resolving, `PermissionFlagsBits.ReadMessageHistory | PermissionFlagsBits.PinMessages` will return straight away on line 182:

https://github.com/discordjs/discord.js/blob/ee3be2c3c3b7b79e41b84cc416e25cf9a9a48d53/packages/discord.js/src/util/BitField.js#L174-L194

Passing an array means it will resolve twice in line 185, then map it, then reduce it.

Code after:
    return (
      (this.inGuild() &&
        Date.now() - this.createdTimestamp < MaxBulkDeletableMessageAge &&
        this.deletable &&
        this.channel?.permissionsFor(this.client.user).has(PermissionFlagsBits.ManageMessages, false)) ??
      false
    );
  }

  /**
   * Whether the message is pinnable by the client user
   *
   * @type {boolean}
   * @readonly
   */
  get pinnable() {
    const { channel } = this;

    if (this.system) return false;
    if (!this.guild) return true;
    if (!channel || channel.isVoiceBased() || !channel.viewable) return false;

    const permissions = channel.permissionsFor(this.client.user);
    if (!permissions) return false;

    return permissions.has(PermissionFlagsBits.ReadMessageHistory | PermissionFlagsBits.PinMessages);
  }

  /**
   * Fetches the Message this crosspost/reply/pin-add references, if available to the client
   *
   * @returns {Promise<Message>}
   */
  async fetchReference() {
    if (!this.reference) throw new DiscordjsError(ErrorCodes.MessageReferenceMissing);
    const { channelId, messageId } = this.reference;
    if (!messageId) throw new DiscordjsError(ErrorCodes.MessageReferenceMissing);
    const channel = this.client.channels.resolve(channelId);
    if (!channel) throw new DiscordjsError(ErrorCodes.GuildChannelResolve);
    return channel.messages.fetch(messageId);
  }

  /**
   * Whether the message is crosspostable by the client user
   *
   * @type {boolean}
   * @readonly
   */
  get crosspostable() {
    const bitfield =
      PermissionFlagsBits.SendMessages |