UNPKG

react-native

Version:

A framework for building native apps using React

299 lines (246 loc) • 7.5 kB
/** * 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 */ /** * This module implements the `Event` interface from the DOM. * See https://dom.spec.whatwg.org/#interface-event. */ // flowlint unsafe-getters-setters:off import type EventTarget from './EventTarget'; import {setPlatformObject} from '../../webidl/PlatformObjects'; import { COMPOSED_PATH_KEY, CURRENT_TARGET_KEY, EVENT_INIT_TIMESTAMP_KEY, EVENT_PHASE_KEY, IN_PASSIVE_LISTENER_FLAG_KEY, IS_TRUSTED_KEY, STOP_IMMEDIATE_PROPAGATION_FLAG_KEY, STOP_PROPAGATION_FLAG_KEY, TARGET_KEY, getComposedPath, getCurrentTarget, getEventPhase, getInPassiveListenerFlag, getIsTrusted, getStopPropagationFlag, getTarget, setStopImmediatePropagationFlag, setStopPropagationFlag, } from './internals/EventInternals'; export interface EventInit { readonly bubbles?: boolean; readonly cancelable?: boolean; readonly composed?: boolean; // React Native-specific. When true, the event is a "direct" event: it is // dispatched only to the target node (single AT_TARGET phase) and never // captures or bubbles through ancestors. A direct event must not bubble, so // `bubbles` cannot also be true. readonly rnIsDirect?: boolean; } export default class Event { static readonly NONE: 0; static readonly CAPTURING_PHASE: 1; static readonly AT_TARGET: 2; static readonly BUBBLING_PHASE: 3; readonly NONE: 0; readonly CAPTURING_PHASE: 1; readonly AT_TARGET: 2; readonly BUBBLING_PHASE: 3; _bubbles: boolean; _cancelable: boolean; _composed: boolean; _rnIsDirect: boolean; _type: string; _defaultPrevented: boolean = false; _timeStamp: number; // $FlowExpectedError[unsupported-syntax] // $FlowFixMe[illegal-key] [COMPOSED_PATH_KEY]: boolean = []; // $FlowExpectedError[unsupported-syntax] // $FlowFixMe[illegal-key] [CURRENT_TARGET_KEY]: EventTarget | null = null; // $FlowExpectedError[unsupported-syntax] // $FlowFixMe[illegal-key] [EVENT_PHASE_KEY]: boolean = Event.NONE; // $FlowExpectedError[unsupported-syntax] // $FlowFixMe[illegal-key] [IN_PASSIVE_LISTENER_FLAG_KEY]: boolean = false; // $FlowExpectedError[unsupported-syntax] // $FlowFixMe[illegal-key] [IS_TRUSTED_KEY]: boolean = false; // $FlowExpectedError[unsupported-syntax] // $FlowFixMe[illegal-key] [STOP_IMMEDIATE_PROPAGATION_FLAG_KEY]: boolean = false; // $FlowExpectedError[unsupported-syntax] // $FlowFixMe[illegal-key] [STOP_PROPAGATION_FLAG_KEY]: boolean = false; // $FlowExpectedError[unsupported-syntax] // $FlowFixMe[illegal-key] [TARGET_KEY]: EventTarget | null = null; constructor(type: string, options?: ?EventInit) { if (arguments.length < 1) { throw new TypeError( "Failed to construct 'Event': 1 argument required, but only 0 present.", ); } const typeOfOptions = typeof options; if ( options != null && typeOfOptions !== 'object' && typeOfOptions !== 'function' ) { throw new TypeError( "Failed to construct 'Event': The provided value is not of type 'EventInit'.", ); } this._type = String(type); this._bubbles = Boolean(options?.bubbles); this._cancelable = Boolean(options?.cancelable); this._composed = Boolean(options?.composed); this._rnIsDirect = Boolean(options?.rnIsDirect); // A direct event is dispatched only to its target and never propagates, so // it cannot bubble. Reject the contradictory combination at construction // time. if (this._rnIsDirect && this._bubbles) { throw new TypeError( "Failed to construct 'Event': 'rnIsDirect' cannot be true when 'bubbles' is also true.", ); } // For internal construction of events using a custom timestamp (instead of // event object creation), for use cases like dispatching events from the // host platform using the original timestamps. // $FlowExpectedError[prop-missing] const initTimestamp: number | void = options?.[EVENT_INIT_TIMESTAMP_KEY]; this._timeStamp = initTimestamp !== undefined ? initTimestamp : performance.now(); } get bubbles(): boolean { return this._bubbles; } get cancelable(): boolean { return this._cancelable; } /** * Historical alias for the stop-propagation flag. Reading it returns whether * `stopPropagation()` has been called (or `cancelBubble` has been set to * `true`). Setting it to `true` stops propagation; setting it to `false` is a * no-op. See https://dom.spec.whatwg.org/#dom-event-cancelbubble. */ get cancelBubble(): boolean { return getStopPropagationFlag(this); } set cancelBubble(value: boolean) { if (value) { setStopPropagationFlag(this, true); } } get composed(): boolean { return this._composed; } /** * React Native-specific. When true, this event is dispatched only to its * target (single `AT_TARGET` phase) and never captures or bubbles through * ancestors. */ get rnIsDirect(): boolean { return this._rnIsDirect; } get currentTarget(): EventTarget | null { return getCurrentTarget(this); } get defaultPrevented(): boolean { return this._defaultPrevented; } get eventPhase(): EventPhase { return getEventPhase(this); } get isTrusted(): boolean { return getIsTrusted(this); } get target(): EventTarget | null { return getTarget(this); } get timeStamp(): number { return this._timeStamp; } get type(): string { return this._type; } composedPath(): ReadonlyArray<EventTarget> { return getComposedPath(this).slice(); } preventDefault(): void { if (!this._cancelable) { return; } if (getInPassiveListenerFlag(this)) { console.error( new Error( 'Unable to preventDefault inside passive event listener invocation.', ), ); return; } this._defaultPrevented = true; } stopImmediatePropagation(): void { setStopPropagationFlag(this, true); setStopImmediatePropagationFlag(this, true); } stopPropagation(): void { setStopPropagationFlag(this, true); } } // $FlowExpectedError[cannot-write] Object.defineProperty(Event, 'NONE', { enumerable: true, value: 0, }); // $FlowExpectedError[cannot-write] Object.defineProperty(Event.prototype, 'NONE', { enumerable: true, value: 0, }); // $FlowExpectedError[cannot-write] Object.defineProperty(Event, 'CAPTURING_PHASE', { enumerable: true, value: 1, }); // $FlowExpectedError[cannot-write] Object.defineProperty(Event.prototype, 'CAPTURING_PHASE', { enumerable: true, value: 1, }); // $FlowExpectedError[cannot-write] Object.defineProperty(Event, 'AT_TARGET', { enumerable: true, value: 2, }); // $FlowExpectedError[cannot-write] Object.defineProperty(Event.prototype, 'AT_TARGET', { enumerable: true, value: 2, }); // $FlowExpectedError[cannot-write] Object.defineProperty(Event, 'BUBBLING_PHASE', { enumerable: true, value: 3, }); // $FlowExpectedError[cannot-write] Object.defineProperty(Event.prototype, 'BUBBLING_PHASE', { enumerable: true, value: 3, }); export type EventPhase = | (typeof Event)['NONE'] | (typeof Event)['CAPTURING_PHASE'] | (typeof Event)['AT_TARGET'] | (typeof Event)['BUBBLING_PHASE']; setPlatformObject(Event);