Skip to content

Commit 3d93036

Browse files
committed
Implement object.fromEntries
1 parent 07271b9 commit 3d93036

12 files changed

+340
-34
lines changed

lib/Parser/rterrors.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,8 @@ RT_ERROR_MSG(JSERR_ObjectIsNotInitialized, 5617, "%s: Object internal state is n
303303

304304
RT_ERROR_MSG(JSERR_GeneratorAlreadyExecuting, 5618, "%s: Cannot execute generator function because it is currently executing", "", kjstTypeError, 0)
305305
RT_ERROR_MSG(JSERR_LengthIsTooBig, 5619, "Length property would exceed maximum value in output from '%s'", "", kjstTypeError, 0)
306-
// 5620-5626 Unused
306+
RT_ERROR_MSG(JSERR_NonObjectFromIterable, 5620, "Iterable provided to %s must not return non-object or null value.", "", kjstTypeError, 0)
307+
// 5621-5626 Unused
307308
RT_ERROR_MSG(JSERR_NeedConstructor, 5627, "'%s' is not a constructor", "Constructor expected", kjstTypeError, 0)
308309

309310
RT_ERROR_MSG(VBSERR_CantDisplayDate, 32812, "", "The specified date is not available in the current locale's calendar", kjstRangeError, 0)

lib/Runtime/Base/JnDirectFields.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ ENTRY(freeze)
156156
ENTRY(from)
157157
ENTRY(fromCharCode)
158158
ENTRY(fromCodePoint)
159+
ENTRY(fromEntries)
159160
ENTRY(function)
160161
ENTRY(Function)
161162
ENTRY(getDate)
@@ -611,6 +612,7 @@ ENTRY(InitInternalProperties)
611612
ENTRY(methodName)
612613
ENTRY(registerChakraLibraryFunction)
613614
ENTRY(registerFunction)
615+
ENTRY(staticMethod)
614616
ENTRY(toLength)
615617
ENTRY(toInteger)
616618
ENTRY(arraySpeciesCreate)
@@ -672,6 +674,7 @@ ENTRY(raiseNeedObject)
672674
ENTRY(raiseNeedObjectOfType)
673675
ENTRY(raiseNeedObjectOrString)
674676
ENTRY(raiseNotAConstructor)
677+
ENTRY(raiseNonObjectFromIterable)
675678
ENTRY(raiseObjectIsAlreadyInitialized)
676679
ENTRY(raiseObjectIsNonExtensible)
677680
ENTRY(raiseOptionValueOutOfRange_3)

lib/Runtime/Library/EngineInterfaceObjectBuiltIns.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ BuiltInRaiseException1(TypeError, This_NullOrUndefined)
5858
BuiltInRaiseException1(TypeError, NotAConstructor)
5959
BuiltInRaiseException1(TypeError, ObjectIsNonExtensible)
6060
BuiltInRaiseException1(TypeError, LengthIsTooBig)
61+
BuiltInRaiseException1(TypeError, NonObjectFromIterable)
6162
BuiltInRaiseException2(TypeError, NeedObjectOfType)
6263
BuiltInRaiseException1(RangeError, InvalidCurrencyCode)
6364
BuiltInRaiseException(TypeError, MissingCurrencyCode)

lib/Runtime/Library/JavascriptLibrary.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3651,6 +3651,18 @@ namespace Js
36513651
propertyCount++;
36523652
}
36533653

3654+
if (scriptContext->GetConfig()->IsES7ValuesEntriesEnabled())
3655+
{
3656+
propertyCount += 2;
3657+
}
3658+
3659+
#ifdef ENABLE_JS_BUILTINS
3660+
if (scriptContext->IsJsBuiltInEnabled())
3661+
{
3662+
propertyCount++;
3663+
}
3664+
#endif
3665+
36543666
typeHandler->Convert(objectConstructor, mode, propertyCount);
36553667

36563668
library->AddMember(objectConstructor, PropertyIds::length, TaggedInt::ToVarUnchecked(1), PropertyConfigurable);
@@ -3707,6 +3719,13 @@ namespace Js
37073719
library->AddFunctionToLibraryObject(objectConstructor, PropertyIds::entries, &JavascriptObject::EntryInfo::Entries, 1));
37083720
}
37093721

