snapshot of https://github.com/RocketChat/Rocket.Chat.git (develop, 2026-09-16; blobs > 131072B omitted)
Some checks failed
Create issues from TODOs / todos (push) Failing after 3s
Close inactive issues / close-issues (push) Has been cancelled
Deploy GitHub Pages / deploy-preview (push) Has been cancelled
CI / ⚙️ Variables Setup (push) Has been cancelled
CI / ⚙️ Test Guard (push) Has been cancelled
CI / 🚀 Notify external services - draft (push) Has been cancelled
CI / 📦 Build Packages (push) Has been cancelled
CI / 📦 Meteor Build (coverage) (push) Has been cancelled
CI / 📦 Meteor Build (production) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], fips) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Publish Docker Images (ghcr.io) (push) Has been cancelled
CI / 📦 Track Image Sizes (push) Has been cancelled
CI / 🔎 Code Check - Action Lint (push) Has been cancelled
CI / 🔎 Code Check (push) Has been cancelled
CI / 🔨 Test Storybook (push) Has been cancelled
CI / 🔨 Test Unit (push) Has been cancelled
CI / 🔨 Test API (CE) (push) Has been cancelled
CI / 🔨 Test API Livechat (CE) (push) Has been cancelled
CI / 🔨 Test UI (CE) (push) Has been cancelled
CI / 🔨 Test API (EE) (push) Has been cancelled
CI / 🔨 Test API Livechat (EE) (push) Has been cancelled
CI / 🔨 Test API Apps (deno-runtime - EE) (push) Has been cancelled
CI / 🔨 Test UI (EE) (push) Has been cancelled
CI / 🔨 Test API (FIPS) (push) Has been cancelled
CI / 🔨 Test API Livechat (FIPS) (push) Has been cancelled
CI / 🔨 Test UI (FIPS) (push) Has been cancelled
CI / 🔨 Test Federation Matrix (push) Has been cancelled
CI / 📊 Report Coverage (push) Has been cancelled
CI / ✅ Tests Done (push) Has been cancelled
CI / 🚀 Publish build assets (push) Has been cancelled
CI / 🚀 Publish Docker Images (DockerHub) (push) Has been cancelled
CI / 🚀 Notify external services (push) Has been cancelled
CI / Update Version Durability (push) Has been cancelled
Release / Release (push) Has been cancelled
Auto-close duplicate issues / auto-close-duplicates (push) Failing after 1s
Code scanning - action / CodeQL-Build (push) Failing after 1s

This commit is contained in:
upstream-mirror
2026-09-16 01:21:02 +05:00
commit 30810eecd7
10161 changed files with 987110 additions and 0 deletions

View File

