1 | /**
|
2 | * Copyright (c) 2013-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 | */
|
8 |
|
9 | ;
|
10 |
|
11 | var _assign = require('object-assign');
|
12 |
|
13 | var CallbackQueue = require('./CallbackQueue');
|
14 | var PooledClass = require('./PooledClass');
|
15 | var ReactBrowserEventEmitter = require('./ReactBrowserEventEmitter');
|
16 | var ReactInputSelection = require('./ReactInputSelection');
|
17 | var ReactInstrumentation = require('./ReactInstrumentation');
|
18 | var Transaction = require('./Transaction');
|
19 | var ReactUpdateQueue = require('./ReactUpdateQueue');
|
20 |
|
21 | /**
|
22 | * Ensures that, when possible, the selection range (currently selected text
|
23 | * input) is not disturbed by performing the transaction.
|
24 | */
|
25 | var SELECTION_RESTORATION = {
|
26 | /**
|
27 | * @return {Selection} Selection information.
|
28 | */
|
29 | initialize: ReactInputSelection.getSelectionInformation,
|
30 | /**
|
31 | * @param {Selection} sel Selection information returned from `initialize`.
|
32 | */
|
33 | close: ReactInputSelection.restoreSelection
|
34 | };
|
35 |
|
36 | /**
|
37 | * Suppresses events (blur/focus) that could be inadvertently dispatched due to
|
38 | * high level DOM manipulations (like temporarily removing a text input from the
|
39 | * DOM).
|
40 | */
|
41 | var EVENT_SUPPRESSION = {
|
42 | /**
|
43 | * @return {boolean} The enabled status of `ReactBrowserEventEmitter` before
|
44 | * the reconciliation.
|
45 | */
|
46 | initialize: function () {
|
47 | var currentlyEnabled = ReactBrowserEventEmitter.isEnabled();
|
48 | ReactBrowserEventEmitter.setEnabled(false);
|
49 | return currentlyEnabled;
|
50 | },
|
51 |
|
52 | /**
|
53 | * @param {boolean} previouslyEnabled Enabled status of
|
54 | * `ReactBrowserEventEmitter` before the reconciliation occurred. `close`
|
55 | * restores the previous value.
|
56 | */
|
57 | close: function (previouslyEnabled) {
|
58 | ReactBrowserEventEmitter.setEnabled(previouslyEnabled);
|
59 | }
|
60 | };
|
61 |
|
62 | /**
|
63 | * Provides a queue for collecting `componentDidMount` and
|
64 | * `componentDidUpdate` callbacks during the transaction.
|
65 | */
|
66 | var ON_DOM_READY_QUEUEING = {
|
67 | /**
|
68 | * Initializes the internal `onDOMReady` queue.
|
69 | */
|
70 | initialize: function () {
|
71 | this.reactMountReady.reset();
|
72 | },
|
73 |
|
74 | /**
|
75 | * After DOM is flushed, invoke all registered `onDOMReady` callbacks.
|
76 | */
|
77 | close: function () {
|
78 | this.reactMountReady.notifyAll();
|
79 | }
|
80 | };
|
81 |
|
82 | /**
|
83 | * Executed within the scope of the `Transaction` instance. Consider these as
|
84 | * being member methods, but with an implied ordering while being isolated from
|
85 | * each other.
|
86 | */
|
87 | var TRANSACTION_WRAPPERS = [SELECTION_RESTORATION, EVENT_SUPPRESSION, ON_DOM_READY_QUEUEING];
|
88 |
|
89 | if (process.env.NODE_ENV !== 'production') {
|
90 | TRANSACTION_WRAPPERS.push({
|
91 | initialize: ReactInstrumentation.debugTool.onBeginFlush,
|
92 | close: ReactInstrumentation.debugTool.onEndFlush
|
93 | });
|
94 | }
|
95 |
|
96 | /**
|
97 | * Currently:
|
98 | * - The order that these are listed in the transaction is critical:
|
99 | * - Suppresses events.
|
100 | * - Restores selection range.
|
101 | *
|
102 | * Future:
|
103 | * - Restore document/overflow scroll positions that were unintentionally
|
104 | * modified via DOM insertions above the top viewport boundary.
|
105 | * - Implement/integrate with customized constraint based layout system and keep
|
106 | * track of which dimensions must be remeasured.
|
107 | *
|
108 | * @class ReactReconcileTransaction
|
109 | */
|
110 | function ReactReconcileTransaction(useCreateElement) {
|
111 | this.reinitializeTransaction();
|
112 | // Only server-side rendering really needs this option (see
|
113 | // `ReactServerRendering`), but server-side uses
|
114 | // `ReactServerRenderingTransaction` instead. This option is here so that it's
|
115 | // accessible and defaults to false when `ReactDOMComponent` and
|
116 | // `ReactDOMTextComponent` checks it in `mountComponent`.`
|
117 | this.renderToStaticMarkup = false;
|
118 | this.reactMountReady = CallbackQueue.getPooled(null);
|
119 | this.useCreateElement = useCreateElement;
|
120 | }
|
121 |
|
122 | var Mixin = {
|
123 | /**
|
124 | * @see Transaction
|
125 | * @abstract
|
126 | * @final
|
127 | * @return {array<object>} List of operation wrap procedures.
|
128 | * TODO: convert to array<TransactionWrapper>
|
129 | */
|
130 | getTransactionWrappers: function () {
|
131 | return TRANSACTION_WRAPPERS;
|
132 | },
|
133 |
|
134 | /**
|
135 | * @return {object} The queue to collect `onDOMReady` callbacks with.
|
136 | */
|
137 | getReactMountReady: function () {
|
138 | return this.reactMountReady;
|
139 | },
|
140 |
|
141 | /**
|
142 | * @return {object} The queue to collect React async events.
|
143 | */
|
144 | getUpdateQueue: function () {
|
145 | return ReactUpdateQueue;
|
146 | },
|
147 |
|
148 | /**
|
149 | * Save current transaction state -- if the return value from this method is
|
150 | * passed to `rollback`, the transaction will be reset to that state.
|
151 | */
|
152 | checkpoint: function () {
|
153 | // reactMountReady is the our only stateful wrapper
|
154 | return this.reactMountReady.checkpoint();
|
155 | },
|
156 |
|
157 | rollback: function (checkpoint) {
|
158 | this.reactMountReady.rollback(checkpoint);
|
159 | },
|
160 |
|
161 | /**
|
162 | * `PooledClass` looks for this, and will invoke this before allowing this
|
163 | * instance to be reused.
|
164 | */
|
165 | destructor: function () {
|
166 | CallbackQueue.release(this.reactMountReady);
|
167 | this.reactMountReady = null;
|
168 | }
|
169 | };
|
170 |
|
171 | _assign(ReactReconcileTransaction.prototype, Transaction, Mixin);
|
172 |
|
173 | PooledClass.addPoolingTo(ReactReconcileTransaction);
|
174 |
|
175 | module.exports = ReactReconcileTransaction; |
\ | No newline at end of file |