Skip to content

Commit 83071cb

Browse files
committed
Writing to proto can leave the TypeHandler::protoCachesWereInvalidated set, and writing to proto again with the same type on the RHS object can skip proto cache invalidation
1 parent e3d4139 commit 83071cb

File tree

3 files changed

+65
-1
lines changed

3 files changed

+65
-1
lines changed

lib/Runtime/Library/JavascriptObject.cpp

+6-1
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ BOOL JavascriptObject::ChangePrototype(RecyclableObject* object, RecyclableObjec
194194
// ii. Let nextp be the result of calling the [[GetInheritance]] internal method of p with no arguments.
195195
// iii. ReturnIfAbrupt(nextp).
196196
// iv. Let p be nextp.
197-
if (IsPrototypeOfStopAtProxy(object, newPrototype, scriptContext)) // Reject cycle
197+
if (IsPrototypeOfStopAtProxy(object, newPrototype, scriptContext)) // Reject cycle
198198
{
199199
if (shouldThrow)
200200
{
@@ -229,6 +229,11 @@ BOOL JavascriptObject::ChangePrototype(RecyclableObject* object, RecyclableObjec
229229
{
230230
bool allProtoCachesInvalidated = false;
231231

232+
JavascriptOperators::MapObjectAndPrototypes<true>(newPrototype, [&](RecyclableObject* obj)
233+
{
234+
obj->ClearProtoCachesWereInvalidated();
235+
});
236+
232237
// Notify old prototypes that they are being removed from a prototype chain. This triggers invalidating protocache, etc.
233238
JavascriptOperators::MapObjectAndPrototypesUntil<true>(object->GetPrototype(), [&](RecyclableObject* obj)->bool
234239
{
+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
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+
function f1() {
7+
var o1 = {},o2 = {};
8+
var proto1 = {a:'a',b:'b'},proto2 = {a:'a'};
9+
o1.__proto__ = proto1;
10+
o2.__proto__ = proto2;
11+
12+
function a(o) { return o.a; }
13+
function b(o) { return o.b; }
14+
15+
a(o1);
16+
a(o2);
17+
b(o1);
18+
b(o2);
19+
proto2.__proto__ = {b:'b'};
20+
if (b(o2) !== 'b') {
21+
WScript.Echo('fail');
22+
}
23+
}
24+
25+
f1()
26+
f1();
27+
28+
function f2() {
29+
var o1 = {b:'b'},o2 = {b:'b'};
30+
var proto1 = {a:'a',b:'b'},proto2 = {a:'a'};
31+
o1.__proto__ = proto1;
32+
o2.__proto__ = proto2;
33+
34+
function a(o) { return o.a; }
35+
function b(o) { return o.b; }
36+
37+
a(o1);
38+
a(o2);
39+
40+
delete o1.b;
41+
delete o2.b;
42+
43+
b(o1);
44+
b(o2);
45+
proto2.__proto__ = {b:'b'};
46+
if (b(o2) !== 'b') {
47+
WScript.Echo('fail');
48+
}
49+
}
50+
51+
f2();
52+
f2();
53+
54+
WScript.Echo('pass');

test/InlineCaches/rlexe.xml

+5
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,11 @@
120120
<files>MissingPropertyCache4.js</files>
121121
</default>
122122
</test>
123+
<test>
124+
<default>
125+
<files>MissingProtoInval.js</files>
126+
</default>
127+
</test>
123128
<test>
124129
<default>
125130
<files>instanceOfCacheCrossRegistration.js</files>

0 commit comments

Comments
 (0)