From: Lady Date: Mon, 4 Sep 2023 21:34:27 +0000 (-0400) Subject: Add symbolToString and symbolValue to symbol.js X-Git-Url: https://git.ladys.computer/Pisces/commitdiff_plain/8ae1056e7a8e0d348781ed6b5e8c3210eebea9df?ds=inline Add symbolToString and symbolValue to symbol.js --- diff --git a/symbol.js b/symbol.js index 343e409..a96cb81 100644 --- a/symbol.js +++ b/symbol.js @@ -15,8 +15,38 @@ import { getOwnPropertyDescriptor } from "./object.js"; * * ※ This is effectively an alias for the `Symbol::description` * getter. + * + * ☡ This function throws if the provided argument is not a symbol. */ export const getSymbolDescription = createCallableFunction( getOwnPropertyDescriptor(Symbol.prototype, "description").get, "getSymbolDescription", ); + +/** + * Returns a string representation of the provided symbol. + * + * ※ Use `getSymbolDescription` instead if you just want the text + * description of a symbol. + * + * ※ This is effectively an alias for the `Symbol::toString`. + * + * ☡ This function throws if the provided argument is not a symbol. + */ +export const symbolToString = createCallableFunction( + Symbol.prototype.toString, + "symbolToString", +); + +/** + * Returns the value of the provided symbol. + * + * ※ This is effectively an alias for the `Symbol::valueOf`. + * + * ☡ This function throws if the provided argument is not a symbol and + * does not have a `[[SymbolData]]` slot. + */ +export const symbolValue = createCallableFunction( + Symbol.prototype.valueOf, + "symbolValue", +); diff --git a/symbol.test.js b/symbol.test.js index bedcc72..38d7425 100644 --- a/symbol.test.js +++ b/symbol.test.js @@ -13,7 +13,11 @@ import { describe, it, } from "./dev-deps.js"; -import { getSymbolDescription } from "./symbol.js"; +import { + getSymbolDescription, + symbolToString, + symbolValue, +} from "./symbol.js"; describe("getSymbolDescription", () => { it("[[Call]] returns undefined when the symbol has no description", () => { @@ -31,10 +35,6 @@ describe("getSymbolDescription", () => { ); }); - it("[[Call]] returns the empty string when the symbol has an empty description", () => { - assertStrictEquals(getSymbolDescription(Symbol("")), ""); - }); - it("[[Construct]] throws an error", () => { assertThrows(() => new getSymbolDescription(Symbol())); }); @@ -48,3 +48,74 @@ describe("getSymbolDescription", () => { }); }); }); + +describe("symbolToString", () => { + it('[[Call]] returns "Symbol()" when the symbol has no description', () => { + assertStrictEquals(symbolToString(Symbol()), "Symbol()"); + }); + + it('[[Call]] returns "Symbol()" when the symbol has an empty description', () => { + assertStrictEquals(symbolToString(Symbol("")), "Symbol()"); + }); + + it('[[Call]] returns "Symbol()" wrapping the description', () => { + assertStrictEquals( + symbolToString(Symbol("etaoin")), + "Symbol(etaoin)", + ); + }); + + it("[[Construct]] throws an error", () => { + assertThrows(() => new symbolToString(Symbol())); + }); + + describe(".name", () => { + it("[[Get]] returns the correct name", () => { + assertStrictEquals( + symbolToString.name, + "symbolToString", + ); + }); + }); +}); + +describe("symbolValue", () => { + it("[[Call]] returns the value of a symbol", () => { + const symbol = Symbol(); + assertStrictEquals(symbolValue(symbol), symbol); + }); + + it("[[Call]] returns the value of a symbol wrapper", () => { + const symbol = Symbol(); + assertStrictEquals(symbolValue(new Object(symbol)), symbol); + }); + + it("[[Call]] returns the value of a symbol subclass", () => { + class SymbolExtension extends Symbol { + constructor(symbol) { + return Object.setPrototypeOf( + new Object(symbol), + SymbolExtension.prototype, + ); + } + } + const symbol = Symbol(); + assertStrictEquals( + symbolValue(new SymbolExtension(symbol)), + symbol, + ); + }); + + it("[[Construct]] throws an error", () => { + assertThrows(() => new symbolValue(Symbol())); + }); + + describe(".name", () => { + it("[[Get]] returns the correct name", () => { + assertStrictEquals( + symbolValue.name, + "symbolValue", + ); + }); + }); +});