@@ -894,39 +894,56 @@ namespace Js
894894 // the proxy has been revoked; TypeError.
895895 if (!threadContext->RecordImplicitException ())
896896 return FALSE ;
897- JavascriptError::ThrowTypeError (GetScriptContext (), JSERR_ErrorOnRevokedProxy, _u (" enumerate" ));
897+ JavascriptError::ThrowTypeError (GetScriptContext (), JSERR_ErrorOnRevokedProxy, _u (" ownKeys" ));
898+ }
899+
900+ Var enmeratorObj;
901+ Var propertyName = nullptr ;
902+ PropertyId propertyId;
903+ int index = 0 ;
904+ JsUtil::BaseDictionary<const char16*, Var, Recycler> dict (scriptContext->GetRecycler ());
905+ JavascriptArray* arrResult = scriptContext->GetLibrary ()->CreateArray ();
906+
907+ // 13.7.5.15 EnumerateObjectProperties(O) (https://tc39.github.io/ecma262/#sec-enumerate-object-properties)
908+ // for (let key of Reflect.ownKeys(obj)) {
909+ Var trapResult = JavascriptOperators::GetOwnPropertyNames (this , scriptContext);
910+ if (JavascriptArray::Is (trapResult))
911+ {
912+ ((JavascriptArray*)trapResult)->GetEnumerator (false , &enmeratorObj, scriptContext);
913+ JavascriptEnumerator* pEnumerator = JavascriptEnumerator::FromVar (enmeratorObj);
914+ while ((propertyName = pEnumerator->MoveAndGetNext (propertyId)) != NULL )
915+ {
916+ PropertyId propId = JavascriptOperators::GetPropertyId (propertyName, scriptContext);
917+ Var prop = JavascriptOperators::GetProperty (RecyclableObject::FromVar (trapResult), propId, scriptContext);
918+ // if (typeof key === "string") {
919+ if (JavascriptString::Is (prop))
920+ {
921+ Js::PropertyDescriptor desc;
922+ JavascriptString* str = JavascriptString::FromVar (prop);
923+ // let desc = Reflect.getOwnPropertyDescriptor(obj, key);
924+ BOOL ret = JavascriptOperators::GetOwnPropertyDescriptor (this , str, scriptContext, &desc);
925+ // if (desc && !visited.has(key)) {
926+ if (ret && !dict.ContainsKey (str->GetSz ()))
927+ {
928+ dict.Add (str->GetSz (), prop);
929+ // if (desc.enumerable) yield key;
930+ if (desc.IsEnumerable ())
931+ {
932+ ret = arrResult->SetItem (index++, prop, PropertyOperation_None);
933+ Assert (ret);
934+ }
935+ }
936+ }
937+ }
898938 }
899-
900- // 4. Let trap be the result of GetMethod(handler, "enumerate").
901- // 5. ReturnIfAbrupt(trap).
902- // 6. If trap is undefined, then
903- // a.Return the result of calling the[[Enumerate]] internal method of target.
904- // 7. Let trapResult be the result of calling the[[Call]] internal method of trap with handler as the this value and a new List containing target.
905- // 8. ReturnIfAbrupt(trapResult).
906- // 9. If Type(trapResult) is not Object, then throw a TypeError exception.
907- // 10. Return trapResult.
908- JavascriptFunction* getEnumeratorMethod = GetMethodHelper (PropertyIds::enumerate, scriptContext);
909- Assert (!GetScriptContext ()->IsHeapEnumInProgress ());
910- if (nullptr == getEnumeratorMethod)
939+ else
911940 {
912- return target-> GetEnumerator (enumNonEnumerable, enumerator, requestContext, preferSnapshotSemantics, enumSymbols );
941+ AssertMsg ( false , " Expect GetOwnPropertyNames result to be array " );
913942 }
914943
915- CallInfo callInfo (CallFlags_Value, 2 );
916- Var varArgs[2 ];
917- Js::Arguments arguments (callInfo, varArgs);
918- varArgs[0 ] = handler;
919- varArgs[1 ] = target;
920-
921- Js::ImplicitCallFlags saveImplicitCallFlags = threadContext->GetImplicitCallFlags ();
922- Var trapResult = getEnumeratorMethod->CallFunction (arguments);
923- threadContext->SetImplicitCallFlags ((Js::ImplicitCallFlags)(saveImplicitCallFlags | ImplicitCall_Accessor));
944+ *enumerator = IteratorObjectEnumerator::Create (scriptContext,
945+ JavascriptOperators::GetIterator (RecyclableObject::FromVar (arrResult), scriptContext));
924946
925- if (!JavascriptOperators::IsObject (trapResult))
926- {
927- JavascriptError::ThrowTypeError (scriptContext, JSERR_InconsistentTrapResult, _u (" enumerate" ));
928- }
929- *enumerator = IteratorObjectEnumerator::Create (scriptContext, trapResult);
930947 return TRUE ;
931948 }
932949
0 commit comments