Commit 040225a3 authored by dcarney's avatar dcarney Committed by Commit bot

handle the special snowflakes that are Integer Indexed Exotic objects

the implementation doesn't yet throw on strict mode assignment

BUG=

Review URL: https://codereview.chromium.org/992913002

Cr-Commit-Position: refs/heads/master@{#27121}
parent fd012f10
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "src/v8.h" #include "src/v8.h"
#include "src/assert-scope.h" #include "src/assert-scope.h"
#include "src/char-predicates-inl.h"
#include "src/conversions-inl.h" #include "src/conversions-inl.h"
#include "src/conversions.h" #include "src/conversions.h"
#include "src/dtoa.h" #include "src/dtoa.h"
...@@ -502,4 +503,54 @@ double StringToDouble(UnicodeCache* unicode_cache, Handle<String> string, ...@@ -502,4 +503,54 @@ double StringToDouble(UnicodeCache* unicode_cache, Handle<String> string,
} }
bool IsNonArrayIndexInteger(String* string) {
const int kBufferSize = 64;
const int kUint32MaxChars = 11;
uint16_t buffer[kBufferSize];
int offset = 0;
const int length = string->length();
DCHECK_NE(0, length);
// First iteration, check for minus, 0 followed by anything else, etc.
int to = std::min(offset + kUint32MaxChars, length);
{
String::WriteToFlat(string, buffer, offset, to);
bool negative = false;
if (buffer[offset] == '-') {
negative = true;
++offset;
if (offset == to) return false; // Just '-' is bad.
}
if (buffer[offset] == '0') {
return to == 2 && negative; // Match just '-0'.
}
// Process positive integers.
if (!negative) {
uint64_t acc = 0;
for (; offset < to; ++offset) {
uint64_t digit = buffer[offset] - '0';
if (digit > 9) return false;
acc = 10 * acc + digit;
}
// String is consumed. Evaluate what we have.
if (offset == length) {
return acc >
static_cast<uint64_t>(std::numeric_limits<uint32_t>::max());
}
}
}
// Consume rest of string. If we get here, we're way out of uint32_t bounds
// or negative.
int i = offset;
while (true) {
for (; offset < to; ++offset, ++i) {
if (!IsDecimalDigit(buffer[i])) return false;
}
if (offset == length) break;
// Read next chunk.
to = std::min(offset + kBufferSize, length);
String::WriteToFlat(string, buffer, offset, to);
i = 0;
}
return true;
}
} } // namespace v8::internal } } // namespace v8::internal
...@@ -236,6 +236,8 @@ inline size_t NumberToSize(Isolate* isolate, ...@@ -236,6 +236,8 @@ inline size_t NumberToSize(Isolate* isolate,
return result; return result;
} }
bool IsNonArrayIndexInteger(String* string);
} } // namespace v8::internal } } // namespace v8::internal
#endif // V8_CONVERSIONS_H_ #endif // V8_CONVERSIONS_H_
...@@ -5266,6 +5266,7 @@ HOptimizedGraphBuilder::LookupGlobalProperty(Variable* var, LookupIterator* it, ...@@ -5266,6 +5266,7 @@ HOptimizedGraphBuilder::LookupGlobalProperty(Variable* var, LookupIterator* it,
case LookupIterator::ACCESSOR: case LookupIterator::ACCESSOR:
case LookupIterator::ACCESS_CHECK: case LookupIterator::ACCESS_CHECK:
case LookupIterator::INTERCEPTOR: case LookupIterator::INTERCEPTOR:
case LookupIterator::INTEGER_INDEXED_EXOTIC:
case LookupIterator::NOT_FOUND: case LookupIterator::NOT_FOUND:
return kUseGeneric; return kUseGeneric;
case LookupIterator::DATA: case LookupIterator::DATA:
...@@ -6071,6 +6072,12 @@ bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes() { ...@@ -6071,6 +6072,12 @@ bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes() {
} }
bool HOptimizedGraphBuilder::PropertyAccessInfo::IsIntegerIndexedExotic() {
InstanceType instance_type = map_->instance_type();
return instance_type == JS_TYPED_ARRAY_TYPE && IsNonArrayIndexInteger(*name_);
}
bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessMonomorphic() { bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessMonomorphic() {
if (!CanInlinePropertyAccess(map_)) return false; if (!CanInlinePropertyAccess(map_)) return false;
if (IsJSObjectFieldAccessor()) return IsLoad(); if (IsJSObjectFieldAccessor()) return IsLoad();
...@@ -6080,6 +6087,7 @@ bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessMonomorphic() { ...@@ -6080,6 +6087,7 @@ bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessMonomorphic() {
} }
if (!LookupDescriptor()) return false; if (!LookupDescriptor()) return false;
if (IsFound()) return IsLoad() || !IsReadOnly(); if (IsFound()) return IsLoad() || !IsReadOnly();
if (IsIntegerIndexedExotic()) return false;
if (!LookupInPrototypes()) return false; if (!LookupInPrototypes()) return false;
if (IsLoad()) return true; if (IsLoad()) return true;
......
...@@ -2641,6 +2641,7 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor { ...@@ -2641,6 +2641,7 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
void LoadFieldMaps(Handle<Map> map); void LoadFieldMaps(Handle<Map> map);
bool LookupDescriptor(); bool LookupDescriptor();
bool LookupInPrototypes(); bool LookupInPrototypes();
bool IsIntegerIndexedExotic();
bool IsCompatible(PropertyAccessInfo* other); bool IsCompatible(PropertyAccessInfo* other);
void GeneralizeRepresentation(Representation r) { void GeneralizeRepresentation(Representation r) {
......
...@@ -280,6 +280,7 @@ Handle<Code> NamedLoadHandlerCompiler::CompileLoadInterceptor( ...@@ -280,6 +280,7 @@ Handle<Code> NamedLoadHandlerCompiler::CompileLoadInterceptor(
case LookupIterator::INTERCEPTOR: case LookupIterator::INTERCEPTOR:
case LookupIterator::JSPROXY: case LookupIterator::JSPROXY:
case LookupIterator::NOT_FOUND: case LookupIterator::NOT_FOUND:
case LookupIterator::INTEGER_INDEXED_EXOTIC:
break; break;
case LookupIterator::DATA: case LookupIterator::DATA:
inline_followup = inline_followup =
...@@ -346,6 +347,7 @@ void NamedLoadHandlerCompiler::GenerateLoadPostInterceptor( ...@@ -346,6 +347,7 @@ void NamedLoadHandlerCompiler::GenerateLoadPostInterceptor(
case LookupIterator::INTERCEPTOR: case LookupIterator::INTERCEPTOR:
case LookupIterator::JSPROXY: case LookupIterator::JSPROXY:
case LookupIterator::NOT_FOUND: case LookupIterator::NOT_FOUND:
case LookupIterator::INTEGER_INDEXED_EXOTIC:
case LookupIterator::TRANSITION: case LookupIterator::TRANSITION:
UNREACHABLE(); UNREACHABLE();
case LookupIterator::DATA: { case LookupIterator::DATA: {
......
...@@ -262,6 +262,7 @@ static void LookupForRead(LookupIterator* it) { ...@@ -262,6 +262,7 @@ static void LookupForRead(LookupIterator* it) {
} }
return; return;
case LookupIterator::ACCESSOR: case LookupIterator::ACCESSOR:
case LookupIterator::INTEGER_INDEXED_EXOTIC:
case LookupIterator::DATA: case LookupIterator::DATA:
return; return;
} }
...@@ -1316,6 +1317,8 @@ Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup, ...@@ -1316,6 +1317,8 @@ Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup,
lookup->GetConstantIndex()); lookup->GetConstantIndex());
} }
case LookupIterator::INTEGER_INDEXED_EXOTIC:
return slow_stub();
case LookupIterator::ACCESS_CHECK: case LookupIterator::ACCESS_CHECK:
case LookupIterator::JSPROXY: case LookupIterator::JSPROXY:
case LookupIterator::NOT_FOUND: case LookupIterator::NOT_FOUND:
...@@ -1506,6 +1509,8 @@ bool StoreIC::LookupForWrite(LookupIterator* it, Handle<Object> value, ...@@ -1506,6 +1509,8 @@ bool StoreIC::LookupForWrite(LookupIterator* it, Handle<Object> value,
break; break;
case LookupIterator::ACCESSOR: case LookupIterator::ACCESSOR:
return !it->IsReadOnly(); return !it->IsReadOnly();
case LookupIterator::INTEGER_INDEXED_EXOTIC:
return false;
case LookupIterator::DATA: { case LookupIterator::DATA: {
if (it->IsReadOnly()) return false; if (it->IsReadOnly()) return false;
Handle<JSObject> holder = it->GetHolder<JSObject>(); Handle<JSObject> holder = it->GetHolder<JSObject>();
...@@ -1530,7 +1535,6 @@ bool StoreIC::LookupForWrite(LookupIterator* it, Handle<Object> value, ...@@ -1530,7 +1535,6 @@ bool StoreIC::LookupForWrite(LookupIterator* it, Handle<Object> value,
} }
} }
if (it->IsSpecialNumericIndex()) return false;
it->PrepareTransitionToDataProperty(value, NONE, store_mode); it->PrepareTransitionToDataProperty(value, NONE, store_mode);
return it->IsCacheableTransition(); return it->IsCacheableTransition();
} }
...@@ -1835,6 +1839,7 @@ Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup, ...@@ -1835,6 +1839,7 @@ Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup,
break; break;
} }
case LookupIterator::INTEGER_INDEXED_EXOTIC:
case LookupIterator::ACCESS_CHECK: case LookupIterator::ACCESS_CHECK:
case LookupIterator::JSPROXY: case LookupIterator::JSPROXY:
case LookupIterator::NOT_FOUND: case LookupIterator::NOT_FOUND:
......
...@@ -44,6 +44,10 @@ LookupIterator::State LookupIterator::LookupInHolder(Map* map, ...@@ -44,6 +44,10 @@ LookupIterator::State LookupIterator::LookupInHolder(Map* map,
} }
// Fall through. // Fall through.
case ACCESS_CHECK: case ACCESS_CHECK:
if (exotic_index_state_ != ExoticIndexState::kNoIndex &&
IsIntegerIndexedExotic(holder)) {
return INTEGER_INDEXED_EXOTIC;
}
if (check_interceptor() && map->has_named_interceptor()) { if (check_interceptor() && map->has_named_interceptor()) {
return INTERCEPTOR; return INTERCEPTOR;
} }
...@@ -75,6 +79,7 @@ LookupIterator::State LookupIterator::LookupInHolder(Map* map, ...@@ -75,6 +79,7 @@ LookupIterator::State LookupIterator::LookupInHolder(Map* map,
case ACCESSOR: case ACCESSOR:
case DATA: case DATA:
return NOT_FOUND; return NOT_FOUND;
case INTEGER_INDEXED_EXOTIC:
case JSPROXY: case JSPROXY:
case TRANSITION: case TRANSITION:
UNREACHABLE(); UNREACHABLE();
......
...@@ -120,9 +120,9 @@ void LookupIterator::PrepareTransitionToDataProperty( ...@@ -120,9 +120,9 @@ void LookupIterator::PrepareTransitionToDataProperty(
Handle<Object> value, PropertyAttributes attributes, Handle<Object> value, PropertyAttributes attributes,
Object::StoreFromKeyed store_mode) { Object::StoreFromKeyed store_mode) {
if (state_ == TRANSITION) return; if (state_ == TRANSITION) return;
DCHECK(state_ != LookupIterator::ACCESSOR); DCHECK_NE(LookupIterator::ACCESSOR, state_);
DCHECK_NE(LookupIterator::INTEGER_INDEXED_EXOTIC, state_);
DCHECK(state_ == NOT_FOUND || !HolderIsReceiverOrHiddenPrototype()); DCHECK(state_ == NOT_FOUND || !HolderIsReceiverOrHiddenPrototype());
DCHECK(!IsSpecialNumericIndex());
// Can only be called when the receiver is a JSObject. JSProxy has to be // Can only be called when the receiver is a JSObject. JSProxy has to be
// handled via a trap. Adding properties to primitive values is not // handled via a trap. Adding properties to primitive values is not
// observable. // observable.
...@@ -333,25 +333,23 @@ Handle<Object> LookupIterator::WriteDataValue(Handle<Object> value) { ...@@ -333,25 +333,23 @@ Handle<Object> LookupIterator::WriteDataValue(Handle<Object> value) {
} }
bool LookupIterator::IsSpecialNumericIndex() const { bool LookupIterator::IsIntegerIndexedExotic(JSReceiver* holder) {
if (GetStoreTarget()->IsJSTypedArray() && name()->IsString()) { DCHECK(exotic_index_state_ != ExoticIndexState::kNoIndex);
// Currently typed arrays are the only such objects.
if (!holder->IsJSTypedArray()) return false;
if (exotic_index_state_ == ExoticIndexState::kIndex) return true;
DCHECK(exotic_index_state_ == ExoticIndexState::kUninitialized);
bool result = false;
// Compute and cache result.
if (name()->IsString()) {
Handle<String> name_string = Handle<String>::cast(name()); Handle<String> name_string = Handle<String>::cast(name());
if (name_string->length() > 0) { if (name_string->length() != 0) {
double d = result = IsNonArrayIndexInteger(*name_string);
StringToDouble(isolate()->unicode_cache(), name_string, NO_FLAGS);
if (!std::isnan(d)) {
if (String::Equals(isolate()->factory()->minus_zero_string(),
name_string))
return true;
Factory* factory = isolate()->factory();
Handle<Object> num = factory->NewNumber(d);
Handle<String> roundtrip_string = factory->NumberToString(num);
if (String::Equals(name_string, roundtrip_string)) return true;
}
} }
} }
return false; exotic_index_state_ =
result ? ExoticIndexState::kIndex : ExoticIndexState::kNoIndex;
return result;
} }
......
...@@ -31,6 +31,7 @@ class LookupIterator FINAL BASE_EMBEDDED { ...@@ -31,6 +31,7 @@ class LookupIterator FINAL BASE_EMBEDDED {
enum State { enum State {
ACCESS_CHECK, ACCESS_CHECK,
INTEGER_INDEXED_EXOTIC,
INTERCEPTOR, INTERCEPTOR,
JSPROXY, JSPROXY,
NOT_FOUND, NOT_FOUND,
...@@ -46,6 +47,7 @@ class LookupIterator FINAL BASE_EMBEDDED { ...@@ -46,6 +47,7 @@ class LookupIterator FINAL BASE_EMBEDDED {
Configuration configuration = PROTOTYPE_CHAIN) Configuration configuration = PROTOTYPE_CHAIN)
: configuration_(ComputeConfiguration(configuration, name)), : configuration_(ComputeConfiguration(configuration, name)),
state_(NOT_FOUND), state_(NOT_FOUND),
exotic_index_state_(ExoticIndexState::kUninitialized),
property_details_(NONE, v8::internal::DATA, 0), property_details_(NONE, v8::internal::DATA, 0),
isolate_(name->GetIsolate()), isolate_(name->GetIsolate()),
name_(name), name_(name),
...@@ -61,6 +63,7 @@ class LookupIterator FINAL BASE_EMBEDDED { ...@@ -61,6 +63,7 @@ class LookupIterator FINAL BASE_EMBEDDED {
Configuration configuration = PROTOTYPE_CHAIN) Configuration configuration = PROTOTYPE_CHAIN)
: configuration_(ComputeConfiguration(configuration, name)), : configuration_(ComputeConfiguration(configuration, name)),
state_(NOT_FOUND), state_(NOT_FOUND),
exotic_index_state_(ExoticIndexState::kUninitialized),
property_details_(NONE, v8::internal::DATA, 0), property_details_(NONE, v8::internal::DATA, 0),
isolate_(name->GetIsolate()), isolate_(name->GetIsolate()),
name_(name), name_(name),
...@@ -140,11 +143,6 @@ class LookupIterator FINAL BASE_EMBEDDED { ...@@ -140,11 +143,6 @@ class LookupIterator FINAL BASE_EMBEDDED {
// Usually returns the value that was passed in, but may perform // Usually returns the value that was passed in, but may perform
// non-observable modifications on it, such as internalize strings. // non-observable modifications on it, such as internalize strings.
Handle<Object> WriteDataValue(Handle<Object> value); Handle<Object> WriteDataValue(Handle<Object> value);
// Checks whether the receiver is an indexed exotic object
// and name is a special numeric index.
bool IsSpecialNumericIndex() const;
void InternalizeName(); void InternalizeName();
private: private:
...@@ -185,11 +183,15 @@ class LookupIterator FINAL BASE_EMBEDDED { ...@@ -185,11 +183,15 @@ class LookupIterator FINAL BASE_EMBEDDED {
} }
} }
enum class ExoticIndexState { kUninitialized, kNoIndex, kIndex };
bool IsIntegerIndexedExotic(JSReceiver* holder);
// If configuration_ becomes mutable, update // If configuration_ becomes mutable, update
// HolderIsReceiverOrHiddenPrototype. // HolderIsReceiverOrHiddenPrototype.
Configuration configuration_; Configuration configuration_;
State state_; State state_;
bool has_property_; bool has_property_;
ExoticIndexState exotic_index_state_;
PropertyDetails property_details_; PropertyDetails property_details_;
Isolate* isolate_; Isolate* isolate_;
Handle<Name> name_; Handle<Name> name_;
......
...@@ -133,6 +133,8 @@ MaybeHandle<Object> Object::GetProperty(LookupIterator* it) { ...@@ -133,6 +133,8 @@ MaybeHandle<Object> Object::GetProperty(LookupIterator* it) {
return GetPropertyWithAccessor(it->GetReceiver(), it->name(), return GetPropertyWithAccessor(it->GetReceiver(), it->name(),
it->GetHolder<JSObject>(), it->GetHolder<JSObject>(),
it->GetAccessors()); it->GetAccessors());
case LookupIterator::INTEGER_INDEXED_EXOTIC:
return it->factory()->undefined_value();
case LookupIterator::DATA: case LookupIterator::DATA:
return it->GetDataValue(); return it->GetDataValue();
} }
...@@ -168,6 +170,8 @@ Handle<Object> JSObject::GetDataProperty(LookupIterator* it) { ...@@ -168,6 +170,8 @@ Handle<Object> JSObject::GetDataProperty(LookupIterator* it) {
// relevant. // relevant.
it->NotFound(); it->NotFound();
return it->isolate()->factory()->undefined_value(); return it->isolate()->factory()->undefined_value();
case LookupIterator::INTEGER_INDEXED_EXOTIC:
return it->isolate()->factory()->undefined_value();
case LookupIterator::DATA: case LookupIterator::DATA:
return it->GetDataValue(); return it->GetDataValue();
} }
...@@ -3130,6 +3134,10 @@ MaybeHandle<Object> Object::SetPropertyInternal(LookupIterator* it, ...@@ -3130,6 +3134,10 @@ MaybeHandle<Object> Object::SetPropertyInternal(LookupIterator* it,
it->GetHolder<JSObject>(), it->GetHolder<JSObject>(),
it->GetAccessors(), language_mode); it->GetAccessors(), language_mode);
case LookupIterator::INTEGER_INDEXED_EXOTIC:
done = true;
break;
case LookupIterator::DATA: case LookupIterator::DATA:
if (it->property_details().IsReadOnly()) { if (it->property_details().IsReadOnly()) {
return WriteToReadOnlyProperty(it, value, language_mode); return WriteToReadOnlyProperty(it, value, language_mode);
...@@ -3192,6 +3200,9 @@ MaybeHandle<Object> Object::SetSuperProperty(LookupIterator* it, ...@@ -3192,6 +3200,9 @@ MaybeHandle<Object> Object::SetSuperProperty(LookupIterator* it,
return JSObject::AddDataProperty(&own_lookup, value, NONE, language_mode, return JSObject::AddDataProperty(&own_lookup, value, NONE, language_mode,
store_mode); store_mode);
case LookupIterator::INTEGER_INDEXED_EXOTIC:
return result;
case LookupIterator::DATA: { case LookupIterator::DATA: {
PropertyDetails details = own_lookup.property_details(); PropertyDetails details = own_lookup.property_details();
if (details.IsConfigurable() || !details.IsReadOnly()) { if (details.IsConfigurable() || !details.IsReadOnly()) {
...@@ -3321,16 +3332,14 @@ MaybeHandle<Object> Object::AddDataProperty(LookupIterator* it, ...@@ -3321,16 +3332,14 @@ MaybeHandle<Object> Object::AddDataProperty(LookupIterator* it,
return WriteToReadOnlyProperty(it, value, language_mode); return WriteToReadOnlyProperty(it, value, language_mode);
} }
if (it->state() == LookupIterator::INTEGER_INDEXED_EXOTIC) return value;
Handle<JSObject> receiver = it->GetStoreTarget(); Handle<JSObject> receiver = it->GetStoreTarget();
// If the receiver is a JSGlobalProxy, store on the prototype (JSGlobalObject) // If the receiver is a JSGlobalProxy, store on the prototype (JSGlobalObject)
// instead. If the prototype is Null, the proxy is detached. // instead. If the prototype is Null, the proxy is detached.
if (receiver->IsJSGlobalProxy()) return value; if (receiver->IsJSGlobalProxy()) return value;
// If the receiver is Indexed Exotic object (currently only typed arrays),
// disallow adding properties with numeric names.
if (it->IsSpecialNumericIndex()) return value;
// Possibly migrate to the most up-to-date map that will be able to store // Possibly migrate to the most up-to-date map that will be able to store
// |value| under it->name() with |attributes|. // |value| under it->name() with |attributes|.
it->PrepareTransitionToDataProperty(value, attributes, store_mode); it->PrepareTransitionToDataProperty(value, attributes, store_mode);
...@@ -4158,6 +4167,7 @@ MaybeHandle<Object> JSObject::SetOwnPropertyIgnoreAttributes( ...@@ -4158,6 +4167,7 @@ MaybeHandle<Object> JSObject::SetOwnPropertyIgnoreAttributes(
!it.isolate()->IsInternallyUsedPropertyName(name); !it.isolate()->IsInternallyUsedPropertyName(name);
for (; it.IsFound(); it.Next()) { for (; it.IsFound(); it.Next()) {
switch (it.state()) { switch (it.state()) {
case LookupIterator::INTEGER_INDEXED_EXOTIC:
case LookupIterator::INTERCEPTOR: case LookupIterator::INTERCEPTOR:
case LookupIterator::JSPROXY: case LookupIterator::JSPROXY:
case LookupIterator::NOT_FOUND: case LookupIterator::NOT_FOUND:
...@@ -4336,6 +4346,8 @@ Maybe<PropertyAttributes> JSReceiver::GetPropertyAttributes( ...@@ -4336,6 +4346,8 @@ Maybe<PropertyAttributes> JSReceiver::GetPropertyAttributes(
case LookupIterator::ACCESS_CHECK: case LookupIterator::ACCESS_CHECK:
if (it->HasAccess()) break; if (it->HasAccess()) break;
return JSObject::GetPropertyAttributesWithFailedAccessCheck(it); return JSObject::GetPropertyAttributesWithFailedAccessCheck(it);
case LookupIterator::INTEGER_INDEXED_EXOTIC:
return Just(ABSENT);
case LookupIterator::ACCESSOR: case LookupIterator::ACCESSOR:
case LookupIterator::DATA: case LookupIterator::DATA:
return Just(it->property_details().attributes()); return Just(it->property_details().attributes());
...@@ -5337,6 +5349,8 @@ MaybeHandle<Object> JSObject::DeleteProperty(Handle<JSObject> object, ...@@ -5337,6 +5349,8 @@ MaybeHandle<Object> JSObject::DeleteProperty(Handle<JSObject> object,
if (it.isolate()->has_pending_exception()) return maybe_result; if (it.isolate()->has_pending_exception()) return maybe_result;
break; break;
} }
case LookupIterator::INTEGER_INDEXED_EXOTIC:
return it.isolate()->factory()->true_value();
case LookupIterator::DATA: case LookupIterator::DATA:
if (is_observed) { if (is_observed) {
old_value = it.GetDataValue(); old_value = it.GetDataValue();
...@@ -6764,6 +6778,8 @@ MaybeHandle<Object> JSObject::GetAccessor(Handle<JSObject> object, ...@@ -6764,6 +6778,8 @@ MaybeHandle<Object> JSObject::GetAccessor(Handle<JSObject> object,
case LookupIterator::JSPROXY: case LookupIterator::JSPROXY:
return isolate->factory()->undefined_value(); return isolate->factory()->undefined_value();
case LookupIterator::INTEGER_INDEXED_EXOTIC:
return isolate->factory()->undefined_value();
case LookupIterator::DATA: case LookupIterator::DATA:
continue; continue;
case LookupIterator::ACCESSOR: { case LookupIterator::ACCESSOR: {
......
...@@ -72,6 +72,7 @@ static Handle<Object> DebugGetProperty(LookupIterator* it, ...@@ -72,6 +72,7 @@ static Handle<Object> DebugGetProperty(LookupIterator* it,
case LookupIterator::ACCESS_CHECK: case LookupIterator::ACCESS_CHECK:
// Ignore access checks. // Ignore access checks.
break; break;
case LookupIterator::INTEGER_INDEXED_EXOTIC:
case LookupIterator::INTERCEPTOR: case LookupIterator::INTERCEPTOR:
case LookupIterator::JSPROXY: case LookupIterator::JSPROXY:
return it->isolate()->factory()->undefined_value(); return it->isolate()->factory()->undefined_value();
......
...@@ -362,3 +362,57 @@ TEST(BitField64) { ...@@ -362,3 +362,57 @@ TEST(BitField64) {
CHECK(x == MiddleBits::encode(3)); CHECK(x == MiddleBits::encode(3));
CHECK_EQ(3, MiddleBits::decode(x)); CHECK_EQ(3, MiddleBits::decode(x));
} }
static void CheckNonArrayIndex(bool expected, const char* chars) {
auto isolate = CcTest::i_isolate();
auto string = isolate->factory()->NewStringFromAsciiChecked(chars);
CHECK_EQ(expected, IsNonArrayIndexInteger(*string));
}
TEST(NonArrayIndexParsing) {
auto isolate = CcTest::i_isolate();
HandleScope scope(isolate);
CheckNonArrayIndex(false, "-");
CheckNonArrayIndex(false, "0");
CheckNonArrayIndex(false, "01");
CheckNonArrayIndex(false, "-01");
CheckNonArrayIndex(false, "4294967295");
CheckNonArrayIndex(false, "429496.7295");
CheckNonArrayIndex(false, "43s3");
CheckNonArrayIndex(true, "-0");
CheckNonArrayIndex(true, "-1");
CheckNonArrayIndex(true, "4294967296");
CheckNonArrayIndex(true, "-4294967296");
CheckNonArrayIndex(
true,
"429496729642949672964294967296429496729642949672964294967296"
"429496729642949672964294967296429496729642949672964294967296"
"429496729642949672964294967296429496729642949672964294967296"
"429496729642949672964294967296429496729642949672964294967296"
"429496729642949672964294967296429496729642949672964294967296"
"429496729642949672964294967296429496729642949672964294967296"
"429496729642949672964294967296429496729642949672964294967296"
"429496729642949672964294967296429496729642949672964294967296"
"429496729642949672964294967296429496729642949672964294967296"
"429496729642949672964294967296429496729642949672964294967296"
"429496729642949672964294967296429496729642949672964294967296"
"429496729642949672964294967296429496729642949672964294967296"
"429496729642949672964294967296429496729642949672964294967296");
CheckNonArrayIndex(
true,
"-429496729642949672964294967296429496729642949672964294967296"
"429496729642949672964294967296429496729642949672964294967296"
"429496729642949672964294967296429496729642949672964294967296"
"429496729642949672964294967296429496729642949672964294967296"
"429496729642949672964294967296429496729642949672964294967296"
"429496729642949672964294967296429496729642949672964294967296"
"429496729642949672964294967296429496729642949672964294967296"
"429496729642949672964294967296429496729642949672964294967296"
"429496729642949672964294967296429496729642949672964294967296"
"429496729642949672964294967296429496729642949672964294967296"
"429496729642949672964294967296429496729642949672964294967296"
"429496729642949672964294967296429496729642949672964294967296"
"429496729642949672964294967296429496729642949672964294967296");
}
// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax
Object.prototype["10"] = "unreachable";
Object.prototype["7"] = "unreachable";
Object.prototype["-1"] = "unreachable";
Object.prototype["-0"] = "unreachable";
Object.prototype["4294967296"] = "unreachable";
var array = new Int32Array(10);
function check() {
for (var i = 0; i < 4; i++) {
assertEquals(undefined, array["-1"]);
assertEquals(undefined, array["-0"]);
assertEquals(undefined, array["10"]);
assertEquals(undefined, array["4294967296"]);
}
assertEquals("unreachable", array.__proto__["-1"]);
assertEquals("unreachable", array.__proto__["-0"]);
assertEquals("unreachable", array.__proto__["10"]);
assertEquals("unreachable", array.__proto__["4294967296"]);
}
check();
array["-1"] = "unreachable";
array["-0"] = "unreachable";
array["10"] = "unreachable";
array["4294967296"] = "unreachable";
check();
delete array["-0"];
delete array["-1"];
delete array["10"];
delete array["4294967296"];
assertEquals(undefined, Object.getOwnPropertyDescriptor(array, "-1"));
assertEquals(undefined, Object.getOwnPropertyDescriptor(array, "-0"));
assertEquals(undefined, Object.getOwnPropertyDescriptor(array, "10"));
assertEquals(undefined, Object.getOwnPropertyDescriptor(array, "4294967296"));
assertEquals(10, Object.keys(array).length);
check();
function f() { return array["-1"]; }
for (var i = 0; i < 3; i++) {
assertEquals(undefined, f());
}
%OptimizeFunctionOnNextCall(f);
assertEquals(undefined, f());
...@@ -530,7 +530,7 @@ function TestTypedArraysWithIllegalIndices() { ...@@ -530,7 +530,7 @@ function TestTypedArraysWithIllegalIndices() {
* assertEquals(undefined, a[-Infinity]); * assertEquals(undefined, a[-Infinity]);
*/ */
a[1.5] = 10; a[1.5] = 10;
assertEquals(undefined, a[1.5]); assertEquals(10, a[1.5]);
var nan = Math.sqrt(-1); var nan = Math.sqrt(-1);
a[nan] = 5; a[nan] = 5;
assertEquals(5, a[nan]); assertEquals(5, a[nan]);
...@@ -579,7 +579,7 @@ function TestTypedArraysWithIllegalIndicesStrict() { ...@@ -579,7 +579,7 @@ function TestTypedArraysWithIllegalIndicesStrict() {
* assertEquals(undefined, a[-Infinity]); * assertEquals(undefined, a[-Infinity]);
*/ */
a[1.5] = 10; a[1.5] = 10;
assertEquals(undefined, a[1.5]); assertEquals(10, a[1.5]);
var nan = Math.sqrt(-1); var nan = Math.sqrt(-1);
a[nan] = 5; a[nan] = 5;
assertEquals(5, a[nan]); assertEquals(5, a[nan]);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment