indexeddbshim 17.3.0 → 17.3.2

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 +1 @@
1
- {"version":3,"file":"setGlobalVars.d.ts","sourceRoot":"","sources":["../src/setGlobalVars.js"],"names":[],"mappings":";;uBAkBa,GAAG;+BAKL,OAAO,UAAU,EAAE,iBAAiB,GAC1C,OAAO,CAAC,OAAO,UAAU,EAAE,YAAY,CAAC,QAClC,QAAQ;wBAoCN,CACR,IAAI,EAAE,OAAO,UAAU,EAAE,iBAAiB,KACvC,OAAO,UAAU,EAAE,WAAW;oCAIzB,CAAC,GAAG,EAAE;IACd,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAA;CAC1B,KAAK,IAAI;4BAIA,CAAC,UAAU,GAAC,MAAM,CAAC,GAAG;IAC5B,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,OAAO,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;IAChC,WAAW,EAAE,SAAS,CAAC;IACvB,WAAW,EAAE,SAAS,CAAC;IACvB,uBAAuB,EAAE,qBAAqB,CAAC;IAC/C,0BAA0B,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,CAAA;CACtD;sBAIO,MAAM;4BAIN,CAAC,OAAO,UAAU,GAAC,MAAM,CAAC,GAAG;IACrC,SAAS,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IAChC,UAAU,EAAE,OAAO,UAAU,CAAC;IAC9B,gBAAgB,EAAE,OAAO,gBAAgB,CAAC;IAC1C,UAAU,EAAE,OAAO,UAAU,CAAC;IAC9B,kBAAkB,EAAE,OAAO,kBAAkB,CAAC;IAC9C,SAAS,EAAE,OAAO,SAAS,CAAC;IAC5B,WAAW,EAAE,OAAO,WAAW,CAAC;IAChC,cAAc,EAAE,OAAO,cAAc,CAAC;IACtC,WAAW,EAAE,OAAO,WAAW,CAAC;IAChC,aAAa,CAAC,EAAE,aAAa,CAAA;CAC9B;mCAhG+C,mBAAmB;AAwDtE;;;;GAIG;AAEH;;;;;GAKG;AAEH;;;;;;;;;GASG;AAEH;;GAEG;AAEH;;;;;;;;;;;;;GAaG;AAEH;;;;;GAKG;AACH,qCAJW,aAAa,kBACb,OAAO,CAAC,OAAO,UAAU,EAAE,YAAY,CAAC,GACtC,aAAa,CAkSzB;2BAxY8C,iBAAiB"}
1
+ {"version":3,"file":"setGlobalVars.d.ts","sourceRoot":"","sources":["../src/setGlobalVars.js"],"names":[],"mappings":";;uBAkBa,GAAG;+BAKL,OAAO,UAAU,EAAE,iBAAiB,GAC1C,OAAO,CAAC,OAAO,UAAU,EAAE,YAAY,CAAC,QAClC,QAAQ;wBAoCN,CACR,IAAI,EAAE,OAAO,UAAU,EAAE,iBAAiB,KACvC,OAAO,UAAU,EAAE,WAAW;oCAIzB,CAAC,GAAG,EAAE;IACd,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAA;CAC1B,KAAK,IAAI;4BAIA,CAAC,UAAU,GAAC,MAAM,CAAC,GAAG;IAC5B,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,OAAO,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;IAChC,WAAW,EAAE,SAAS,CAAC;IACvB,WAAW,EAAE,SAAS,CAAC;IACvB,uBAAuB,EAAE,qBAAqB,CAAC;IAC/C,0BAA0B,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,CAAA;CACtD;sBAIO,MAAM;4BAIN,CAAC,OAAO,UAAU,GAAC,MAAM,CAAC,GAAG;IACrC,SAAS,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IAChC,UAAU,EAAE,OAAO,UAAU,CAAC;IAC9B,gBAAgB,EAAE,OAAO,gBAAgB,CAAC;IAC1C,UAAU,EAAE,OAAO,UAAU,CAAC;IAC9B,kBAAkB,EAAE,OAAO,kBAAkB,CAAC;IAC9C,SAAS,EAAE,OAAO,SAAS,CAAC;IAC5B,WAAW,EAAE,OAAO,WAAW,CAAC;IAChC,cAAc,EAAE,OAAO,cAAc,CAAC;IACtC,WAAW,EAAE,OAAO,WAAW,CAAC;IAChC,aAAa,CAAC,EAAE,aAAa,CAAA;CAC9B;mCAhG+C,mBAAmB;AAwDtE;;;;GAIG;AAEH;;;;;GAKG;AAEH;;;;;;;;;GASG;AAEH;;GAEG;AAEH;;;;;;;;;;;;;GAaG;AAEH;;;;;GAKG;AACH,qCAJW,aAAa,kBACb,OAAO,CAAC,OAAO,UAAU,EAAE,YAAY,CAAC,GACtC,aAAa,CAkTzB;2BAxZ8C,iBAAiB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "indexeddbshim",
3
- "version": "17.3.0",
3
+ "version": "17.3.2",
4
4
  "type": "module",
5
5
  "author": "Parashuram <code@nparashuram.com>",
6
6
  "contributors": [
@@ -102,6 +102,7 @@
102
102
  "w3c-test": "run-s clean-w3c test-and-start:w3c",
103
103
  "w3c-good-only": "NODE_OPTIONS=--max_old_space_size=16384 node test-support/node-idb-test.js good",
104
104
  "w3c-bad-only": "NODE_OPTIONS=--max_old_space_size=16384 node test-support/node-idb-test.js bad",
105
+ "w3c-good-worker-only": "NODE_OPTIONS=--max_old_space_size=16384 node test-support/node-idb-test.js good-worker",
105
106
  "w3c-good": "run-s w3c-build w3c-good-only clean-w3c",
106
107
  "w3c-bad": "run-s w3c-build w3c-bad-only clean-w3c",
107
108
  "w3c-good-test": "run-s w3c-good-only clean-w3c",
@@ -171,7 +172,7 @@
171
172
  "eventtargeter": "0.12.0",
172
173
  "sync-promise-expanded": "^2.0.0",
173
174
  "typeson": "10.2.0",
174
- "typeson-registry": "14.2.1",
175
+ "typeson-registry": "14.2.2",
175
176
  "websql-configurable": "^3.0.6"
176
177
  },
177
178
  "devDependencies": {
package/src/IDBFactory.js CHANGED
@@ -668,7 +668,22 @@ IDBFactory.prototype.open = function (name /* , version */) {
668
668
  // open/close the transaction's active-handler window itself.
669
669
  req.transaction.__handlerActive = true;
670
670
  req.dispatchEvent(e);
671
- req.transaction.__handlerActive = false;
671
+ // Give any same-tick microtask scheduled from within the
672
+ // `upgradeneeded` handler (e.g. a plain
673
+ // `Promise.resolve().then(...)`) a chance to run -- and still
674
+ // observe the transaction as active -- before we deactivate it
675
+ // again, per https://github.com/w3c/IndexedDB/issues/87. Only
676
+ // the flag reset itself is deferred here -- unlike
677
+ // `IDBTransaction.js`'s `advanceAfterDispatch`, `finished()`
678
+ // (this transaction's own queue-advancement/completion signal)
679
+ // still runs synchronously, at exactly its previous timing: an
680
+ // earlier attempt at deferring `finished()` too raced against
681
+ // unrelated test setup that assumed a freshly deleted/created
682
+ // database's upgrade transaction had already fully completed by
683
+ // the time this function returns.
684
+ queueMicrotask(() => {
685
+ req.transaction.__handlerActive = false;
686
+ });
672
687
 
673
688
  if (e.__legacyOutputDidListenersThrowError) {
674
689
  logError('Error', 'An error occurred in an upgradeneeded handler attached to request chain', /** @type {Error} */ (e.__legacyOutputDidListenersThrowError)); // We do nothing else with this error as per spec
@@ -6,6 +6,7 @@ import DOMStringList from './DOMStringList.js';
6
6
  import * as util from './util.js';
7
7
  import * as Key from './Key.js';
8
8
  import {executeFetchIndexData, buildFetchIndexDataSQL, IDBIndex} from './IDBIndex.js';
9
+ import cmp from './cmp.js';
9
10
  import IDBTransaction from './IDBTransaction.js';
10
11
  import * as Sca from './Sca.js';
11
12
  import CFG from './CFG.js';
@@ -69,6 +70,11 @@ const IDBObjectStoreAlias = IDBObjectStore;
69
70
  * success: (key: import('./Key.js').Key, cn?: Integer) => void,
70
71
  * failCb: import('./Key.js').SQLFailureCallback
71
72
  * ) => void,
73
+ * __checkIndexConstraints: (
74
+ * tx: WebSQLTransaction,
75
+ * value: import('./Key.js').Value,
76
+ * excludeKey: import('./Key.js').Key|Integer|undefined
77
+ * ) => SyncPromise,
72
78
  * __insertData: (
73
79
  * tx: WebSQLTransaction,
74
80
  * encoded: string,
@@ -518,6 +524,77 @@ IDBObjectStore.prototype.__deriveKey = function (tx, value, key, success, failCb
518
524
  }
519
525
  };
520
526
 
527
+ /**
528
+ * Validates `value`'s unique index entries against the table's *current*
529
+ * state without mutating anything -- used by `__storingRecordObjectStore`
530
+ * to check a `put()`'s constraints *before* `__overwrite` deletes the
531
+ * existing row for that key, so a rejected `put()` can't end up losing
532
+ * the record it was trying to replace (see
533
+ * `idbobjectstore-put-unique-index-constraint-is-atomic.any.js`).
534
+ * `excludeKey`, when given, treats a conflicting record as a non-conflict
535
+ * if it's the very record being overwritten (its own current entry would
536
+ * otherwise self-conflict on every no-op `put()` of an unchanged value).
537
+ * `__insertData` below still runs its own (now redundant, but harmless --
538
+ * the old row is gone by then) equivalent check as its first step; this
539
+ * isn't merged into it because `__insertData` also performs the actual
540
+ * `INSERT`, which cannot safely run before `__overwrite`'s `DELETE` when
541
+ * overwriting an existing key.
542
+ * @param {WebSQLTransaction} tx
543
+ * @param {import('./Key.js').Value} value
544
+ * @param {import('./Key.js').Key|Integer|undefined} excludeKey
545
+ * @this {IDBObjectStoreFull}
546
+ * @returns {SyncPromise}
547
+ */
548
+ IDBObjectStore.prototype.__checkIndexConstraints = function (tx, value, excludeKey) {
549
+ const me = this;
550
+ const indexPromises = Object.keys(me.__indexes).map((indexName) => {
551
+ return new SyncPromise((resolve, reject) => {
552
+ const index = me.__indexes[indexName];
553
+ if (index.__pendingCreate || index.__deleted || !index.unique) {
554
+ resolve(undefined);
555
+ return;
556
+ }
557
+ /**
558
+ * @type {import('./Key.js').KeyValueObject|
559
+ * import('./Key.js').KeyPathEvaluateValue}
560
+ */
561
+ let indexKey;
562
+ try {
563
+ indexKey = Key.extractKeyValueDecodedFromValueUsingKeyPath(value, index.keyPath, index.multiEntry);
564
+ if (
565
+ ('invalid' in indexKey && indexKey.invalid) ||
566
+ ('failure' in indexKey && indexKey.failure)
567
+ ) {
568
+ throw new Error('Go to catch');
569
+ }
570
+ } catch (err) {
571
+ resolve(undefined);
572
+ return;
573
+ }
574
+ indexKey = indexKey.value;
575
+ if (indexKey === undefined) {
576
+ resolve(undefined);
577
+ return;
578
+ }
579
+ const multiCheck = index.multiEntry && Array.isArray(indexKey);
580
+ const fetchArgs = buildFetchIndexDataSQL(true, index, indexKey, 'key', multiCheck);
581
+ executeFetchIndexData(null, ...fetchArgs, tx, null, function success (key) {
582
+ if (key === undefined || (excludeKey !== undefined && cmp(key, excludeKey) === 0)) {
583
+ resolve(undefined);
584
+ return;
585
+ }
586
+ reject(createDOMException(
587
+ 'ConstraintError',
588
+ 'Index already contains a record equal to ' +
589
+ (multiCheck ? 'one of the subkeys of' : '') +
590
+ '`indexKey`'
591
+ ));
592
+ }, reject);
593
+ });
594
+ });
595
+ return SyncPromise.all(indexPromises);
596
+ };
597
+
521
598
  /**
522
599
  *
523
600
  * @param {WebSQLTransaction} tx
@@ -794,7 +871,32 @@ IDBObjectStore.__storingRecordObjectStore = function (request, store, invalidate
794
871
  }, error);
795
872
  }
796
873
  if (!noOverwrite) {
797
- store.__overwrite(tx, clonedKeyOrCurrentNumber, insert, error);
874
+ // Validate unique index constraints *before* `__overwrite`
875
+ // deletes the existing row at this key -- otherwise a
876
+ // `put()` that ends up rejected still permanently loses
877
+ // the record it was trying to replace (see
878
+ // `idbobjectstore-put-unique-index-constraint-is-atomic.any.js`).
879
+ store.__checkIndexConstraints(tx, value, clonedKeyOrCurrentNumber).then(() => {
880
+ store.__overwrite(tx, clonedKeyOrCurrentNumber, insert, error);
881
+ return undefined;
882
+ /**
883
+ * @param {Error|DOMException} err
884
+ * @returns {null}
885
+ */
886
+ }).catch(function (err) {
887
+ /**
888
+ * @returns {void}
889
+ */
890
+ function fail () {
891
+ error(err);
892
+ }
893
+ if (typeof oldCn === 'number') {
894
+ Key.assignCurrentNumber(tx, store, oldCn, fail, fail);
895
+ return null;
896
+ }
897
+ fail();
898
+ return null;
899
+ });
798
900
  return;
799
901
  }