3722+
#ifdef ENABLE_JS_BUILTINS
3723+
if (scriptContext->IsJsBuiltInEnabled())
3724+
{
3725+
library->EnsureBuiltInEngineIsReady();
3726+
}
3727+
#endif
3728+
37103729
objectConstructor->SetHasNoEnumerableProperties(true);
37113730

37123731
return true;

lib/Runtime/Library/JsBuiltIn/JsBuiltIn.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
ArrayFlat: { className: "Array", methodName: "flat", argumentsCount: 0, forceInline: true /*optional*/ },
1818
ArrayFlatMap: { className: "Array", methodName: "flatMap", argumentsCount: 1, forceInline: true /*optional*/ },
1919
ArrayForEach: { className: "Array", methodName: "forEach", argumentsCount: 1, forceInline: true /*optional*/ },
20+
ObjectFromEntries: { className: "Object", staticMethod: true, methodName: "fromEntries", argumentsCount: 1, forceInline: true /*optional*/ },
2021
};
2122

2223
var setPrototype = platform.builtInSetPrototype;
@@ -39,10 +40,13 @@
3940
__chakraLibrary.ArrayIterator.prototype = CreateObject(iteratorPrototype);
4041
__chakraLibrary.raiseNeedObjectOfType = platform.raiseNeedObjectOfType;
4142
__chakraLibrary.raiseThis_NullOrUndefined = platform.raiseThis_NullOrUndefined;
43+
__chakraLibrary.raiseNeedObject = platform.raiseNeedObject;
44+
__chakraLibrary.raiseNonObjectFromIterable = platform.raiseNonObjectFromIterable;
4245
__chakraLibrary.raiseLengthIsTooBig = platform.raiseLengthIsTooBig;
4346
__chakraLibrary.raiseFunctionArgument_NeedFunction = platform.raiseFunctionArgument_NeedFunction;
4447
__chakraLibrary.callInstanceFunc = platform.builtInCallInstanceFunction;
4548
__chakraLibrary.functionBind = platform.builtInJavascriptFunctionEntryBind;
49+
__chakraLibrary.objectDefineProperty = _objectDefineProperty;
4650

4751
_objectDefineProperty(__chakraLibrary.ArrayIterator.prototype, 'next',
4852
// Object's getter and setter can get overriden on the prototype, in that case while setting the value attributes, we will end up with TypeError
@@ -440,4 +444,32 @@
440444

441445
return undefined;
442446
});
447+
448+
platform.registerFunction(FunctionsEnum.ObjectFromEntries, function (iterable) {
449+
// #sec-object.fromentries
450+
"use strict";
451+
if (iterable === null || iterable === undefined) {
452+
__chakraLibrary.raiseNeedObject("Object.fromEntries");
453+
}
454+
455+
const o = {};
456+
const propDescriptor = {
457+
enumerable : true,
458+
configurable : true,
459+
writable : true,
460+
value : undefined
461+
};
462+
463+
let key;
464+
for (const entry of iterable) {
465+
if (typeof entry !== "object" || entry === null) {
466+
__chakraLibrary.raiseNonObjectFromIterable("Object.fromEntries");
467+
}
468+
469+
key = entry[0];
470+
propDescriptor.value = entry[1];
471+
__chakraLibrary.objectDefineProperty(o, key, propDescriptor);
472+
}
473+
return o;
474+
});
443475
});

lib/Runtime/Library/JsBuiltInEngineInterfaceExtensionObject.cpp

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -224,22 +224,43 @@ namespace Js
224224
}
225225
}
226226

