NativeSymbol.java revision 1508:a661018d34b8
14Srgrimes/*
21690Sdg * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
31690Sdg * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
41690Sdg *
54Srgrimes * This code is free software; you can redistribute it and/or modify it
64Srgrimes * under the terms of the GNU General Public License version 2 only, as
74Srgrimes * published by the Free Software Foundation.  Oracle designates this
84Srgrimes * particular file as subject to the "Classpath" exception as provided
94Srgrimes * by Oracle in the LICENSE file that accompanied this code.
104Srgrimes *
114Srgrimes * This code is distributed in the hope that it will be useful, but WITHOUT
124Srgrimes * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
134Srgrimes * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
144Srgrimes * version 2 for more details (a copy is included in the LICENSE file that
154Srgrimes * accompanied this code).
164Srgrimes *
174Srgrimes * You should have received a copy of the GNU General Public License version
184Srgrimes * 2 along with this work; if not, write to the Free Software Foundation,
194Srgrimes * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
204Srgrimes *
214Srgrimes * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
224Srgrimes * or visit www.oracle.com if you need additional information or have any
234Srgrimes * questions.
244Srgrimes */
254Srgrimes
264Srgrimespackage jdk.nashorn.internal.objects;
274Srgrimes
284Srgrimesimport static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
294Srgrimes
304Srgrimesimport jdk.nashorn.internal.WeakValueCache;
314Srgrimesimport jdk.nashorn.internal.objects.annotations.Attribute;
324Srgrimesimport jdk.nashorn.internal.objects.annotations.Constructor;
334Srgrimesimport jdk.nashorn.internal.objects.annotations.Function;
344Srgrimesimport jdk.nashorn.internal.objects.annotations.ScriptClass;
354Srgrimesimport jdk.nashorn.internal.objects.annotations.Where;
364Srgrimesimport jdk.nashorn.internal.runtime.JSType;
37608Srgrimesimport jdk.nashorn.internal.runtime.PropertyMap;
384Srgrimesimport jdk.nashorn.internal.runtime.ScriptObject;
394Srgrimesimport jdk.nashorn.internal.runtime.ScriptRuntime;
40115683Sobrienimport jdk.nashorn.internal.runtime.Symbol;
41115683Sobrienimport jdk.nashorn.internal.runtime.Undefined;
42115683Sobrien
434Srgrimes/**
441704Sdg * ECMAScript 6 - 19.4 Symbol Objects
454Srgrimes */
464Srgrimes@ScriptClass("Symbol")
4771257Speterpublic final class NativeSymbol extends ScriptObject {
4831544Sjmg
49147565Speter    private final Symbol symbol;
5071785Speter
51147674Speter    // initialized by nasgen
52179277Sjb    private static PropertyMap $nasgenmap$;
5371257Speter
5432925Seivind    /** See ES6 19.4.2.1 */
5513203Swollman    private static WeakValueCache<String, Symbol> globalSymbolRegistry = new WeakValueCache<>();
561549Srgrimes
5765557Sjasone    NativeSymbol(final Symbol symbol, final Global global) {
581549Srgrimes        this(symbol, global.getSymbolPrototype(), $nasgenmap$);
591549Srgrimes    }
6031564Ssef
61120937Srobert    private NativeSymbol(final Symbol symbol, final ScriptObject prototype, final PropertyMap map) {
62131936Smarcel        super(prototype, map);
631549Srgrimes        this.symbol = symbol;
6465557Sjasone    }
6584811Sjhb
6667365Sjhb    private static Symbol getSymbolValue(final Object self) {
6731389Sbde        if (self instanceof Symbol) {
6831389Sbde            return (Symbol) self;
691549Srgrimes        } else if (self instanceof NativeSymbol) {
7064294Sps            return ((NativeSymbol) self).symbol;
712257Ssos        } else {
7234924Sbde            throw typeError("not.a.symbol");
7312662Sdg        }
74146799Sjkoshy    }
75146799Sjkoshy
76236238Sfabient    // ECMA 6 19.4.3.4 Symbol.prototype [ @@toPrimitive ] ( hint )
77236238Sfabient    @Override
78236238Sfabient    public Object getDefaultValue(final Class<?> typeHint) {
79146799Sjkoshy        // Just return the symbol value.
80155299Swsalamon        return symbol;
814Srgrimes    }
8212662Sdg
831549Srgrimes    /**
841549Srgrimes     * ECMA 6 19.4.3.2 Symbol.prototype.toString ( )
857090Sbde     *
861549Srgrimes     * @param self self reference
871549Srgrimes     * @return localized string for this Number
8812662Sdg     */
894Srgrimes    @Function(attributes = Attribute.NOT_ENUMERABLE)
901549Srgrimes    public static String toString(final Object self) {
91121986Sjhb        return getSymbolValue(self).toString();
92214630Sjhb    }
937090Sbde
9431389Sbde
9531389Sbde    /**
9625164Speter     * ECMA 6 19.4.3.3  Symbol.prototype.valueOf ( )
9731389Sbde     *
9830275Speter     * @param self self reference
99118952Sjhb     * @return number value for this Number
1001549Srgrimes     */
1019545Sjoerg    @Function(attributes = Attribute.NOT_ENUMERABLE)
10218207Sbde    public static Object valueOf(final Object self) {
10318207Sbde        return getSymbolValue(self);
1049545Sjoerg    }
1059545Sjoerg
106179277Sjb    /**
107179277Sjb     * ECMA 6 19.4.1.1 Symbol ( [ description ] )
108179277Sjb     *
109179277Sjb     * @param newObj is this function invoked with the new operator
110179277Sjb     * @param self   self reference
111179277Sjb     * @param args   arguments
112179277Sjb     * @return new symbol value
113179277Sjb     */
114179277Sjb    @Constructor(arity = 1)
115179277Sjb    public static Object constructor(final boolean newObj, final Object self, final Object... args) {
116179277Sjb        if (newObj) {
117179277Sjb            throw typeError("symbol.as.constructor");
118179277Sjb        }
119179277Sjb        final String description = args.length > 0 && args[0] != Undefined.getUndefined() ?
120179277Sjb                JSType.toString(args[0]) : "";
121179277Sjb        return new Symbol(description);
122179277Sjb    }
123179277Sjb
124211804Srpaulo    /**
125211839Srpaulo     * ES6 19.4.2.1 Symbol.for ( key )
126211839Srpaulo     *
127211839Srpaulo     * @param self self reference
128211839Srpaulo     * @param arg the argument
129211839Srpaulo     * @return the symbol value
130211839Srpaulo     */
131179277Sjb    @Function(name = "for", attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
132179277Sjb    public synchronized static Object _for(final Object self, final Object arg) {
133165302Skmacy        final String name = JSType.toString(arg);
134165302Skmacy        return globalSymbolRegistry.getOrCreate(name, Symbol::new);
13511343Sbde    }
13692770Salfred
13792770Salfred    /**
13892770Salfred     * ES6 19.4.2.5 Symbol.keyFor ( sym )
1394Srgrimes     *
14073001Sjake     * @param self self reference
14111163Sjulian     * @param arg the argument
142227945Srstone     * @return the symbol name
14312702Sphk     */
1445603Sbde    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
145757Sdg    public synchronized static Object keyFor(final Object self, final Object arg) {
1465603Sbde        if (!(arg instanceof Symbol)) {
147757Sdg            throw typeError("not.a.symbol", ScriptRuntime.safeToString(arg));
148757Sdg        }
1495603Sbde        final String name = ((Symbol) arg).getName();
150757Sdg        return globalSymbolRegistry.get(name) == arg ? name : Undefined.getUndefined();
15172700Sbde    }
1525603Sbde}
1531690Sdg