first commit

This commit is contained in:
2026-03-10 16:18:05 +00:00
commit 11f9c069b5
31635 changed files with 3187747 additions and 0 deletions

View File

@@ -0,0 +1,15 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
type ErrorHandlerCallback = (error: any, isFatal?: boolean) => void;
export interface ErrorUtils {
setGlobalHandler: (callback: ErrorHandlerCallback) => void;
getGlobalHandler: () => ErrorHandlerCallback;
}

View File

@@ -0,0 +1,51 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @format
*/
// From @react-native/js-polyfills
type ErrorHandler = (error: mixed, isFatal: boolean) => void;
type Fn<Args: $ReadOnlyArray<mixed>, Return> = (...Args) => Return;
export type ErrorUtils = {
applyWithGuard<TArgs: $ReadOnlyArray<mixed>, TOut>(
fun: Fn<TArgs, TOut>,
context?: mixed,
args?: ?TArgs,
unused_onError?: null,
unused_name?: ?string,
): ?TOut,
applyWithGuardIfNeeded<TArgs: $ReadOnlyArray<mixed>, TOut>(
fun: Fn<TArgs, TOut>,
context?: mixed,
args?: ?TArgs,
): ?TOut,
getGlobalHandler(): ErrorHandler,
guard<TArgs: $ReadOnlyArray<mixed>, TOut>(
fun: Fn<TArgs, TOut>,
name?: ?string,
context?: mixed,
): ?(...TArgs) => ?TOut,
inGuard(): boolean,
reportError(error: mixed): void,
reportFatalError(error: mixed): void,
setGlobalHandler(fun: ErrorHandler): void,
};
/**
* The particular require runtime that we are using looks for a global
* `ErrorUtils` object and if it exists, then it requires modules with the
* error handler specified via ErrorUtils.setGlobalHandler by calling the
* require function with applyWithGuard. Since the require module is loaded
* before any of the modules, this ErrorUtils must be defined (and the handler
* set) globally before requiring anything.
*
* However, we still want to treat ErrorUtils as a module so that other modules
* that use it aren't just using a global variable, so simply export the global
* variable here. ErrorUtils is originally defined in a file named error-guard.js.
*/
export default global.ErrorUtils as ErrorUtils;

View File

@@ -0,0 +1,164 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
/**
* EventSubscription represents a subscription to a particular event. It can
* remove its own subscription.
*/
interface EventSubscription {
eventType: string;
key: number;
subscriber: EventSubscriptionVendor;
/**
* @param subscriber the subscriber that controls
* this subscription.
*/
new (subscriber: EventSubscriptionVendor): EventSubscription;
/**
* Removes this subscription from the subscriber that controls it.
*/
remove(): void;
}
/**
* EventSubscriptionVendor stores a set of EventSubscriptions that are
* subscribed to a particular event type.
*/
declare class EventSubscriptionVendor {
constructor();
/**
* Adds a subscription keyed by an event type.
*
*/
addSubscription(
eventType: string,
subscription: EventSubscription,
): EventSubscription;
/**
* Removes a bulk set of the subscriptions.
*
* @param eventType - Optional name of the event type whose
* registered subscriptions to remove, if null remove all subscriptions.
*/
removeAllSubscriptions(eventType?: string): void;
/**
* Removes a specific subscription. Instead of calling this function, call
* `subscription.remove()` directly.
*
*/
removeSubscription(subscription: any): void;
/**
* Returns the array of subscriptions that are currently registered for the
* given event type.
*
* Note: This array can be potentially sparse as subscriptions are deleted
* from it when they are removed.
*
*/
getSubscriptionsForType(eventType: string): EventSubscription[];
}
/**
* EmitterSubscription represents a subscription with listener and context data.
*/
interface EmitterSubscription extends EventSubscription {
emitter: EventEmitter;
listener: () => any;
context: any;
/**
* @param emitter - The event emitter that registered this
* subscription
* @param subscriber - The subscriber that controls
* this subscription
* @param listener - Function to invoke when the specified event is
* emitted
* @param context - Optional context object to use when invoking the
* listener
*/
new (
emitter: EventEmitter,
subscriber: EventSubscriptionVendor,
listener: () => any,
context: any,
): EmitterSubscription;
/**
* Removes this subscription from the emitter that registered it.
* Note: we're overriding the `remove()` method of EventSubscription here
* but deliberately not calling `super.remove()` as the responsibility
* for removing the subscription lies with the EventEmitter.
*/
remove(): void;
}
export default class EventEmitter {
/**
*
* @param subscriber - Optional subscriber instance
* to use. If omitted, a new subscriber will be created for the emitter.
*/
constructor(subscriber?: EventSubscriptionVendor | null);
/**
* Adds a listener to be invoked when events of the specified type are
* emitted. An optional calling context may be provided. The data arguments
* emitted will be passed to the listener function.
*
* @param eventType - Name of the event to listen to
* @param listener - Function to invoke when the specified event is
* emitted
* @param context - Optional context object to use when invoking the
* listener
*/
addListener(
eventType: string,
listener: (...args: any[]) => any,
context?: any,
): EmitterSubscription;
/**
* Removes all of the registered listeners, including those registered as
* listener maps.
*
* @param eventType - Optional name of the event whose registered
* listeners to remove
*/
removeAllListeners(eventType?: string): void;
/**
* Returns the number of listeners that are currently registered for the given
* event.
*
* @param eventType - Name of the event to query
*/
listenerCount(eventType: string): number;
/**
* Emits an event of the given type with the given data. All handlers of that
* particular type will be notified.
*
* @param eventType - Name of the event to emit
* @param Arbitrary arguments to be passed to each registered listener
*
* @example
* emitter.addListener('someEvent', function(message) {
* console.log(message);
* });
*
* emitter.emit('someEvent', 'abc'); // logs 'abc'
*/
emit(eventType: string, ...params: any[]): void;
}

