mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Type Transaction (#7581)
This one is interesting because we have transaction objects being passed around everywhere in the codebase but there's actually no Transaction class. It's a "mixin" that comes to life by being Object.assigned to the prototype of a real "class" (before class was cool!). Therefore, we can't just say `var Transaction = require('Transaction'); (transaction: Transaction) => { }` because it would be the object that contains a mixin and not an instance of a transaction.
The trick I use is to export `TransactionType` and alias it to `Transaction` in the file as it doesn't actually require transaction. In case they do, we'll figure it out, but in the few files I looked at, it doesn't seem to be the case.
For the perform function, it actually typechecks pretty well!
This commit is contained in:
committed by
GitHub
parent
dd0c65c6aa
commit
a3e576e1bb
@@ -175,7 +175,7 @@ var Mixin = {
|
||||
};
|
||||
|
||||
|
||||
Object.assign(ReactReconcileTransaction.prototype, Transaction.Mixin, Mixin);
|
||||
Object.assign(ReactReconcileTransaction.prototype, Transaction, Mixin);
|
||||
|
||||
PooledClass.addPoolingTo(ReactReconcileTransaction);
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ var Mixin = {
|
||||
|
||||
Object.assign(
|
||||
ReactServerRenderingTransaction.prototype,
|
||||
Transaction.Mixin,
|
||||
Transaction,
|
||||
Mixin
|
||||
);
|
||||
|
||||
|
||||
@@ -13,9 +13,11 @@
|
||||
'use strict';
|
||||
|
||||
var ReactUpdateQueue = require('ReactUpdateQueue');
|
||||
var Transaction = require('Transaction');
|
||||
|
||||
var warning = require('warning');
|
||||
|
||||
import type { Transaction } from 'Transaction';
|
||||
|
||||
function warnNoop(publicInstance: ReactComponent<any, any, any>, callerName: string) {
|
||||
if (__DEV__) {
|
||||
var constructor = publicInstance.constructor;
|
||||
@@ -39,7 +41,7 @@ function warnNoop(publicInstance: ReactComponent<any, any, any>, callerName: str
|
||||
* @param {Transaction} transaction
|
||||
*/
|
||||
class ReactServerUpdateQueue {
|
||||
/* :: transaction: Transaction; */
|
||||
transaction: Transaction;
|
||||
|
||||
constructor(transaction: Transaction) {
|
||||
this.transaction = transaction;
|
||||
|
||||
@@ -109,7 +109,7 @@ var Mixin = {
|
||||
|
||||
Object.assign(
|
||||
ReactNativeReconcileTransaction.prototype,
|
||||
Transaction.Mixin,
|
||||
Transaction,
|
||||
ReactNativeReconcileTransaction,
|
||||
Mixin
|
||||
);
|
||||
|
||||
@@ -36,7 +36,7 @@ function ReactDefaultBatchingStrategyTransaction() {
|
||||
|
||||
Object.assign(
|
||||
ReactDefaultBatchingStrategyTransaction.prototype,
|
||||
Transaction.Mixin,
|
||||
Transaction,
|
||||
{
|
||||
getTransactionWrappers: function() {
|
||||
return TRANSACTION_WRAPPERS;
|
||||
|
||||
@@ -75,7 +75,7 @@ function ReactUpdatesFlushTransaction() {
|
||||
|
||||
Object.assign(
|
||||
ReactUpdatesFlushTransaction.prototype,
|
||||
Transaction.Mixin,
|
||||
Transaction,
|
||||
{
|
||||
getTransactionWrappers: function() {
|
||||
return TRANSACTION_WRAPPERS;
|
||||
@@ -92,7 +92,7 @@ Object.assign(
|
||||
perform: function(method, scope, a) {
|
||||
// Essentially calls `this.reconcileTransaction.perform(method, scope, a)`
|
||||
// with this transaction's wrappers around it.
|
||||
return Transaction.Mixin.perform.call(
|
||||
return Transaction.perform.call(
|
||||
this,
|
||||
this.reconcileTransaction.perform,
|
||||
this.reconcileTransaction,
|
||||
|
||||
@@ -7,12 +7,15 @@
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @providesModule Transaction
|
||||
* @flow
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var invariant = require('invariant');
|
||||
|
||||
var OBSERVED_ERROR = {};
|
||||
|
||||
/**
|
||||
* `Transaction` creates a black box that is able to wrap any method such that
|
||||
* certain invariants are maintained before and after the method is invoked
|
||||
@@ -74,7 +77,7 @@ var invariant = require('invariant');
|
||||
*
|
||||
* @class Transaction
|
||||
*/
|
||||
var Mixin = {
|
||||
var TransactionImpl = {
|
||||
/**
|
||||
* Sets up this instance so that it is prepared for collecting metrics. Does
|
||||
* so such that this setup method may be used on an instance that is already
|
||||
@@ -82,7 +85,7 @@ var Mixin = {
|
||||
* That can be useful if you decide to make your subclass of this mixin a
|
||||
* "PooledClass".
|
||||
*/
|
||||
reinitializeTransaction: function() {
|
||||
reinitializeTransaction: function(): void {
|
||||
this.transactionWrappers = this.getTransactionWrappers();
|
||||
if (this.wrapperInitData) {
|
||||
this.wrapperInitData.length = 0;
|
||||
@@ -100,7 +103,7 @@ var Mixin = {
|
||||
*/
|
||||
getTransactionWrappers: null,
|
||||
|
||||
isInTransaction: function() {
|
||||
isInTransaction: function(): bool {
|
||||
return !!this._isInTransaction;
|
||||
},
|
||||
|
||||
@@ -121,7 +124,13 @@ var Mixin = {
|
||||
*
|
||||
* @return {*} Return value from `method`.
|
||||
*/
|
||||
perform: function(method, scope, a, b, c, d, e, f) {
|
||||
perform: function<
|
||||
A, B, C, D, E, F, G,
|
||||
T: (a: A, b: B, c: C, d: D, e: E, f: F) => G // eslint-disable-line space-before-function-paren
|
||||
>(
|
||||
method: T, scope: any,
|
||||
a: A, b: B, c: C, d: D, e: E, f: F,
|
||||
): G {
|
||||
invariant(
|
||||
!this.isInTransaction(),
|
||||
'Transaction.perform(...): Cannot initialize a transaction when there ' +
|
||||
@@ -160,7 +169,7 @@ var Mixin = {
|
||||
return ret;
|
||||
},
|
||||
|
||||
initializeAll: function(startIndex) {
|
||||
initializeAll: function(startIndex: number): void {
|
||||
var transactionWrappers = this.transactionWrappers;
|
||||
for (var i = startIndex; i < transactionWrappers.length; i++) {
|
||||
var wrapper = transactionWrappers[i];
|
||||
@@ -169,12 +178,12 @@ var Mixin = {
|
||||
// OBSERVED_ERROR state before overwriting it with the real return value
|
||||
// of initialize -- if it's still set to OBSERVED_ERROR in the finally
|
||||
// block, it means wrapper.initialize threw.
|
||||
this.wrapperInitData[i] = Transaction.OBSERVED_ERROR;
|
||||
this.wrapperInitData[i] = OBSERVED_ERROR;
|
||||
this.wrapperInitData[i] = wrapper.initialize ?
|
||||
wrapper.initialize.call(this) :
|
||||
null;
|
||||
} finally {
|
||||
if (this.wrapperInitData[i] === Transaction.OBSERVED_ERROR) {
|
||||
if (this.wrapperInitData[i] === OBSERVED_ERROR) {
|
||||
// The initializer for wrapper i threw an error; initialize the
|
||||
// remaining wrappers but silence any exceptions from them to ensure
|
||||
// that the first error is the one to bubble up.
|
||||
@@ -193,7 +202,7 @@ var Mixin = {
|
||||
* (`close`rs that correspond to initializers that failed will not be
|
||||
* invoked).
|
||||
*/
|
||||
closeAll: function(startIndex) {
|
||||
closeAll: function(startIndex: number): void {
|
||||
invariant(
|
||||
this.isInTransaction(),
|
||||
'Transaction.closeAll(): Cannot close transaction when none are open.'
|
||||
@@ -209,7 +218,7 @@ var Mixin = {
|
||||
// close -- if it's still set to true in the finally block, it means
|
||||
// wrapper.close threw.
|
||||
errorThrown = true;
|
||||
if (initData !== Transaction.OBSERVED_ERROR && wrapper.close) {
|
||||
if (initData !== OBSERVED_ERROR && wrapper.close) {
|
||||
wrapper.close.call(this, initData);
|
||||
}
|
||||
errorThrown = false;
|
||||
@@ -229,15 +238,6 @@ var Mixin = {
|
||||
},
|
||||
};
|
||||
|
||||
var Transaction = {
|
||||
export type Transaction = typeof TransactionImpl;
|
||||
|
||||
Mixin: Mixin,
|
||||
|
||||
/**
|
||||
* Token to look for to determine if an error occurred.
|
||||
*/
|
||||
OBSERVED_ERROR: {},
|
||||
|
||||
};
|
||||
|
||||
module.exports = Transaction;
|
||||
module.exports = TransactionImpl;
|
||||
|
||||
@@ -45,7 +45,7 @@ describe('Transaction', function() {
|
||||
this.secondCloseParam = INIT_ERRORED; // WILL be set to something else
|
||||
this.lastCloseParam = INIT_ERRORED; // WON'T be set to something else
|
||||
};
|
||||
Object.assign(TestTransaction.prototype, Transaction.Mixin);
|
||||
Object.assign(TestTransaction.prototype, Transaction);
|
||||
TestTransaction.prototype.getTransactionWrappers = function() {
|
||||
return [
|
||||
{
|
||||
@@ -96,7 +96,7 @@ describe('Transaction', function() {
|
||||
this.secondCloseParam = INIT_ERRORED; // WILL be set to something else
|
||||
this.lastCloseParam = INIT_ERRORED; // WILL be set to something else
|
||||
};
|
||||
Object.assign(TestTransaction.prototype, Transaction.Mixin);
|
||||
Object.assign(TestTransaction.prototype, Transaction);
|
||||
TestTransaction.prototype.getTransactionWrappers = function() {
|
||||
return [
|
||||
{
|
||||
@@ -157,7 +157,7 @@ describe('Transaction', function() {
|
||||
this.secondCloseParam = INIT_ERRORED; // WILL be set to something else
|
||||
this.lastCloseParam = INIT_ERRORED; // WILL be set to something else
|
||||
};
|
||||
Object.assign(TestTransaction.prototype, Transaction.Mixin);
|
||||
Object.assign(TestTransaction.prototype, Transaction);
|
||||
// Now, none of the close/inits throw, but the operation we wrap will throw.
|
||||
TestTransaction.prototype.getTransactionWrappers = function() {
|
||||
return [
|
||||
@@ -221,7 +221,7 @@ describe('Transaction', function() {
|
||||
var TestTransaction = function() {
|
||||
this.reinitializeTransaction();
|
||||
};
|
||||
Object.assign(TestTransaction.prototype, Transaction.Mixin);
|
||||
Object.assign(TestTransaction.prototype, Transaction);
|
||||
var exceptionMsg = 'This exception should throw.';
|
||||
TestTransaction.prototype.getTransactionWrappers = function() {
|
||||
return [
|
||||
@@ -250,7 +250,7 @@ describe('Transaction', function() {
|
||||
this.reinitializeTransaction();
|
||||
this.firstCloseParam = INIT_ERRORED; // WILL be set to something else
|
||||
};
|
||||
Object.assign(TestTransaction.prototype, Transaction.Mixin);
|
||||
Object.assign(TestTransaction.prototype, Transaction);
|
||||
TestTransaction.prototype.getTransactionWrappers = function() {
|
||||
return [
|
||||
{
|
||||
@@ -278,7 +278,7 @@ describe('Transaction', function() {
|
||||
var NestedTransaction = function() {
|
||||
this.reinitializeTransaction();
|
||||
};
|
||||
Object.assign(NestedTransaction.prototype, Transaction.Mixin);
|
||||
Object.assign(NestedTransaction.prototype, Transaction);
|
||||
NestedTransaction.prototype.getTransactionWrappers = function() {
|
||||
return [
|
||||
{
|
||||
|
||||
@@ -114,7 +114,7 @@ var Mixin = {
|
||||
|
||||
Object.assign(
|
||||
ReactTestReconcileTransaction.prototype,
|
||||
Transaction.Mixin,
|
||||
Transaction,
|
||||
ReactTestReconcileTransaction,
|
||||
Mixin
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user