Skip to content

Commit

Permalink
Add Symbol.prototype.description
Browse files Browse the repository at this point in the history
Summary:
This diff add a new getter `description` to `Symbol.prototype`,
which returned the [[Description]] slot w/o wrapping into `Symbol(...)`.

Noted that this is NOT spec-conformant as for the `Symbol(undefined)`.

Reviewed By: avp

Differential Revision: D25002865

fbshipit-source-id: 25bddb8366c447f3995dd822dac3bb37099f3d84
  • Loading branch information
Huxpro authored and facebook-github-bot committed Nov 21, 2020
1 parent 133a872 commit 9237135
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 0 deletions.
1 change: 1 addition & 0 deletions doc/Features.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ Hermes plans to target ECMAScript 2015 (ES6), with some carefully considered exc
- `Intl` API glue for Android has been added, in order to enable community contribution of a complete, spec-compliant implementation.
- Promise is opt-in (via `-Xes6-promise` flag or `withES6Promise` runtime config).
- Async function (`async` and `await`).
- `Symbol.prototype.description` (it's not fully spec-conformant yet. `Symbol().description` should be `undefined` but it's currently `''`).

## Excluded From Support

Expand Down
1 change: 1 addition & 0 deletions include/hermes/VM/NativeFunctions.def
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,7 @@ NATIVE_FUNCTION(symbolConstructor)
NATIVE_FUNCTION(symbolFor)
NATIVE_FUNCTION(symbolKeyFor)
NATIVE_FUNCTION(symbolPrototypeToString)
NATIVE_FUNCTION(symbolPrototypeDescriptionGetter)
NATIVE_FUNCTION(symbolPrototypeValueOf)
NATIVE_FUNCTION(throwTypeError)
NATIVE_FUNCTION(typedArrayBaseConstructor)
Expand Down
1 change: 1 addition & 0 deletions include/hermes/VM/PredefinedStrings.def
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ STR(symbol, "symbol")
STR(object, "object")
STR(function, "function")
STR(toString, "toString")
STR(description, "description")
STR(toLocaleString, "toLocaleString")
STR(hasOwnProperty, "hasOwnProperty")
STR(isPrototypeOf, "isPrototypeOf")
Expand Down
30 changes: 30 additions & 0 deletions lib/VM/JSLib/Symbol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,15 @@ Handle<JSObject> createSymbolConstructor(Runtime *runtime) {

// Symbol.prototype.xxx methods.
void *ctx = nullptr;
defineAccessor(
runtime,
symbolPrototype,
Predefined::getSymbolID(Predefined::description),
ctx,
symbolPrototypeDescriptionGetter,
nullptr,
false,
true);
defineMethod(
runtime,
symbolPrototype,
Expand Down Expand Up @@ -223,6 +232,27 @@ symbolKeyFor(void *, Runtime *runtime, NativeArgs args) {
return HermesValue::encodeUndefinedValue();
}

/// ES10.0 19.4.3.2 get Symbol.prototype.description
/// TODO(T79770380): make the Symbol(undefined) case spec-conformant.
CallResult<HermesValue>
symbolPrototypeDescriptionGetter(void *, Runtime *runtime, NativeArgs args) {
MutableHandle<SymbolID> sym{runtime};
// 1. Let s be the this value.
// 2. Let sym be ? thisSymbolValue(s).
if (args.getThisArg().isSymbol()) {
sym = args.vmcastThis<SymbolID>().get();
} else if (auto symHandle = args.dyncastThis<JSSymbol>()) {
sym = JSSymbol::getPrimitiveSymbol(*symHandle, runtime).get();
} else {
return runtime->raiseTypeError(
"Symbol.prototype.description can only be called on Symbol");
}

// 3. Return sym.[[Description]].
StringPrimitive *desc = runtime->getStringPrimFromSymbolID(*sym);
return HermesValue::encodeStringValue(desc);
}

CallResult<HermesValue>
symbolPrototypeToString(void *, Runtime *runtime, NativeArgs args) {
MutableHandle<SymbolID> sym{runtime};
Expand Down
20 changes: 20 additions & 0 deletions test/hermes/symbol.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,26 @@ gc();
print(String(sym));
// CHECK-NEXT: Symbol(44912)

print('description');
// CHECK-LABEL: description
print(Symbol().description);
// CHECK-EMPTY:
print(Symbol('asdf').description);
// CHECK-NEXT: asdf
print(Symbol({toString: function() {return 'asdf'}}).description)
// CHECK-NEXT: asdf
print(Object(Symbol('asdf')).description)
// CHECK-NEXT: asdf
try { print(Symbol.prototype.description.call(3)); }
catch (e) { print('caught', e.name); }
// CHECK-NEXT: caught TypeError
print(Symbol.iterator.description) // well-known Symbols
// CHECK-NEXT: Symbol.iterator

// TODO(The below cases need to return `undefined` to be fully conformant.)
// print(Symbol().description)
// print(Symbol(undefined).description)

print('toString');
// CHECK-LABEL: toString
print(Symbol().toString());
Expand Down

0 comments on commit 9237135

Please sign in to comment.