[builtins] take slow path in IsConcatSpreadable if proxy in prototype

BUG=v8:5134
R=cbruni@chromium.org, littledan@chromium.org, neis@chromium.org

Review-Url: https://codereview.chromium.org/2131383002
Cr-Commit-Position: refs/heads/master@{#37987}
This commit is contained in:
caitp 2016-07-22 11:42:14 -07:00 committed by Commit bot
parent 7883414e8b
commit 122a9b7af0
7 changed files with 40 additions and 4 deletions

View File

@ -938,7 +938,7 @@ bool IterateElements(Isolate* isolate, Handle<JSReceiver> receiver,
static Maybe<bool> IsConcatSpreadable(Isolate* isolate, Handle<Object> obj) {
HandleScope handle_scope(isolate);
if (!obj->IsJSReceiver()) return Just(false);
if (!isolate->IsIsConcatSpreadableLookupChainIntact()) {
if (!isolate->IsIsConcatSpreadableLookupChainIntact(JSReceiver::cast(*obj))) {
// Slow path if @@isConcatSpreadable has been used.
Handle<Symbol> key(isolate->factory()->is_concat_spreadable_symbol());
Handle<Object> value;

View File

@ -2685,6 +2685,11 @@ bool Isolate::IsIsConcatSpreadableLookupChainIntact() {
return !is_is_concat_spreadable_set;
}
bool Isolate::IsIsConcatSpreadableLookupChainIntact(JSReceiver* receiver) {
if (!IsIsConcatSpreadableLookupChainIntact()) return false;
return !receiver->HasProxyInPrototype(this);
}
void Isolate::UpdateArrayProtectorOnSetElement(Handle<JSObject> object) {
DisallowHeapAllocation no_gc;
if (!object->map()->is_prototype_map()) return;

View File

@ -985,6 +985,7 @@ class Isolate {
inline bool IsArraySpeciesLookupChainIntact();
inline bool IsHasInstanceLookupChainIntact();
bool IsIsConcatSpreadableLookupChainIntact();
bool IsIsConcatSpreadableLookupChainIntact(JSReceiver* receiver);
// On intent to set an element in object, make sure that appropriate
// notifications occur if the set is on the elements of the array or

View File

@ -18986,5 +18986,14 @@ AccessCheckInfo* AccessCheckInfo::Get(Isolate* isolate,
return AccessCheckInfo::cast(data_obj);
}
bool JSReceiver::HasProxyInPrototype(Isolate* isolate) {
for (PrototypeIterator iter(isolate, this, kStartAtReceiver,
PrototypeIterator::END_AT_NULL);
!iter.IsAtEnd(); iter.AdvanceIgnoringProxies()) {
if (iter.GetCurrent<Object>()->IsJSProxy()) return true;
}
return false;
}
} // namespace internal
} // namespace v8

View File

@ -2008,6 +2008,8 @@ class JSReceiver: public HeapObject {
static const int kPropertiesOffset = HeapObject::kHeaderSize;
static const int kHeaderSize = HeapObject::kHeaderSize + kPointerSize;
bool HasProxyInPrototype(Isolate* isolate);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(JSReceiver);
};

View File

@ -872,3 +872,25 @@ logger.get = function(t, trap, r) {
assertThrows(() => [].concat(obj), TypeError);
assertThrows(() => Array.prototype.concat.apply(obj), TypeError);
})();
(function testConcatRevokedProxy() {
"use strict";
var target = [];
var handler = {
get(_, name) {
if (name === Symbol.isConcatSpreadable) {
p.revoke();
}
return target[name];
}
}
p = Proxy.revocable(target, handler);
target = {};
target.__proto__ = p.proxy;
assertThrows(function() { [].concat({ __proto__: p.proxy }); }, TypeError);
target = [];
var p = Proxy.revocable(target, handler);
assertThrows(function() { [].concat(p.proxy); }, TypeError);
})();

View File

@ -406,9 +406,6 @@
'annexB/built-ins/Object/prototype/__lookupSetter__/lookup-proto-get-err': [FAIL],
'annexB/built-ins/Object/prototype/__lookupSetter__/lookup-proto-proto-err': [FAIL],
# https://bugs.chromium.org/p/v8/issues/detail?id=5134
'built-ins/Array/prototype/concat/is-concat-spreadable-is-array-proxy-revoked': [FAIL],
# https://bugs.chromium.org/p/v8/issues/detail?id=4451
'annexB/language/eval-code/direct/global-block-decl-eval-global-exsting-global-init': [FAIL],
'annexB/language/eval-code/direct/global-if-decl-else-decl-a-eval-global-exsting-global-init': [FAIL],