From 3154c4a5f233c88f5edd34790902b1b0098dd6c1 Mon Sep 17 00:00:00 2001 From: "dslomov@chromium.org" Date: Fri, 17 Oct 2014 11:40:40 +0000 Subject: [PATCH] Correct semantics for numerically indexed stores to typed arrays. R=verwaest@chromium.org, ishell@chromium.org Review URL: https://codereview.chromium.org/652303002 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24691 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/lookup.cc | 18 +++++++++ src/lookup.h | 4 ++ src/objects.cc | 4 ++ test/mjsunit/harmony/typedarrays.js | 79 +++++++++++++++++++++++++++++++++++++ 4 files changed, 105 insertions(+) diff --git a/src/lookup.cc b/src/lookup.cc index b855abe..bca0ab5 100644 --- a/src/lookup.cc +++ b/src/lookup.cc @@ -309,6 +309,24 @@ void LookupIterator::WriteDataValue(Handle value) { } +bool LookupIterator::IsSpecialNumericIndex() const { + if (GetStoreTarget()->IsJSTypedArray() && name()->IsString()) { + Handle name_string = Handle::cast(name()); + if (name_string->length() > 0) { + double d = + StringToDouble(isolate()->unicode_cache(), *name_string, NO_FLAGS); + if (!std::isnan(d)) { + Factory* factory = isolate()->factory(); + Handle num = factory->NewNumber(d); + Handle roundtrip_string = factory->NumberToString(num); + if (String::Equals(name_string, roundtrip_string)) return true; + } + } + } + return false; +} + + void LookupIterator::InternalizeName() { if (name_->IsUniqueName()) return; name_ = factory()->InternalizeString(Handle::cast(name_)); diff --git a/src/lookup.h b/src/lookup.h index 14ca010..52231e5 100644 --- a/src/lookup.h +++ b/src/lookup.h @@ -138,6 +138,10 @@ class LookupIterator FINAL BASE_EMBEDDED { Handle GetDataValue() const; void WriteDataValue(Handle value); + // Checks whether the receiver is an indexed exotic object + // and name is a special numeric index. + bool IsSpecialNumericIndex() const; + void InternalizeName(); private: diff --git a/src/objects.cc b/src/objects.cc index 5e9e154..a697a77 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -2986,6 +2986,10 @@ MaybeHandle Object::AddDataProperty(LookupIterator* it, // instead. If the prototype is Null, the proxy is detached. 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 // |value| under it->name() with |attributes|. it->PrepareTransitionToDataProperty(value, attributes, store_mode); diff --git a/test/mjsunit/harmony/typedarrays.js b/test/mjsunit/harmony/typedarrays.js index 5b75874..59d09bb 100644 --- a/test/mjsunit/harmony/typedarrays.js +++ b/test/mjsunit/harmony/typedarrays.js @@ -481,6 +481,85 @@ function TestTypedArraySet() { TestTypedArraySet(); +function TestTypedArraysWithIllegalIndices() { + var a = new Int32Array(100); + + a[-10] = 10; + assertEquals(undefined, a[-10]); + a["-10"] = 10; + assertEquals(undefined, a["-10"]); + + var s = " -10"; + a[s] = 10; + assertEquals(10, a[s]); + var s1 = " -10 "; + a[s] = 10; + assertEquals(10, a[s]); + + a["-1e2"] = 10; + assertEquals(10, a["-1e2"]); + assertEquals(undefined, a[-1e2]); + + a[-Infinity] = 50; + assertEquals(undefined, a[-Infinity]); + a[1.5] = 10; + assertEquals(undefined, a[1.5]); + var nan = Math.sqrt(-1); + a[nan] = 5; + assertEquals(5, a[nan]); + + var x = 0; + var y = -0; + assertEquals(Infinity, 1/x); + assertEquals(-Infinity, 1/y); + a[x] = 5; + a[y] = 27; + assertEquals(27, a[x]); + assertEquals(27, a[y]); +} + +TestTypedArraysWithIllegalIndices(); + +function TestTypedArraysWithIllegalIndicesStrict() { + 'use strict'; + var a = new Int32Array(100); + + a[-10] = 10; + assertEquals(undefined, a[-10]); + a["-10"] = 10; + assertEquals(undefined, a["-10"]); + + var s = " -10"; + a[s] = 10; + assertEquals(10, a[s]); + var s1 = " -10 "; + a[s] = 10; + assertEquals(10, a[s]); + + a["-1e2"] = 10; + assertEquals(10, a["-1e2"]); + assertEquals(undefined, a[-1e2]); + + a[-Infinity] = 50; + assertEquals(undefined, a[-Infinity]); + a[1.5] = 10; + assertEquals(undefined, a[1.5]); + var nan = Math.sqrt(-1); + a[nan] = 5; + assertEquals(5, a[nan]); + + var x = 0; + var y = -0; + assertEquals(Infinity, 1/x); + assertEquals(-Infinity, 1/y); + a[x] = 5; + a[y] = 27; + assertEquals(27, a[x]); + assertEquals(27, a[y]); +} + +TestTypedArraysWithIllegalIndicesStrict(); + // DataView function TestDataViewConstructor() { var ab = new ArrayBuffer(256); -- 2.7.4