1// Copyright 2013 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5"use strict";
6
7// This file relies on the fact that the following declaration has been made
8// in runtime.js:
9// var $Array = global.Array;
10
11var $Symbol = global.Symbol;
12
13// -------------------------------------------------------------------
14
15function SymbolConstructor(x) {
16  if (%_IsConstructCall()) {
17    throw MakeTypeError('not_constructor', ["Symbol"]);
18  }
19  // NOTE: Passing in a Symbol value will throw on ToString().
20  return %CreateSymbol(IS_UNDEFINED(x) ? x : ToString(x));
21}
22
23
24function SymbolToString() {
25  if (!(IS_SYMBOL(this) || IS_SYMBOL_WRAPPER(this))) {
26    throw MakeTypeError(
27      'incompatible_method_receiver', ["Symbol.prototype.toString", this]);
28  }
29  var description = %SymbolDescription(%_ValueOf(this));
30  return "Symbol(" + (IS_UNDEFINED(description) ? "" : description) + ")";
31}
32
33
34function SymbolValueOf() {
35  if (!(IS_SYMBOL(this) || IS_SYMBOL_WRAPPER(this))) {
36    throw MakeTypeError(
37      'incompatible_method_receiver', ["Symbol.prototype.valueOf", this]);
38  }
39  return %_ValueOf(this);
40}
41
42
43function InternalSymbol(key) {
44  var internal_registry = %SymbolRegistry().for_intern;
45  if (IS_UNDEFINED(internal_registry[key])) {
46    internal_registry[key] = %CreateSymbol(key);
47  }
48  return internal_registry[key];
49}
50
51
52function SymbolFor(key) {
53  key = TO_STRING_INLINE(key);
54  var registry = %SymbolRegistry();
55  if (IS_UNDEFINED(registry.for[key])) {
56    var symbol = %CreateSymbol(key);
57    registry.for[key] = symbol;
58    registry.keyFor[symbol] = key;
59  }
60  return registry.for[key];
61}
62
63
64function SymbolKeyFor(symbol) {
65  if (!IS_SYMBOL(symbol)) throw MakeTypeError("not_a_symbol", [symbol]);
66  return %SymbolRegistry().keyFor[symbol];
67}
68
69
70// ES6 19.1.2.8
71function ObjectGetOwnPropertySymbols(obj) {
72  if (!IS_SPEC_OBJECT(obj)) {
73    throw MakeTypeError("called_on_non_object",
74                        ["Object.getOwnPropertySymbols"]);
75  }
76
77  // TODO(arv): Proxies use a shared trap for String and Symbol keys.
78
79  return ObjectGetOwnPropertyKeys(obj, true);
80}
81
82
83//-------------------------------------------------------------------
84
85var symbolHasInstance = InternalSymbol("Symbol.hasInstance");
86var symbolIsConcatSpreadable = InternalSymbol("Symbol.isConcatSpreadable");
87var symbolIsRegExp = InternalSymbol("Symbol.isRegExp");
88var symbolIterator = InternalSymbol("Symbol.iterator");
89var symbolToStringTag = InternalSymbol("Symbol.toStringTag");
90var symbolUnscopables = InternalSymbol("Symbol.unscopables");
91
92
93//-------------------------------------------------------------------
94
95function SetUpSymbol() {
96  %CheckIsBootstrapping();
97
98  %SetCode($Symbol, SymbolConstructor);
99  %FunctionSetPrototype($Symbol, new $Object());
100
101  InstallConstants($Symbol, $Array(
102    // TODO(rossberg): expose when implemented.
103    // "hasInstance", symbolHasInstance,
104    // "isConcatSpreadable", symbolIsConcatSpreadable,
105    // "isRegExp", symbolIsRegExp,
106    "iterator", symbolIterator,
107    // "toStringTag", symbolToStringTag,
108    "unscopables", symbolUnscopables
109  ));
110  InstallFunctions($Symbol, DONT_ENUM, $Array(
111    "for", SymbolFor,
112    "keyFor", SymbolKeyFor
113  ));
114
115  %AddNamedProperty($Symbol.prototype, "constructor", $Symbol, DONT_ENUM);
116  InstallFunctions($Symbol.prototype, DONT_ENUM, $Array(
117    "toString", SymbolToString,
118    "valueOf", SymbolValueOf
119  ));
120}
121
122SetUpSymbol();
123
124
125function ExtendObject() {
126  %CheckIsBootstrapping();
127
128  InstallFunctions($Object, DONT_ENUM, $Array(
129    "getOwnPropertySymbols", ObjectGetOwnPropertySymbols
130  ));
131}
132
133ExtendObject();
134