Skip to content

Commit be27da3

Browse files
committed
feat: Add unique symbols
1 parent fae026b commit be27da3

File tree

4 files changed

+59
-13
lines changed

4 files changed

+59
-13
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,11 @@ const re = parse('!re /fo./g', { customTags: [regexp] })
2424
- `regexp` (`!re`) - [RegExp] values,
2525
using their default `/foo/flags` string representation.
2626
- `sharedSymbol` (`!symbol/shared`) - [Shared Symbols], i.e. ones created with `Symbol.for()`
27+
- `symbol` (`!symbol`) - [Unique Symbols]
2728

2829
[RegExp]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions
2930
[Shared Symbols]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol#shared_symbols_in_the_global_symbol_registry
31+
[Unique Symbols]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol
3032

3133
## Customising Tag Names
3234

src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
export { regexp } from './regexp.js'
2-
export { sharedSymbol } from './symbol.js'
2+
export { sharedSymbol, symbol } from './symbol.js'

src/symbol.test.ts

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,56 @@
11
import { test } from 'tap'
2-
import { parse, stringify } from 'yaml'
2+
import { Document, type Scalar, parse, stringify } from 'yaml'
33

4-
import { sharedSymbol } from '.'
4+
import { sharedSymbol, symbol } from '.'
55

6-
test('parse', t => {
6+
test('parse shared', t => {
77
const res: symbol = parse(`!symbol/shared foo`, {
8-
customTags: [sharedSymbol]
8+
customTags: [sharedSymbol, symbol]
99
})
1010
t.type(res, 'symbol')
1111
t.same(Symbol.keyFor(res), 'foo')
1212
t.end()
1313
})
1414

1515
test('stringify shared', t => {
16-
const res = stringify(Symbol.for('some\nsymbol'), {
17-
customTags: [sharedSymbol]
16+
const doc = new Document<Scalar, false>(Symbol.for('some\nsymbol'), {
17+
customTags: [sharedSymbol, symbol]
1818
})
19-
t.equal(res, '!symbol/shared |-\nsome\nsymbol\n')
20-
t.end()
21-
})
19+
t.equal(doc.toString(), '!symbol/shared |-\nsome\nsymbol\n')
20+
21+
doc.contents.value = Symbol('foo')
22+
t.throws(() => doc.toString(), { name: 'TypeError' })
23+
24+
doc.contents.value = 42
25+
t.throws(() => doc.toString(), { name: 'TypeError' })
2226

23-
test('stringify private', t => {
2427
t.throws(() =>
2528
stringify(Symbol('some\nsymbol'), { customTags: [sharedSymbol] })
2629
)
30+
31+
t.end()
32+
})
33+
34+
test('parse private', t => {
35+
const res: symbol = parse(`!symbol foo`, {
36+
customTags: [sharedSymbol, symbol]
37+
})
38+
t.type(res, 'symbol')
39+
t.notOk(Symbol.keyFor(res))
40+
t.end()
41+
})
42+
43+
test('stringify private', t => {
44+
const doc = new Document<Scalar, false>(Symbol('some\nsymbol'), {
45+
customTags: [sharedSymbol, symbol]
46+
})
47+
t.equal(doc.toString(), '!symbol |-\nsome\nsymbol\n')
48+
49+
doc.contents.value = Symbol.for('foo')
50+
t.equal(doc.toString(), '!symbol foo\n')
51+
52+
doc.contents.value = 'foo'
53+
t.throws(() => doc.toString(), { name: 'TypeError' })
54+
2755
t.end()
2856
})

src/symbol.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,28 @@ import type { Scalar, ScalarTag } from 'yaml'
22
import { StringifyContext, stringifyString } from 'yaml/util'
33

44
export const sharedSymbol = {
5-
identify: value => value?.constructor === Symbol,
5+
identify: value =>
6+
value?.constructor === Symbol && typeof Symbol.keyFor(value) === 'string',
67
tag: '!symbol/shared',
78
resolve: str => Symbol.for(str),
89
stringify(item: Scalar, ctx: StringifyContext, onComment, onChompKeep) {
910
const key = Symbol.keyFor(item.value as symbol)
10-
if (key === undefined) throw new Error('Only shared symbols are supported')
11+
if (key === undefined) {
12+
throw new TypeError('Only shared symbols are supported')
13+
}
1114
return stringifyString({ value: key }, ctx, onComment, onChompKeep)
1215
}
1316
} satisfies ScalarTag
17+
18+
export const symbol = {
19+
identify: value =>
20+
value?.constructor === Symbol && Symbol.keyFor(value) === undefined,
21+
tag: '!symbol',
22+
resolve: str => Symbol(str),
23+
stringify(item: Scalar, ctx: StringifyContext, onComment, onChompKeep) {
24+
const sym = item.value
25+
if (typeof sym !== 'symbol') throw new TypeError(`${sym} is not a symbol`)
26+
const value = String(sym).replace(/^Symbol\(|\)$/g, '')
27+
return stringifyString({ value }, ctx, onComment, onChompKeep)
28+
}
29+
} satisfies ScalarTag

0 commit comments

Comments
 (0)