solid-ui 2.4.28-e3ba3633 → 2.4.28-e5cde855

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.
Files changed (78) hide show
  1. package/dist/805.solid-ui.min.js +1 -1
  2. package/dist/805.solid-ui.min.js.map +1 -1
  3. package/dist/solid-ui.js +2080 -1330
  4. package/dist/solid-ui.js.map +1 -1
  5. package/dist/solid-ui.min.js +1 -1
  6. package/dist/solid-ui.min.js.map +1 -1
  7. package/dist/vendors-node_modules_jsonld_lib_jsonld_js.solid-ui.js +1938 -1938
  8. package/dist/vendors-node_modules_jsonld_lib_jsonld_js.solid-ui.js.map +1 -1
  9. package/lib/chat/bookmarks.js +6 -7
  10. package/lib/chat/bookmarks.js.map +1 -1
  11. package/lib/chat/chatLogic.js +249 -65
  12. package/lib/chat/chatLogic.js.map +1 -1
  13. package/lib/chat/dateFolder.js +129 -126
  14. package/lib/chat/dateFolder.js.map +1 -1
  15. package/lib/chat/infinite.js +637 -423
  16. package/lib/chat/infinite.js.map +1 -1
  17. package/lib/chat/message.js +332 -193
  18. package/lib/chat/message.js.map +1 -1
  19. package/lib/chat/messageTools.js +463 -277
  20. package/lib/chat/messageTools.js.map +1 -1
  21. package/lib/chat/thread.js +299 -209
  22. package/lib/chat/thread.js.map +1 -1
  23. package/lib/header/index.js +5 -0
  24. package/lib/header/index.js.map +1 -1
  25. package/lib/log.js +5 -5
  26. package/lib/log.js.map +1 -1
  27. package/lib/login/login.js +24 -1
  28. package/lib/login/login.js.map +1 -1
  29. package/lib/media/media-capture.d.ts +2 -2
  30. package/lib/media/media-capture.d.ts.map +1 -1
  31. package/lib/media/media-capture.js +15 -11
  32. package/lib/media/media-capture.js.map +1 -1
  33. package/lib/pad.d.ts +2 -2
  34. package/lib/pad.d.ts.map +1 -1
  35. package/lib/pad.js +41 -15
  36. package/lib/pad.js.map +1 -1
  37. package/lib/participation.d.ts +5 -5
  38. package/lib/participation.d.ts.map +1 -1
  39. package/lib/participation.js +23 -22
  40. package/lib/participation.js.map +1 -1
  41. package/lib/preferences.js +4 -0
  42. package/lib/preferences.js.map +1 -1
  43. package/lib/style.js +28 -35
  44. package/lib/style.js.map +1 -1
  45. package/lib/tabs.d.ts +125 -0
  46. package/lib/tabs.d.ts.map +1 -1
  47. package/lib/tabs.js +8 -15
  48. package/lib/tabs.js.map +1 -1
  49. package/lib/utils/headerFooterHelpers.js +2 -0
  50. package/lib/utils/headerFooterHelpers.js.map +1 -1
  51. package/lib/versionInfo.js +2 -2
  52. package/lib/versionInfo.js.map +1 -1
  53. package/lib/widgets/buttons.js +0 -2
  54. package/lib/widgets/buttons.js.map +1 -1
  55. package/lib/widgets/dragAndDrop.js +18 -10
  56. package/lib/widgets/dragAndDrop.js.map +1 -1
  57. package/lib/widgets/error.d.ts.map +1 -1
  58. package/lib/widgets/error.js +2 -9
  59. package/lib/widgets/error.js.map +1 -1
  60. package/lib/widgets/forms/autocomplete/autocompleteBar.js +8 -1
  61. package/lib/widgets/forms/autocomplete/autocompleteBar.js.map +1 -1
  62. package/lib/widgets/forms/autocomplete/autocompletePicker.d.ts.map +1 -1
  63. package/lib/widgets/forms/autocomplete/autocompletePicker.js +9 -5
  64. package/lib/widgets/forms/autocomplete/autocompletePicker.js.map +1 -1
  65. package/lib/widgets/forms/autocomplete/language.js +5 -0
  66. package/lib/widgets/forms/autocomplete/language.js.map +1 -1
  67. package/lib/widgets/forms/basic.d.ts.map +1 -1
  68. package/lib/widgets/forms/basic.js +3 -4
  69. package/lib/widgets/forms/basic.js.map +1 -1
  70. package/lib/widgets/forms/fieldParams.js +2 -2
  71. package/lib/widgets/forms/fieldParams.js.map +1 -1
  72. package/lib/widgets/forms.js +12 -10
  73. package/lib/widgets/forms.js.map +1 -1
  74. package/lib/widgets/peoplePicker.js +11 -0
  75. package/lib/widgets/peoplePicker.js.map +1 -1
  76. package/package.json +3 -2
  77. package/lib/styleConstants.js +0 -34
  78. package/lib/styleConstants.js.map +0 -1
@@ -485,7 +485,7 @@ module.exports = class RequestQueue {
485
485
  */
486
486
 
487
487
 
488
- const LRU = __webpack_require__(/*! lru-cache */ "./node_modules/lru-cache/index.js");
488
+ const LRU = __webpack_require__(/*! lru-cache */ "./node_modules/jsonld/node_modules/lru-cache/index.js");
489
489
 
490
490
  const MAX_ACTIVE_CONTEXTS = 10;
491
491
 
@@ -6383,7 +6383,7 @@ const util = __webpack_require__(/*! ./util */ "./node_modules/jsonld/lib/util.j
6383
6383
  const ContextResolver = __webpack_require__(/*! ./ContextResolver */ "./node_modules/jsonld/lib/ContextResolver.js");
6384
6384
  const IdentifierIssuer = util.IdentifierIssuer;
6385
6385
  const JsonLdError = __webpack_require__(/*! ./JsonLdError */ "./node_modules/jsonld/lib/JsonLdError.js");
6386
- const LRU = __webpack_require__(/*! lru-cache */ "./node_modules/lru-cache/index.js");
6386
+ const LRU = __webpack_require__(/*! lru-cache */ "./node_modules/jsonld/node_modules/lru-cache/index.js");
6387
6387
  const NQuads = __webpack_require__(/*! ./NQuads */ "./node_modules/jsonld/lib/NQuads.js");
6388
6388
 
6389
6389
  const {expand: _expand} = __webpack_require__(/*! ./expand */ "./node_modules/jsonld/lib/expand.js");
@@ -9014,17 +9014,17 @@ function _labelBlankNodes(issuer, element) {
9014
9014
 
9015
9015
  /***/ }),
9016
9016
 
9017
- /***/ "./node_modules/lru-cache/index.js":
9018
- /*!*****************************************!*\
9019
- !*** ./node_modules/lru-cache/index.js ***!
9020
- \*****************************************/
9017
+ /***/ "./node_modules/jsonld/node_modules/lru-cache/index.js":
9018
+ /*!*************************************************************!*\
9019
+ !*** ./node_modules/jsonld/node_modules/lru-cache/index.js ***!
9020
+ \*************************************************************/
9021
9021
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
9022
9022
 
9023
9023
  "use strict";
9024
9024
 
9025
9025
 
9026
9026
  // A linked list to keep track of recently-used-ness
9027
- const Yallist = __webpack_require__(/*! yallist */ "./node_modules/yallist/yallist.js")
9027
+ const Yallist = __webpack_require__(/*! yallist */ "./node_modules/jsonld/node_modules/yallist/yallist.js")
9028
9028
 
9029
9029
  const MAX = Symbol('max')
9030
9030
  const LENGTH = Symbol('length')
@@ -9359,1223 +9359,1141 @@ module.exports = LRUCache
9359
9359
 
9360
9360
  /***/ }),
9361
9361
 
9362
- /***/ "./node_modules/rdf-canonize/index.js":
9363
- /*!********************************************!*\
9364
- !*** ./node_modules/rdf-canonize/index.js ***!
9365
- \********************************************/
9366
- /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
9362
+ /***/ "./node_modules/jsonld/node_modules/yallist/iterator.js":
9363
+ /*!**************************************************************!*\
9364
+ !*** ./node_modules/jsonld/node_modules/yallist/iterator.js ***!
9365
+ \**************************************************************/
9366
+ /***/ ((module) => {
9367
9367
 
9368
- /**
9369
- * An implementation of the RDF Dataset Normalization specification.
9370
- *
9371
- * @author Dave Longley
9372
- *
9373
- * Copyright 2010-2021 Digital Bazaar, Inc.
9374
- */
9375
- module.exports = __webpack_require__(/*! ./lib */ "./node_modules/rdf-canonize/lib/index.js");
9368
+ "use strict";
9369
+
9370
+ module.exports = function (Yallist) {
9371
+ Yallist.prototype[Symbol.iterator] = function* () {
9372
+ for (let walker = this.head; walker; walker = walker.next) {
9373
+ yield walker.value
9374
+ }
9375
+ }
9376
+ }
9376
9377
 
9377
9378
 
9378
9379
  /***/ }),
9379
9380
 