View File

@@ -0,0 +1,174 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @format
*/
// $FlowFixMe[unclear-type] unclear type of events
type UnsafeEventObject = Object;
export interface EventSubscription {
remove(): void;
}
export interface IEventEmitter<
TEventToArgsMap: $ReadOnly<Record<string, $ReadOnlyArray<UnsafeEventObject>>>,
> {
addListener<TEvent: $Keys<TEventToArgsMap>>(
eventType: TEvent,
listener: (...args: TEventToArgsMap[TEvent]) => mixed,
context?: mixed,
): EventSubscription;
emit<TEvent: $Keys<TEventToArgsMap>>(
eventType: TEvent,
...args: TEventToArgsMap[TEvent]
): void;
removeAllListeners<TEvent: $Keys<TEventToArgsMap>>(eventType?: ?TEvent): void;
listenerCount<TEvent: $Keys<TEventToArgsMap>>(eventType: TEvent): number;
}
interface Registration<TArgs> {
+context: mixed;
+listener: (...args: TArgs) => mixed;
+remove: () => void;
}
type Registry<
TEventToArgsMap: $ReadOnly<Record<string, $ReadOnlyArray<UnsafeEventObject>>>,
> = {
[K in keyof TEventToArgsMap]: Set<Registration<TEventToArgsMap[K]>>,
};
/**
* EventEmitter manages listeners and publishes events to them.
*
* EventEmitter accepts a single type parameter that defines the valid events
* and associated listener argument(s).
*
* @example
*
* const emitter = new EventEmitter<{
* success: [number, string],
* error: [Error],
* }>();
*
* emitter.on('success', (statusCode, responseText) => {...});
* emitter.emit('success', 200, '...');
*
* emitter.on('error', error => {...});
* emitter.emit('error', new Error('Resource not found'));
*
*/
export default class EventEmitter<
TEventToArgsMap: $ReadOnly<
Record<string, $ReadOnlyArray<UnsafeEventObject>>,
> = $ReadOnly<Record<string, $ReadOnlyArray<UnsafeEventObject>>>,
> implements IEventEmitter<TEventToArgsMap>
{
#registry: Registry<TEventToArgsMap>;
constructor() {
// $FlowFixMe[incompatible-type]
this.#registry = {};
}
/**
* Registers a listener that is called when the supplied event is emitted.
* Returns a subscription that has a `remove` method to undo registration.
*/
addListener<TEvent: $Keys<TEventToArgsMap>>(
eventType: TEvent,
listener: (...args: TEventToArgsMap[TEvent]) => mixed,
context: mixed,
): EventSubscription {
if (typeof listener !== 'function') {
throw new TypeError(
'EventEmitter.addListener(...): 2nd argument must be a function.',
);
}
const registrations = allocate<
TEventToArgsMap,
$Keys<TEventToArgsMap>,
TEventToArgsMap[TEvent],
>(this.#registry, eventType);
const registration: Registration<TEventToArgsMap[TEvent]> = {
context,
listener,
remove(): void {
registrations.delete(registration);
},
};
registrations.add(registration);
return registration;
}
/**
* Emits the supplied event. Additional arguments supplied to `emit` will be
* passed through to each of the registered listeners.
*
* If a listener modifies the listeners registered for the same event, those
* changes will not be reflected in the current invocation of `emit`.
*/
emit<TEvent: $Keys<TEventToArgsMap>>(
eventType: TEvent,
...args: TEventToArgsMap[TEvent]
): void {
const registrations: ?Set<Registration<TEventToArgsMap[TEvent]>> =
this.#registry[eventType];
if (registrations != null) {
// Copy `registrations` to take a snapshot when we invoke `emit`, in case
// registrations are added or removed when listeners are invoked.
for (const registration of Array.from(registrations)) {
// $FlowFixMe[incompatible-type]
registration.listener.apply(registration.context, args);
}
}
}
/**
* Removes all registered listeners.
*/
removeAllListeners<TEvent: $Keys<TEventToArgsMap>>(
eventType?: ?TEvent,
): void {
if (eventType == null) {
// $FlowFixMe[incompatible-type]
this.#registry = {};
} else {
delete this.#registry[eventType];
}
}
/**
* Returns the number of registered listeners for the supplied event.
*/
listenerCount<TEvent: $Keys<TEventToArgsMap>>(eventType: TEvent): number {
const registrations: ?Set<Registration<TEventToArgsMap[TEvent]>> =
this.#registry[eventType];
return registrations == null ? 0 : registrations.size;
}
}
function allocate<
TEventToArgsMap: $ReadOnly<Record<string, $ReadOnlyArray<UnsafeEventObject>>>,
TEvent: $Keys<TEventToArgsMap>,
TEventArgs: TEventToArgsMap[TEvent],
>(
registry: Registry<TEventToArgsMap>,
eventType: TEvent,
): Set<Registration<TEventToArgsMap[TEvent]>> {
let registrations: ?Set<Registration<TEventToArgsMap[TEvent]>> =
registry[eventType];
if (registrations == null) {
registrations = new Set();
registry[eventType] = registrations;
}
return registrations;
}