Skip to content

Commit 1cec619

Browse files
authored
fix: use slash as flag that an object is a CID (multiformats#217)
As per multiformats#212 making `asCID` enumerable breaks tests where modules don't handle self-referential data properly. As proposed in multiformats#213 this swaps `cid.CID === cid` for `cid['/'] === cid.bytes` as a mechanism to tell consumers that the object in question is a `CID` which lets them write CBOR with the correct tags, for example. Fixes multiformats#212 Closes multiformats#213
1 parent a43ffff commit 1cec619

File tree

3 files changed

+44
-12
lines changed

3 files changed

+44
-12
lines changed

src/cid.js

+24-9
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,20 @@ export class CID {
7878
/** @readonly */
7979
this.bytes = bytes
8080

81-
// Circular reference
81+
// flag to serializers that this is a CID and
82+
// should be treated specially
8283
/** @readonly */
83-
this.asCID = this
84+
this['/'] = bytes
85+
}
86+
87+
/**
88+
* Signalling `cid.asCID === cid` has been replaced with `cid['/'] === cid.bytes`
89+
* please either use `CID.asCID(cid)` or switch to new signalling mechanism
90+
*
91+
* @deprecated
92+
*/
93+
get asCID () {
94+
return this
8495
}
8596

8697
// ArrayBufferView
@@ -229,24 +240,28 @@ export class CID {
229240
* @returns {CID<Data, Format, Alg, Version>|null}
230241
*/
231242
static asCID (input) {
243+
if (input == null) {
244+
return null
245+
}
246+
232247
const value = /** @type {any} */ (input)
233248
if (value instanceof CID) {
234249
// If value is instance of CID then we're all set.
235250
return value
236-
} else if (value != null && value.asCID === value) {
237-
// If value isn't instance of this CID class but `this.asCID === this` is
238-
// true it is CID instance coming from a different implementation (diff
239-
// version or duplicate). In that case we rebase it to this `CID`
240-
// implementation so caller is guaranteed to get instance with expected
241-
// API.
251+
} else if ((value['/'] != null && value['/'] === value.bytes) || value.asCID === value) {
252+
// If value isn't instance of this CID class but `this.asCID === this` or
253+
// `value['/'] === value.bytes` is true it is CID instance coming from a
254+
// different implementation (diff version or duplicate). In that case we
255+
// rebase it to this `CID` implementation so caller is guaranteed to get
256+
// instance with expected API.
242257
const { version, code, multihash, bytes } = value
243258
return new CID(
244259
version,
245260
code,
246261
/** @type {API.MultihashDigest<Alg>} */ (multihash),
247262
bytes || encodeCID(version, code, multihash.bytes)
248263
)
249-
} else if (value != null && value[cidSymbol] === true) {
264+
} else if (value[cidSymbol] === true) {
250265
// If value is a CID from older implementation that used to be tagged via
251266
// symbol we still rebase it to the this `CID` implementation by
252267
// delegating that to a constructor.

src/link.js

+19-2
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,25 @@ export const create = (code, digest) => CID.create(1, code, digest)
3636
* @param {unknown|L} value
3737
* @returns {value is L & CID}
3838
*/
39-
export const isLink = value =>
40-
value != null && /** @type {{asCID: unknown}} */ (value).asCID === value
39+
export const isLink = value => {
40+
if (value == null) {
41+
return false
42+
}
43+
44+
const withSlash = /** @type {{'/'?: Uint8Array, bytes: Uint8Array}} */ (value)
45+
46+
if (withSlash['/'] != null && withSlash['/'] === withSlash.bytes) {
47+
return true
48+
}
49+
50+
const withAsCID = /** @type {{'asCID'?: unknown}} */ (value)
51+
52+
if (withAsCID.asCID === value) {
53+
return true
54+
}
55+
56+
return false
57+
}
4158

4259
/**
4360
* Takes cid in a string representation and creates an instance. If `base`

test/test-cid.spec.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -700,9 +700,9 @@ describe('CID', () => {
700700
const cid2 = await new Promise((resolve) => {
701701
receiver.onmessage = (event) => { resolve(event.data) }
702702
})
703-
assert.strictEqual(cid2.asCID, cid2)
704703
sender.close()
705704
receiver.close()
705+
assert.strictEqual(cid2['/'], cid2.bytes)
706706
})
707707

708708
describe('decode', () => {

0 commit comments

Comments
 (0)