9380
- /***/ "./node_modules/rdf-canonize/lib/IdentifierIssuer.js":
9381
- /*!***********************************************************!*\
9382
- !*** ./node_modules/rdf-canonize/lib/IdentifierIssuer.js ***!
9383
- \***********************************************************/
9384
- /***/ ((module) => {
9381
+ /***/ "./node_modules/jsonld/node_modules/yallist/yallist.js":
9382
+ /*!*************************************************************!*\
9383
+ !*** ./node_modules/jsonld/node_modules/yallist/yallist.js ***!
9384
+ \*************************************************************/
9385
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
9385
9386
 
9386
9387
  "use strict";
9387
- /*
9388
- * Copyright (c) 2016-2021 Digital Bazaar, Inc. All rights reserved.
9389
- */
9390
9388
 
9389
+ module.exports = Yallist
9391
9390
 
9392
- module.exports = class IdentifierIssuer {
9393
- /**
9394
- * Creates a new IdentifierIssuer. A IdentifierIssuer issues unique
9395
- * identifiers, keeping track of any previously issued identifiers.
9396
- *
9397
- * @param prefix the prefix to use ('<prefix><counter>').
9398
- * @param existing an existing Map to use.
9399
- * @param counter the counter to use.
9400
- */
9401
- constructor(prefix, existing = new Map(), counter = 0) {
9402
- this.prefix = prefix;
9403
- this._existing = existing;
9404
- this.counter = counter;
9405
- }
9391
+ Yallist.Node = Node
9392
+ Yallist.create = Yallist
9406
9393
 
9407
- /**
9408
- * Copies this IdentifierIssuer.
9409
- *
9410
- * @return a copy of this IdentifierIssuer.
9411
- */
9412
- clone() {
9413
- const {prefix, _existing, counter} = this;
9414
- return new IdentifierIssuer(prefix, new Map(_existing), counter);
9394
+ function Yallist (list) {
9395
+ var self = this
9396
+ if (!(self instanceof Yallist)) {
9397
+ self = new Yallist()
9415
9398
  }
9416
9399
 
9417
- /**
9418
- * Gets the new identifier for the given old identifier, where if no old
9419
- * identifier is given a new identifier will be generated.
9420
- *
9421
- * @param [old] the old identifier to get the new identifier for.
9422
- *
9423
- * @return the new identifier.
9424
- */
9425
- getId(old) {
9426
- // return existing old identifier
9427
- const existing = old && this._existing.get(old);
9428
- if(existing) {
9429
- return existing;
9400
+ self.tail = null
9401
+ self.head = null
9402
+ self.length = 0
9403
+
9404
+ if (list && typeof list.forEach === 'function') {
9405
+ list.forEach(function (item) {
9406
+ self.push(item)
9407
+ })
9408
+ } else if (arguments.length > 0) {
9409
+ for (var i = 0, l = arguments.length; i < l; i++) {
9410
+ self.push(arguments[i])
9430
9411
  }
9412
+ }
9431
9413
 
9432
- // get next identifier
9433
- const identifier = this.prefix + this.counter;
9434
- this.counter++;
9414
+ return self
9415
+ }
9435
9416
 
9436
- // save mapping
9437
- if(old) {
9438
- this._existing.set(old, identifier);
9439
- }
9417
+ Yallist.prototype.removeNode = function (node) {
9418
+ if (node.list !== this) {
9419
+ throw new Error('removing node which does not belong to this list')
9420
+ }
9440
9421
 
9441
- return identifier;
9422
+ var next = node.next
9423
+ var prev = node.prev
9424
+
9425
+ if (next) {
9426
+ next.prev = prev
9442
9427
  }
9443
9428
 
9444
- /**
9445
- * Returns true if the given old identifer has already been assigned a new
9446
- * identifier.
9447
- *
9448
- * @param old the old identifier to check.
9449
- *
9450
- * @return true if the old identifier has been assigned a new identifier,
9451
- * false if not.
9452
- */
9453
- hasId(old) {
9454
- return this._existing.has(old);
9429
+ if (prev) {
9430
+ prev.next = next
9455
9431
  }
9456
9432
 
9457
- /**
9458
- * Returns all of the IDs that have been issued new IDs in the order in
9459
- * which they were issued new IDs.
9460
- *
9461
- * @return the list of old IDs that has been issued new IDs in order.
9462
- */
9463
- getOldIds() {
9464
- return [...this._existing.keys()];
9433
+ if (node === this.head) {
9434
+ this.head = next
9435
+ }
9436
+ if (node === this.tail) {
9437
+ this.tail = prev
9465
9438
  }
9466
- };
9467
9439
 
9440
+ node.list.length--
9441
+ node.next = null
9442
+ node.prev = null
9443
+ node.list = null
9468
9444
 
9469
- /***/ }),
9445
+ return next
9446
+ }
9470
9447
 
9471
- /***/ "./node_modules/rdf-canonize/lib/MessageDigest-browser.js":
9472
- /*!****************************************************************!*\
9473
- !*** ./node_modules/rdf-canonize/lib/MessageDigest-browser.js ***!
9474
- \****************************************************************/
9475
- /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
9448
+ Yallist.prototype.unshiftNode = function (node) {
9449
+ if (node === this.head) {
9450
+ return
9451
+ }
9476
9452
 
9477
- "use strict";
9478
- /*!
9479
- * Copyright (c) 2016-2022 Digital Bazaar, Inc. All rights reserved.
9480
- */
9453
+ if (node.list) {
9454
+ node.list.removeNode(node)
9455
+ }
9481
9456
 
9457
+ var head = this.head
9458
+ node.list = this
9459
+ node.next = head
9460
+ if (head) {
9461
+ head.prev = node
9462
+ }
9482
9463
 
9483
- __webpack_require__(/*! setimmediate */ "./node_modules/setimmediate/setImmediate.js");
9464
+ this.head = node
9465
+ if (!this.tail) {
9466
+ this.tail = node
9467
+ }
9468
+ this.length++
9469
+ }
9484
9470
 
9485
- const crypto = self.crypto || self.msCrypto;
9471
+ Yallist.prototype.pushNode = function (node) {
9472
+ if (node === this.tail) {
9473
+ return
9474
+ }
9486
9475
 
9487
- module.exports = class MessageDigest {
9488
- /**
9489
- * Creates a new MessageDigest.
9490
- *
9491
- * @param algorithm the algorithm to use.
9492
- */
9493
- constructor(algorithm) {
9494
- // check if crypto.subtle is available
9495
- // check is here rather than top-level to only fail if class is used
9496
- if(!(crypto && crypto.subtle)) {
9497
- throw new Error('crypto.subtle not found.');
9498
- }
9499
- if(algorithm === 'sha256') {
9500
- this.algorithm = {name: 'SHA-256'};
9501
- } else if(algorithm === 'sha1') {
9502
- this.algorithm = {name: 'SHA-1'};
9503
- } else {
9504
- throw new Error(`Unsupported algorithm "${algorithm}".`);
9505
- }
9506
- this._content = '';
9476
+ if (node.list) {
9477
+ node.list.removeNode(node)
9507
9478
  }
9508
9479
 
9509
- update(msg) {
9510
- this._content += msg;
9480
+ var tail = this.tail
9481
+ node.list = this
9482
+ node.prev = tail
9483
+ if (tail) {
9484
+ tail.next = node
9511
9485
  }
9512
9486
 
9513
- async digest() {
9514
- const data = new TextEncoder().encode(this._content);
9515
- const buffer = new Uint8Array(
9516
- await crypto.subtle.digest(this.algorithm, data));
9517
- // return digest in hex
9518
- let hex = '';
9519
- for(let i = 0; i < buffer.length; ++i) {
9520
- hex += buffer[i].toString(16).padStart(2, '0');
9521
- }
9522
- return hex;
9487
+ this.tail = node
9488
+ if (!this.head) {
9489
+ this.head = node
9523
9490
  }
9524
- };
9491
+ this.length++
9492
+ }
9525
9493
 
9494
+ Yallist.prototype.push = function () {
9495
+ for (var i = 0, l = arguments.length; i < l; i++) {
9496
+ push(this, arguments[i])
9497
+ }
9498
+ return this.length
9499
+ }
9526
9500
 
9527
- /***/ }),
9501
+ Yallist.prototype.unshift = function () {
9502
+ for (var i = 0, l = arguments.length; i < l; i++) {
9503
+ unshift(this, arguments[i])
9504
+ }
9505
+ return this.length
9506
+ }
9528
9507
 
9529
- /***/ "./node_modules/rdf-canonize/lib/NQuads.js":
9530
- /*!*************************************************!*\
9531
- !*** ./node_modules/rdf-canonize/lib/NQuads.js ***!
9532
- \*************************************************/
9533
- /***/ ((module) => {
9508
+ Yallist.prototype.pop = function () {
9509
+ if (!this.tail) {
9510
+ return undefined
9511
+ }
9534
9512
 
9535
- "use strict";
9536
- /*!
9537
- * Copyright (c) 2016-2022 Digital Bazaar, Inc. All rights reserved.
9538
- */
9513
+ var res = this.tail.value
9514
+ this.tail = this.tail.prev
9515
+ if (this.tail) {
9516
+ this.tail.next = null
9517
+ } else {
9518
+ this.head = null
9519
+ }
9520
+ this.length--
9521
+ return res
9522
+ }
9539
9523
 
9524
+ Yallist.prototype.shift = function () {
9525
+ if (!this.head) {
9526
+ return undefined
9527
+ }
9540
9528
 
9541
- // eslint-disable-next-line no-unused-vars
9542
- const TERMS = ['subject', 'predicate', 'object', 'graph'];
9543
- const RDF = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#';
9544
- const RDF_LANGSTRING = RDF + 'langString';
9545
- const XSD_STRING = 'http://www.w3.org/2001/XMLSchema#string';
9546
-
9547
- const TYPE_NAMED_NODE = 'NamedNode';
9548
- const TYPE_BLANK_NODE = 'BlankNode';
9549
- const TYPE_LITERAL = 'Literal';
9550
- const TYPE_DEFAULT_GRAPH = 'DefaultGraph';
9551
-
9552
- // build regexes
9553
- const REGEX = {};
9554
- (() => {
9555
- const iri = '(?:<([^:]+:[^>]*)>)';
9556
- // https://www.w3.org/TR/turtle/#grammar-production-BLANK_NODE_LABEL
9557
- const PN_CHARS_BASE =
9558
- 'A-Z' + 'a-z' +
9559
- '\u00C0-\u00D6' +
9560
- '\u00D8-\u00F6' +
9561
- '\u00F8-\u02FF' +
9562
- '\u0370-\u037D' +
9563
- '\u037F-\u1FFF' +
9564
- '\u200C-\u200D' +
9565
- '\u2070-\u218F' +
9566
- '\u2C00-\u2FEF' +
9567
- '\u3001-\uD7FF' +
9568
- '\uF900-\uFDCF' +
9569
- '\uFDF0-\uFFFD';
9570
- // TODO:
9571
- //'\u10000-\uEFFFF';
9572
- const PN_CHARS_U =
9573
- PN_CHARS_BASE +
9574
- '_';
9575
- const PN_CHARS =
9576
- PN_CHARS_U +
9577
- '0-9' +
9578
- '-' +
9579
- '\u00B7' +
9580
- '\u0300-\u036F' +
9581
- '\u203F-\u2040';
9582
- const BLANK_NODE_LABEL =
9583
- '(_:' +
9584
- '(?:[' + PN_CHARS_U + '0-9])' +
9585
- '(?:(?:[' + PN_CHARS + '.])*(?:[' + PN_CHARS + ']))?' +
9586
- ')';
9587
- const bnode = BLANK_NODE_LABEL;
9588
- const plain = '"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"';
9589
- const datatype = '(?:\\^\\^' + iri + ')';
9590
- const language = '(?:@([a-zA-Z]+(?:-[a-zA-Z0-9]+)*))';
9591
- const literal = '(?:' + plain + '(?:' + datatype + '|' + language + ')?)';
9592
- const ws = '[ \\t]+';
9593
- const wso = '[ \\t]*';
9594
-
9595
- // define quad part regexes
9596
- const subject = '(?:' + iri + '|' + bnode + ')' + ws;
9597
- const property = iri + ws;
9598
- const object = '(?:' + iri + '|' + bnode + '|' + literal + ')' + wso;
9599
- const graphName = '(?:\\.|(?:(?:' + iri + '|' + bnode + ')' + wso + '\\.))';
9529
+ var res = this.head.value
9530
+ this.head = this.head.next
9531
+ if (this.head) {
9532
+ this.head.prev = null
9533
+ } else {
9534
+ this.tail = null
9535
+ }
9536
+ this.length--
9537
+ return res
9538
+ }
9600
9539
 
9601
- // end of line and empty regexes
9602
- REGEX.eoln = /(?:\r\n)|(?:\n)|(?:\r)/g;
9603
- REGEX.empty = new RegExp('^' + wso + '$');
9540
+ Yallist.prototype.forEach = function (fn, thisp) {
9541
+ thisp = thisp || this
9542
+ for (var walker = this.head, i = 0; walker !== null; i++) {
9543
+ fn.call(thisp, walker.value, i, this)
9544
+ walker = walker.next
9545
+ }
9546
+ }
9604
9547
 
9605
- // full quad regex
9606
- REGEX.quad = new RegExp(
9607
- '^' + wso + subject + property + object + graphName + wso + '$');
9608
- })();
9548
+ Yallist.prototype.forEachReverse = function (fn, thisp) {
9549
+ thisp = thisp || this
9550
+ for (var walker = this.tail, i = this.length - 1; walker !== null; i--) {
9551
+ fn.call(thisp, walker.value, i, this)
9552
+ walker = walker.prev
9553
+ }
9554
+ }
9609
9555
 
9610
- module.exports = class NQuads {
9611
- /**
9612
- * Parses RDF in the form of N-Quads.
9613
- *
9614
- * @param input the N-Quads input to parse.
9615
- *
9616
- * @return an RDF dataset (an array of quads per http://rdf.js.org/).
9617
- */
9618
- static parse(input) {
9619
- // build RDF dataset
9620
- const dataset = [];
9556
+ Yallist.prototype.get = function (n) {
9557
+ for (var i = 0, walker = this.head; walker !== null && i < n; i++) {
9558
+ // abort out of the list early if we hit a cycle
9559
+ walker = walker.next
9560
+ }
9561
+ if (i === n && walker !== null) {
9562
+ return walker.value
9563
+ }
9564
+ }
9621
9565
 
9622
- const graphs = {};
9566
+ Yallist.prototype.getReverse = function (n) {
9567
+ for (var i = 0, walker = this.tail; walker !== null && i < n; i++) {
9568
+ // abort out of the list early if we hit a cycle
9569
+ walker = walker.prev
9570
+ }
9571
+ if (i === n && walker !== null) {
9572
+ return walker.value
9573
+ }
9574
+ }
9623
9575
 
9624
- // split N-Quad input into lines
9625
- const lines = input.split(REGEX.eoln);
9626
- let lineNumber = 0;
9627
- for(const line of lines) {
9628
- lineNumber++;
9576
+ Yallist.prototype.map = function (fn, thisp) {
9577
+ thisp = thisp || this
9578
+ var res = new Yallist()
9579
+ for (var walker = this.head; walker !== null;) {
9580
+ res.push(fn.call(thisp, walker.value, this))
9581
+ walker = walker.next
9582
+ }
9583
+ return res
9584
+ }
9629
9585
 
9630
- // skip empty lines
9631
- if(REGEX.empty.test(line)) {
9632
- continue;
9633
- }
9586
+ Yallist.prototype.mapReverse = function (fn, thisp) {
9587
+ thisp = thisp || this
9588
+ var res = new Yallist()
9589
+ for (var walker = this.tail; walker !== null;) {
9590
+ res.push(fn.call(thisp, walker.value, this))
9591
+ walker = walker.prev
9592
+ }
9593
+ return res
9594
+ }
9634
9595
 
9635
- // parse quad
9636
- const match = line.match(REGEX.quad);
9637
- if(match === null) {
9638
- throw new Error('N-Quads parse error on line ' + lineNumber + '.');
9639
- }
9596
+ Yallist.prototype.reduce = function (fn, initial) {
9597
+ var acc
9598
+ var walker = this.head
9599
+ if (arguments.length > 1) {
9600
+ acc = initial
9601
+ } else if (this.head) {
9602
+ walker = this.head.next
9603
+ acc = this.head.value
9604
+ } else {
9605
+ throw new TypeError('Reduce of empty list with no initial value')
9606
+ }
9640
9607
 
9641
- // create RDF quad
9642
- const quad = {subject: null, predicate: null, object: null, graph: null};
9608
+ for (var i = 0; walker !== null; i++) {
9609
+ acc = fn(acc, walker.value, i)
9610
+ walker = walker.next
9611
+ }
9643
9612
 
9644
- // get subject
9645
- if(match[1] !== undefined) {
9646
- quad.subject = {termType: TYPE_NAMED_NODE, value: match[1]};
9647
- } else {
9648
- quad.subject = {termType: TYPE_BLANK_NODE, value: match[2]};
9649
- }
9613
+ return acc
9614
+ }
9650
9615
 
9651
- // get predicate
9652
- quad.predicate = {termType: TYPE_NAMED_NODE, value: match[3]};
9616
+ Yallist.prototype.reduceReverse = function (fn, initial) {
9617
+ var acc
9618
+ var walker = this.tail
9619
+ if (arguments.length > 1) {
9620
+ acc = initial
9621
+ } else if (this.tail) {
9622
+ walker = this.tail.prev
9623
+ acc = this.tail.value
9624
+ } else {
9625
+ throw new TypeError('Reduce of empty list with no initial value')
9626
+ }
9653
9627
 
9654
- // get object
9655
- if(match[4] !== undefined) {
9656
- quad.object = {termType: TYPE_NAMED_NODE, value: match[4]};
9657
- } else if(match[5] !== undefined) {
9658
- quad.object = {termType: TYPE_BLANK_NODE, value: match[5]};
9659
- } else {
9660
- quad.object = {
9661
- termType: TYPE_LITERAL,
9662
- value: undefined,
9663
- datatype: {
9664
- termType: TYPE_NAMED_NODE
9665
- }
9666
- };
9667
- if(match[7] !== undefined) {
9668
- quad.object.datatype.value = match[7];
9669
- } else if(match[8] !== undefined) {
9670
- quad.object.datatype.value = RDF_LANGSTRING;
9671
- quad.object.language = match[8];
9672
- } else {
9673
- quad.object.datatype.value = XSD_STRING;
9674
- }
9675
- quad.object.value = _unescape(match[6]);
9676
- }
9628
+ for (var i = this.length - 1; walker !== null; i--) {
9629
+ acc = fn(acc, walker.value, i)
9630
+ walker = walker.prev
9631
+ }
9677
9632
 
9678
- // get graph
9679
- if(match[9] !== undefined) {
9680
- quad.graph = {
9681
- termType: TYPE_NAMED_NODE,
9682
- value: match[9]
9683
- };
9684
- } else if(match[10] !== undefined) {
9685
- quad.graph = {
9686
- termType: TYPE_BLANK_NODE,
9687
- value: match[10]
9688
- };
9689
- } else {
9690
- quad.graph = {
9691
- termType: TYPE_DEFAULT_GRAPH,
9692
- value: ''
9693
- };
9694
- }
9633
+ return acc
9634
+ }
9695
9635
 
9696
- // only add quad if it is unique in its graph
9697
- if(!(quad.graph.value in graphs)) {
9698
- graphs[quad.graph.value] = [quad];
9699
- dataset.push(quad);
9700
- } else {
9701
- let unique = true;
9702
- const quads = graphs[quad.graph.value];
9703
- for(const q of quads) {
9704
- if(_compareTriples(q, quad)) {
9705
- unique = false;
9706
- break;
9707
- }
9708
- }
9709
- if(unique) {
9710
- quads.push(quad);
9711
- dataset.push(quad);
9712
- }
9713
- }
9714
- }
9636
+ Yallist.prototype.toArray = function () {
9637
+ var arr = new Array(this.length)
9638
+ for (var i = 0, walker = this.head; walker !== null; i++) {
9639
+ arr[i] = walker.value
9640
+ walker = walker.next
9641
+ }
9642
+ return arr
9643
+ }
9715
9644
 
9716
- return dataset;
9645
+ Yallist.prototype.toArrayReverse = function () {
9646
+ var arr = new Array(this.length)
9647
+ for (var i = 0, walker = this.tail; walker !== null; i++) {
9648
+ arr[i] = walker.value
9649
+ walker = walker.prev
9717
9650
  }
9651
+ return arr
9652
+ }
9718
9653
 
9719
- /**
9720
- * Converts an RDF dataset to N-Quads.
9721
- *
9722
- * @param dataset (array of quads) the RDF dataset to convert.
9723
- *
9724
- * @return the N-Quads string.
9725
- */
9726
- static serialize(dataset) {
9727
- if(!Array.isArray(dataset)) {
9728
- dataset = NQuads.legacyDatasetToQuads(dataset);
9729
- }
9730
- const quads = [];
9731
- for(const quad of dataset) {
9732
- quads.push(NQuads.serializeQuad(quad));
9733
- }
9734
- return quads.sort().join('');
9654
+ Yallist.prototype.slice = function (from, to) {
9655
+ to = to || this.length
9656
+ if (to < 0) {
9657
+ to += this.length
9658
+ }
9659
+ from = from || 0
9660
+ if (from < 0) {
9661
+ from += this.length
9662
+ }
9663
+ var ret = new Yallist()
9664
+ if (to < from || to < 0) {
9665
+ return ret
9666
+ }
9667
+ if (from < 0) {
9668
+ from = 0
9669
+ }
9670
+ if (to > this.length) {
9671
+ to = this.length
9672
+ }
9673
+ for (var i = 0, walker = this.head; walker !== null && i < from; i++) {
9674
+ walker = walker.next
9675
+ }
9676
+ for (; walker !== null && i < to; i++, walker = walker.next) {
9677
+ ret.push(walker.value)
9735
9678
  }
9679
+ return ret
9680
+ }
9736
9681
 
9737
- /**
9738
- * Converts RDF quad components to an N-Quad string (a single quad).
9739
- *
9740
- * @param {Object} s - N-Quad subject component.
9741
- * @param {Object} p - N-Quad predicate component.
9742
- * @param {Object} o - N-Quad object component.
9743
- * @param {Object} g - N-Quad graph component.
9744
- *
9745
- * @return {string} the N-Quad.
9746
- */
9747
- static serializeQuadComponents(s, p, o, g) {
9748
- let nquad = '';
9682
+ Yallist.prototype.sliceReverse = function (from, to) {
9683
+ to = to || this.length
9684
+ if (to < 0) {
9685
+ to += this.length
9686
+ }
9687
+ from = from || 0
9688
+ if (from < 0) {
9689
+ from += this.length
9690
+ }
9691
+ var ret = new Yallist()
9692
+ if (to < from || to < 0) {
9693
+ return ret
9694
+ }
9695
+ if (from < 0) {
9696
+ from = 0
9697
+ }
9698
+ if (to > this.length) {
9699
+ to = this.length
9700
+ }
9701
+ for (var i = this.length, walker = this.tail; walker !== null && i > to; i--) {
9702
+ walker = walker.prev
9703
+ }
9704
+ for (; walker !== null && i > from; i--, walker = walker.prev) {
9705
+ ret.push(walker.value)
9706
+ }
9707
+ return ret
9708
+ }
9749
9709
 
9750
- // subject can only be NamedNode or BlankNode
9751
- if(s.termType === TYPE_NAMED_NODE) {
9752
- nquad += `<${s.value}>`;
9753
- } else {
9754
- nquad += `${s.value}`;
9755
- }
9710
+ Yallist.prototype.splice = function (start, deleteCount, ...nodes) {
9711
+ if (start > this.length) {
9712
+ start = this.length - 1
9713
+ }
9714
+ if (start < 0) {
9715
+ start = this.length + start;
9716
+ }
9756
9717
 
9757
- // predicate can only be NamedNode
9758
- nquad += ` <${p.value}> `;
9718
+ for (var i = 0, walker = this.head; walker !== null && i < start; i++) {
9719
+ walker = walker.next
9720
+ }
9759
9721
 
9760
- // object is NamedNode, BlankNode, or Literal
9761
- if(o.termType === TYPE_NAMED_NODE) {
9762
- nquad += `<${o.value}>`;
9763
- } else if(o.termType === TYPE_BLANK_NODE) {
9764
- nquad += o.value;
9765
- } else {
9766
- nquad += `"${_escape(o.value)}"`;
9767
- if(o.datatype.value === RDF_LANGSTRING) {
9768
- if(o.language) {
9769
- nquad += `@${o.language}`;
9770
- }
9771
- } else if(o.datatype.value !== XSD_STRING) {
9772
- nquad += `^^<${o.datatype.value}>`;
9773
- }
9774
- }
9722
+ var ret = []
9723
+ for (var i = 0; walker && i < deleteCount; i++) {
9724
+ ret.push(walker.value)
9725
+ walker = this.removeNode(walker)
9726
+ }
9727
+ if (walker === null) {
9728
+ walker = this.tail
9729
+ }
9775
9730
 
9776
- // graph can only be NamedNode or BlankNode (or DefaultGraph, but that
9777
- // does not add to `nquad`)
9778
- if(g.termType === TYPE_NAMED_NODE) {
9779
- nquad += ` <${g.value}>`;
9780
- } else if(g.termType === TYPE_BLANK_NODE) {
9781
- nquad += ` ${g.value}`;
9782
- }
9731
+ if (walker !== this.head && walker !== this.tail) {
9732
+ walker = walker.prev
9733
+ }
9783
9734
 
9784
- nquad += ' .\n';
9785
- return nquad;
9735
+ for (var i = 0; i < nodes.length; i++) {
9736
+ walker = insert(this, walker, nodes[i])
9786
9737
  }
9738
+ return ret;
9739
+ }
9787
9740
 
9788
- /**
9789
- * Converts an RDF quad to an N-Quad string (a single quad).
9790
- *
9791
- * @param quad the RDF quad convert.
9792
- *
9793
- * @return the N-Quad string.
9794
- */
9795
- static serializeQuad(quad) {
9796
- return NQuads.serializeQuadComponents(
9797
- quad.subject, quad.predicate, quad.object, quad.graph);
9741
+ Yallist.prototype.reverse = function () {
9742
+ var head = this.head
9743
+ var tail = this.tail
9744
+ for (var walker = head; walker !== null; walker = walker.prev) {
9745
+ var p = walker.prev
9746
+ walker.prev = walker.next
9747
+ walker.next = p
9798
9748
  }
9749
+ this.head = tail
9750
+ this.tail = head
9751
+ return this
9752
+ }
9799
9753
 
9800
- /**
9801
- * Converts a legacy-formatted dataset to an array of quads dataset per
9802
- * http://rdf.js.org/.
9803
- *
9804
- * @param dataset the legacy dataset to convert.
9805
- *
9806
- * @return the array of quads dataset.
9807
- */
9808
- static legacyDatasetToQuads(dataset) {
9809
- const quads = [];
9754
+ function insert (self, node, value) {
9755
+ var inserted = node === self.head ?
9756
+ new Node(value, null, node, self) :
9757
+ new Node(value, node, node.next, self)
9810
9758
 
9811
- const termTypeMap = {
9812
- 'blank node': TYPE_BLANK_NODE,
9813
- IRI: TYPE_NAMED_NODE,
9814
- literal: TYPE_LITERAL
9815
- };
9759
+ if (inserted.next === null) {
9760
+ self.tail = inserted
9761
+ }
9762
+ if (inserted.prev === null) {
9763
+ self.head = inserted
9764
+ }
9816
9765
 
9817
- for(const graphName in dataset) {
9818
- const triples = dataset[graphName];
9819
- triples.forEach(triple => {
9820
- const quad = {};
9821
- for(const componentName in triple) {
9822
- const oldComponent = triple[componentName];
9823
- const newComponent = {
9824
- termType: termTypeMap[oldComponent.type],
9825
- value: oldComponent.value
9826
- };
9827
- if(newComponent.termType === TYPE_LITERAL) {
9828
- newComponent.datatype = {
9829
- termType: TYPE_NAMED_NODE
9830
- };
9831
- if('datatype' in oldComponent) {
9832
- newComponent.datatype.value = oldComponent.datatype;
9833
- }
9834
- if('language' in oldComponent) {
9835
- if(!('datatype' in oldComponent)) {
9836
- newComponent.datatype.value = RDF_LANGSTRING;
9837
- }
9838
- newComponent.language = oldComponent.language;
9839
- } else if(!('datatype' in oldComponent)) {
9840
- newComponent.datatype.value = XSD_STRING;
9841
- }
9842
- }
9843
- quad[componentName] = newComponent;
9844
- }
9845
- if(graphName === '@default') {
9846
- quad.graph = {
9847
- termType: TYPE_DEFAULT_GRAPH,
9848
- value: ''
9849
- };
9850
- } else {
9851
- quad.graph = {
9852
- termType: graphName.startsWith('_:') ?
9853
- TYPE_BLANK_NODE : TYPE_NAMED_NODE,
9854
- value: graphName
9855
- };
9856
- }
9857
- quads.push(quad);
9858
- });
9859
- }
9766
+ self.length++
9860
9767
 
9861
- return quads;
9768
+ return inserted
9769
+ }
9770
+
9771
+ function push (self, item) {
9772
+ self.tail = new Node(item, self.tail, null, self)
9773
+ if (!self.head) {
9774
+ self.head = self.tail
9862
9775
  }
9863
- };
9776
+ self.length++
9777
+ }
9778
+
9779
+ function unshift (self, item) {
9780
+ self.head = new Node(item, null, self.head, self)
9781
+ if (!self.tail) {
9782
+ self.tail = self.head
9783
+ }
9784
+ self.length++
9785
+ }
9864
9786
 
9865
- /**
9866
- * Compares two RDF triples for equality.
9867
- *
9868
- * @param t1 the first triple.
9869
- * @param t2 the second triple.
9870
- *
9871
- * @return true if the triples are the same, false if not.
9872
- */
9873
- function _compareTriples(t1, t2) {
9874
- // compare subject and object types first as it is the quickest check
9875
- if(!(t1.subject.termType === t2.subject.termType &&
9876
- t1.object.termType === t2.object.termType)) {
9877
- return false;
9787
+ function Node (value, prev, next, list) {
9788
+ if (!(this instanceof Node)) {
9789
+ return new Node(value, prev, next, list)
9878
9790
  }
9879
- // compare values
9880
- if(!(t1.subject.value === t2.subject.value &&
9881
- t1.predicate.value === t2.predicate.value &&
9882
- t1.object.value === t2.object.value)) {
9883
- return false;
9791
+
9792
+ this.list = list
9793
+ this.value = value
9794
+
9795
+ if (prev) {
9796
+ prev.next = this
9797
+ this.prev = prev
9798
+ } else {
9799
+ this.prev = null
9884
9800
  }
9885
- if(t1.object.termType !== TYPE_LITERAL) {
9886
- // no `datatype` or `language` to check
9887
- return true;
9801
+
9802
+ if (next) {
9803
+ next.prev = this
9804
+ this.next = next
9805
+ } else {
9806
+ this.next = null
9888
9807
  }
9889
- return (
9890
- (t1.object.datatype.termType === t2.object.datatype.termType) &&
9891
- (t1.object.language === t2.object.language) &&
9892
- (t1.object.datatype.value === t2.object.datatype.value)
9893
- );
9894
9808
  }
9895
9809
 
9896
- const _escapeRegex = /["\\\n\r]/g;
9897
- /**
9898
- * Escape string to N-Quads literal
9899
- */
9900
- function _escape(s) {
9901
- return s.replace(_escapeRegex, function(match) {
9902
- switch(match) {
9903
- case '"': return '\\"';
9904
- case '\\': return '\\\\';
9905
- case '\n': return '\\n';
9906
- case '\r': return '\\r';
9907
- }
9908
- });
9909
- }
9810
+ try {
9811
+ // add if support for Symbol.iterator is present
9812
+ __webpack_require__(/*! ./iterator.js */ "./node_modules/jsonld/node_modules/yallist/iterator.js")(Yallist)
9813
+ } catch (er) {}
9814
+
9815
+
9816
+ /***/ }),
9817
+
9818
+ /***/ "./node_modules/rdf-canonize/index.js":
9819
+ /*!********************************************!*\
9820
+ !*** ./node_modules/rdf-canonize/index.js ***!
9821
+ \********************************************/
9822
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
9910
9823
 
9911
- const _unescapeRegex =
9912
- /(?:\\([tbnrf"'\\]))|(?:\\u([0-9A-Fa-f]{4}))|(?:\\U([0-9A-Fa-f]{8}))/g;
9913
9824
  /**
9914
- * Unescape N-Quads literal to string
9825
+ * An implementation of the RDF Dataset Normalization specification.
9826
+ *
9827
+ * @author Dave Longley
9828
+ *
9829
+ * Copyright 2010-2021 Digital Bazaar, Inc.
9915
9830
  */
9916
- function _unescape(s) {
9917
- return s.replace(_unescapeRegex, function(match, code, u, U) {
9918
- if(code) {
9919
- switch(code) {
9920
- case 't': return '\t';
9921
- case 'b': return '\b';
9922
- case 'n': return '\n';
9923
- case 'r': return '\r';
9924
- case 'f': return '\f';
9925
- case '"': return '"';
9926
- case '\'': return '\'';
9927
- case '\\': return '\\';
9928
- }
9929
- }
9930
- if(u) {
9931
- return String.fromCharCode(parseInt(u, 16));
9932
- }
9933
- if(U) {
9934
- // FIXME: support larger values
9935
- throw new Error('Unsupported U escape');
9936
- }
9937
- });
9938
- }
9831
+ module.exports = __webpack_require__(/*! ./lib */ "./node_modules/rdf-canonize/lib/index.js");
9939
9832
 
9940
9833
 
9941
9834
  /***/ }),
9942
9835
 
9943
- /***/ "./node_modules/rdf-canonize/lib/Permuter.js":
9944
- /*!***************************************************!*\
9945
- !*** ./node_modules/rdf-canonize/lib/Permuter.js ***!
9946
- \***************************************************/
9836
+ /***/ "./node_modules/rdf-canonize/lib/IdentifierIssuer.js":
9837
+ /*!***********************************************************!*\
9838
+ !*** ./node_modules/rdf-canonize/lib/IdentifierIssuer.js ***!
9839
+ \***********************************************************/
9947
9840
  /***/ ((module) => {
9948
9841
 
9949
9842
  "use strict";
9950
- /*!
9951
- * Copyright (c) 2016-2022 Digital Bazaar, Inc. All rights reserved.
9843
+ /*
9844
+ * Copyright (c) 2016-2021 Digital Bazaar, Inc. All rights reserved.
9952
9845
  */
9953
9846
 
9954
9847
 
9955
- module.exports = class Permuter {
9848
+ module.exports = class IdentifierIssuer {
9956
9849
  /**
9957
- * A Permuter iterates over all possible permutations of the given array
9958
- * of elements.
9850
+ * Creates a new IdentifierIssuer. A IdentifierIssuer issues unique
9851
+ * identifiers, keeping track of any previously issued identifiers.
9959
9852
  *
9960
- * @param list the array of elements to iterate over.
9853
+ * @param prefix the prefix to use ('<prefix><counter>').
9854
+ * @param existing an existing Map to use.
9855
+ * @param counter the counter to use.
9961
9856
  */
9962
- constructor(list) {
9963
- // original array
9964
- this.current = list.sort();
9965
- // indicates whether there are more permutations
9966
- this.done = false;
9967
- // directional info for permutation algorithm
9968
- this.dir = new Map();
9969
- for(let i = 0; i < list.length; ++i) {
9970
- this.dir.set(list[i], true);
9971
- }
9857
+ constructor(prefix, existing = new Map(), counter = 0) {
9858
+ this.prefix = prefix;
9859
+ this._existing = existing;
9860
+ this.counter = counter;
9972
9861
  }
9973
9862
 
9974
9863
  /**
9975
- * Returns true if there is another permutation.
9864
+ * Copies this IdentifierIssuer.
9976
9865
  *
9977
- * @return true if there is another permutation, false if not.
9866
+ * @return a copy of this IdentifierIssuer.
9978
9867
  */
9979
- hasNext() {
9980
- return !this.done;
9868
+ clone() {
9869
+ const {prefix, _existing, counter} = this;
9870
+ return new IdentifierIssuer(prefix, new Map(_existing), counter);
9981
9871
  }
9982
9872
 
9983
9873
  /**
9984
- * Gets the next permutation. Call hasNext() to ensure there is another one
9985
- * first.
9874
+ * Gets the new identifier for the given old identifier, where if no old
9875
+ * identifier is given a new identifier will be generated.
9986
9876
  *
9987
- * @return the next permutation.
9877
+ * @param [old] the old identifier to get the new identifier for.
9878
+ *
9879
+ * @return the new identifier.
9988
9880
  */
9989
- next() {
9990
- // copy current permutation to return it
9991
- const {current, dir} = this;
9992
- const rval = current.slice();
9993
-
9994
- /* Calculate the next permutation using the Steinhaus-Johnson-Trotter
9995
- permutation algorithm. */
9996
-
9997
- // get largest mobile element k
9998
- // (mobile: element is greater than the one it is looking at)
9999
- let k = null;
10000
- let pos = 0;
10001
- const length = current.length;
10002
- for(let i = 0; i < length; ++i) {
10003
- const element = current[i];
10004
- const left = dir.get(element);
10005
- if((k === null || element > k) &&
10006
- ((left && i > 0 && element > current[i - 1]) ||
10007
- (!left && i < (length - 1) && element > current[i + 1]))) {
10008
- k = element;
10009
- pos = i;
10010
- }
10011
- }
10012
-
10013
- // no more permutations
10014
- if(k === null) {
10015
- this.done = true;
10016
- } else {
10017
- // swap k and the element it is looking at
10018
- const swap = dir.get(k) ? pos - 1 : pos + 1;
10019
- current[pos] = current[swap];
10020
- current[swap] = k;
10021
-
10022
- // reverse the direction of all elements larger than k
10023
- for(const element of current) {
10024
- if(element > k) {
10025
- dir.set(element, !dir.get(element));
10026
- }
10027
- }
9881
+ getId(old) {
9882
+ // return existing old identifier
9883
+ const existing = old && this._existing.get(old);
9884
+ if(existing) {
9885
+ return existing;
10028
9886
  }
10029
9887
 
10030
- return rval;
10031
- }
10032
- };
10033
-
10034
-
10035
- /***/ }),
10036
-
10037
- /***/ "./node_modules/rdf-canonize/lib/URDNA2015.js":
10038
- /*!****************************************************!*\
10039
- !*** ./node_modules/rdf-canonize/lib/URDNA2015.js ***!
10040
- \****************************************************/
10041
- /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
10042
-
10043
- "use strict";
10044
- /*!
10045
- * Copyright (c) 2016-2022 Digital Bazaar, Inc. All rights reserved.
10046
- */
10047
-
10048
-
10049
- const IdentifierIssuer = __webpack_require__(/*! ./IdentifierIssuer */ "./node_modules/rdf-canonize/lib/IdentifierIssuer.js");
10050
- const MessageDigest = __webpack_require__(/*! ./MessageDigest */ "./node_modules/rdf-canonize/lib/MessageDigest-browser.js");
10051
- const Permuter = __webpack_require__(/*! ./Permuter */ "./node_modules/rdf-canonize/lib/Permuter.js");
10052
- const NQuads = __webpack_require__(/*! ./NQuads */ "./node_modules/rdf-canonize/lib/NQuads.js");
10053
-
10054
- module.exports = class URDNA2015 {
10055
- constructor({
10056
- createMessageDigest = () => new MessageDigest('sha256'),
10057
- maxDeepIterations = Infinity
10058
- } = {}) {
10059
- this.name = 'URDNA2015';
10060
- this.blankNodeInfo = new Map();
10061
- this.canonicalIssuer = new IdentifierIssuer('_:c14n');
10062
- this.createMessageDigest = createMessageDigest;
10063
- this.maxDeepIterations = maxDeepIterations;
10064
- this.quads = null;
10065
- this.deepIterations = null;
10066
- }
10067
-
10068
- // 4.4) Normalization Algorithm
10069
- async main(dataset) {
10070
- this.deepIterations = new Map();
10071
- this.quads = dataset;
9888
+ // get next identifier
9889
+ const identifier = this.prefix + this.counter;
9890
+ this.counter++;
10072
9891
 
10073
- // 1) Create the normalization state.
10074
- // 2) For every quad in input dataset:
10075
- for(const quad of dataset) {
10076
- // 2.1) For each blank node that occurs in the quad, add a reference
10077
- // to the quad using the blank node identifier in the blank node to
10078
- // quads map, creating a new entry if necessary.
10079
- this._addBlankNodeQuadInfo({quad, component: quad.subject});
10080
- this._addBlankNodeQuadInfo({quad, component: quad.object});
10081
- this._addBlankNodeQuadInfo({quad, component: quad.graph});
9892
+ // save mapping
9893
+ if(old) {
9894
+ this._existing.set(old, identifier);
10082
9895
  }
10083
9896
 
10084
- // 3) Create a list of non-normalized blank node identifiers
10085
- // non-normalized identifiers and populate it using the keys from the
10086
- // blank node to quads map.
10087
- // Note: We use a map here and it was generated during step 2.
10088
-
10089
- // 4) `simple` flag is skipped -- loop is optimized away. This optimization
10090
- // is permitted because there was a typo in the hash first degree quads
10091
- // algorithm in the URDNA2015 spec that was implemented widely making it
10092
- // such that it could not be fixed; the result was that the loop only
10093
- // needs to be run once and the first degree quad hashes will never change.
10094
- // 5.1-5.2 are skipped; first degree quad hashes are generated just once
10095
- // for all non-normalized blank nodes.
9897
+ return identifier;
9898
+ }
10096
9899
 
10097
- // 5.3) For each blank node identifier identifier in non-normalized
10098
- // identifiers:
10099
- const hashToBlankNodes = new Map();
10100
- const nonNormalized = [...this.blankNodeInfo.keys()];
10101
- let i = 0;
10102
- for(const id of nonNormalized) {
10103
- // Note: batch hashing first degree quads 100 at a time
10104
- if(++i % 100 === 0) {
10105
- await this._yield();
10106
- }
10107
- // steps 5.3.1 and 5.3.2:
10108
- await this._hashAndTrackBlankNode({id, hashToBlankNodes});
10109
- }
9900
+ /**
9901
+ * Returns true if the given old identifer has already been assigned a new
9902
+ * identifier.
9903
+ *
9904
+ * @param old the old identifier to check.
9905
+ *
9906
+ * @return true if the old identifier has been assigned a new identifier,
9907
+ * false if not.
9908
+ */
9909
+ hasId(old) {
9910
+ return this._existing.has(old);
9911
+ }
10110
9912
 
10111
- // 5.4) For each hash to identifier list mapping in hash to blank
10112
- // nodes map, lexicographically-sorted by hash:
10113
- const hashes = [...hashToBlankNodes.keys()].sort();
10114
- // optimize away second sort, gather non-unique hashes in order as we go
10115
- const nonUnique = [];
10116
- for(const hash of hashes) {
10117
- // 5.4.1) If the length of identifier list is greater than 1,
10118
- // continue to the next mapping.
10119
- const idList = hashToBlankNodes.get(hash);
10120
- if(idList.length > 1) {
10121
- nonUnique.push(idList);
10122
- continue;
10123
- }
9913
+ /**
9914
+ * Returns all of the IDs that have been issued new IDs in the order in
9915
+ * which they were issued new IDs.
9916
+ *
9917
+ * @return the list of old IDs that has been issued new IDs in order.
9918
+ */
9919
+ getOldIds() {
9920
+ return [...this._existing.keys()];
9921
+ }
9922
+ };
10124
9923
 
10125
- // 5.4.2) Use the Issue Identifier algorithm, passing canonical
10126
- // issuer and the single blank node identifier in identifier
10127
- // list, identifier, to issue a canonical replacement identifier
10128
- // for identifier.
10129
- const id = idList[0];
10130
- this.canonicalIssuer.getId(id);
10131
9924
 
10132
- // Note: These steps are skipped, optimized away since the loop
10133
- // only needs to be run once.
10134
- // 5.4.3) Remove identifier from non-normalized identifiers.
10135
- // 5.4.4) Remove hash from the hash to blank nodes map.
10136
- // 5.4.5) Set simple to true.
10137
- }
9925
+ /***/ }),
10138
9926
 
10139
- // 6) For each hash to identifier list mapping in hash to blank nodes map,
10140
- // lexicographically-sorted by hash:
10141
- // Note: sort optimized away, use `nonUnique`.
10142
- for(const idList of nonUnique) {
10143
- // 6.1) Create hash path list where each item will be a result of
10144
- // running the Hash N-Degree Quads algorithm.
10145
- const hashPathList = [];
9927
+ /***/ "./node_modules/rdf-canonize/lib/MessageDigest-browser.js":
9928
+ /*!****************************************************************!*\
9929
+ !*** ./node_modules/rdf-canonize/lib/MessageDigest-browser.js ***!
9930
+ \****************************************************************/
9931
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
10146
9932
 
10147
- // 6.2) For each blank node identifier identifier in identifier list:
10148
- for(const id of idList) {
10149
- // 6.2.1) If a canonical identifier has already been issued for
10150
- // identifier, continue to the next identifier.
10151
- if(this.canonicalIssuer.hasId(id)) {
10152
- continue;
10153
- }
9933
+ "use strict";
9934
+ /*!
9935
+ * Copyright (c) 2016-2022 Digital Bazaar, Inc. All rights reserved.
9936
+ */
10154
9937
 
10155
- // 6.2.2) Create temporary issuer, an identifier issuer
10156
- // initialized with the prefix _:b.
10157
- const issuer = new IdentifierIssuer('_:b');
10158
9938
 
10159
- // 6.2.3) Use the Issue Identifier algorithm, passing temporary
10160
- // issuer and identifier, to issue a new temporary blank node
10161
- // identifier for identifier.
10162
- issuer.getId(id);
9939
+ __webpack_require__(/*! setimmediate */ "./node_modules/setimmediate/setImmediate.js");
10163
9940
 
10164
- // 6.2.4) Run the Hash N-Degree Quads algorithm, passing
10165
- // temporary issuer, and append the result to the hash path list.
10166
- const result = await this.hashNDegreeQuads(id, issuer);
10167
- hashPathList.push(result);
10168
- }
9941
+ const crypto = self.crypto || self.msCrypto;
10169
9942
 
10170
- // 6.3) For each result in the hash path list,
10171
- // lexicographically-sorted by the hash in result:
10172
- hashPathList.sort(_stringHashCompare);
10173
- for(const result of hashPathList) {
10174
- // 6.3.1) For each blank node identifier, existing identifier,
10175
- // that was issued a temporary identifier by identifier issuer
10176
- // in result, issue a canonical identifier, in the same order,
10177
- // using the Issue Identifier algorithm, passing canonical
10178
- // issuer and existing identifier.
10179
- const oldIds = result.issuer.getOldIds();
10180
- for(const id of oldIds) {
10181
- this.canonicalIssuer.getId(id);
10182
- }
10183
- }
9943
+ module.exports = class MessageDigest {
9944
+ /**
9945
+ * Creates a new MessageDigest.
9946
+ *
9947
+ * @param algorithm the algorithm to use.
9948
+ */
9949
+ constructor(algorithm) {
9950
+ // check if crypto.subtle is available
9951
+ // check is here rather than top-level to only fail if class is used
9952
+ if(!(crypto && crypto.subtle)) {
9953
+ throw new Error('crypto.subtle not found.');
9954
+ }
9955
+ if(algorithm === 'sha256') {
9956
+ this.algorithm = {name: 'SHA-256'};
9957
+ } else if(algorithm === 'sha1') {
9958
+ this.algorithm = {name: 'SHA-1'};
9959
+ } else {
9960
+ throw new Error(`Unsupported algorithm "${algorithm}".`);
10184
9961
  }
9962
+ this._content = '';
9963
+ }
10185
9964
 
10186
- /* Note: At this point all blank nodes in the set of RDF quads have been
10187
- assigned canonical identifiers, which have been stored in the canonical
10188
- issuer. Here each quad is updated by assigning each of its blank nodes
10189
- its new identifier. */
9965
+ update(msg) {
9966
+ this._content += msg;
9967
+ }
10190
9968
 
10191
- // 7) For each quad, quad, in input dataset:
10192
- const normalized = [];
10193
- for(const quad of this.quads) {
10194
- // 7.1) Create a copy, quad copy, of quad and replace any existing
10195
- // blank node identifiers using the canonical identifiers
10196
- // previously issued by canonical issuer.
10197
- // Note: We optimize away the copy here.
10198
- const nQuad = NQuads.serializeQuadComponents(
10199
- this._componentWithCanonicalId(quad.subject),
10200
- quad.predicate,
10201
- this._componentWithCanonicalId(quad.object),
10202
- this._componentWithCanonicalId(quad.graph)
10203
- );
10204
- // 7.2) Add quad copy to the normalized dataset.
10205
- normalized.push(nQuad);
9969
+ async digest() {
9970
+ const data = new TextEncoder().encode(this._content);
9971
+ const buffer = new Uint8Array(
9972
+ await crypto.subtle.digest(this.algorithm, data));
9973
+ // return digest in hex
9974
+ let hex = '';
9975
+ for(let i = 0; i < buffer.length; ++i) {
9976
+ hex += buffer[i].toString(16).padStart(2, '0');
10206
9977
  }
9978
+ return hex;
9979
+ }
9980
+ };
10207
9981
 
10208
- // sort normalized output
10209
- normalized.sort();
10210
9982
 
10211
- // 8) Return the normalized dataset.
10212
- return normalized.join('');
10213
- }
9983
+ /***/ }),
10214
9984
 
10215
- // 4.6) Hash First Degree Quads
10216
- async hashFirstDegreeQuads(id) {
10217
- // 1) Initialize nquads to an empty list. It will be used to store quads in
10218
- // N-Quads format.
10219
- const nquads = [];
9985
+ /***/ "./node_modules/rdf-canonize/lib/NQuads.js":
9986
+ /*!*************************************************!*\
9987
+ !*** ./node_modules/rdf-canonize/lib/NQuads.js ***!
9988
+ \*************************************************/
9989
+ /***/ ((module) => {
10220
9990
 
10221
- // 2) Get the list of quads `quads` associated with the reference blank node
10222
- // identifier in the blank node to quads map.
10223
- const info = this.blankNodeInfo.get(id);
10224
- const quads = info.quads;
9991
+ "use strict";
9992
+ /*!
9993
+ * Copyright (c) 2016-2022 Digital Bazaar, Inc. All rights reserved.
9994
+ */
10225
9995
 
10226
- // 3) For each quad `quad` in `quads`:
10227
- for(const quad of quads) {
10228
- // 3.1) Serialize the quad in N-Quads format with the following special
10229
- // rule:
10230
9996
 
10231
- // 3.1.1) If any component in quad is an blank node, then serialize it
10232
- // using a special identifier as follows:
10233
- const copy = {
10234
- subject: null, predicate: quad.predicate, object: null, graph: null
10235
- };
10236
- // 3.1.2) If the blank node's existing blank node identifier matches
10237
- // the reference blank node identifier then use the blank node
10238
- // identifier _:a, otherwise, use the blank node identifier _:z.
10239
- copy.subject = this.modifyFirstDegreeComponent(
10240
- id, quad.subject, 'subject');
10241
- copy.object = this.modifyFirstDegreeComponent(
10242
- id, quad.object, 'object');
10243
- copy.graph = this.modifyFirstDegreeComponent(
10244
- id, quad.graph, 'graph');
10245
- nquads.push(NQuads.serializeQuad(copy));
10246
- }
9997
+ // eslint-disable-next-line no-unused-vars
9998
+ const TERMS = ['subject', 'predicate', 'object', 'graph'];
9999
+ const RDF = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#';
10000
+ const RDF_LANGSTRING = RDF + 'langString';
10001
+ const XSD_STRING = 'http://www.w3.org/2001/XMLSchema#string';
10002
+
10003
+ const TYPE_NAMED_NODE = 'NamedNode';
10004
+ const TYPE_BLANK_NODE = 'BlankNode';
10005
+ const TYPE_LITERAL = 'Literal';
10006
+ const TYPE_DEFAULT_GRAPH = 'DefaultGraph';
10007
+
10008
+ // build regexes
10009
+ const REGEX = {};
10010
+ (() => {
10011
+ const iri = '(?:<([^:]+:[^>]*)>)';
10012
+ // https://www.w3.org/TR/turtle/#grammar-production-BLANK_NODE_LABEL
10013
+ const PN_CHARS_BASE =
10014
+ 'A-Z' + 'a-z' +
10015
+ '\u00C0-\u00D6' +
10016
+ '\u00D8-\u00F6' +
10017
+ '\u00F8-\u02FF' +
10018
+ '\u0370-\u037D' +
10019
+ '\u037F-\u1FFF' +
10020
+ '\u200C-\u200D' +
10021
+ '\u2070-\u218F' +
10022
+ '\u2C00-\u2FEF' +
10023
+ '\u3001-\uD7FF' +
10024
+ '\uF900-\uFDCF' +
10025
+ '\uFDF0-\uFFFD';
10026
+ // TODO:
10027
+ //'\u10000-\uEFFFF';
10028
+ const PN_CHARS_U =
10029
+ PN_CHARS_BASE +
10030
+ '_';
10031
+ const PN_CHARS =
10032
+ PN_CHARS_U +
10033
+ '0-9' +
10034
+ '-' +
10035
+ '\u00B7' +
10036
+ '\u0300-\u036F' +
10037
+ '\u203F-\u2040';
10038
+ const BLANK_NODE_LABEL =
10039
+ '(_:' +
10040
+ '(?:[' + PN_CHARS_U + '0-9])' +
10041
+ '(?:(?:[' + PN_CHARS + '.])*(?:[' + PN_CHARS + ']))?' +
10042
+ ')';
10043
+ const bnode = BLANK_NODE_LABEL;
10044
+ const plain = '"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"';
10045
+ const datatype = '(?:\\^\\^' + iri + ')';
10046
+ const language = '(?:@([a-zA-Z]+(?:-[a-zA-Z0-9]+)*))';
10047
+ const literal = '(?:' + plain + '(?:' + datatype + '|' + language + ')?)';
10048
+ const ws = '[ \\t]+';
10049
+ const wso = '[ \\t]*';
10247
10050
 
10248
- // 4) Sort nquads in lexicographical order.
10249
- nquads.sort();
10051
+ // define quad part regexes
10052
+ const subject = '(?:' + iri + '|' + bnode + ')' + ws;
10053
+ const property = iri + ws;
10054
+ const object = '(?:' + iri + '|' + bnode + '|' + literal + ')' + wso;
10055
+ const graphName = '(?:\\.|(?:(?:' + iri + '|' + bnode + ')' + wso + '\\.))';
10250
10056
 
10251
- // 5) Return the hash that results from passing the sorted, joined nquads
10252
- // through the hash algorithm.
10253
- const md = this.createMessageDigest();
10254
- for(const nquad of nquads) {
10255
- md.update(nquad);
10256
- }
10257
- info.hash = await md.digest();
10258
- return info.hash;
10259
- }
10057
+ // end of line and empty regexes
10058
+ REGEX.eoln = /(?:\r\n)|(?:\n)|(?:\r)/g;
10059
+ REGEX.empty = new RegExp('^' + wso + '$');
10260
10060
 
10261
- // 4.7) Hash Related Blank Node
10262
- async hashRelatedBlankNode(related, quad, issuer, position) {
10263
- // 1) Set the identifier to use for related, preferring first the canonical
10264
- // identifier for related if issued, second the identifier issued by issuer
10265
- // if issued, and last, if necessary, the result of the Hash First Degree
10266
- // Quads algorithm, passing related.
10267
- let id;
10268
- if(this.canonicalIssuer.hasId(related)) {
10269
- id = this.canonicalIssuer.getId(related);
10270
- } else if(issuer.hasId(related)) {
10271
- id = issuer.getId(related);
10272
- } else {
10273
- id = this.blankNodeInfo.get(related).hash;
10274
- }
10061
+ // full quad regex
10062
+ REGEX.quad = new RegExp(
10063
+ '^' + wso + subject + property + object + graphName + wso + '$');
10064
+ })();
10275
10065
 
10276
- // 2) Initialize a string input to the value of position.
10277
- // Note: We use a hash object instead.
10278
- const md = this.createMessageDigest();
10279
- md.update(position);
10066
+ module.exports = class NQuads {
10067
+ /**
10068
+ * Parses RDF in the form of N-Quads.
10069
+ *
10070
+ * @param input the N-Quads input to parse.
10071
+ *
10072
+ * @return an RDF dataset (an array of quads per http://rdf.js.org/).
10073
+ */
10074
+ static parse(input) {
10075
+ // build RDF dataset
10076
+ const dataset = [];
10280
10077
 
10281
- // 3) If position is not g, append <, the value of the predicate in quad,
10282
- // and > to input.
10283
- if(position !== 'g') {
10284
- md.update(this.getRelatedPredicate(quad));
10285
- }
10078
+ const graphs = {};
10286
10079
 
10287
- // 4) Append identifier to input.
10288
- md.update(id);
10080
+ // split N-Quad input into lines
10081
+ const lines = input.split(REGEX.eoln);
10082
+ let lineNumber = 0;
10083
+ for(const line of lines) {
10084
+ lineNumber++;
10289
10085
 
10290
- // 5) Return the hash that results from passing input through the hash
10291
- // algorithm.
10292
- return md.digest();
10293
- }
10086
+ // skip empty lines
10087
+ if(REGEX.empty.test(line)) {
10088
+ continue;
10089
+ }
10294
10090
 
10295
- // 4.8) Hash N-Degree Quads
10296
- async hashNDegreeQuads(id, issuer) {
10297
- const deepIterations = this.deepIterations.get(id) || 0;
10298
- if(deepIterations > this.maxDeepIterations) {
10299
- throw new Error(
10300
- `Maximum deep iterations (${this.maxDeepIterations}) exceeded.`);
10301
- }
10302
- this.deepIterations.set(id, deepIterations + 1);
10091
+ // parse quad
10092
+ const match = line.match(REGEX.quad);
10093
+ if(match === null) {
10094
+ throw new Error('N-Quads parse error on line ' + lineNumber + '.');
10095
+ }
10303
10096
 
10304
- // 1) Create a hash to related blank nodes map for storing hashes that
10305
- // identify related blank nodes.
10306
- // Note: 2) and 3) handled within `createHashToRelated`
10307
- const md = this.createMessageDigest();
10308
- const hashToRelated = await this.createHashToRelated(id, issuer);
10097
+ // create RDF quad
10098
+ const quad = {subject: null, predicate: null, object: null, graph: null};
10309
10099
 
10310
- // 4) Create an empty string, data to hash.
10311
- // Note: We created a hash object `md` above instead.
10100
+ // get subject
10101
+ if(match[1] !== undefined) {
10102
+ quad.subject = {termType: TYPE_NAMED_NODE, value: match[1]};
10103
+ } else {
10104
+ quad.subject = {termType: TYPE_BLANK_NODE, value: match[2]};
10105
+ }
10312
10106
 
10313
- // 5) For each related hash to blank node list mapping in hash to related
10314
- // blank nodes map, sorted lexicographically by related hash:
10315
- const hashes = [...hashToRelated.keys()].sort();
10316
- for(const hash of hashes) {
10317
- // 5.1) Append the related hash to the data to hash.
10318
- md.update(hash);
10107
+ // get predicate
10108
+ quad.predicate = {termType: TYPE_NAMED_NODE, value: match[3]};
10319
10109
 
10320
- // 5.2) Create a string chosen path.
10321
- let chosenPath = '';
10110
+ // get object
10111
+ if(match[4] !== undefined) {
10112
+ quad.object = {termType: TYPE_NAMED_NODE, value: match[4]};
10113
+ } else if(match[5] !== undefined) {
10114
+ quad.object = {termType: TYPE_BLANK_NODE, value: match[5]};
10115
+ } else {
10116
+ quad.object = {
10117
+ termType: TYPE_LITERAL,
10118
+ value: undefined,
10119
+ datatype: {
10120
+ termType: TYPE_NAMED_NODE
10121
+ }
10122
+ };
10123
+ if(match[7] !== undefined) {
10124
+ quad.object.datatype.value = match[7];
10125
+ } else if(match[8] !== undefined) {
10126
+ quad.object.datatype.value = RDF_LANGSTRING;
10127
+ quad.object.language = match[8];
10128
+ } else {
10129
+ quad.object.datatype.value = XSD_STRING;
10130
+ }
10131
+ quad.object.value = _unescape(match[6]);
10132
+ }
10322
10133
 
10323
- // 5.3) Create an unset chosen issuer variable.
10324
- let chosenIssuer;
10134
+ // get graph
10135
+ if(match[9] !== undefined) {
10136
+ quad.graph = {
10137
+ termType: TYPE_NAMED_NODE,
10138
+ value: match[9]
10139
+ };
10140
+ } else if(match[10] !== undefined) {
10141
+ quad.graph = {
10142
+ termType: TYPE_BLANK_NODE,
10143
+ value: match[10]
10144
+ };
10145
+ } else {
10146
+ quad.graph = {
10147
+ termType: TYPE_DEFAULT_GRAPH,
10148
+ value: ''
10149
+ };
10150
+ }
10325
10151
 
10326
- // 5.4) For each permutation of blank node list:
10327
- const permuter = new Permuter(hashToRelated.get(hash));
10328
- let i = 0;
10329
- while(permuter.hasNext()) {
10330
- const permutation = permuter.next();
10331
- // Note: batch permutations 3 at a time
10332
- if(++i % 3 === 0) {
10333
- await this._yield();
10152
+ // only add quad if it is unique in its graph
10153
+ if(!(quad.graph.value in graphs)) {
10154
+ graphs[quad.graph.value] = [quad];
10155
+ dataset.push(quad);
10156
+ } else {
10157
+ let unique = true;
10158
+ const quads = graphs[quad.graph.value];
10159
+ for(const q of quads) {
10160
+ if(_compareTriples(q, quad)) {
10161
+ unique = false;
10162
+ break;
10163
+ }
10164
+ }
10165
+ if(unique) {
10166
+ quads.push(quad);
10167
+ dataset.push(quad);
10334
10168
  }
10169
+ }
10170
+ }
10335
10171
 
10336
- // 5.4.1) Create a copy of issuer, issuer copy.
10337
- let issuerCopy = issuer.clone();
10172
+ return dataset;
10173
+ }
10338
10174
 
10339
- // 5.4.2) Create a string path.
10340
- let path = '';
10175
+ /**
10176
+ * Converts an RDF dataset to N-Quads.
10177
+ *
10178
+ * @param dataset (array of quads) the RDF dataset to convert.
10179
+ *
10180
+ * @return the N-Quads string.
10181
+ */
10182
+ static serialize(dataset) {
10183
+ if(!Array.isArray(dataset)) {
10184
+ dataset = NQuads.legacyDatasetToQuads(dataset);
10185
+ }
10186
+ const quads = [];
10187
+ for(const quad of dataset) {
10188
+ quads.push(NQuads.serializeQuad(quad));
10189
+ }
10190
+ return quads.sort().join('');
10191
+ }
10341
10192
 
10342
- // 5.4.3) Create a recursion list, to store blank node identifiers
10343
- // that must be recursively processed by this algorithm.
10344
- const recursionList = [];
10193
+ /**
10194
+ * Converts RDF quad components to an N-Quad string (a single quad).
10195
+ *
10196
+ * @param {Object} s - N-Quad subject component.
10197
+ * @param {Object} p - N-Quad predicate component.
10198
+ * @param {Object} o - N-Quad object component.
10199
+ * @param {Object} g - N-Quad graph component.
10200
+ *
10201
+ * @return {string} the N-Quad.
10202
+ */
10203
+ static serializeQuadComponents(s, p, o, g) {
10204
+ let nquad = '';
10345
10205
 
10346
- // 5.4.4) For each related in permutation:
10347
- let nextPermutation = false;
10348
- for(const related of permutation) {
10349
- // 5.4.4.1) If a canonical identifier has been issued for
10350
- // related, append it to path.
10351
- if(this.canonicalIssuer.hasId(related)) {
10352
- path += this.canonicalIssuer.getId(related);
10353
- } else {
10354
- // 5.4.4.2) Otherwise:
10355
- // 5.4.4.2.1) If issuer copy has not issued an identifier for
10356
- // related, append related to recursion list.
10357
- if(!issuerCopy.hasId(related)) {
10358
- recursionList.push(related);
10359
- }
10360
- // 5.4.4.2.2) Use the Issue Identifier algorithm, passing
10361
- // issuer copy and related and append the result to path.
10362
- path += issuerCopy.getId(related);
10363
- }
10206
+ // subject can only be NamedNode or BlankNode
10207
+ if(s.termType === TYPE_NAMED_NODE) {
10208
+ nquad += `<${s.value}>`;
10209
+ } else {
10210
+ nquad += `${s.value}`;
10211
+ }
10364
10212
 
10365
- // 5.4.4.3) If chosen path is not empty and the length of path
10366
- // is greater than or equal to the length of chosen path and
10367
- // path is lexicographically greater than chosen path, then
10368
- // skip to the next permutation.
10369
- // Note: Comparing path length to chosen path length can be optimized
10370
- // away; only compare lexicographically.
10371
- if(chosenPath.length !== 0 && path > chosenPath) {
10372
- nextPermutation = true;
10373
- break;
10374
- }
10375
- }
10213
+ // predicate can only be NamedNode
10214
+ nquad += ` <${p.value}> `;
10376
10215
 
10377
- if(nextPermutation) {
10378
- continue;
10216
+ // object is NamedNode, BlankNode, or Literal
10217
+ if(o.termType === TYPE_NAMED_NODE) {
10218
+ nquad += `<${o.value}>`;
10219
+ } else if(o.termType === TYPE_BLANK_NODE) {
10220
+ nquad += o.value;
10221
+ } else {
10222
+ nquad += `"${_escape(o.value)}"`;
10223
+ if(o.datatype.value === RDF_LANGSTRING) {
10224
+ if(o.language) {
10225
+ nquad += `@${o.language}`;
10379
10226
  }
10227
+ } else if(o.datatype.value !== XSD_STRING) {
10228
+ nquad += `^^<${o.datatype.value}>`;
10229
+ }
10230
+ }
10380
10231
 
10381
- // 5.4.5) For each related in recursion list:
10382
- for(const related of recursionList) {
10383
- // 5.4.5.1) Set result to the result of recursively executing
10384
- // the Hash N-Degree Quads algorithm, passing related for
10385
- // identifier and issuer copy for path identifier issuer.
10386
- const result = await this.hashNDegreeQuads(related, issuerCopy);
10232
+ // graph can only be NamedNode or BlankNode (or DefaultGraph, but that
10233
+ // does not add to `nquad`)
10234
+ if(g.termType === TYPE_NAMED_NODE) {
10235
+ nquad += ` <${g.value}>`;
10236
+ } else if(g.termType === TYPE_BLANK_NODE) {
10237
+ nquad += ` ${g.value}`;
10238
+ }
10387
10239
 
10388
- // 5.4.5.2) Use the Issue Identifier algorithm, passing issuer
10389
- // copy and related and append the result to path.
10390
- path += issuerCopy.getId(related);
10240
+ nquad += ' .\n';
10241
+ return nquad;
10242
+ }
10391
10243
 
10392
- // 5.4.5.3) Append <, the hash in result, and > to path.
10393
- path += `<${result.hash}>`;
10244
+ /**
10245
+ * Converts an RDF quad to an N-Quad string (a single quad).
10246
+ *
10247
+ * @param quad the RDF quad convert.
10248
+ *
10249
+ * @return the N-Quad string.
10250
+ */
10251
+ static serializeQuad(quad) {
10252
+ return NQuads.serializeQuadComponents(
10253
+ quad.subject, quad.predicate, quad.object, quad.graph);
10254
+ }
10394
10255
 
10395
- // 5.4.5.4) Set issuer copy to the identifier issuer in
10396
- // result.
10397
- issuerCopy = result.issuer;
10256
+ /**
10257
+ * Converts a legacy-formatted dataset to an array of quads dataset per
10258
+ * http://rdf.js.org/.
10259
+ *
10260
+ * @param dataset the legacy dataset to convert.
10261
+ *
10262
+ * @return the array of quads dataset.
10263
+ */
10264
+ static legacyDatasetToQuads(dataset) {
10265
+ const quads = [];
10398
10266
 
10399
- // 5.4.5.5) If chosen path is not empty and the length of path
10400
- // is greater than or equal to the length of chosen path and
10401
- // path is lexicographically greater than chosen path, then
10402
- // skip to the next permutation.
10403
- // Note: Comparing path length to chosen path length can be optimized
10404
- // away; only compare lexicographically.
10405
- if(chosenPath.length !== 0 && path > chosenPath) {
10406
- nextPermutation = true;
10407
- break;
10408
- }
10409
- }
10267
+ const termTypeMap = {
10268
+ 'blank node': TYPE_BLANK_NODE,
10269
+ IRI: TYPE_NAMED_NODE,
10270
+ literal: TYPE_LITERAL
10271
+ };
10410
10272
 
10411
- if(nextPermutation) {
10412
- continue;
10273
+ for(const graphName in dataset) {
10274
+ const triples = dataset[graphName];
10275
+ triples.forEach(triple => {
10276
+ const quad = {};
10277
+ for(const componentName in triple) {
10278
+ const oldComponent = triple[componentName];
10279
+ const newComponent = {
10280
+ termType: termTypeMap[oldComponent.type],
10281
+ value: oldComponent.value
10282
+ };
10283
+ if(newComponent.termType === TYPE_LITERAL) {
10284
+ newComponent.datatype = {
10285
+ termType: TYPE_NAMED_NODE
10286
+ };
10287
+ if('datatype' in oldComponent) {
10288
+ newComponent.datatype.value = oldComponent.datatype;
10289
+ }
10290
+ if('language' in oldComponent) {
10291
+ if(!('datatype' in oldComponent)) {
10292
+ newComponent.datatype.value = RDF_LANGSTRING;
10293
+ }
10294
+ newComponent.language = oldComponent.language;
10295
+ } else if(!('datatype' in oldComponent)) {
10296
+ newComponent.datatype.value = XSD_STRING;
10297
+ }
10298
+ }
10299
+ quad[componentName] = newComponent;
10413
10300
  }
10414
-
10415
- // 5.4.6) If chosen path is empty or path is lexicographically
10416
- // less than chosen path, set chosen path to path and chosen
10417
- // issuer to issuer copy.
10418
- if(chosenPath.length === 0 || path < chosenPath) {
10419
- chosenPath = path;
10420
- chosenIssuer = issuerCopy;
10301
+ if(graphName === '@default') {
10302
+ quad.graph = {
10303
+ termType: TYPE_DEFAULT_GRAPH,
10304
+ value: ''
10305
+ };
10306
+ } else {
10307
+ quad.graph = {
10308
+ termType: graphName.startsWith('_:') ?
10309
+ TYPE_BLANK_NODE : TYPE_NAMED_NODE,
10310
+ value: graphName
10311
+ };
10421
10312
  }
10422
- }
10423
-
10424
- // 5.5) Append chosen path to data to hash.
10425
- md.update(chosenPath);
10426
-
10427
- // 5.6) Replace issuer, by reference, with chosen issuer.
10428
- issuer = chosenIssuer;
10313
+ quads.push(quad);
10314
+ });
10429
10315
  }
10430
10316
 
10431
- // 6) Return issuer and the hash that results from passing data to hash
10432
- // through the hash algorithm.
10433
- return {hash: await md.digest(), issuer};
10317
+ return quads;
10434
10318
  }
10319
+ };
10435
10320
 
10436
- // helper for modifying component during Hash First Degree Quads
10437
- modifyFirstDegreeComponent(id, component) {
10438
- if(component.termType !== 'BlankNode') {
10439
- return component;
10440
- }
10441
- /* Note: A mistake in the URDNA2015 spec that made its way into
10442
- implementations (and therefore must stay to avoid interop breakage)
10443
- resulted in an assigned canonical ID, if available for
10444
- `component.value`, not being used in place of `_:a`/`_:z`, so
10445
- we don't use it here. */
10446
- return {
10447
- termType: 'BlankNode',
10448
- value: component.value === id ? '_:a' : '_:z'
10449
- };
10321
+ /**
10322
+ * Compares two RDF triples for equality.
10323
+ *
10324
+ * @param t1 the first triple.
10325
+ * @param t2 the second triple.
10326
+ *
10327
+ * @return true if the triples are the same, false if not.
10328
+ */
10329
+ function _compareTriples(t1, t2) {
10330
+ // compare subject and object types first as it is the quickest check
10331
+ if(!(t1.subject.termType === t2.subject.termType &&
10332
+ t1.object.termType === t2.object.termType)) {
10333
+ return false;
10450
10334
  }
10451
-
10452
- // helper for getting a related predicate
10453
- getRelatedPredicate(quad) {
10454
- return `<${quad.predicate.value}>`;
10335
+ // compare values
10336
+ if(!(t1.subject.value === t2.subject.value &&
10337
+ t1.predicate.value === t2.predicate.value &&
10338
+ t1.object.value === t2.object.value)) {
10339
+ return false;
10455
10340
  }
10341
+ if(t1.object.termType !== TYPE_LITERAL) {
10342
+ // no `datatype` or `language` to check
10343
+ return true;
10344
+ }
10345
+ return (
10346
+ (t1.object.datatype.termType === t2.object.datatype.termType) &&
10347
+ (t1.object.language === t2.object.language) &&
10348
+ (t1.object.datatype.value === t2.object.datatype.value)
10349
+ );
10350
+ }
10456
10351
 
10457
- // helper for creating hash to related blank nodes map
10458
- async createHashToRelated(id, issuer) {
10459
- // 1) Create a hash to related blank nodes map for storing hashes that
10460
- // identify related blank nodes.
10461
- const hashToRelated = new Map();
10462
-
10463
- // 2) Get a reference, quads, to the list of quads in the blank node to
10464
- // quads map for the key identifier.
10465
- const quads = this.blankNodeInfo.get(id).quads;
10352
+ const _escapeRegex = /["\\\n\r]/g;
10353
+ /**
10354
+ * Escape string to N-Quads literal
10355
+ */
10356
+ function _escape(s) {
10357
+ return s.replace(_escapeRegex, function(match) {
10358
+ switch(match) {
10359
+ case '"': return '\\"';
10360
+ case '\\': return '\\\\';
10361
+ case '\n': return '\\n';
10362
+ case '\r': return '\\r';
10363
+ }
10364
+ });
10365
+ }
10466
10366
 
10467
- // 3) For each quad in quads:
10468
- let i = 0;
10469
- for(const quad of quads) {
10470
- // Note: batch hashing related blank node quads 100 at a time
10471
- if(++i % 100 === 0) {
10472
- await this._yield();
10473
- }
10474
- // 3.1) For each component in quad, if component is the subject, object,
10475
- // and graph name and it is a blank node that is not identified by
10476
- // identifier:
10477
- // steps 3.1.1 and 3.1.2 occur in helpers:
10478
- await Promise.all([
10479
- this._addRelatedBlankNodeHash({
10480
- quad, component: quad.subject, position: 's',
10481
- id, issuer, hashToRelated
10482
- }),
10483
- this._addRelatedBlankNodeHash({
10484
- quad, component: quad.object, position: 'o',
10485
- id, issuer, hashToRelated
10486
- }),
10487
- this._addRelatedBlankNodeHash({
10488
- quad, component: quad.graph, position: 'g',
10489
- id, issuer, hashToRelated
10490
- })
10491
- ]);
10367
+ const _unescapeRegex =
10368
+ /(?:\\([tbnrf"'\\]))|(?:\\u([0-9A-Fa-f]{4}))|(?:\\U([0-9A-Fa-f]{8}))/g;
10369
+ /**
10370
+ * Unescape N-Quads literal to string
10371
+ */
10372
+ function _unescape(s) {
10373
+ return s.replace(_unescapeRegex, function(match, code, u, U) {
10374
+ if(code) {
10375
+ switch(code) {
10376
+ case 't': return '\t';
10377
+ case 'b': return '\b';
10378
+ case 'n': return '\n';
10379
+ case 'r': return '\r';
10380
+ case 'f': return '\f';
10381
+ case '"': return '"';
10382
+ case '\'': return '\'';
10383
+ case '\\': return '\\';
10384
+ }
10385
+ }
10386
+ if(u) {
10387
+ return String.fromCharCode(parseInt(u, 16));
10388
+ }
10389
+ if(U) {
10390
+ // FIXME: support larger values
10391
+ throw new Error('Unsupported U escape');
10492
10392
  }
10393
+ });
10394
+ }
10493
10395
 
10494
- return hashToRelated;
10495
- }
10496
10396
 
10497
- async _hashAndTrackBlankNode({id, hashToBlankNodes}) {
10498
- // 5.3.1) Create a hash, hash, according to the Hash First Degree
10499
- // Quads algorithm.
10500
- const hash = await this.hashFirstDegreeQuads(id);
10397
+ /***/ }),
10501
10398
 
10502
- // 5.3.2) Add hash and identifier to hash to blank nodes map,
10503
- // creating a new entry if necessary.
10504
- const idList = hashToBlankNodes.get(hash);
10505
- if(!idList) {
10506
- hashToBlankNodes.set(hash, [id]);
10507
- } else {
10508
- idList.push(id);
10399
+ /***/ "./node_modules/rdf-canonize/lib/Permuter.js":
10400
+ /*!***************************************************!*\
10401
+ !*** ./node_modules/rdf-canonize/lib/Permuter.js ***!
10402
+ \***************************************************/
10403
+ /***/ ((module) => {
10404
+
10405
+ "use strict";
10406
+ /*!
10407
+ * Copyright (c) 2016-2022 Digital Bazaar, Inc. All rights reserved.
10408
+ */
10409
+
10410
+
10411
+ module.exports = class Permuter {
10412
+ /**
10413
+ * A Permuter iterates over all possible permutations of the given array
10414
+ * of elements.
10415
+ *
10416
+ * @param list the array of elements to iterate over.
10417
+ */
10418
+ constructor(list) {
10419
+ // original array
10420
+ this.current = list.sort();
10421
+ // indicates whether there are more permutations
10422
+ this.done = false;
10423
+ // directional info for permutation algorithm
10424
+ this.dir = new Map();
10425
+ for(let i = 0; i < list.length; ++i) {
10426
+ this.dir.set(list[i], true);
10509
10427
  }
10510
10428
  }
10511
10429
 
10512
- _addBlankNodeQuadInfo({quad, component}) {
10513
- if(component.termType !== 'BlankNode') {
10514
- return;
10515
- }
10516
- const id = component.value;
10517
- const info = this.blankNodeInfo.get(id);
10518
- if(info) {
10519
- info.quads.add(quad);
10520
- } else {
10521
- this.blankNodeInfo.set(id, {quads: new Set([quad]), hash: null});
10522
- }
10430
+ /**
10431
+ * Returns true if there is another permutation.
10432
+ *
10433
+ * @return true if there is another permutation, false if not.
10434
+ */
10435
+ hasNext() {
10436
+ return !this.done;
10523
10437
  }
10524
10438
 
10525
- async _addRelatedBlankNodeHash(
10526
- {quad, component, position, id, issuer, hashToRelated}) {
10527
- if(!(component.termType === 'BlankNode' && component.value !== id)) {
10528
- return;
10439
+ /**
10440
+ * Gets the next permutation. Call hasNext() to ensure there is another one
10441
+ * first.
10442
+ *
10443
+ * @return the next permutation.
10444
+ */
10445
+ next() {
10446
+ // copy current permutation to return it
10447
+ const {current, dir} = this;
10448
+ const rval = current.slice();
10449
+
10450
+ /* Calculate the next permutation using the Steinhaus-Johnson-Trotter
10451
+ permutation algorithm. */
10452
+
10453
+ // get largest mobile element k
10454
+ // (mobile: element is greater than the one it is looking at)
10455
+ let k = null;
10456
+ let pos = 0;
10457
+ const length = current.length;
10458
+ for(let i = 0; i < length; ++i) {
10459
+ const element = current[i];
10460
+ const left = dir.get(element);
10461
+ if((k === null || element > k) &&
10462
+ ((left && i > 0 && element > current[i - 1]) ||
10463
+ (!left && i < (length - 1) && element > current[i + 1]))) {
10464
+ k = element;
10465
+ pos = i;
10466
+ }
10529
10467
  }
10530
- // 3.1.1) Set hash to the result of the Hash Related Blank Node
10531
- // algorithm, passing the blank node identifier for component as
10532
- // related, quad, path identifier issuer as issuer, and position as
10533
- // either s, o, or g based on whether component is a subject, object,
10534
- // graph name, respectively.
10535
- const related = component.value;
10536
- const hash = await this.hashRelatedBlankNode(
10537
- related, quad, issuer, position);
10538
10468
 
10539
- // 3.1.2) Add a mapping of hash to the blank node identifier for
10540
- // component to hash to related blank nodes map, adding an entry as
10541
- // necessary.
10542
- const entries = hashToRelated.get(hash);
10543
- if(entries) {
10544
- entries.push(related);
10469
+ // no more permutations
10470
+ if(k === null) {
10471
+ this.done = true;
10545
10472
  } else {
10546
- hashToRelated.set(hash, [related]);
10547
- }
10548
- }
10473
+ // swap k and the element it is looking at
10474
+ const swap = dir.get(k) ? pos - 1 : pos + 1;
10475
+ current[pos] = current[swap];
10476
+ current[swap] = k;
10549
10477
 
10550
- // canonical ids for 7.1
10551
- _componentWithCanonicalId(component) {
10552
- if(component.termType === 'BlankNode' &&
10553
- !component.value.startsWith(this.canonicalIssuer.prefix)) {
10554
- // create new BlankNode
10555
- return {
10556
- termType: 'BlankNode',
10557
- value: this.canonicalIssuer.getId(component.value)
10558
- };
10478
+ // reverse the direction of all elements larger than k
10479
+ for(const element of current) {
10480
+ if(element > k) {
10481
+ dir.set(element, !dir.get(element));
10482
+ }
10483
+ }
10559
10484
  }
10560
- return component;
10561
- }
10562
10485
 
10563
- async _yield() {
10564
- return new Promise(resolve => setImmediate(resolve));
10486
+ return rval;
10565
10487
  }
10566
10488
  };
10567
10489
 
10568
- function _stringHashCompare(a, b) {
10569
- return a.hash < b.hash ? -1 : a.hash > b.hash ? 1 : 0;
10570
- }
10571
-
10572
10490
 
10573
10491
  /***/ }),
10574
10492
 
10575
- /***/ "./node_modules/rdf-canonize/lib/URDNA2015Sync.js":
10576
- /*!********************************************************!*\
10577
- !*** ./node_modules/rdf-canonize/lib/URDNA2015Sync.js ***!
10578
- \********************************************************/
10493
+ /***/ "./node_modules/rdf-canonize/lib/URDNA2015.js":
10494
+ /*!****************************************************!*\
10495
+ !*** ./node_modules/rdf-canonize/lib/URDNA2015.js ***!
10496
+ \****************************************************/
10579
10497
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
10580
10498
 
10581
10499
  "use strict";
@@ -10585,13 +10503,11 @@ function _stringHashCompare(a, b) {
10585
10503
 
10586
10504
 
10587
10505
  const IdentifierIssuer = __webpack_require__(/*! ./IdentifierIssuer */ "./node_modules/rdf-canonize/lib/IdentifierIssuer.js");
10588
- // FIXME: do not import; convert to requiring a
10589
- // hash factory
10590
10506
  const MessageDigest = __webpack_require__(/*! ./MessageDigest */ "./node_modules/rdf-canonize/lib/MessageDigest-browser.js");
10591
10507
  const Permuter = __webpack_require__(/*! ./Permuter */ "./node_modules/rdf-canonize/lib/Permuter.js");
10592
10508
  const NQuads = __webpack_require__(/*! ./NQuads */ "./node_modules/rdf-canonize/lib/NQuads.js");
10593
10509
 
10594
- module.exports = class URDNA2015Sync {
10510
+ module.exports = class URDNA2015 {
10595
10511
  constructor({
10596
10512
  createMessageDigest = () => new MessageDigest('sha256'),
10597
10513
  maxDeepIterations = Infinity
@@ -10606,7 +10522,7 @@ module.exports = class URDNA2015Sync {
10606
10522
  }
10607
10523
 
10608
10524
  // 4.4) Normalization Algorithm
10609
- main(dataset) {
10525
+ async main(dataset) {
10610
10526
  this.deepIterations = new Map();
10611
10527
  this.quads = dataset;
10612
10528
 
@@ -10638,9 +10554,14 @@ module.exports = class URDNA2015Sync {
10638
10554
  // identifiers:
10639
10555
  const hashToBlankNodes = new Map();
10640
10556
  const nonNormalized = [...this.blankNodeInfo.keys()];
10557
+ let i = 0;
10641
10558
  for(const id of nonNormalized) {
10559
+ // Note: batch hashing first degree quads 100 at a time
10560
+ if(++i % 100 === 0) {
10561
+ await this._yield();
10562
+ }
10642
10563
  // steps 5.3.1 and 5.3.2:
10643
- this._hashAndTrackBlankNode({id, hashToBlankNodes});
10564
+ await this._hashAndTrackBlankNode({id, hashToBlankNodes});
10644
10565
  }
10645
10566
 
10646
10567
  // 5.4) For each hash to identifier list mapping in hash to blank
@@ -10698,7 +10619,7 @@ module.exports = class URDNA2015Sync {
10698
10619
 
10699
10620
  // 6.2.4) Run the Hash N-Degree Quads algorithm, passing
10700
10621
  // temporary issuer, and append the result to the hash path list.
10701
- const result = this.hashNDegreeQuads(id, issuer);
10622
+ const result = await this.hashNDegreeQuads(id, issuer);
10702
10623
  hashPathList.push(result);
10703
10624
  }
10704
10625
 
@@ -10731,10 +10652,10 @@ module.exports = class URDNA2015Sync {
10731
10652
  // previously issued by canonical issuer.
10732
10653
  // Note: We optimize away the copy here.
10733
10654
  const nQuad = NQuads.serializeQuadComponents(
10734
- this._componentWithCanonicalId({component: quad.subject}),
10655
+ this._componentWithCanonicalId(quad.subject),
10735
10656
  quad.predicate,
10736
- this._componentWithCanonicalId({component: quad.object}),
10737
- this._componentWithCanonicalId({component: quad.graph})
10657
+ this._componentWithCanonicalId(quad.object),
10658
+ this._componentWithCanonicalId(quad.graph)
10738
10659
  );
10739
10660
  // 7.2) Add quad copy to the normalized dataset.
10740
10661
  normalized.push(nQuad);
@@ -10748,7 +10669,7 @@ module.exports = class URDNA2015Sync {
10748
10669
  }
10749
10670
 
10750
10671
  // 4.6) Hash First Degree Quads
10751
- hashFirstDegreeQuads(id) {
10672
+ async hashFirstDegreeQuads(id) {
10752
10673
  // 1) Initialize nquads to an empty list. It will be used to store quads in
10753
10674
  // N-Quads format.
10754
10675
  const nquads = [];
@@ -10789,12 +10710,12 @@ module.exports = class URDNA2015Sync {
10789
10710
  for(const nquad of nquads) {
10790
10711
  md.update(nquad);
10791
10712
  }
10792
- info.hash = md.digest();
10713
+ info.hash = await md.digest();
10793
10714
  return info.hash;
10794
10715
  }
10795
10716
 
10796
10717
  // 4.7) Hash Related Blank Node
10797
- hashRelatedBlankNode(related, quad, issuer, position) {
10718
+ async hashRelatedBlankNode(related, quad, issuer, position) {
10798
10719
  // 1) Set the identifier to use for related, preferring first the canonical
10799
10720
  // identifier for related if issued, second the identifier issued by issuer
10800
10721
  // if issued, and last, if necessary, the result of the Hash First Degree
@@ -10828,7 +10749,7 @@ module.exports = class URDNA2015Sync {
10828
10749
  }
10829
10750
 
10830
10751
  // 4.8) Hash N-Degree Quads
10831
- hashNDegreeQuads(id, issuer) {
10752
+ async hashNDegreeQuads(id, issuer) {
10832
10753
  const deepIterations = this.deepIterations.get(id) || 0;
10833
10754
  if(deepIterations > this.maxDeepIterations) {
10834
10755
  throw new Error(
@@ -10840,7 +10761,7 @@ module.exports = class URDNA2015Sync {
10840
10761
  // identify related blank nodes.
10841
10762
  // Note: 2) and 3) handled within `createHashToRelated`
10842
10763
  const md = this.createMessageDigest();
10843
- const hashToRelated = this.createHashToRelated(id, issuer);
10764
+ const hashToRelated = await this.createHashToRelated(id, issuer);
10844
10765
 
10845
10766
  // 4) Create an empty string, data to hash.
10846
10767
  // Note: We created a hash object `md` above instead.
@@ -10860,8 +10781,13 @@ module.exports = class URDNA2015Sync {
10860
10781
 
10861
10782
  // 5.4) For each permutation of blank node list:
10862
10783
  const permuter = new Permuter(hashToRelated.get(hash));
10784
+ let i = 0;
10863
10785
  while(permuter.hasNext()) {
10864
10786
  const permutation = permuter.next();
10787
+ // Note: batch permutations 3 at a time
10788
+ if(++i % 3 === 0) {
10789
+ await this._yield();
10790
+ }
10865
10791
 
10866
10792
  // 5.4.1) Create a copy of issuer, issuer copy.
10867
10793
  let issuerCopy = issuer.clone();
@@ -10913,7 +10839,7 @@ module.exports = class URDNA2015Sync {
10913
10839
  // 5.4.5.1) Set result to the result of recursively executing
10914
10840
  // the Hash N-Degree Quads algorithm, passing related for
10915
10841
  // identifier and issuer copy for path identifier issuer.
10916
- const result = this.hashNDegreeQuads(related, issuerCopy);
10842
+ const result = await this.hashNDegreeQuads(related, issuerCopy);
10917
10843
 
10918
10844
  // 5.4.5.2) Use the Issue Identifier algorithm, passing issuer
10919
10845
  // copy and related and append the result to path.
@@ -10960,7 +10886,7 @@ module.exports = class URDNA2015Sync {
10960
10886
 
10961
10887
  // 6) Return issuer and the hash that results from passing data to hash
10962
10888
  // through the hash algorithm.
10963
- return {hash: md.digest(), issuer};
10889
+ return {hash: await md.digest(), issuer};
10964
10890
  }
10965
10891
 
10966
10892
  // helper for modifying component during Hash First Degree Quads
@@ -10985,7 +10911,7 @@ module.exports = class URDNA2015Sync {
10985
10911
  }
10986
10912
 
10987
10913
  // helper for creating hash to related blank nodes map
10988
- createHashToRelated(id, issuer) {
10914
+ async createHashToRelated(id, issuer) {
10989
10915
  // 1) Create a hash to related blank nodes map for storing hashes that
10990
10916
  // identify related blank nodes.
10991
10917
  const hashToRelated = new Map();
@@ -10995,32 +10921,39 @@ module.exports = class URDNA2015Sync {
10995
10921
  const quads = this.blankNodeInfo.get(id).quads;
10996
10922
 
10997
10923
  // 3) For each quad in quads:
10924
+ let i = 0;
10998
10925
  for(const quad of quads) {
10926
+ // Note: batch hashing related blank node quads 100 at a time
10927
+ if(++i % 100 === 0) {
10928
+ await this._yield();
10929
+ }
10999
10930
  // 3.1) For each component in quad, if component is the subject, object,
11000
- // or graph name and it is a blank node that is not identified by
10931
+ // and graph name and it is a blank node that is not identified by
11001
10932
  // identifier:
11002
10933
  // steps 3.1.1 and 3.1.2 occur in helpers:
11003
- this._addRelatedBlankNodeHash({
11004
- quad, component: quad.subject, position: 's',
11005
- id, issuer, hashToRelated
11006
- });
11007
- this._addRelatedBlankNodeHash({
11008
- quad, component: quad.object, position: 'o',
11009
- id, issuer, hashToRelated
11010
- });
11011
- this._addRelatedBlankNodeHash({
11012
- quad, component: quad.graph, position: 'g',
11013
- id, issuer, hashToRelated
11014
- });
10934
+ await Promise.all([
10935
+ this._addRelatedBlankNodeHash({
10936
+ quad, component: quad.subject, position: 's',
10937
+ id, issuer, hashToRelated
10938
+ }),
10939
+ this._addRelatedBlankNodeHash({
10940
+ quad, component: quad.object, position: 'o',
10941
+ id, issuer, hashToRelated
10942
+ }),
10943
+ this._addRelatedBlankNodeHash({
10944
+ quad, component: quad.graph, position: 'g',
10945
+ id, issuer, hashToRelated
10946
+ })
10947
+ ]);
11015
10948
  }
11016
10949
 
11017
10950
  return hashToRelated;
11018
10951
  }
11019
10952
 
11020
- _hashAndTrackBlankNode({id, hashToBlankNodes}) {
10953
+ async _hashAndTrackBlankNode({id, hashToBlankNodes}) {
11021
10954
  // 5.3.1) Create a hash, hash, according to the Hash First Degree
11022
10955
  // Quads algorithm.
11023
- const hash = this.hashFirstDegreeQuads(id);
10956
+ const hash = await this.hashFirstDegreeQuads(id);
11024
10957
 
11025
10958
  // 5.3.2) Add hash and identifier to hash to blank nodes map,
11026
10959
  // creating a new entry if necessary.
@@ -11045,7 +10978,7 @@ module.exports = class URDNA2015Sync {
11045
10978
  }
11046
10979
  }
11047
10980
 
11048
- _addRelatedBlankNodeHash(
10981
+ async _addRelatedBlankNodeHash(
11049
10982
  {quad, component, position, id, issuer, hashToRelated}) {
11050
10983
  if(!(component.termType === 'BlankNode' && component.value !== id)) {
11051
10984
  return;
@@ -11056,7 +10989,8 @@ module.exports = class URDNA2015Sync {
11056
10989
  // either s, o, or g based on whether component is a subject, object,
11057
10990
  // graph name, respectively.
11058
10991
  const related = component.value;
11059
- const hash = this.hashRelatedBlankNode(related, quad, issuer, position);
10992
+ const hash = await this.hashRelatedBlankNode(
10993
+ related, quad, issuer, position);
11060
10994
 
11061
10995
  // 3.1.2) Add a mapping of hash to the blank node identifier for
11062
10996
  // component to hash to related blank nodes map, adding an entry as
@@ -11070,7 +11004,7 @@ module.exports = class URDNA2015Sync {
11070
11004
  }
11071
11005
 
11072
11006
  // canonical ids for 7.1
11073
- _componentWithCanonicalId({component}) {
11007
+ _componentWithCanonicalId(component) {
11074
11008
  if(component.termType === 'BlankNode' &&
11075
11009
  !component.value.startsWith(this.canonicalIssuer.prefix)) {
11076
11010
  // create new BlankNode
@@ -11081,6 +11015,10 @@ module.exports = class URDNA2015Sync {
11081
11015
  }
11082
11016
  return component;
11083
11017
  }
11018
+
11019
+ async _yield() {
11020
+ return new Promise(resolve => setImmediate(resolve));
11021
+ }
11084
11022
  };
11085
11023
 
11086
11024
  function _stringHashCompare(a, b) {
@@ -11090,10 +11028,10 @@ function _stringHashCompare(a, b) {
11090
11028
 
11091
11029
  /***/ }),
11092
11030
 
11093
- /***/ "./node_modules/rdf-canonize/lib/URGNA2012.js":
11094
- /*!****************************************************!*\
11095
- !*** ./node_modules/rdf-canonize/lib/URGNA2012.js ***!
11096
- \****************************************************/
11031
+ /***/ "./node_modules/rdf-canonize/lib/URDNA2015Sync.js":
11032
+ /*!********************************************************!*\
11033
+ !*** ./node_modules/rdf-canonize/lib/URDNA2015Sync.js ***!
11034
+ \********************************************************/
11097
11035
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
11098
11036
 
11099
11037
  "use strict";
@@ -11102,1030 +11040,1092 @@ function _stringHashCompare(a, b) {
11102
11040
  */
11103
11041
 
11104
11042
 
11043
+ const IdentifierIssuer = __webpack_require__(/*! ./IdentifierIssuer */ "./node_modules/rdf-canonize/lib/IdentifierIssuer.js");
11044
+ // FIXME: do not import; convert to requiring a
11045
+ // hash factory
11105
11046
  const MessageDigest = __webpack_require__(/*! ./MessageDigest */ "./node_modules/rdf-canonize/lib/MessageDigest-browser.js");
11106
- const URDNA2015 = __webpack_require__(/*! ./URDNA2015 */ "./node_modules/rdf-canonize/lib/URDNA2015.js");
11047
+ const Permuter = __webpack_require__(/*! ./Permuter */ "./node_modules/rdf-canonize/lib/Permuter.js");
11048
+ const NQuads = __webpack_require__(/*! ./NQuads */ "./node_modules/rdf-canonize/lib/NQuads.js");
11107
11049
 
11108
- module.exports = class URDNA2012 extends URDNA2015 {
11109
- constructor() {
11110
- super();
11111
- this.name = 'URGNA2012';
11112
- this.createMessageDigest = () => new MessageDigest('sha1');
11050
+ module.exports = class URDNA2015Sync {
11051
+ constructor({
11052
+ createMessageDigest = () => new MessageDigest('sha256'),
11053
+ maxDeepIterations = Infinity
11054
+ } = {}) {
11055
+ this.name = 'URDNA2015';
11056
+ this.blankNodeInfo = new Map();
11057
+ this.canonicalIssuer = new IdentifierIssuer('_:c14n');
11058
+ this.createMessageDigest = createMessageDigest;
11059
+ this.maxDeepIterations = maxDeepIterations;
11060
+ this.quads = null;
11061
+ this.deepIterations = null;
11113
11062
  }
11114
11063
 
11115
- // helper for modifying component during Hash First Degree Quads
11116
- modifyFirstDegreeComponent(id, component, key) {
11117
- if(component.termType !== 'BlankNode') {
11118
- return component;
11119
- }
11120
- if(key === 'graph') {
11121
- return {
11122
- termType: 'BlankNode',
11123
- value: '_:g'
11124
- };
11064
+ // 4.4) Normalization Algorithm
11065
+ main(dataset) {
11066
+ this.deepIterations = new Map();
11067
+ this.quads = dataset;
11068
+
11069
+ // 1) Create the normalization state.
11070
+ // 2) For every quad in input dataset:
11071
+ for(const quad of dataset) {
11072
+ // 2.1) For each blank node that occurs in the quad, add a reference
11073
+ // to the quad using the blank node identifier in the blank node to
11074
+ // quads map, creating a new entry if necessary.
11075
+ this._addBlankNodeQuadInfo({quad, component: quad.subject});
11076
+ this._addBlankNodeQuadInfo({quad, component: quad.object});
11077
+ this._addBlankNodeQuadInfo({quad, component: quad.graph});
11125
11078
  }
11126
- return {
11127
- termType: 'BlankNode',
11128
- value: (component.value === id ? '_:a' : '_:z')
11129
- };
11130
- }
11131
11079
 
11132
- // helper for getting a related predicate
11133
- getRelatedPredicate(quad) {
11134
- return quad.predicate.value;
11135
- }
11080
+ // 3) Create a list of non-normalized blank node identifiers
11081
+ // non-normalized identifiers and populate it using the keys from the
11082
+ // blank node to quads map.
11083
+ // Note: We use a map here and it was generated during step 2.
11136
11084
 
11137
- // helper for creating hash to related blank nodes map
11138
- async createHashToRelated(id, issuer) {
11139
- // 1) Create a hash to related blank nodes map for storing hashes that
11140
- // identify related blank nodes.
11141
- const hashToRelated = new Map();
11085
+ // 4) `simple` flag is skipped -- loop is optimized away. This optimization
11086
+ // is permitted because there was a typo in the hash first degree quads
11087
+ // algorithm in the URDNA2015 spec that was implemented widely making it
11088
+ // such that it could not be fixed; the result was that the loop only
11089
+ // needs to be run once and the first degree quad hashes will never change.
11090
+ // 5.1-5.2 are skipped; first degree quad hashes are generated just once
11091
+ // for all non-normalized blank nodes.
11142
11092
 
11143
- // 2) Get a reference, quads, to the list of quads in the blank node to
11144
- // quads map for the key identifier.
11145
- const quads = this.blankNodeInfo.get(id).quads;
11093
+ // 5.3) For each blank node identifier identifier in non-normalized
11094
+ // identifiers:
11095
+ const hashToBlankNodes = new Map();
11096
+ const nonNormalized = [...this.blankNodeInfo.keys()];
11097
+ for(const id of nonNormalized) {
11098
+ // steps 5.3.1 and 5.3.2:
11099
+ this._hashAndTrackBlankNode({id, hashToBlankNodes});
11100
+ }
11146
11101
 
11147
- // 3) For each quad in quads:
11148
- let i = 0;
11149
- for(const quad of quads) {
11150
- // 3.1) If the quad's subject is a blank node that does not match
11151
- // identifier, set hash to the result of the Hash Related Blank Node
11152
- // algorithm, passing the blank node identifier for subject as related,
11153
- // quad, path identifier issuer as issuer, and p as position.
11154
- let position;
11155
- let related;
11156
- if(quad.subject.termType === 'BlankNode' && quad.subject.value !== id) {
11157
- related = quad.subject.value;
11158
- position = 'p';
11159
- } else if(
11160
- quad.object.termType === 'BlankNode' && quad.object.value !== id) {
11161
- // 3.2) Otherwise, if quad's object is a blank node that does not match
11162
- // identifier, to the result of the Hash Related Blank Node algorithm,
11163
- // passing the blank node identifier for object as related, quad, path
11164
- // identifier issuer as issuer, and r as position.
11165
- related = quad.object.value;
11166
- position = 'r';
11167
- } else {
11168
- // 3.3) Otherwise, continue to the next quad.
11102
+ // 5.4) For each hash to identifier list mapping in hash to blank
11103
+ // nodes map, lexicographically-sorted by hash:
11104
+ const hashes = [...hashToBlankNodes.keys()].sort();
11105
+ // optimize away second sort, gather non-unique hashes in order as we go
11106
+ const nonUnique = [];
11107
+ for(const hash of hashes) {
11108
+ // 5.4.1) If the length of identifier list is greater than 1,
11109
+ // continue to the next mapping.
11110
+ const idList = hashToBlankNodes.get(hash);
11111
+ if(idList.length > 1) {
11112
+ nonUnique.push(idList);
11169
11113
  continue;
11170
11114
  }
11171
- // Note: batch hashing related blank nodes 100 at a time
11172
- if(++i % 100 === 0) {
11173
- await this._yield();
11174
- }
11175
- // 3.4) Add a mapping of hash to the blank node identifier for the
11176
- // component that matched (subject or object) to hash to related blank
11177
- // nodes map, adding an entry as necessary.
11178
- const hash = await this.hashRelatedBlankNode(
11179
- related, quad, issuer, position);
11180
- const entries = hashToRelated.get(hash);
11181
- if(entries) {
11182
- entries.push(related);
11183
- } else {
11184
- hashToRelated.set(hash, [related]);
11185
- }
11186
- }
11187
-
11188
- return hashToRelated;
11189
- }
11190
- };
11191
-
11192
-
11193
- /***/ }),
11194
-
11195
- /***/ "./node_modules/rdf-canonize/lib/URGNA2012Sync.js":
11196
- /*!********************************************************!*\
11197
- !*** ./node_modules/rdf-canonize/lib/URGNA2012Sync.js ***!
11198
- \********************************************************/
11199
- /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
11200
-
11201
- "use strict";
11202
- /*!
11203
- * Copyright (c) 2016-2021 Digital Bazaar, Inc. All rights reserved.
11204
- */
11205
-
11206
-
11207
- const MessageDigest = __webpack_require__(/*! ./MessageDigest */ "./node_modules/rdf-canonize/lib/MessageDigest-browser.js");
11208
- const URDNA2015Sync = __webpack_require__(/*! ./URDNA2015Sync */ "./node_modules/rdf-canonize/lib/URDNA2015Sync.js");
11209
11115
 
11210
- module.exports = class URDNA2012Sync extends URDNA2015Sync {
11211
- constructor() {
11212
- super();
11213
- this.name = 'URGNA2012';
11214
- this.createMessageDigest = () => new MessageDigest('sha1');
11215
- }
11116
+ // 5.4.2) Use the Issue Identifier algorithm, passing canonical
11117
+ // issuer and the single blank node identifier in identifier
11118
+ // list, identifier, to issue a canonical replacement identifier
11119
+ // for identifier.
11120
+ const id = idList[0];
11121
+ this.canonicalIssuer.getId(id);
11216
11122
 
11217
- // helper for modifying component during Hash First Degree Quads
11218
- modifyFirstDegreeComponent(id, component, key) {
11219
- if(component.termType !== 'BlankNode') {
11220
- return component;
11221
- }
11222
- if(key === 'graph') {
11223
- return {
11224
- termType: 'BlankNode',
11225
- value: '_:g'
11226
- };
11123
+ // Note: These steps are skipped, optimized away since the loop
11124
+ // only needs to be run once.
11125
+ // 5.4.3) Remove identifier from non-normalized identifiers.
11126
+ // 5.4.4) Remove hash from the hash to blank nodes map.
11127
+ // 5.4.5) Set simple to true.
11227
11128
  }
11228
- return {
11229
- termType: 'BlankNode',
11230
- value: (component.value === id ? '_:a' : '_:z')
11231
- };
11232
- }
11233
11129
 
11234
- // helper for getting a related predicate
11235
- getRelatedPredicate(quad) {
11236
- return quad.predicate.value;
11237
- }
11130
+ // 6) For each hash to identifier list mapping in hash to blank nodes map,
11131
+ // lexicographically-sorted by hash:
11132
+ // Note: sort optimized away, use `nonUnique`.
11133
+ for(const idList of nonUnique) {
11134
+ // 6.1) Create hash path list where each item will be a result of
11135
+ // running the Hash N-Degree Quads algorithm.
11136
+ const hashPathList = [];
11238
11137
 
11239
- // helper for creating hash to related blank nodes map
11240
- createHashToRelated(id, issuer) {
11241
- // 1) Create a hash to related blank nodes map for storing hashes that
11242
- // identify related blank nodes.
11243
- const hashToRelated = new Map();
11138
+ // 6.2) For each blank node identifier identifier in identifier list:
11139
+ for(const id of idList) {
11140
+ // 6.2.1) If a canonical identifier has already been issued for
11141
+ // identifier, continue to the next identifier.
11142
+ if(this.canonicalIssuer.hasId(id)) {
11143
+ continue;
11144
+ }
11244
11145
 
11245
- // 2) Get a reference, quads, to the list of quads in the blank node to
11246
- // quads map for the key identifier.
11247
- const quads = this.blankNodeInfo.get(id).quads;
11146
+ // 6.2.2) Create temporary issuer, an identifier issuer
11147
+ // initialized with the prefix _:b.
11148
+ const issuer = new IdentifierIssuer('_:b');
11248
11149
 
11249
- // 3) For each quad in quads:
11250
- for(const quad of quads) {
11251
- // 3.1) If the quad's subject is a blank node that does not match
11252
- // identifier, set hash to the result of the Hash Related Blank Node
11253
- // algorithm, passing the blank node identifier for subject as related,
11254
- // quad, path identifier issuer as issuer, and p as position.
11255
- let position;
11256
- let related;
11257
- if(quad.subject.termType === 'BlankNode' && quad.subject.value !== id) {
11258
- related = quad.subject.value;
11259
- position = 'p';
11260
- } else if(
11261
- quad.object.termType === 'BlankNode' && quad.object.value !== id) {
11262
- // 3.2) Otherwise, if quad's object is a blank node that does not match
11263
- // identifier, to the result of the Hash Related Blank Node algorithm,
11264
- // passing the blank node identifier for object as related, quad, path
11265
- // identifier issuer as issuer, and r as position.
11266
- related = quad.object.value;
11267
- position = 'r';
11268
- } else {
11269
- // 3.3) Otherwise, continue to the next quad.
11270
- continue;
11150
+ // 6.2.3) Use the Issue Identifier algorithm, passing temporary
11151
+ // issuer and identifier, to issue a new temporary blank node
11152
+ // identifier for identifier.
11153
+ issuer.getId(id);
11154
+
11155
+ // 6.2.4) Run the Hash N-Degree Quads algorithm, passing
11156
+ // temporary issuer, and append the result to the hash path list.
11157
+ const result = this.hashNDegreeQuads(id, issuer);
11158
+ hashPathList.push(result);
11271
11159
  }
11272
- // 3.4) Add a mapping of hash to the blank node identifier for the
11273
- // component that matched (subject or object) to hash to related blank
11274
- // nodes map, adding an entry as necessary.
11275
- const hash = this.hashRelatedBlankNode(related, quad, issuer, position);
11276
- const entries = hashToRelated.get(hash);
11277
- if(entries) {
11278
- entries.push(related);
11279
- } else {
11280
- hashToRelated.set(hash, [related]);
11160
+
11161
+ // 6.3) For each result in the hash path list,
11162
+ // lexicographically-sorted by the hash in result:
11163
+ hashPathList.sort(_stringHashCompare);
11164
+ for(const result of hashPathList) {
11165
+ // 6.3.1) For each blank node identifier, existing identifier,
11166
+ // that was issued a temporary identifier by identifier issuer
11167
+ // in result, issue a canonical identifier, in the same order,
11168
+ // using the Issue Identifier algorithm, passing canonical
11169
+ // issuer and existing identifier.
11170
+ const oldIds = result.issuer.getOldIds();
11171
+ for(const id of oldIds) {
11172
+ this.canonicalIssuer.getId(id);
11173
+ }
11281
11174
  }
11282
11175
  }
11283
11176
 
11284
- return hashToRelated;
11285
- }
11286
- };
11287
-
11288
-
11289
- /***/ }),
11177
+ /* Note: At this point all blank nodes in the set of RDF quads have been
11178
+ assigned canonical identifiers, which have been stored in the canonical
11179
+ issuer. Here each quad is updated by assigning each of its blank nodes
11180
+ its new identifier. */
11290
11181
 
11291
- /***/ "./node_modules/rdf-canonize/lib/index.js":
11292
- /*!************************************************!*\
11293
- !*** ./node_modules/rdf-canonize/lib/index.js ***!
11294
- \************************************************/
11295
- /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
11182
+ // 7) For each quad, quad, in input dataset:
11183
+ const normalized = [];
11184
+ for(const quad of this.quads) {
11185
+ // 7.1) Create a copy, quad copy, of quad and replace any existing
11186
+ // blank node identifiers using the canonical identifiers
11187
+ // previously issued by canonical issuer.
11188
+ // Note: We optimize away the copy here.
11189
+ const nQuad = NQuads.serializeQuadComponents(
11190
+ this._componentWithCanonicalId({component: quad.subject}),
11191
+ quad.predicate,
11192
+ this._componentWithCanonicalId({component: quad.object}),
11193
+ this._componentWithCanonicalId({component: quad.graph})
11194
+ );
11195
+ // 7.2) Add quad copy to the normalized dataset.
11196
+ normalized.push(nQuad);
11197
+ }
11296
11198
 
11297
- "use strict";
11298
- /**
11299
- * An implementation of the RDF Dataset Normalization specification.
11300
- * This library works in the browser and node.js.
11301
- *
11302
- * BSD 3-Clause License
11303
- * Copyright (c) 2016-2022 Digital Bazaar, Inc.
11304
- * All rights reserved.
11305
- *
11306
- * Redistribution and use in source and binary forms, with or without
11307
- * modification, are permitted provided that the following conditions are met:
11308
- *
11309
- * Redistributions of source code must retain the above copyright notice,
11310
- * this list of conditions and the following disclaimer.
11311
- *
11312
- * Redistributions in binary form must reproduce the above copyright
11313
- * notice, this list of conditions and the following disclaimer in the
11314
- * documentation and/or other materials provided with the distribution.
11315
- *
11316
- * Neither the name of the Digital Bazaar, Inc. nor the names of its
11317
- * contributors may be used to endorse or promote products derived from
11318
- * this software without specific prior written permission.
11319
- *
11320
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
11321
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
11322
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
11323
- * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
11324
- * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
11325
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
11326
- * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
11327
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
11328
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
11329
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
11330
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
11331
- */
11199
+ // sort normalized output
11200
+ normalized.sort();
11332
11201
 
11202
+ // 8) Return the normalized dataset.
11203
+ return normalized.join('');
11204
+ }
11333
11205
 
11334
- const URDNA2015 = __webpack_require__(/*! ./URDNA2015 */ "./node_modules/rdf-canonize/lib/URDNA2015.js");
11335
- const URGNA2012 = __webpack_require__(/*! ./URGNA2012 */ "./node_modules/rdf-canonize/lib/URGNA2012.js");
11336
- const URDNA2015Sync = __webpack_require__(/*! ./URDNA2015Sync */ "./node_modules/rdf-canonize/lib/URDNA2015Sync.js");
11337
- const URGNA2012Sync = __webpack_require__(/*! ./URGNA2012Sync */ "./node_modules/rdf-canonize/lib/URGNA2012Sync.js");
11206
+ // 4.6) Hash First Degree Quads
11207
+ hashFirstDegreeQuads(id) {
11208
+ // 1) Initialize nquads to an empty list. It will be used to store quads in
11209
+ // N-Quads format.
11210
+ const nquads = [];
11338
11211
 
11339
- // optional native support
11340
- let rdfCanonizeNative;
11341
- try {
11342
- rdfCanonizeNative = __webpack_require__(/*! rdf-canonize-native */ "?2b19");
11343
- } catch(e) {}
11212
+ // 2) Get the list of quads `quads` associated with the reference blank node
11213
+ // identifier in the blank node to quads map.
11214
+ const info = this.blankNodeInfo.get(id);
11215
+ const quads = info.quads;
11344
11216
 
11345
- // expose helpers
11346
- exports.NQuads = __webpack_require__(/*! ./NQuads */ "./node_modules/rdf-canonize/lib/NQuads.js");
11347
- exports.IdentifierIssuer = __webpack_require__(/*! ./IdentifierIssuer */ "./node_modules/rdf-canonize/lib/IdentifierIssuer.js");
11217
+ // 3) For each quad `quad` in `quads`:
11218
+ for(const quad of quads) {
11219
+ // 3.1) Serialize the quad in N-Quads format with the following special
11220
+ // rule:
11348
11221
 
11349
- /**
11350
- * Get or set native API.
11351
- *
11352
- * @param api the native API.
11353
- *
11354
- * @return the currently set native API.
11355
- */
11356
- exports._rdfCanonizeNative = function(api) {
11357
- if(api) {
11358
- rdfCanonizeNative = api;
11359
- }
11360
- return rdfCanonizeNative;
11361
- };
11222
+ // 3.1.1) If any component in quad is an blank node, then serialize it
11223
+ // using a special identifier as follows:
11224
+ const copy = {
11225
+ subject: null, predicate: quad.predicate, object: null, graph: null
11226
+ };
11227
+ // 3.1.2) If the blank node's existing blank node identifier matches
11228
+ // the reference blank node identifier then use the blank node
11229
+ // identifier _:a, otherwise, use the blank node identifier _:z.
11230
+ copy.subject = this.modifyFirstDegreeComponent(
11231
+ id, quad.subject, 'subject');
11232
+ copy.object = this.modifyFirstDegreeComponent(
11233
+ id, quad.object, 'object');
11234
+ copy.graph = this.modifyFirstDegreeComponent(
11235
+ id, quad.graph, 'graph');
11236
+ nquads.push(NQuads.serializeQuad(copy));
11237
+ }
11362
11238
 
11363
- /**
11364
- * Asynchronously canonizes an RDF dataset.
11365
- *
11366
- * @param {Array} dataset - The dataset to canonize.
11367
- * @param {object} options - The options to use:
11368
- * {string} algorithm - The canonicalization algorithm to use, `URDNA2015` or
11369
- * `URGNA2012`.
11370
- * {Function} [createMessageDigest] - A factory function for creating a
11371
- * `MessageDigest` interface that overrides the built-in message digest
11372
- * implementation used by the canonize algorithm; note that using a hash
11373
- * algorithm (or HMAC algorithm) that differs from the one specified by
11374
- * the canonize algorithm will result in different output.
11375
- * {boolean} [useNative=false] - Use native implementation.
11376
- * {number} [maxDeepIterations=Infinity] - The maximum number of times to run
11377
- * deep comparison algorithms (such as the N-Degree Hash Quads algorithm
11378
- * used in URDNA2015) before bailing out and throwing an error; this is a
11379
- * useful setting for preventing wasted CPU cycles or DoS when canonizing
11380
- * meaningless or potentially malicious datasets, a recommended value is
11381
- * `1`.
11382
- *
11383
- * @return a Promise that resolves to the canonicalized RDF Dataset.
11384
- */
11385
- exports.canonize = async function(dataset, options) {
11386
- // back-compat with legacy dataset
11387
- if(!Array.isArray(dataset)) {
11388
- dataset = exports.NQuads.legacyDatasetToQuads(dataset);
11389
- }
11239
+ // 4) Sort nquads in lexicographical order.
11240
+ nquads.sort();
11390
11241
 
11391
- if(options.useNative) {
11392
- if(!rdfCanonizeNative) {
11393
- throw new Error('rdf-canonize-native not available');
11394
- }
11395
- if(options.createMessageDigest) {
11396
- throw new Error(
11397
- '"createMessageDigest" cannot be used with "useNative".');
11242
+ // 5) Return the hash that results from passing the sorted, joined nquads
11243
+ // through the hash algorithm.
11244
+ const md = this.createMessageDigest();
11245
+ for(const nquad of nquads) {
11246
+ md.update(nquad);
11398
11247
  }
11399
- return new Promise((resolve, reject) =>
11400
- rdfCanonizeNative.canonize(dataset, options, (err, canonical) =>
11401
- err ? reject(err) : resolve(canonical)));
11248
+ info.hash = md.digest();
11249
+ return info.hash;
11402
11250
  }
11403
11251
 
11404
- if(options.algorithm === 'URDNA2015') {
11405
- return new URDNA2015(options).main(dataset);
11406
- }
11407
- if(options.algorithm === 'URGNA2012') {
11408
- if(options.createMessageDigest) {
11409
- throw new Error(
11410
- '"createMessageDigest" cannot be used with "URGNA2012".');
11252
+ // 4.7) Hash Related Blank Node
11253
+ hashRelatedBlankNode(related, quad, issuer, position) {
11254
+ // 1) Set the identifier to use for related, preferring first the canonical
11255
+ // identifier for related if issued, second the identifier issued by issuer
11256
+ // if issued, and last, if necessary, the result of the Hash First Degree
11257
+ // Quads algorithm, passing related.
11258
+ let id;
11259
+ if(this.canonicalIssuer.hasId(related)) {
11260
+ id = this.canonicalIssuer.getId(related);
11261
+ } else if(issuer.hasId(related)) {
11262
+ id = issuer.getId(related);
11263
+ } else {
11264
+ id = this.blankNodeInfo.get(related).hash;
11411
11265
  }
11412
- return new URGNA2012(options).main(dataset);
11413
- }
11414
- if(!('algorithm' in options)) {
11415
- throw new Error('No RDF Dataset Canonicalization algorithm specified.');
11416
- }
11417
- throw new Error(
11418
- 'Invalid RDF Dataset Canonicalization algorithm: ' + options.algorithm);
11419
- };
11420
11266
 
11421
- /**
11422
- * This method is no longer available in the public API, it is for testing
11423
- * only. It synchronously canonizes an RDF dataset and does not work in the
11424
- * browser.
11425
- *
11426
- * @param {Array} dataset - The dataset to canonize.
11427
- * @param {object} options - The options to use:
11428
- * {string} algorithm - The canonicalization algorithm to use, `URDNA2015` or
11429
- * `URGNA2012`.
11430
- * {Function} [createMessageDigest] - A factory function for creating a
11431
- * `MessageDigest` interface that overrides the built-in message digest
11432
- * implementation used by the canonize algorithm; note that using a hash
11433
- * algorithm (or HMAC algorithm) that differs from the one specified by
11434
- * the canonize algorithm will result in different output.
11435
- * {boolean} [useNative=false] - Use native implementation.
11436
- * {number} [maxDeepIterations=Infinity] - The maximum number of times to run
11437
- * deep comparison algorithms (such as the N-Degree Hash Quads algorithm
11438
- * used in URDNA2015) before bailing out and throwing an error; this is a
11439
- * useful setting for preventing wasted CPU cycles or DoS when canonizing
11440
- * meaningless or potentially malicious datasets, a recommended value is
11441
- * `1`.
11442
- *
11443
- * @return the RDF dataset in canonical form.
11444
- */
11445
- exports._canonizeSync = function(dataset, options) {
11446
- // back-compat with legacy dataset
11447
- if(!Array.isArray(dataset)) {
11448
- dataset = exports.NQuads.legacyDatasetToQuads(dataset);
11449
- }
11267
+ // 2) Initialize a string input to the value of position.
11268
+ // Note: We use a hash object instead.
11269
+ const md = this.createMessageDigest();
11270
+ md.update(position);
11450
11271
 
11451
- if(options.useNative) {
11452
- if(!rdfCanonizeNative) {
11453
- throw new Error('rdf-canonize-native not available');
11454
- }
11455
- if(options.createMessageDigest) {
11456
- throw new Error(
11457
- '"createMessageDigest" cannot be used with "useNative".');
11272
+ // 3) If position is not g, append <, the value of the predicate in quad,
11273
+ // and > to input.
11274
+ if(position !== 'g') {
11275
+ md.update(this.getRelatedPredicate(quad));
11458
11276
  }
11459
- return rdfCanonizeNative.canonizeSync(dataset, options);
11460
- }
11461
- if(options.algorithm === 'URDNA2015') {
11462
- return new URDNA2015Sync(options).main(dataset);
11277
+
11278
+ // 4) Append identifier to input.
11279
+ md.update(id);
11280
+
11281
+ // 5) Return the hash that results from passing input through the hash
11282
+ // algorithm.
11283
+ return md.digest();
11463
11284
  }
11464
- if(options.algorithm === 'URGNA2012') {
11465
- if(options.createMessageDigest) {
11285
+
11286
+ // 4.8) Hash N-Degree Quads
11287
+ hashNDegreeQuads(id, issuer) {
11288
+ const deepIterations = this.deepIterations.get(id) || 0;
11289
+ if(deepIterations > this.maxDeepIterations) {
11466
11290
  throw new Error(
11467
- '"createMessageDigest" cannot be used with "URGNA2012".');
11291
+ `Maximum deep iterations (${this.maxDeepIterations}) exceeded.`);
11468
11292
  }
11469
- return new URGNA2012Sync(options).main(dataset);
11470
- }
11471
- if(!('algorithm' in options)) {
11472
- throw new Error('No RDF Dataset Canonicalization algorithm specified.');
11473
- }
11474
- throw new Error(
11475
- 'Invalid RDF Dataset Canonicalization algorithm: ' + options.algorithm);
11476
- };
11293
+ this.deepIterations.set(id, deepIterations + 1);
11477
11294
 
11295
+ // 1) Create a hash to related blank nodes map for storing hashes that
11296
+ // identify related blank nodes.
11297
+ // Note: 2) and 3) handled within `createHashToRelated`
11298
+ const md = this.createMessageDigest();
11299
+ const hashToRelated = this.createHashToRelated(id, issuer);
11478
11300
 
11479
- /***/ }),
11301
+ // 4) Create an empty string, data to hash.
11302
+ // Note: We created a hash object `md` above instead.
11480
11303
 
11481
- /***/ "./node_modules/setimmediate/setImmediate.js":
11482
- /*!***************************************************!*\
11483
- !*** ./node_modules/setimmediate/setImmediate.js ***!
11484
- \***************************************************/
11485
- /***/ (function(__unused_webpack_module, __unused_webpack_exports, __webpack_require__) {
11304
+ // 5) For each related hash to blank node list mapping in hash to related
11305
+ // blank nodes map, sorted lexicographically by related hash:
11306
+ const hashes = [...hashToRelated.keys()].sort();
11307
+ for(const hash of hashes) {
11308
+ // 5.1) Append the related hash to the data to hash.
11309
+ md.update(hash);
11486
11310
 
11487
- (function (global, undefined) {
11488
- "use strict";
11311
+ // 5.2) Create a string chosen path.
11312
+ let chosenPath = '';
11489
11313
 
11490
- if (global.setImmediate) {
11491
- return;
11492
- }
11314
+ // 5.3) Create an unset chosen issuer variable.
11315
+ let chosenIssuer;
11493
11316
 
11494
- var nextHandle = 1; // Spec says greater than zero
11495
- var tasksByHandle = {};
11496
- var currentlyRunningATask = false;
11497
- var doc = global.document;
11498
- var registerImmediate;
11317
+ // 5.4) For each permutation of blank node list:
11318
+ const permuter = new Permuter(hashToRelated.get(hash));
11319
+ while(permuter.hasNext()) {
11320
+ const permutation = permuter.next();
11499
11321
 
11500
- function setImmediate(callback) {
11501
- // Callback can either be a function or a string
11502
- if (typeof callback !== "function") {
11503
- callback = new Function("" + callback);
11504
- }
11505
- // Copy function arguments
11506
- var args = new Array(arguments.length - 1);
11507
- for (var i = 0; i < args.length; i++) {
11508
- args[i] = arguments[i + 1];
11509
- }
11510
- // Store and register the task
11511
- var task = { callback: callback, args: args };
11512
- tasksByHandle[nextHandle] = task;
11513
- registerImmediate(nextHandle);
11514
- return nextHandle++;
11515
- }
11322
+ // 5.4.1) Create a copy of issuer, issuer copy.
11323
+ let issuerCopy = issuer.clone();
11516
11324
 
11517
- function clearImmediate(handle) {
11518
- delete tasksByHandle[handle];
11519
- }
11325
+ // 5.4.2) Create a string path.
11326
+ let path = '';
11520
11327
 
11521
- function run(task) {
11522
- var callback = task.callback;
11523
- var args = task.args;
11524
- switch (args.length) {
11525
- case 0:
11526
- callback();
11527
- break;
11528
- case 1:
11529
- callback(args[0]);
11530
- break;
11531
- case 2:
11532
- callback(args[0], args[1]);
11533
- break;
11534
- case 3:
11535
- callback(args[0], args[1], args[2]);
11536
- break;
11537
- default:
11538
- callback.apply(undefined, args);
11328
+ // 5.4.3) Create a recursion list, to store blank node identifiers
11329
+ // that must be recursively processed by this algorithm.
11330
+ const recursionList = [];
11331
+
11332
+ // 5.4.4) For each related in permutation:
11333
+ let nextPermutation = false;
11334
+ for(const related of permutation) {
11335
+ // 5.4.4.1) If a canonical identifier has been issued for
11336
+ // related, append it to path.
11337
+ if(this.canonicalIssuer.hasId(related)) {
11338
+ path += this.canonicalIssuer.getId(related);
11339
+ } else {
11340
+ // 5.4.4.2) Otherwise:
11341
+ // 5.4.4.2.1) If issuer copy has not issued an identifier for
11342
+ // related, append related to recursion list.
11343
+ if(!issuerCopy.hasId(related)) {
11344
+ recursionList.push(related);
11345
+ }
11346
+ // 5.4.4.2.2) Use the Issue Identifier algorithm, passing
11347
+ // issuer copy and related and append the result to path.
11348
+ path += issuerCopy.getId(related);
11349
+ }
11350
+
11351
+ // 5.4.4.3) If chosen path is not empty and the length of path
11352
+ // is greater than or equal to the length of chosen path and
11353
+ // path is lexicographically greater than chosen path, then
11354
+ // skip to the next permutation.
11355
+ // Note: Comparing path length to chosen path length can be optimized
11356
+ // away; only compare lexicographically.
11357
+ if(chosenPath.length !== 0 && path > chosenPath) {
11358
+ nextPermutation = true;
11539
11359
  break;
11360
+ }
11540
11361
  }
11541
- }
11542
11362
 
11543
- function runIfPresent(handle) {
11544
- // From the spec: "Wait until any invocations of this algorithm started before this one have completed."
11545
- // So if we're currently running a task, we'll need to delay this invocation.
11546
- if (currentlyRunningATask) {
11547
- // Delay by doing a setTimeout. setImmediate was tried instead, but in Firefox 7 it generated a
11548
- // "too much recursion" error.
11549
- setTimeout(runIfPresent, 0, handle);
11550
- } else {
11551
- var task = tasksByHandle[handle];
11552
- if (task) {
11553
- currentlyRunningATask = true;
11554
- try {
11555
- run(task);
11556
- } finally {
11557
- clearImmediate(handle);
11558
- currentlyRunningATask = false;
11559
- }
11560
- }
11363
+ if(nextPermutation) {
11364
+ continue;
11561
11365
  }
11562
- }
11563
11366
 
11564
- function installNextTickImplementation() {
11565
- registerImmediate = function(handle) {
11566
- process.nextTick(function () { runIfPresent(handle); });
11567
- };
11568
- }
11367
+ // 5.4.5) For each related in recursion list:
11368
+ for(const related of recursionList) {
11369
+ // 5.4.5.1) Set result to the result of recursively executing
11370
+ // the Hash N-Degree Quads algorithm, passing related for
11371
+ // identifier and issuer copy for path identifier issuer.
11372
+ const result = this.hashNDegreeQuads(related, issuerCopy);
11569
11373
 
11570
- function canUsePostMessage() {
11571
- // The test against `importScripts` prevents this implementation from being installed inside a web worker,
11572
- // where `global.postMessage` means something completely different and can't be used for this purpose.
11573
- if (global.postMessage && !global.importScripts) {
11574
- var postMessageIsAsynchronous = true;
11575
- var oldOnMessage = global.onmessage;
11576
- global.onmessage = function() {
11577
- postMessageIsAsynchronous = false;
11578
- };
11579
- global.postMessage("", "*");
11580
- global.onmessage = oldOnMessage;
11581
- return postMessageIsAsynchronous;
11582
- }
11583
- }
11374
+ // 5.4.5.2) Use the Issue Identifier algorithm, passing issuer
11375
+ // copy and related and append the result to path.
11376
+ path += issuerCopy.getId(related);
11584
11377
 
11585
- function installPostMessageImplementation() {
11586
- // Installs an event handler on `global` for the `message` event: see
11587
- // * https://developer.mozilla.org/en/DOM/window.postMessage
11588
- // * http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html#crossDocumentMessages
11378
+ // 5.4.5.3) Append <, the hash in result, and > to path.
11379
+ path += `<${result.hash}>`;
11589
11380
 
11590
- var messagePrefix = "setImmediate$" + Math.random() + "$";
11591
- var onGlobalMessage = function(event) {
11592
- if (event.source === global &&
11593
- typeof event.data === "string" &&
11594
- event.data.indexOf(messagePrefix) === 0) {
11595
- runIfPresent(+event.data.slice(messagePrefix.length));
11596
- }
11597
- };
11381
+ // 5.4.5.4) Set issuer copy to the identifier issuer in
11382
+ // result.
11383
+ issuerCopy = result.issuer;
11598
11384
 
11599
- if (global.addEventListener) {
11600
- global.addEventListener("message", onGlobalMessage, false);
11601
- } else {
11602
- global.attachEvent("onmessage", onGlobalMessage);
11385
+ // 5.4.5.5) If chosen path is not empty and the length of path
11386
+ // is greater than or equal to the length of chosen path and
11387
+ // path is lexicographically greater than chosen path, then
11388
+ // skip to the next permutation.
11389
+ // Note: Comparing path length to chosen path length can be optimized
11390
+ // away; only compare lexicographically.
11391
+ if(chosenPath.length !== 0 && path > chosenPath) {
11392
+ nextPermutation = true;
11393
+ break;
11394
+ }
11603
11395
  }
11604
11396
 
11605
- registerImmediate = function(handle) {
11606
- global.postMessage(messagePrefix + handle, "*");
11607
- };
11608
- }
11397
+ if(nextPermutation) {
11398
+ continue;
11399
+ }
11609
11400
 
11610
- function installMessageChannelImplementation() {
11611
- var channel = new MessageChannel();
11612
- channel.port1.onmessage = function(event) {
11613
- var handle = event.data;
11614
- runIfPresent(handle);
11615
- };
11401
+ // 5.4.6) If chosen path is empty or path is lexicographically
11402
+ // less than chosen path, set chosen path to path and chosen
11403
+ // issuer to issuer copy.
11404
+ if(chosenPath.length === 0 || path < chosenPath) {
11405
+ chosenPath = path;
11406
+ chosenIssuer = issuerCopy;
11407
+ }
11408
+ }
11616
11409
 
11617
- registerImmediate = function(handle) {
11618
- channel.port2.postMessage(handle);
11619
- };
11620
- }
11410
+ // 5.5) Append chosen path to data to hash.
11411
+ md.update(chosenPath);
11621
11412
 
11622
- function installReadyStateChangeImplementation() {
11623
- var html = doc.documentElement;
11624
- registerImmediate = function(handle) {
11625
- // Create a <script> element; its readystatechange event will be fired asynchronously once it is inserted
11626
- // into the document. Do so, thus queuing up the task. Remember to clean up once it's been called.
11627
- var script = doc.createElement("script");
11628
- script.onreadystatechange = function () {
11629
- runIfPresent(handle);
11630
- script.onreadystatechange = null;
11631
- html.removeChild(script);
11632
- script = null;
11633
- };
11634
- html.appendChild(script);
11635
- };
11413
+ // 5.6) Replace issuer, by reference, with chosen issuer.
11414
+ issuer = chosenIssuer;
11636
11415
  }
11637
11416
 
11638
- function installSetTimeoutImplementation() {
11639
- registerImmediate = function(handle) {
11640
- setTimeout(runIfPresent, 0, handle);
11641
- };
11417
+ // 6) Return issuer and the hash that results from passing data to hash
11418
+ // through the hash algorithm.
11419
+ return {hash: md.digest(), issuer};
11420
+ }
11421
+
11422
+ // helper for modifying component during Hash First Degree Quads
11423
+ modifyFirstDegreeComponent(id, component) {
11424
+ if(component.termType !== 'BlankNode') {
11425
+ return component;
11642
11426
  }
11427
+ /* Note: A mistake in the URDNA2015 spec that made its way into
11428
+ implementations (and therefore must stay to avoid interop breakage)
11429
+ resulted in an assigned canonical ID, if available for
11430
+ `component.value`, not being used in place of `_:a`/`_:z`, so
11431
+ we don't use it here. */
11432
+ return {
11433
+ termType: 'BlankNode',
11434
+ value: component.value === id ? '_:a' : '_:z'
11435
+ };
11436
+ }
11643
11437
 
11644
- // If supported, we should attach to the prototype of global, since that is where setTimeout et al. live.
11645
- var attachTo = Object.getPrototypeOf && Object.getPrototypeOf(global);
11646
- attachTo = attachTo && attachTo.setTimeout ? attachTo : global;
11438
+ // helper for getting a related predicate
11439
+ getRelatedPredicate(quad) {
11440
+ return `<${quad.predicate.value}>`;
11441
+ }
11647
11442
 
11648
- // Don't get fooled by e.g. browserify environments.
11649
- if ({}.toString.call(global.process) === "[object process]") {
11650
- // For Node.js before 0.9
11651
- installNextTickImplementation();
11443
+ // helper for creating hash to related blank nodes map
11444
+ createHashToRelated(id, issuer) {
11445
+ // 1) Create a hash to related blank nodes map for storing hashes that
11446
+ // identify related blank nodes.
11447
+ const hashToRelated = new Map();
11652
11448
 
11653
- } else if (canUsePostMessage()) {
11654
- // For non-IE10 modern browsers
11655
- installPostMessageImplementation();
11449
+ // 2) Get a reference, quads, to the list of quads in the blank node to
11450
+ // quads map for the key identifier.
11451
+ const quads = this.blankNodeInfo.get(id).quads;
11656
11452
 
11657
- } else if (global.MessageChannel) {
11658
- // For web workers, where supported
11659
- installMessageChannelImplementation();
11453
+ // 3) For each quad in quads:
11454
+ for(const quad of quads) {
11455
+ // 3.1) For each component in quad, if component is the subject, object,
11456
+ // or graph name and it is a blank node that is not identified by
11457
+ // identifier:
11458
+ // steps 3.1.1 and 3.1.2 occur in helpers:
11459
+ this._addRelatedBlankNodeHash({
11460
+ quad, component: quad.subject, position: 's',
11461
+ id, issuer, hashToRelated
11462
+ });
11463
+ this._addRelatedBlankNodeHash({
11464
+ quad, component: quad.object, position: 'o',
11465
+ id, issuer, hashToRelated
11466
+ });
11467
+ this._addRelatedBlankNodeHash({
11468
+ quad, component: quad.graph, position: 'g',
11469
+ id, issuer, hashToRelated
11470
+ });
11471
+ }
11660
11472
 
11661
- } else if (doc && "onreadystatechange" in doc.createElement("script")) {
11662
- // For IE 6–8
11663
- installReadyStateChangeImplementation();
11473
+ return hashToRelated;
11474
+ }
11475
+
11476
+ _hashAndTrackBlankNode({id, hashToBlankNodes}) {
11477
+ // 5.3.1) Create a hash, hash, according to the Hash First Degree
11478
+ // Quads algorithm.
11479
+ const hash = this.hashFirstDegreeQuads(id);
11664
11480
 
11481
+ // 5.3.2) Add hash and identifier to hash to blank nodes map,
11482
+ // creating a new entry if necessary.
11483
+ const idList = hashToBlankNodes.get(hash);
11484
+ if(!idList) {
11485
+ hashToBlankNodes.set(hash, [id]);
11665
11486
  } else {
11666
- // For older browsers
11667
- installSetTimeoutImplementation();
11487
+ idList.push(id);
11668
11488
  }
11489
+ }
11669
11490
 
11670
- attachTo.setImmediate = setImmediate;
11671
- attachTo.clearImmediate = clearImmediate;
11672
- }(typeof self === "undefined" ? typeof __webpack_require__.g === "undefined" ? this : __webpack_require__.g : self));
11673
-
11674
-
11675
- /***/ }),
11491
+ _addBlankNodeQuadInfo({quad, component}) {
11492
+ if(component.termType !== 'BlankNode') {
11493
+ return;
11494
+ }
11495
+ const id = component.value;
11496
+ const info = this.blankNodeInfo.get(id);
11497
+ if(info) {
11498
+ info.quads.add(quad);
11499
+ } else {
11500
+ this.blankNodeInfo.set(id, {quads: new Set([quad]), hash: null});
11501
+ }
11502
+ }
11676
11503
 
11677
- /***/ "./node_modules/yallist/iterator.js":
11678
- /*!******************************************!*\
11679
- !*** ./node_modules/yallist/iterator.js ***!
11680
- \******************************************/
11681
- /***/ ((module) => {
11504
+ _addRelatedBlankNodeHash(
11505
+ {quad, component, position, id, issuer, hashToRelated}) {
11506
+ if(!(component.termType === 'BlankNode' && component.value !== id)) {
11507
+ return;
11508
+ }
11509
+ // 3.1.1) Set hash to the result of the Hash Related Blank Node
11510
+ // algorithm, passing the blank node identifier for component as
11511
+ // related, quad, path identifier issuer as issuer, and position as
11512
+ // either s, o, or g based on whether component is a subject, object,
11513
+ // graph name, respectively.
11514
+ const related = component.value;
11515
+ const hash = this.hashRelatedBlankNode(related, quad, issuer, position);
11682
11516
 
11683
- "use strict";
11517
+ // 3.1.2) Add a mapping of hash to the blank node identifier for
11518
+ // component to hash to related blank nodes map, adding an entry as
11519
+ // necessary.
11520
+ const entries = hashToRelated.get(hash);
11521
+ if(entries) {
11522
+ entries.push(related);
11523
+ } else {
11524
+ hashToRelated.set(hash, [related]);
11525
+ }
11526
+ }
11684
11527
 
11685
- module.exports = function (Yallist) {
11686
- Yallist.prototype[Symbol.iterator] = function* () {
11687
- for (let walker = this.head; walker; walker = walker.next) {
11688
- yield walker.value
11528
+ // canonical ids for 7.1
11529
+ _componentWithCanonicalId({component}) {
11530
+ if(component.termType === 'BlankNode' &&
11531
+ !component.value.startsWith(this.canonicalIssuer.prefix)) {
11532
+ // create new BlankNode
11533
+ return {
11534
+ termType: 'BlankNode',
11535
+ value: this.canonicalIssuer.getId(component.value)
11536
+ };
11689
11537
  }
11538
+ return component;
11690
11539
  }
11540
+ };
11541
+
11542
+ function _stringHashCompare(a, b) {
11543
+ return a.hash < b.hash ? -1 : a.hash > b.hash ? 1 : 0;
11691
11544
  }
11692
11545
 
11693
11546
 
11694
11547
  /***/ }),
11695
11548
 
11696
- /***/ "./node_modules/yallist/yallist.js":
11697
- /*!*****************************************!*\
11698
- !*** ./node_modules/yallist/yallist.js ***!
11699
- \*****************************************/
11549
+ /***/ "./node_modules/rdf-canonize/lib/URGNA2012.js":
11550
+ /*!****************************************************!*\
11551
+ !*** ./node_modules/rdf-canonize/lib/URGNA2012.js ***!
11552
+ \****************************************************/
11700
11553
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
11701
11554
 
11702
11555
  "use strict";
11556
+ /*!
11557
+ * Copyright (c) 2016-2022 Digital Bazaar, Inc. All rights reserved.
11558
+ */
11703
11559
 
11704
- module.exports = Yallist
11705
11560
 
11706
- Yallist.Node = Node
11707
- Yallist.create = Yallist
11561
+ const MessageDigest = __webpack_require__(/*! ./MessageDigest */ "./node_modules/rdf-canonize/lib/MessageDigest-browser.js");
11562
+ const URDNA2015 = __webpack_require__(/*! ./URDNA2015 */ "./node_modules/rdf-canonize/lib/URDNA2015.js");
11708
11563
 
11709
- function Yallist (list) {
11710
- var self = this
11711
- if (!(self instanceof Yallist)) {
11712
- self = new Yallist()
11564
+ module.exports = class URDNA2012 extends URDNA2015 {
11565
+ constructor() {
11566
+ super();
11567
+ this.name = 'URGNA2012';
11568
+ this.createMessageDigest = () => new MessageDigest('sha1');
11713
11569
  }
11714
11570
 
11715
- self.tail = null
11716
- self.head = null
11717
- self.length = 0
11571
+ // helper for modifying component during Hash First Degree Quads
11572
+ modifyFirstDegreeComponent(id, component, key) {
11573
+ if(component.termType !== 'BlankNode') {
11574
+ return component;
11575
+ }
11576
+ if(key === 'graph') {
11577
+ return {
11578
+ termType: 'BlankNode',
11579
+ value: '_:g'
11580
+ };
11581
+ }
11582
+ return {
11583
+ termType: 'BlankNode',
11584
+ value: (component.value === id ? '_:a' : '_:z')
11585
+ };
11586
+ }
11718
11587
 
11719
- if (list && typeof list.forEach === 'function') {
11720
- list.forEach(function (item) {
11721
- self.push(item)
11722
- })
11723
- } else if (arguments.length > 0) {
11724
- for (var i = 0, l = arguments.length; i < l; i++) {
11725
- self.push(arguments[i])
11588
+ // helper for getting a related predicate
11589
+ getRelatedPredicate(quad) {
11590
+ return quad.predicate.value;
11591
+ }
11592
+
11593
+ // helper for creating hash to related blank nodes map
11594
+ async createHashToRelated(id, issuer) {
11595
+ // 1) Create a hash to related blank nodes map for storing hashes that
11596
+ // identify related blank nodes.
11597
+ const hashToRelated = new Map();
11598
+
11599
+ // 2) Get a reference, quads, to the list of quads in the blank node to
11600
+ // quads map for the key identifier.
11601
+ const quads = this.blankNodeInfo.get(id).quads;
11602
+
11603
+ // 3) For each quad in quads:
11604
+ let i = 0;
11605
+ for(const quad of quads) {
11606
+ // 3.1) If the quad's subject is a blank node that does not match
11607
+ // identifier, set hash to the result of the Hash Related Blank Node
11608
+ // algorithm, passing the blank node identifier for subject as related,
11609
+ // quad, path identifier issuer as issuer, and p as position.
11610
+ let position;
11611
+ let related;
11612
+ if(quad.subject.termType === 'BlankNode' && quad.subject.value !== id) {
11613
+ related = quad.subject.value;
11614
+ position = 'p';
11615
+ } else if(
11616
+ quad.object.termType === 'BlankNode' && quad.object.value !== id) {
11617
+ // 3.2) Otherwise, if quad's object is a blank node that does not match
11618
+ // identifier, to the result of the Hash Related Blank Node algorithm,
11619
+ // passing the blank node identifier for object as related, quad, path
11620
+ // identifier issuer as issuer, and r as position.
11621
+ related = quad.object.value;
11622
+ position = 'r';
11623
+ } else {
11624
+ // 3.3) Otherwise, continue to the next quad.
11625
+ continue;
11626
+ }
11627
+ // Note: batch hashing related blank nodes 100 at a time
11628
+ if(++i % 100 === 0) {
11629
+ await this._yield();
11630
+ }
11631
+ // 3.4) Add a mapping of hash to the blank node identifier for the
11632
+ // component that matched (subject or object) to hash to related blank
11633
+ // nodes map, adding an entry as necessary.
11634
+ const hash = await this.hashRelatedBlankNode(
11635
+ related, quad, issuer, position);
11636
+ const entries = hashToRelated.get(hash);
11637
+ if(entries) {
11638
+ entries.push(related);
11639
+ } else {
11640
+ hashToRelated.set(hash, [related]);
11641
+ }
11726
11642
  }
11727
- }
11728
-
11729
- return self
11730
- }
11731
11643
 
11732
- Yallist.prototype.removeNode = function (node) {
11733
- if (node.list !== this) {
11734
- throw new Error('removing node which does not belong to this list')
11644
+ return hashToRelated;
11735
11645
  }
11646
+ };
11736
11647
 
11737
- var next = node.next
11738
- var prev = node.prev
11739
11648
 
11740
- if (next) {
11741
- next.prev = prev
11742
- }
11649
+ /***/ }),
11743
11650
 
11744
- if (prev) {
11745
- prev.next = next
11746
- }
11651
+ /***/ "./node_modules/rdf-canonize/lib/URGNA2012Sync.js":
11652
+ /*!********************************************************!*\
11653
+ !*** ./node_modules/rdf-canonize/lib/URGNA2012Sync.js ***!
11654
+ \********************************************************/
11655
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
11747
11656
 
11748
- if (node === this.head) {
11749
- this.head = next
11750
- }
11751
- if (node === this.tail) {
11752
- this.tail = prev
11753
- }
11657
+ "use strict";
11658
+ /*!
11659
+ * Copyright (c) 2016-2021 Digital Bazaar, Inc. All rights reserved.
11660
+ */
11754
11661
 
11755
- node.list.length--
11756
- node.next = null
11757
- node.prev = null
11758
- node.list = null
11759
11662
 
11760
- return next
11761
- }
11663
+ const MessageDigest = __webpack_require__(/*! ./MessageDigest */ "./node_modules/rdf-canonize/lib/MessageDigest-browser.js");
11664
+ const URDNA2015Sync = __webpack_require__(/*! ./URDNA2015Sync */ "./node_modules/rdf-canonize/lib/URDNA2015Sync.js");
11762
11665
 
11763
- Yallist.prototype.unshiftNode = function (node) {
11764
- if (node === this.head) {
11765
- return
11666
+ module.exports = class URDNA2012Sync extends URDNA2015Sync {
11667
+ constructor() {
11668
+ super();
11669
+ this.name = 'URGNA2012';
11670
+ this.createMessageDigest = () => new MessageDigest('sha1');
11766
11671
  }
11767
11672
 
11768
- if (node.list) {
11769
- node.list.removeNode(node)
11673
+ // helper for modifying component during Hash First Degree Quads
11674
+ modifyFirstDegreeComponent(id, component, key) {
11675
+ if(component.termType !== 'BlankNode') {
11676
+ return component;
11677
+ }
11678
+ if(key === 'graph') {
11679
+ return {
11680
+ termType: 'BlankNode',
11681
+ value: '_:g'
11682
+ };
11683
+ }
11684
+ return {
11685
+ termType: 'BlankNode',
11686
+ value: (component.value === id ? '_:a' : '_:z')
11687
+ };
11770
11688
  }
11771
11689
 
11772
- var head = this.head
11773
- node.list = this
11774
- node.next = head
11775
- if (head) {
11776
- head.prev = node
11690
+ // helper for getting a related predicate
11691
+ getRelatedPredicate(quad) {
11692
+ return quad.predicate.value;
11777
11693
  }
11778
11694
 
11779
- this.head = node
11780
- if (!this.tail) {
11781
- this.tail = node
11782
- }
11783
- this.length++
11784
- }
11695
+ // helper for creating hash to related blank nodes map
11696
+ createHashToRelated(id, issuer) {
11697
+ // 1) Create a hash to related blank nodes map for storing hashes that
11698
+ // identify related blank nodes.
11699
+ const hashToRelated = new Map();
11785
11700
 
11786
- Yallist.prototype.pushNode = function (node) {
11787
- if (node === this.tail) {
11788
- return
11789
- }
11701
+ // 2) Get a reference, quads, to the list of quads in the blank node to
11702
+ // quads map for the key identifier.
11703
+ const quads = this.blankNodeInfo.get(id).quads;
11790
11704
 
11791
- if (node.list) {
11792
- node.list.removeNode(node)
11793
- }
11705
+ // 3) For each quad in quads:
11706
+ for(const quad of quads) {
11707
+ // 3.1) If the quad's subject is a blank node that does not match
11708
+ // identifier, set hash to the result of the Hash Related Blank Node
11709
+ // algorithm, passing the blank node identifier for subject as related,
11710
+ // quad, path identifier issuer as issuer, and p as position.
11711
+ let position;
11712
+ let related;
11713
+ if(quad.subject.termType === 'BlankNode' && quad.subject.value !== id) {
11714
+ related = quad.subject.value;
11715
+ position = 'p';
11716
+ } else if(
11717
+ quad.object.termType === 'BlankNode' && quad.object.value !== id) {
11718
+ // 3.2) Otherwise, if quad's object is a blank node that does not match
11719
+ // identifier, to the result of the Hash Related Blank Node algorithm,
11720
+ // passing the blank node identifier for object as related, quad, path
11721
+ // identifier issuer as issuer, and r as position.
11722
+ related = quad.object.value;
11723
+ position = 'r';
11724
+ } else {
11725
+ // 3.3) Otherwise, continue to the next quad.
11726
+ continue;
11727
+ }
11728
+ // 3.4) Add a mapping of hash to the blank node identifier for the
11729
+ // component that matched (subject or object) to hash to related blank
11730
+ // nodes map, adding an entry as necessary.
11731
+ const hash = this.hashRelatedBlankNode(related, quad, issuer, position);
11732
+ const entries = hashToRelated.get(hash);
11733
+ if(entries) {
11734
+ entries.push(related);
11735
+ } else {
11736
+ hashToRelated.set(hash, [related]);
11737
+ }
11738
+ }
11794
11739
 
11795
- var tail = this.tail
11796
- node.list = this
11797
- node.prev = tail
11798
- if (tail) {
11799
- tail.next = node
11740
+ return hashToRelated;
11800
11741
  }
11742
+ };
11801
11743
 
11802
- this.tail = node
11803
- if (!this.head) {
11804
- this.head = node
11805
- }
11806
- this.length++
11807
- }
11808
11744
 
11809
- Yallist.prototype.push = function () {
11810
- for (var i = 0, l = arguments.length; i < l; i++) {
11811
- push(this, arguments[i])
11812
- }
11813
- return this.length
11814
- }
11745
+ /***/ }),
11815
11746
 
11816
- Yallist.prototype.unshift = function () {
11817
- for (var i = 0, l = arguments.length; i < l; i++) {
11818
- unshift(this, arguments[i])
11819
- }
11820
- return this.length
11821
- }
11747
+ /***/ "./node_modules/rdf-canonize/lib/index.js":
11748
+ /*!************************************************!*\
11749
+ !*** ./node_modules/rdf-canonize/lib/index.js ***!
11750
+ \************************************************/
11751
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
11822
11752
 
11823
- Yallist.prototype.pop = function () {
11824
- if (!this.tail) {
11825
- return undefined
11826
- }
11753
+ "use strict";
11754
+ /**
11755
+ * An implementation of the RDF Dataset Normalization specification.
11756
+ * This library works in the browser and node.js.
11757
+ *
11758
+ * BSD 3-Clause License
11759
+ * Copyright (c) 2016-2022 Digital Bazaar, Inc.
11760
+ * All rights reserved.
11761
+ *
11762
+ * Redistribution and use in source and binary forms, with or without
11763
+ * modification, are permitted provided that the following conditions are met:
11764
+ *
11765
+ * Redistributions of source code must retain the above copyright notice,
11766
+ * this list of conditions and the following disclaimer.
11767
+ *
11768
+ * Redistributions in binary form must reproduce the above copyright
11769
+ * notice, this list of conditions and the following disclaimer in the
11770
+ * documentation and/or other materials provided with the distribution.
11771
+ *
11772
+ * Neither the name of the Digital Bazaar, Inc. nor the names of its
11773
+ * contributors may be used to endorse or promote products derived from
11774
+ * this software without specific prior written permission.
11775
+ *
11776
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
11777
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
11778
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
11779
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
11780
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
11781
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
11782
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
11783
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
11784
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
11785
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
11786
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
11787
+ */
11827
11788
 
11828
- var res = this.tail.value
11829
- this.tail = this.tail.prev
11830
- if (this.tail) {
11831
- this.tail.next = null
11832
- } else {
11833
- this.head = null
11834
- }
11835
- this.length--
11836
- return res
11837
- }
11838
11789
 
11839
- Yallist.prototype.shift = function () {
11840
- if (!this.head) {
11841
- return undefined
11842
- }
11790
+ const URDNA2015 = __webpack_require__(/*! ./URDNA2015 */ "./node_modules/rdf-canonize/lib/URDNA2015.js");
11791
+ const URGNA2012 = __webpack_require__(/*! ./URGNA2012 */ "./node_modules/rdf-canonize/lib/URGNA2012.js");
11792
+ const URDNA2015Sync = __webpack_require__(/*! ./URDNA2015Sync */ "./node_modules/rdf-canonize/lib/URDNA2015Sync.js");
11793
+ const URGNA2012Sync = __webpack_require__(/*! ./URGNA2012Sync */ "./node_modules/rdf-canonize/lib/URGNA2012Sync.js");
11843
11794
 
11844
- var res = this.head.value
11845
- this.head = this.head.next
11846
- if (this.head) {
11847
- this.head.prev = null
11848
- } else {
11849
- this.tail = null
11795
+ // optional native support
11796
+ let rdfCanonizeNative;
11797
+ try {
11798
+ rdfCanonizeNative = __webpack_require__(/*! rdf-canonize-native */ "?2b19");
11799
+ } catch(e) {}
11800
+
11801
+ // expose helpers
11802
+ exports.NQuads = __webpack_require__(/*! ./NQuads */ "./node_modules/rdf-canonize/lib/NQuads.js");
11803
+ exports.IdentifierIssuer = __webpack_require__(/*! ./IdentifierIssuer */ "./node_modules/rdf-canonize/lib/IdentifierIssuer.js");
11804
+
11805
+ /**
11806
+ * Get or set native API.
11807
+ *
11808
+ * @param api the native API.
11809
+ *
11810
+ * @return the currently set native API.
11811
+ */
11812
+ exports._rdfCanonizeNative = function(api) {
11813
+ if(api) {
11814
+ rdfCanonizeNative = api;
11850
11815
  }
11851
- this.length--
11852
- return res
11853
- }
11816
+ return rdfCanonizeNative;
11817
+ };
11854
11818
 
11855
- Yallist.prototype.forEach = function (fn, thisp) {
11856
- thisp = thisp || this
11857
- for (var walker = this.head, i = 0; walker !== null; i++) {
11858
- fn.call(thisp, walker.value, i, this)
11859
- walker = walker.next
11819
+ /**
11820
+ * Asynchronously canonizes an RDF dataset.
11821
+ *
11822
+ * @param {Array} dataset - The dataset to canonize.
11823
+ * @param {object} options - The options to use:
11824
+ * {string} algorithm - The canonicalization algorithm to use, `URDNA2015` or
11825
+ * `URGNA2012`.
11826
+ * {Function} [createMessageDigest] - A factory function for creating a
11827
+ * `MessageDigest` interface that overrides the built-in message digest
11828
+ * implementation used by the canonize algorithm; note that using a hash
11829
+ * algorithm (or HMAC algorithm) that differs from the one specified by
11830
+ * the canonize algorithm will result in different output.
11831
+ * {boolean} [useNative=false] - Use native implementation.
11832
+ * {number} [maxDeepIterations=Infinity] - The maximum number of times to run
11833
+ * deep comparison algorithms (such as the N-Degree Hash Quads algorithm
11834
+ * used in URDNA2015) before bailing out and throwing an error; this is a
11835
+ * useful setting for preventing wasted CPU cycles or DoS when canonizing
11836
+ * meaningless or potentially malicious datasets, a recommended value is
11837
+ * `1`.
11838
+ *
11839
+ * @return a Promise that resolves to the canonicalized RDF Dataset.
11840
+ */
11841
+ exports.canonize = async function(dataset, options) {
11842
+ // back-compat with legacy dataset
11843
+ if(!Array.isArray(dataset)) {
11844
+ dataset = exports.NQuads.legacyDatasetToQuads(dataset);
11860
11845
  }
11861
- }
11862
11846
 
11863
- Yallist.prototype.forEachReverse = function (fn, thisp) {
11864
- thisp = thisp || this
11865
- for (var walker = this.tail, i = this.length - 1; walker !== null; i--) {
11866
- fn.call(thisp, walker.value, i, this)
11867
- walker = walker.prev
11847
+ if(options.useNative) {
11848
+ if(!rdfCanonizeNative) {
11849
+ throw new Error('rdf-canonize-native not available');
11850
+ }
11851
+ if(options.createMessageDigest) {
11852
+ throw new Error(
11853
+ '"createMessageDigest" cannot be used with "useNative".');
11854
+ }
11855
+ return new Promise((resolve, reject) =>
11856
+ rdfCanonizeNative.canonize(dataset, options, (err, canonical) =>
11857
+ err ? reject(err) : resolve(canonical)));
11868
11858
  }
11869
- }
11870
11859
 
11871
- Yallist.prototype.get = function (n) {
11872
- for (var i = 0, walker = this.head; walker !== null && i < n; i++) {
11873
- // abort out of the list early if we hit a cycle
11874
- walker = walker.next
11875
- }
11876
- if (i === n && walker !== null) {
11877
- return walker.value
11860
+ if(options.algorithm === 'URDNA2015') {
11861
+ return new URDNA2015(options).main(dataset);
11878
11862
  }
11879
- }
11880
-
11881
- Yallist.prototype.getReverse = function (n) {
11882
- for (var i = 0, walker = this.tail; walker !== null && i < n; i++) {
11883
- // abort out of the list early if we hit a cycle
11884
- walker = walker.prev
11863
+ if(options.algorithm === 'URGNA2012') {
11864
+ if(options.createMessageDigest) {
11865
+ throw new Error(
11866
+ '"createMessageDigest" cannot be used with "URGNA2012".');
11867
+ }
11868
+ return new URGNA2012(options).main(dataset);
11885
11869
  }
11886
- if (i === n && walker !== null) {
11887
- return walker.value
11870
+ if(!('algorithm' in options)) {
11871
+ throw new Error('No RDF Dataset Canonicalization algorithm specified.');
11888
11872
  }
11889
- }
11873
+ throw new Error(
11874
+ 'Invalid RDF Dataset Canonicalization algorithm: ' + options.algorithm);
11875
+ };
11890
11876
 
11891
- Yallist.prototype.map = function (fn, thisp) {
11892
- thisp = thisp || this
11893
- var res = new Yallist()
11894
- for (var walker = this.head; walker !== null;) {
11895
- res.push(fn.call(thisp, walker.value, this))
11896
- walker = walker.next
11877
+ /**
11878
+ * This method is no longer available in the public API, it is for testing
11879
+ * only. It synchronously canonizes an RDF dataset and does not work in the
11880
+ * browser.
11881
+ *
11882
+ * @param {Array} dataset - The dataset to canonize.
11883
+ * @param {object} options - The options to use:
11884
+ * {string} algorithm - The canonicalization algorithm to use, `URDNA2015` or
11885
+ * `URGNA2012`.
11886
+ * {Function} [createMessageDigest] - A factory function for creating a
11887
+ * `MessageDigest` interface that overrides the built-in message digest
11888
+ * implementation used by the canonize algorithm; note that using a hash
11889
+ * algorithm (or HMAC algorithm) that differs from the one specified by
11890
+ * the canonize algorithm will result in different output.
11891
+ * {boolean} [useNative=false] - Use native implementation.
11892
+ * {number} [maxDeepIterations=Infinity] - The maximum number of times to run
11893
+ * deep comparison algorithms (such as the N-Degree Hash Quads algorithm
11894
+ * used in URDNA2015) before bailing out and throwing an error; this is a
11895
+ * useful setting for preventing wasted CPU cycles or DoS when canonizing
11896
+ * meaningless or potentially malicious datasets, a recommended value is
11897
+ * `1`.
11898
+ *
11899
+ * @return the RDF dataset in canonical form.
11900
+ */
11901
+ exports._canonizeSync = function(dataset, options) {
11902
+ // back-compat with legacy dataset
11903
+ if(!Array.isArray(dataset)) {
11904
+ dataset = exports.NQuads.legacyDatasetToQuads(dataset);
11897
11905
  }
11898
- return res
11899
- }
11900
11906
 
11901
- Yallist.prototype.mapReverse = function (fn, thisp) {
11902
- thisp = thisp || this
11903
- var res = new Yallist()
11904
- for (var walker = this.tail; walker !== null;) {
11905
- res.push(fn.call(thisp, walker.value, this))
11906
- walker = walker.prev
11907
+ if(options.useNative) {
11908
+ if(!rdfCanonizeNative) {
11909
+ throw new Error('rdf-canonize-native not available');
11910
+ }
11911
+ if(options.createMessageDigest) {
11912
+ throw new Error(
11913
+ '"createMessageDigest" cannot be used with "useNative".');
11914
+ }
11915
+ return rdfCanonizeNative.canonizeSync(dataset, options);
11907
11916
  }
11908
- return res
11909
- }
11910
-
11911
- Yallist.prototype.reduce = function (fn, initial) {
11912
- var acc
11913
- var walker = this.head
11914
- if (arguments.length > 1) {
11915
- acc = initial
11916
- } else if (this.head) {
11917
- walker = this.head.next
11918
- acc = this.head.value
11919
- } else {
11920
- throw new TypeError('Reduce of empty list with no initial value')
11917
+ if(options.algorithm === 'URDNA2015') {
11918
+ return new URDNA2015Sync(options).main(dataset);
11921
11919
  }
11922
-
11923
- for (var i = 0; walker !== null; i++) {
11924
- acc = fn(acc, walker.value, i)
11925
- walker = walker.next
11920
+ if(options.algorithm === 'URGNA2012') {
11921
+ if(options.createMessageDigest) {
11922
+ throw new Error(
11923
+ '"createMessageDigest" cannot be used with "URGNA2012".');
11924
+ }
11925
+ return new URGNA2012Sync(options).main(dataset);
11926
+ }
11927
+ if(!('algorithm' in options)) {
11928
+ throw new Error('No RDF Dataset Canonicalization algorithm specified.');
11926
11929
  }
11930
+ throw new Error(
11931
+ 'Invalid RDF Dataset Canonicalization algorithm: ' + options.algorithm);
11932
+ };
11927
11933
 
11928
- return acc
11929
- }
11930
11934
 
11931
- Yallist.prototype.reduceReverse = function (fn, initial) {
11932
- var acc
11933
- var walker = this.tail
11934
- if (arguments.length > 1) {
11935
- acc = initial
11936
- } else if (this.tail) {
11937
- walker = this.tail.prev
11938
- acc = this.tail.value
11939
- } else {
11940
- throw new TypeError('Reduce of empty list with no initial value')
11941
- }
11935
+ /***/ }),
11942
11936
 
11943
- for (var i = this.length - 1; walker !== null; i--) {
11944
- acc = fn(acc, walker.value, i)
11945
- walker = walker.prev
11946
- }
11937
+ /***/ "./node_modules/setimmediate/setImmediate.js":
11938
+ /*!***************************************************!*\
11939
+ !*** ./node_modules/setimmediate/setImmediate.js ***!
11940
+ \***************************************************/
11941
+ /***/ (function(__unused_webpack_module, __unused_webpack_exports, __webpack_require__) {
11947
11942
 
11948
- return acc
11949
- }
11943
+ (function (global, undefined) {
11944
+ "use strict";
11950
11945
 
11951
- Yallist.prototype.toArray = function () {
11952
- var arr = new Array(this.length)
11953
- for (var i = 0, walker = this.head; walker !== null; i++) {
11954
- arr[i] = walker.value
11955
- walker = walker.next
11956
- }
11957
- return arr
11958
- }
11946
+ if (global.setImmediate) {
11947
+ return;
11948
+ }
11959
11949
 
11960
- Yallist.prototype.toArrayReverse = function () {
11961
- var arr = new Array(this.length)
11962
- for (var i = 0, walker = this.tail; walker !== null; i++) {
11963
- arr[i] = walker.value
11964
- walker = walker.prev
11965
- }
11966
- return arr
11967
- }
11950
+ var nextHandle = 1; // Spec says greater than zero
11951
+ var tasksByHandle = {};
11952
+ var currentlyRunningATask = false;
11953
+ var doc = global.document;
11954
+ var registerImmediate;
11968
11955
 
11969
- Yallist.prototype.slice = function (from, to) {
11970
- to = to || this.length
11971
- if (to < 0) {
11972
- to += this.length
11973
- }
11974
- from = from || 0
11975
- if (from < 0) {
11976
- from += this.length
11977
- }
11978
- var ret = new Yallist()
11979
- if (to < from || to < 0) {
11980
- return ret
11981
- }
11982
- if (from < 0) {
11983
- from = 0
11984
- }
11985
- if (to > this.length) {
11986
- to = this.length
11987
- }
11988
- for (var i = 0, walker = this.head; walker !== null && i < from; i++) {
11989
- walker = walker.next
11990
- }
11991
- for (; walker !== null && i < to; i++, walker = walker.next) {
11992
- ret.push(walker.value)
11993
- }
11994
- return ret
11995
- }
11956
+ function setImmediate(callback) {
11957
+ // Callback can either be a function or a string
11958
+ if (typeof callback !== "function") {
11959
+ callback = new Function("" + callback);
11960
+ }
11961
+ // Copy function arguments
11962
+ var args = new Array(arguments.length - 1);
11963
+ for (var i = 0; i < args.length; i++) {
11964
+ args[i] = arguments[i + 1];
11965
+ }
11966
+ // Store and register the task
11967
+ var task = { callback: callback, args: args };
11968
+ tasksByHandle[nextHandle] = task;
11969
+ registerImmediate(nextHandle);
11970
+ return nextHandle++;
11971
+ }
11996
11972
 
11997
- Yallist.prototype.sliceReverse = function (from, to) {
11998
- to = to || this.length
11999
- if (to < 0) {
12000
- to += this.length
12001
- }
12002
- from = from || 0
12003
- if (from < 0) {
12004
- from += this.length
12005
- }
12006
- var ret = new Yallist()
12007
- if (to < from || to < 0) {
12008
- return ret
12009
- }
12010
- if (from < 0) {
12011
- from = 0
12012
- }
12013
- if (to > this.length) {
12014
- to = this.length
12015
- }
12016
- for (var i = this.length, walker = this.tail; walker !== null && i > to; i--) {
12017
- walker = walker.prev
12018
- }
12019
- for (; walker !== null && i > from; i--, walker = walker.prev) {
12020
- ret.push(walker.value)
12021
- }
12022
- return ret
12023
- }
11973
+ function clearImmediate(handle) {
11974
+ delete tasksByHandle[handle];
11975
+ }
12024
11976
 
12025
- Yallist.prototype.splice = function (start, deleteCount, ...nodes) {
12026
- if (start > this.length) {
12027
- start = this.length - 1
12028
- }
12029
- if (start < 0) {
12030
- start = this.length + start;
12031
- }
11977
+ function run(task) {
11978
+ var callback = task.callback;
11979
+ var args = task.args;
11980
+ switch (args.length) {
11981
+ case 0:
11982
+ callback();
11983
+ break;
11984
+ case 1:
11985
+ callback(args[0]);
11986
+ break;
11987
+ case 2:
11988
+ callback(args[0], args[1]);
11989
+ break;
11990
+ case 3:
11991
+ callback(args[0], args[1], args[2]);
11992
+ break;
11993
+ default:
11994
+ callback.apply(undefined, args);
11995
+ break;
11996
+ }
11997
+ }
12032
11998
 
12033
- for (var i = 0, walker = this.head; walker !== null && i < start; i++) {
12034
- walker = walker.next
12035
- }
11999
+ function runIfPresent(handle) {
12000
+ // From the spec: "Wait until any invocations of this algorithm started before this one have completed."
12001
+ // So if we're currently running a task, we'll need to delay this invocation.
12002
+ if (currentlyRunningATask) {
12003
+ // Delay by doing a setTimeout. setImmediate was tried instead, but in Firefox 7 it generated a
12004
+ // "too much recursion" error.
12005
+ setTimeout(runIfPresent, 0, handle);
12006
+ } else {
12007
+ var task = tasksByHandle[handle];
12008
+ if (task) {
12009
+ currentlyRunningATask = true;
12010
+ try {
12011
+ run(task);
12012
+ } finally {
12013
+ clearImmediate(handle);
12014
+ currentlyRunningATask = false;
12015
+ }
12016
+ }
12017
+ }
12018
+ }
12036
12019
 
12037
- var ret = []
12038
- for (var i = 0; walker && i < deleteCount; i++) {
12039
- ret.push(walker.value)
12040
- walker = this.removeNode(walker)
12041
- }
12042
- if (walker === null) {
12043
- walker = this.tail
12044
- }
12020
+ function installNextTickImplementation() {
12021
+ registerImmediate = function(handle) {
12022
+ process.nextTick(function () { runIfPresent(handle); });
12023
+ };
12024
+ }
12045
12025
 
12046
- if (walker !== this.head && walker !== this.tail) {
12047
- walker = walker.prev
12048
- }
12026
+ function canUsePostMessage() {
12027
+ // The test against `importScripts` prevents this implementation from being installed inside a web worker,
12028
+ // where `global.postMessage` means something completely different and can't be used for this purpose.
12029
+ if (global.postMessage && !global.importScripts) {
12030
+ var postMessageIsAsynchronous = true;
12031
+ var oldOnMessage = global.onmessage;
12032
+ global.onmessage = function() {
12033
+ postMessageIsAsynchronous = false;
12034
+ };
12035
+ global.postMessage("", "*");
12036
+ global.onmessage = oldOnMessage;
12037
+ return postMessageIsAsynchronous;
12038
+ }
12039
+ }
12049
12040
 
12050
- for (var i = 0; i < nodes.length; i++) {
12051
- walker = insert(this, walker, nodes[i])
12052
- }
12053
- return ret;
12054
- }
12041
+ function installPostMessageImplementation() {
12042
+ // Installs an event handler on `global` for the `message` event: see
12043
+ // * https://developer.mozilla.org/en/DOM/window.postMessage
12044
+ // * http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html#crossDocumentMessages
12055
12045
 
12056
- Yallist.prototype.reverse = function () {
12057
- var head = this.head
12058
- var tail = this.tail
12059
- for (var walker = head; walker !== null; walker = walker.prev) {
12060
- var p = walker.prev
12061
- walker.prev = walker.next
12062
- walker.next = p
12063
- }
12064
- this.head = tail
12065
- this.tail = head
12066
- return this
12067
- }
12046
+ var messagePrefix = "setImmediate$" + Math.random() + "$";
12047
+ var onGlobalMessage = function(event) {
12048
+ if (event.source === global &&
12049
+ typeof event.data === "string" &&
12050
+ event.data.indexOf(messagePrefix) === 0) {
12051
+ runIfPresent(+event.data.slice(messagePrefix.length));
12052
+ }
12053
+ };
12068
12054
 
12069
- function insert (self, node, value) {
12070
- var inserted = node === self.head ?
12071
- new Node(value, null, node, self) :
12072
- new Node(value, node, node.next, self)
12055
+ if (global.addEventListener) {
12056
+ global.addEventListener("message", onGlobalMessage, false);
12057
+ } else {
12058
+ global.attachEvent("onmessage", onGlobalMessage);
12059
+ }
12073
12060
 
12074
- if (inserted.next === null) {
12075
- self.tail = inserted
12076
- }
12077
- if (inserted.prev === null) {
12078
- self.head = inserted
12079
- }
12061
+ registerImmediate = function(handle) {
12062
+ global.postMessage(messagePrefix + handle, "*");
12063
+ };
12064
+ }
12080
12065
 
12081
- self.length++
12066
+ function installMessageChannelImplementation() {
12067
+ var channel = new MessageChannel();
12068
+ channel.port1.onmessage = function(event) {
12069
+ var handle = event.data;
12070
+ runIfPresent(handle);
12071
+ };
12082
12072
 
12083
- return inserted
12084
- }
12073
+ registerImmediate = function(handle) {
12074
+ channel.port2.postMessage(handle);
12075
+ };
12076
+ }
12085
12077
 
12086
- function push (self, item) {
12087
- self.tail = new Node(item, self.tail, null, self)
12088
- if (!self.head) {
12089
- self.head = self.tail
12090
- }
12091
- self.length++
12092
- }
12078
+ function installReadyStateChangeImplementation() {
12079
+ var html = doc.documentElement;
12080
+ registerImmediate = function(handle) {
12081
+ // Create a <script> element; its readystatechange event will be fired asynchronously once it is inserted
12082
+ // into the document. Do so, thus queuing up the task. Remember to clean up once it's been called.
12083
+ var script = doc.createElement("script");
12084
+ script.onreadystatechange = function () {
12085
+ runIfPresent(handle);
12086
+ script.onreadystatechange = null;
12087
+ html.removeChild(script);
12088
+ script = null;
12089
+ };
12090
+ html.appendChild(script);
12091
+ };
12092
+ }
12093
12093
 
12094
- function unshift (self, item) {
12095
- self.head = new Node(item, null, self.head, self)
12096
- if (!self.tail) {
12097
- self.tail = self.head
12098
- }
12099
- self.length++
12100
- }
12094
+ function installSetTimeoutImplementation() {
12095
+ registerImmediate = function(handle) {
12096
+ setTimeout(runIfPresent, 0, handle);
12097
+ };
12098
+ }
12101
12099
 
12102
- function Node (value, prev, next, list) {
12103
- if (!(this instanceof Node)) {
12104
- return new Node(value, prev, next, list)
12105
- }
12100
+ // If supported, we should attach to the prototype of global, since that is where setTimeout et al. live.
12101
+ var attachTo = Object.getPrototypeOf && Object.getPrototypeOf(global);
12102
+ attachTo = attachTo && attachTo.setTimeout ? attachTo : global;
12106
12103
 
12107
- this.list = list
12108
- this.value = value
12104
+ // Don't get fooled by e.g. browserify environments.
12105
+ if ({}.toString.call(global.process) === "[object process]") {
12106
+ // For Node.js before 0.9
12107
+ installNextTickImplementation();
12109
12108
 
12110
- if (prev) {
12111
- prev.next = this
12112
- this.prev = prev
12113
- } else {
12114
- this.prev = null
12115
- }
12109
+ } else if (canUsePostMessage()) {
12110
+ // For non-IE10 modern browsers
12111
+ installPostMessageImplementation();
12116
12112
 
12117
- if (next) {
12118
- next.prev = this
12119
- this.next = next
12120
- } else {
12121
- this.next = null
12122
- }
12123
- }
12113
+ } else if (global.MessageChannel) {
12114
+ // For web workers, where supported
12115
+ installMessageChannelImplementation();
12124
12116
 
12125
- try {
12126
- // add if support for Symbol.iterator is present
12127
- __webpack_require__(/*! ./iterator.js */ "./node_modules/yallist/iterator.js")(Yallist)
12128
- } catch (er) {}
12117
+ } else if (doc && "onreadystatechange" in doc.createElement("script")) {
12118
+ // For IE 6–8
12119
+ installReadyStateChangeImplementation();
12120
+
12121
+ } else {
12122
+ // For older browsers
12123
+ installSetTimeoutImplementation();
12124
+ }
12125
+
12126
+ attachTo.setImmediate = setImmediate;
12127
+ attachTo.clearImmediate = clearImmediate;
12128
+ }(typeof self === "undefined" ? typeof __webpack_require__.g === "undefined" ? this : __webpack_require__.g : self));
12129
12129
 
12130
12130
 
12131
12131
  /***/ })