@firebase/database 0.13.9 → 0.13.10-canary.09dfc3aac

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,11 +1,11 @@
1
1
  import { getApp, _getProvider, _registerComponent, registerVersion, SDK_VERSION as SDK_VERSION$1 } from '@firebase/app';
2
2
  import { Component } from '@firebase/component';
3
3
  import { __spreadArray, __read, __values, __extends, __awaiter, __generator, __assign } from 'tslib';
4
- import { stringify, jsonEval, contains, assert, isNodeSdk, base64, stringToByteArray, Sha1, deepCopy, base64Encode, isMobileCordova, stringLength, Deferred, safeGet, isAdmin, isValidFormat, isEmpty, isReactNative, assertionError, map, querystring, errorPrefix, getModularInstance, getDefaultEmulatorHostnameAndPort, createMockUserToken } from '@firebase/util';
4
+ import { stringify, jsonEval, contains, assert, isNodeSdk, stringToByteArray, Sha1, base64, deepCopy, base64Encode, isMobileCordova, stringLength, Deferred, safeGet, isAdmin, isValidFormat, isEmpty, isReactNative, assertionError, map, querystring, errorPrefix, getModularInstance, getDefaultEmulatorHostnameAndPort, createMockUserToken } from '@firebase/util';
5
5
  import { Logger, LogLevel } from '@firebase/logger';
6
6
 
7
7
  var name = "@firebase/database";
8
- var version = "0.13.9";
8
+ var version = "0.13.10-canary.09dfc3aac";
9
9
 
10
10
  /**
11
11
  * @license
@@ -6166,153 +6166,6 @@ var ValueIndex = /** @class */ (function (_super) {
6166
6166
  }(Index));
6167
6167
  var VALUE_INDEX = new ValueIndex();
6168
6168
 
6169
- /**
6170
- * @license
6171
- * Copyright 2017 Google LLC
6172
- *
6173
- * Licensed under the Apache License, Version 2.0 (the "License");
6174
- * you may not use this file except in compliance with the License.
6175
- * You may obtain a copy of the License at
6176
- *
6177
- * http://www.apache.org/licenses/LICENSE-2.0
6178
- *
6179
- * Unless required by applicable law or agreed to in writing, software
6180
- * distributed under the License is distributed on an "AS IS" BASIS,
6181
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
6182
- * See the License for the specific language governing permissions and
6183
- * limitations under the License.
6184
- */
6185
- // Modeled after base64 web-safe chars, but ordered by ASCII.
6186
- var PUSH_CHARS = '-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz';
6187
- var MIN_PUSH_CHAR = '-';
6188
- var MAX_PUSH_CHAR = 'z';
6189
- var MAX_KEY_LEN = 786;
6190
- /**
6191
- * Fancy ID generator that creates 20-character string identifiers with the
6192
- * following properties:
6193
- *
6194
- * 1. They're based on timestamp so that they sort *after* any existing ids.
6195
- * 2. They contain 72-bits of random data after the timestamp so that IDs won't
6196
- * collide with other clients' IDs.
6197
- * 3. They sort *lexicographically* (so the timestamp is converted to characters
6198
- * that will sort properly).
6199
- * 4. They're monotonically increasing. Even if you generate more than one in
6200
- * the same timestamp, the latter ones will sort after the former ones. We do
6201
- * this by using the previous random bits but "incrementing" them by 1 (only
6202
- * in the case of a timestamp collision).
6203
- */
6204
- var nextPushId = (function () {
6205
- // Timestamp of last push, used to prevent local collisions if you push twice
6206
- // in one ms.
6207
- var lastPushTime = 0;
6208
- // We generate 72-bits of randomness which get turned into 12 characters and
6209
- // appended to the timestamp to prevent collisions with other clients. We
6210
- // store the last characters we generated because in the event of a collision,
6211
- // we'll use those same characters except "incremented" by one.
6212
- var lastRandChars = [];
6213
- return function (now) {
6214
- var duplicateTime = now === lastPushTime;
6215
- lastPushTime = now;
6216
- var i;
6217
- var timeStampChars = new Array(8);
6218
- for (i = 7; i >= 0; i--) {
6219
- timeStampChars[i] = PUSH_CHARS.charAt(now % 64);
6220
- // NOTE: Can't use << here because javascript will convert to int and lose
6221
- // the upper bits.
6222
- now = Math.floor(now / 64);
6223
- }
6224
- assert(now === 0, 'Cannot push at time == 0');
6225
- var id = timeStampChars.join('');
6226
- if (!duplicateTime) {
6227
- for (i = 0; i < 12; i++) {
6228
- lastRandChars[i] = Math.floor(Math.random() * 64);
6229
- }
6230
- }
6231
- else {
6232
- // If the timestamp hasn't changed since last push, use the same random
6233
- // number, except incremented by 1.
6234
- for (i = 11; i >= 0 && lastRandChars[i] === 63; i--) {
6235
- lastRandChars[i] = 0;
6236
- }
6237
- lastRandChars[i]++;
6238
- }
6239
- for (i = 0; i < 12; i++) {
6240
- id += PUSH_CHARS.charAt(lastRandChars[i]);
6241
- }
6242
- assert(id.length === 20, 'nextPushId: Length should be 20.');
6243
- return id;
6244
- };
6245
- })();
6246
- var successor = function (key) {
6247
- if (key === '' + INTEGER_32_MAX) {
6248
- // See https://firebase.google.com/docs/database/web/lists-of-data#data-order
6249
- return MIN_PUSH_CHAR;
6250
- }
6251
- var keyAsInt = tryParseInt(key);
6252
- if (keyAsInt != null) {
6253
- return '' + (keyAsInt + 1);
6254
- }
6255
- var next = new Array(key.length);
6256
- for (var i_1 = 0; i_1 < next.length; i_1++) {
6257
- next[i_1] = key.charAt(i_1);
6258
- }
6259
- if (next.length < MAX_KEY_LEN) {
6260
- next.push(MIN_PUSH_CHAR);
6261
- return next.join('');
6262
- }
6263
- var i = next.length - 1;
6264
- while (i >= 0 && next[i] === MAX_PUSH_CHAR) {
6265
- i--;
6266
- }
6267
- // `successor` was called on the largest possible key, so return the
6268
- // MAX_NAME, which sorts larger than all keys.
6269
- if (i === -1) {
6270
- return MAX_NAME;
6271
- }
6272
- var source = next[i];
6273
- var sourcePlusOne = PUSH_CHARS.charAt(PUSH_CHARS.indexOf(source) + 1);
6274
- next[i] = sourcePlusOne;
6275
- return next.slice(0, i + 1).join('');
6276
- };
6277
- // `key` is assumed to be non-empty.
6278
- var predecessor = function (key) {
6279
- if (key === '' + INTEGER_32_MIN) {
6280
- return MIN_NAME;
6281
- }
6282
- var keyAsInt = tryParseInt(key);
6283
- if (keyAsInt != null) {
6284
- return '' + (keyAsInt - 1);
6285
- }
6286
- var next = new Array(key.length);
6287
- for (var i = 0; i < next.length; i++) {
6288
- next[i] = key.charAt(i);
6289
- }
6290
- // If `key` ends in `MIN_PUSH_CHAR`, the largest key lexicographically
6291
- // smaller than `key`, is `key[0:key.length - 1]`. The next key smaller
6292
- // than that, `predecessor(predecessor(key))`, is
6293
- //
6294
- // `key[0:key.length - 2] + (key[key.length - 1] - 1) + \
6295
- // { MAX_PUSH_CHAR repeated MAX_KEY_LEN - (key.length - 1) times }
6296
- //
6297
- // analogous to increment/decrement for base-10 integers.
6298
- //
6299
- // This works because lexigographic comparison works character-by-character,
6300
- // using length as a tie-breaker if one key is a prefix of the other.
6301
- if (next[next.length - 1] === MIN_PUSH_CHAR) {
6302
- if (next.length === 1) {
6303
- // See https://firebase.google.com/docs/database/web/lists-of-data#orderbykey
6304
- return '' + INTEGER_32_MAX;
6305
- }
6306
- delete next[next.length - 1];
6307
- return next.join('');
6308
- }
6309
- // Replace the last character with it's immediate predecessor, and
6310
- // fill the suffix of the key with MAX_PUSH_CHAR. This is the
6311
- // lexicographically largest possible key smaller than `key`.
6312
- next[next.length - 1] = PUSH_CHARS.charAt(PUSH_CHARS.indexOf(next[next.length - 1]) - 1);
6313
- return next.join('') + MAX_PUSH_CHAR.repeat(MAX_KEY_LEN - next.length);
6314
- };
6315
-
6316
6169
  /**
6317
6170
  * @license
6318
6171
  * Copyright 2017 Google LLC
@@ -6482,6 +6335,8 @@ var RangedFilter = /** @class */ (function () {
6482
6335
  this.index_ = params.getIndex();
6483
6336
  this.startPost_ = RangedFilter.getStartPost_(params);
6484
6337
  this.endPost_ = RangedFilter.getEndPost_(params);
6338
+ this.startIsInclusive_ = !params.startAfterSet_;
6339
+ this.endIsInclusive_ = !params.endBeforeSet_;
6485
6340
  }
6486
6341
  RangedFilter.prototype.getStartPost = function () {
6487
6342
  return this.startPost_;
@@ -6490,8 +6345,13 @@ var RangedFilter = /** @class */ (function () {
6490
6345
  return this.endPost_;
6491
6346
  };
6492
6347
  RangedFilter.prototype.matches = function (node) {
6493
- return (this.index_.compare(this.getStartPost(), node) <= 0 &&
6494
- this.index_.compare(node, this.getEndPost()) <= 0);
6348
+ var isWithinStart = this.startIsInclusive_
6349
+ ? this.index_.compare(this.getStartPost(), node) <= 0
6350
+ : this.index_.compare(this.getStartPost(), node) < 0;
6351
+ var isWithinEnd = this.endIsInclusive_
6352
+ ? this.index_.compare(node, this.getEndPost()) <= 0
6353
+ : this.index_.compare(node, this.getEndPost()) < 0;
6354
+ return isWithinStart && isWithinEnd;
6495
6355
  };
6496
6356
  RangedFilter.prototype.updateChild = function (snap, key, newChild, affectedPath, source, optChangeAccumulator) {
6497
6357
  if (!this.matches(new NamedNode(key, newChild))) {
@@ -6570,10 +6430,27 @@ var RangedFilter = /** @class */ (function () {
6570
6430
  */
6571
6431
  var LimitedFilter = /** @class */ (function () {
6572
6432
  function LimitedFilter(params) {
6433
+ var _this = this;
6434
+ this.withinDirectionalStart = function (node) {
6435
+ return _this.reverse_ ? _this.withinEndPost(node) : _this.withinStartPost(node);
6436
+ };
6437
+ this.withinDirectionalEnd = function (node) {
6438
+ return _this.reverse_ ? _this.withinStartPost(node) : _this.withinEndPost(node);
6439
+ };
6440
+ this.withinStartPost = function (node) {
6441
+ var compareRes = _this.index_.compare(_this.rangedFilter_.getStartPost(), node);
6442
+ return _this.startIsInclusive_ ? compareRes <= 0 : compareRes < 0;
6443
+ };
6444
+ this.withinEndPost = function (node) {
6445
+ var compareRes = _this.index_.compare(node, _this.rangedFilter_.getEndPost());
6446
+ return _this.endIsInclusive_ ? compareRes <= 0 : compareRes < 0;
6447
+ };
6573
6448
  this.rangedFilter_ = new RangedFilter(params);
6574
6449
  this.index_ = params.getIndex();
6575
6450
  this.limit_ = params.getLimit();
6576
6451
  this.reverse_ = !params.isViewFromLeft();
6452
+ this.startIsInclusive_ = !params.startAfterSet_;
6453
+ this.endIsInclusive_ = !params.endBeforeSet_;
6577
6454
  }
6578
6455
  LimitedFilter.prototype.updateChild = function (snap, key, newChild, affectedPath, source, optChangeAccumulator) {
6579
6456
  if (!this.rangedFilter_.matches(new NamedNode(key, newChild))) {
@@ -6614,23 +6491,18 @@ var LimitedFilter = /** @class */ (function () {
6614
6491
  var count = 0;
6615
6492
  while (iterator.hasNext() && count < this.limit_) {
6616
6493
  var next = iterator.getNext();
6617
- var inRange = void 0;
6618
- if (this.reverse_) {
6619
- inRange =
6620
- this.index_.compare(this.rangedFilter_.getStartPost(), next) <= 0;
6494
+ if (!this.withinDirectionalStart(next)) {
6495
+ // if we have not reached the start, skip to the next element
6496
+ continue;
6621
6497
  }
6622
- else {
6623
- inRange =
6624
- this.index_.compare(next, this.rangedFilter_.getEndPost()) <= 0;
6498
+ else if (!this.withinDirectionalEnd(next)) {
6499
+ // if we have reached the end, stop adding elements
6500
+ break;
6625
6501
  }
6626
- if (inRange) {
6502
+ else {
6627
6503
  filtered = filtered.updateImmediateChild(next.name, next.node);
6628
6504
  count++;
6629
6505
  }
6630
- else {
6631
- // if we have reached the end post, we cannot keep adding elemments
6632
- break;
6633
- }
6634
6506
  }
6635
6507
  }
6636
6508
  else {
@@ -6638,32 +6510,19 @@ var LimitedFilter = /** @class */ (function () {
6638
6510
  filtered = newSnap.withIndex(this.index_);
6639
6511
  // Don't support priorities on queries
6640
6512
  filtered = filtered.updatePriority(ChildrenNode.EMPTY_NODE);
6641
- var startPost = void 0;
6642
- var endPost = void 0;
6643
- var cmp = void 0;
6644
6513
  var iterator = void 0;
6645
6514
  if (this.reverse_) {
6646
6515
  iterator = filtered.getReverseIterator(this.index_);
6647
- startPost = this.rangedFilter_.getEndPost();
6648
- endPost = this.rangedFilter_.getStartPost();
6649
- var indexCompare_1 = this.index_.getCompare();
6650
- cmp = function (a, b) { return indexCompare_1(b, a); };
6651
6516
  }
6652
6517
  else {
6653
6518
  iterator = filtered.getIterator(this.index_);
6654
- startPost = this.rangedFilter_.getStartPost();
6655
- endPost = this.rangedFilter_.getEndPost();
6656
- cmp = this.index_.getCompare();
6657
6519
  }
6658
6520
  var count = 0;
6659
- var foundStartPost = false;
6660
6521
  while (iterator.hasNext()) {
6661
6522
  var next = iterator.getNext();
6662
- if (!foundStartPost && cmp(startPost, next) <= 0) {
6663
- // start adding
6664
- foundStartPost = true;
6665
- }
6666
- var inRange = foundStartPost && count < this.limit_ && cmp(next, endPost) <= 0;
6523
+ var inRange = count < this.limit_ &&
6524
+ this.withinDirectionalStart(next) &&
6525
+ this.withinDirectionalEnd(next);
6667
6526
  if (inRange) {
6668
6527
  count++;
6669
6528
  }
@@ -6795,10 +6654,10 @@ var QueryParams = /** @class */ (function () {
6795
6654
  this.limitSet_ = false;
6796
6655
  this.startSet_ = false;
6797
6656
  this.startNameSet_ = false;
6798
- this.startAfterSet_ = false;
6657
+ this.startAfterSet_ = false; // can only be true if startSet_ is true
6799
6658
  this.endSet_ = false;
6800
6659
  this.endNameSet_ = false;
6801
- this.endBeforeSet_ = false;
6660
+ this.endBeforeSet_ = false; // can only be true if endSet_ is true
6802
6661
  this.limit_ = 0;
6803
6662
  this.viewFrom_ = '';
6804
6663
  this.indexStartValue_ = null;
@@ -6810,12 +6669,6 @@ var QueryParams = /** @class */ (function () {
6810
6669
  QueryParams.prototype.hasStart = function () {
6811
6670
  return this.startSet_;
6812
6671
  };
6813
- QueryParams.prototype.hasStartAfter = function () {
6814
- return this.startAfterSet_;
6815
- };
6816
- QueryParams.prototype.hasEndBefore = function () {
6817
- return this.endBeforeSet_;
6818
- };
6819
6672
  /**
6820
6673
  * @returns True if it would return from left.
6821
6674
  */
@@ -6904,10 +6757,12 @@ var QueryParams = /** @class */ (function () {
6904
6757
  copy.limitSet_ = this.limitSet_;
6905
6758
  copy.limit_ = this.limit_;
6906
6759
  copy.startSet_ = this.startSet_;
6760
+ copy.startAfterSet_ = this.startAfterSet_;
6907
6761
  copy.indexStartValue_ = this.indexStartValue_;
6908
6762
  copy.startNameSet_ = this.startNameSet_;
6909
6763
  copy.indexStartName_ = this.indexStartName_;
6910
6764
  copy.endSet_ = this.endSet_;
6765
+ copy.endBeforeSet_ = this.endBeforeSet_;
6911
6766
  copy.indexEndValue_ = this.indexEndValue_;
6912
6767
  copy.endNameSet_ = this.endNameSet_;
6913
6768
  copy.indexEndName_ = this.indexEndName_;
@@ -6961,21 +6816,11 @@ function queryParamsStartAt(queryParams, indexValue, key) {
6961
6816
  }
6962
6817
  function queryParamsStartAfter(queryParams, indexValue, key) {
6963
6818
  var params;
6964
- if (queryParams.index_ === KEY_INDEX) {
6965
- if (typeof indexValue === 'string') {
6966
- indexValue = successor(indexValue);
6967
- }
6819
+ if (queryParams.index_ === KEY_INDEX || !!key) {
6968
6820
  params = queryParamsStartAt(queryParams, indexValue, key);
6969
6821
  }
6970
6822
  else {
6971
- var childKey = void 0;
6972
- if (key == null) {
6973
- childKey = MAX_NAME;
6974
- }
6975
- else {
6976
- childKey = successor(key);
6977
- }
6978
- params = queryParamsStartAt(queryParams, indexValue, childKey);
6823
+ params = queryParamsStartAt(queryParams, indexValue, MAX_NAME);
6979
6824
  }
6980
6825
  params.startAfterSet_ = true;
6981
6826
  return params;
@@ -6998,22 +6843,12 @@ function queryParamsEndAt(queryParams, indexValue, key) {
6998
6843
  return newParams;
6999
6844
  }
7000
6845
  function queryParamsEndBefore(queryParams, indexValue, key) {
7001
- var childKey;
7002
6846
  var params;
7003
- if (queryParams.index_ === KEY_INDEX) {
7004
- if (typeof indexValue === 'string') {
7005
- indexValue = predecessor(indexValue);
7006
- }
6847
+ if (queryParams.index_ === KEY_INDEX || !!key) {
7007
6848
  params = queryParamsEndAt(queryParams, indexValue, key);
7008
6849
  }
7009
6850
  else {
7010
- if (key == null) {
7011
- childKey = MIN_NAME;
7012
- }
7013
- else {
7014
- childKey = predecessor(key);
7015
- }
7016
- params = queryParamsEndAt(queryParams, indexValue, childKey);
6851
+ params = queryParamsEndAt(queryParams, indexValue, MIN_NAME);
7017
6852
  }
7018
6853
  params.endBeforeSet_ = true;
7019
6854
  return params;
@@ -7049,17 +6884,21 @@ function queryParamsToRestQueryStringParameters(queryParams) {
7049
6884
  }
7050
6885
  qs["orderBy" /* ORDER_BY */] = stringify(orderBy);
7051
6886
  if (queryParams.startSet_) {
7052
- qs["startAt" /* START_AT */] = stringify(queryParams.indexStartValue_);
6887
+ var startParam = queryParams.startAfterSet_
6888
+ ? "startAfter" /* START_AFTER */
6889
+ : "startAt" /* START_AT */;
6890
+ qs[startParam] = stringify(queryParams.indexStartValue_);
7053
6891
  if (queryParams.startNameSet_) {
7054
- qs["startAt" /* START_AT */] +=
7055
- ',' + stringify(queryParams.indexStartName_);
6892
+ qs[startParam] += ',' + stringify(queryParams.indexStartName_);
7056
6893
  }
7057
6894
  }
7058
6895
  if (queryParams.endSet_) {
7059
- qs["endAt" /* END_AT */] = stringify(queryParams.indexEndValue_);
6896
+ var endParam = queryParams.endBeforeSet_
6897
+ ? "endBefore" /* END_BEFORE */
6898
+ : "endAt" /* END_AT */;
6899
+ qs[endParam] = stringify(queryParams.indexEndValue_);
7060
6900
  if (queryParams.endNameSet_) {
7061
- qs["endAt" /* END_AT */] +=
7062
- ',' + stringify(queryParams.indexEndName_);
6901
+ qs[endParam] += ',' + stringify(queryParams.indexEndName_);
7063
6902
  }
7064
6903
  }
7065
6904
  if (queryParams.limitSet_) {
@@ -7081,12 +6920,16 @@ function queryParamsGetQueryObject(queryParams) {
7081
6920
  obj["sn" /* INDEX_START_NAME */] =
7082
6921
  queryParams.indexStartName_;
7083
6922
  }
6923
+ obj["sin" /* INDEX_START_IS_INCLUSIVE */] =
6924
+ !queryParams.startAfterSet_;
7084
6925
  }
7085
6926
  if (queryParams.endSet_) {
7086
6927
  obj["ep" /* INDEX_END_VALUE */] = queryParams.indexEndValue_;
7087
6928
  if (queryParams.endNameSet_) {
7088
6929
  obj["en" /* INDEX_END_NAME */] = queryParams.indexEndName_;
7089
6930
  }
6931
+ obj["ein" /* INDEX_END_IS_INCLUSIVE */] =
6932
+ !queryParams.endBeforeSet_;
7090
6933
  }
7091
6934
  if (queryParams.limitSet_) {
7092
6935
  obj["l" /* LIMIT */] = queryParams.limit_;
@@ -12360,6 +12203,81 @@ var parseDatabaseURL = function (dataURL) {
12360
12203
  };
12361
12204
  };
12362
12205
 
12206
+ /**
12207
+ * @license
12208
+ * Copyright 2017 Google LLC
12209
+ *
12210
+ * Licensed under the Apache License, Version 2.0 (the "License");
12211
+ * you may not use this file except in compliance with the License.
12212
+ * You may obtain a copy of the License at
12213
+ *
12214
+ * http://www.apache.org/licenses/LICENSE-2.0
12215
+ *
12216
+ * Unless required by applicable law or agreed to in writing, software
12217
+ * distributed under the License is distributed on an "AS IS" BASIS,
12218
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12219
+ * See the License for the specific language governing permissions and
12220
+ * limitations under the License.
12221
+ */
12222
+ // Modeled after base64 web-safe chars, but ordered by ASCII.
12223
+ var PUSH_CHARS = '-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz';
12224
+ /**
12225
+ * Fancy ID generator that creates 20-character string identifiers with the
12226
+ * following properties:
12227
+ *
12228
+ * 1. They're based on timestamp so that they sort *after* any existing ids.
12229
+ * 2. They contain 72-bits of random data after the timestamp so that IDs won't
12230
+ * collide with other clients' IDs.
12231
+ * 3. They sort *lexicographically* (so the timestamp is converted to characters
12232
+ * that will sort properly).
12233
+ * 4. They're monotonically increasing. Even if you generate more than one in
12234
+ * the same timestamp, the latter ones will sort after the former ones. We do
12235
+ * this by using the previous random bits but "incrementing" them by 1 (only
12236
+ * in the case of a timestamp collision).
12237
+ */
12238
+ var nextPushId = (function () {
12239
+ // Timestamp of last push, used to prevent local collisions if you push twice
12240
+ // in one ms.
12241
+ var lastPushTime = 0;
12242
+ // We generate 72-bits of randomness which get turned into 12 characters and
12243
+ // appended to the timestamp to prevent collisions with other clients. We
12244
+ // store the last characters we generated because in the event of a collision,
12245
+ // we'll use those same characters except "incremented" by one.
12246
+ var lastRandChars = [];
12247
+ return function (now) {
12248
+ var duplicateTime = now === lastPushTime;
12249
+ lastPushTime = now;
12250
+ var i;
12251
+ var timeStampChars = new Array(8);
12252
+ for (i = 7; i >= 0; i--) {
12253
+ timeStampChars[i] = PUSH_CHARS.charAt(now % 64);
12254
+ // NOTE: Can't use << here because javascript will convert to int and lose
12255
+ // the upper bits.
12256
+ now = Math.floor(now / 64);
12257
+ }
12258
+ assert(now === 0, 'Cannot push at time == 0');
12259
+ var id = timeStampChars.join('');
12260
+ if (!duplicateTime) {
12261
+ for (i = 0; i < 12; i++) {
12262
+ lastRandChars[i] = Math.floor(Math.random() * 64);
12263
+ }
12264
+ }
12265
+ else {
12266
+ // If the timestamp hasn't changed since last push, use the same random
12267
+ // number, except incremented by 1.
12268
+ for (i = 11; i >= 0 && lastRandChars[i] === 63; i--) {
12269
+ lastRandChars[i] = 0;
12270
+ }
12271
+ lastRandChars[i]++;
12272
+ }
12273
+ for (i = 0; i < 12; i++) {
12274
+ id += PUSH_CHARS.charAt(lastRandChars[i]);
12275
+ }
12276
+ assert(id.length === 20, 'nextPushId: Length should be 20.');
12277
+ return id;
12278
+ };
12279
+ })();
12280
+
12363
12281
  /**
12364
12282
  * @license
12365
12283
  * Copyright 2017 Google LLC