Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions lib/Runtime/Library/JavascriptBuiltInFunctionList.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,8 @@ BUILTIN(JavascriptObject, LookupGetter, EntryLookupGetter, FunctionInfo::ErrorOn
BUILTIN(JavascriptObject, LookupSetter, EntryLookupSetter, FunctionInfo::ErrorOnNew)
BUILTIN(JavascriptObject, Is, EntryIs, FunctionInfo::ErrorOnNew)
BUILTIN(JavascriptObject, Assign, EntryAssign, FunctionInfo::ErrorOnNew)
BUILTIN(JavascriptObject, Values, EntryValues, FunctionInfo::ErrorOnNew)
BUILTIN(JavascriptObject, Entries, EntryEntries, FunctionInfo::ErrorOnNew)
BUILTIN(ObjectPrototypeObject, __proto__getter, Entry__proto__getter, FunctionInfo::ErrorOnNew | FunctionInfo::DoNotProfile)
BUILTIN(ObjectPrototypeObject, __proto__setter, Entry__proto__setter, FunctionInfo::ErrorOnNew | FunctionInfo::DoNotProfile)
BUILTIN(JavascriptRegExp, NewInstance, NewInstance, FunctionInfo::SkipDefaultNewObject)
Expand Down
14 changes: 14 additions & 0 deletions lib/Runtime/Library/JavascriptLibrary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3602,6 +3602,14 @@ namespace Js
library->AddFunctionToLibraryObject(objectConstructor, PropertyIds::assign, &JavascriptObject::EntryInfo::Assign, 2));
}

if (scriptContext->GetConfig()->IsES7BuiltinsEnabled())
{
scriptContext->SetBuiltInLibraryFunction(JavascriptObject::EntryInfo::Values.GetOriginalEntryPoint(),
library->AddFunctionToLibraryObject(objectConstructor, PropertyIds::values, &JavascriptObject::EntryInfo::Values, 1));
scriptContext->SetBuiltInLibraryFunction(JavascriptObject::EntryInfo::Entries.GetOriginalEntryPoint(),
library->AddFunctionToLibraryObject(objectConstructor, PropertyIds::entries, &JavascriptObject::EntryInfo::Entries, 1));
}

objectConstructor->SetHasNoEnumerableProperties(true);
}

Expand Down Expand Up @@ -6183,6 +6191,12 @@ namespace Js
REG_OBJECTS_LIB_FUNC(assign, JavascriptObject::EntryAssign);
}

if (config.IsES7BuiltinsEnabled())
{
REG_OBJECTS_LIB_FUNC(values, JavascriptObject::EntryValues);
REG_OBJECTS_LIB_FUNC(entries, JavascriptObject::EntryEntries);
}

return hr;
}

Expand Down
86 changes: 86 additions & 0 deletions lib/Runtime/Library/JavascriptObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1096,6 +1096,92 @@ namespace Js
return JavascriptOperators::GetOwnEnumerablePropertyNames(object, scriptContext);
}

Var JavascriptObject::GetValuesOrEntries(RecyclableObject* object, bool valuesToReturn, ScriptContext* scriptContext)
{
Assert(object != nullptr);
Assert(scriptContext != nullptr);
JavascriptArray* valuesArray = scriptContext->GetLibrary()->CreateArray(0);

Var ownKeysVar = JavascriptOperators::GetOwnPropertyNames(object, scriptContext);
JavascriptArray* ownKeysResult = nullptr;
if (JavascriptArray::Is(ownKeysVar))
{
ownKeysResult = JavascriptArray::FromVar(ownKeysVar);
}
else
{
return valuesArray;
}

uint32 length = ownKeysResult->GetLength();

Var nextKey;
const PropertyRecord* propertyRecord = nullptr;
PropertyId propertyId;
for (uint32 i = 0, index = 0; i < length; i++)
{
nextKey = ownKeysResult->DirectGetItem(i);
Assert(JavascriptString::Is(nextKey));

PropertyDescriptor propertyDescriptor;

BOOL propertyKeyResult = JavascriptConversion::ToPropertyKey(nextKey, scriptContext, &propertyRecord);
Assert(propertyKeyResult);
propertyId = propertyRecord->GetPropertyId();
Assert(propertyId != Constants::NoProperty);
if (JavascriptOperators::GetOwnPropertyDescriptor(object, propertyId, scriptContext, &propertyDescriptor))
{
if (propertyDescriptor.IsEnumerable())
{
Var value = JavascriptOperators::GetProperty(object, propertyId, scriptContext);
if (!valuesToReturn)
{
// For Object.entries each entry is key, value pair
JavascriptArray* entry = scriptContext->GetLibrary()->CreateArray(2);
entry->DirectSetItemAt(0, CrossSite::MarshalVar(scriptContext, nextKey));
entry->DirectSetItemAt(1, CrossSite::MarshalVar(scriptContext, value));
value = entry;
}
valuesArray->DirectSetItemAt(index++, CrossSite::MarshalVar(scriptContext, value));
}
}
}

return valuesArray;
}

