From: dslomov@chromium.org Date: Fri, 17 Oct 2014 16:33:38 +0000 (+0000) Subject: Correct semantics for numerically indexed stores to typed arrays. X-Git-Tag: upstream/4.7.83~6279 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e3ad6930200b77bd2a9399eac025669ffa544870;p=platform%2Fupstream%2Fv8.git Correct semantics for numerically indexed stores to typed arrays. R=verwaest@chromium.org, ishell@chromium.org Committed: https://code.google.com/p/v8/source/detail?r=24691 Review URL: https://codereview.chromium.org/652303002 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24705 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/lookup.cc b/src/lookup.cc index b855abe97..bca0ab5d5 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 14ca010d3..52231e5d9 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 930342d20..1dff71eca 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -3077,6 +3077,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 5b75874cd..c70d8e5ea 100644 --- a/test/mjsunit/harmony/typedarrays.js +++ b/test/mjsunit/harmony/typedarrays.js @@ -481,6 +481,89 @@ 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]); + + /* Chromium bug: 424619 + * 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]); + + /* Chromium bug: 424619 + * 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);