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