Pārlūkot izejas kodu

Add proposal-promise-any (#6641)

Implement Promise.any and AggregateError
https://github.com/tc39/proposal-promise-any
Wenlu Wang 4 gadi atpakaļ
vecāks
revīzija
8220c858e5

+ 1 - 0
bin/ch/DbgController.js

@@ -64,6 +64,7 @@ var controllerObj = (function () {
         [
             "#__proto__",
             "globalThis",
+            "AggregateError",
             "Array",
             "ArrayBuffer",
             "Atomics",

+ 4 - 0
lib/Common/ConfigFlagsList.h

@@ -671,6 +671,7 @@ PHASE(All)
 #define DEFAULT_CONFIG_ESHashbang              (true)
 #define DEFAULT_CONFIG_ESSymbolDescription     (true)
 #define DEFAULT_CONFIG_ESArrayFindFromLast     (false)
+#define DEFAULT_CONFIG_ESPromiseAny            (true)
 #define DEFAULT_CONFIG_ESNullishCoalescingOperator (true)
 #define DEFAULT_CONFIG_ESGlobalThis            (true)
 
@@ -1208,6 +1209,9 @@ FLAGR(Boolean, ESSymbolDescription, "Enable Symbol.prototype.description", DEFAU
 
 FLAGR(Boolean, ESArrayFindFromLast, "Enable findLast, findLastIndex for Array.prototype and TypedArray.prorotype", DEFAULT_CONFIG_ESArrayFindFromLast)
 
+// ES Promise.any and AggregateError flag
+FLAGR(Boolean, ESPromiseAny, "Enable Promise.any and AggregateError", DEFAULT_CONFIG_ESPromiseAny)
+
 // ES import.meta keyword meta-property
 FLAGR(Boolean, ESImportMeta, "Enable import.meta keyword", DEFAULT_CONFIG_ESImportMeta)
 

+ 2 - 0
lib/Parser/ParserCommon.h

@@ -1,5 +1,6 @@
 //-------------------------------------------------------------------------------------------------------
 // Copyright (C) Microsoft. All rights reserved.
+// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
 // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
 //-------------------------------------------------------------------------------------------------------
 // Common definitions used outside parser so that we don't have to include the whole Parser.h.
@@ -25,6 +26,7 @@ enum ErrorTypeEnum
     kjstSyntaxError,
     kjstTypeError,
     kjstURIError,
+    kjstAggregateError,
     kjstWebAssemblyCompileError,
     kjstWebAssemblyRuntimeError,
     kjstWebAssemblyLinkError,

+ 6 - 3
lib/Parser/rterrors.h

@@ -1,5 +1,6 @@
 //-------------------------------------------------------------------------------------------------------
-// Copyright (C) Microsoft. All rights reserved.
+// Copyright (C) Microsoft Corporation and contributors. All rights reserved.
+// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
 // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
 //-------------------------------------------------------------------------------------------------------
 #define IDS_COMPILATION_ERROR_SOURCE    4096
@@ -205,7 +206,7 @@ RT_ERROR_MSG(JSERR_InvalidTypedArraySubarrayLength, 5085, "", "Invalid begin/end
 RT_ERROR_MSG(JSERR_TypedArray_NeedSource, 5086, "", "Invalid source in typed array set", kjstTypeError, 0)
 RT_ERROR_MSG(JSERR_This_NeedDataView, 5087, "", "'this' is not a DataView object", kjstTypeError, 0)
 RT_ERROR_MSG(JSERR_DataView_NeedArgument, 5088, "Required argument %s in DataView method is not specified", "Invalid arguments in DataView", kjstTypeError, 0)
-RT_ERROR_MSG(JSERR_DataView_InvalidOffset, 5089, "", "DataView operation access beyond specified buffer length",  kjstTypeError, 0)
+RT_ERROR_MSG(JSERR_DataView_InvalidOffset, 5089, "", "DataView operation access beyond specified buffer length", kjstTypeError, 0)
 RT_ERROR_MSG(JSERR_DataView_InvalidArgument, 5090, "DataView constructor argument %s is invalid", "Invalid arguments in DataView", kjstRangeError, 0)
 
 RT_ERROR_MSG(JSERR_InvalidFunctionSignature, 5091, "The function '%s' has an invalid signature and cannot be called", "invalid function signature", kjstTypeError, 0)
@@ -305,7 +306,9 @@ RT_ERROR_MSG(JSERR_GeneratorAlreadyExecuting, 5618, "%s: Cannot execute generato
 RT_ERROR_MSG(JSERR_LengthIsTooBig, 5619, "Length property would exceed maximum value in output from '%s'", "", kjstTypeError, 0)
 RT_ERROR_MSG(JSERR_NonObjectFromIterable, 5620, "Iterable provided to %s must not return non-object or null value.", "", kjstTypeError, 0)
 RT_ERROR_MSG(JSERR_EmptyArrayAndInitValueNotPresent, 5621, "%s: Array contains no elements and initialValue is not provided", "", kjstTypeError, 0)
-// 5622-5626 Unused
+RT_ERROR_MSG(JSERR_PromiseAllRejected, 5622, "", "Promise.any all promises rejected.", kjstAggregateError, 0)
+
+// 5623-5626 Unused
 RT_ERROR_MSG(JSERR_NeedConstructor, 5627, "'%s' is not a constructor", "Constructor expected", kjstTypeError, 0)
 
 RT_ERROR_MSG(VBSERR_CantDisplayDate, 32812, "", "The specified date is not available in the current locale's calendar", kjstRangeError, 0)

+ 3 - 0
lib/Runtime/Base/JnDirectFields.h

@@ -44,6 +44,7 @@ ENTRY_SYMBOL(_symbolUnscopables, _u("Symbol.unscopables"))
 // math functions must remain contiguous for quick modification check
 ENTRY(abs)
 ENTRY(acos)
+ENTRY(any)
 ENTRY(asin)
 ENTRY(atan)
 ENTRY(atan2)
@@ -132,6 +133,7 @@ ENTRY(description)
 ENTRY(detach)
 ENTRY(done)
 ENTRY(E)
+ENTRY(errors)
 ENTRY(encodeURI)
 ENTRY(encodeURIComponent)
 ENTRY(endsWith)
@@ -414,6 +416,7 @@ ENTRY(unknown)
 ENTRY(unscopables)
 ENTRY(unshift)
 ENTRY(URIError)
+ENTRY(AggregateError)
 ENTRY(UTC)
 ENTRY(valueOf)
 ENTRY(values)

+ 1 - 0
lib/Runtime/Base/ThreadConfigFlagsList.h

@@ -48,6 +48,7 @@ FLAG_RELEASE(IsESHashbangEnabled, ESHashbang)
 FLAG_RELEASE(IsESNullishCoalescingOperatorEnabled, ESNullishCoalescingOperator)
 FLAG_RELEASE(IsESExportNsAsEnabled, ESExportNsAs)
 FLAG_RELEASE(IsESSymbolDescriptionEnabled, ESSymbolDescription)
+FLAG_RELEASE(IsESPromiseAnyEnabled, ESPromiseAny)
 FLAG_RELEASE(IsESArrayFindFromLastEnabled , ESArrayFindFromLast)
 FLAG_RELEASE(IsESGlobalThisEnabled, ESGlobalThis)
 FLAG_RELEASE(IsES2018AsyncIterationEnabled, ES2018AsyncIteration)

+ 2 - 2
lib/Runtime/ByteCode/ByteCodeCacheReleaseFileVersion.h

@@ -6,7 +6,7 @@
 // NOTE: If there is a merge conflict the correct fix is to make a new GUID.
 // This file was generated with tools/regenByteCode.py
 
-// {61a8b64e-9359-442c-af0c-5a4fa8058917}
+// {7e624f04-e6a9-408a-9a53-d067a2b1c80e}
 const GUID byteCodeCacheReleaseFileVersion =
-{ 0x61a8b64e, 0x9359, 0x442c, {0xaf, 0x0c, 0x5a, 0x4f, 0xa8, 0x05, 0x89, 0x17 } };
+{ 0x7e624f04, 0xe6a9, 0x408a, {0x9a, 0x53, 0xd0, 0x67, 0xa2, 0xb1, 0xc8, 0x0e } };
 

+ 2 - 0
lib/Runtime/Debug/TTSupport.h

@@ -1,5 +1,6 @@
 //-------------------------------------------------------------------------------------------------------
 // Copyright (C) Microsoft. All rights reserved.
+// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
 // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
 //-------------------------------------------------------------------------------------------------------
 #pragma once
@@ -251,6 +252,7 @@ namespace TTD
             SnapPromiseReactionTaskFunctionObject,
             SnapPromiseAllResolveElementFunctionObject,
             SnapPromiseAllSettledResolveOrRejectElementFunctionObject,
+            SnapPromiseAnyRejectElementFunctionObject,
             SnapGeneratorFunction,
             SnapGeneratorVirtualScriptFunction,
             SnapAsyncFunction,

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 299 - 299
lib/Runtime/Library/InJavascript/JsBuiltIn.bc.32b.h


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 299 - 299
lib/Runtime/Library/InJavascript/JsBuiltIn.bc.64b.h


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 301 - 301
lib/Runtime/Library/InJavascript/JsBuiltIn.nojit.bc.32b.h


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 301 - 301
lib/Runtime/Library/InJavascript/JsBuiltIn.nojit.bc.64b.h


+ 3 - 0
lib/Runtime/Library/JavascriptBuiltInFunctionList.h

@@ -139,6 +139,7 @@ BUILTIN(JavascriptError, NewReferenceErrorInstance, NewReferenceErrorInstance, F
 BUILTIN(JavascriptError, NewSyntaxErrorInstance, NewSyntaxErrorInstance, FunctionInfo::None)
 BUILTIN(JavascriptError, NewTypeErrorInstance, NewTypeErrorInstance, FunctionInfo::None)
 BUILTIN(JavascriptError, NewURIErrorInstance, NewURIErrorInstance, FunctionInfo::None)
+BUILTIN(JavascriptError, NewAggregateErrorInstance, NewAggregateErrorInstance, FunctionInfo::None)
 BUILTIN(JavascriptError, NewWebAssemblyCompileErrorInstance, NewWebAssemblyCompileErrorInstance, FunctionInfo::None)
 BUILTIN(JavascriptError, NewWebAssemblyRuntimeErrorInstance, NewWebAssemblyRuntimeErrorInstance, FunctionInfo::None)
 BUILTIN(JavascriptError, NewWebAssemblyLinkErrorInstance, NewWebAssemblyLinkErrorInstance, FunctionInfo::None)
@@ -468,6 +469,7 @@ BUILTIN(JavascriptListIterator, Next, EntryNext, FunctionInfo::ErrorOnNew)
 BUILTIN(JavascriptPromise, NewInstance, NewInstance, FunctionInfo::SkipDefaultNewObject)
 BUILTIN(JavascriptPromise, All, EntryAll, FunctionInfo::ErrorOnNew)
 BUILTIN(JavascriptPromise, AllSettled, EntryAllSettled, FunctionInfo::ErrorOnNew)
+BUILTIN(JavascriptPromise, Any, EntryAny, FunctionInfo::ErrorOnNew)
 BUILTIN(JavascriptPromise, Catch, EntryCatch, FunctionInfo::ErrorOnNew)
 BUILTIN(JavascriptPromise, Race, EntryRace, FunctionInfo::ErrorOnNew)
 BUILTIN(JavascriptPromise, Reject, EntryReject, FunctionInfo::ErrorOnNew)
@@ -480,6 +482,7 @@ BUILTIN(JavascriptPromise, ResolveOrRejectFunction, EntryResolveOrRejectFunction
 BUILTIN(JavascriptPromise, CapabilitiesExecutorFunction, EntryCapabilitiesExecutorFunction, FunctionInfo::ErrorOnNew | FunctionInfo::DoNotProfile)
 BUILTIN(JavascriptPromise, AllResolveElementFunction, EntryAllResolveElementFunction, FunctionInfo::ErrorOnNew | FunctionInfo::DoNotProfile)
 BUILTIN(JavascriptPromise, AllSettledResolveOrRejectElementFunction, EntryAllSettledResolveOrRejectElementFunction, FunctionInfo::ErrorOnNew | FunctionInfo::DoNotProfile)
+BUILTIN(JavascriptPromise, AnyRejectElementFunction, EntryAnyRejectElementFunction, FunctionInfo::ErrorOnNew | FunctionInfo::DoNotProfile)
 BUILTIN(JavascriptPromise, GetterSymbolSpecies, EntryGetterSymbolSpecies, FunctionInfo::ErrorOnNew)
 BUILTIN(JavascriptReflect, DefineProperty, EntryDefineProperty, FunctionInfo::ErrorOnNew | FunctionInfo::DoNotProfile)
 BUILTIN(JavascriptReflect, DeleteProperty, EntryDeleteProperty, FunctionInfo::ErrorOnNew | FunctionInfo::DoNotProfile)

+ 76 - 0
lib/Runtime/Library/JavascriptError.cpp

@@ -108,6 +108,79 @@ namespace Js
 
 #undef NEW_ERROR
 
+    Var JavascriptError::NewAggregateErrorInstance(RecyclableObject* function, CallInfo callInfo, ...)
+    {
+        PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
+        ARGUMENTS(args, callInfo);
+        ScriptContext* scriptContext = function->GetScriptContext();
+        JavascriptError* pError = scriptContext->GetLibrary()->CreateAggregateError();
+        Var newTarget = args.GetNewTarget();
+        Var errors = args.Info.Count > 1 ? args[1] : scriptContext->GetLibrary()->GetUndefined();
+        Var message = args.Info.Count > 2 ? args[2] : scriptContext->GetLibrary()->GetUndefined();
+        Var options = args.Info.Count > 3 ? args[3] : scriptContext->GetLibrary()->GetUndefined();
+
+        bool isCtorSuperCall = (callInfo.Flags & CallFlags_New) && newTarget != nullptr && !JavascriptOperators::IsUndefined(newTarget);
+        JavascriptString* messageString = nullptr;
+
+        if (JavascriptOperators::GetTypeId(message) != TypeIds_Undefined)
+        {
+            messageString = JavascriptConversion::ToString(message, scriptContext);
+        }
+
+        if (messageString)
+        {
+            JavascriptOperators::SetProperty(pError, pError, PropertyIds::message, messageString, scriptContext);
+            pError->SetNotEnumerable(PropertyIds::message);
+        }
+
+        if (JavascriptOperators::IsObject(options) && JavascriptOperators::HasProperty(UnsafeVarTo<RecyclableObject>(options), PropertyIds::cause))
+        {
+            Var cause = JavascriptOperators::GetPropertyNoCache(UnsafeVarTo<RecyclableObject>(options), PropertyIds::cause, scriptContext);
+            JavascriptOperators::SetProperty(pError, pError, PropertyIds::cause, cause, scriptContext);
+            pError->SetNotEnumerable(PropertyIds::cause);
+        }
+
+        using ErrorListType = SList<Var, Recycler>;
+        Recycler* recycler = scriptContext->GetRecycler();
+        ErrorListType* errorsList = RecyclerNew(recycler, ErrorListType, recycler);
+        RecyclableObject* iterator = JavascriptOperators::GetIterator(errors, scriptContext);
+        JavascriptOperators::DoIteratorStepAndValue(iterator, scriptContext, [&](Var next)
+            {
+                errorsList->Push(next);
+            });
+        errorsList->Reverse();
+        JavascriptError::SetErrorsList(pError, errorsList, scriptContext);
+
+        JavascriptExceptionContext exceptionContext;
+        JavascriptExceptionOperators::WalkStackForExceptionContext(*scriptContext, exceptionContext, pError,
+            JavascriptExceptionOperators::StackCrawlLimitOnThrow(pError, *scriptContext), /*returnAddress=*/ nullptr, /*isThrownException=*/ false, /*resetSatck=*/ false);
+        JavascriptExceptionOperators::AddStackTraceToObject(pError, exceptionContext.GetStackTrace(), *scriptContext, /*isThrownException=*/ false, /*resetSatck=*/ false);
+
+        return isCtorSuperCall ?
+            JavascriptOperators::OrdinaryCreateFromConstructor(VarTo<RecyclableObject>(newTarget), pError, nullptr, scriptContext) :
+            pError;
+    }
+
+    void JavascriptError::SetErrorsList(JavascriptError* pError, SList<Var, Recycler>* errorsList, ScriptContext* scriptContext)
+    {
+        JavascriptArray* errors = scriptContext->GetLibrary()->CreateArray(errorsList->Count());
+        uint32 n = 0;
+        SList<Var, Recycler>::Iterator it = errorsList->GetIterator();
+        while (it.Next())
+        {
+            errors->DirectSetItemAt(n, it.Data());
+            n++;
+        }
+
+        JavascriptError::SetErrorsList(pError, errors, scriptContext);
+    }
+
+    void JavascriptError::SetErrorsList(JavascriptError* pError, JavascriptArray* errors, ScriptContext* scriptContext)
+    {
+        JavascriptOperators::SetProperty(pError, pError, PropertyIds::errors, errors, scriptContext);
+        pError->SetNotEnumerable(PropertyIds::errors);
+    }
+
     Var JavascriptError::EntryToString(RecyclableObject* function, CallInfo callInfo, ...)
     {
         PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
@@ -771,6 +844,9 @@ namespace Js
         case kjstURIError:
             jsNewError = targetJavascriptLibrary->CreateURIError();
             break;
+        case kjstAggregateError:
+            jsNewError = targetJavascriptLibrary->CreateAggregateError();
+            break;
         case kjstWebAssemblyCompileError:
             jsNewError = targetJavascriptLibrary->CreateWebAssemblyCompileError();
         case kjstWebAssemblyRuntimeError:

+ 6 - 0
lib/Runtime/Library/JavascriptError.h

@@ -53,6 +53,7 @@ namespace Js
             static FunctionInfo NewSyntaxErrorInstance;
             static FunctionInfo NewTypeErrorInstance;
             static FunctionInfo NewURIErrorInstance;
+            static FunctionInfo NewAggregateErrorInstance;
             static FunctionInfo NewWebAssemblyCompileErrorInstance;
             static FunctionInfo NewWebAssemblyRuntimeErrorInstance;
             static FunctionInfo NewWebAssemblyLinkErrorInstance;
@@ -145,6 +146,11 @@ namespace Js
         static void TryThrowTypeError(ScriptContext * checkScriptContext, ScriptContext * scriptContext, int32 hCode, PCWSTR varName = nullptr);
         static JavascriptError* CreateFromCompileScriptException(ScriptContext* scriptContext, CompileScriptException* cse, const WCHAR * sourceUrl = nullptr);
 
+        static Var NewAggregateErrorInstance(RecyclableObject* function, CallInfo callinfo, ...);
+
+        static void SetErrorsList(JavascriptError* pError, SList<Var, Recycler>* errorsList, ScriptContext* scriptContext);
+        static void SetErrorsList(JavascriptError* pError, JavascriptArray* errors, ScriptContext* scriptContext);
+
     private:
 
         Field(BOOL) isExternalError;

+ 39 - 7
lib/Runtime/Library/JavascriptLibrary.cpp

@@ -331,6 +331,7 @@ namespace Js
         INIT_ERROR_PROTO(syntaxErrorPrototype, InitializeSyntaxErrorPrototype);
         INIT_ERROR_PROTO(typeErrorPrototype, InitializeTypeErrorPrototype);
         INIT_ERROR_PROTO(uriErrorPrototype, InitializeURIErrorPrototype);
+        INIT_ERROR_PROTO(aggregateErrorPrototype, InitializeAggregateErrorPrototype);
 
 #ifdef ENABLE_WASM
         if (CONFIG_FLAG(Wasm) && PHASE_ENABLED1(WasmPhase))
@@ -566,6 +567,7 @@ namespace Js
         INIT_SIMPLE_TYPE(syntaxErrorType, TypeIds_Error, syntaxErrorPrototype);
         INIT_SIMPLE_TYPE(typeErrorType, TypeIds_Error, typeErrorPrototype);
         INIT_SIMPLE_TYPE(uriErrorType, TypeIds_Error, uriErrorPrototype);
+        INIT_SIMPLE_TYPE(aggregateErrorType, TypeIds_Error, aggregateErrorPrototype);
 
 #ifdef ENABLE_WASM
         if (CONFIG_FLAG(Wasm) && PHASE_ENABLED1(WasmPhase))
@@ -1019,6 +1021,9 @@ namespace Js
         case kjstURIError:
             return GetURIErrorType();
 
+        case kjstAggregateError:
+            return GetAggregateErrorType();
+
         case kjstWebAssemblyCompileError:
             return GetWebAssemblyCompileErrorType();
 
@@ -1792,6 +1797,14 @@ namespace Js
             nativeErrorPrototype);
         AddFunction(globalObject, PropertyIds::URIError, uriErrorConstructor);
 
+        if (scriptContext->GetConfig()->IsESPromiseAnyEnabled())
+        {
+            aggregateErrorConstructor = CreateBuiltinConstructor(&JavascriptError::EntryInfo::NewAggregateErrorInstance,
+                DeferredTypeHandler<InitializeAggregateErrorConstructor>::GetDefaultInstance(),
+                nativeErrorPrototype);
+            AddFunction(globalObject, PropertyIds::AggregateError, aggregateErrorConstructor);
+        }
+
 #ifdef ENABLE_WASM
         if (CONFIG_FLAG(Wasm) && PHASE_ENABLED1(WasmPhase))
         {
@@ -2503,13 +2516,13 @@ namespace Js
         return true;
     }
 
-#define INIT_ERROR_IMPL(error, errorName) \
+#define INIT_ERROR_IMPL(error, errorName, ctorLength) \
     bool JavascriptLibrary::Initialize##error##Constructor(DynamicObject* constructor, DeferredTypeHandlerBase* typeHandler, DeferredInitializeMode mode) \
     { \
         typeHandler->Convert(constructor, mode, 3); \
         JavascriptLibrary* library = constructor->GetLibrary(); \
         library->AddMember(constructor, PropertyIds::prototype, library->Get##error##Prototype(), PropertyNone); \
-        library->AddMember(constructor, PropertyIds::length, TaggedInt::ToVarUnchecked(1), PropertyConfigurable); \
+        library->AddMember(constructor, PropertyIds::length, TaggedInt::ToVarUnchecked(ctorLength), PropertyConfigurable); \
         PropertyAttributes prototypeNameMessageAttributes = PropertyConfigurable; \
         library->AddMember(constructor, PropertyIds::name, library->CreateStringFromCppLiteral(_u(#errorName)), prototypeNameMessageAttributes); \
         constructor->SetHasNoEnumerableProperties(true); \
@@ -2528,16 +2541,17 @@ namespace Js
         return true; \
     }
 
-#define INIT_ERROR(error) INIT_ERROR_IMPL(error, error)
+#define INIT_ERROR(error) INIT_ERROR_IMPL(error, error, 1)
     INIT_ERROR(EvalError);
     INIT_ERROR(RangeError);
     INIT_ERROR(ReferenceError);
     INIT_ERROR(SyntaxError);
     INIT_ERROR(TypeError);
     INIT_ERROR(URIError);
-    INIT_ERROR_IMPL(WebAssemblyCompileError, CompileError);
-    INIT_ERROR_IMPL(WebAssemblyRuntimeError, RuntimeError);
-    INIT_ERROR_IMPL(WebAssemblyLinkError, LinkError);
+    INIT_ERROR_IMPL(AggregateError, AggregateError, 2);
+    INIT_ERROR_IMPL(WebAssemblyCompileError, CompileError, 1);
+    INIT_ERROR_IMPL(WebAssemblyRuntimeError, RuntimeError, 1);
+    INIT_ERROR_IMPL(WebAssemblyLinkError, LinkError, 1);
 
 #undef INIT_ERROR
 
@@ -2666,7 +2680,7 @@ namespace Js
 
     bool JavascriptLibrary::InitializePromiseConstructor(DynamicObject* promiseConstructor, DeferredTypeHandlerBase * typeHandler, DeferredInitializeMode mode)
     {
-        typeHandler->Convert(promiseConstructor, mode, 8);
+        typeHandler->Convert(promiseConstructor, mode, 9);
         // Note: Any new function addition/deletion/modification should also be updated in JavascriptLibrary::ProfilerRegisterPromise
         // so that the update is in sync with profiler
         JavascriptLibrary* library = promiseConstructor->GetLibrary();
@@ -2678,6 +2692,10 @@ namespace Js
 
         library->AddFunctionToLibraryObject(promiseConstructor, PropertyIds::all, &JavascriptPromise::EntryInfo::All, 1);
         library->AddFunctionToLibraryObject(promiseConstructor, PropertyIds::allSettled, &JavascriptPromise::EntryInfo::AllSettled, 1);
+        if (scriptContext->GetConfig()->IsESPromiseAnyEnabled())
+        {
+            library->AddFunctionToLibraryObject(promiseConstructor, PropertyIds::any, &JavascriptPromise::EntryInfo::Any, 1);
+        }
         library->AddFunctionToLibraryObject(promiseConstructor, PropertyIds::race, &JavascriptPromise::EntryInfo::Race, 1);
         library->AddFunctionToLibraryObject(promiseConstructor, PropertyIds::reject, &JavascriptPromise::EntryInfo::Reject, 1);
         library->AddMember(promiseConstructor, PropertyIds::resolve, library->EnsurePromiseResolveFunction(), PropertyBuiltInMethodDefaults);
@@ -6278,6 +6296,9 @@ namespace Js
         case kjstURIError:
             baseErrorType = uriErrorType;
             break;
+        case kjstAggregateError:
+            baseErrorType = aggregateErrorType;
+            break;
         case kjstWebAssemblyCompileError:
             baseErrorType = webAssemblyCompileErrorType;
             break;
@@ -6309,6 +6330,7 @@ namespace Js
     CREATE_ERROR(SyntaxError, syntaxErrorType, kjstSyntaxError);
     CREATE_ERROR(TypeError, typeErrorType, kjstTypeError);
     CREATE_ERROR(URIError, uriErrorType, kjstURIError);
+    CREATE_ERROR(AggregateError, aggregateErrorType, kjstAggregateError);
     CREATE_ERROR(WebAssemblyCompileError, webAssemblyCompileErrorType, kjstWebAssemblyCompileError);
     CREATE_ERROR(WebAssemblyRuntimeError, webAssemblyRuntimeErrorType, kjstWebAssemblyRuntimeError);
     CREATE_ERROR(WebAssemblyLinkError, webAssemblyLinkErrorType, kjstWebAssemblyLinkError);
@@ -6634,6 +6656,15 @@ namespace Js
         return function;
     }
 
+    JavascriptPromiseAnyRejectElementFunction* JavascriptLibrary::CreatePromiseAnyRejectElementFunction(JavascriptMethod entryPoint, uint32 index, JavascriptArray* errors, JavascriptPromiseCapability* capabilities, JavascriptPromiseAllResolveElementFunctionRemainingElementsWrapper* remainingElements, JavascriptPromiseResolveOrRejectFunctionAlreadyResolvedWrapper* alreadyCalledWrapper)
+    {
+        FunctionInfo* functionInfo = &Js::JavascriptPromise::EntryInfo::AnyRejectElementFunction;
+        DynamicType* type = DynamicType::New(scriptContext, TypeIds_Function, functionPrototype, entryPoint, GetDeferredAnonymousFunctionTypeHandler());
+        JavascriptPromiseAnyRejectElementFunction* function = RecyclerNewEnumClass(this->GetRecycler(), EnumFunctionClass, JavascriptPromiseAnyRejectElementFunction, type, functionInfo, index, errors, capabilities, remainingElements, alreadyCalledWrapper);
+        // Length should be 1 but not accessible from script.
+        return function;
+    }
+
     JavascriptPromiseAllSettledResolveOrRejectElementFunction* JavascriptLibrary::CreatePromiseAllSettledResolveOrRejectElementFunction(JavascriptMethod entryPoint, uint32 index, JavascriptArray* values, JavascriptPromiseCapability* capabilities, JavascriptPromiseAllResolveElementFunctionRemainingElementsWrapper* remainingElements, JavascriptPromiseResolveOrRejectFunctionAlreadyResolvedWrapper* alreadyCalledWrapper, bool isRejecting)
     {
         FunctionInfo* functionInfo = &Js::JavascriptPromise::EntryInfo::AllSettledResolveOrRejectElementFunction;
@@ -7469,6 +7500,7 @@ namespace Js
         REGISTER_ERROR_OBJECT(SyntaxError);
         REGISTER_ERROR_OBJECT(TypeError);
         REGISTER_ERROR_OBJECT(URIError);
+        REGISTER_ERROR_OBJECT(AggregateError);
 
         return hr;
     }

+ 5 - 0
lib/Runtime/Library/JavascriptLibrary.h

@@ -308,6 +308,7 @@ namespace Js
         Field(DynamicType *) syntaxErrorType;
         Field(DynamicType *) typeErrorType;
         Field(DynamicType *) uriErrorType;
+        Field(DynamicType *) aggregateErrorType;
         Field(DynamicType *) webAssemblyCompileErrorType;
         Field(DynamicType *) webAssemblyRuntimeErrorType;
         Field(DynamicType *) webAssemblyLinkErrorType;
@@ -725,6 +726,7 @@ namespace Js
         DynamicType * GetSyntaxErrorType() const { return syntaxErrorType; }
         DynamicType * GetTypeErrorType() const { return typeErrorType; }
         DynamicType * GetURIErrorType() const { return uriErrorType; }
+        DynamicType * GetAggregateErrorType() const { return aggregateErrorType; }
         DynamicType * GetWebAssemblyCompileErrorType() const { return webAssemblyCompileErrorType; }
         DynamicType * GetWebAssemblyRuntimeErrorType() const { return webAssemblyRuntimeErrorType; }
         DynamicType * GetWebAssemblyLinkErrorType() const { return webAssemblyLinkErrorType; }
@@ -923,6 +925,7 @@ namespace Js
         JavascriptError* CreateSyntaxError();
         JavascriptError* CreateTypeError();
         JavascriptError* CreateURIError();
+        JavascriptError* CreateAggregateError();
         JavascriptError* CreateStackOverflowError();
         JavascriptError* CreateOutOfMemoryError();
         JavascriptError* CreateWebAssemblyCompileError();
@@ -1030,6 +1033,7 @@ namespace Js
         JavascriptPromiseReactionTaskFunction* CreatePromiseReactionTaskFunction(JavascriptMethod entryPoint, JavascriptPromiseReaction* reaction, Var argument);
         JavascriptPromiseResolveThenableTaskFunction* CreatePromiseResolveThenableTaskFunction(JavascriptMethod entryPoint, JavascriptPromise* promise, RecyclableObject* thenable, RecyclableObject* thenFunction);
         JavascriptPromiseAllResolveElementFunction* CreatePromiseAllResolveElementFunction(JavascriptMethod entryPoint, uint32 index, JavascriptArray* values, JavascriptPromiseCapability* capabilities, JavascriptPromiseAllResolveElementFunctionRemainingElementsWrapper* remainingElements);
+        JavascriptPromiseAnyRejectElementFunction* CreatePromiseAnyRejectElementFunction(JavascriptMethod entryPoint, uint32 index, JavascriptArray* errors, JavascriptPromiseCapability* capabilities, JavascriptPromiseAllResolveElementFunctionRemainingElementsWrapper* remainingElements, JavascriptPromiseResolveOrRejectFunctionAlreadyResolvedWrapper* alreadyCalledWrapper);
         JavascriptPromiseAllSettledResolveOrRejectElementFunction* CreatePromiseAllSettledResolveOrRejectElementFunction(JavascriptMethod entryPoint, uint32 index, JavascriptArray* values, JavascriptPromiseCapability* capabilities, JavascriptPromiseAllResolveElementFunctionRemainingElementsWrapper* remainingElements, JavascriptPromiseResolveOrRejectFunctionAlreadyResolvedWrapper* alreadyCalledWrapper, bool isRejecting);
         JavascriptPromiseThenFinallyFunction* CreatePromiseThenFinallyFunction(JavascriptMethod entryPoint, RecyclableObject* OnFinally, RecyclableObject* Constructor, bool shouldThrow);
         JavascriptPromiseThunkFinallyFunction* CreatePromiseThunkFinallyFunction(JavascriptMethod entryPoint, Var value, bool shouldThrow);
@@ -1227,6 +1231,7 @@ namespace Js
         STANDARD_INIT(SyntaxError);
         STANDARD_INIT(TypeError);
         STANDARD_INIT(URIError);
+        STANDARD_INIT(AggregateError);
         STANDARD_INIT(RuntimeError);
         STANDARD_INIT(TypedArray);
         STANDARD_INIT(Int8Array);

+ 5 - 0
lib/Runtime/Library/JavascriptLibraryBase.h

@@ -1,5 +1,6 @@
 //-------------------------------------------------------------------------------------------------------
 // Copyright (C) Microsoft. All rights reserved.
+// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
 // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
 //-------------------------------------------------------------------------------------------------------
 
@@ -84,6 +85,7 @@ namespace Js
         JavascriptFunction* GetSyntaxErrorConstructor() const { return syntaxErrorConstructor; }
         JavascriptFunction* GetTypeErrorConstructor() const { return typeErrorConstructor; }
         JavascriptFunction* GetURIErrorConstructor() const { return uriErrorConstructor; }
+        JavascriptFunction* GetAggregateErrorConstructor() const { return aggregateErrorConstructor;  }
         JavascriptFunction* GetPromiseResolve() const { return promiseResolveFunction; }
         JavascriptFunction* GetPromiseThen() const { return promiseThenFunction; }
         JavascriptFunction* GetJSONStringify() const { return jsonStringifyFunction; }
@@ -153,6 +155,7 @@ namespace Js
         DynamicObject* GetSyntaxErrorPrototype() const { return syntaxErrorPrototype; }
         DynamicObject* GetTypeErrorPrototype() const { return typeErrorPrototype; }
         DynamicObject* GetURIErrorPrototype() const { return uriErrorPrototype; }
+        DynamicObject* GetAggregateErrorPrototype() const { return aggregateErrorPrototype;  }
         PropertyId GetPropertyIdSymbolIterator() { return PropertyIds::_symbolIterator; };
         PropertyId GetPropertyIdSymbolToStringTag() { return PropertyIds::_symbolToStringTag; };
         PropertyId GetPropertyIdSymbolUnscopables() { return PropertyIds::_symbolUnscopables; };
@@ -196,6 +199,7 @@ namespace Js
         Field(RuntimeFunction*) syntaxErrorConstructor;
         Field(RuntimeFunction*) typeErrorConstructor;
         Field(RuntimeFunction*) uriErrorConstructor;
+        Field(RuntimeFunction*) aggregateErrorConstructor;
         Field(RuntimeFunction*) proxyConstructor;
         Field(RuntimeFunction*) promiseConstructor;
         Field(RuntimeFunction*) generatorFunctionConstructor;
@@ -283,6 +287,7 @@ namespace Js
         Field(DynamicObject*) syntaxErrorPrototype;
         Field(DynamicObject*) typeErrorPrototype;
         Field(DynamicObject*) uriErrorPrototype;
+        Field(DynamicObject*) aggregateErrorPrototype;
 
         //SIMD Prototypes
         Field(DynamicObject*) simdBool8x16Prototype;

+ 261 - 0
lib/Runtime/Library/JavascriptPromise.cpp

@@ -1,5 +1,6 @@
 //-------------------------------------------------------------------------------------------------------
 // Copyright (C) Microsoft. All rights reserved.
+// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
 // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
 //-------------------------------------------------------------------------------------------------------
 #include "RuntimeLibraryPch.h"
@@ -267,6 +268,204 @@ namespace Js
         return promiseCapability->GetPromise();
     }
 
+    Var JavascriptPromise::EntryAny(RecyclableObject* function, CallInfo callInfo, ...)
+    {
+        PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
+        ARGUMENTS(args, callInfo);
+        Assert(!(callInfo.Flags & CallFlags_New));
+
+        ScriptContext* scriptContext = function->GetScriptContext();
+
+        AUTO_TAG_NATIVE_LIBRARY_ENTRY(function, callInfo, _u("Promise.any"));
+
+        // 1. Let C be the this value.
+        Var C = args[0];
+
+        // 2. Let promiseCapability be ? NewPromiseCapability(C).
+        JavascriptPromiseCapability* promiseCapability = NewPromiseCapability(C, scriptContext);
+        RecyclableObject* constructor = UnsafeVarTo<RecyclableObject>(C);
+
+        JavascriptLibrary* library = scriptContext->GetLibrary();
+        RecyclableObject* promiseResolve = nullptr;
+        RecyclableObject* iteratorRecord = nullptr;
+        try {
+            // 3. Let promiseResolve be GetPromiseResolve(C).
+            // 4. IfAbruptRejectPromise(promiseResolve, promiseCapability).
+            Var resolveVar = JavascriptOperators::GetProperty(constructor, Js::PropertyIds::resolve, scriptContext);
+            if (!JavascriptConversion::IsCallable(resolveVar))
+            {
+                JavascriptError::ThrowTypeError(scriptContext, JSERR_NeedFunction);
+            }
+            promiseResolve = UnsafeVarTo<RecyclableObject>(resolveVar);
+
+            // 5. Let iteratorRecord be GetIterator(iterable).
+            // 6. IfAbruptRejectPromise(iteratorRecord, promiseCapability).
+            Var iterable = args.Info.Count > 1 ? args[1] : library->GetUndefined();
+            iteratorRecord = JavascriptOperators::GetIterator(iterable, scriptContext); 
+        }
+        catch (const JavascriptException& err)
+        {
+            JavascriptExceptionObject* exception = err.GetAndClear();
+            return JavascriptPromise::CreateRejectedPromise(exception->GetThrownObject(scriptContext), scriptContext);
+        }
+
+        // Abstract operation PerformPromiseAny
+        // 7. Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability, promiseResolve).
+        try {
+            // 1. Assert: ! IsConstructor(constructor) is true. 
+            // 2. Assert: resultCapability is a PromiseCapability Record.
+            // 3. Assert: ! IsCallable(promiseResolve) is true.
+            // 4. Let errors be a new empty List.
+            JavascriptArray* errors = library->CreateArray();
+
+            // 5. Let remainingElementsCount be a new Record { [[Value]]: 1 }.
+            JavascriptPromiseAllResolveElementFunctionRemainingElementsWrapper* remainingElementsWrapper = RecyclerNewStructZ(scriptContext->GetRecycler(), JavascriptPromiseAllResolveElementFunctionRemainingElementsWrapper);
+            remainingElementsWrapper->remainingElements = 1;
+
+            // 6. Let index be 0.
+            uint32 index = 0;
+
+            // 7. Repeat,
+            JavascriptOperators::DoIteratorStepAndValue(iteratorRecord, scriptContext, [&](Var nextValue) {
+                // a. Let next be IteratorStep(iteratorRecord).
+                // e. Let nextValue be IteratorValue(next).
+                // h. Append undefined to errors.
+                errors->DirectAppendItem(library->GetUndefined());
+
+                // i. Let nextPromise be ? Call(promiseResolve, constructor, << nextValue >> ).
+                ThreadContext* threadContext = scriptContext->GetThreadContext();
+                Var nextPromise = nullptr;
+                BEGIN_SAFE_REENTRANT_CALL(threadContext);
+                {
+                    nextPromise = CALL_FUNCTION(threadContext,
+                        promiseResolve, Js::CallInfo(CallFlags_Value, 2),
+                        constructor,
+                        nextValue);
+                }
+                END_SAFE_REENTRANT_CALL;
+
+
+                JavascriptPromiseResolveOrRejectFunctionAlreadyResolvedWrapper* alreadyCalledWrapper = RecyclerNewStructZ(scriptContext->GetRecycler(), JavascriptPromiseResolveOrRejectFunctionAlreadyResolvedWrapper);
+                alreadyCalledWrapper->alreadyResolved = false;
+
+                // j. Let steps be the algorithm steps defined in Promise.any Reject Element Functions.
+                // k. Let rejectElement be ! CreateBuiltinFunction(steps, << [[AlreadyCalled]], [[Index]], [[Errors]], [[Capability]], [[RemainingElements]] >> ).
+                // p. Set rejectElement.[[RemainingElements]] to remainingElementsCount.
+                Var rejectElement = library->CreatePromiseAnyRejectElementFunction(EntryAnyRejectElementFunction, index, errors, promiseCapability, remainingElementsWrapper, alreadyCalledWrapper);
+
+                // q. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] + 1.
+                remainingElementsWrapper->remainingElements++;
+
+                // r. Perform ? Invoke(nextPromise, "then", << resultCapability.[[Resolve]], rejectElement >> ).
+                RecyclableObject* nextPromiseObject;
+                if (!JavascriptConversion::ToObject(nextPromise, scriptContext, &nextPromiseObject))
+                {
+                    JavascriptError::ThrowTypeError(scriptContext, JSERR_NeedObject);
+                }
+                Var thenVar = JavascriptOperators::GetProperty(nextPromiseObject, Js::PropertyIds::then, scriptContext);
+                if (!JavascriptConversion::IsCallable(thenVar))
+                {
+                    JavascriptError::ThrowTypeError(scriptContext, JSERR_NeedFunction);
+                }
+
+                RecyclableObject* thenFunc = UnsafeVarTo<RecyclableObject>(thenVar);
+
+                BEGIN_SAFE_REENTRANT_CALL(threadContext)
+                {
+                    CALL_FUNCTION(scriptContext->GetThreadContext(),
+                        thenFunc, Js::CallInfo(CallFlags_Value, 3),
+                        nextPromiseObject,
+                        promiseCapability->GetResolve(),
+                        rejectElement);
+                }
+                END_SAFE_REENTRANT_CALL;
+
+                // s.Increase index by 1.
+                index++;
+            });
+
+            // 7.d. If next is false, then
+            // 7.d.i. Set iteratorRecord.[[Done]] to true.
+            // 7.d.ii. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1.
+            remainingElementsWrapper->remainingElements--;
+            // 7.d.iii. If remainingElementsCount.[[Value]] is 0, then
+            if (remainingElementsWrapper->remainingElements == 0)
+            {
+                // 7.d.iii.1 Let error be a newly created AggregateError object.
+                JavascriptError* pError = library->CreateAggregateError();
+                JavascriptError::SetErrorsList(pError, errors, scriptContext);
+                JavascriptError::SetErrorMessage(pError, JSERR_PromiseAllRejected, _u(""), scriptContext);
+                JavascriptExceptionOperators::Throw(pError, scriptContext);
+            }
+        }
+        catch (const JavascriptException& err)
+        {
+            // 8. If result is an abrupt completion, then
+            //   a. If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result).
+            //   b. IfAbruptRejectPromise(result, promiseCapability).
+            JavascriptExceptionObject* exception = err.GetAndClear();
+            TryRejectWithExceptionObject(exception, promiseCapability->GetReject(), scriptContext);
+        }
+
+        return promiseCapability->GetPromise();
+    }
+
+    Var JavascriptPromise::EntryAnyRejectElementFunction(RecyclableObject* function, CallInfo callInfo, ...)
+    {
+        ScriptContext* scriptContext = function->GetScriptContext();
+        PROBE_STACK(scriptContext, Js::Constants::MinStackDefault);
+        ARGUMENTS(args, callInfo);
+        Assert(!(callInfo.Flags & CallFlags_New));
+
+        JavascriptLibrary* library = scriptContext->GetLibrary();
+        Var undefinedVar = library ->GetUndefined();
+        Var x = args.Info.Count > 1 ? args[1] : undefinedVar;
+
+
+        // 1. Let F be the active function object.
+        JavascriptPromiseAnyRejectElementFunction* anyRejectElementFunction = VarTo<JavascriptPromiseAnyRejectElementFunction>(function);
+
+        // 2. Let alreadyCalled be F. [[AlreadyCalled]].
+        // 3. If alreadyCalled. [[Value]] is true, return undefined.
+        if (anyRejectElementFunction->IsAlreadyCalled())
+        {
+            return undefinedVar;
+        }
+
+        // 4. Set alreadyCalled.[[Value]] to true.
+        anyRejectElementFunction->SetAlreadyCalled(true);
+
+        // 5. Let index be F.[[Index]].
+        uint32 index = anyRejectElementFunction->GetIndex();
+
+        // 6. Let errors be F.[[Errors]].
+        JavascriptArray* errors = anyRejectElementFunction->GetValues();
+
+
+        // 7. Let promiseCapability be F.[[Capability]].
+        JavascriptPromiseCapability* promiseCapability = anyRejectElementFunction->GetCapabilities();
+
+        // 9. Set errors[index] to x.
+        errors->DirectSetItemAt(index, x);
+
+        // 8. Let remainingElementsCount be F.[[RemainingElements]].
+        // 10. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1.
+        // 11. If remainingElementsCount.[[Value]] is 0, then
+        if (anyRejectElementFunction->DecrementRemainingElements() == 0)
+        {
+            // a. Let error be a newly created AggregateError object.
+            JavascriptError* pError = library->CreateAggregateError();
+            // b. Perform ! DefinePropertyOrThrow(error, "errors", Property Descriptor { [[Configurable]]: true, [[Enumerable]]: false, [[Writable]]: true, [[Value]]: ! CreateArrayFromList(errors) }).
+            JavascriptError::SetErrorsList(pError, errors, scriptContext);
+            JavascriptError::SetErrorMessage(pError, JSERR_PromiseAllRejected, _u(""), scriptContext);
+
+            // c. Return ? Call(promiseCapability.[[Reject]], undefined, << error >> ).
+            return TryCallResolveOrRejectHandler(promiseCapability->GetReject(), pError, scriptContext);
+        }
+
+        return undefinedVar;
+    }
+
     Var JavascriptPromise::EntryAllSettled(RecyclableObject* function, CallInfo callInfo, ...)
     {
         PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
@@ -2169,6 +2368,68 @@ namespace Js
     }
 #endif
 
+    JavascriptPromiseAnyRejectElementFunction::JavascriptPromiseAnyRejectElementFunction(DynamicType* type)
+        : JavascriptPromiseAllResolveElementFunction(type), alreadyCalledWrapper(nullptr)
+    { }
+
+    JavascriptPromiseAnyRejectElementFunction::JavascriptPromiseAnyRejectElementFunction(DynamicType* type, FunctionInfo* functionInfo, uint32 index, JavascriptArray* values, JavascriptPromiseCapability* capabilities, JavascriptPromiseAllResolveElementFunctionRemainingElementsWrapper* remainingElementsWrapper, JavascriptPromiseResolveOrRejectFunctionAlreadyResolvedWrapper* alreadyCalledWrapper)
+        : JavascriptPromiseAllResolveElementFunction(type, functionInfo, index, values, capabilities, remainingElementsWrapper), alreadyCalledWrapper(alreadyCalledWrapper)
+    { }
+
+#if ENABLE_TTD
+    void JavascriptPromiseAnyRejectElementFunction::MarkVisitKindSpecificPtrs(TTD::SnapshotExtractor* extractor)
+    {
+        TTDAssert(this->capabilities != nullptr && this->remainingElementsWrapper != nullptr && this->alreadyCalledWrapper != nullptr && this->values != nullptr, "Don't think these can be null");
+
+        this->capabilities->MarkVisitPtrs(extractor);
+        extractor->MarkVisitVar(this->values);
+    }
+
+    TTD::NSSnapObjects::SnapObjectType JavascriptPromiseAnyRejectElementFunction::GetSnapTag_TTD() const
+    {
+        return TTD::NSSnapObjects::SnapObjectType::SnapPromiseAnyRejectElementFunctionObject;
+    }
+
+    void JavascriptPromiseAnyRejectElementFunction::ExtractSnapObjectDataInto(TTD::NSSnapObjects::SnapObject* objData, TTD::SlabAllocator& alloc)
+    {
+        TTD::NSSnapObjects::SnapPromiseAllResolveElementFunctionInfo* sprai = alloc.SlabAllocateStruct<TTD::NSSnapObjects::SnapPromiseAllResolveElementFunctionInfo>();
+
+        JsUtil::List<TTD_PTR_ID, HeapAllocator> depOnList(&HeapAllocator::Instance);
+        this->capabilities->ExtractSnapPromiseCapabilityInto(&sprai->Capabilities, depOnList, alloc);
+
+        sprai->Index = this->index;
+        sprai->RemainingElementsWrapperId = TTD_CONVERT_PROMISE_INFO_TO_PTR_ID(this->remainingElementsWrapper);
+        sprai->RemainingElementsValue = this->remainingElementsWrapper->remainingElements;
+
+        sprai->Values = TTD_CONVERT_VAR_TO_PTR_ID(this->values);
+        depOnList.Add(sprai->Values);
+
+        sprai->AlreadyCalled = this->alreadyCalled;
+
+        uint32 depOnCount = depOnList.Count();
+        TTD_PTR_ID* depOnArray = alloc.SlabAllocateArray<TTD_PTR_ID>(depOnCount);
+
+        for (uint32 i = 0; i < depOnCount; ++i)
+        {
+            depOnArray[i] = depOnList.Item(i);
+        }
+
+        TTD::NSSnapObjects::StdExtractSetKindSpecificInfo<TTD::NSSnapObjects::SnapPromiseAllResolveElementFunctionInfo*, TTD::NSSnapObjects::SnapObjectType::SnapPromiseAllResolveElementFunctionObject>(objData, sprai, alloc, depOnCount, depOnArray);
+    }
+#endif
+
+    template <> bool VarIsImpl<JavascriptPromiseAnyRejectElementFunction>(RecyclableObject* obj)
+    {
+        if (VarIs<JavascriptFunction>(obj))
+        {
+            return VirtualTableInfo<JavascriptPromiseAnyRejectElementFunction>::HasVirtualTable(obj)
+                || VirtualTableInfo<CrossSiteObject<JavascriptPromiseAnyRejectElementFunction>>::HasVirtualTable(obj);
+        }
+
+        return false;
+    }
+
+
     JavascriptPromiseAllResolveElementFunction::JavascriptPromiseAllResolveElementFunction(DynamicType* type)
         : RuntimeFunction(type, &Js::JavascriptPromise::EntryInfo::AllResolveElementFunction), index(0), values(nullptr), capabilities(nullptr), remainingElementsWrapper(nullptr), alreadyCalled(false)
     { }

+ 28 - 0
lib/Runtime/Library/JavascriptPromise.h

@@ -1,5 +1,6 @@
 //-------------------------------------------------------------------------------------------------------
 // Copyright (C) Microsoft. All rights reserved.
+// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
 // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
 //-------------------------------------------------------------------------------------------------------
 #pragma once
@@ -362,6 +363,7 @@ namespace Js
             static FunctionInfo Then;
             static FunctionInfo Finally;
             static FunctionInfo AllSettled;
+            static FunctionInfo Any;
 
             static FunctionInfo Identity;
             static FunctionInfo Thrower;
@@ -372,6 +374,7 @@ namespace Js
             static FunctionInfo CapabilitiesExecutorFunction;
             static FunctionInfo AllResolveElementFunction;
             static FunctionInfo AllSettledResolveOrRejectElementFunction;
+            static FunctionInfo AnyRejectElementFunction;
 
             static FunctionInfo GetterSymbolSpecies;
         };
@@ -388,6 +391,7 @@ namespace Js
         static Var EntryThen(RecyclableObject* function, CallInfo callInfo, ...);
         static Var EntryFinally(RecyclableObject* function, CallInfo callInfo, ...);
         static Var EntryAllSettled(RecyclableObject* function, CallInfo callInfo, ...);
+        static Var EntryAny(RecyclableObject* function, CallInfo callInfo, ...);
 
         static Var EntryThunkFinallyFunction(RecyclableObject* function, CallInfo callInfo, ...);
         static Var EntryThenFinallyFunction(RecyclableObject* function, CallInfo callInfo, ...);
@@ -399,6 +403,7 @@ namespace Js
         static Var EntryThrowerFunction(RecyclableObject* function, CallInfo callInfo, ...);
         static Var EntryAllResolveElementFunction(RecyclableObject* function, CallInfo callInfo, ...);
         static Var EntryAllSettledResolveOrRejectElementFunction(RecyclableObject* function, CallInfo callInfo, ...);
+        static Var EntryAnyRejectElementFunction(RecyclableObject* function, CallInfo callInfo, ...);
 
         static Var EntryGetterSymbolSpecies(RecyclableObject* function, CallInfo callInfo, ...);
 
@@ -485,4 +490,27 @@ namespace Js
     {
         return Js::JavascriptOperators::GetTypeId(obj) == TypeIds_Promise;
     }
+
+    class JavascriptPromiseAnyRejectElementFunction : public JavascriptPromiseAllResolveElementFunction {
+    protected:
+        DEFINE_VTABLE_CTOR(JavascriptPromiseAnyRejectElementFunction, JavascriptPromiseAllResolveElementFunction);
+        DEFINE_MARSHAL_OBJECT_TO_SCRIPT_CONTEXT(JavascriptPromiseAnyRejectElementFunction);
+
+    public:
+        JavascriptPromiseAnyRejectElementFunction(DynamicType* type);
+        JavascriptPromiseAnyRejectElementFunction(DynamicType* type, FunctionInfo* functionInfo, uint32 index, JavascriptArray* values, JavascriptPromiseCapability* capabilities, JavascriptPromiseAllResolveElementFunctionRemainingElementsWrapper* remainingElementsWrapper, JavascriptPromiseResolveOrRejectFunctionAlreadyResolvedWrapper* alreadyCalledWrapper);
+
+    private:
+        Field(JavascriptPromiseResolveOrRejectFunctionAlreadyResolvedWrapper*) alreadyCalledWrapper;
+
+#if ENABLE_TTD
+    public:
+        virtual void MarkVisitKindSpecificPtrs(TTD::SnapshotExtractor* extractor) override;
+
+        virtual TTD::NSSnapObjects::SnapObjectType GetSnapTag_TTD() const override;
+        virtual void ExtractSnapObjectDataInto(TTD::NSSnapObjects::SnapObject* objData, TTD::SlabAllocator& alloc) override;
+#endif
+    };
+
+    template <> bool VarIsImpl<JavascriptPromiseAnyRejectElementFunction>(RecyclableObject* obj);
 }

+ 3 - 0
lib/Runtime/Runtime.h

@@ -1,5 +1,6 @@
 //-------------------------------------------------------------------------------------------------------
 // Copyright (C) Microsoft. All rights reserved.
+// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
 // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
 //-------------------------------------------------------------------------------------------------------
 #pragma once
@@ -123,6 +124,7 @@ namespace Js
     class JavascriptPromiseResolveThenableTaskFunction;
     class JavascriptPromiseAllResolveElementFunction;
     class JavascriptPromiseAllSettledResolveOrRejectElementFunction;
+    class JavascriptPromiseAnyRejectElementFunction;
     struct JavascriptPromiseAllResolveElementFunctionRemainingElementsWrapper;
     struct JavascriptPromiseResolveOrRejectFunctionAlreadyResolvedWrapper;
     class JavascriptAsyncSpawnExecutorFunction;
@@ -162,6 +164,7 @@ namespace Js
 
     struct RestrictedErrorStrings;
     class JavascriptError;
+    class JavascriptAggregateError;
     class RecyclableObject;
     class JavascriptRegExp;
     class JavascriptRegularExpressionResult;

+ 364 - 0
test/Error/aggregate_error.js

@@ -0,0 +1,364 @@
+//-------------------------------------------------------------------------------------------------------
+// Copyright (C) Microsoft Corporation and contributors. All rights reserved.
+// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
+//-------------------------------------------------------------------------------------------------------
+
+WScript.LoadScriptFile("..\\UnitTestFramework\\UnitTestFramework.js");
+
+var tests = [
+   {
+       name: "AggregateError Prototype and Constructor Shape",
+       body: function ()
+       {
+            assert.areEqual(AggregateError, AggregateError.prototype.constructor);
+            assert.isFalse(AggregateError.prototype.hasOwnProperty("errors"));
+            assert.areEqual("", AggregateError.prototype.message);
+            assert.areEqual("AggregateError", AggregateError.prototype.name);
+            assert.areEqual("object", typeof AggregateError.prototype);
+            assert.areEqual(Error.prototype, Object.getPrototypeOf(AggregateError.prototype));
+            assert.areEqual("AggregateError", AggregateError.name);
+            assert.areEqual(2, AggregateError.length);
+            assert.areEqual("function", typeof AggregateError);
+            var proto = Object.getPrototypeOf(AggregateError);
+            assert.areEqual(Error, proto);
+            var obj = new AggregateError([]);
+            assert.areEqual(AggregateError.prototype, Object.getPrototypeOf(obj));
+        }
+    },
+    {
+        name: "Failures in the iterable errors argument to list",
+        body: function ()
+        {
+            class TestError extends Error {}
+
+            // Iterator that throws with getter
+            var case1 = {
+                get [Symbol.iterator]() { throw new TestError(); }
+            };
+            assert.throws(() => { new AggregateError(case1); }, TestError);
+
+            // Iterator with no 'next' method
+            var case2 = {
+                get [Symbol.iterator]() { return {}; }
+            };
+            assert.throws(() => { new AggregateError(case2); }, TypeError);
+
+            // Iterator that throws with property
+            var case3 = {
+                [Symbol.iterator]() { throw new TestError(); }
+            };
+            assert.throws(() => { new AggregateError(case3); }, TestError);
+
+            // Iterator with string
+            var case4 = {
+                [Symbol.iterator]() { return "a string"; }
+            };
+            assert.throws(() => { new AggregateError(case4); }, TypeError);
+
+            // Iterator with undefined
+            var case5 = {
+                [Symbol.iterator]() { return undefined; }
+            };
+            assert.throws(() => { new AggregateError(case5); }, TypeError);
+
+            // Iterator that throws in 'next' method
+            var case6 = {
+                [Symbol.iterator]() {
+                    return {
+                        get next() {
+                            throw new TestError();
+                        }
+                    }
+                }
+            };
+            assert.throws(() => { new AggregateError(case6); }, TestError);
+
+            // Iterator with empty object returns in 'next' method
+            var case7 = {
+                [Symbol.iterator]() {
+                    return {
+                        get next() { return {}; }
+                    }
+                }
+            };
+            assert.throws(() => { new AggregateError(case7); }, TypeError);
+
+            // Iterator throws in 'next' method
+            var case8 = {
+                [Symbol.iterator]() {
+                    return {
+                        next() { throw new TestError(); }
+                    }
+                }
+            };
+            assert.throws(() => { new AggregateError(case8); }, TestError);
+
+            // Iterator with undefined returns in 'next' method
+            var case9 = {
+                [Symbol.iterator]() {
+                    return {
+                        next() {
+                            return undefined;
+                        }
+                    }
+                }
+            };
+            assert.throws(() => { new AggregateError(case9); }, TypeError);
+
+            // Iterator with string returns in 'next' method
+            var case10 = {
+                [Symbol.iterator]() {
+                    return {
+                        next() { return "a string"; }
+                    }
+                }
+            };
+            assert.throws(() => { new AggregateError(case10); }, TypeError);
+
+            // Iterator with string returns in 'done'
+            var case11 = {
+                [Symbol.iterator]() {
+                    return {
+                        next() {
+                            return {
+                                get done() { throw new TestError(); }
+                            };
+                        }
+                    }
+                }
+            };
+            assert.throws(() => { new AggregateError(case11); }, TestError);
+        }
+    },
+    {
+        name: "Failures in the iterable errors argument to list with non-objects",
+        body: function ()
+        {
+            const values = [
+                undefined,
+                null,
+                42,
+                false,
+                true
+            ];
+            for (const value of values) {
+                assert.throws(() => new AggregateError(value), TypeError);
+            }
+
+            var o = new AggregateError("string");
+            assert.areEqual(o.errors, "string".split(""));
+        }
+    },
+    {
+        name: "Iterable errors argument to list",
+        body: function ()
+        {
+            var count = 0;
+            var values = [];
+            var obj = {
+                [Symbol.iterator]() {
+                    return {
+                        next() {
+                            count += 1;
+                            return {
+                                done: count === 3,
+                                get value() {
+                                    values.push(count)
+                                }
+                            };
+                        }
+                    };
+                }
+            };
+            new AggregateError(obj);
+            assert.areEqual(3, count)
+            assert.areEqual([1, 2], values)
+        }
+    },
+    {
+        name: "message method prop",
+        body: function ()
+        {
+            var obj = new AggregateError([], "42");
+            assert.areEqual("42", obj.message);
+        }
+    },
+    {
+        name: "message tostring abrupt symbol",
+        body: function ()
+        {
+            class TestError extends Error {}
+
+            var case1 = Symbol();
+            assert.throws(() => {
+                new AggregateError([], case1);
+            }, TypeError)
+
+            var case2 = {
+                [Symbol.toPrimitive]() {
+                    return Symbol();
+                },
+                toString() {
+                    throw new TestError();
+                },
+                valueOf() {
+                    throw new TestError();
+                }
+            };
+
+            assert.throws(() => {
+                new AggregateError([], case2);
+            }, TypeError)
+        }
+    },
+    {
+        name: "message tostring abrupt",
+        body: function ()
+        {
+            class TestError extends Error { }
+
+            var case1 = {
+                [Symbol.toPrimitive]() {
+                    throw new TestError();
+                },
+                toString() {
+                    throw "toString called";
+                },
+                valueOf() {
+                    throw "valueOf called";
+                }
+            };
+
+            assert.throws(() => {
+                new AggregateError([], case1);
+            }, TestError);
+            var case2 = {
+                [Symbol.toPrimitive]: undefined,
+                toString() {
+                    throw new TestError();
+                },
+                valueOf() {
+                    throw "valueOf called";
+                }
+            };
+            assert.throws(() => {
+                new AggregateError([], case2);
+            }, TestError);
+
+            var case3 = {
+                [Symbol.toPrimitive]: undefined,
+                toString: undefined,
+                valueOf() {
+                    throw new TestError();
+                }
+            };
+            assert.throws(() => {
+                new AggregateError([], case3);
+            }, TestError);
+        }
+    },
+    {
+        name: "message undefined no prop",
+        body: function ()
+        {
+            var case1 = new AggregateError([], undefined);
+            assert.areEqual(false, Object.prototype.hasOwnProperty.call(case1, "message"))
+
+            var case2 = new AggregateError([]);
+            assert.areEqual(false, Object.prototype.hasOwnProperty.call(case2, "message"))
+        }
+    },
+    {
+        name: "newtarget is undefined",
+        body: function ()
+        {
+            var obj = AggregateError([], "");
+
+            assert.areEqual(AggregateError.prototype, Object.getPrototypeOf(obj));
+            assert.isTrue(obj instanceof AggregateError);
+        }
+    },
+    {
+        name: "newtarget proto custom",
+        body: function ()
+        {
+            var custom = { x: 42 };
+            var newt = new Proxy(function () { }, {
+                get(t, p) {
+                    if (p === "prototype") {
+                        return custom;
+                    }
+
+                    return t[p];
+                }
+            });
+
+            var obj = Reflect.construct(AggregateError, [[]], newt);
+            assert.areEqual(custom, Object.getPrototypeOf(obj));
+            assert.areEqual(42, obj.x);
+        }
+    },
+    {
+        name: "newtarget proto fallback",
+        body: function ()
+        {
+            const values = [
+                undefined,
+                null,
+                42,
+                false,
+                true,
+                Symbol(),
+                "string",
+                AggregateError.prototype,
+            ];
+
+            const NewTarget = new Function();
+
+            for (const value of values) {
+                const NewTargetProxy = new Proxy(NewTarget, {
+                    get(t, p) {
+                        if (p === "prototype") {
+                            return value;
+                        }
+                        return t[p];
+                    }
+                });
+
+                const error = Reflect.construct(AggregateError, [[]], NewTargetProxy);
+                assert.areEqual(AggregateError.prototype, Object.getPrototypeOf(error));
+            }
+        }
+    },
+    {
+        name: "order of args evaluation",
+        body: function () {
+            let sequence = [];
+            const message = {
+                toString() {
+                    sequence.push(1);
+                    return "";
+                }
+            };
+            const errors = {
+                [Symbol.iterator]() {
+                    sequence.push(2);
+                    return {
+                        next() {
+                            sequence.push(3);
+                            return {
+                                done: true
+                            };
+                        }
+                    };
+                }
+            };
+
+            new AggregateError(errors, message);
+            assert.areEqual(3, sequence.length);
+            assert.areEqual([1, 2, 3], sequence);
+        }
+    }
+];
+testRunner.runTests(tests, { verbose: WScript.Arguments[0] != "summary" });

+ 11 - 6
test/Error/error_cause.js

@@ -7,15 +7,17 @@
 WScript.LoadScriptFile("..\\UnitTestFramework\\UnitTestFramework.js");
 
 
-function makeTestsFor(ErrorConstructor) {
-    const name = ErrorConstructor.name;
+function makeTestsFor(ErrorConstructor, options) {
+    const name = options ? options.getNameOfConstructor() : ErrorConstructor.name;
+    const prototype = options ? options.getPrototypeOfConstructor() : ErrorConstructor.prototype;
+    const rawConstructor = options ? options.rawConstructor : ErrorConstructor
     const message = "Test message";
     const o = {};
     return [
         {
             name: `"cause" in ${ name }.prototype.cause === false`,
             body: function () {
-                assert.isFalse("cause" in ErrorConstructor.prototype, `Cause property must not exist in ${ name }.prototype`);
+                assert.isFalse("cause" in prototype, `Cause property must not exist in ${ name }.prototype`);
             }
         },
         {
@@ -74,7 +76,7 @@ function makeTestsFor(ErrorConstructor) {
                         throw ErrorConstructor();
                     }
                 }
-                assert.throws(() => ErrorConstructor(message, options), ErrorConstructor);
+                assert.throws(() => ErrorConstructor(message, options), rawConstructor);
             }
         },
         {
@@ -123,8 +125,11 @@ const tests = [
     ...makeTestsFor(SyntaxError),
     ...makeTestsFor(RangeError),
     ...makeTestsFor(EvalError),
-    // TODO: Uncomment when #6301 is landed
-    // ...makeTestsFor(AggregateError)
+    ...makeTestsFor((message, options) => AggregateError([], message, options), {
+        getNameOfConstructor: () => AggregateError.name,
+        getPrototypeOfConstructor: () => AggregateError.prototype,
+        rawConstructor: AggregateError
+    })
 ];
 
 testRunner.runTests(tests, { verbose: WScript.Arguments[0] != "summary" });

+ 6 - 0
test/Error/rlexe.xml

@@ -6,6 +6,12 @@
       <compile-flags>-args summary -endargs</compile-flags>
     </default>
   </test>
+  <test>
+    <default>
+      <files>aggregate_error.js</files>
+      <compile-flags>-args summary -endargs</compile-flags>
+    </default>
+  </test>
   <test>
     <default>
       <files>errorProps.js</files>

+ 39 - 1
test/es6/ES6Promise.js

@@ -1,5 +1,6 @@
 //-------------------------------------------------------------------------------------------------------
-// Copyright (C) Microsoft. All rights reserved.
+// Copyright (C) Microsoft Corporation and contributors. All rights reserved.
+// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
 // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
 //-------------------------------------------------------------------------------------------------------
 
@@ -43,6 +44,13 @@ var tests = [
             assert.areEqual('function', typeof descriptor.value, "typeof Promise.allSettled === 'function'");
             assert.areEqual(1, Promise.allSettled.length, "Promise.allSettled.length === 1");
 
+            var descriptor = Object.getOwnPropertyDescriptor(Promise, 'any');
+            assert.isTrue(descriptor.writable, "Promise.any.writable === true");
+            assert.isFalse(descriptor.enumerable, "Promise.any.enumerable === false");
+            assert.isTrue(descriptor.configurable, "Promise.any.configurable === true");
+            assert.areEqual('function', typeof descriptor.value, "typeof Promise.any === 'function'");
+            assert.areEqual(1, Promise.any.length, "Promise.any.length === 1");
+
             var descriptor = Object.getOwnPropertyDescriptor(Promise, 'race');
             assert.isTrue(descriptor.writable, "Promise.race.writable === true");
             assert.isFalse(descriptor.enumerable, "Promise.race.enumerable === false");
@@ -221,6 +229,19 @@ var tests = [
             assert.throws(function() { Promise.allSettled.call(Math.sin); }, TypeError, "Promise.allSettled throws when this parameter is a non-constructor", "Function expected");
         }
     },
+    {
+        name: "Promise.any throwing behavior",
+        body: function () {
+            assert.throws(function() { Promise.any.call(); }, TypeError, "Promise.any throws when called with no this parameter", "Function expected");
+            assert.throws(function() { Promise.any.call(undefined); }, TypeError, "Promise.any throws when called when this parameter is undefined", "Function expected");
+            assert.throws(function() { Promise.any.call(null); }, TypeError, "Promise.any throws when called when this parameter is null", "Function expected");
+            assert.throws(function() { Promise.any.call({}); }, TypeError, "Promise.any throws when called when this parameter is non-callable", "Function expected");
+            assert.throws(function() { Promise.any.call(Math.sin); }, TypeError, "Promise.any throws when this parameter is a non-constructor", "Function expected");
+            assert.throws(function() { Promise.any.call(5); }, TypeError, "Promise.any throws when this parameter is a integer", "Function expected");
+            assert.throws(function() { Promise.any.call(5.0); }, TypeError, "Promise.any throws when this parameter is a float", "Function expected");
+            assert.throws(function() { Promise.any.call("literal"); }, TypeError, "Promise.any throws when this parameter is a string literal", "Function expected");
+        }
+    },
     {
         name: "Promise.prototype.then to access constructor through [@@species]",
         body: function () {
@@ -323,6 +344,22 @@ var tests = [
             assert.areEqual(3, calledNext, "Promise.allSettled should use the iterator protocol, and next should be cached");
         }
     },
+    {
+        name: "Promise.any uses iterator next correctly",
+        body: function () {
+            let calledNext = 0;
+            const bar = {
+                [Symbol.iterator]() { return this; },
+                next () {
+                    this.next = function (){ throw new Error ("Next should have been cached so this should not be called") };
+                    return {value : Promise.resolve(0), done : (++calledNext > 2)}
+                }
+            }
+
+            Promise.any(bar);
+            assert.areEqual(3, calledNext, "Promise.any should use the iterator protocol, and next should be cached");
+        }
+    },
     {
         name: "Promise.race uses iterator next correctly",
         body: function () {
@@ -559,6 +596,7 @@ var tests = [
             assert.isTrue(finallyPromise instanceof MyPromise, "Subclass of Promise is returned from Promise.prototype.finally called with subclass of Promise object as this");
             assert.isTrue(MyPromise.race([]) instanceof MyPromise, "Subclass of Promise inherits Promise.race which uses 'this' argument as constructor for return object");
             assert.isTrue(MyPromise.all([]) instanceof MyPromise, "Subclass of Promise inherits Promise.all which uses 'this' argument as constructor for return object");
+            assert.isTrue(MyPromise.any([]) instanceof MyPromise, "Subclass of Promise inherits Promise.any which uses 'this' argument as constructor for return object");
             assert.isTrue(MyPromise.resolve(42) instanceof MyPromise, "Subclass of Promise inherits Promise.resolve which uses 'this' argument as constructor for return object");
             assert.isTrue(MyPromise.reject(42) instanceof MyPromise, "Subclass of Promise inherits Promise.reject which uses 'this' argument as constructor for return object");
         }

+ 81 - 1
test/es6/ES6PromiseAsync.baseline

@@ -88,6 +88,35 @@ Executing test #74 - Promise.race gets the constructor's resolve function only o
 Test #74 - get constructor resolve
 Test #74 - constructor resolve called
 Test #74 - constructor resolve called
+Executing test #75 - Promise.any gets the constructor's resolve function only once
+Test #75 - get constructor resolve
+Test #75 - constructor resolve called
+Test #75 - constructor resolve called
+Executing test #76 - Promise.any with an object containing a non-function iterator property
+Executing test #77 - Promise.any with this argument missing the resolve function
+Executing test #78 - Promise.any with this argument resolve function returning a non-object
+Executing test #79 - Promise.any with this argument resolve function returning an object with no then function
+Executing test #80 - Promise.any with an object containing an iterator that throws
+Executing test #81 - Promise.any still returns a rejected promise if anything throws while iterating, even if resolved promises are encountered
+Executing test #82 - Promise.any fulfills with the same value as the first encountered resolved promise
+Executing test #83 - Promise.any fulfills with the same value as the first encountered resolved promise (promises complete async)
+Executing test #84 - Promise.any fulfills with the same value as the first encountered rejected promise (promises complete async)
+Executing test #85 - Promise.any should wait until one resolve
+Executing test #86 - Promise.any should wait until all reject
+Executing test #87 - Promise.any should not call return
+Test #87 - get iterator called
+Test #87 - iterator next called: 2
+Test #87 - iterator next called: 1
+Test #87 - iterator next throw
+Executing test #88 - Promise.any should call return once
+Test #88 - get iterator called
+Test #88 - iterator next called: 2
+Test #88 - iterator return called
+Executing test #89 - Promise.any should throw TypeError if resolve not a function
+Test #89 - resolve getter called
+Executing test #90 - Promise.any passes each element in it's argument to Promise.resolve
+Executing test #91 - Promise.any should failure with empty list
+Executing test #92 - Promise.any should reject with aggregate error and errors
 
 Completion Results:
 Test #1 - Success handler called with result = basic:success
@@ -135,6 +164,38 @@ Test #56 - Success finally handler called for rejected promise without value
 Test #63 - val is 0(Expect 0)
 Test #66 - Success - []
 Test #68 - Failed - {}
+Test #76 - Catch handler #1 called with err = TypeError: Function expected
+Test #76 - Catch handler #1 called with err.message = Function expected
+Test #77 - Catch handler #1 called with err = TypeError: Function expected
+Test #77 - Catch handler #1 called with err.message = Function expected
+Test #78 - Catch handler #1 called with err = TypeError: Object expected
+Test #78 - Catch handler #1 called with err.message = Object expected
+Test #79 - Catch handler #1 called with err = TypeError: Function expected
+Test #79 - Catch handler #1 called with err.message = Function expected
+Test #80 - Catch handler #1 called with err = TypeError: failure inside iterator
+Test #80 - Catch handler #1 called with err.message = failure inside iterator
+Test #81 - Error handler #1 called with err = TypeError: failure inside iterator
+Test #81 - Error handler #1 called with err.message = failure inside iterator
+Test #87 - Error handler #1 called with err = Error: BANG
+Test #88 - Error handler #1 called with err = Error
+Test #89 - Error handler #1 called with err = TypeError: Function expected
+Test #90 - Error handler #1 called with err = Error
+Test #90 - Error handler #1 called with err.message = 
+Test #91 - Error handler #1 called with err = AggregateError: Promise.any all promises rejected.
+Test #91 - Error handler #1 called with err.errors = []
+Test #91 - Error handler #1 called with err.message = Promise.any all promises rejected.
+Test #92 - Error handler #1 called with err = AggregateError: Promise.any all promises rejected.
+Test #92 - Error handler #1 called with err.message = "Promise.any all promises rejected."
+Test #92 - Error handler #1 called with err.name = AggregateError
+Test #92 - Error handler #1 called with err.errors = []
+Test #92 - Error handler #2 called with err = Error
+Test #92 - Error handler #2 called with err.message = ""
+Test #92 - Error handler #2 called with err.name = Error
+Test #92 - Error handler #2 called with err.errors = undefined
+Test #92 - Error handler #3 called with err = Error
+Test #92 - Error handler #3 called with err.message = ""
+Test #92 - Error handler #3 called with err.name = Error
+Test #92 - Error handler #3 called with err.errors = undefined
 Test #6 - Error handler #2 called with err = thenable.get:error!
 Test #8 - Error handler #2 called with err = success.throw:error
 Test #9 - Error handler #2 called with err = error.throw:error
@@ -158,7 +219,6 @@ Test #38 - p1 success: p1
 Test #38 - p2 success: p2
 Test #38 - p3 success: p3
 Test #39 - Success handler #1 called with result = success value 1,42,TypeError: an error
-Test #41 - Promise.resolve call nested within thenable.then = nested Promise.resolve call
 Test #47 - Success handler #1b called with result = '3' (isArray = false) (fulfillCalled = false)
 Test #48 - Error handler #1 called with err = 2
 Test #59 - Success - Rejected status and value passed through finally with not callable argument
@@ -173,6 +233,19 @@ Test #68 - p2 success: p2
 Test #68 - p3 success: p3
 Test #69 - p1 success: p1
 Test #70 - Success - [{"status":"fulfilled","value":"p1"},{"status":"fulfilled","value":"p2"}]
+Test #82 - Success handler #1 called with result = first promise
+Test #83 - p1 success: p1
+Test #83 - p2 success: p2
+Test #83 - p3 failure: p3
+Test #84 - p1 failure: p1
+Test #84 - p2 success: p2
+Test #84 - p3 success: p3
+Test #85 - 2 failure: 2
+Test #85 - 3 success: 3
+Test #85 - 4 failure: 4
+Test #86 - 2 failure: 2
+Test #86 - 3 failure: 3
+Test #86 - 4 failure: 4
 Test #7 - Error handler #2 called with err = thenable.call:error!
 Test #13 - Catch handler #2 called with err = error2
 Test #15 - Catch handler #1 called with err = failure
@@ -188,6 +261,13 @@ Test #65 - Success - [{"status":"rejected","reason":"p1"},{"status":"rejected","
 Test #69 - Success: [{"status":"fulfilled","value":"p1"}]
 Test #69 - p1 success: p2
 Test #69 - p1 failure: e2
+Test #83 - Success handler #1 called with result = p1
+Test #84 - Success handler #1 called with result = p2
+Test #85 - Success handler #1 called with result = 3
+Test #86 - Error handler #1 called with err = AggregateError: Promise.any all promises rejected.
+Test #86 - Error handler #1 called with err.message = "Promise.any all promises rejected."
+Test #86 - Error handler #1 called with err.name = AggregateError
+Test #86 - Error handler #1 called with err.errors = [1,2,3,4,5]
 Test #4 - Success handler #2 called with result = chain:success2
 Test #57 - Success - Rejected status and value passed through finally
 Test #58 - Success - Resolved status and value passed through finally

+ 415 - 1
test/es6/ES6PromiseAsync.js

@@ -1,5 +1,6 @@
 //-------------------------------------------------------------------------------------------------------
-// Copyright (C) Microsoft. All rights reserved.
+// Copyright (C) Microsoft Corporation and contributors. All rights reserved.
+// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
 // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
 //-------------------------------------------------------------------------------------------------------
 
@@ -1400,6 +1401,419 @@ var tests = [
 
             Promise.race.call(FakePromise, [1, 2]);
         }
+    },
+    {
+        name: "Promise.any gets the constructor's resolve function only once",
+        body: function(index) {
+            function FakePromise(fn) {
+                fn(function() {}, function() {});
+                this.then = function(onResolve, onReject) {};
+            }
+            FakePromise.reject = Promise.reject;
+
+            Object.defineProperty(FakePromise, 'resolve', {
+                get: function() {
+                    echo(`Test #${index} - get constructor resolve`);
+                    return function(x) {
+                        echo(`Test #${index} - constructor resolve called`);
+                        return Promise.resolve(x);
+                    };
+                }
+            });
+
+            Promise.any.call(FakePromise, [
+                FakePromise.reject(1),
+                FakePromise.reject(2)
+            ]);
+        }
+    },
+    {
+        name: "Promise.any with an object containing a non-function iterator property",
+        body: function (index) {
+            var objectWithNonObjectIterator = {
+                [Symbol.iterator]: 123
+            };
+            
+            var p = Promise.any(objectWithNonObjectIterator);
+            p.catch(
+                function(err) {
+                    echo('Test #' + index + ' - Catch handler #1 called with err = ' + err);
+                    echo('Test #' + index + ' - Catch handler #1 called with err.message = ' + err.message);
+                }
+            );
+        }
+    },
+    {
+        name: "Promise.any with this argument missing the resolve function",
+        body: function (index) {
+            var _resolve = Promise.resolve;
+            Promise.resolve = undefined;
+            
+            var p = Promise.any([Promise.reject(42)]);
+            p.catch(
+                function(err) {
+                    echo('Test #' + index + ' - Catch handler #1 called with err = ' + err);
+                    echo('Test #' + index + ' - Catch handler #1 called with err.message = ' + err.message);
+                }
+            );
+            
+            Promise.resolve = _resolve;
+        }
+    },
+    {
+        name: "Promise.any with this argument resolve function returning a non-object",
+        body: function (index) {
+            var _resolve = Promise.resolve;
+            Promise.resolve = function() { return undefined; };
+            
+            var p = Promise.any([Promise.reject(42)]);
+            p.catch(
+                function(err) {
+                    echo('Test #' + index + ' - Catch handler #1 called with err = ' + err);
+                    echo('Test #' + index + ' - Catch handler #1 called with err.message = ' + err.message);
+                }
+            );
+            
+            Promise.resolve = _resolve;
+        }
+    },
+    {
+        name: "Promise.any with this argument resolve function returning an object with no then function",
+        body: function (index) {
+            var _resolve = Promise.resolve;
+            Promise.resolve = function() { return {}; };
+            
+            var p = Promise.any([Promise.reject(42)]);
+            p.catch(
+                function(err) {
+                    echo('Test #' + index + ' - Catch handler #1 called with err = ' + err);
+                    echo('Test #' + index + ' - Catch handler #1 called with err.message = ' + err.message);
+                }
+            );
+            
+            Promise.resolve = _resolve;
+        }
+    },
+    {
+        name: "Promise.any with an object containing an iterator that throws",
+        body: function (index) {
+            var objectWithIterator = {
+                [Symbol.iterator]: function() {
+                    return {
+                        next: function () { 
+                            throw new TypeError('failure inside iterator');
+                        }
+                    };
+                }
+            };
+            
+            var p = Promise.any(objectWithIterator);
+            p.catch(
+                function(err) {
+                    echo('Test #' + index + ' - Catch handler #1 called with err = ' + err);
+                    echo('Test #' + index + ' - Catch handler #1 called with err.message = ' + err.message);
+                }
+            );
+        }
+    },
+    {
+        name: "Promise.any still returns a rejected promise if anything throws while iterating, even if resolved promises are encountered",
+        body: function (index) {
+            var objectWithIterator = {
+                [Symbol.iterator]: function() {
+                    return {
+                        i: 0,
+                        next: function () { 
+                            if (this.i > 2)
+                            {
+                                throw new TypeError('failure inside iterator');
+                            }
+                            
+                            this.i++;
+                            
+                            return {
+                                done: this.i == 5,
+                                value: Promise.resolve('resolved promise completion #' + this.i)
+                            };
+                        }
+                    };
+                }
+            };
+            
+            var p = Promise.any(objectWithIterator);
+            p.then(
+                function(result) {
+                    echo('Test #' + index + ' - Success handler #1 called with result = ' + result);
+                },
+                function(err) {
+                    echo('Test #' + index + ' - Error handler #1 called with err = ' + err);
+                    echo('Test #' + index + ' - Error handler #1 called with err.message = ' + err.message);
+                }
+            );
+        }
+    },
+    {
+        name: "Promise.any fulfills with the same value as the first encountered resolved promise",
+        body: function (index) {
+            var promises = [
+                new Promise(function() {}),
+                Promise.resolve('first promise'),
+                Promise.resolve('second promise'),
+                Promise.reject('third promise')
+            ];
+            
+            var p = Promise.any(promises);
+            p.then(
+                function(result) {
+                    echo('Test #' + index + ' - Success handler #1 called with result = ' + result);
+                },
+                function(err) {
+                    echo('Test #' + index + ' - Error handler #1 called with err = ' + err);
+                    echo('Test #' + index + ' - Error handler #1 called with err.message = ' + err.message);
+                }
+            );
+        }
+    },
+    {
+        name: "Promise.any fulfills with the same value as the first encountered resolved promise (promises complete async)",
+        body: function (index) {
+            var promises = [
+                new Promise(function() {}),
+                getAsyncResolvePromise('Test #' + index + ' - ', 'p1'),
+                getAsyncResolvePromise('Test #' + index + ' - ', 'p2'),
+                getAsyncRejectPromise('Test #' + index + ' - ', 'p3')
+            ];
+            
+            var p = Promise.any(promises);
+            p.then(
+                function(result) {
+                    echo('Test #' + index + ' - Success handler #1 called with result = ' + result);
+                },
+                function(err) {
+                    echo('Test #' + index + ' - Error handler #1 called with err = ' + err);
+                    echo('Test #' + index + ' - Error handler #1 called with err.message = ' + err.message);
+                }
+            );
+        }
+    },
+    {
+        name: "Promise.any fulfills with the same value as the first encountered rejected promise (promises complete async)",
+        body: function (index) {
+            var promises = [
+                new Promise(function() {}),
+                getAsyncRejectPromise('Test #' + index + ' - ', 'p1'),
+                getAsyncResolvePromise('Test #' + index + ' - ', 'p2'),
+                getAsyncResolvePromise('Test #' + index + ' - ', 'p3')
+            ];
+            
+            var p = Promise.any(promises);
+            p.then(
+                function(result) {
+                    echo('Test #' + index + ' - Success handler #1 called with result = ' + result);
+                },
+                function(err) {
+                    echo('Test #' + index + ' - Error handler #1 called with err = ' + err);
+                    echo('Test #' + index + ' - Error handler #1 called with err.message = ' + err.message);
+                }
+            );
+        }
+    },
+    {
+        name: "Promise.any should wait until one resolve",
+        body: function (index) {
+            const list = [
+                Promise.reject(1),
+                getAsyncRejectPromise('Test #' + index + ' - ', 2),
+                getAsyncResolvePromise('Test #' + index + ' - ', 3),
+                getAsyncRejectPromise('Test #' + index + ' - ', 4),
+                Promise.reject(5),
+            ]
+
+            Promise.any(list).then(
+                function(result) {
+                    echo('Test #' + index + ' - Success handler #1 called with result = ' + result);
+                },
+                function(err){
+                    echo('Test #' + index + ' - Error handler #1 called with err = ' + err);
+                    echo('Test #' + index + ' - Error handler #1 called with err.message = ' + JSON.stringify(err.message));
+                    echo('Test #' + index + ' - Error handler #1 called with err.name = ' + err.name);
+                    echo('Test #' + index + ' - Error handler #1 called with err.errors = ' + JSON.stringify(err.errors));
+                }
+            );
+        }
+    },
+    {
+        name: "Promise.any should wait until all reject",
+        body: function (index) {
+            const list = [
+                Promise.reject(1),
+                getAsyncRejectPromise('Test #' + index + ' - ', 2),
+                getAsyncRejectPromise('Test #' + index + ' - ', 3),
+                getAsyncRejectPromise('Test #' + index + ' - ', 4),
+                Promise.reject(5),
+            ]
+            Promise.any(list).then(
+                function(result) {
+                    echo('Test #' + index + ' - Success handler #1 called with result = ' + result);
+                },
+                function(err){
+                    echo('Test #' + index + ' - Error handler #1 called with err = ' + err);
+                    echo('Test #' + index + ' - Error handler #1 called with err.message = ' + JSON.stringify(err.message));
+                    echo('Test #' + index + ' - Error handler #1 called with err.name = ' + err.name);
+                    echo('Test #' + index + ' - Error handler #1 called with err.errors = ' + JSON.stringify(err.errors));
+                }
+            );
+        }
+    },
+    {
+        name: "Promise.any should not call return",
+        body: function (index) {
+            function it() {
+                return {
+                    [Symbol.iterator]() {
+                        echo(`Test #${index} - get iterator called`);
+                        return this;
+                    },
+                    i: 2,
+                    next() {
+                        if (this.i > 0) {
+                            let i = this.i--;
+                            echo(`Test #${index} - iterator next called: ${i}`);
+                            return { value: i, done: false }
+                        } else {
+                            echo(`Test #${index} - iterator next throw`);
+                            throw new Error("BANG");
+                        }
+                    },
+                    return() {
+                        echo(`Test #${index} - iterator return called`);
+                    }
+                }
+            }
+
+            Promise.any(it()).then(
+                function (result) {
+                    echo('Test #' + index + ' - Success handler #1 called with result = ' + result);
+                },
+                function (err) {
+                    echo('Test #' + index + ' - Error handler #1 called with err = ' + err);
+                }
+            );
+        }
+    },
+    {
+        name: "Promise.any should call return once",
+        body: function (index) {
+            function it() {
+                return {
+                    [Symbol.iterator]() {
+                        echo(`Test #${index} - get iterator called`);
+                        return this;
+                    },
+                    i: 2,
+                    next() {
+                        if (this.i > 0) {
+                            let i = this.i--;
+                            echo(`Test #${index} - iterator next called: ${i}`);
+                            return { value: i, done: false }
+                        } else {
+                            echo(`Test #${index} - iterator next throw`);
+                            throw new Error("BANG");
+                        }
+                    },
+                    return() {
+                        echo(`Test #${index} - iterator return called`);
+                    }
+                }
+            }
+
+            Promise.resolve = function () { throw new Error(); }
+            Promise.any(it()).then(
+                function (result) {
+                    echo('Test #' + index + ' - Success handler #1 called with result = ' + result);
+                },
+                function (err) {
+                    echo('Test #' + index + ' - Error handler #1 called with err = ' + err);
+                }
+            );
+        }
+    },
+    {
+        name: "Promise.any should throw TypeError if resolve not a function",
+        body: function (index) {
+            class foo extends Promise {
+                static get resolve() {
+                    echo('Test #' + index + ' - resolve getter called');
+                    return 5;
+                }
+            }
+            Promise.any.call(foo, [2, 3]).then(
+                function(result) {
+                    echo('Test #' + index + ' - Success handler #1 called with result = ' + result);
+                },
+                function(err) {
+                    echo('Test #' + index + ' - Error handler #1 called with err = ' + err);
+                }
+            );
+        }
+    },
+    {
+        name: "Promise.any passes each element in it's argument to Promise.resolve",
+        body: function (index) {
+            var promises = [
+                'first promise value',
+                42,
+                new TypeError('some error')
+            ];
+            
+            var p = Promise.any(promises);
+            p.then(
+                function(result) {
+                    echo('Test #' + index + ' - Success handler #1 called with result = ' + result);
+                },
+                function(err) {
+                    echo('Test #' + index + ' - Error handler #1 called with err = ' + err);
+                    echo('Test #' + index + ' - Error handler #1 called with err.message = ' + err.message);
+                }
+            );
+        }
+    },
+    {
+        name: "Promise.any should failure with empty list",
+        body: function (index) {
+            Promise.any([]).then(
+                function(result) {
+                    echo('Test #' + index + ' - Success handler #1 called with result = ' + result);
+                },
+                function(err){
+                    echo('Test #' + index + ' - Error handler #1 called with err = ' + err);
+                    echo('Test #' + index + ' - Error handler #1 called with err.errors = ' + JSON.stringify(err.errors));
+                    echo('Test #' + index + ' - Error handler #1 called with err.message = ' + err.message);
+                }
+            )
+        }
+    },
+    {
+        name: "Promise.any should reject with aggregate error and errors",
+        body: function (index) {
+            function applyTest(list, idx) {
+                Promise.any(list).then(
+                    function(result) {
+                        echo('Test #' + index + ' - Success handler #' + idx + ' called with result = ' + result);
+                    },
+                    function(err){
+                        echo('Test #' + index + ' - Error handler #' + idx + ' called with err = ' + err);
+                        echo('Test #' + index + ' - Error handler #' + idx + ' called with err.message = ' + JSON.stringify(err.message));
+                        echo('Test #' + index + ' - Error handler #' + idx + ' called with err.name = ' + err.name);
+                        echo('Test #' + index + ' - Error handler #' + idx + ' called with err.errors = ' + JSON.stringify(err.errors));
+                    }
+                );
+            }
+
+            applyTest([], 1)
+            applyTest([Promise.reject(1)], 2)
+            applyTest([Promise.reject(1), Promise.reject(2), Promise.reject(3)], 3)
+        }
     }
 ];
 

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels