n3 2.11.5 → 2.11.7

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.
package/lib/N3Lexer.js CHANGED
@@ -4,7 +4,6 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
- var _buffer = require("buffer");
8
7
  var _IRIs = _interopRequireDefault(require("./IRIs"));
9
8
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
10
9
  // **N3Lexer** tokenizes N3 documents.
@@ -94,6 +93,9 @@ function isSeparatorCode(code) {
94
93
  return code === SPACE || code === TAB || code === LF || code === CR || code === HASH;
95
94
  }
96
95
 
96
+ // Unfinished input in a stream up to this length is tokenized again with every chunk
97
+ const MIN_RESCAN_LENGTH = 1024;
98
+
97
99
  // ## Constructor
98
100
  class N3Lexer {
99
101
  constructor(options) {
@@ -721,31 +723,39 @@ class N3Lexer {
721
723
  }
722
724
  // Otherwise, the input must be a stream
723
725
  else {
724
- this._pendingBuffer = null;
726
+ let decoder,
727
+ retryLength = 0;
725
728
  if (typeof input.setEncoding === 'function') input.setEncoding('utf8');
726
729
  // Adds the data chunk to the buffer and parses as far as possible
727
730
  input.on('data', data => {
728
731
  if (this._tokenization === tokenization && this._input !== null && data.length !== 0) {
729
- // Prepend any previous pending writes
730
- if (this._pendingBuffer) {
731
- data = _buffer.Buffer.concat([this._pendingBuffer, data]);
732
- this._pendingBuffer = null;
733
- }
734
- // Hold if the buffer ends in an incomplete unicode sequence
735
- if (data[data.length - 1] & 0x80) {
736
- this._pendingBuffer = data;
732
+ // Decode bytes, keeping an incomplete trailing character for the next chunk
733
+ if (typeof data !== 'string') {
734
+ decoder = decoder || new TextDecoder('utf-8', {
735
+ ignoreBOM: true
736
+ });
737
+ if (!(data = decoder.decode(data, {
738
+ stream: true
739
+ }))) return;
737
740
  }
738
- // Otherwise, tokenize as far as possible
739
- else {
740
- // Only read a BOM at the start
741
- if (typeof this._input === 'undefined') this._input = this._readStartingBom(typeof data === 'string' ? data : data.toString());else this._input += data;
741
+ // Only read a BOM at the start
742
+ if (typeof this._input === 'undefined') this._input = this._readStartingBom(data);else this._input += data;
743
+ // Tokenize as far as possible. When a previous attempt left a long unfinished token,
744
+ // wait until the buffered input has doubled, so the token is not rescanned for every chunk.
745
+ if (this._input.length >= retryLength) {
742
746
  this._tokenizeToEnd(callback, false);
747
+ retryLength = this._input !== null && this._input.length > MIN_RESCAN_LENGTH ? 2 * this._input.length : 0;
743
748
  }
744
749
  }
745
750
  });
746
751
  // Parses until the end
747
752
  input.on('end', () => {
748
- if (this._tokenization === tokenization && typeof this._input === 'string') this._tokenizeToEnd(callback, true);
753
+ if (this._tokenization === tokenization && this._input !== null) {
754
+ // Decode any incomplete character left at the end
755
+ const rest = decoder ? decoder.decode() : '';
756
+ if (rest) this._input = typeof this._input === 'string' ? this._input + rest : rest;
757
+ if (typeof this._input === 'string') this._tokenizeToEnd(callback, true);
758
+ }
749
759
  });
750
760
  input.on('error', error => {
751
761
  if (this._tokenization === tokenization) callback(error);
package/lib/N3Parser.js CHANGED
@@ -93,9 +93,13 @@ class N3Parser {
93
93
  const queryPos = baseIRI.indexOf('?');
94
94
  const path = queryPos < 0 ? baseIRI : baseIRI.substr(0, queryPos);
95
95
  this._basePath = baseIRI.indexOf('/') < 0 ? baseIRI : path.substr(0, path.lastIndexOf('/') + 1);
96
- baseIRI = baseIRI.match(/^(?:([a-z][a-z0-9+.-]*:))?(?:\/\/[^\/]*)?/i);
96
+ const base = baseIRI;
97
+ baseIRI = baseIRI.match(/^(?:([a-z][a-z0-9+.-]*:))?(\/\/[^\/?#]*)?/i);
97
98
  this._baseRoot = baseIRI[0];
98
99
  this._baseScheme = baseIRI[1];
100
+ // If the base has an authority but an empty path,
101
+ // relative IRIs merge under the path '/' (RFC 3986 §5.2.3)
102
+ if (baseIRI[2] !== undefined && (base.length === this._baseRoot.length || base[this._baseRoot.length] === '?')) this._basePath = `${this._baseRoot}/`;
99
103
  }
100
104
  }
101
105
 
@@ -1430,8 +1434,11 @@ class N3Parser {
1430
1434
  }
1431
1435
  // Resolve root-relative IRIs at the root of the base IRI
1432
1436
  case '/':
1433
- // Resolve scheme-relative IRIs to the scheme
1434
- return (iri[1] === '/' ? this._baseScheme : this._baseRoot) + this._removeDotSegments(iri);
1437
+ // Resolve scheme-relative IRIs to the scheme,
1438
+ // keeping the reference's authority intact (RFC 3986 §5.2.4)
1439
+ if (iri[1] !== '/') return this._baseRoot + this._removeDotSegments(iri);
1440
+ // Without a base scheme, a leading ':' marks where the authority starts
1441
+ return this._baseScheme ? this._removeDotSegments(this._baseScheme + iri) : this._removeDotSegments(`:${iri}`).substr(1);
1435
1442
  // Resolve all other IRIs at the base IRI's path
1436
1443
  default:
1437
1444
  // Relative IRIs cannot contain a colon in the first path segment
@@ -1458,8 +1465,8 @@ class N3Parser {
1458
1465
  if (pathStart < 0) {
1459
1466
  // Skip two slashes before the authority
1460
1467
  if (iri[++i] === '/' && iri[++i] === '/')
1461
- // Skip to slash after the authority
1462
- while ((pathStart = i + 1) < length && iri[pathStart] !== '/') i = pathStart;
1468
+ // Skip to the end of the authority
1469
+ while ((pathStart = i + 1) < length && iri[pathStart] !== '/' && iri[pathStart] !== '?' && iri[pathStart] !== '#') i = pathStart;
1463
1470
  }
1464
1471
  break;
1465
1472
  // Don't modify a query string or fragment
package/lib/N3Store.js CHANGED
@@ -116,6 +116,31 @@ function difference(s1, s2, depth = 4) {
116
116
  return target;
117
117
  }
118
118
 
119
+ // Returns the key of a term in the entity index.
120
+ // Keys mark the term type by their first character, so the IRI of a named node
121
+ // that starts with such a marker (as relative IRIs can) is wrapped in < and >.
122
+ const markedIRI = /^[?_"[.<]/;
123
+ function entityKey(term) {
124
+ // Strings are term ids, which only need wrapping when they are IRIs starting with <
125
+ if (typeof term === 'string') return term.charCodeAt(0) !== 0x3C || term === '<>' ? term : `<${term}>`;
126
+ // IDs of IRIs usually start with a lowercase scheme letter, which never marks a term type
127
+ const id = (0, _N3DataFactory.termToId)(term);
128
+ if (id.charCodeAt(0) >= 0x61 || !term) return id;
129
+ // Keys of quoted triples are built from the keys of their components
130
+ if (term.termType === 'Quad') return JSON.stringify(quadKeyParts(term));
131
+ return term.termType !== 'NamedNode' || !markedIRI.test(term.value) ? id : `<${term.value}>`;
132
+ }
133
+
134
+ // Returns the keys of the components of a quad, nested like the parts of its internal id
135
+ function quadKeyParts(quad) {
136
+ const parts = [nestedKey(quad.subject), nestedKey(quad.predicate), nestedKey(quad.object)];
137
+ if (quad.graph && !(0, _N3Util.isDefaultGraph)(quad.graph)) parts.push(nestedKey(quad.graph));
138
+ return parts;
139
+ }
140
+ function nestedKey(term) {
141
+ return term.termType === 'Quad' ? quadKeyParts(term) : entityKey(term);
142
+ }
143
+
119
144
  // ## Constructor
120
145
  class N3EntityIndex {
121
146
  constructor(options = {}) {
@@ -132,6 +157,9 @@ class N3EntityIndex {
132
157
  this._factory = options.factory || _N3DataFactory.default;
133
158
  }
134
159
  _termFromId(id) {
160
+ // A key in < and > is a named node
161
+ if (id[0] === '<') return this._factory.namedNode(id.substring(1, id.length - 1));
162
+ // A key starting with . is a quoted triple
135
163
  if (id[0] === '.') {
136
164
  const entities = this._entities;
137
165
  const terms = id.split('.');
@@ -148,12 +176,25 @@ class N3EntityIndex {
148
176
  let g;
149
177
  return s && p && o && ((0, _N3Util.isDefaultGraph)(term.graph) || (g = this._termToNumericId(term.graph))) && this._ids[g ? `.${s}.${p}.${o}.${g}` : `.${s}.${p}.${o}`];
150
178
  }
151
- return this._ids[(0, _N3DataFactory.termToId)(term)];
179
+ return typeof term === 'string' ? this._stringToNumericId(term) : this._ids[entityKey(term)];
180
+ }
181
+
182
+ // Returns the numeric id of a term given as a string id
183
+ _stringToNumericId(term) {
184
+ // The string is the key unless it is an IRI starting with <. Read the first character
185
+ // from the stored key after a match, which is cheaper than from a concatenated string.
186
+ const id = this._ids[term];
187
+ if (id ? this._entities[id].charCodeAt(0) !== 0x3C : term.charCodeAt(0) !== 0x3C) return id;
188
+ return term === '<>' ? id : this._ids[`<${term}>`];
152
189
  }
153
190
  _termToNewNumericId(term) {
191
+ if (typeof term === 'string') return this._stringToNumericId(term) || this._addEntity(entityKey(term));
154
192
  // This assumes that no graph term is present - we may wish to error if there is one
155
- const str = term && term.termType === 'Quad' ? `.${this._termToNewNumericId(term.subject)}.${this._termToNewNumericId(term.predicate)}.${this._termToNewNumericId(term.object)}${(0, _N3Util.isDefaultGraph)(term.graph) ? '' : `.${this._termToNewNumericId(term.graph)}`}` : (0, _N3DataFactory.termToId)(term);
156
- return this._ids[str] || (this._ids[this._entities[++this._id] = str] = this._id);
193
+ const str = term && term.termType === 'Quad' ? `.${this._termToNewNumericId(term.subject)}.${this._termToNewNumericId(term.predicate)}.${this._termToNewNumericId(term.object)}${(0, _N3Util.isDefaultGraph)(term.graph) ? '' : `.${this._termToNewNumericId(term.graph)}`}` : entityKey(term);
194
+ return this._ids[str] || this._addEntity(str);
195
+ }
196
+ _addEntity(key) {
197
+ return this._ids[this._entities[++this._id] = key] = this._id;
157
198
  }
158
199
  createBlankNode(suggestedName) {
159
200
  let name, index;
@@ -1305,7 +1346,7 @@ function intersectMatchPatterns(left, right) {
1305
1346
  for (let i = 0; i < 4; i++) {
1306
1347
  const leftTerm = left[i],
1307
1348
  rightTerm = right[i];
1308
- if (leftTerm === null || leftTerm === undefined) result[i] = rightTerm;else if (rightTerm === null || rightTerm === undefined || (0, _N3DataFactory.termToId)(leftTerm) === (0, _N3DataFactory.termToId)(rightTerm)) result[i] = leftTerm;else return false;
1349
+ if (leftTerm === null || leftTerm === undefined) result[i] = rightTerm;else if (rightTerm === null || rightTerm === undefined || entityKey(leftTerm) === entityKey(rightTerm)) result[i] = leftTerm;else return false;
1309
1350
  }
1310
1351
  return result;
1311
1352
  }
@@ -1368,7 +1409,7 @@ class DatasetCoreAndReadableStream extends _readableStream.Readable {
1368
1409
  object,
1369
1410
  graph
1370
1411
  } = this;
1371
- return !this._matchesNothing && (subject === null || subject === undefined || (0, _N3DataFactory.termToId)(subject) === (0, _N3DataFactory.termToId)(quad.subject)) && (predicate === null || predicate === undefined || (0, _N3DataFactory.termToId)(predicate) === (0, _N3DataFactory.termToId)(quad.predicate)) && (object === null || object === undefined || (0, _N3DataFactory.termToId)(object) === (0, _N3DataFactory.termToId)(quad.object)) && (graph === null || graph === undefined || (0, _N3DataFactory.termToId)(graph) === (0, _N3DataFactory.termToId)(quad.graph));
1412
+ return !this._matchesNothing && (subject === null || subject === undefined || entityKey(subject) === entityKey(quad.subject)) && (predicate === null || predicate === undefined || entityKey(predicate) === entityKey(quad.predicate)) && (object === null || object === undefined || entityKey(object) === entityKey(quad.object)) && (graph === null || graph === undefined || entityKey(graph) === entityKey(quad.graph));
1372
1413
  }
1373
1414
 
1374
1415
  // ### `_assertMatchesPattern` rejects a Quad outside this view.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n3",
3
- "version": "2.11.5",
3
+ "version": "2.11.7",
4
4
  "description": "Lightning fast, asynchronous, streaming Turtle / N3 / RDF library.",
5
5
  "author": "Ruben Verborgh <ruben.verborgh@gmail.com>",
6
6
  "keywords": [
package/src/N3Lexer.js CHANGED
@@ -1,5 +1,4 @@
1
1
  // **N3Lexer** tokenizes N3 documents.
2
- import { Buffer } from 'buffer';
3
2
  import namespaces from './IRIs';
4
3
 
5
4
  const { xsd } = namespaces;
@@ -59,6 +58,9 @@ function isSeparatorCode(code) {
59
58
  return code === SPACE || code === TAB || code === LF || code === CR || code === HASH;
60
59
  }
61
60
 
61
+ // Unfinished input in a stream up to this length is tokenized again with every chunk
62
+ const MIN_RESCAN_LENGTH = 1024;
63
+
62
64
  // ## Constructor
63
65
  export default class N3Lexer {
64
66
  constructor(options) {
@@ -747,36 +749,42 @@ export default class N3Lexer {
747
749
  }
748
750
  // Otherwise, the input must be a stream
749
751
  else {
750
- this._pendingBuffer = null;
752
+ let decoder, retryLength = 0;
751
753
  if (typeof input.setEncoding === 'function')
752
754
  input.setEncoding('utf8');
753
755
  // Adds the data chunk to the buffer and parses as far as possible
754
756
  input.on('data', data => {
755
757
  if (this._tokenization === tokenization && this._input !== null && data.length !== 0) {
756
- // Prepend any previous pending writes
757
- if (this._pendingBuffer) {
758
- data = Buffer.concat([this._pendingBuffer, data]);
759
- this._pendingBuffer = null;
760
- }
761
- // Hold if the buffer ends in an incomplete unicode sequence
762
- if (data[data.length - 1] & 0x80) {
763
- this._pendingBuffer = data;
758
+ // Decode bytes, keeping an incomplete trailing character for the next chunk
759
+ if (typeof data !== 'string') {
760
+ decoder = decoder || new TextDecoder('utf-8', { ignoreBOM: true });
761
+ if (!(data = decoder.decode(data, { stream: true })))
762
+ return;
764
763
  }
765
- // Otherwise, tokenize as far as possible
766
- else {
767
- // Only read a BOM at the start
768
- if (typeof this._input === 'undefined')
769
- this._input = this._readStartingBom(typeof data === 'string' ? data : data.toString());
770
- else
771
- this._input += data;
764
+ // Only read a BOM at the start
765
+ if (typeof this._input === 'undefined')
766
+ this._input = this._readStartingBom(data);
767
+ else
768
+ this._input += data;
769
+ // Tokenize as far as possible. When a previous attempt left a long unfinished token,
770
+ // wait until the buffered input has doubled, so the token is not rescanned for every chunk.
771
+ if (this._input.length >= retryLength) {
772
772
  this._tokenizeToEnd(callback, false);
773
+ retryLength = this._input !== null && this._input.length > MIN_RESCAN_LENGTH ?
774
+ 2 * this._input.length : 0;
773
775
  }
774
776
  }
775
777
  });
776
778
  // Parses until the end
777
779
  input.on('end', () => {
778
- if (this._tokenization === tokenization && typeof this._input === 'string')
779
- this._tokenizeToEnd(callback, true);
780
+ if (this._tokenization === tokenization && this._input !== null) {
781
+ // Decode any incomplete character left at the end
782
+ const rest = decoder ? decoder.decode() : '';
783
+ if (rest)
784
+ this._input = typeof this._input === 'string' ? this._input + rest : rest;
785
+ if (typeof this._input === 'string')
786
+ this._tokenizeToEnd(callback, true);
787
+ }
780
788
  });
781
789
  input.on('error', error => {
782
790
  if (this._tokenization === tokenization)
package/src/N3Parser.js CHANGED
@@ -86,9 +86,14 @@ export default class N3Parser {
86
86
  const path = queryPos < 0 ? baseIRI : baseIRI.substr(0, queryPos);
87
87
  this._basePath = baseIRI.indexOf('/') < 0 ? baseIRI :
88
88
  path.substr(0, path.lastIndexOf('/') + 1);
89
- baseIRI = baseIRI.match(/^(?:([a-z][a-z0-9+.-]*:))?(?:\/\/[^\/]*)?/i);
89
+ const base = baseIRI;
90
+ baseIRI = baseIRI.match(/^(?:([a-z][a-z0-9+.-]*:))?(\/\/[^\/?#]*)?/i);
90
91
  this._baseRoot = baseIRI[0];
91
92
  this._baseScheme = baseIRI[1];
93
+ // If the base has an authority but an empty path,
94
+ // relative IRIs merge under the path '/' (RFC 3986 §5.2.3)
95
+ if (baseIRI[2] !== undefined && (base.length === this._baseRoot.length || base[this._baseRoot.length] === '?'))
96
+ this._basePath = `${this._baseRoot}/`;
92
97
  }
93
98
  }
94
99
 
@@ -1546,8 +1551,13 @@ export default class N3Parser {
1546
1551
  }
1547
1552
  // Resolve root-relative IRIs at the root of the base IRI
1548
1553
  case '/':
1549
- // Resolve scheme-relative IRIs to the scheme
1550
- return (iri[1] === '/' ? this._baseScheme : this._baseRoot) + this._removeDotSegments(iri);
1554
+ // Resolve scheme-relative IRIs to the scheme,
1555
+ // keeping the reference's authority intact (RFC 3986 §5.2.4)
1556
+ if (iri[1] !== '/')
1557
+ return this._baseRoot + this._removeDotSegments(iri);
1558
+ // Without a base scheme, a leading ':' marks where the authority starts
1559
+ return this._baseScheme ? this._removeDotSegments(this._baseScheme + iri) :
1560
+ this._removeDotSegments(`:${iri}`).substr(1);
1551
1561
  // Resolve all other IRIs at the base IRI's path
1552
1562
  default:
1553
1563
  // Relative IRIs cannot contain a colon in the first path segment
@@ -1572,8 +1582,8 @@ export default class N3Parser {
1572
1582
  if (pathStart < 0) {
1573
1583
  // Skip two slashes before the authority
1574
1584
  if (iri[++i] === '/' && iri[++i] === '/')
1575
- // Skip to slash after the authority
1576
- while ((pathStart = i + 1) < length && iri[pathStart] !== '/')
1585
+ // Skip to the end of the authority
1586
+ while ((pathStart = i + 1) < length && iri[pathStart] !== '/' && iri[pathStart] !== '?' && iri[pathStart] !== '#')
1577
1587
  i = pathStart;
1578
1588
  }
1579
1589
  break;
package/src/N3Store.js CHANGED
@@ -118,6 +118,35 @@ function difference(s1, s2, depth = 4) {
118
118
  return target;
119
119
  }
120
120
 
121
+ // Returns the key of a term in the entity index.
122
+ // Keys mark the term type by their first character, so the IRI of a named node
123
+ // that starts with such a marker (as relative IRIs can) is wrapped in < and >.
124
+ const markedIRI = /^[?_"[.<]/;
125
+ function entityKey(term) {
126
+ // Strings are term ids, which only need wrapping when they are IRIs starting with <
127
+ if (typeof term === 'string')
128
+ return term.charCodeAt(0) !== 0x3C || term === '<>' ? term : `<${term}>`;
129
+ // IDs of IRIs usually start with a lowercase scheme letter, which never marks a term type
130
+ const id = termToId(term);
131
+ if (id.charCodeAt(0) >= 0x61 || !term)
132
+ return id;
133
+ // Keys of quoted triples are built from the keys of their components
134
+ if (term.termType === 'Quad')
135
+ return JSON.stringify(quadKeyParts(term));
136
+ return term.termType !== 'NamedNode' || !markedIRI.test(term.value) ? id : `<${term.value}>`;
137
+ }
138
+
139
+ // Returns the keys of the components of a quad, nested like the parts of its internal id
140
+ function quadKeyParts(quad) {
141
+ const parts = [nestedKey(quad.subject), nestedKey(quad.predicate), nestedKey(quad.object)];
142
+ if (quad.graph && !isDefaultGraph(quad.graph))
143
+ parts.push(nestedKey(quad.graph));
144
+ return parts;
145
+ }
146
+ function nestedKey(term) {
147
+ return term.termType === 'Quad' ? quadKeyParts(term) : entityKey(term);
148
+ }
149
+
121
150
  // ## Constructor
122
151
  export class N3EntityIndex {
123
152
  constructor(options = {}) {
@@ -135,6 +164,10 @@ export class N3EntityIndex {
135
164
  }
136
165
 
137
166
  _termFromId(id) {
167
+ // A key in < and > is a named node
168
+ if (id[0] === '<')
169
+ return this._factory.namedNode(id.substring(1, id.length - 1));
170
+ // A key starting with . is a quoted triple
138
171
  if (id[0] === '.') {
139
172
  const entities = this._entities;
140
173
  const terms = id.split('.');
@@ -159,18 +192,34 @@ export class N3EntityIndex {
159
192
  return s && p && o && (isDefaultGraph(term.graph) || (g = this._termToNumericId(term.graph))) &&
160
193
  this._ids[g ? `.${s}.${p}.${o}.${g}` : `.${s}.${p}.${o}`];
161
194
  }
162
- return this._ids[termToId(term)];
195
+ return typeof term === 'string' ? this._stringToNumericId(term) : this._ids[entityKey(term)];
196
+ }
197
+
198
+ // Returns the numeric id of a term given as a string id
199
+ _stringToNumericId(term) {
200
+ // The string is the key unless it is an IRI starting with <. Read the first character
201
+ // from the stored key after a match, which is cheaper than from a concatenated string.
202
+ const id = this._ids[term];
203
+ if (id ? this._entities[id].charCodeAt(0) !== 0x3C : term.charCodeAt(0) !== 0x3C)
204
+ return id;
205
+ return term === '<>' ? id : this._ids[`<${term}>`];
163
206
  }
164
207
 
165
208
  _termToNewNumericId(term) {
209
+ if (typeof term === 'string')
210
+ return this._stringToNumericId(term) || this._addEntity(entityKey(term));
166
211
  // This assumes that no graph term is present - we may wish to error if there is one
167
212
  const str = term && term.termType === 'Quad' ?
168
213
  `.${this._termToNewNumericId(term.subject)}.${this._termToNewNumericId(term.predicate)}.${this._termToNewNumericId(term.object)}${
169
214
  isDefaultGraph(term.graph) ? '' : `.${this._termToNewNumericId(term.graph)}`
170
215
  }`
171
- : termToId(term);
216
+ : entityKey(term);
217
+
218
+ return this._ids[str] || this._addEntity(str);
219
+ }
172
220
 
173
- return this._ids[str] || (this._ids[this._entities[++this._id] = str] = this._id);
221
+ _addEntity(key) {
222
+ return this._ids[this._entities[++this._id] = key] = this._id;
174
223
  }
175
224
 
176
225
  createBlankNode(suggestedName) {
@@ -1382,7 +1431,7 @@ function intersectMatchPatterns(left, right) {
1382
1431
  const leftTerm = left[i], rightTerm = right[i];
1383
1432
  if (leftTerm === null || leftTerm === undefined)
1384
1433
  result[i] = rightTerm;
1385
- else if (rightTerm === null || rightTerm === undefined || termToId(leftTerm) === termToId(rightTerm))
1434
+ else if (rightTerm === null || rightTerm === undefined || entityKey(leftTerm) === entityKey(rightTerm))
1386
1435
  result[i] = leftTerm;
1387
1436
  else
1388
1437
  return false;
@@ -1433,10 +1482,10 @@ class DatasetCoreAndReadableStream extends Readable {
1433
1482
  _matchesQuad(quad) {
1434
1483
  const { subject, predicate, object, graph } = this;
1435
1484
  return !this._matchesNothing &&
1436
- (subject === null || subject === undefined || termToId(subject) === termToId(quad.subject)) &&
1437
- (predicate === null || predicate === undefined || termToId(predicate) === termToId(quad.predicate)) &&
1438
- (object === null || object === undefined || termToId(object) === termToId(quad.object)) &&
1439
- (graph === null || graph === undefined || termToId(graph) === termToId(quad.graph));
1485
+ (subject === null || subject === undefined || entityKey(subject) === entityKey(quad.subject)) &&
1486
+ (predicate === null || predicate === undefined || entityKey(predicate) === entityKey(quad.predicate)) &&
1487
+ (object === null || object === undefined || entityKey(object) === entityKey(quad.object)) &&
1488
+ (graph === null || graph === undefined || entityKey(graph) === entityKey(quad.graph));
1440
1489
  }
1441
1490
 
1442
1491
  // ### `_assertMatchesPattern` rejects a Quad outside this view.