Procházet zdrojové kódy

Fix issue#3246: Module namespace entries are not sorted properly

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.
Suwei Chen před 8 roky
rodič
revize
840d31dc29

+ 17 - 0
lib/Runtime/Language/JavascriptOperators.cpp

@@ -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);
     }
 

+ 4 - 1
lib/Runtime/Language/ModuleNamespace.h

@@ -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; }

+ 23 - 0
test/es6/ValidExportStatements2.js

@@ -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');

+ 14 - 0
test/es6/module-namespace.js

@@ -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" });