Skip to content

Commit 3602cd7

Browse files
committed
WIP: fixing broken int tests (order_by spec)
1 parent 6b053f2 commit 3602cd7

17 files changed

+63
-59
lines changed

src/database.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import { RepoManager } from "./database/core/RepoManager";
2424

2525
export function registerDatabase(instance) {
2626
// Register the Database Service with the 'firebase' namespace.
27-
firebase.INTERNAL.registerService(
27+
instance.INTERNAL.registerService(
2828
'database',
2929
app => RepoManager.getInstance().databaseFromApp(app),
3030
// firebase.database namespace properties

src/database/api/Database.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,9 @@ export class Database {
1919
root_;
2020
INTERNAL;
2121

22-
static get ServerValue() {
23-
return {
24-
'TIMESTAMP': {
25-
'.sv' : 'timestamp'
26-
}
22+
static ServerValue = {
23+
'TIMESTAMP': {
24+
'.sv' : 'timestamp'
2725
}
2826
}
2927

src/database/core/PersistentConnection.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import firebase from "../../app";
2-
import { forEach, contains, isEmpty, getCount } from "../../utils/obj";
2+
import { forEach, contains, isEmpty, getCount, safeGet } from "../../utils/obj";
33
import { stringify } from "../../utils/json";
44
import { assert } from '../../utils/assert';
55
import { error, log, logWrapper, warn, ObjectToUniqueKey } from "./util/util";
@@ -243,7 +243,7 @@ export class PersistentConnection {
243243
*/
244244
warnOnListenWarnings_(payload, query) {
245245
if (payload && typeof payload === 'object' && contains(payload, 'w')) {
246-
var warnings = payload['w'];
246+
var warnings = safeGet(payload, 'w');
247247
if (Array.isArray(warnings) && ~warnings.indexOf('no_index')) {
248248
var indexSpec = '".indexOn": "' + query.getQueryParams().getIndex().toString() + '"';
249249
var indexPath = query.path.toString();

src/database/core/ReadonlyRestClient.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { assert } from "../../utils/assert";
22
import { logWrapper, warn } from "./util/util";
33
import { jsonEval } from "../../utils/json";
4+
import { safeGet } from "../../utils/obj";
45
import { querystring } from "../../utils/util";
56

67
/**
@@ -35,9 +36,9 @@ export class ReadonlyRestClient {
3536
* @return {string}
3637
* @private
3738
*/
38-
static getListenId_(query, opt_tag) {
39-
if (opt_tag !== undefined) {
40-
return 'tag$' + opt_tag;
39+
static getListenId_(query, tag?) {
40+
if (tag !== undefined) {
41+
return 'tag$' + tag;
4142
} else {
4243
assert(query.getQueryParams().isDefault(), "should have a tag if it's not a default query.");
4344
return query.path.toString();
@@ -81,7 +82,7 @@ export class ReadonlyRestClient {
8182
self.onDataUpdate_(pathString, data, /*isMerge=*/false, tag);
8283
}
8384

84-
if (self.listens_[listenId] === thisListen) {
85+
if (safeGet(self.listens_, listenId) === thisListen) {
8586
var status;
8687
if (!error) {
8788
status = 'ok';

src/database/core/RepoManager.ts

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { FirebaseApp } from "../../app/firebase_app";
2+
import { safeGet } from "../../utils/obj";
23
import { Repo } from "./Repo";
34
import { fatal } from "./util/util";
45
import { parseRepoInfo } from "./util/libs/parser";
@@ -8,28 +9,30 @@ import "./Repo_transaction";
89
/** @const {string} */
910
var DATABASE_URL_OPTION = 'databaseURL';
1011

12+
let _staticInstance;
13+
1114
/**
1215
* Creates and caches Repo instances.
1316
*/
1417
export class RepoManager {
1518
/**
1619
* @private {!Object.<string, !Repo>}
1720
*/
18-
private repos_;
21+
private repos_: {
22+
[name: string]: Repo
23+
} = {};
1924

2025
/**
2126
* If true, new Repos will be created to use ReadonlyRestClient (for testing purposes).
2227
* @private {boolean}
2328
*/
24-
private useRestClient_;
29+
private useRestClient_: boolean = false;
2530

2631
static getInstance() {
27-
return new RepoManager();
28-
}
29-
30-
constructor() {
31-
this.repos_ = { };
32-
this.useRestClient_ = false;
32+
if (!_staticInstance) {
33+
_staticInstance = new RepoManager();
34+
}
35+
return _staticInstance;
3336
}
3437

3538
// TODO(koss): Remove these functions unless used in tests?
@@ -79,8 +82,9 @@ export class RepoManager {
7982
* @param {!Repo} repo
8083
*/
8184
deleteRepo(repo) {
85+
8286
// This should never happen...
83-
if (this.repos_[repo.app.name] !== repo) {
87+
if (safeGet(this.repos_, repo.app.name) !== repo) {
8488
fatal("Database " + repo.app.name + " has already been deleted.");
8589
}
8690
repo.interrupt();
@@ -96,7 +100,7 @@ export class RepoManager {
96100
* @return {!Repo} The Repo object for the specified server / repoName.
97101
*/
98102
createRepo(repoInfo, app: FirebaseApp): Repo {
99-
var repo = this.repos_[app.name];
103+
var repo = safeGet(this.repos_, app.name);
100104
if (repo) {
101105
fatal('FIREBASE INTERNAL ERROR: Database initialized multiple times.');
102106
}

src/database/core/Repo_transaction.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
} from "./util/util";
1212
import { resolveDeferredValueSnapshot } from "./util/ServerValues";
1313
import { isValidPriority, validateFirebaseData } from "./util/validation";
14-
import { contains } from "../../utils/obj";
14+
import { contains, safeGet } from "../../utils/obj";
1515
import { nodeFromJSON } from "./snap/nodeFromJSON";
1616
import { ChildrenNode } from "./snap/ChildrenNode";
1717
import { Repo } from "./Repo";
@@ -176,7 +176,7 @@ declare module './Repo' {
176176
// start new transactions from the event callbacks.
177177
var priorityForNode;
178178
if (typeof newVal === 'object' && newVal !== null && contains(newVal, '.priority')) {
179-
priorityForNode = newVal['.priority'];
179+
priorityForNode = safeGet(newVal, '.priority');
180180
assert(isValidPriority(priorityForNode), 'Invalid priority returned by transaction. ' +
181181
'Priority must be a valid string, finite number, server value, or null.');
182182
} else {

src/database/core/SyncPoint.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { CacheNode } from "./view/CacheNode";
22
import { ChildrenNode } from "./snap/ChildrenNode";
33
import { assert } from "../../utils/assert";
4-
import { isEmpty, forEach, findValue } from "../../utils/obj";
4+
import { isEmpty, forEach, findValue, safeGet } from "../../utils/obj";
55
import { ViewCache } from "./view/ViewCache";
66
import { View } from "./view/View";
77

@@ -57,7 +57,7 @@ export class SyncPoint {
5757
applyOperation(operation, writesCache, optCompleteServerCache) {
5858
var queryId = operation.source.queryId;
5959
if (queryId !== null) {
60-
var view = this.views_[queryId];
60+
var view = safeGet(this.views_, queryId);
6161
assert(view != null, 'SyncTree gave us an op for an invalid query.');
6262
return view.applyOperation(operation, writesCache, optCompleteServerCache);
6363
} else {
@@ -83,7 +83,7 @@ export class SyncPoint {
8383
*/
8484
addEventRegistration(query, eventRegistration, writesCache, serverCache, serverCacheComplete) {
8585
var queryId = query.queryIdentifier();
86-
var view = this.views_[queryId];
86+
var view = safeGet(this.views_, queryId);
8787
if (!view) {
8888
// TODO: make writesCache take flag for complete server node
8989
var eventCache = writesCache.calcCompleteEventCache(serverCacheComplete ? serverCache : null);
@@ -142,7 +142,7 @@ export class SyncPoint {
142142
});
143143
} else {
144144
// remove the callback from the specific view.
145-
var view = this.views_[queryId];
145+
var view = safeGet(this.views_, queryId);
146146
if (view) {
147147
cancelEvents = cancelEvents.concat(view.removeEventRegistration(eventRegistration, cancelError));
148148
if (view.isEmpty()) {
@@ -198,7 +198,7 @@ export class SyncPoint {
198198
return this.getCompleteView();
199199
} else {
200200
var queryId = query.queryIdentifier();
201-
return this.views_[queryId];
201+
return safeGet(this.views_, queryId);
202202
}
203203
};
204204

src/database/core/SyncTree.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { assert } from '../../utils/assert';
22
import { errorForServerCode } from "./util/util";
33
import { AckUserWrite } from "./operation/AckUserWrite";
44
import { ChildrenNode } from "./snap/ChildrenNode";
5-
import { forEach } from "../../utils/obj";
5+
import { forEach, safeGet } from "../../utils/obj";
66
import { ImmutableTree } from "./util/ImmutableTree";
77
import { ListenComplete } from "./operation/ListenComplete";
88
import { Merge } from "./operation/Merge";
@@ -610,7 +610,7 @@ export class SyncTree {
610610
*/
611611
tagForQuery_(query) {
612612
var queryKey = this.makeQueryKey_(query);
613-
return this.queryToTagMap_[queryKey];
613+
return safeGet(this.queryToTagMap_, queryKey);
614614
};
615615

616616
/**

src/database/core/WriteTree.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { findKey, forEach } from "../../utils/obj";
1+
import { findKey, forEach, safeGet } from "../../utils/obj";
22
import { assert, assertionError } from "../../utils/assert";
33
import { Path } from "./util/Path";
44
import { CompoundWrite } from "./CompoundWrite";
@@ -483,7 +483,7 @@ export class WriteTree {
483483
if (relativePath.isEmpty()) {
484484
compoundWrite = compoundWrite.addWrites(Path.Empty, write.children);
485485
} else {
486-
var child = write.children[relativePath.getFront()];
486+
var child = safeGet(write.children, relativePath.getFront());
487487
if (child) {
488488
// There exists a child in this node that matches the root path
489489
var deepNode = child.getChild(relativePath.popFront());

src/database/core/snap/IndexMap.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { assert } from "../../../utils/assert";
22
import { buildChildSet } from "./childSet";
3-
import { contains, clone, map } from "../../../utils/obj";
3+
import { contains, clone, map, safeGet } from "../../../utils/obj";
44
import { NamedNode } from "./Node";
55
import { PRIORITY_INDEX } from "./indexes/PriorityIndex";
66
import { KEY_INDEX } from "./indexes/KeyIndex";
@@ -42,7 +42,7 @@ export class IndexMap {
4242
* @return {?SortedMap.<NamedNode, Node>}
4343
*/
4444
get(indexKey) {
45-
var sortedMap = this.indexes_[indexKey];
45+
var sortedMap = safeGet(this.indexes_, indexKey);
4646
if (!sortedMap) throw new Error('No index defined for ' + indexKey);
4747

4848
if (sortedMap === fallbackObject) {
@@ -103,7 +103,7 @@ export class IndexMap {
103103
addToIndexes(namedNode, existingChildren) {
104104
var self = this;
105105
var newIndexes = map(this.indexes_, function(indexedChildren, indexName) {
106-
var index = self.indexSet_[indexName];
106+
var index = safeGet(self.indexSet_, indexName);
107107
assert(index, 'Missing index implementation for ' + indexName);
108108
if (indexedChildren === fallbackObject) {
109109
// Check to see if we need to index everything

src/database/core/snap/LeafNode.ts

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,13 @@ export class LeafNode implements Node {
2323
static get __childrenNodeConstructor() {
2424
return __childrenNodeConstructor;
2525
}
26+
/**
27+
* The sort order for comparing leaf nodes of different types. If two leaf nodes have
28+
* the same type, the comparison falls back to their value
29+
* @type {Array.<!string>}
30+
* @const
31+
*/
32+
static VALUE_TYPE_ORDER = ['object', 'boolean', 'number', 'string'];
2633

2734
value_;
2835
priorityNode_;
@@ -54,16 +61,6 @@ export class LeafNode implements Node {
5461
this.lazyHash_ = null;
5562
}
5663

57-
/**
58-
* The sort order for comparing leaf nodes of different types. If two leaf nodes have
59-
* the same type, the comparison falls back to their value
60-
* @type {Array.<!string>}
61-
* @const
62-
*/
63-
static get VALUE_TYPE_ORDER() {
64-
return ['object', 'boolean', 'number', 'string'];
65-
}
66-
6764
/** @inheritDoc */
6865
isLeafNode() {
6966
return true;

src/database/core/util/ImmutableTree.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import { Path } from "./Path";
33
import { stringCompare } from "./util";
44
import { forEach } from "../../../utils/obj";
55

6+
let emptyChildrenSingleton;
7+
68
/**
79
* A tree with immutable elements.
810
*/
@@ -20,7 +22,10 @@ export class ImmutableTree {
2022
* @private
2123
*/
2224
static get EmptyChildren_() {
23-
return new SortedMap(stringCompare)
25+
if (!emptyChildrenSingleton) {
26+
emptyChildrenSingleton = new SortedMap(stringCompare);
27+
}
28+
return emptyChildrenSingleton;
2429
}
2530

2631
/**
@@ -41,7 +46,7 @@ export class ImmutableTree {
4146
* @param {?T} value
4247
* @param {SortedMap.<string, !ImmutableTree.<T>>=} opt_children
4348
*/
44-
constructor(value, opt_children?) {
49+
constructor(value, children?) {
4550
/**
4651
* @const
4752
* @type {?T}
@@ -52,7 +57,7 @@ export class ImmutableTree {
5257
* @const
5358
* @type {!SortedMap.<string, !ImmutableTree.<T>>}
5459
*/
55-
this.children = opt_children || ImmutableTree.EmptyChildren_;
60+
this.children = children || ImmutableTree.EmptyChildren_;
5661
}
5762

5863
/**

src/database/core/util/Tree.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { assert } from "../../../utils/assert";
22
import { Path } from "./Path";
3-
import { forEach, contains } from '../../../utils/obj'
3+
import { forEach, contains, safeGet } from '../../../utils/obj'
44

55
/**
66
* Node in a Tree.
@@ -54,7 +54,7 @@ export class Tree {
5454
pathObj : new Path(pathObj);
5555
var child = <any>this, next;
5656
while ((next = path.getFront()) !== null) {
57-
var childNode = child.node_.children[next] || new TreeNode();
57+
var childNode = safeGet(child.node_.children, next) || new TreeNode();
5858
child = new Tree(next, child, childNode);
5959
path = path.popFront();
6060
}

src/database/core/util/util.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ export const buildLogMessage_ = function(var_args) {
114114
* Use this for all debug messages in Firebase.
115115
* @type {?function(string)}
116116
*/
117-
export var logger = null;
117+
export var logger = console.log.bind(console);
118118

119119

120120
/**
@@ -131,8 +131,7 @@ export var firstLog_ = true;
131131
* @param {boolean=} opt_persistent Whether or not to persist logging settings across refreshes
132132
*/
133133
export const enableLogging = function(logger, opt_persistent?) {
134-
assert(!opt_persistent || (logger === true || logger === false),
135-
"Can't turn on custom loggers persistently.");
134+
assert(!opt_persistent || (logger === true || logger === false), "Can't turn on custom loggers persistently.");
136135
if (logger === true) {
137136
if (typeof console !== 'undefined') {
138137
if (typeof console.log === 'function') {

src/database/core/util/validation.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Path, ValidationPath } from "./Path";
2-
import { forEach, contains } from "../../../utils/obj";
2+
import { forEach, contains, safeGet } from "../../../utils/obj";
33
import { isInvalidJSONNumber } from "./util";
44
import { errorPrefix as errorPrefixFxn } from "../../../utils/validation";
55
import { stringLength } from "../../../utils/utf8";
@@ -362,7 +362,7 @@ export const validateObjectContainsKey = function(fnName, argumentNumber, obj, k
362362
}
363363

364364
if (opt_type) {
365-
var val = obj[key];
365+
var val = safeGet(obj, key);
366366
if ((opt_type === 'number' && !(typeof val === 'number')) ||
367367
(opt_type === 'string' && !(typeof val === 'string')) ||
368368
(opt_type === 'boolean' && !(typeof val === 'boolean')) ||

src/database/core/view/ChildChangeAccumulator.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { getValues } from '../../../utils/obj';
1+
import { getValues, safeGet } from '../../../utils/obj';
22
import { Change } from "./Change";
33
import { assert, assertionError } from "../../../utils/assert";
44

@@ -17,7 +17,7 @@ export class ChildChangeAccumulator {
1717
type == Change.CHILD_CHANGED ||
1818
type == Change.CHILD_REMOVED, 'Only child changes supported for tracking');
1919
assert(childKey !== '.priority', 'Only non-priority child changes can be tracked.');
20-
var oldChange = this.changeMap_[childKey];
20+
var oldChange = safeGet(this.changeMap_, childKey);
2121
if (oldChange) {
2222
var oldType = oldChange.type;
2323
if (type == Change.CHILD_ADDED && oldType == Change.CHILD_REMOVED) {

0 commit comments

Comments
 (0)