800
902
  insert(tx);
package/src/IDBRecord.js CHANGED
@@ -77,6 +77,14 @@ readonlyProperties.forEach((prop) => {
77
77
  * @returns {import('./Key.js').Key|import('./Key.js').Value}
78
78
  */
79
79
  get [prop] () {
80
+ // This is defined on the *shared* prototype (see above), so,
81
+ // unlike a per-instance getter, it's reachable by calling it
82
+ // directly on `IDBRecord.prototype` itself (not a real
83
+ // instance) -- WebIDL requires that to throw.
84
+ if (!(this instanceof IDBRecordAlias)) {
85
+ throw new TypeError('Illegal invocation');
86
+ }
87
+ // @ts-ignore `this` is a real instance past the check above (not an issue in TS7)
80
88
  return this['__' + prop];
81
89
  }
82
90
  };
@@ -274,8 +274,24 @@ function setGlobalVars (idb, initialConfig) {
274
274
  Object.setPrototypeOf(shimIDBRequest, ShimEventTarget);
275
275
  Object.setPrototypeOf(shimIDBTransaction, ShimEventTarget);
276
276
  Object.setPrototypeOf(shimIDBVersionChangeEvent, ShimEvent);
277
- Object.setPrototypeOf(ShimDOMException, Error);
278
- Object.setPrototypeOf(ShimDOMException.prototype, Error.prototype);
277
+ // `ShimDOMException` is the real native `DOMException` when one
278
+ // is available (see `DOMException.js`'s `useNativeDOMException`)
279
+ // -- which, unlike the shim classes above, is a single,
280
+ // process-wide singleton shared by reference across every
281
+ // sandbox this library gets installed into (see
282
+ // `node-idb-test.js`'s `sandboxObj`). A native `DOMException`
283
+ // already has the correct prototype chain out of the box
284
+ // (`Object.getPrototypeOf(DOMException) === Function.prototype`,
285
+ // not `Error`), so forcing it here isn't just unneeded but
286
+ // actively wrong -- and, because it's shared, permanently
287
+ // wrong for every later use of `DOMException` in the same
288
+ // process (e.g. a later WPT test file's own idlharness-style
289
+ // check that `DOMException` does *not* inherit from `Error`
290
+ // on the class side), not just this one shim install.
291
+ if (typeof DOMException === 'undefined' || ShimDOMException !== DOMException) {
292
+ Object.setPrototypeOf(ShimDOMException, Error);
293
+ Object.setPrototypeOf(ShimDOMException.prototype, Error.prototype);
294
+ }
279
295
  }
280
296
  if (IDB.indexedDB && !IDB.indexedDB.toString().includes('[native code]')) {
281
297
  if (CFG.addNonIDBGlobals) {