@firebase/database-compat 0.2.10-canary.e2a90bf67 → 0.2.10-canary.fde5adf63

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.
@@ -5,7 +5,7 @@ import { errorPrefix, validateArgCount, validateCallback, validateContextObject,
5
5
  import { Logger } from '@firebase/logger';
6
6
 
7
7
  const name = "@firebase/database-compat";
8
- const version = "0.2.10-canary.e2a90bf67";
8
+ const version = "0.2.10-canary.fde5adf63";
9
9
 
10
10
  /**
11
11
  * @license
@@ -6,7 +6,7 @@ import { __extends } from 'tslib';
6
6
  import { Logger } from '@firebase/logger';
7
7
 
8
8
  var name = "@firebase/database-compat";
9
- var version = "0.2.10-canary.e2a90bf67";
9
+ var version = "0.2.10-canary.fde5adf63";
10
10
 
11
11
  /**
12
12
  * @license
package/dist/index.js CHANGED
@@ -12,7 +12,7 @@ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'defau
12
12
  var firebase__default = /*#__PURE__*/_interopDefaultLegacy(firebase);
13
13
 
14
14
  var name = "@firebase/database-compat";
15
- var version = "0.2.10-canary.e2a90bf67";
15
+ var version = "0.2.10-canary.fde5adf63";
16
16
 
17
17
  /**
18
18
  * @license
@@ -9519,153 +9519,6 @@ var ValueIndex = /** @class */ (function (_super) {
9519
9519
  }(Index));
9520
9520
  var VALUE_INDEX = new ValueIndex();
9521
9521
 
9522
- /**
9523
- * @license
9524
- * Copyright 2017 Google LLC
9525
- *
9526
- * Licensed under the Apache License, Version 2.0 (the "License");
9527
- * you may not use this file except in compliance with the License.
9528
- * You may obtain a copy of the License at
9529
- *
9530
- * http://www.apache.org/licenses/LICENSE-2.0
9531
- *
9532
- * Unless required by applicable law or agreed to in writing, software
9533
- * distributed under the License is distributed on an "AS IS" BASIS,
9534
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9535
- * See the License for the specific language governing permissions and
9536
- * limitations under the License.
9537
- */
9538
- // Modeled after base64 web-safe chars, but ordered by ASCII.
9539
- var PUSH_CHARS = '-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz';
9540
- var MIN_PUSH_CHAR = '-';
9541
- var MAX_PUSH_CHAR = 'z';
9542
- var MAX_KEY_LEN = 786;
9543
- /**
9544
- * Fancy ID generator that creates 20-character string identifiers with the
9545
- * following properties:
9546
- *
9547
- * 1. They're based on timestamp so that they sort *after* any existing ids.
9548
- * 2. They contain 72-bits of random data after the timestamp so that IDs won't
9549
- * collide with other clients' IDs.
9550
- * 3. They sort *lexicographically* (so the timestamp is converted to characters
9551
- * that will sort properly).
9552
- * 4. They're monotonically increasing. Even if you generate more than one in
9553
- * the same timestamp, the latter ones will sort after the former ones. We do
9554
- * this by using the previous random bits but "incrementing" them by 1 (only
9555
- * in the case of a timestamp collision).
9556
- */
9557
- var nextPushId = (function () {
9558
- // Timestamp of last push, used to prevent local collisions if you push twice
9559
- // in one ms.
9560
- var lastPushTime = 0;
9561
- // We generate 72-bits of randomness which get turned into 12 characters and
9562
- // appended to the timestamp to prevent collisions with other clients. We
9563
- // store the last characters we generated because in the event of a collision,
9564
- // we'll use those same characters except "incremented" by one.
9565
- var lastRandChars = [];
9566
- return function (now) {
9567
- var duplicateTime = now === lastPushTime;
9568
- lastPushTime = now;
9569
- var i;
9570
- var timeStampChars = new Array(8);
9571
- for (i = 7; i >= 0; i--) {
9572
- timeStampChars[i] = PUSH_CHARS.charAt(now % 64);
9573
- // NOTE: Can't use << here because javascript will convert to int and lose
9574
- // the upper bits.
9575
- now = Math.floor(now / 64);
9576
- }
9577
- util.assert(now === 0, 'Cannot push at time == 0');
9578
- var id = timeStampChars.join('');
9579
- if (!duplicateTime) {
9580
- for (i = 0; i < 12; i++) {
9581
- lastRandChars[i] = Math.floor(Math.random() * 64);
9582
- }
9583
- }
9584
- else {
9585
- // If the timestamp hasn't changed since last push, use the same random
9586
- // number, except incremented by 1.
9587
- for (i = 11; i >= 0 && lastRandChars[i] === 63; i--) {
9588
- lastRandChars[i] = 0;
9589
- }
9590
- lastRandChars[i]++;
9591
- }
9592
- for (i = 0; i < 12; i++) {
9593
- id += PUSH_CHARS.charAt(lastRandChars[i]);
9594
- }
9595
- util.assert(id.length === 20, 'nextPushId: Length should be 20.');
9596
- return id;
9597
- };
9598
- })();
9599
- var successor = function (key) {
9600
- if (key === '' + INTEGER_32_MAX) {
9601
- // See https://firebase.google.com/docs/database/web/lists-of-data#data-order
9602
- return MIN_PUSH_CHAR;
9603
- }
9604
- var keyAsInt = tryParseInt(key);
9605
- if (keyAsInt != null) {
9606
- return '' + (keyAsInt + 1);
9607
- }
9608
- var next = new Array(key.length);
9609
- for (var i_1 = 0; i_1 < next.length; i_1++) {
9610
- next[i_1] = key.charAt(i_1);
9611
- }
9612
- if (next.length < MAX_KEY_LEN) {
9613
- next.push(MIN_PUSH_CHAR);
9614
- return next.join('');
9615
- }
9616
- var i = next.length - 1;
9617
- while (i >= 0 && next[i] === MAX_PUSH_CHAR) {
9618
- i--;
9619
- }
9620
- // `successor` was called on the largest possible key, so return the
9621
- // MAX_NAME, which sorts larger than all keys.
9622
- if (i === -1) {
9623
- return MAX_NAME;
9624
- }
9625
- var source = next[i];
9626
- var sourcePlusOne = PUSH_CHARS.charAt(PUSH_CHARS.indexOf(source) + 1);
9627
- next[i] = sourcePlusOne;
9628
- return next.slice(0, i + 1).join('');
9629
- };
9630
- // `key` is assumed to be non-empty.
9631
- var predecessor = function (key) {
9632
- if (key === '' + INTEGER_32_MIN) {
9633
- return MIN_NAME;
9634
- }
9635
- var keyAsInt = tryParseInt(key);
9636
- if (keyAsInt != null) {
9637
- return '' + (keyAsInt - 1);
9638
- }
9639
- var next = new Array(key.length);
9640
- for (var i = 0; i < next.length; i++) {
9641
- next[i] = key.charAt(i);
9642
- }
9643
- // If `key` ends in `MIN_PUSH_CHAR`, the largest key lexicographically
9644
- // smaller than `key`, is `key[0:key.length - 1]`. The next key smaller
9645
- // than that, `predecessor(predecessor(key))`, is
9646
- //
9647
- // `key[0:key.length - 2] + (key[key.length - 1] - 1) + \
9648
- // { MAX_PUSH_CHAR repeated MAX_KEY_LEN - (key.length - 1) times }
9649
- //
9650
- // analogous to increment/decrement for base-10 integers.
9651
- //
9652
- // This works because lexigographic comparison works character-by-character,
9653
- // using length as a tie-breaker if one key is a prefix of the other.
9654
- if (next[next.length - 1] === MIN_PUSH_CHAR) {
9655
- if (next.length === 1) {
9656
- // See https://firebase.google.com/docs/database/web/lists-of-data#orderbykey
9657
- return '' + INTEGER_32_MAX;
9658
- }
9659
- delete next[next.length - 1];
9660
- return next.join('');
9661
- }
9662
- // Replace the last character with it's immediate predecessor, and
9663
- // fill the suffix of the key with MAX_PUSH_CHAR. This is the
9664
- // lexicographically largest possible key smaller than `key`.
9665
- next[next.length - 1] = PUSH_CHARS.charAt(PUSH_CHARS.indexOf(next[next.length - 1]) - 1);
9666
- return next.join('') + MAX_PUSH_CHAR.repeat(MAX_KEY_LEN - next.length);
9667
- };
9668
-
9669
9522
  /**
9670
9523
  * @license
9671
9524
  * Copyright 2017 Google LLC
@@ -9835,6 +9688,8 @@ var RangedFilter = /** @class */ (function () {
9835
9688
  this.index_ = params.getIndex();
9836
9689
  this.startPost_ = RangedFilter.getStartPost_(params);
9837
9690
  this.endPost_ = RangedFilter.getEndPost_(params);
9691
+ this.startIsInclusive_ = !params.startAfterSet_;
9692
+ this.endIsInclusive_ = !params.endBeforeSet_;
9838
9693
  }
9839
9694
  RangedFilter.prototype.getStartPost = function () {
9840
9695
  return this.startPost_;
@@ -9843,8 +9698,13 @@ var RangedFilter = /** @class */ (function () {
9843
9698
  return this.endPost_;
9844
9699
  };
9845
9700
  RangedFilter.prototype.matches = function (node) {
9846
- return (this.index_.compare(this.getStartPost(), node) <= 0 &&
9847
- this.index_.compare(node, this.getEndPost()) <= 0);
9701
+ var isWithinStart = this.startIsInclusive_
9702
+ ? this.index_.compare(this.getStartPost(), node) <= 0
9703
+ : this.index_.compare(this.getStartPost(), node) < 0;
9704
+ var isWithinEnd = this.endIsInclusive_
9705
+ ? this.index_.compare(node, this.getEndPost()) <= 0
9706
+ : this.index_.compare(node, this.getEndPost()) < 0;
9707
+ return isWithinStart && isWithinEnd;
9848
9708
  };
9849
9709
  RangedFilter.prototype.updateChild = function (snap, key, newChild, affectedPath, source, optChangeAccumulator) {
9850
9710
  if (!this.matches(new NamedNode(key, newChild))) {
@@ -9923,10 +9783,27 @@ var RangedFilter = /** @class */ (function () {
9923
9783
  */
9924
9784
  var LimitedFilter = /** @class */ (function () {
9925
9785
  function LimitedFilter(params) {
9786
+ var _this = this;
9787
+ this.withinDirectionalStart = function (node) {
9788
+ return _this.reverse_ ? _this.withinEndPost(node) : _this.withinStartPost(node);
9789
+ };
9790
+ this.withinDirectionalEnd = function (node) {
9791
+ return _this.reverse_ ? _this.withinStartPost(node) : _this.withinEndPost(node);
9792
+ };
9793
+ this.withinStartPost = function (node) {
9794
+ var compareRes = _this.index_.compare(_this.rangedFilter_.getStartPost(), node);
9795
+ return _this.startIsInclusive_ ? compareRes <= 0 : compareRes < 0;
9796
+ };
9797
+ this.withinEndPost = function (node) {
9798
+ var compareRes = _this.index_.compare(node, _this.rangedFilter_.getEndPost());
9799
+ return _this.endIsInclusive_ ? compareRes <= 0 : compareRes < 0;
9800
+ };
9926
9801
  this.rangedFilter_ = new RangedFilter(params);
9927
9802
  this.index_ = params.getIndex();
9928
9803
  this.limit_ = params.getLimit();
9929
9804
  this.reverse_ = !params.isViewFromLeft();
9805
+ this.startIsInclusive_ = !params.startAfterSet_;
9806
+ this.endIsInclusive_ = !params.endBeforeSet_;
9930
9807
  }
9931
9808
  LimitedFilter.prototype.updateChild = function (snap, key, newChild, affectedPath, source, optChangeAccumulator) {
9932
9809
  if (!this.rangedFilter_.matches(new NamedNode(key, newChild))) {
@@ -9967,23 +9844,18 @@ var LimitedFilter = /** @class */ (function () {
9967
9844
  var count = 0;
9968
9845
  while (iterator.hasNext() && count < this.limit_) {
9969
9846
  var next = iterator.getNext();
9970
- var inRange = void 0;
9971
- if (this.reverse_) {
9972
- inRange =
9973
- this.index_.compare(this.rangedFilter_.getStartPost(), next) <= 0;
9847
+ if (!this.withinDirectionalStart(next)) {
9848
+ // if we have not reached the start, skip to the next element
9849
+ continue;
9974
9850
  }
9975
- else {
9976
- inRange =
9977
- this.index_.compare(next, this.rangedFilter_.getEndPost()) <= 0;
9851
+ else if (!this.withinDirectionalEnd(next)) {
9852
+ // if we have reached the end, stop adding elements
9853
+ break;
9978
9854
  }
9979
- if (inRange) {
9855
+ else {
9980
9856
  filtered = filtered.updateImmediateChild(next.name, next.node);
9981
9857
  count++;
9982
9858
  }
9983
- else {
9984
- // if we have reached the end post, we cannot keep adding elemments
9985
- break;
9986
- }
9987
9859
  }
9988
9860
  }
9989
9861
  else {
@@ -9991,32 +9863,19 @@ var LimitedFilter = /** @class */ (function () {
9991
9863
  filtered = newSnap.withIndex(this.index_);
9992
9864
  // Don't support priorities on queries
9993
9865
  filtered = filtered.updatePriority(ChildrenNode.EMPTY_NODE);
9994
- var startPost = void 0;
9995
- var endPost = void 0;
9996
- var cmp = void 0;
9997
9866
  var iterator = void 0;
9998
9867
  if (this.reverse_) {
9999
9868
  iterator = filtered.getReverseIterator(this.index_);
10000
- startPost = this.rangedFilter_.getEndPost();
10001
- endPost = this.rangedFilter_.getStartPost();
10002
- var indexCompare_1 = this.index_.getCompare();
10003
- cmp = function (a, b) { return indexCompare_1(b, a); };
10004
9869
  }
10005
9870
  else {
10006
9871
  iterator = filtered.getIterator(this.index_);
10007
- startPost = this.rangedFilter_.getStartPost();
10008
- endPost = this.rangedFilter_.getEndPost();
10009
- cmp = this.index_.getCompare();
10010
9872
  }
10011
9873
  var count = 0;
10012
- var foundStartPost = false;
10013
9874
  while (iterator.hasNext()) {
10014
9875
  var next = iterator.getNext();
10015
- if (!foundStartPost && cmp(startPost, next) <= 0) {
10016
- // start adding
10017
- foundStartPost = true;
10018
- }
10019
- var inRange = foundStartPost && count < this.limit_ && cmp(next, endPost) <= 0;
9876
+ var inRange = count < this.limit_ &&
9877
+ this.withinDirectionalStart(next) &&
9878
+ this.withinDirectionalEnd(next);
10020
9879
  if (inRange) {
10021
9880
  count++;
10022
9881
  }
@@ -10148,10 +10007,10 @@ var QueryParams = /** @class */ (function () {
10148
10007
  this.limitSet_ = false;
10149
10008
  this.startSet_ = false;
10150
10009
  this.startNameSet_ = false;
10151
- this.startAfterSet_ = false;
10010
+ this.startAfterSet_ = false; // can only be true if startSet_ is true
10152
10011
  this.endSet_ = false;
10153
10012
  this.endNameSet_ = false;
10154
- this.endBeforeSet_ = false;
10013
+ this.endBeforeSet_ = false; // can only be true if endSet_ is true
10155
10014
  this.limit_ = 0;
10156
10015
  this.viewFrom_ = '';
10157
10016
  this.indexStartValue_ = null;
@@ -10163,12 +10022,6 @@ var QueryParams = /** @class */ (function () {
10163
10022
  QueryParams.prototype.hasStart = function () {
10164
10023
  return this.startSet_;
10165
10024
  };
10166
- QueryParams.prototype.hasStartAfter = function () {
10167
- return this.startAfterSet_;
10168
- };
10169
- QueryParams.prototype.hasEndBefore = function () {
10170
- return this.endBeforeSet_;
10171
- };
10172
10025
  /**
10173
10026
  * @returns True if it would return from left.
10174
10027
  */
@@ -10257,10 +10110,12 @@ var QueryParams = /** @class */ (function () {
10257
10110
  copy.limitSet_ = this.limitSet_;
10258
10111
  copy.limit_ = this.limit_;
10259
10112
  copy.startSet_ = this.startSet_;
10113
+ copy.startAfterSet_ = this.startAfterSet_;
10260
10114
  copy.indexStartValue_ = this.indexStartValue_;
10261
10115
  copy.startNameSet_ = this.startNameSet_;
10262
10116
  copy.indexStartName_ = this.indexStartName_;
10263
10117
  copy.endSet_ = this.endSet_;
10118
+ copy.endBeforeSet_ = this.endBeforeSet_;
10264
10119
  copy.indexEndValue_ = this.indexEndValue_;
10265
10120
  copy.endNameSet_ = this.endNameSet_;
10266
10121
  copy.indexEndName_ = this.indexEndName_;
@@ -10314,21 +10169,11 @@ function queryParamsStartAt(queryParams, indexValue, key) {
10314
10169
  }
10315
10170
  function queryParamsStartAfter(queryParams, indexValue, key) {
10316
10171
  var params;
10317
- if (queryParams.index_ === KEY_INDEX) {
10318
- if (typeof indexValue === 'string') {
10319
- indexValue = successor(indexValue);
10320
- }
10172
+ if (queryParams.index_ === KEY_INDEX || !!key) {
10321
10173
  params = queryParamsStartAt(queryParams, indexValue, key);
10322
10174
  }
10323
10175
  else {
10324
- var childKey = void 0;
10325
- if (key == null) {
10326
- childKey = MAX_NAME;
10327
- }
10328
- else {
10329
- childKey = successor(key);
10330
- }
10331
- params = queryParamsStartAt(queryParams, indexValue, childKey);
10176
+ params = queryParamsStartAt(queryParams, indexValue, MAX_NAME);
10332
10177
  }
10333
10178
  params.startAfterSet_ = true;
10334
10179
  return params;
@@ -10351,22 +10196,12 @@ function queryParamsEndAt(queryParams, indexValue, key) {
10351
10196
  return newParams;
10352
10197
  }
10353
10198
  function queryParamsEndBefore(queryParams, indexValue, key) {
10354
- var childKey;
10355
10199
  var params;
10356
- if (queryParams.index_ === KEY_INDEX) {
10357
- if (typeof indexValue === 'string') {
10358
- indexValue = predecessor(indexValue);
10359
- }
10200
+ if (queryParams.index_ === KEY_INDEX || !!key) {
10360
10201
  params = queryParamsEndAt(queryParams, indexValue, key);
10361
10202
  }
10362
10203
  else {
10363
- if (key == null) {
10364
- childKey = MIN_NAME;
10365
- }
10366
- else {
10367
- childKey = predecessor(key);
10368
- }
10369
- params = queryParamsEndAt(queryParams, indexValue, childKey);
10204
+ params = queryParamsEndAt(queryParams, indexValue, MIN_NAME);
10370
10205
  }
10371
10206
  params.endBeforeSet_ = true;
10372
10207
  return params;
@@ -10402,17 +10237,21 @@ function queryParamsToRestQueryStringParameters(queryParams) {
10402
10237
  }
10403
10238
  qs["orderBy" /* ORDER_BY */] = util.stringify(orderBy);
10404
10239
  if (queryParams.startSet_) {
10405
- qs["startAt" /* START_AT */] = util.stringify(queryParams.indexStartValue_);
10240
+ var startParam = queryParams.startAfterSet_
10241
+ ? "startAfter" /* START_AFTER */
10242
+ : "startAt" /* START_AT */;
10243
+ qs[startParam] = util.stringify(queryParams.indexStartValue_);
10406
10244
  if (queryParams.startNameSet_) {
10407
- qs["startAt" /* START_AT */] +=
10408
- ',' + util.stringify(queryParams.indexStartName_);
10245
+ qs[startParam] += ',' + util.stringify(queryParams.indexStartName_);
10409
10246
  }
10410
10247
  }
10411
10248
  if (queryParams.endSet_) {
10412
- qs["endAt" /* END_AT */] = util.stringify(queryParams.indexEndValue_);
10249
+ var endParam = queryParams.endBeforeSet_
10250
+ ? "endBefore" /* END_BEFORE */
10251
+ : "endAt" /* END_AT */;
10252
+ qs[endParam] = util.stringify(queryParams.indexEndValue_);
10413
10253
  if (queryParams.endNameSet_) {
10414
- qs["endAt" /* END_AT */] +=
10415
- ',' + util.stringify(queryParams.indexEndName_);
10254
+ qs[endParam] += ',' + util.stringify(queryParams.indexEndName_);
10416
10255
  }
10417
10256
  }
10418
10257
  if (queryParams.limitSet_) {
@@ -10434,12 +10273,16 @@ function queryParamsGetQueryObject(queryParams) {
10434
10273
  obj["sn" /* INDEX_START_NAME */] =
10435
10274
  queryParams.indexStartName_;
10436
10275
  }
10276
+ obj["sin" /* INDEX_START_IS_INCLUSIVE */] =
10277
+ !queryParams.startAfterSet_;
10437
10278
  }
10438
10279
  if (queryParams.endSet_) {
10439
10280
  obj["ep" /* INDEX_END_VALUE */] = queryParams.indexEndValue_;
10440
10281
  if (queryParams.endNameSet_) {
10441
10282
  obj["en" /* INDEX_END_NAME */] = queryParams.indexEndName_;
10442
10283
  }
10284
+ obj["ein" /* INDEX_END_IS_INCLUSIVE */] =
10285
+ !queryParams.endBeforeSet_;
10443
10286
  }
10444
10287
  if (queryParams.limitSet_) {
10445
10288
  obj["l" /* LIMIT */] = queryParams.limit_;
@@ -15713,6 +15556,81 @@ var parseDatabaseURL = function (dataURL) {
15713
15556
  };
15714
15557
  };
15715
15558
 
15559
+ /**
15560
+ * @license
15561
+ * Copyright 2017 Google LLC
15562
+ *
15563
+ * Licensed under the Apache License, Version 2.0 (the "License");
15564
+ * you may not use this file except in compliance with the License.
15565
+ * You may obtain a copy of the License at
15566
+ *
15567
+ * http://www.apache.org/licenses/LICENSE-2.0
15568
+ *
15569
+ * Unless required by applicable law or agreed to in writing, software
15570
+ * distributed under the License is distributed on an "AS IS" BASIS,
15571
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15572
+ * See the License for the specific language governing permissions and
15573
+ * limitations under the License.
15574
+ */
15575
+ // Modeled after base64 web-safe chars, but ordered by ASCII.
15576
+ var PUSH_CHARS = '-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz';
15577
+ /**
15578
+ * Fancy ID generator that creates 20-character string identifiers with the
15579
+ * following properties:
15580
+ *
15581
+ * 1. They're based on timestamp so that they sort *after* any existing ids.
15582
+ * 2. They contain 72-bits of random data after the timestamp so that IDs won't
15583
+ * collide with other clients' IDs.
15584
+ * 3. They sort *lexicographically* (so the timestamp is converted to characters
15585
+ * that will sort properly).
15586
+ * 4. They're monotonically increasing. Even if you generate more than one in
15587
+ * the same timestamp, the latter ones will sort after the former ones. We do
15588
+ * this by using the previous random bits but "incrementing" them by 1 (only
15589
+ * in the case of a timestamp collision).
15590
+ */
15591
+ var nextPushId = (function () {
15592
+ // Timestamp of last push, used to prevent local collisions if you push twice
15593
+ // in one ms.
15594
+ var lastPushTime = 0;
15595
+ // We generate 72-bits of randomness which get turned into 12 characters and
15596
+ // appended to the timestamp to prevent collisions with other clients. We
15597
+ // store the last characters we generated because in the event of a collision,
15598
+ // we'll use those same characters except "incremented" by one.
15599
+ var lastRandChars = [];
15600
+ return function (now) {
15601
+ var duplicateTime = now === lastPushTime;
15602
+ lastPushTime = now;
15603
+ var i;
15604
+ var timeStampChars = new Array(8);
15605
+ for (i = 7; i >= 0; i--) {
15606
+ timeStampChars[i] = PUSH_CHARS.charAt(now % 64);
15607
+ // NOTE: Can't use << here because javascript will convert to int and lose
15608
+ // the upper bits.
15609
+ now = Math.floor(now / 64);
15610
+ }
15611
+ util.assert(now === 0, 'Cannot push at time == 0');
15612
+ var id = timeStampChars.join('');
15613
+ if (!duplicateTime) {
15614
+ for (i = 0; i < 12; i++) {
15615
+ lastRandChars[i] = Math.floor(Math.random() * 64);
15616
+ }
15617
+ }
15618
+ else {
15619
+ // If the timestamp hasn't changed since last push, use the same random
15620
+ // number, except incremented by 1.
15621
+ for (i = 11; i >= 0 && lastRandChars[i] === 63; i--) {
15622
+ lastRandChars[i] = 0;
15623
+ }
15624
+ lastRandChars[i]++;
15625
+ }
15626
+ for (i = 0; i < 12; i++) {
15627
+ id += PUSH_CHARS.charAt(lastRandChars[i]);
15628
+ }
15629
+ util.assert(id.length === 20, 'nextPushId: Length should be 20.');
15630
+ return id;
15631
+ };
15632
+ })();
15633
+
15716
15634
  /**
15717
15635
  * @license
15718
15636
  * Copyright 2017 Google LLC