Bug 1299323 - Implement @@toStringTag for module namespace objects r=evilpie
authorJon Coppeard <jcoppeard@mozilla.com>
Wed, 07 Sep 2016 11:32:07 +0100
changeset 312988 f590934ef71f3fb00a7339c992677eda891d3705
parent 312987 cef1721594bf04fb708e6fb1f5a4d80722443b02
child 312989 c1c9882472df9624b37436208c278021a9b0ff44
push id20479
push userkwierso@gmail.com
push dateThu, 08 Sep 2016 01:08:46 +0000
treeherderfx-team@fb7c6b034329 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersevilpie
bugs1299323
milestone51.0a1
Bug 1299323 - Implement @@toStringTag for module namespace objects r=evilpie
js/src/builtin/ModuleObject.cpp
js/src/jit-test/tests/modules/import-namespace.js
js/src/vm/CommonPropertyNames.h
--- a/js/src/builtin/ModuleObject.cpp
+++ b/js/src/builtin/ModuleObject.cpp
@@ -406,17 +406,25 @@ ModuleNamespaceObject::ProxyHandler::get
             RootedValue enumerateFun(cx, getEnumerateFunction(proxy));
             desc.object().set(proxy);
             desc.setConfigurable(false);
             desc.setEnumerable(false);
             desc.setValue(enumerateFun);
             return true;
         }
 
-        // TODO: Implement @@toStringTag here and in has() and get() methods.
+        if (symbol == cx->wellKnownSymbols().toStringTag) {
+            RootedValue value(cx, StringValue(cx->names().Module));
+            desc.object().set(proxy);
+            desc.setWritable(false);
+            desc.setEnumerable(false);
+            desc.setConfigurable(true);
+            desc.setValue(value);
+            return true;
+        }
 
         return true;
     }
 
     const IndirectBindingMap& bindings = ns->bindings();
     ModuleEnvironmentObject* env;
     Shape* shape;
     if (!bindings.lookup(id, &env, &shape))
@@ -445,20 +453,18 @@ ModuleNamespaceObject::ProxyHandler::def
 
 bool
 ModuleNamespaceObject::ProxyHandler::has(JSContext* cx, HandleObject proxy, HandleId id,
                                          bool* bp) const
 {
     Rooted<ModuleNamespaceObject*> ns(cx, &proxy->as<ModuleNamespaceObject>());
     if (JSID_IS_SYMBOL(id)) {
         Rooted<JS::Symbol*> symbol(cx, JSID_TO_SYMBOL(id));
-        if (symbol == cx->wellKnownSymbols().iterator)
-            return true;
-
-        return false;
+        return symbol == cx->wellKnownSymbols().iterator ||
+               symbol == cx->wellKnownSymbols().toStringTag;
     }
 
     *bp = ns->bindings().has(id);
     return true;
 }
 
 bool
 ModuleNamespaceObject::ProxyHandler::get(JSContext* cx, HandleObject proxy, HandleValue receiver,
@@ -467,16 +473,21 @@ ModuleNamespaceObject::ProxyHandler::get
     Rooted<ModuleNamespaceObject*> ns(cx, &proxy->as<ModuleNamespaceObject>());
     if (JSID_IS_SYMBOL(id)) {
         Rooted<JS::Symbol*> symbol(cx, JSID_TO_SYMBOL(id));
         if (symbol == cx->wellKnownSymbols().iterator) {
             vp.set(getEnumerateFunction(proxy));
             return true;
         }
 
+        if (symbol == cx->wellKnownSymbols().toStringTag) {
+            vp.setString(cx->names().Module);
+            return true;
+        }
+
         return false;
     }
 
     ModuleEnvironmentObject* env;
     Shape* shape;
     if (!ns->bindings().lookup(id, &env, &shape))
         return false;
 
--- a/js/src/jit-test/tests/modules/import-namespace.js
+++ b/js/src/jit-test/tests/modules/import-namespace.js
@@ -49,16 +49,26 @@ assertEq(desc.writable, true);
 assertEq(desc.enumerable, true);
 assertEq(desc.configurable, false);
 assertEq(typeof desc.get, "undefined");
 assertEq(typeof desc.set, "undefined");
 assertThrowsInstanceOf(function() { ns.a = 1; }, TypeError);
 delete ns.foo;
 assertThrowsInstanceOf(function() { delete ns.a; }, TypeError);
 
+// Test @@toStringTag property
+desc = Object.getOwnPropertyDescriptor(ns, Symbol.toStringTag);
+assertEq(desc.value, "Module");
+assertEq(desc.writable, false);
+assertEq(desc.enumerable, false);
+assertEq(desc.configurable, true);
+assertEq(typeof desc.get, "undefined");
+assertEq(typeof desc.set, "undefined");
+assertEq(Object.prototype.toString.call(ns), "[object Module]");
+
 // Test @@iterator method.
 let iteratorFun = ns[Symbol.iterator];
 assertEq(iteratorFun.name, "[Symbol.iterator]");
 
 let iterator = ns[Symbol.iterator]();
 assertEq(iterator[Symbol.iterator](), iterator);
 assertIteratorNext(iterator, "a");
 assertIteratorNext(iterator, "b");
--- a/js/src/vm/CommonPropertyNames.h
+++ b/js/src/vm/CommonPropertyNames.h
@@ -186,16 +186,17 @@
     macro(message, message, "message") \
     macro(minDays, minDays, "minDays") \
     macro(minimumFractionDigits, minimumFractionDigits, "minimumFractionDigits") \
     macro(minimumIntegerDigits, minimumIntegerDigits, "minimumIntegerDigits") \
     macro(minimumSignificantDigits, minimumSignificantDigits, "minimumSignificantDigits") \
     macro(minute, minute, "minute") \
     macro(missingArguments, missingArguments, "missingArguments") \
     macro(module, module, "module") \
+    macro(Module, Module, "Module") \
     macro(ModuleDeclarationInstantiation, ModuleDeclarationInstantiation, "ModuleDeclarationInstantiation") \
     macro(ModuleEvaluation, ModuleEvaluation, "ModuleEvaluation") \
     macro(month, month, "month") \
     macro(multiline, multiline, "multiline") \
     macro(name, name, "name") \
     macro(NaN, NaN, "NaN") \
     macro(NegativeInfinity, NegativeInfinity, "-Infinity") \
     macro(new, new_, "new") \