Index: test/mjsunit/strong/load-element.js |
diff --git a/test/mjsunit/strong/load-element.js b/test/mjsunit/strong/load-element.js |
new file mode 100644 |
index 0000000000000000000000000000000000000000..4007b7db6163325b53dc5472ceb0f3d03f16b7cd |
--- /dev/null |
+++ b/test/mjsunit/strong/load-element.js |
@@ -0,0 +1,267 @@ |
+// Copyright 2015 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: --strong-mode --allow-natives-syntax |
+ |
+function getSloppyArguments() { |
+ return arguments; |
+} |
+ |
+function getObjects() { |
+ "use strict"; |
+ return [ |
+ {}, |
+ Object(""), |
+ [], |
+ (function(){}), |
+ (class Foo {}), |
+ getSloppyArguments(), |
+ arguments, |
+ new Date() |
+ ]; |
+} |
+ |
+//TODO(conradw): add tests for non-inheritance once semantics are implemented. |
+function getNonInheritingObjects() { |
+ "use strong"; |
+ return [ |
+ Object(""), |
+ [], |
+ new Uint32Array(0) |
+ ]; |
+} |
+ |
+function readFromObjectElementSloppy(o) { |
+ return o[0]; |
+} |
+ |
+function readFromObjectElementSparseSloppy(o) { |
+ return o[100000]; |
+} |
+ |
+function readFromObjectElementNonSmiSloppy(o) { |
+ return o[3000000000]; |
+} |
+ |
+function readFromObjectNonIndexSloppy(o) { |
+ return o[5000000000]; |
+} |
+ |
+function readFromObjectElementVarSloppy(o) { |
+ var a = 0; |
+ return o[a]; |
+} |
+ |
+function readFromObjectElementSparseVarSloppy(o) { |
+ var a = 100000; |
+ return o[a]; |
+} |
+ |
+function readFromObjectElementNonSmiVarSloppy(o) { |
+ var a = 3000000000; |
+ return o[a]; |
+} |
+ |
+function readFromObjectNonIndexVarSloppy(o) { |
+ var a = 5000000000; |
+ return o[a]; |
+} |
+ |
+function readFromObjectElementStrong(o) { |
+ "use strong"; |
+ return o[0]; |
+} |
+ |
+function readFromObjectElementSparseStrong(o) { |
+ "use strong"; |
+ return o[100000]; |
+} |
+ |
+function readFromObjectElementNonSmiStrong(o) { |
+ "use strong"; |
+ return o[3000000000]; |
+} |
+ |
+function readFromObjectNonIndexStrong(o) { |
+ "use strong"; |
+ return o[5000000000]; |
+} |
+ |
+function readFromObjectElementLetStrong(o) { |
+ "use strong"; |
+ let a = 0; |
+ return o[a]; |
+} |
+ |
+function readFromObjectElementSparseLetStrong(o) { |
+ "use strong"; |
+ let a = 100000; |
+ return o[a]; |
+} |
+ |
+function readFromObjectElementNonSmiLetStrong(o) { |
+ "use strong"; |
+ let a = 3000000000; |
+ return o[a]; |
+} |
+ |
+function readFromObjectNonIndexLetStrong(o) { |
+ "use strong"; |
+ let a = 5000000000; |
+ return o[a]; |
+} |
+ |
+function getDescs(x) { |
+ return [ |
+ {value: x}, |
+ {configurable: true, enumerable: true, writable: true, value: x}, |
+ {configurable: true, enumerable: true, get: (function() {return x}) }, |
+ ]; |
+} |
+ |
+function assertStrongSemantics(func, object) { |
+ %DeoptimizeFunction(func); |
+ %ClearFunctionTypeFeedback(func); |
+ assertThrows(function(){func(object)}, TypeError); |
+ assertThrows(function(){func(object)}, TypeError); |
+ assertThrows(function(){func(object)}, TypeError); |
+ %OptimizeFunctionOnNextCall(func); |
+ assertThrows(function(){func(object)}, TypeError); |
+ %DeoptimizeFunction(func); |
+ assertThrows(function(){func(object)}, TypeError); |
+} |
+ |
+function assertSloppySemantics(func, object) { |
+ %DeoptimizeFunction(func); |
+ %ClearFunctionTypeFeedback(func); |
+ assertDoesNotThrow(function(){func(object)}); |
+ assertDoesNotThrow(function(){func(object)}); |
+ assertDoesNotThrow(function(){func(object)}); |
+ %OptimizeFunctionOnNextCall(func); |
+ assertDoesNotThrow(function(){func(object)}); |
+ %DeoptimizeFunction(func); |
+ assertDoesNotThrow(function(){func(object)}); |
+} |
+ |
+(function () { |
+ "use strict"; |
+ |
+ let goodKeys = [ |
+ "0", |
+ "100000", |
+ "3000000000", |
+ "5000000000" |
+ ] |
+ |
+ let badKeys = [ |
+ "bar", |
+ "1", |
+ "100001", |
+ "3000000001", |
+ "5000000001" |
+ ]; |
+ |
+ let values = [ |
+ "string", |
+ 1, |
+ 100001, |
+ 30000000001, |
+ 50000000001, |
+ NaN, |
+ {}, |
+ undefined |
+ ]; |
+ |
+ let literals = [0, NaN, true, ""]; |
+ |
+ let badAccessorDescs = [ |
+ { set: (function(){}) }, |
+ { configurable: true, enumerable: true, set: (function(){}) } |
+ ]; |
+ |
+ let readSloppy = [ |
+ readFromObjectElementSloppy, |
+ readFromObjectElementSparseSloppy, |
+ readFromObjectElementNonSmiSloppy, |
+ readFromObjectNonIndexSloppy, |
+ readFromObjectElementVarSloppy, |
+ readFromObjectElementSparseVarSloppy, |
+ readFromObjectElementNonSmiVarSloppy, |
+ readFromObjectNonIndexVarSloppy |
+ ]; |
+ |
+ let readStrong = [ |
+ readFromObjectElementStrong, |
+ readFromObjectElementSparseStrong, |
+ readFromObjectElementNonSmiStrong, |
+ readFromObjectNonIndexStrong, |
+ readFromObjectElementLetStrong, |
+ readFromObjectElementSparseLetStrong, |
+ readFromObjectElementNonSmiLetStrong, |
+ readFromObjectNonIndexLetStrong |
+ ]; |
+ |
+ let dummyProto = {}; |
+ for (let key of goodKeys) { |
+ Object.defineProperty(dummyProto, key, { value: undefined }); |
+ } |
+ |
+ let dummyAccessorProto = {}; |
+ for (let key of goodKeys) { |
+ Object.defineProperty(dummyAccessorProto, key, { set: (function(){}) }) |
+ } |
+ |
+ // String literals/objects should not throw on character index access |
+ assertDoesNotThrow(function() {"use strong"; return "string"[0]; }); |
+ assertDoesNotThrow(function() {"use strong"; return Object("string")[0]; }); |
+ |
+ // Attempting to access a property on an object with no defined properties |
+ // should throw. |
+ for (let object of getObjects().concat(getNonInheritingObjects(), literals)) { |
+ for (let func of readStrong) { |
+ assertStrongSemantics(func, object); |
+ } |
+ for (let func of readSloppy) { |
+ assertSloppySemantics(func, object); |
+ } |
+ } |
+ for (let object of getObjects()) { |
+ // Accessing a property which is on the prototype chain of the object should |
+ // not throw. |
+ object.__proto__ = dummyProto; |
+ for (let key of goodKeys) { |
+ for (let func of readStrong.concat(readSloppy)) { |
+ assertSloppySemantics(func, object); |
+ } |
+ } |
+ } |
+ // Properties with accessor descriptors missing 'get' should throw on access. |
+ for (let desc of badAccessorDescs) { |
+ for (let key of goodKeys) { |
+ for (let object of getObjects()) { |
+ Object.defineProperty(object, key, desc); |
+ for (let func of readStrong) { |
+ assertStrongSemantics(func, object); |
+ } |
+ for (let func of readSloppy) { |
+ assertSloppySemantics(func, object); |
+ } |
+ } |
+ } |
+ } |
+ // The same behaviour should be expected for bad accessor properties on the |
+ // prototype chain. |
+ for (let object of getObjects()) { |
+ object.__proto__ = dummyAccessorProto; |
+ for (let func of readStrong) { |
+ assertStrongSemantics(func, object); |
+ } |
+ for (let func of readSloppy) { |
+ assertSloppySemantics(func, object); |
+ } |
+ } |
+ assertThrows(function(){"use strong"; typeof ({})[1];}, TypeError); |
+ assertThrows( |
+ function(){"use strong"; typeof ({})[1] === "undefined"}, TypeError); |
+})(); |