Skip to content

Commit adc85d7

Browse files
committed
[JSC] Proxy should be trapped if base value is primitive
https://bugs.webkit.org/show_bug.cgi?id=216764 Reviewed by Darin Adler. JSTests: * stress/proxy-trap-in-primitive.js: Added. (shouldBe): * test262/expectations.yaml: Source/JavaScriptCore: While we have special care in JSObject::putInline etc., we missed it in JSValue::putToPrimitive. So, if proxy exists in the prototype chain for the primitive values (e.g. StringPrototype -> Proxy chain), we miss the Proxy trap. We should have ProxyObject special check in JSValue::putToPrimitive too. * runtime/JSCJSValue.cpp: (JSC::JSValue::putToPrimitive): Canonical link: https://commits.webkit.org/229567@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@267348 268f45cc-cd09-0410-ab3c-d52691b4dbfc
1 parent 644c932 commit adc85d7

6 files changed

Lines changed: 73 additions & 10 deletions

File tree

JSTests/ChangeLog

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1+
2020-09-21 Yusuke Suzuki <ysuzuki@apple.com>
2+
3+
[JSC] Proxy should be trapped if base value is primitive
4+
https://bugs.webkit.org/show_bug.cgi?id=216764
5+
6+
Reviewed by Darin Adler.
7+
8+
* stress/proxy-trap-in-primitive.js: Added.
9+
(shouldBe):
10+
* test262/expectations.yaml:
11+
112
2020-09-20 Yusuke Suzuki <ysuzuki@apple.com>
213

314
Test262 update
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
function shouldBe(actual, expected) {
2+
if (actual !== expected)
3+
throw new Error('bad value: ' + actual);
4+
}
5+
6+
var numberCount = 0;
7+
var stringCount = 0;
8+
var booleanCount = 0;
9+
var symbolCount = 0;
10+
var bigIntCount = 0;
11+
var spy;
12+
13+
spy = new Proxy({}, { set: function() { numberCount += 1; return true; } });
14+
Object.setPrototypeOf(Number.prototype, spy);
15+
0..property = null;
16+
shouldBe(numberCount, 1);
17+
18+
spy = new Proxy({}, { set: function() { stringCount += 1; return true; } });
19+
Object.setPrototypeOf(String.prototype, spy);
20+
"".property = null;
21+
shouldBe(stringCount, 1);
22+
23+
spy = new Proxy({}, { set: function() { booleanCount += 1; return true; } });
24+
Object.setPrototypeOf(Boolean.prototype, spy);
25+
true.property = null;
26+
shouldBe(booleanCount, 1);
27+
28+
spy = new Proxy({}, { set: function() { symbolCount += 1; return true; } });
29+
Object.setPrototypeOf(Symbol.prototype, spy);
30+
Symbol().property = null;
31+
shouldBe(symbolCount, 1);
32+
33+
34+
spy = new Proxy({}, { set: function() { bigIntCount += 1; return true; } });
35+
Object.setPrototypeOf(BigInt.prototype, spy);
36+
(1n).property = null;
37+
shouldBe(bigIntCount, 1);

JSTests/test262/expectations.yaml

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3738,9 +3738,3 @@ test/language/statements/variable/dstr/ary-init-iter-get-err-array-prototype.js:
37383738
test/language/statements/variable/dstr/ary-ptrn-elem-id-iter-val-array-prototype.js:
37393739
default: 'Test262Error: Expected SameValue(«3», «42») to be true'
37403740
strict mode: 'Test262Error: Expected SameValue(«3», «42») to be true'
3741-
test/language/types/reference/put-value-prop-base-primitive-realm.js:
3742-
default: 'Test262Error: number Expected SameValue(«0», «1») to be true'
3743-
strict mode: 'Test262Error: number Expected SameValue(«0», «1») to be true'
3744-
test/language/types/reference/put-value-prop-base-primitive.js:
3745-
default: 'Test262Error: number Expected SameValue(«0», «1») to be true'
3746-
strict mode: 'TypeError: Attempted to assign to readonly property.'

