Skip to content

Commit 72434a7

Browse files
authored
Remove or inline some fbjs dependencies (facebook#13046)
1 parent 64c54ed commit 72434a7

19 files changed

+236
-50
lines changed

packages/react-dom/src/client/ReactDOM.js

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import './ReactDOMClientInjection';
2121

2222
import * as DOMRenderer from 'react-reconciler/inline.dom';
2323
import * as ReactPortal from 'shared/ReactPortal';
24-
import ExecutionEnvironment from 'fbjs/lib/ExecutionEnvironment';
24+
import {canUseDOM} from 'shared/ExecutionEnvironment';
2525
import * as ReactGenericBatching from 'events/ReactGenericBatching';
2626
import * as ReactControlledComponent from 'events/ReactControlledComponent';
2727
import * as EventPluginHub from 'events/EventPluginHub';
@@ -768,11 +768,7 @@ const foundDevTools = DOMRenderer.injectIntoDevTools({
768768
});
769769

770770
if (__DEV__) {
771-
if (
772-
!foundDevTools &&
773-
ExecutionEnvironment.canUseDOM &&
774-
window.top === window.self
775-
) {
771+
if (!foundDevTools && canUseDOM && window.top === window.self) {
776772
// If we're in Chrome or Firefox, provide a download link if not installed.
777773
if (
778774
(navigator.userAgent.indexOf('Chrome') > -1 &&

packages/react-dom/src/client/ReactInputSelection.js

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,48 @@
55
* LICENSE file in the root directory of this source tree.
66
*/
77

8-
import containsNode from 'fbjs/lib/containsNode';
9-
import getActiveElement from 'fbjs/lib/getActiveElement';
8+
import getActiveElement from './getActiveElement';
109

1110
import * as ReactDOMSelection from './ReactDOMSelection';
12-
import {ELEMENT_NODE} from '../shared/HTMLNodeType';
11+
import {ELEMENT_NODE, TEXT_NODE} from '../shared/HTMLNodeType';
12+
13+
// TODO: this code is originally inlined from fbjs.
14+
// It is likely that we don't actually need all these checks
15+
// for the particular use case in this file.
16+
function isNode(object) {
17+
const doc = object ? object.ownerDocument || object : document;
18+
const defaultView = doc.defaultView || window;
19+
return !!(
20+
object &&
21+
(typeof defaultView.Node === 'function'
22+
? object instanceof defaultView.Node
23+
: typeof object === 'object' &&
24+
typeof object.nodeType === 'number' &&
25+
typeof object.nodeName === 'string')
26+
);
27+
}
28+
29+
function isTextNode(object) {
30+
return isNode(object) && object.nodeType === TEXT_NODE;
31+
}
32+
33+
function containsNode(outerNode, innerNode) {
34+
if (!outerNode || !innerNode) {
35+
return false;
36+
} else if (outerNode === innerNode) {
37+
return true;
38+
} else if (isTextNode(outerNode)) {
39+
return false;
40+
} else if (isTextNode(innerNode)) {
41+
return containsNode(outerNode, innerNode.parentNode);
42+
} else if ('contains' in outerNode) {
43+
return outerNode.contains(innerNode);
44+
} else if (outerNode.compareDocumentPosition) {
45+
return !!(outerNode.compareDocumentPosition(innerNode) & 16);
46+
} else {
47+
return false;
48+
}
49+
}
1350

1451
function isInDocument(node) {
1552
return containsNode(document.documentElement, node);
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/**
2+
* Copyright (c) 2015-present, Facebook, Inc.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*
7+
* @flow
8+
*/
9+
10+
export default function getActiveElement(doc: ?Document): ?Element {
11+
doc = doc || (typeof document !== 'undefined' ? document : undefined);
12+
if (typeof doc === 'undefined') {
13+
return null;
14+
}
15+
try {
16+
return doc.activeElement || doc.body;
17+
} catch (e) {
18+
return doc.body;
19+
}
20+
}

packages/react-dom/src/client/getTextContentAccessor.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* LICENSE file in the root directory of this source tree.
66
*/
77

8-
import ExecutionEnvironment from 'fbjs/lib/ExecutionEnvironment';
8+
import {canUseDOM} from 'shared/ExecutionEnvironment';
99

1010
let contentKey = null;
1111

@@ -16,7 +16,7 @@ let contentKey = null;
1616
* @internal
1717
*/
1818
function getTextContentAccessor() {
19-
if (!contentKey && ExecutionEnvironment.canUseDOM) {
19+
if (!contentKey && canUseDOM) {
2020
// Prefer textContent to innerText because many browsers support both but
2121
// SVG <text> elements don't support innerText even when <div> does.
2222
contentKey =

packages/react-dom/src/events/BeforeInputEventPlugin.js

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import type {TopLevelType} from 'events/TopLevelEventTypes';
99

1010
import {accumulateTwoPhaseDispatches} from 'events/EventPropagators';
11-
import ExecutionEnvironment from 'fbjs/lib/ExecutionEnvironment';
11+
import {canUseDOM} from 'shared/ExecutionEnvironment';
1212

1313
import {
1414
TOP_BLUR,
@@ -29,25 +29,24 @@ import SyntheticInputEvent from './SyntheticInputEvent';
2929
const END_KEYCODES = [9, 13, 27, 32]; // Tab, Return, Esc, Space
3030
const START_KEYCODE = 229;
3131

32-
const canUseCompositionEvent =
33-
ExecutionEnvironment.canUseDOM && 'CompositionEvent' in window;
32+
const canUseCompositionEvent = canUseDOM && 'CompositionEvent' in window;
3433

3534
let documentMode = null;
36-
if (ExecutionEnvironment.canUseDOM && 'documentMode' in document) {
35+
if (canUseDOM && 'documentMode' in document) {
3736
documentMode = document.documentMode;
3837
}
3938

4039
// Webkit offers a very useful `textInput` event that can be used to
4140
// directly represent `beforeInput`. The IE `textinput` event is not as
4241
// useful, so we don't use it.
4342
const canUseTextInputEvent =
44-
ExecutionEnvironment.canUseDOM && 'TextEvent' in window && !documentMode;
43+
canUseDOM && 'TextEvent' in window && !documentMode;
4544

4645
// In IE9+, we have access to composition events, but the data supplied
4746
// by the native compositionend event may be incorrect. Japanese ideographic
4847
// spaces, for instance (\u3000) are not recorded correctly.
4948
const useFallbackCompositionData =
50-
ExecutionEnvironment.canUseDOM &&
49+
canUseDOM &&
5150
(!canUseCompositionEvent ||
5251
(documentMode && documentMode > 8 && documentMode <= 11));
5352

packages/react-dom/src/events/ChangeEventPlugin.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {enqueueStateRestore} from 'events/ReactControlledComponent';
1111
import {batchedUpdates} from 'events/ReactGenericBatching';
1212
import SyntheticEvent from 'events/SyntheticEvent';
1313
import isTextInputElement from 'shared/isTextInputElement';
14-
import ExecutionEnvironment from 'fbjs/lib/ExecutionEnvironment';
14+
import {canUseDOM} from 'shared/ExecutionEnvironment';
1515

1616
import {
1717
TOP_BLUR,
@@ -119,7 +119,7 @@ function getTargetInstForChangeEvent(topLevelType, targetInst) {
119119
* SECTION: handle `input` event
120120
*/
121121
let isInputEventSupported = false;
122-
if (ExecutionEnvironment.canUseDOM) {
122+
if (canUseDOM) {
123123
// IE9 claims to support the input event but fails to trigger it when
124124
// deleting text, so we ignore its input events.
125125
isInputEventSupported =

packages/react-dom/src/events/SelectEventPlugin.js

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,10 @@
66
*/
77

88
import {accumulateTwoPhaseDispatches} from 'events/EventPropagators';
9-
import ExecutionEnvironment from 'fbjs/lib/ExecutionEnvironment';
9+
import {canUseDOM} from 'shared/ExecutionEnvironment';
1010
import SyntheticEvent from 'events/SyntheticEvent';
1111
import isTextInputElement from 'shared/isTextInputElement';
12-
import getActiveElement from 'fbjs/lib/getActiveElement';
13-
import shallowEqual from 'fbjs/lib/shallowEqual';
12+
import shallowEqual from 'shared/shallowEqual';
1413

1514
import {
1615
TOP_BLUR,
@@ -23,14 +22,13 @@ import {
2322
TOP_SELECTION_CHANGE,
2423
} from './DOMTopLevelEventTypes';
2524
import {isListeningToAllDependencies} from './ReactBrowserEventEmitter';
25+
import getActiveElement from '../client/getActiveElement';
2626
import {getNodeFromInstance} from '../client/ReactDOMComponentTree';
2727
import * as ReactInputSelection from '../client/ReactInputSelection';
2828
import {DOCUMENT_NODE} from '../shared/HTMLNodeType';
2929

3030
const skipSelectionChangeEvent =
31-
ExecutionEnvironment.canUseDOM &&
32-
'documentMode' in document &&
33-
document.documentMode <= 11;
31+
canUseDOM && 'documentMode' in document && document.documentMode <= 11;
3432

3533
const eventTypes = {
3634
select: {

packages/react-dom/src/events/TapEventPlugin.js

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
*/
99

1010
import {accumulateTwoPhaseDispatches} from 'events/EventPropagators';
11-
import TouchEventUtils from 'fbjs/lib/TouchEventUtils';
1211
import type {TopLevelType} from 'events/TopLevelEventTypes';
1312

1413
import {
@@ -85,11 +84,24 @@ const Axis: AxisType = {
8584
y: {page: 'pageY', client: 'clientY', envScroll: 'currentPageScrollTop'},
8685
};
8786

87+
function extractSingleTouch(nativeEvent) {
88+
// $FlowFixMe: figure out why this is missing
89+
const touches = nativeEvent.touches;
90+
// $FlowFixMe: figure out why this is missing
91+
const changedTouches = nativeEvent.changedTouches;
92+
const hasTouches = touches && touches.length > 0;
93+
const hasChangedTouches = changedTouches && changedTouches.length > 0;
94+
95+
return !hasTouches && hasChangedTouches
96+
? changedTouches[0]
97+
: hasTouches ? touches[0] : nativeEvent;
98+
}
99+
88100
function getAxisCoordOfEvent(
89101
axis: AxisCoordinateData,
90102
nativeEvent: _Touch,
91103
): number {
92-
const singleTouch = TouchEventUtils.extractSingleTouch(nativeEvent);
104+
const singleTouch = extractSingleTouch(nativeEvent);
93105
if (singleTouch) {
94106
return singleTouch[axis.page];
95107
}

packages/react-dom/src/events/getVendorPrefixedEventName.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* LICENSE file in the root directory of this source tree.
66
*/
77

8-
import ExecutionEnvironment from 'fbjs/lib/ExecutionEnvironment';
8+
import {canUseDOM} from 'shared/ExecutionEnvironment';
99

1010
/**
1111
* Generate a mapping of standard vendor prefixes using the defined style property and event name.
@@ -49,7 +49,7 @@ let style = {};
4949
/**
5050
* Bootstrap if a DOM exists.
5151
*/
52-
if (ExecutionEnvironment.canUseDOM) {
52+
if (canUseDOM) {
5353
style = document.createElement('div').style;
5454

5555
// On some platforms, in particular some releases of Android 4.x,

packages/react-dom/src/events/isEventSupported.js

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* LICENSE file in the root directory of this source tree.
66
*/
77

8-
import ExecutionEnvironment from 'fbjs/lib/ExecutionEnvironment';
8+
import {canUseDOM} from 'shared/ExecutionEnvironment';
99

1010
/**
1111
* Checks if an event is supported in the current execution environment.
@@ -22,10 +22,7 @@ import ExecutionEnvironment from 'fbjs/lib/ExecutionEnvironment';
2222
* @license Modernizr 3.0.0pre (Custom Build) | MIT
2323
*/
2424
function isEventSupported(eventNameSuffix, capture) {
25-
if (
26-
!ExecutionEnvironment.canUseDOM ||
27-
(capture && !('addEventListener' in document))
28-
) {
25+
if (!canUseDOM || (capture && !('addEventListener' in document))) {
2926
return false;
3027
}
3128

0 commit comments

Comments
 (0)