Skip to content

Commit e71ec03

Browse files
committed
WIP: Convert several ES5 classes to TS classes
1 parent 521e26a commit e71ec03

File tree

14 files changed

+867
-877
lines changed

14 files changed

+867
-877
lines changed
Lines changed: 28 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,42 @@
11
import { assert } from "../../../utils/assert";
22
import { Path } from "../util/Path";
3-
import { OperationSource, OperationType } from "./Operation";
3+
import { Operation, OperationSource, OperationType } from './Operation';
4+
import { ImmutableTree } from '../util/ImmutableTree';
45

5-
/**
6-
*
7-
* @param {!Path} path
8-
* @param {!ImmutableTree<!boolean>} affectedTree
9-
* @param {!boolean} revert
10-
* @constructor
11-
* @implements {fb.core.Operation}
12-
*/
13-
export const AckUserWrite = function(path, affectedTree, revert) {
6+
export class AckUserWrite implements Operation {
147
/** @inheritDoc */
15-
this.type = OperationType.ACK_USER_WRITE;
8+
type = OperationType.ACK_USER_WRITE;
169

1710
/** @inheritDoc */
18-
this.source = OperationSource.User;
19-
20-
/** @inheritDoc */
21-
this.path = path;
11+
source = OperationSource.User;
2212

2313
/**
24-
* A tree containing true for each affected path. Affected paths can't overlap.
25-
* @type {!util.ImmutableTree.<!boolean>}
14+
*
15+
* @param {!Path} path
16+
* @param {!ImmutableTree<!boolean>} affectedTree A tree containing true for each affected path. Affected paths can't overlap.
17+
* @param {!boolean} revert
2618
*/
27-
this.affectedTree = affectedTree;
19+
constructor(/**@inheritDoc */ public path: Path,
20+
/**@inheritDoc */ public affectedTree: ImmutableTree,
21+
/**@inheritDoc */ public revert: boolean) {
22+
23+
}
2824

2925
/**
30-
* @type {boolean}
26+
* @inheritDoc
3127
*/
32-
this.revert = revert;
33-
};
34-
35-
/**
36-
* @inheritDoc
37-
*/
38-
AckUserWrite.prototype.operationForChild = function(childName) {
39-
if (!this.path.isEmpty()) {
40-
assert(this.path.getFront() === childName, 'operationForChild called for unrelated child.');
41-
return new AckUserWrite(this.path.popFront(), this.affectedTree, this.revert);
42-
} else if (this.affectedTree.value != null) {
43-
assert(this.affectedTree.children.isEmpty(),
28+
operationForChild(childName: string) {
29+
if (!this.path.isEmpty()) {
30+
assert(this.path.getFront() === childName, 'operationForChild called for unrelated child.');
31+
return new AckUserWrite(this.path.popFront(), this.affectedTree, this.revert);
32+
} else if (this.affectedTree.value != null) {
33+
assert(this.affectedTree.children.isEmpty(),
4434
'affectedTree should not have overlapping affected paths.');
45-
// All child locations are affected as well; just return same operation.
46-
return this;
47-
} else {
48-
var childTree = this.affectedTree.subtree(new Path(childName));
49-
return new AckUserWrite(Path.Empty, childTree, this.revert);
35+
// All child locations are affected as well; just return same operation.
36+
return this;
37+
} else {
38+
const childTree = this.affectedTree.subtree(new Path(childName));
39+
return new AckUserWrite(Path.Empty, childTree, this.revert);
40+
}
5041
}
51-
};
42+
}

src/database/core/operation/Merge.ts

Lines changed: 32 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
import { OperationType } from "./Operation";
1+
import { Operation, OperationSource, OperationType } from './Operation';
22
import { Overwrite } from "./Overwrite";
33
import { Path } from "../util/Path";
44
import { assert } from "../../../utils/assert";
5+
import { ImmutableTree } from '../util/ImmutableTree';
56

67
/**
78
* @param {!fb.core.OperationSource} source
@@ -10,48 +11,42 @@ import { assert } from "../../../utils/assert";
1011
* @constructor
1112
* @implements {fb.core.Operation}
1213
*/
13-
export const Merge = function(source, path, children) {
14+
export class Merge implements Operation {
1415
/** @inheritDoc */
15-
this.type = OperationType.MERGE;
16+
type = OperationType.MERGE;
1617

17-
/** @inheritDoc */
18-
this.source = source;
19-
20-
/** @inheritDoc */
21-
this.path = path;
18+
constructor(/**@inheritDoc */ public source: OperationSource,
19+
/**@inheritDoc */ public path: Path,
20+
/**@inheritDoc */ public children: ImmutableTree) {
21+
}
2222

2323
/**
24-
* @type {!fb.core.util.ImmutableTree.<!fb.core.snap.Node>}
24+
* @inheritDoc
2525
*/
26-
this.children = children;
27-
};
28-
29-
/**
30-
* @inheritDoc
31-
*/
32-
Merge.prototype.operationForChild = function(childName) {
33-
if (this.path.isEmpty()) {
34-
var childTree = this.children.subtree(new Path(childName));
35-
if (childTree.isEmpty()) {
36-
// This child is unaffected
37-
return null;
38-
} else if (childTree.value) {
39-
// We have a snapshot for the child in question. This becomes an overwrite of the child.
40-
return new Overwrite(this.source, Path.Empty, childTree.value);
26+
operationForChild(childName: string): Operation {
27+
if (this.path.isEmpty()) {
28+
const childTree = this.children.subtree(new Path(childName));
29+
if (childTree.isEmpty()) {
30+
// This child is unaffected
31+
return null;
32+
} else if (childTree.value) {
33+
// We have a snapshot for the child in question. This becomes an overwrite of the child.
34+
return new Overwrite(this.source, Path.Empty, childTree.value);
35+
} else {
36+
// This is a merge at a deeper level
37+
return new Merge(this.source, Path.Empty, childTree);
38+
}
4139
} else {
42-
// This is a merge at a deeper level
43-
return new Merge(this.source, Path.Empty, childTree);
40+
assert(this.path.getFront() === childName,
41+
'Can\'t get a merge for a child not on the path of the operation');
42+
return new Merge(this.source, this.path.popFront(), this.children);
4443
}
45-
} else {
46-
assert(this.path.getFront() === childName,
47-
'Can\'t get a merge for a child not on the path of the operation');
48-
return new Merge(this.source, this.path.popFront(), this.children);
4944
}
50-
};
5145

52-
/**
53-
* @inheritDoc
54-
*/
55-
Merge.prototype.toString = function() {
56-
return 'Operation(' + this.path + ': ' + this.source.toString() + ' merge: ' + this.children.toString() + ')';
57-
};
46+
/**
47+
* @inheritDoc
48+
*/
49+
toString() {
50+
return 'Operation(' + this.path + ': ' + this.source.toString() + ' merge: ' + this.children.toString() + ')';
51+
}
52+
}

src/database/core/operation/Operation.ts

Lines changed: 30 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,42 @@
11
import { assert } from "../../../utils/assert";
2+
import { Path } from '../util/Path';
23

34
/**
45
*
56
* @enum
67
*/
7-
export const OperationType = {
8-
OVERWRITE: 0,
9-
MERGE: 1,
10-
ACK_USER_WRITE: 2,
11-
LISTEN_COMPLETE: 3
12-
};
8+
export enum OperationType {
9+
OVERWRITE,
10+
MERGE,
11+
ACK_USER_WRITE,
12+
LISTEN_COMPLETE
13+
}
1314

1415
/**
1516
* @interface
1617
*/
17-
export const Operation = function() { };
18-
19-
/**
20-
* @type {!OperationSource}
21-
*/
22-
Operation.prototype.source;
23-
24-
/**
25-
* @type {!OperationType}
26-
*/
27-
Operation.prototype.type;
18+
export interface Operation {
19+
/**
20+
* @type {!OperationSource}
21+
*/
22+
source: OperationSource;
2823

29-
/**
30-
* @type {!Path}
31-
*/
32-
Operation.prototype.path;
24+
/**
25+
* @type {!OperationType}
26+
*/
27+
type: OperationType;
3328

34-
/**
35-
* @param {string} childName
36-
* @return {?Operation}
37-
*/
38-
Operation.prototype.operationForChild = () => {};
29+
/**
30+
* @type {!Path}
31+
*/
32+
path: Path;
3933

34+
/**
35+
* @param {string} childName
36+
* @return {?Operation}
37+
*/
38+
operationForChild(childName: string): Operation | null;
39+
}
4040

4141
/**
4242
* @param {boolean} fromUser
@@ -46,16 +46,10 @@ Operation.prototype.operationForChild = () => {};
4646
* @constructor
4747
*/
4848
export class OperationSource {
49-
fromUser;
50-
fromServer;
51-
queryId;
52-
tagged;
53-
54-
constructor(fromUser, fromServer, queryId, tagged) {
55-
this.fromUser = fromUser;
56-
this.fromServer = fromServer;
57-
this.queryId = queryId;
58-
this.tagged = tagged;
49+
constructor(public fromUser: boolean,
50+
public fromServer: boolean,
51+
public queryId: string | null,
52+
public tagged: boolean) {
5953
assert(!tagged || fromServer, 'Tagged queries must be from server.');
6054
}
6155
/**

src/database/core/operation/Overwrite.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { OperationType } from "./Operation";
1+
import { Operation, OperationType } from './Operation';
22
import { Path } from "../util/Path";
33

44
/**
@@ -8,7 +8,7 @@ import { Path } from "../util/Path";
88
* @constructor
99
* @implements {Operation}
1010
*/
11-
export class Overwrite {
11+
export class Overwrite implements Operation {
1212
/** @inheritDoc */
1313
type;
1414

src/database/core/stats/StatsListener.ts

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,21 @@ import { clone } from "../../../utils/obj";
33
/**
44
* Returns the delta from the previous call to get stats.
55
*
6-
* @param collection The collection to "listen" to.
6+
* @param collection_ The collection to "listen" to.
77
* @constructor
88
*/
99
export class StatsListener {
10-
collection_;
11-
last_;
10+
private last_ = null;
1211

13-
constructor(collection) {
14-
this.collection_ = collection;
15-
this.last_ = null;
12+
constructor(private collection_) {
1613
}
14+
1715
get() {
18-
var newStats = this.collection_.get();
16+
const newStats = this.collection_.get();
1917

20-
var delta = clone(newStats);
18+
const delta = clone(newStats);
2119
if (this.last_) {
22-
for (var stat in this.last_) {
20+
for (let stat in this.last_) {
2321
delta[stat] = delta[stat] - this.last_[stat];
2422
}
2523
}

src/database/core/stats/StatsReporter.ts

Lines changed: 34 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5,46 +5,49 @@ import { StatsListener } from "./StatsListener";
55
// Assuming some apps may have a short amount of time on page, and a bulk of firebase operations probably
66
// happen on page load, we try to report our first set of stats pretty quickly, but we wait at least 10
77
// seconds to try to ensure the Firebase connection is established / settled.
8-
var FIRST_STATS_MIN_TIME = 10 * 1000;
9-
var FIRST_STATS_MAX_TIME = 30 * 1000;
8+
const FIRST_STATS_MIN_TIME = 10 * 1000;
9+
const FIRST_STATS_MAX_TIME = 30 * 1000;
1010

1111
// We'll continue to report stats on average every 5 minutes.
12-
var REPORT_STATS_INTERVAL = 5 * 60 * 1000;
12+
const REPORT_STATS_INTERVAL = 5 * 60 * 1000;
1313

1414
/**
1515
*
1616
* @param collection
17-
* @param connection
17+
* @param server_
1818
* @constructor
1919
*/
20-
export const StatsReporter = function(collection, connection) {
21-
this.statsToReport_ = {};
22-
this.statsListener_ = new StatsListener(collection);
23-
this.server_ = connection;
24-
25-
var timeout = FIRST_STATS_MIN_TIME + (FIRST_STATS_MAX_TIME - FIRST_STATS_MIN_TIME) * Math.random();
26-
setTimeoutNonBlocking(this.reportStats_.bind(this), Math.floor(timeout));
27-
};
28-
29-
StatsReporter.prototype.includeStat = function(stat) {
30-
this.statsToReport_[stat] = true;
31-
};
32-
33-
StatsReporter.prototype.reportStats_ = function() {
34-
var stats = this.statsListener_.get();
35-
var reportedStats = { };
36-
var haveStatsToReport = false;
37-
for (var stat in stats) {
38-
if (stats[stat] > 0 && contains(this.statsToReport_, stat)) {
39-
reportedStats[stat] = stats[stat];
40-
haveStatsToReport = true;
41-
}
20+
export class StatsReporter {
21+
private statsListener_;
22+
private statsToReport_ = {};
23+
24+
constructor(collection, private server_: any) {
25+
this.statsListener_ = new StatsListener(collection);
26+
27+
const timeout = FIRST_STATS_MIN_TIME + (FIRST_STATS_MAX_TIME - FIRST_STATS_MIN_TIME) * Math.random();
28+
setTimeoutNonBlocking(this.reportStats_.bind(this), Math.floor(timeout));
4229
}
4330

44-
if (haveStatsToReport) {
45-
this.server_.reportStats(reportedStats);
31+
includeStat(stat) {
32+
this.statsToReport_[stat] = true;
4633
}
4734

48-
// queue our next run.
49-
setTimeoutNonBlocking(this.reportStats_.bind(this), Math.floor(Math.random() * 2 * REPORT_STATS_INTERVAL));
50-
};
35+
private reportStats_() {
36+
const stats = this.statsListener_.get();
37+
const reportedStats = {};
38+
let haveStatsToReport = false;
39+
for (let stat in stats) {
40+
if (stats[stat] > 0 && contains(this.statsToReport_, stat)) {
41+
reportedStats[stat] = stats[stat];
42+
haveStatsToReport = true;
43+
}
44+
}
45+
46+
if (haveStatsToReport) {
47+
this.server_.reportStats(reportedStats);
48+
}
49+
50+
// queue our next run.
51+
setTimeoutNonBlocking(this.reportStats_.bind(this), Math.floor(Math.random() * 2 * REPORT_STATS_INTERVAL));
52+
}
53+
}

0 commit comments

Comments
 (0)