Skip to content

Commit 6e4b82d

Browse files
committed
address review comments
1 parent 1bb71ab commit 6e4b82d

File tree

5 files changed

+76
-33
lines changed

5 files changed

+76
-33
lines changed

lib/Runtime/Library/JavascriptObject.cpp

Lines changed: 41 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1507,53 +1507,63 @@ namespace Js
15071507

15081508
// 4. Let sources be the List of argument values starting with the second argument.
15091509
// 5. For each element nextSource of sources, in ascending index order,
1510-
for (unsigned int i = 2; i < args.Info.Count; i++)
1510+
AssignHelper<true>(args[2], to, scriptContext);
1511+
for (unsigned int i = 3; i < args.Info.Count; i++)
15111512
{
1512-
// a. If nextSource is undefined or null, let keys be an empty List.
1513-
// b. Else,
1514-
// i.Let from be ToObject(nextSource).
1515-
// ii.ReturnIfAbrupt(from).
1516-
// iii.Let keys be from.[[OwnPropertyKeys]]().
1517-
// iv.ReturnIfAbrupt(keys).
1513+
AssignHelper<false>(args[2], to, scriptContext);
1514+
}
1515+
1516+
// 6. Return to.
1517+
return to;
1518+
}
1519+
1520+
template <bool tryCopy>
1521+
void JavascriptObject::AssignHelper(Var fromArg, RecyclableObject* to, ScriptContext* scriptContext)
1522+
{
1523+
// a. If nextSource is undefined or null, let keys be an empty List.
1524+
// b. Else,
1525+
// i.Let from be ToObject(nextSource).
1526+
// ii.ReturnIfAbrupt(from).
1527+
// iii.Let keys be from.[[OwnPropertyKeys]]().
1528+
// iv.ReturnIfAbrupt(keys).
15181529

1519-
RecyclableObject* from = nullptr;
1520-
if (!JavascriptConversion::ToObject(args[i], scriptContext, &from))
1530+
RecyclableObject* from = nullptr;
1531+
if (!JavascriptConversion::ToObject(fromArg, scriptContext, &from))
1532+
{
1533+
if (JavascriptOperators::IsUndefinedOrNull(fromArg))
15211534
{
1522-
if (JavascriptOperators::IsUndefinedOrNull(args[i]))
1523-
{
1524-
continue;
1525-
}
1526-
JavascriptError::ThrowTypeError(scriptContext, JSERR_FunctionArgument_NeedObject, _u("Object.assign"));
1535+
return;
15271536
}
1537+
JavascriptError::ThrowTypeError(scriptContext, JSERR_FunctionArgument_NeedObject, _u("Object.assign"));
1538+
}
15281539

15291540
#if ENABLE_COPYONACCESS_ARRAY
1530-
JavascriptLibrary::CheckAndConvertCopyOnAccessNativeIntArray<Var>(from);
1541+
JavascriptLibrary::CheckAndConvertCopyOnAccessNativeIntArray<Var>(from);
15311542
#endif
15321543

1533-
// if proxy, take slow path by calling [[OwnPropertyKeys]] on source
1534-
if (JavascriptProxy::Is(from))
1535-
{
1536-
AssignForProxyObjects(from, to, scriptContext);
1537-
}
1538-
// else use enumerator to extract keys from source
1539-
else
1544+
// if proxy, take slow path by calling [[OwnPropertyKeys]] on source
1545+
if (JavascriptProxy::Is(from))
1546+
{
1547+
AssignForProxyObjects(from, to, scriptContext);
1548+
}
1549+
// else use enumerator to extract keys from source
1550+
else
1551+
{
1552+
bool copied = false;
1553+
if (tryCopy)
15401554
{
15411555
DynamicObject* fromObj = JavascriptOperators::TryFromVar<DynamicObject>(from);
15421556
DynamicObject* toObj = JavascriptOperators::TryFromVar<DynamicObject>(to);
1543-
bool cloned = false;
15441557
if (toObj && fromObj && toObj->GetType() == scriptContext->GetLibrary()->GetObjectType())
15451558
{
1546-
cloned = toObj->TryCopy(fromObj);
1547-
}
1548-
if(!cloned)
1549-
{
1550-
AssignForGenericObjects(from, to, scriptContext);
1559+
copied = toObj->TryCopy(fromObj);
15511560
}
15521561
}
1562+
if (!copied)
1563+
{
1564+
AssignForGenericObjects(from, to, scriptContext);
1565+
}
15531566
}
1554-
1555-
// 6. Return to.
1556-
return to;
15571567
}
15581568