Var JavascriptObject::EntryValues(RecyclableObject* function, CallInfo callInfo, ...)
{
PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);

ARGUMENTS(args, callInfo);
ScriptContext* scriptContext = function->GetScriptContext();

Assert(!(callInfo.Flags & CallFlags_New));
CHAKRATEL_LANGSTATS_INC_BUILTINCOUNT(ObjectValuesCount);

Var tempVar = args.Info.Count < 2 ? scriptContext->GetLibrary()->GetUndefined() : args[1];
RecyclableObject *object = RecyclableObject::FromVar(JavascriptOperators::ToObject(tempVar, scriptContext));

return GetValuesOrEntries(object, true /*valuesToReturn*/, scriptContext);
}

Var JavascriptObject::EntryEntries(RecyclableObject* function, CallInfo callInfo, ...)
{
PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);

ARGUMENTS(args, callInfo);
ScriptContext* scriptContext = function->GetScriptContext();

Assert(!(callInfo.Flags & CallFlags_New));
CHAKRATEL_LANGSTATS_INC_BUILTINCOUNT(ObjectEntriesCount);

Var tempVar = args.Info.Count < 2 ? scriptContext->GetLibrary()->GetUndefined() : args[1];
RecyclableObject *object = RecyclableObject::FromVar(JavascriptOperators::ToObject(tempVar, scriptContext));

return GetValuesOrEntries(object, false /*valuesToReturn*/, scriptContext);
}

Var JavascriptObject::CreateOwnSymbolPropertiesHelper(RecyclableObject* object, ScriptContext* scriptContext)
{
return CreateKeysHelper(object, scriptContext, TRUE, true /*includeSymbolsOnly */, false, true /*includeSpecialProperties*/);
Expand Down
8 changes: 7 additions & 1 deletion lib/Runtime/Library/JavascriptObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ namespace Js
static FunctionInfo LookupSetter;
static FunctionInfo Is;
static FunctionInfo Assign;
static FunctionInfo Values;
static FunctionInfo Entries;
};

static Var NewInstance(RecyclableObject* function, CallInfo callInfo, ...);
Expand Down Expand Up @@ -77,7 +79,8 @@ namespace Js
static Var EntryLookupSetter(RecyclableObject* function, CallInfo callInfo, ...);
static Var EntryIs(RecyclableObject* function, CallInfo callInfo, ...);
static Var EntryAssign(RecyclableObject* function, CallInfo callInfo, ...);

static Var EntryValues(RecyclableObject* function, CallInfo callInfo, ...);
static Var EntryEntries(RecyclableObject* function, CallInfo callInfo, ...);

static Var GetPrototypeOf(RecyclableObject* obj, ScriptContext* scriptContext);
static BOOL ChangePrototype(RecyclableObject* object, RecyclableObject* newPrototype, bool validate, ScriptContext* scriptContext);
Expand All @@ -91,6 +94,9 @@ namespace Js
static Var GetOwnPropertyDescriptorHelper(RecyclableObject* obj, Var propertyKey, ScriptContext* scriptContext);
static BOOL GetOwnPropertyDescriptorHelper(RecyclableObject* obj, PropertyId propertyId, ScriptContext* scriptContext, PropertyDescriptor& propertyDescriptor);

// Param valuesToReturn should be set to true when we are looking for values from an object otherwise entries will be returned
static Var GetValuesOrEntries(RecyclableObject* object, bool valuesToReturn, ScriptContext* scriptContext);

// Presently used in the projection as a mechanism of calling the general object prototype toString.
static JavascriptString* ToStringInternal(Var thisArg, ScriptContext* scriptContext)
{
Expand Down
7 changes: 7 additions & 0 deletions test/es7/rlexe.xml
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,11 @@
<compile-flags>-es7asyncawait -es6tostringtag -args summary -endargs</compile-flags>
</default>
</test>
<test>
<default>
<files>valuesAndEntries.js</files>
<compile-flags>-ES7Builtins -args summary -endargs</compile-flags>
<tags>BugFix</tags>
</default>
</test>
</regress-exe>
Loading