227-
DynamicObject* JsBuiltInEngineInterfaceExtensionObject::GetPrototypeFromName(Js::PropertyIds propertyId, ScriptContext* scriptContext)
227+
DynamicObject* JsBuiltInEngineInterfaceExtensionObject::GetPrototypeFromName(Js::PropertyIds propertyId, bool staticMethod, ScriptContext* scriptContext)
228228
{
229229
JavascriptLibrary* library = scriptContext->GetLibrary();
230230

231+
if (staticMethod)
232+
{
233+
switch (propertyId) {
234+
case PropertyIds::Array:
235+
return library->arrayConstructor;
236+
237+
case PropertyIds::Object:
238+
return library->objectConstructor;
239+
240+
case PropertyIds::String:
241+
return library->stringConstructor;
242+
243+
default:
244+
AssertOrFailFastMsg(false, "Unable to find a constructor that match with this className.");
245+
return nullptr;
246+
}
247+
}
248+
231249
switch (propertyId) {
232250
case PropertyIds::Array:
233251
return library->arrayPrototype;
234252

253+
case PropertyIds::Object:
254+
return library->objectPrototype;
255+
235256
case PropertyIds::String:
236257
return library->stringPrototype;
237258

238259
case PropertyIds::__chakraLibrary:
239260
return library->GetChakraLib();
240261

241262
default:
242-
AssertMsg(false, "Unable to find a prototype that match with this className.");
263+
AssertOrFailFastMsg(false, "Unable to find a prototype that match with this className.");
243264
return nullptr;
244265
}
245266
}
@@ -301,7 +322,7 @@ namespace Js
301322
func->GetFunctionProxy()->SetIsPublicLibraryCode();
302323
func->GetFunctionProxy()->EnsureDeserialized()->SetDisplayName(methodName->GetString(), methodName->GetLength(), 0);
303324

304-
DynamicObject* chakraLibraryObject = GetPrototypeFromName(PropertyIds::__chakraLibrary, scriptContext);
325+
DynamicObject* chakraLibraryObject = GetPrototypeFromName(PropertyIds::__chakraLibrary, false, scriptContext);
305326
PropertyIds functionIdentifier = JavascriptOperators::GetPropertyId(methodName, scriptContext);
306327

307328
// Link the function to __chakraLibrary.
@@ -339,6 +360,7 @@ namespace Js
339360
Var argumentsCountProperty = JavascriptOperators::OP_GetProperty(funcInfo, Js::PropertyIds::argumentsCount, scriptContext);
340361
Var forceInlineProperty = JavascriptOperators::OP_GetProperty(funcInfo, Js::PropertyIds::forceInline, scriptContext);
341362
Var aliasProperty = JavascriptOperators::OP_GetProperty(funcInfo, Js::PropertyIds::alias, scriptContext);
363+
Var staticMethodProperty = JavascriptOperators::OP_GetProperty(funcInfo, Js::PropertyIds::staticMethod, scriptContext);
342364

343365
Assert(JavascriptString::Is(classNameProperty));
344366
Assert(JavascriptString::Is(methodNameProperty));
@@ -348,6 +370,7 @@ namespace Js
348370
JavascriptString* methodName = JavascriptString::FromVar(methodNameProperty);
349371
int argumentsCount = TaggedInt::ToInt32(argumentsCountProperty);
350372

373+
BOOL staticMethod = JavascriptConversion::ToBoolean(staticMethodProperty, scriptContext);
351374
BOOL forceInline = JavascriptConversion::ToBoolean(forceInlineProperty, scriptContext);
352375

353376
JavascriptFunction* func = JavascriptFunction::FromVar(args.Values[2]);
@@ -356,7 +379,7 @@ namespace Js
356379
func->GetFunctionProxy()->SetIsPublicLibraryCode();
357380
func->GetFunctionProxy()->EnsureDeserialized()->SetDisplayName(methodName->GetString(), methodName->GetLength(), 0);
358381

359-
DynamicObject* prototype = GetPrototypeFromName(JavascriptOperators::GetPropertyId(className, scriptContext), scriptContext);
382+
DynamicObject* prototype = GetPrototypeFromName(JavascriptOperators::GetPropertyId(className, scriptContext), staticMethod, scriptContext);
360383
PropertyIds functionIdentifier = methodName->BufferEquals(_u("Symbol.iterator"), 15)? PropertyIds::_symbolIterator :
361384
JavascriptOperators::GetPropertyId(methodName, scriptContext);
362385

lib/Runtime/Library/JsBuiltInEngineInterfaceExtensionObject.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ namespace Js
4242

4343
void EnsureJsBuiltInByteCode(ScriptContext * scriptContext);
4444