15591569
void JavascriptObject::AssignForGenericObjects(RecyclableObject* from, RecyclableObject* to, ScriptContext* scriptContext)

lib/Runtime/Library/JavascriptObject.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ namespace Js
110110
static JavascriptString* ToStringTagHelper(Var thisArg, ScriptContext* scriptContext, TypeId type);
111111

112112
private:
113+
template <bool tryCopy>
114+
static void AssignHelper(Var fromArg, RecyclableObject* to, ScriptContext* scriptContext);
113115
static void AssignForGenericObjects(RecyclableObject* from, RecyclableObject* to, ScriptContext* scriptContext);
114116
static void AssignForProxyObjects(RecyclableObject* from, RecyclableObject* to, ScriptContext* scriptContext);
115117
static JavascriptArray* CreateKeysHelper(RecyclableObject* object, ScriptContext* scriptContext, BOOL enumNonEnumerable, bool includeSymbolProperties, bool includeStringProperties, bool includeSpecialProperties);

lib/Runtime/Types/DynamicObject.cpp

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -760,9 +760,8 @@ namespace Js
760760
return reinterpret_cast<Field(Var)*>(reinterpret_cast<size_t>(this) + this->GetOffsetOfInlineSlots());
761761
}
762762

763-
bool DynamicObject::TryCopy(DynamicObject* from)
763+
bool DynamicObject::IsCompatibleForCopy(DynamicObject* from) const
764764
{
765-
// Validate that objects are compatible
766765
if (this->GetTypeHandler()->GetInlineSlotCapacity() != from->GetTypeHandler()->GetInlineSlotCapacity())
767766
{
768767
if (PHASE_TRACE1(ObjectCopyPhase))
@@ -805,8 +804,35 @@ namespace Js
805804
}
806805
return false;
807806
}
807+
if (from->IsExternal())
808+
{
809+
if (PHASE_TRACE1(ObjectCopyPhase))
810+
{
811+
Output::Print(_u("ObjectCopy: Can't copy: from obj is External\n"));
812+
}
813+
return false;
814+
}
815+
if (this->GetScriptContext() != from->GetScriptContext())
816+
{
817+
if (PHASE_TRACE1(ObjectCopyPhase))
818+
{
819+
Output::Print(_u("ObjectCopy: Can't copy: from obj is from different ScriptContext\n"));
820+
}
821+
return false;
822+
}
823+
824+
return true;
825+
}
808826

827+
bool DynamicObject::TryCopy(DynamicObject* from)
828+
{
829+
// Validate that objects are compatible
830+
if (!this->IsCompatibleForCopy(from))
831+
{
832+
return false;
833+
}
809834
// Share the type
835+
// Note: this will mark type as shared in case of success
810836
if (!from->GetDynamicType()->ShareType())
811837
{
812838
if (PHASE_TRACE1(ObjectCopyPhase))

lib/Runtime/Types/DynamicObject.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,8 @@ namespace Js
157157
#endif
158158

159159
private:
160+
bool IsCompatibleForCopy(DynamicObject* from) const;
161+
160162
bool IsObjectHeaderInlinedTypeHandlerUnchecked() const;
161163
public:
162164
bool IsObjectHeaderInlinedTypeHandler() const;

test/Object/assign.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,14 @@ var tests = [
1111
body: function ()
1212
{
1313
let orig = {};
14+
let sym = Symbol("c");
1415
orig.a = 1;
1516
orig.b = "asdf";
17+
orig[sym] = "qwert";
1618
let newObj = Object.assign({}, orig);
1719
assert.areEqual(newObj.b, orig.b);
1820
assert.areEqual(newObj.a, orig.a);
21+
assert.areEqual(newObj[sym], orig[sym]);
1922
}
2023
},
2124
{

0 commit comments

Comments
 (0)