9.4.6 Module namespace exotic objects' [[OwnPropertyKeys]] should return a list of property names as sorted with Array.prototype.sort using undefined as comparefn.
@@ -15,6 +15,9 @@
#include "Library/ForInObjectEnumerator.h"
#include "Library/ES5Array.h"
+#include "Types/SimpleDictionaryPropertyDescriptor.h"
+#include "Types/SimpleDictionaryTypeHandler.h"
+#include "Language/ModuleNamespace.h"
#ifndef SCRIPT_DIRECT_TYPE
typedef enum JsNativeValueType: int
@@ -1145,6 +1148,20 @@ CommonNumber:
return proxy->PropertyKeysTrap(JavascriptProxy::KeysTrapKind::GetOwnPropertyNamesKind, scriptContext);
}
+ if (ModuleNamespace::Is(object))
+ {
+ ModuleNamespace *ns = ModuleNamespace::FromVar(object);
+ JavascriptArray *names = ns->GetSortedExportedNames();
+ if (names == nullptr)
+ names = JavascriptObject::CreateOwnStringPropertiesHelper(object, scriptContext);
+ names->Sort(nullptr);
+ ns->SetSortedExportedNames(names);
+ }
+
+ return names;
return JavascriptObject::CreateOwnStringPropertiesHelper(object, scriptContext);
@@ -29,6 +29,9 @@ namespace Js
static ModuleNamespace* GetModuleNamespace(ModuleRecordBase* moduleRecord);
void Initialize();
+ JavascriptArray *GetSortedExportedNames() { return this->sortedExportedNames; }
+ void SetSortedExportedNames(JavascriptArray *val) { this->sortedExportedNames = val; }
+ static bool Is(Var aValue) { return JavascriptOperators::GetTypeId(aValue) == TypeIds_ModuleNamespace; }
static ModuleNamespace* FromVar(Var obj) { Assert(JavascriptOperators::GetTypeId(obj) == TypeIds_ModuleNamespace); return static_cast<ModuleNamespace*>(obj); }
virtual PropertyId GetPropertyId(BigPropertyIndex index) override;
@@ -83,7 +86,7 @@ namespace Js
Field(ModuleRecordBase*) moduleRecord;
Field(UnambiguousExportMap*) unambiguousNonLocalExports;
Field(SimplePropertyDescriptorMap*) propertyMap; // local exports.
- Field(ListForListIterator*) sortedExportedNames; // sorted exported names for both local and indirect exports; excludes symbols.
+ Field(JavascriptArray*) sortedExportedNames; // sorted exported names
Field(Field(Var)*) nsSlots;
void SetNSSlotsForModuleNS(Field(Var)* nsSlot) { this->nsSlots = nsSlot; }
@@ -0,0 +1,23 @@
+//-------------------------------------------------------------------------------------------------------
+// Copyright (C) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
+var x;
+export { x as \u03c0 }; // u03c0
+export { x as az };
+export { x as __ };
+export { x as za };
+export { x as Z };
+export { x as \u03bc };
+export { x as z };
+export { x as zz };
+export { x as a };
+export { x as A };
+export { x as aa }
+export { x as \u03bb }; // u03bb
+export { x as _ };
+export { x as $$ };
+export { x as $ };
+export default null;
+export var sym0 = Symbol('abc');
@@ -220,7 +220,21 @@ var tests = [
testModuleScript(functionBody, "Test importing as different binding identifiers", false);
},
+ name: "Issue3246: namespace property names are sorted",
+ body: function () {
+ let functionBody =
+ `
+ import * as ns from 'ValidExportStatements2.js';
+ var p = new Proxy(ns, {});
+ var names = ["sym0","default","$","$$","_","\u03bb","aa","A","a","zz","z","\u03bc","Z","za","__","az","\u03c0"].sort();
+ assert.areEqual(names, Object.getOwnPropertyNames(ns), "ModuleNamespace");
+ assert.areEqual(names, Object.getOwnPropertyNames(p), "Proxy");
+ `;
+ testModuleScript(functionBody, "Test importing as different binding identifiers", false);
+ },
];
testRunner.runTests(tests, { verbose: WScript.Arguments[0] != "summary" });