45-
static DynamicObject* GetPrototypeFromName(Js::PropertyIds propertyId, ScriptContext* scriptContext);
45+
static DynamicObject* GetPrototypeFromName(Js::PropertyIds propertyId, bool staticMethod, ScriptContext* scriptContext);
4646
static void RecordDefaultIteratorFunctions(Js::PropertyIds propertyId, ScriptContext * scriptContext, JavascriptFunction* iteratorFunc);
4747
static void RecordCommonNativeInterfaceBuiltIns(Js::PropertyIds propertyId, ScriptContext * scriptContext, JavascriptFunction * scriptFunction);
4848
static Var EntryJsBuiltIn_RegisterChakraLibraryFunction(RecyclableObject* function, CallInfo callInfo, ...);

test/AsmJs/params.js

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ function wrapType(type, name) {
2727
}
2828
}
2929

30+
let done = false;
31+
3032
const tested = {};
3133
function test(n) {
3234
if (n in tested) {
@@ -80,36 +82,38 @@ const [forceTest] = WScript.Arguments;
8082
if (forceTest !== undefined) {
8183
const res = test(forceTest);
8284
print(res ? "Module is valid" : "Module is invalid");
83-
WScript.Quit(0);
85+
done = true;
8486
}
8587

86-
let nParams = 8201;
87-
let inc = 100;
88-
let direction = true;
88+
if (done === false) {
89+
let nParams = 8201;
90+
let inc = 100;
91+
let direction = true;
8992

90-
while (inc !== 0) {
91-
if (test(nParams)) {
92-
if (direction) {
93-
nParams += inc;
93+
while (inc !== 0) {
94+
if (test(nParams)) {
95+
if (direction) {
96+
nParams += inc;
97+
} else {
98+
direction = true;
99+
inc >>= 1;
100+
nParams += inc;
101+
}
94102
} else {
95-
direction = true;
96-
inc >>= 1;
97-
nParams += inc;
103+
if (!direction) {
104+
nParams -= inc;
105+
} else {
106+
direction = false;
107+
inc >>= 1;
108+
nParams -= inc;
109+
}
98110
}
99-
} else {
100-
if (!direction) {
101-
nParams -= inc;
102-
} else {
103-
direction = false;
104-
inc >>= 1;
105-
nParams -= inc;
111+
112+
if (nParams > 100000 || nParams < 0) {
113+
print(`FAILED. Params reached ${nParams} long. Expected an error by now`);
114+
break;
106115
}
107116
}
108117

109-
if (nParams > 100000 || nParams < 0) {
110-
print(`FAILED. Params reached ${nParams} long. Expected an error by now`);
111-
break;
112-
}
118+
print(`Support at most ${nParams} params`);
113119
}
114-
115-
print(`Support at most ${nParams} params`);

test/DebuggerCommon/ES6_intl_simple_attach.js.dbg.baseline

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@
5757
"is": "function <large string>",
5858
"assign": "function <large string>",
5959
"values": "function <large string>",
60-
"entries": "function <large string>"
60+
"entries": "function <large string>",
61+
"fromEntries": "function <large string>"
6162
},
6263
"hasOwnProperty": {
6364
"#__proto__": "function <large string>",
@@ -205,7 +206,8 @@
205206
"is": "function <large string>",
206207
"assign": "function <large string>",
207208
"values": "function <large string>",
208-
"entries": "function <large string>"
209+
"entries": "function <large string>",
210+
"fromEntries": "function <large string>"
209211
},
210212
"hasOwnProperty": {
211213
"#__proto__": "function <large string>",
@@ -353,7 +355,8 @@
353355
"is": "function <large string>",
354356
"assign": "function <large string>",
355357
"values": "function <large string>",
356-
"entries": "function <large string>"
358+
"entries": "function <large string>",
359+
"fromEntries": "function <large string>"
357360
},
358361
"hasOwnProperty": {
359362
"#__proto__": "function <large string>",

test/DebuggerCommon/symbols.js.dbg.baseline

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@
3232
"is": "function <large string>",
3333
"assign": "function <large string>",
3434
"values": "function <large string>",
35-
"entries": "function <large string>"
35+
"entries": "function <large string>",
36+
"fromEntries": "function <large string>"
3637
},
3738
"hasOwnProperty": {
3839
"#__proto__": "function <large string>",

0 commit comments

Comments
 (0)