@@ -0,0 +1,237 @@
import type { AnyNode, AssignmentExpression, Function, AwaitExpression, Expression, Identifier, MethodDefinition, Property } from 'acorn';
import type { FullAncestorWalkerCallback } from 'acorn-walk';
export type WalkerState = {
isModified: boolean;
functionIdentifiers: Set<string>;
};
export function getFunctionIdentifier(ancestors: AnyNode[], functionNodeIndex: number) {
const parent = ancestors[functionNodeIndex - 1];
// If there is a parent node and it's not a computed property, we can try to
// extract an identifier for our function from it. This needs to be done first
// because when functions are assigned to named symbols, this will be the only
// way to call it, even if the function itself has an identifier
// Consider the following block:
//
// const foo = function bar() {}
//
// Even though the function itself has a name, the only way to call it in the
// program is wiht `foo()`
if (parent && !(parent as Property | MethodDefinition).computed) {
// Several node types can have an id prop of type Identifier
const { id } = parent as unknown as { id?: Identifier };
if (id?.type === 'Identifier') {
return id.name;
}
// Usually assignments to object properties (MethodDefinition, Property)
const { key } = parent as MethodDefinition | Property;
if (key?.type === 'Identifier') {
return key.name;
}
// Variable assignments have left hand side that can be used as Identifier
const { left } = parent as AssignmentExpression;
// Simple assignment: `const fn = () => {}`
if (left?.type === 'Identifier') {
return left.name;
}
// Object property assignment: `obj.fn = () => {}`
if (left?.type === 'MemberExpression' && !left.computed) {
return (left.property as Identifier).name;
}
}
// nodeIndex needs to be the index of a Function node (either FunctionDeclaration or FunctionExpression)
const currentNode = ancestors[functionNodeIndex] as Function;
// Function declarations or expressions can be directly named
if (currentNode.id?.type === 'Identifier') {
return currentNode.id.name;
}
}
export function wrapWithAwait(node: Expression) {
if (!node.type.endsWith('Expression')) {
throw new Error(`Can't wrap "${node.type}" with await`);
}
const innerNode: Expression = { ...node };
node.type = 'AwaitExpression';
// starting here node has become an AwaitExpression
(node as AwaitExpression).argument = innerNode;
Object.keys(node).forEach((key) => !['type', 'argument'].includes(key) && delete node[key as keyof AnyNode]);
}
export function asyncifyScope(ancestors: AnyNode[], state: WalkerState) {
const functionNodeIndex = ancestors.findLastIndex((n) => 'async' in n);
if (functionNodeIndex === -1) return;
// At this point this is a node with an "async" property, so it has to be
// of type Function - let TS know about that
const functionScopeNode = ancestors[functionNodeIndex] as Function;
if (functionScopeNode.async) {
return;
}
functionScopeNode.async = true;
// If the parent of a function node is a call expression, we're talking about an IIFE
// Should we care about this case as well?
// const parentNode = ancestors[functionScopeIndex-1];
// if (parentNode?.type === 'CallExpression' && ancestors[functionScopeIndex-2] && ancestors[functionScopeIndex-2].type !== 'AwaitExpression') {
// pendingOperations.push(buildFunctionPredicate(getFunctionIdentifier(ancestors, functionScopeIndex-2)));
// }
const identifier = getFunctionIdentifier(ancestors, functionNodeIndex);
// We can't fix calls of functions which name we can't determine at compile time
if (!identifier) return;
state.functionIdentifiers.add(identifier);
}
export function buildFixModifiedFunctionsOperation(functionIdentifiers: Set<string>): FullAncestorWalkerCallback<WalkerState> {
return function _fixModifiedFunctionsOperation(node, state, ancestors) {
if (node.type !== 'CallExpression') return;
// This node is a simple call to a function, like `fn()`
let isWrappable = node.callee.type === 'Identifier' && functionIdentifiers.has(node.callee.name);
// This node is a call to an object property or instance method, like `obj.fn()`, but not computed like `obj[fn]()`
isWrappable ||=
node.callee.type === 'MemberExpression' &&
!node.callee.computed &&
node.callee.property?.type === 'Identifier' &&
functionIdentifiers.has(node.callee.property.name);
// This is a weird dereferencing technique used by bundlers, and since we'll be dealing with bundled sources we have to check for it
// e.g. `r=(0,fn)(e)`
if (!isWrappable && node.callee.type === 'SequenceExpression') {
const [, secondExpression] = node.callee.expressions;
isWrappable = secondExpression?.type === 'Identifier' && functionIdentifiers.has(secondExpression.name);
isWrappable ||=
secondExpression?.type === 'MemberExpression' &&
!secondExpression.computed &&
secondExpression.property.type === 'Identifier' &&
functionIdentifiers.has(secondExpression.property.name);
}
if (!isWrappable) return;
// ancestors[ancestors.length-1] === node, so here we're checking for parent node
const parentNode = ancestors[ancestors.length - 2];
if (!parentNode || parentNode.type === 'AwaitExpression') return;
wrapWithAwait(node);
asyncifyScope(ancestors, state);
state.isModified = true;
};
}
export const checkReassignmentOfModifiedIdentifiers: FullAncestorWalkerCallback<WalkerState> = (
node,
{ functionIdentifiers },
_ancestors,
) => {
if (node.type === 'AssignmentExpression') {
if (node.operator !== '=') return;
let identifier = '';
if (node.left.type === 'Identifier') identifier = node.left.name;
if (node.left.type === 'MemberExpression' && !node.left.computed) {
identifier = (node.left.property as Identifier).name;
}
if (!identifier || node.right.type !== 'Identifier' || !functionIdentifiers.has(node.right.name)) return;
functionIdentifiers.add(identifier);
return;
}
if (node.type === 'VariableDeclarator') {
if (node.id.type !== 'Identifier' || functionIdentifiers.has(node.id.name)) return;
if (node.init?.type !== 'Identifier' || !functionIdentifiers.has(node.init?.name)) return;
functionIdentifiers.add(node.id.name);
return;
}
// "Property" is for plain objects, "PropertyDefinition" is for classes
// but both share the same structure
if (node.type === 'Property' || node.type === 'PropertyDefinition') {
if (node.key.type !== 'Identifier' || functionIdentifiers.has(node.key.name)) return;
if (node.value?.type !== 'Identifier' || !functionIdentifiers.has(node.value.name)) return;
functionIdentifiers.add(node.key.name);
}
};
export const fixLivechatIsOnlineCalls: FullAncestorWalkerCallback<WalkerState> = (node, state, ancestors) => {
if (node.type !== 'MemberExpression' || node.computed) return;
if ((node.property as Identifier).name !== 'isOnline') return;
if (node.object.type !== 'CallExpression') return;
if (node.object.callee.type !== 'MemberExpression') return;
if ((node.object.callee.property as Identifier).name !== 'getLivechatReader') return;
let parentIndex = ancestors.length - 2;
let targetNode = ancestors[parentIndex];
if (targetNode.type !== 'CallExpression') {
targetNode = node;
} else {
parentIndex--;
}
// If we're already wrapped with an await, nothing to do
if (ancestors[parentIndex].type === 'AwaitExpression') return;
// If we're in the middle of a chained member access, we can't wrap with await
if (ancestors[parentIndex].type === 'MemberExpression') return;
wrapWithAwait(targetNode);
asyncifyScope(ancestors, state);
state.isModified = true;
};
export const fixRoomUsernamesCalls: FullAncestorWalkerCallback<WalkerState> = (node, state, ancestors) => {
if (node.type !== 'MemberExpression' || node.computed) return;
if ((node.property as Identifier).name !== 'usernames') return;
let parentIndex = ancestors.length - 2;
let targetNode = ancestors[parentIndex];
if (targetNode.type !== 'CallExpression') {
targetNode = node;
} else {
parentIndex--;
}
// If we're already wrapped with an await, nothing to do
if (ancestors[parentIndex].type === 'AwaitExpression') return;
wrapWithAwait(targetNode);
asyncifyScope(ancestors, state);
state.isModified = true;
};