Skip to content

Commit 655dc14

Browse files
committed
[MERGE chakra-core#886] Fix 7019631: Check whether a Proxy object is anywhere in the prototype chain before choosing to do the optimized ToPropertyDescriptor for non-Proxy objects.
Merge pull request chakra-core#886 from dilijev:protoproxy See: https://tc39.github.io/ecma262/2016/#sec-topropertydescriptor
2 parents 9366a64 + 50e9328 commit 655dc14

5 files changed

Lines changed: 79 additions & 4 deletions

File tree

lib/Runtime/Language/JavascriptOperators.cpp

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8670,6 +8670,7 @@ namespace Js
86708670

86718671
return true;
86728672
}
8673+
86738674
BOOL JavascriptOperators::ToPropertyDescriptorForProxyObjects(Var propertySpec, PropertyDescriptor* descriptor, ScriptContext* scriptContext)
86748675
{
86758676
if (!JavascriptOperators::IsObject(propertySpec))
@@ -8822,7 +8823,8 @@ namespace Js
88228823

88238824
BOOL JavascriptOperators::ToPropertyDescriptor(Var propertySpec, PropertyDescriptor* descriptor, ScriptContext* scriptContext)
88248825
{
8825-
if (JavascriptProxy::Is(propertySpec))
8826+
if (JavascriptProxy::Is(propertySpec) ||
8827+
JavascriptOperators::CheckIfPrototypeChainContainsProxyObject(RecyclableObject::FromVar(propertySpec)->GetPrototype()))
88268828
{
88278829
if (ToPropertyDescriptorForProxyObjects(propertySpec, descriptor, scriptContext) == FALSE)
88288830
{
@@ -9960,16 +9962,13 @@ namespace Js
99609962
return !Equal(aLeft, aRight, scriptContext);
99619963
}
99629964

9963-
99649965
// NotStrictEqual() returns whether the two vars have strict equality, as
99659966
// described in (ES3.0: S11.9.5, S11.9.6).
9966-
99679967
BOOL JavascriptOperators::NotStrictEqual(Var aLeft, Var aRight, ScriptContext* scriptContext)
99689968
{
99699969
return !StrictEqual(aLeft, aRight, scriptContext);
99709970
}
99719971

9972-
99739972
bool JavascriptOperators::CheckIfObjectAndPrototypeChainHasOnlyWritableDataProperties(RecyclableObject* object)
99749973
{
99759974
Assert(object);
@@ -10040,6 +10039,25 @@ namespace Js
1004010039
return true;
1004110040
}
1004210041

10042+
// Checks to see if the specified object (which should be a prototype object)
10043+
// contains a proxy anywhere in the prototype chain.
10044+
bool JavascriptOperators::CheckIfPrototypeChainContainsProxyObject(RecyclableObject* prototype)
10045+
{
10046+
Assert(JavascriptOperators::IsObjectOrNull(prototype));
10047+
10048+
while (prototype->GetTypeId() != TypeIds_Null)
10049+
{
10050+
if (prototype->GetTypeId() == TypeIds_Proxy)
10051+
{
10052+
return true;
10053+
}
10054+
10055+
prototype = prototype->GetPrototype();
10056+
}
10057+
10058+
return false;
10059+
}
10060+
1004310061
BOOL JavascriptOperators::Equal(Var aLeft, Var aRight, ScriptContext* scriptContext)
1004410062
{
1004510063
if (aLeft == aRight)

lib/Runtime/Language/JavascriptOperators.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,7 @@ namespace Js
538538
static bool CheckIfObjectAndPrototypeChainHasOnlyWritableDataProperties(RecyclableObject* object);
539539
static bool CheckIfPrototypeChainHasOnlyWritableDataProperties(RecyclableObject* prototype);
540540
static bool DoCheckIfPrototypeChainHasOnlyWritableDataProperties(RecyclableObject* prototype);
541+
static bool CheckIfPrototypeChainContainsProxyObject(RecyclableObject* prototype);
541542
static void OP_SetComputedNameVar(Var method, Var computedNameVar);
542543
static void OP_SetHomeObj(Var method, Var homeObj);
543544
static Var OP_LdSuper(Var scriptFunction, ScriptContext * scriptContext);

test/es6/proxyprotobug.baseline

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
has enumerable
2+
get enumerable
3+
has configurable
4+
get configurable
5+
has value
6+
get value
7+
has writable
8+
get writable
9+
has get
10+
has set
11+
======================
12+
has enumerable
13+
get enumerable
14+
has configurable
15+
get configurable
16+
has value
17+
get value
18+
has writable
19+
get writable
20+
has get
21+
has set

test/es6/proxyprotobug.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//-------------------------------------------------------------------------------------------------------
2+
// Copyright (C) Microsoft. All rights reserved.
3+
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
4+
//-------------------------------------------------------------------------------------------------------
5+
6+
var proxyHandler = {
7+
has(p, n) {
8+
WScript.Echo("has " + n);
9+
return !(n === "get" || n === "set");
10+
},
11+
get(p, n) {
12+
WScript.Echo("get " + n);
13+
if (n == "get" || n == "set") {
14+
return () => 1;
15+
} else {
16+
return 1;
17+
}
18+
}
19+
};
20+
21+
var p = new Proxy({}, proxyHandler);
22+
var o = {};
23+
Object.defineProperty(o, "x", p);
24+
25+
WScript.Echo("======================");
26+
27+
var pp = {};
28+
pp.__proto__ = p;
29+
Object.defineProperty(o, "y", pp);

test/es6/rlexe.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,12 @@
682682
<files>proxybug3.js</files>
683683
</default>
684684
</test>
685+
<test>
686+
<default>
687+
<files>proxyprotobug.js</files>
688+
<baseline>proxyprotobug.baseline</baseline>
689+
</default>
690+
</test>
685691
<test>
686692
<default>
687693
<files>proxyenumbug.js</files>

0 commit comments

Comments
 (0)