Source/JavaScriptCore/ChangeLog

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
2020-09-21 Yusuke Suzuki <ysuzuki@apple.com>
2+
3+
[JSC] Proxy should be trapped if base value is primitive
4+
https://bugs.webkit.org/show_bug.cgi?id=216764
5+
6+
Reviewed by Darin Adler.
7+
8+
While we have special care in JSObject::putInline etc., we missed it in JSValue::putToPrimitive.
9+
So, if proxy exists in the prototype chain for the primitive values (e.g. StringPrototype -> Proxy chain),
10+
we miss the Proxy trap. We should have ProxyObject special check in JSValue::putToPrimitive too.
11+
12+
* runtime/JSCJSValue.cpp:
13+
(JSC::JSValue::putToPrimitive):
14+
115
2020-09-20 Yusuke Suzuki <ysuzuki@apple.com>
216

317
[JSC] Drop Options::useBigInt

Source/JavaScriptCore/runtime/JSCJSValue.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,10 @@ bool JSValue::putToPrimitive(JSGlobalObject* globalObject, PropertyName property
184184
Structure* structure = obj->structure(vm);
185185
if (structure->hasReadOnlyOrGetterSetterPropertiesExcludingProto() || structure->typeInfo().hasPutPropertySecurityCheck())
186186
break;
187+
if (obj->type() == ProxyObjectType) {
188+
auto* proxy = jsCast<ProxyObject*>(obj);
189+
RELEASE_AND_RETURN(scope, proxy->ProxyObject::put(proxy, globalObject, propertyName, value, slot));
190+
}
187191
prototype = obj->getPrototype(vm, globalObject);
188192
RETURN_IF_EXCEPTION(scope, false);
189193

@@ -216,7 +220,10 @@ bool JSValue::putToPrimitive(JSGlobalObject* globalObject, PropertyName property
216220
// prototypes it should be replaced, so break here.
217221
break;
218222
}
219-
223+
if (obj->type() == ProxyObjectType) {
224+
auto* proxy = jsCast<ProxyObject*>(obj);
225+
RELEASE_AND_RETURN(scope, proxy->ProxyObject::put(proxy, globalObject, propertyName, value, slot));
226+
}
220227
prototype = obj->getPrototype(vm, globalObject);
221228
RETURN_IF_EXCEPTION(scope, false);
222229
if (prototype.isNull())

Source/JavaScriptCore/runtime/JSObject.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -719,7 +719,7 @@ bool ordinarySetSlow(JSGlobalObject* globalObject, JSObject* object, PropertyNam
719719
PropertyDescriptor ownDescriptor;
720720
while (true) {
721721
if (current->type() == ProxyObjectType) {
722-
ProxyObject* proxy = jsCast<ProxyObject*>(current);
722+
auto* proxy = jsCast<ProxyObject*>(current);
723723
PutPropertySlot slot(receiver, shouldThrow);
724724
RELEASE_AND_RETURN(scope, proxy->ProxyObject::put(proxy, globalObject, propertyName, value, slot));
725725
}
@@ -875,7 +875,7 @@ bool JSObject::putInlineSlow(JSGlobalObject* globalObject, PropertyName property
875875
}
876876
}
877877
if (obj->type() == ProxyObjectType) {
878-
ProxyObject* proxy = jsCast<ProxyObject*>(obj);
878+
auto* proxy = jsCast<ProxyObject*>(obj);
879879
RELEASE_AND_RETURN(scope, proxy->ProxyObject::put(proxy, globalObject, propertyName, value, slot));
880880
}
881881
JSValue prototype = obj->getPrototype(vm, globalObject);
@@ -2832,7 +2832,7 @@ bool JSObject::attemptToInterceptPutByIndexOnHoleForPrototype(JSGlobalObject* gl
28322832

28332833
if (current->type() == ProxyObjectType) {
28342834
scope.release();
2835-
ProxyObject* proxy = jsCast<ProxyObject*>(current);
2835+
auto* proxy = jsCast<ProxyObject*>(current);
28362836
putResult = proxy->putByIndexCommon(globalObject, thisValue, i, value, shouldThrow);
28372837
return true;
28382838
}

0 commit comments

Comments
 (0)